// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/bitops.c
// Function: redisBitpos
long redisBitpos(void *s, long count, int bit) {
    unsigned long *l;
    unsigned char *c;
    unsigned long skipval, word = 0, one;
    long pos = 0; /* Position of bit, to return to the caller. */
    int j;

    /* Process whole words first, seeking for first word that is not
     * all ones or all zeros respectively if we are lookig for zeros
     * or ones. This is much faster with large strings having contiguous
     * blocks of 1 or 0 bits compared to the vanilla bit per bit processing.
     *
     * Note that if we start from an address that is not aligned
     * to sizeof(unsigned long) we consume it byte by byte until it is
     * aligned. */

    /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */
    skipval = bit ? 0 : UCHAR_MAX;
    c = (unsigned char*) s;
    while((unsigned long)c & (sizeof(*l)-1) && count) {
        if (*c != skipval) break;
        c++;
        count--;
        pos += 8;
    }

    /* Skip bits with full word step. */
    skipval = bit ? 0 : ULONG_MAX;
    l = (unsigned long*) c;
    while (count >= sizeof(*l)) {
        if (*l != skipval) break;
        l++;
        count -= sizeof(*l);
        pos += sizeof(*l)*8;
    }

    /* Load bytes into "word" considering the first byte as the most significant
     * (we basically consider it as written in big endian, since we consider the
     * string as a set of bits from left to right, with the first bit at position
     * zero.
     *
     * Note that the loading is designed to work even when the bytes left
     * (count) are less than a full word. We pad it with zero on the right. */
    c = (unsigned char*)l;
    for (j = 0; j < sizeof(*l); j++) {
        word <<= 8;
        if (count) {
            word |= *c;
            c++;
            count--;
        }
    }

    /* Special case:
     * If bits in the string are all zero and we are looking for one,
     * return -1 to signal that there is not a single "1" in the whole
     * string. This can't happen when we are looking for "0" as we assume
     * that the right of the string is zero padded. */
    if (bit == 1 && word == 0) return -1;

    /* Last word left, scan bit by bit. The first thing we need is to
     * have a single "1" set in the most significant position in an
     * unsigned long. We don't know the size of the long so we use a
     * simple trick. */
    one = ULONG_MAX; /* All bits set to 1.*/
    one >>= 1;       /* All bits set to 1 but the MSB. */
    one = ~one;      /* All bits set to 0 but the MSB. */

    while(one) {
        if (((one & word) != 0) == bit) return pos;
        pos++;
        one >>= 1;
    }

    /* If we reached this point, there is a bug in the algorithm, since
     * the case of no match is handled as a special case before. */
    redisPanic("End of redisBitpos() reached.");
    return 0; /* Just to avoid warnings. */
}

// Assembly:
pushq %rax
xorl %ecx, %ecx
testl %edx, %edx
movl $0xff, %r8d
cmovneq %rcx, %r8
testb $0x7, %dil
sete %al
testq %rsi, %rsi
sete %r9b
orb %al, %r9b
jne 0x59c07
leaq 0x1(%rdi), %r9
xorl %ecx, %ecx
movzbl (%rdi), %eax
cmpl %eax, %r8d
jne 0x59c07
incq %rdi
leaq -0x1(%rsi), %rax
addq $0x8, %rcx
testb $0x7, %r9b
je 0x59c0a
incq %r9
cmpq $0x1, %rsi
movq %rax, %rsi
jne 0x59be0
jmp 0x59c0a
movq %rsi, %rax
xorl %esi, %esi
cmpl $0x1, %edx
sbbq %rsi, %rsi
cmpq $0x8, %rax
jb 0x59c2f
cmpq %rsi, (%rdi)
jne 0x59c2f
addq $0x8, %rdi
addq $-0x8, %rax
addq $0x40, %rcx
cmpq $0x7, %rax
ja 0x59c18
movl $0x8, %r8d
xorl %esi, %esi
shlq $0x8, %rsi
testq %rax, %rax
je 0x59c4f
movzbl (%rdi), %r9d
orq %r9, %rsi
incq %rdi
decq %rax
jmp 0x59c51
xorl %eax, %eax
decl %r8d
jne 0x59c37
cmpl $0x1, %edx
jne 0x59c67
movq $-0x1, %rax
testq %rsi, %rsi
je 0x59cb5
movabsq $-0x8000000000000000, %rdi # imm = 0x8000000000000000
xorl %eax, %eax
xorl %r8d, %r8d
testq %rsi, %rdi
setne %r8b
cmpl %edx, %r8d
je 0x59caf
shrq %rdi
incq %rax
cmpl $0x40, %eax
jne 0x59c73
leaq 0x44fcc(%rip), %rdi     # 0x9ec60
leaq 0x44fe5(%rip), %rsi     # 0x9ec80
movl $0xc7, %edx
callq 0x4d0e5
movl $0x1, %edi
callq 0x1f3b0
addq %rax, %rcx
movq %rcx, %rax
popq %rcx
retq