// File: /workspace/github_cpp_makefile_star2_O2/ctSkennerton[P]fxtract/util/./railgun7g.c
// Function: Railgun7g
char *
Railgun7g(char *pbTarget, int cbTarget, char *pbPattern, int cbPattern)
{
    char *pbTargetMax = pbTarget + cbTarget;
    register unsigned long ulHashPattern;
    register unsigned long ulHashTarget;
    signed long count;
    signed long countSTATIC;

    unsigned char SINGLET;
    unsigned long Quadruplet2nd;
    unsigned long Quadruplet3rd;
    unsigned long Quadruplet4th;

    int         AdvanceHopperGrass;

    long i;                     //BMH needed
    int a, j;
    //UNUSED unsigned int bm_bc[256];    //BMH needed
    //UNUSED unsigned int bm_bc2nd[256]; //BMS needed
    unsigned char bm_Sunday_Order2[256 * 256];  //BMHSS(Elsiane) needed, 'char' limits patterns to 255, if 'long' then table becomes 256KB, grrr.
    int     Gulliver;     // or unsigned char or unsigned short

    if (cbPattern > cbTarget)
        return (NULL);

    if (cbPattern < 4) {
        pbTarget = pbTarget + cbPattern;
        ulHashPattern =
            ((*(char *) (pbPattern)) << 8) + *(pbPattern + (cbPattern - 1));

        if (cbPattern == 3) {
            for (;;) {
                if (ulHashPattern == (uint32_t)
                    ((*(uint8_t const *) (pbTarget - 3)) << 8) + *(uint8_t const*)(pbTarget - 1)) {
                    if (*(uint8_t const*) (pbPattern + 1) == *(uint8_t const *) (pbTarget - 2))
                        return ((pbTarget - 3));
                }
                if ((char) (ulHashPattern >> 8) != *(pbTarget - 2))
                    pbTarget++;
                pbTarget++;
                if (pbTarget > pbTargetMax)
                    return (NULL);
            }
        }
        else {
        }
        for (;;) {
            if (ulHashPattern == (uint32_t)
                ((*(uint8_t const*) (pbTarget - 2)) << 8) + *(uint8_t const*)(pbTarget - 1))
                return((pbTarget-2));
            if ((char) (ulHashPattern >> 8) != *(pbTarget - 1))
                pbTarget++;
            pbTarget++;
            if (pbTarget > pbTargetMax)
                return (NULL);
        }
    }
    else {                      //if ( cbPattern<4)
        if (cbTarget < 961) {   // This value is arbitrary(don't know how exactly), it ensures(at least must) better performance than 'Boyer_Moore_Horspool'.
            pbTarget = pbTarget + cbPattern;
            ulHashPattern = *(unsigned long *) (pbPattern);

            SINGLET = ulHashPattern & 0xFF;
            Quadruplet2nd = SINGLET << 8;
            Quadruplet3rd = SINGLET << 16;
            Quadruplet4th = SINGLET << 24;

            for (;;) {
                AdvanceHopperGrass = 0;
                ulHashTarget = *(unsigned long *) (pbTarget - cbPattern);

                if (ulHashPattern == ulHashTarget) {    // Three unnecessary comparisons here, but 'AdvanceHopperGrass' must be calculated - it has a higher priority.
                    count = cbPattern - 1;
                    while (count
                           && *(char *) (pbPattern + (cbPattern - count)) ==
                           *(char *) (pbTarget - count)) {
                        if (cbPattern - 1 == AdvanceHopperGrass + count
                            && SINGLET != *(char *) (pbTarget - count))
                            AdvanceHopperGrass++;
                        count--;
                    }
                    if (count == 0)
                        return((pbTarget-cbPattern));
                }
                else {          // The goal here: to avoid memory accesses by stressing the registers.
                    if (Quadruplet2nd != (ulHashTarget & 0x0000FF00)) {
                        AdvanceHopperGrass++;
                        if (Quadruplet3rd != (ulHashTarget & 0x00FF0000)) {
                            AdvanceHopperGrass++;
                            if (Quadruplet4th != (ulHashTarget & 0xFF000000))
                                AdvanceHopperGrass++;
                        }
                    }
                }

                AdvanceHopperGrass++;

                pbTarget = pbTarget + AdvanceHopperGrass;
                if (pbTarget > pbTargetMax)
                    return (NULL);
            }
        }
        else {                  //if (cbTarget<961)
            countSTATIC = cbPattern - 2 - 2;

            //UNUSED for (a = 0; a < 256; a++) bm_bc[a] = cbPattern, bm_bc2nd[a] = cbPattern + 1;
            //for (j = 0; j < cbPattern - 1; j++) bm_bc[(uint8_t)pbPattern[j]] = cbPattern - j - 1;
            //for (j = 0; j < cbPattern; j++) bm_bc2nd[(uint8_t)pbPattern[j]] = cbPattern - j;

            // Elsiane r.2  [
            for (a = 0; a < 256 * 256; a++) {
                bm_Sunday_Order2[a] = cbPattern - 1;
            }                   // 'memset' if not optimized

            // alfalfa 7 long 6 BBs (al lf fa al lf fa) 3 distinct BBs (al lf fa) 
            // fast 4 0-1-2 fa as st
            for (j = 0; j < cbPattern - 1; j++)
                bm_Sunday_Order2[*(unsigned short *) (pbPattern + j)] = j;  // Rightmost appearance/position is needed

            // Elsiane r.2 ]

            ulHashPattern = *(unsigned short *) (pbPattern + cbPattern - 1 - 1);    // Last two bytes
            ulHashTarget = *(unsigned long *) (pbPattern);  // First four bytes

            AdvanceHopperGrass = 0;
            i = 0;
            while (i <= cbTarget - cbPattern - 1 - 1) {
                Gulliver =
                    bm_Sunday_Order2[*(unsigned short *)
                                     &pbTarget[i + cbPattern - 1 - 1]];

                if (Gulliver == cbPattern - 2) {    // CASE #1: means the pair (char order 2) is found
                    if (*(unsigned long *) &pbTarget[i] == ulHashTarget) {
                        count = countSTATIC;    // Last two chars already matched, to be fixed with -2
                        while (count != 0
                               && *(char *) (pbPattern + (countSTATIC - count) +
                                             4) ==
                               *(char *) (&pbTarget[i] + (countSTATIC - count) +
                                          4))
                            count--;
                        if (count == 0)
                            return(pbTarget+i);
                    }
                    i = i + 1;
                }
                else if (Gulliver == cbPattern - 1) // CASE #2: means the pair (char order 2) is found
                    i = i + Gulliver;   // the pair is not found, skip the whole pattern and fall back one char
                else
                    i = i + cbPattern - Gulliver - 2;   // CASE #3: the pair is found and not as suffix i.e. rightmost position

// 32323218 Order 1 Horspool
// fa af fa af fa as st Order 2 Horspool
//  0  1  2  3  4  5  6
// HIKARIfast
// fafafast
//   fafafast +2 Order 1 'a' vs 't'
//   fafafast +2 = (cbPattern-Gulliver-2 = 8-4-2 = 2) Order 2 'fa' vs 'st' i.e. CASE #3

// 76543218 Order 1 Horspool
// lo on ng gp pa ac ce Order 2 Horspool
//  0  1  2  3  4  5  6
// HIKARIfast
// longpace
//   longpace +2 Order 1 'a' vs 'e'
//        longpace +7 = (cbPattern-1 = 8-1 = 7) Order 2 'fa' vs 'ce' i.e. CASE #2

                AdvanceHopperGrass++;
            }

            if (i == cbTarget - cbPattern - 1) {
                if (*(unsigned long *) &pbTarget[i] == ulHashPattern) {
                    count = countSTATIC;
                    while (count != 0
                           && *(char *) (pbPattern + (countSTATIC - count) +
                                         4) ==
                           *(char *) (&pbTarget[i] + (countSTATIC - count) + 4))
                        count--;
                    if (count == 0)
                        return(pbTarget+i);
                }
                i++;
                AdvanceHopperGrass++;
            }

            if (i == cbTarget - cbPattern) {
                if (*(unsigned long *) &pbTarget[i] == ulHashPattern) {
                    count = countSTATIC;
                    while (count != 0
                           && *(char *) (pbPattern + (countSTATIC - count) +
                                         4) ==
                           *(char *) (&pbTarget[i] + (countSTATIC - count) + 4))
                        count--;
                    if (count == 0)
                        return(pbTarget+i);
                }
                AdvanceHopperGrass++;
            }
#if 0
            GlobalSP += (int) ((double) cbTarget / AdvanceHopperGrass * 100);
            GlobalI += AdvanceHopperGrass;
            printf
                ("Skip-Performance(bigger-the-better): %d%%, %d skips/iterations\n",
                 (int) ((double) cbTarget / AdvanceHopperGrass * 100),
                 AdvanceHopperGrass);
#endif
            return (NULL);
        }                       //if (cbTarget<961)
    }                           //if ( cbPattern<4)
}

