// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1108, %rsp           # imm = 0x1108
movl %ecx, %r14d
movq %rdx, %r15
movq %rdi, %rbx
movslq %esi, %r12
addq %rdi, %r12
movslq %ecx, %r13
subq %r13, %r12
cmpl $0x20, %r13d
jg 0x559b
leaq 0x100(%rsp), %rdi
xorl %r13d, %r13d
movl $0x400, %edx            # imm = 0x400
xorl %esi, %esi
callq 0x3110
testl %r14d, %r14d
cmovgl %r14d, %r13d
pushq $0x1f
popq %rcx
pushq $0x1
popq %rax
leaq (%rcx,%r13), %rdx
cmpq $0x1f, %rdx
je 0x55f5
movzbl (%r15), %edx
leaq (%rsp,%rdx,4), %rdx
addq $0x100, %rdx            # imm = 0x100
movl %eax, %esi
shll %cl, %esi
movq %rcx, %rdi
shrq $0x5, %rdi
orl %esi, (%rdx,%rdi,4)
decq %rcx
incq %r15
jmp 0x556c
movl %r14d, %ebp
cmpl $0x40, %r14d
ja 0x5641
leaq 0x100(%rsp), %rdi
movl $0x800, %edx            # imm = 0x800
xorl %esi, %esi
callq 0x3110
pushq $0x3f
popq %rcx
pushq $0x1
popq %rax
leaq (%rcx,%rbp), %rdx
cmpq $0x3f, %rdx
je 0x56b4
movzbl (%r15), %edx
leaq (%rsp,%rdx,8), %rdx
addq $0x100, %rdx            # imm = 0x100
movl %eax, %esi
shll %cl, %esi
movq %rcx, %rdi
shrq $0x5, %rdi
orl %esi, (%rdx,%rdi,4)
decq %rcx
incq %r15
jmp 0x55c2
leal -0x1(%r14), %eax
cltq
cmpq %r12, %rbx
ja 0x579d
movzbl (%rbx,%rax), %ecx
movl 0x100(%rsp,%rcx,4), %ecx
movq %rax, %rdx
movl %r14d, %esi
testl %ecx, %ecx
je 0x5639
jns 0x5626
movl %edx, %esi
testq %rdx, %rdx
je 0x579f
addl %ecx, %ecx
movzbl -0x1(%rbx,%rdx), %edi
decq %rdx
andl 0x100(%rsp,%rdi,4), %ecx
jmp 0x5615
movslq %esi, %rcx
addq %rcx, %rbx
jmp 0x55fb
cmpl $0x80, %r14d
ja 0x579d
movq %rsp, %rdi
movl $0x100, %edx            # imm = 0x100
xorl %esi, %esi
callq 0x3110
pushq $0x7f
popq %rcx
pxor %xmm0, %xmm0
pushq $0x1
popq %rax
leaq (%rcx,%rbp), %rdx
cmpq $0x7f, %rdx
je 0x5707
movzbl (%r15), %edx
cmpb $0x0, (%rsp,%rdx)
jne 0x5691
movb $0x1, (%rsp,%rdx)
movl %edx, %esi
shll $0x4, %esi
movdqa %xmm0, 0x100(%rsp,%rsi)
shll $0x4, %edx
addq %rsp, %rdx
addq $0x100, %rdx            # imm = 0x100
movl %eax, %esi
shll %cl, %esi
movq %rcx, %rdi
shrq $0x5, %rdi
orl %esi, (%rdx,%rdi,4)
decq %rcx
incq %r15
jmp 0x5667
decl %r14d
cmpq %r12, %rbx
ja 0x579d
movzbl (%rbx,%r14), %eax
movq 0x100(%rsp,%rax,8), %rax
movl %r14d, %ecx
movq %r13, %rdx
movl %ebp, %esi
testq %rax, %rax
je 0x56ff
jns 0x56e8
movl %ecx, %esi
cmpq $0x1, %rdx
je 0x579f
addq %rax, %rax
movzbl -0x2(%rbx,%rdx), %edi
andq 0x100(%rsp,%rdi,8), %rax
decq %rdx
decl %ecx
jmp 0x56d5
movslq %esi, %rax
addq %rax, %rbx
jmp 0x56b7
decl %r14d
pxor %xmm0, %xmm0
cmpq %r12, %rbx
ja 0x579d
movzbl (%rbx,%r14), %eax
cmpb $0x0, (%rsp,%rax)
movq %r13, %rcx
je 0x5795
shll $0x4, %eax
movdqa 0x100(%rsp,%rax), %xmm1
movl %r14d, %eax
movq %r13, %rcx
movl %ebp, %edx
pmovmskb %xmm1, %esi
testw %si, %si
jns 0x574a
movl %eax, %edx
cmpq $0x1, %rcx
je 0x579f
movzbl -0x2(%rbx,%rcx), %esi
cmpb $0x0, (%rsp,%rsi)
je 0x5792
movdqa %xmm1, %xmm2
pslldq $0x8, %xmm2             # xmm2 = zero,zero,zero,zero,zero,zero,zero,zero,xmm2[0,1,2,3,4,5,6,7]
paddq %xmm1, %xmm1
psrlq $0x3f, %xmm2
por %xmm1, %xmm2
shll $0x4, %esi
pand 0x100(%rsp,%rsi), %xmm2
movdqa %xmm2, %xmm1
pcmpeqb %xmm0, %xmm2
pmovmskb %xmm2, %esi
xorl $0xffff, %esi           # imm = 0xFFFF
decq %rcx
decl %eax
testl %esi, %esi
jne 0x5739
movslq %edx, %rcx
addq %rcx, %rbx
jmp 0x570e
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x1108, %rsp           # imm = 0x1108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq