// File: /workspace/github_c_makefile_star2_O0/gplessis[P]dotdeb-redis/src/bitops.c
// Function: redisBitpos
long redisBitpos(void *s, unsigned 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. */
    unsigned long 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. */
    serverPanic("End of redisBitpos() reached.");
    return 0; /* Just to avoid warnings. */
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq $0x0, -0x40(%rbp)
movq $0x0, -0x50(%rbp)
movl -0x1c(%rbp), %edx
movl $0xff, %eax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
cltq
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rcx
andq $0x7, %rcx
xorl %eax, %eax
cmpq $0x0, %rcx
movb %al, -0x59(%rbp)
je 0x9053f
cmpq $0x0, -0x18(%rbp)
setne %al
movb %al, -0x59(%rbp)
movb -0x59(%rbp), %al
testb $0x1, %al
jne 0x90548
jmp 0x9057d
movq -0x30(%rbp), %rax
movzbl (%rax), %eax
cmpq -0x38(%rbp), %rax
je 0x90557
jmp 0x9057d
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x18(%rbp)
movq -0x50(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x50(%rbp)
jmp 0x90521
movl -0x1c(%rbp), %edx
movq $-0x1, %rax
xorl %ecx, %ecx
cmpl $0x0, %edx
cmovneq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x28(%rbp)
cmpq $0x8, -0x18(%rbp)
jb 0x905d8
movq -0x28(%rbp), %rax
movq (%rax), %rax
cmpq -0x38(%rbp), %rax
je 0x905b2
jmp 0x905d8
movq -0x28(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rax
subq $0x8, %rax
movq %rax, -0x18(%rbp)
movq -0x50(%rbp), %rax
addq $0x40, %rax
movq %rax, -0x50(%rbp)
jmp 0x9059c
movq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq $0x0, -0x58(%rbp)
cmpq $0x8, -0x58(%rbp)
jae 0x90639
movq -0x40(%rbp), %rax
shlq $0x8, %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x90629
movq -0x30(%rbp), %rax
movzbl (%rax), %eax
orq -0x40(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x30(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x18(%rbp)
jmp 0x9062b
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x905e8
cmpl $0x1, -0x1c(%rbp)
jne 0x90653
cmpq $0x0, -0x40(%rbp)
jne 0x90653
movq $-0x1, -0x8(%rbp)
jmp 0x906d7
movq $-0x1, -0x48(%rbp)
movq -0x48(%rbp), %rax
shrq %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
xorq $-0x1, %rax
movq %rax, -0x48(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x906b5
movq -0x48(%rbp), %rax
andq -0x40(%rbp), %rax
cmpq $0x0, %rax
setne %al
andb $0x1, %al
movzbl %al, %eax
cmpl -0x1c(%rbp), %eax
jne 0x9069c
movq -0x50(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x906d7
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rax
shrq %rax
movq %rax, -0x48(%rbp)
jmp 0x90672
leaq 0xb5704(%rip), %rdi     # 0x145dc0
leaq 0xb571d(%rip), %rsi     # 0x145de0
movl $0xb1, %edx
callq 0x76d80
movl $0x1, %edi
callq 0x263c0
movq -0x8(%rbp), %rax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)