// File: ctSkennerton[P]fxtract/util/./bndmem.c
// Function: bndmem
char *
bndmem(char *target, int tgtlen, char *pattern, int patlen)
{
    uint8_t *tgt = (uint8_t*)target, *pat = (uint8_t*)pattern;
    uint8_t *tgtend = tgt + tgtlen - patlen;
    int i, skip;
#if __SIZEOF_INT__ == 4
    if (patlen <= 32) {
        int32_t mask, maskv[256] = {};
        
        for (i = 0; i < patlen; ++i)
            setbit(&maskv[pat[i]], sizeof(mask)*8 - 1 - i);

        for (; tgt <= tgtend; tgt += skip)
            for (i = skip = patlen, mask = maskv[tgt[--i]];
                    mask; mask = (mask << 1) & maskv[tgt[--i]])
                if (mask < 0 && !(skip = i)) return (char*)tgt;
    } else 
#endif
    if (patlen <= 64) {
        int64_t mask, maskv[256] = {};

        for (i = 0; i < patlen; ++i)
            setbit(&maskv[pat[i]], sizeof(mask)*8 - 1 - i);

        for (; tgt <= tgtend; tgt += skip)
            for (i = skip = patlen, mask = maskv[tgt[--i]];
                    mask; mask = (mask << 1) & maskv[tgt[--i]])
                if (mask < 0 && !(skip = i)) return (char*)tgt;

    } else if (patlen <= 128) {
        __m128i mask, maskv[256], zero = {};
        int8_t used[256] = {};

        for (i = 0; i < patlen; ++i) {
            if (!used[pat[i]]) used[pat[i]] = 1, maskv[pat[i]] = zero;
            setbit(&maskv[pat[i]], sizeof(mask)*8 - 1 - i);
        }
        
        for (; tgt <= tgtend; tgt += skip) {
            i = skip = patlen;
            if (!used[tgt[--i]]) continue;
            mask = maskv[tgt[i]]; // gteed not zero.
            do {
                if (0 > (int16_t)_mm_movemask_epi8(mask) && !(skip = i))
                    return (char*)tgt;
                if (!used[tgt[--i]]) break;
                mask = _mm_and_si128(xm_shl_001(mask), maskv[tgt[i]]);
            } while (0xFFFF != _mm_movemask_epi8(_mm_cmpeq_epi8(mask, zero)));
        }
    }
    //TODO: AVX 256-bit ops.
    return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1de0, %rsp           # imm = 0x1DE0
movq %rdi, -0x70(%rbp)
movl %esi, -0x74(%rbp)
movq %rdx, -0x80(%rbp)
movl %ecx, -0x84(%rbp)
movq -0x70(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x90(%rbp), %rax
movslq -0x74(%rbp), %rcx
addq %rcx, %rax
movslq -0x84(%rbp), %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0xa0(%rbp)
cmpl $0x20, -0x84(%rbp)
jg 0x45b6
leaq -0x4b0(%rbp), %rdi
xorl %esi, %esi
movl $0x400, %edx            # imm = 0x400
callq 0x3110
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x84(%rbp), %eax
jge 0x44d5
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
leaq -0x4b0(%rbp), %rdi
shlq $0x2, %rax
addq %rax, %rdi
movslq -0xa4(%rbp), %rcx
movl $0x1f, %eax
subq %rcx, %rax
movl %eax, %esi
callq 0x6420
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x4480
jmp 0x44d7
movq -0x90(%rbp), %rax
cmpq -0xa0(%rbp), %rax
ja 0x45b1
movl -0x84(%rbp), %eax
movl %eax, -0xa8(%rbp)
movl %eax, -0xa4(%rbp)
movq -0x90(%rbp), %rax
movl -0xa4(%rbp), %ecx
addl $-0x1, %ecx
movl %ecx, -0xa4(%rbp)
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movl -0x4b0(%rbp,%rax,4), %eax
movl %eax, -0xac(%rbp)
cmpl $0x0, -0xac(%rbp)
je 0x4590
cmpl $0x0, -0xac(%rbp)
jge 0x455a
movl -0xa4(%rbp), %eax
movl %eax, -0xa8(%rbp)
cmpl $0x0, %eax
jne 0x455a
movq -0x90(%rbp), %rax
movq %rax, -0x68(%rbp)
jmp 0x49c1
jmp 0x455c
movl -0xac(%rbp), %eax
shll %eax
movq -0x90(%rbp), %rcx
movl -0xa4(%rbp), %edx
addl $-0x1, %edx
movl %edx, -0xa4(%rbp)
movslq %edx, %rdx
movzbl (%rcx,%rdx), %ecx
andl -0x4b0(%rbp,%rcx,4), %eax
movl %eax, -0xac(%rbp)
jmp 0x4527
jmp 0x4592
movl -0xa8(%rbp), %ecx
movq -0x90(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
jmp 0x44d7
jmp 0x49b9
cmpl $0x40, -0x84(%rbp)
jg 0x471e
leaq -0xcc0(%rbp), %rdi
xorl %esi, %esi
movl $0x800, %edx            # imm = 0x800
callq 0x3110
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x84(%rbp), %eax
jge 0x4635
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
leaq -0xcc0(%rbp), %rdi
shlq $0x3, %rax
addq %rax, %rdi
movslq -0xa4(%rbp), %rcx
movl $0x3f, %eax
subq %rcx, %rax
movl %eax, %esi
callq 0x6420
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x45e0
jmp 0x4637
movq -0x90(%rbp), %rax
cmpq -0xa0(%rbp), %rax
ja 0x4719
movl -0x84(%rbp), %eax
movl %eax, -0xa8(%rbp)
movl %eax, -0xa4(%rbp)
movq -0x90(%rbp), %rax
movl -0xa4(%rbp), %ecx
addl $-0x1, %ecx
movl %ecx, -0xa4(%rbp)
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
movq -0xcc0(%rbp,%rax,8), %rax
movq %rax, -0x4b8(%rbp)
cmpq $0x0, -0x4b8(%rbp)
je 0x46f8
cmpq $0x0, -0x4b8(%rbp)
jge 0x46be
movl -0xa4(%rbp), %eax
movl %eax, -0xa8(%rbp)
cmpl $0x0, %eax
jne 0x46be
movq -0x90(%rbp), %rax
movq %rax, -0x68(%rbp)
jmp 0x49c1
jmp 0x46c0
movq -0x4b8(%rbp), %rax
shlq %rax
movq -0x90(%rbp), %rcx
movl -0xa4(%rbp), %edx
addl $-0x1, %edx
movl %edx, -0xa4(%rbp)
movslq %edx, %rdx
movzbl (%rcx,%rdx), %ecx
andq -0xcc0(%rbp,%rcx,8), %rax
movq %rax, -0x4b8(%rbp)
jmp 0x4689
jmp 0x46fa
movl -0xa8(%rbp), %ecx
movq -0x90(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
jmp 0x4637
jmp 0x49b7
cmpl $0x80, -0x84(%rbp)
jg 0x49b5
xorps %xmm0, %xmm0
movaps %xmm0, -0x1ce0(%rbp)
leaq -0x1de0(%rbp), %rdi
xorl %esi, %esi
movl $0x100, %edx            # imm = 0x100
callq 0x3110
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x84(%rbp), %eax
jge 0x4815
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
cmpb $0x0, -0x1de0(%rbp,%rax)
jne 0x47cb
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movb $0x1, -0x1de0(%rbp,%rax)
movdqa -0x1ce0(%rbp), %xmm0
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq -0x1cd0(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movdqa %xmm0, (%rax)
movq -0x98(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
leaq -0x1cd0(%rbp), %rdi
shlq $0x4, %rax
addq %rax, %rdi
movslq -0xa4(%rbp), %rcx
movl $0x7f, %eax
subq %rcx, %rax
movl %eax, %esi
callq 0x6420
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x4755
jmp 0x4817
movq -0x90(%rbp), %rax
cmpq -0xa0(%rbp), %rax
ja 0x49b3
movl -0x84(%rbp), %eax
movl %eax, -0xa8(%rbp)
movl %eax, -0xa4(%rbp)
movq -0x90(%rbp), %rax
movl -0xa4(%rbp), %ecx
addl $-0x1, %ecx
movl %ecx, -0xa4(%rbp)
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
cmpb $0x0, -0x1de0(%rbp,%rax)
jne 0x4869
jmp 0x4994
movq -0x90(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq -0x1cd0(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movdqa (%rax), %xmm0
movdqa %xmm0, -0xcd0(%rbp)
movdqa -0xcd0(%rbp), %xmm0
movdqa %xmm0, -0x50(%rbp)
movdqa -0x50(%rbp), %xmm0
pmovmskb %xmm0, %eax
movswl %ax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jle 0x48d7
movl -0xa4(%rbp), %eax
movl %eax, -0xa8(%rbp)
cmpl $0x0, %eax
jne 0x48d7
movq -0x90(%rbp), %rax
movq %rax, -0x68(%rbp)
jmp 0x49c1
movq -0x90(%rbp), %rax
movl -0xa4(%rbp), %ecx
addl $-0x1, %ecx
movl %ecx, -0xa4(%rbp)
movslq %ecx, %rcx
movzbl (%rax,%rcx), %eax
cmpb $0x0, -0x1de0(%rbp,%rax)
jne 0x4903
jmp 0x4992
movdqa -0xcd0(%rbp), %xmm0
callq 0x6450
movaps %xmm0, %xmm1
movq -0x90(%rbp), %rax
movslq -0xa4(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, %ecx
leaq -0x1cd0(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movdqa (%rax), %xmm0
movdqa %xmm1, -0x30(%rbp)
movdqa %xmm0, -0x40(%rbp)
movdqa -0x30(%rbp), %xmm0
pand -0x40(%rbp), %xmm0
movdqa %xmm0, -0xcd0(%rbp)
movaps -0xcd0(%rbp), %xmm1
movaps -0x1ce0(%rbp), %xmm0
movaps %xmm1, -0x10(%rbp)
movaps %xmm0, -0x20(%rbp)
movaps -0x10(%rbp), %xmm0
movaps -0x20(%rbp), %xmm1
pcmpeqb %xmm1, %xmm0
movdqa %xmm0, -0x60(%rbp)
movdqa -0x60(%rbp), %xmm0
pmovmskb %xmm0, %ecx
movl $0xffff, %eax           # imm = 0xFFFF
cmpl %ecx, %eax
jne 0x4897
jmp 0x4994
movl -0xa8(%rbp), %ecx
movq -0x90(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x90(%rbp)
jmp 0x4817
jmp 0x49b5
jmp 0x49b7
jmp 0x49b9
movq $0x0, -0x68(%rbp)
movq -0x68(%rbp), %rax
addq $0x1de0, %rsp           # imm = 0x1DE0
popq %rbp
retq
nop