// File: /workspace/github_cpp_makefile_star2_O3/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x10018, %rsp          # imm = 0x10018
movl %esi, %r13d
subl %ecx, %r13d
jge 0x3d27
xorl %eax, %eax
jmp 0x3fcb
movl %ecx, %r15d
movq %rdx, %r14
movq %rdi, %rbx
movslq %esi, %rcx
addq %rdi, %rcx
cmpl $0x3, %r15d
jg 0x3de1
movslq %r15d, %rax
addq %rax, %rbx
movsbq (%r14), %rsi
shlq $0x8, %rsi
movsbq -0x1(%r14,%rax), %rdx
addq %rsi, %rdx
movl %edx, %eax
shrl $0x8, %eax
movsbl %al, %esi
xorl %eax, %eax
cmpl $0x3, %r15d
jne 0x3dab
movzbl -0x3(%rbx), %edi
shll $0x8, %edi
movzbl -0x1(%rbx), %r8d
orq %rdi, %r8
cmpq %rdx, %r8
jne 0x3d8a
movb -0x2(%rbx), %dil
cmpb %dil, 0x1(%r14)
jne 0x3d8e
jmp 0x3fc4
movb -0x2(%rbx), %dil
movsbl %dil, %edi
xorl %r8d, %r8d
cmpl %edi, %esi
setne %r8b
addq %r8, %rbx
incq %rbx
cmpq %rcx, %rbx
jbe 0x3d67
jmp 0x3fcb
movzbl -0x2(%rbx), %r8d
shll $0x8, %r8d
movzbl -0x1(%rbx), %edi
orq %rdi, %r8
cmpq %rdx, %r8
je 0x3f51
movsbl %dil, %edi
xorl %r8d, %r8d
cmpl %edi, %esi
setne %r8b
addq %r8, %rbx
incq %rbx
cmpq %rcx, %rbx
jbe 0x3dab
jmp 0x3fcb
cmpl $0x3c0, %esi            # imm = 0x3C0
jg 0x3ec4
movl %r15d, %edx
addq %rdx, %rbx
movq (%r14), %rsi
movzbl %sil, %edi
movl %edi, %r8d
shll $0x8, %r8d
movl %edi, %eax
shll $0x10, %eax
movq %rax, 0x8(%rsp)
movl %esi, %eax
shll $0x18, %eax
cltq
movq %rax, (%rsp)
movq %rdx, %r10
negq %r10
decl %r15d
movq %r15, %r12
negq %r12
subq %r15, %rdx
addq %r14, %rdx
xorl %eax, %eax
movq (%rbx,%r10), %r14
cmpq %r14, %rsi
jne 0x3e72
leaq (%rbx,%r12), %r14
xorl %r13d, %r13d
xorl %ebp, %ebp
movsbl (%rdx,%r13), %r11d
cmpb (%r14,%r13), %r11b
jne 0x3ead
movl %ebp, %r9d
cmpq %r13, %r9
sete %r9b
cmpl %r11d, %edi
setne %r11b
andb %r9b, %r11b
movzbl %r11b, %r9d
addl %r9d, %ebp
incq %r13
cmpq %r13, %r15
jne 0x3e3f
jmp 0x3f4c
movl %r14d, %r9d
andl $0xff00, %r9d           # imm = 0xFF00
xorl %ebp, %ebp
cmpl %r8d, %r9d
je 0x3ead
movl %r14d, %r9d
andl $0xff0000, %r9d         # imm = 0xFF0000
movl $0x1, %ebp
cmpl 0x8(%rsp), %r9d
je 0x3ead
andl $0xff000000, %r14d      # imm = 0xFF000000
xorl %ebp, %ebp
cmpq (%rsp), %r14
sete %bpl
xorl $0x3, %ebp
movslq %ebp, %r9
addq %r9, %rbx
incq %rbx
cmpq %rcx, %rbx
jbe 0x3e2d
jmp 0x3fcb
leal -0x4(%r15), %r12d
leal -0x1(%r15), %eax
movzbl %al, %esi
leaq 0x10(%rsp), %rdi
movl $0x10000, %edx          # imm = 0x10000
callq 0x3100
leal -0x2(%r15), %esi
leal -0x1(%r15), %edi
xorl %eax, %eax
movzwl (%r14,%rax), %ecx
movb %al, 0x10(%rsp,%rcx)
incq %rax
cmpq %rax, %rdi
jne 0x3ee8
movl %r15d, %r8d
movzwl -0x2(%r14,%r8), %ecx
cmpl $0x2, %r13d
jge 0x3f57
xorl %edx, %edx
leal -0x1(%r13), %eax
cltq
cmpq %rax, %rdx
jne 0x3fe0
cmpq %rcx, (%rbx,%rdx)
jne 0x3fdd
leaq (%rbx,%rdx), %rax
testq %r12, %r12
je 0x3fcb
xorl %esi, %esi
movb 0x4(%r14,%rsi), %dil
cmpb 0x4(%rax,%rsi), %dil
jne 0x3fdd
incq %rsi
cmpq %rsi, %r12
jne 0x3f32
jmp 0x3fcb
addq %r10, %rbx
jmp 0x3fc8
addq $-0x2, %rbx
jmp 0x3fc8
movq (%r14), %r9
leal -0x2(%r13), %eax
movslq %eax, %r10
xorl %edx, %edx
leaq (%rdx,%r8), %rax
movzwl -0x2(%rbx,%rax), %r11d
movzbl 0x10(%rsp,%r11), %ebp
cmpl %ebp, %esi
jne 0x3f9f
cmpq %r9, (%rbx,%rdx)
jne 0x3fab
leaq (%rbx,%rdx), %rax
testq %r12, %r12
je 0x3fcb
xorl %r11d, %r11d
movb 0x4(%r14,%r11), %bpl
cmpb 0x4(%rax,%r11), %bpl
jne 0x3fab
incq %r11
cmpq %r11, %r12
jne 0x3f89
jmp 0x3fcb
movl %ebp, %r11d
cmpl %ebp, %edi
jne 0x3fb0
addq %r11, %rdx
jmp 0x3fba
incq %rdx
jmp 0x3fba
subq %r11, %rax
addq $-0x2, %rax
movq %rax, %rdx
cmpq %r10, %rdx
jle 0x3f63
jmp 0x3f0a
addq $-0x3, %rbx
movq %rbx, %rax
addq $0x10018, %rsp          # imm = 0x10018
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
incq %rdx
movslq %r13d, %rax
cmpq %rax, %rdx
jne 0x3d20
cmpq %rcx, (%rbx,%rdx)
jne 0x3d20
addq %rdx, %rbx
testq %r12, %r12
je 0x3fc8
xorl %eax, %eax
xorl %ecx, %ecx
movb 0x4(%r14,%rcx), %dl
cmpb 0x4(%rbx,%rcx), %dl
jne 0x3fcb
incq %rcx
cmpq %rcx, %r12
jne 0x4002
jmp 0x3fc8