// File: ctSkennerton[P]fxtract/util/./railgun7w.c
// Function: check4
static byte *
check4(byte *pbTarget, byte *pbPattern, uint cbTarget, uint cbPattern)
{
    byte *pbTargetMax = pbTarget + cbTarget;
    uint ulHashPattern = *(uint*)pbPattern;
    uint skip, quad = pbPattern[0];
    quad |= quad << 8;
    quad |= quad << 16;
    pbTarget = pbTarget + cbPattern;

    do {
        uint ulHashTarget = *(uint*) (pbTarget - cbPattern);
        skip = 1;
        if (ulHashPattern == ulHashTarget) {    // Three unnecessary comparisons here, but 'skip' must be calculated - it has a higher priority.
            int count = cbPattern - 1;
            while (count && pbPattern[cbPattern - count] == pbTarget[-count]) {
                if (cbPattern - 1 == skip + count && (byte)quad != pbTarget[-count])
                    skip++;
                count--;
            } 

            if (count == 0)
                return pbTarget - cbPattern;
        } else { // The goal here: to avoid memory accesses by stressing the registers.
            ulHashTarget ^= quad; //XXX Slightly cheaper way to test each byte vs pbPattern[0]
            skip += !(ulHashTarget & 0x0000FF00) ? 0
                  : !(ulHashTarget & 0x00FF0000) ? 1
                  : !(ulHashTarget & 0xFF000000) ? 2
                                                 : 3;
        }
    } while ((pbTarget += skip) <= pbTargetMax);

    return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movl %ecx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl -0x1c(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
shll $0x8, %eax
orl -0x34(%rbp), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
shll $0x10, %eax
orl -0x34(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
movl %ecx, %edx
xorl %ecx, %ecx
subq %rdx, %rcx
movl (%rax,%rcx), %eax
movl %eax, -0x38(%rbp)
movl $0x1, -0x30(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x38(%rbp), %eax
jne 0x66c5
movl -0x20(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x3c(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x3c(%rbp)
movb %al, -0x3d(%rbp)
je 0x665c
movq -0x18(%rbp), %rax
movl -0x20(%rbp), %ecx
subl -0x3c(%rbp), %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
movq -0x10(%rbp), %rcx
xorl %edx, %edx
subl -0x3c(%rbp), %edx
movslq %edx, %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
sete %al
movb %al, -0x3d(%rbp)
movb -0x3d(%rbp), %al
testb $0x1, %al
jne 0x6665
jmp 0x66a3
movl -0x20(%rbp), %eax
subl $0x1, %eax
movl -0x30(%rbp), %ecx
addl -0x3c(%rbp), %ecx
cmpl %ecx, %eax
jne 0x6698
movl -0x34(%rbp), %eax
movzbl %al, %eax
movq -0x10(%rbp), %rcx
xorl %edx, %edx
subl -0x3c(%rbp), %edx
movslq %edx, %rdx
movzbl (%rcx,%rdx), %ecx
cmpl %ecx, %eax
je 0x6698
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
movl -0x3c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x6629
cmpl $0x0, -0x3c(%rbp)
jne 0x66c3
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
movl %ecx, %edx
xorl %ecx, %ecx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x8(%rbp)
jmp 0x6750
jmp 0x672c
movl -0x34(%rbp), %eax
xorl -0x38(%rbp), %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
cmpl $0x0, %eax
jne 0x66e2
xorl %eax, %eax
movl %eax, -0x44(%rbp)
jmp 0x6723
movl -0x38(%rbp), %eax
andl $0xff0000, %eax         # imm = 0xFF0000
cmpl $0x0, %eax
jne 0x66f9
movl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x671d
movl -0x38(%rbp), %eax
andl $0xff000000, %eax       # imm = 0xFF000000
cmpl $0x0, %eax
setne %dl
xorb $-0x1, %dl
movl $0x3, %eax
movl $0x2, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
addl -0x30(%rbp), %eax
movl %eax, -0x30(%rbp)
jmp 0x672e
movl -0x30(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x10(%rbp)
cmpq -0x28(%rbp), %rax
jbe 0x65f9
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
popq %rbp
retq
nopw %cs:(%rax,%rax)