// Assembly:
movl %esi, %r9d
subl %ecx, %r9d
jge 0x3c48
xorl %eax, %eax
retq
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xff98, %rsp           # imm = 0xFF98
movslq %esi, %r8
addq %rdi, %r8
cmpl $0x3, %ecx
jg 0x3cd5
movslq %ecx, %rax
addq %rax, %rdi
movsbq (%rdx), %r9
shlq $0x8, %r9
movsbq -0x1(%rdx,%rax), %rsi
addq %r9, %rsi
movl %esi, %eax
shrl $0x8, %eax
cmpl $0x3, %ecx
jne 0x3dbc
movsbl %al, %ecx
xorl %eax, %eax
movzbl -0x3(%rdi), %r9d
shll $0x8, %r9d
movzbl -0x1(%rdi), %r10d
orq %r9, %r10
cmpq %rsi, %r10
jne 0x3cb3
movb -0x2(%rdi), %r9b
cmpb %r9b, 0x1(%rdx)
jne 0x3cb7
jmp 0x3eaf
movb -0x2(%rdi), %r9b
movsbl %r9b, %r9d
xorl %r10d, %r10d
cmpl %r9d, %ecx
setne %r10b
addq %r10, %rdi
incq %rdi
cmpq %r8, %rdi
jbe 0x3c8e
jmp 0x3eb6
cmpl $0x3c0, %esi            # imm = 0x3C0
jg 0x3df6
movl %ecx, %esi
addq %rsi, %rdi
movq (%rdx), %r9
movzbl %r9b, %r10d
movl %r10d, %r11d
shll $0x8, %r11d
movl %r10d, %eax
shll $0x10, %eax
movq %rax, -0x78(%rsp)
movl %r9d, %eax
shll $0x18, %eax
cltq
movq %rax, -0x80(%rsp)
movq %rsi, %r14
negq %r14
decl %ecx
subq %rcx, %rsi
addq %rdx, %rsi
movq %rcx, %rdx
negq %rdx
xorl %eax, %eax
movq (%rdi,%r14), %r13
cmpq %r13, %r9
jne 0x3d68
leaq (%rdi,%rdx), %r13
xorl %ebp, %ebp
xorl %r12d, %r12d
cmpq %rbp, %rcx
je 0x3ea4
movsbl (%rsi,%rbp), %r15d
cmpb (%r13,%rbp), %r15b
jne 0x3da5
movl %r12d, %ebx
cmpq %rbp, %rbx
sete %bl
cmpl %r15d, %r10d
setne %r15b
andb %bl, %r15b
movzbl %r15b, %ebx
addl %ebx, %r12d
incq %rbp
jmp 0x3d34
movl %r13d, %ebx
andl $0xff00, %ebx           # imm = 0xFF00
xorl %r12d, %r12d
cmpl %r11d, %ebx
je 0x3da5
movl %r13d, %ebx
andl $0xff0000, %ebx         # imm = 0xFF0000
movl $0x1, %r12d
cmpl -0x78(%rsp), %ebx
je 0x3da5
andl $0xff000000, %r13d      # imm = 0xFF000000
xorl %r12d, %r12d
cmpq -0x80(%rsp), %r13
sete %r12b
xorl $0x3, %r12d
movslq %r12d, %rbx
addq %rbx, %rdi
incq %rdi
cmpq %r8, %rdi
jbe 0x3d22
jmp 0x3eb6
movsbl %al, %ecx
xorl %eax, %eax
movzbl -0x2(%rdi), %r9d
shll $0x8, %r9d
movzbl -0x1(%rdi), %edx
orq %rdx, %r9
cmpq %rsi, %r9
je 0x3ea9
movsbl %dl, %edx
xorl %r9d, %r9d
cmpl %edx, %ecx
setne %r9b
addq %r9, %rdi
incq %rdi
cmpq %r8, %rdi
jbe 0x3dc1
jmp 0x3eb6
leal -0x4(%rcx), %eax
leal -0x1(%rcx), %esi
xorl %r8d, %r8d
cmpq $0x10000, %r8           # imm = 0x10000
je 0x3e12
movb %sil, -0x70(%rsp,%r8)
incq %r8
jmp 0x3dff
leal -0x2(%rcx), %r10d
leal -0x1(%rcx), %r11d
xorl %esi, %esi
cmpq %rsi, %r11
je 0x3e30
movzwl (%rdx,%rsi), %r8d
movb %sil, -0x70(%rsp,%r8)
incq %rsi
jmp 0x3e1c
movl %eax, %esi
movl %ecx, %ebx
movzwl -0x2(%rdx,%rbx), %ecx
movq (%rdx), %r14
leal -0x2(%r9), %eax
movslq %eax, %r15
xorl %r8d, %r8d
cmpq %r15, %r8
jg 0x3ec8
leaq (%r8,%rbx), %rax
movzwl -0x2(%rdi,%rax), %r12d
movzbl -0x70(%rsp,%r12), %ebp
cmpl %ebp, %r10d
jne 0x3e8b
cmpq %r14, (%rdi,%r8)
jne 0x3e86
leaq (%rdi,%r8), %rax
xorl %r12d, %r12d
cmpq %r12, %rsi
je 0x3eb6
movb 0x4(%rdx,%r12), %bpl
leaq 0x1(%r12), %r13
cmpb 0x4(%rax,%r12), %bpl
movq %r13, %r12
je 0x3e6d
incq %r8
jmp 0x3e46
movl %ebp, %r12d
cmpl %ebp, %r11d
jne 0x3e98
addq %r12, %r8
jmp 0x3e46
subq %r12, %rax
addq $-0x2, %rax
movq %rax, %r8
jmp 0x3e46
addq %r14, %rdi
jmp 0x3eb3
addq $-0x2, %rdi
jmp 0x3eb3
addq $-0x3, %rdi
movq %rdi, %rax
addq $0xff98, %rsp           # imm = 0xFF98
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leal -0x1(%r9), %eax
cltq
cmpq %rax, %r8
jne 0x3efb
cmpq %rcx, (%rdi,%r8)
jne 0x3ef8
leaq (%rdi,%r8), %rax
xorl %r10d, %r10d
cmpq %r10, %rsi
je 0x3eb6
movb 0x4(%rdx,%r10), %r11b
leaq 0x1(%r10), %rbx
cmpb 0x4(%rax,%r10), %r11b
movq %rbx, %r10
je 0x3ee0
incq %r8
movslq %r9d, %rax
cmpq %rax, %r8
jne 0x3f2a
cmpq %rcx, (%rdi,%r8)
jne 0x3f2a
addq %r8, %rdi
xorl %eax, %eax
xorl %ecx, %ecx
cmpq %rcx, %rsi
je 0x3eb3
movb 0x4(%rdx,%rcx), %r8b
leaq 0x1(%rcx), %r9
cmpb 0x4(%rdi,%rcx), %r8b
movq %r9, %rcx
je 0x3f10
jmp 0x3eb6
xorl %eax, %eax
jmp 0x3eb6