// File: /workspace/github_c_makefile_star2_O3/gplessis[P]dotdeb-redis/src/bitops.c
// Function: bitfieldCommand
void bitfieldCommand(client *c) {
    robj *o;
    size_t bitoffset;
    int j, numops = 0, changes = 0;
    struct bitfieldOp *ops = NULL; /* Array of ops to execute at end. */
    int owtype = BFOVERFLOW_WRAP; /* Overflow type. */
    int readonly = 1;
    size_t higest_write_offset = 0;

    for (j = 2; j < c->argc; j++) {
        int remargs = c->argc-j-1; /* Remaining args other than current. */
        char *subcmd = c->argv[j]->ptr; /* Current command name. */
        int opcode; /* Current operation code. */
        long long i64 = 0;  /* Signed SET value. */
        int sign = 0; /* Signed or unsigned type? */
        int bits = 0; /* Bitfield width in bits. */

        if (!strcasecmp(subcmd,"get") && remargs >= 2)
            opcode = BITFIELDOP_GET;
        else if (!strcasecmp(subcmd,"set") && remargs >= 3)
            opcode = BITFIELDOP_SET;
        else if (!strcasecmp(subcmd,"incrby") && remargs >= 3)
            opcode = BITFIELDOP_INCRBY;
        else if (!strcasecmp(subcmd,"overflow") && remargs >= 1) {
            char *owtypename = c->argv[j+1]->ptr;
            j++;
            if (!strcasecmp(owtypename,"wrap"))
                owtype = BFOVERFLOW_WRAP;
            else if (!strcasecmp(owtypename,"sat"))
                owtype = BFOVERFLOW_SAT;
            else if (!strcasecmp(owtypename,"fail"))
                owtype = BFOVERFLOW_FAIL;
            else {
                addReplyError(c,"Invalid OVERFLOW type specified");
                zfree(ops);
                return;
            }
            continue;
        } else {
            addReply(c,shared.syntaxerr);
            zfree(ops);
            return;
        }

        /* Get the type and offset arguments, common to all the ops. */
        if (getBitfieldTypeFromArgument(c,c->argv[j+1],&sign,&bits) != C_OK) {
            zfree(ops);
            return;
        }

        if (getBitOffsetFromArgument(c,c->argv[j+2],&bitoffset,1,bits) != C_OK){
            zfree(ops);
            return;
        }

        if (opcode != BITFIELDOP_GET) {
            readonly = 0;
            if (higest_write_offset < bitoffset + bits - 1)
                higest_write_offset = bitoffset + bits - 1;
            /* INCRBY and SET require another argument. */
            if (getLongLongFromObjectOrReply(c,c->argv[j+3],&i64,NULL) != C_OK){
                zfree(ops);
                return;
            }
        }

        /* Populate the array of operations we'll process. */
        ops = zrealloc(ops,sizeof(*ops)*(numops+1));
        ops[numops].offset = bitoffset;
        ops[numops].i64 = i64;
        ops[numops].opcode = opcode;
        ops[numops].owtype = owtype;
        ops[numops].bits = bits;
        ops[numops].sign = sign;
        numops++;

        j += 3 - (opcode == BITFIELDOP_GET);
    }

    if (readonly) {
        /* Lookup for read is ok if key doesn't exit, but errors
         * if it's not a string. */
        o = lookupKeyRead(c->db,c->argv[1]);
        if (o != NULL && checkType(c,o,OBJ_STRING)) return;
    } else {
        /* Lookup by making room up to the farest bit reached by
         * this operation. */
        if ((o = lookupStringForBitCommand(c,
            higest_write_offset)) == NULL) return;
    }

    addReplyMultiBulkLen(c,numops);

    /* Actually process the operations. */
    for (j = 0; j < numops; j++) {
        struct bitfieldOp *thisop = ops+j;

        /* Execute the operation. */
        if (thisop->opcode == BITFIELDOP_SET ||
            thisop->opcode == BITFIELDOP_INCRBY)
        {
            /* SET and INCRBY: We handle both with the same code path
             * for simplicity. SET return value is the previous value so
             * we need fetch & store as well. */

            /* We need two different but very similar code paths for signed
             * and unsigned operations, since the set of functions to get/set
             * the integers and the used variables types are different. */
            if (thisop->sign) {
                int64_t oldval, newval, wrapped, retval;
                int overflow;

                oldval = getSignedBitfield(o->ptr,thisop->offset,
                        thisop->bits);

                if (thisop->opcode == BITFIELDOP_INCRBY) {
                    newval = oldval + thisop->i64;
                    overflow = checkSignedBitfieldOverflow(oldval,
                            thisop->i64,thisop->bits,thisop->owtype,&wrapped);
                    if (overflow) newval = wrapped;
                    retval = newval;
                } else {
                    newval = thisop->i64;
                    overflow = checkSignedBitfieldOverflow(newval,
                            0,thisop->bits,thisop->owtype,&wrapped);
                    if (overflow) newval = wrapped;
                    retval = oldval;
                }

                /* On overflow of type is "FAIL", don't write and return
                 * NULL to signal the condition. */
                if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {
                    addReplyLongLong(c,retval);
                    setSignedBitfield(o->ptr,thisop->offset,
                                      thisop->bits,newval);
                } else {
                    addReply(c,shared.nullbulk);
                }
            } else {
                uint64_t oldval, newval, wrapped, retval;
                int overflow;

                oldval = getUnsignedBitfield(o->ptr,thisop->offset,
                        thisop->bits);

                if (thisop->opcode == BITFIELDOP_INCRBY) {
                    newval = oldval + thisop->i64;
                    overflow = checkUnsignedBitfieldOverflow(oldval,
                            thisop->i64,thisop->bits,thisop->owtype,&wrapped);
                    if (overflow) newval = wrapped;
                    retval = newval;
                } else {
                    newval = thisop->i64;
                    overflow = checkUnsignedBitfieldOverflow(newval,
                            0,thisop->bits,thisop->owtype,&wrapped);
                    if (overflow) newval = wrapped;
                    retval = oldval;
                }
                /* On overflow of type is "FAIL", don't write and return
                 * NULL to signal the condition. */
                if (!(overflow && thisop->owtype == BFOVERFLOW_FAIL)) {
                    addReplyLongLong(c,retval);
                    setUnsignedBitfield(o->ptr,thisop->offset,
                                        thisop->bits,newval);
                } else {
                    addReply(c,shared.nullbulk);
                }
            }
            changes++;
        } else {
            /* GET */
            unsigned char buf[9];
            long strlen = 0;
            unsigned char *src = NULL;
            char llbuf[LONG_STR_SIZE];

            if (o != NULL)
                src = getObjectReadOnlyString(o,&strlen,llbuf);

            /* For GET we use a trick: before executing the operation
             * copy up to 9 bytes to a local buffer, so that we can easily
             * execute up to 64 bit operations that are at actual string
             * object boundaries. */
            memset(buf,0,9);
            int i;
            size_t byte = thisop->offset >> 3;
            for (i = 0; i < 9; i++) {
                if (src == NULL || i+byte >= (size_t)strlen) break;
                buf[i] = src[i+byte];
            }

            /* Now operate on the copied buffer which is guaranteed
             * to be zero-padded. */
            if (thisop->sign) {
                int64_t val = getSignedBitfield(buf,thisop->offset-(byte*8),
                                            thisop->bits);
                addReplyLongLong(c,val);
            } else {
                uint64_t val = getUnsignedBitfield(buf,thisop->offset-(byte*8),
                                            thisop->bits);
                addReplyLongLong(c,val);
            }
        }
    }

    if (changes) {
        signalModifiedKey(c->db,c->argv[1]);
        notifyKeyspaceEvent(NOTIFY_STRING,"setbit",c->argv[1],c->db->id);
        server.dirty += changes;
    }
    zfree(ops);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdi, %r14
movl 0x38(%rdi), %ecx
cmpl $0x3, %ecx
movq %rdi, 0x8(%rsp)
jl 0x75039
movl $0x1, %eax
movq %rax, 0x68(%rsp)
movl $0x2, %ebp
xorl %r15d, %r15d
xorl %eax, %eax
movl $0x0, 0x18(%rsp)
movq $0x0, 0x60(%rsp)
movq %r15, 0x38(%rsp)
movq %rax, 0x10(%rsp)
movl %ebp, %ebx
notl %ebx
movl %ecx, 0x4(%rsp)
addl %ecx, %ebx
movq 0x40(%r14), %r14
movslq %ebp, %r13
movq (%r14,%r13,8), %rax
movq 0x8(%rax), %r12
movq $0x0, 0x40(%rsp)
xorl %eax, %eax
movl %eax, 0x20(%rsp)
movl %eax, 0x30(%rsp)
movq %r12, %rdi
leaq 0x47961(%rip), %rsi     # 0xbc775
callq 0x262f0
testl %eax, %eax
sete %al
cmpl $0x2, %ebx
setge %r15b
movl $0x0, %ecx
andb %al, %r15b
jne 0x74e71
movq %r12, %rdi
leaq 0x48a8c(%rip), %rsi     # 0xbd8c5
callq 0x262f0
cmpl $0x3, %ebx
jl 0x74e4c
movl $0x1, %ecx
testl %eax, %eax
je 0x74e71
movq %r12, %rdi
leaq 0x47930(%rip), %rsi     # 0xbc786
callq 0x262f0
cmpl $0x3, %ebx
jl 0x74f89
movl $0x2, %ecx
testl %eax, %eax
jne 0x74f89
movl %ecx, 0x4(%rsp)
movq 0x8(%r14,%r13,8), %rsi
movq 0x8(%rsp), %r14
movq %r14, %rdi
leaq 0x20(%rsp), %rdx
leaq 0x30(%rsp), %rcx
callq 0x73ea7
testl %eax, %eax
jne 0x75474
movq 0x40(%r14), %rax
movq 0x10(%rax,%r13,8), %rsi
movl 0x30(%rsp), %r12d
movq %r14, %rdi
leaq 0x70(%rsp), %rdx
movl $0x1, %ecx
movl %r12d, %r8d
callq 0x73de5
testl %eax, %eax
jne 0x75474
movl $0x2, %ebx
testb %r15b, %r15b
jne 0x74f1b
movslq %r12d, %rax
movq 0x70(%rsp), %rcx
addq %rcx, %rax
decq %rax
movq 0x60(%rsp), %rcx
cmpq %rax, %rcx
cmovbeq %rax, %rcx
movq %rcx, 0x60(%rsp)
movq 0x40(%r14), %rax
movq 0x18(%rax,%r13,8), %rsi
movq $0x0, 0x68(%rsp)
movq %r14, %rdi
leaq 0x40(%rsp), %rdx
xorl %ecx, %ecx
callq 0x416bb
movl $0x3, %ebx
testl %eax, %eax
jne 0x75474
movq 0x38(%rsp), %r15
movslq %r15d, %r14
incl %r15d
shlq $0x5, %r14
leaq 0x20(%r14), %rsi
movq 0x10(%rsp), %rdi
callq 0x3837d
movq 0x70(%rsp), %rcx
movq %rcx, (%rax,%r14)
movq 0x40(%rsp), %rcx
movq %rcx, 0x8(%rax,%r14)
movl 0x4(%rsp), %ecx
movl %ecx, 0x10(%rax,%r14)
movl 0x18(%rsp), %ecx
movl %ecx, 0x14(%rax,%r14)
movl 0x30(%rsp), %ecx
movl %ecx, 0x18(%rax,%r14)
movl 0x20(%rsp), %ecx
movl %ecx, 0x1c(%rax,%r14)
movq 0x8(%rsp), %r14
addl %ebx, %ebp
movl 0x38(%r14), %ecx
incl %ebp
cmpl %ecx, %ebp
jl 0x74dd4
jmp 0x75420
movq %r12, %rdi
leaq 0x4e2fa(%rip), %rsi     # 0xc328d
callq 0x262f0
testl %ebx, %ebx
jle 0x7544b
testl %eax, %eax
jne 0x7544b
leal 0x1(%r13), %ebp
movq 0x8(%r14,%r13,8), %rax
movq 0x8(%rax), %r12
movq %r12, %rdi
leaq 0x5709e(%rip), %rsi     # 0xcc05d
callq 0x262f0
testl %eax, %eax
je 0x75005
movq %r12, %rdi
leaq 0x57090(%rip), %rsi     # 0xcc062
callq 0x262f0
testl %eax, %eax
movq 0x38(%rsp), %r15
je 0x7501e
movq %r12, %rdi
leaq 0x5273b(%rip), %rsi     # 0xc7725
callq 0x262f0
movl $0x2, 0x18(%rsp)
testl %eax, %eax
movq 0x8(%rsp), %r14
je 0x7502b
jmp 0x75465
movl $0x0, 0x18(%rsp)
movq 0x8(%rsp), %r14
movq 0x10(%rsp), %rax
movq 0x38(%rsp), %r15
jmp 0x75030
movl $0x1, 0x18(%rsp)
movq 0x8(%rsp), %r14
movq 0x10(%rsp), %rax
movl 0x4(%rsp), %ecx
jmp 0x74f7a
xorl %r15d, %r15d
xorl %eax, %eax
movq %rax, 0x10(%rsp)
movq 0x10(%r14), %rdi
movq 0x40(%r14), %rax
movq 0x8(%rax), %rsi
callq 0x41acf
testq %rax, %rax
je 0x75073
movq %rax, %rbp
movq %r14, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x40d47
testl %eax, %eax
jne 0x7547e
jmp 0x75075
xorl %ebp, %ebp
movslq %r15d, %r12
movq %r14, %rdi
movq %r12, %rsi
callq 0x3d274
testl %r12d, %r12d
movq 0x10(%rsp), %r12
jle 0x7541b
movl %r15d, %eax
movq %rax, 0x38(%rsp)
xorl %r15d, %r15d
xorl %r13d, %r13d
movq %rbp, 0x18(%rsp)
movq %r15, %rax
shlq $0x5, %rax
leaq (%r12,%rax), %rbx
movl 0x10(%r12,%rax), %r14d
leal -0x1(%r14), %eax
cmpl $0x1, %eax
ja 0x7511d
cmpl $0x0, 0x1c(%rbx)
movl %r13d, 0x4(%rsp)
je 0x75192
movq 0x8(%rbp), %rdi
movq (%rbx), %rsi
movslq 0x18(%rbx), %r12
movq %r12, %rdx
callq 0x73ba2
movq %rax, %rbp
movq 0x8(%rbx), %r13
cmpl $0x2, %r14d
jne 0x75269
movl 0x14(%rbx), %ecx
movq %rbp, %rdi
movq %r13, %rsi
movq %r12, %rdx
leaq 0x40(%rsp), %r8
callq 0x73ca2
testl %eax, %eax
movq 0x8(%rsp), %r14
je 0x75293
movq 0x40(%rsp), %r13
jmp 0x75296
movq $0x0, 0x30(%rsp)
testq %rbp, %rbp
je 0x751e1
movq %rbp, %rdi
leaq 0x30(%rsp), %rsi
leaq 0x40(%rsp), %rdx
callq 0x74007
movq $0x0, 0x20(%rsp)
movb $0x0, 0x28(%rsp)
movq (%rbx), %rcx
testq %rax, %rax
movq 0x8(%rsp), %r14
je 0x751f7
movq %rcx, %rdx
shrq $0x3, %rdx
movq 0x30(%rsp), %rsi
addq %rdx, %rax
xorl %edi, %edi
leaq (%rdx,%rdi), %r8
cmpq %rsi, %r8
jae 0x751f7
movb (%rax,%rdi), %r8b
movb %r8b, 0x20(%rsp,%rdi)
leaq 0x1(%rdi), %r8
cmpq $0x8, %rdi
movq %r8, %rdi
jb 0x75171
jmp 0x751f7
movslq 0x18(%rbx), %rcx
testq %rcx, %rcx
je 0x752ef
movq 0x8(%rbp), %rax
movq (%rbx), %rdx
movq %rcx, %rsi
xorl %r13d, %r13d
movq %rdx, %rdi
shrq $0x3, %rdi
movzbl (%rax,%rdi), %edi
movl %edx, %r8d
notb %r8b
movzbl %r8b, %r8d
andl $0x7, %r8d
xorl %r9d, %r9d
btl %r8d, %edi
setb %r9b
leaq (%r9,%r13,2), %r13
incq %rdx
decq %rsi
jne 0x751ac
jmp 0x752f2
movb $0x0, 0x28(%rsp)
movq $0x0, 0x20(%rsp)
movq (%rbx), %rcx
movq 0x8(%rsp), %r14
cmpl $0x0, 0x1c(%rbx)
je 0x7521d
movq (%rbx), %rsi
andq $-0x8, %rcx
subq %rcx, %rsi
movslq 0x18(%rbx), %rdx
leaq 0x20(%rsp), %rdi
callq 0x73ba2
movq %rax, %rsi
jmp 0x7536a
movslq 0x18(%rbx), %rax
testq %rax, %rax
je 0x75368
movq (%rbx), %rdx
andq $-0x8, %rcx
subq %rcx, %rdx
xorl %esi, %esi
movq %rdx, %rcx
shrq $0x3, %rcx
movzbl 0x20(%rsp,%rcx), %ecx
movl %edx, %edi
notb %dil
movzbl %dil, %edi
andl $0x7, %edi
xorl %r8d, %r8d
btl %edi, %ecx
setb %r8b
leaq (%r8,%rsi,2), %rsi
incq %rdx
decq %rax
jne 0x75236
jmp 0x7536a
movl 0x14(%rbx), %ecx
movq %r13, %rdi
xorl %esi, %esi
movq %r12, %rdx
leaq 0x40(%rsp), %r8
callq 0x73ca2
testl %eax, %eax
movq 0x8(%rsp), %r14
je 0x7528c
movq 0x40(%rsp), %r13
movq 0x10(%rsp), %r12
jmp 0x7529e
addq %rbp, %r13
movq 0x10(%rsp), %r12
movq %r13, %rbp
testl %eax, %eax
je 0x752c2
cmpl $0x2, 0x14(%rbx)
jne 0x752c2
leaq 0x8d061(%rip), %rax     # 0x102310
movq 0x50(%rax), %rsi
movq %r14, %rdi
callq 0x3c854
movq 0x18(%rsp), %rbp
jmp 0x752e5
movq %r14, %rdi
movq %rbp, %rsi
callq 0x3d23f
movq 0x18(%rsp), %rbp
movq 0x8(%rbp), %rdi
movq (%rbx), %rsi
movslq 0x18(%rbx), %rdx
movq %r13, %rcx
callq 0x73b24
movl 0x4(%rsp), %r13d
jmp 0x753c3
xorl %r13d, %r13d
movq 0x8(%rbx), %rbp
cmpl $0x2, %r14d
jne 0x7532a
movl 0x14(%rbx), %eax
movq %r13, %rdi
movq %rbp, %rsi
movq %rcx, %rdx
movl %eax, %ecx
leaq 0x40(%rsp), %r8
callq 0x73c02
testl %eax, %eax
movq 0x8(%rsp), %r14
je 0x75374
movq 0x40(%rsp), %r13
movl 0x14(%rbx), %ecx
movq %r13, %rbp
jmp 0x7537c
cmpl $0x40, %ecx
setne %dl
movq $-0x1, %rax
shlq %cl, %rax
notq %rax
cmpq %rax, %rbp
seta %cl
andb %dl, %cl
cmpb $0x1, %cl
movq 0x8(%rsp), %r14
jne 0x75396
movl 0x14(%rbx), %ecx
cmpl $0x1, %ecx
je 0x7535e
testl %ecx, %ecx
jne 0x7537c
andq %rbp, %rax
movq %rax, 0x40(%rsp)
movq %rax, %rbp
jmp 0x75396
xorl %esi, %esi
movq %r14, %rdi
callq 0x3d23f
jmp 0x753c6
addq %r13, %rbp
movq %rbp, %r13
jmp 0x75396
cmpl $0x2, %ecx
jne 0x75396
leaq 0x8cf88(%rip), %rax     # 0x102310
movq 0x50(%rax), %rsi
movq %r14, %rdi
callq 0x3c854
jmp 0x753b9
movq %r14, %rdi
movq %r13, %rsi
callq 0x3d23f
movq 0x18(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rbx), %rsi
movslq 0x18(%rbx), %rdx
movq %rbp, %rcx
callq 0x73b24
movl 0x4(%rsp), %r13d
movq 0x18(%rsp), %rbp
incl %r13d
incq %r15
cmpq 0x38(%rsp), %r15
jne 0x750a4
testl %r13d, %r13d
je 0x7541b
movq 0x10(%r14), %rdi
movq 0x40(%r14), %rax
movq 0x8(%rax), %rsi
callq 0x41d90
movq 0x10(%r14), %rax
movq 0x40(%r14), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
leaq 0x47180(%rip), %rsi     # 0xbc580
movl $0x8, %edi
callq 0x7c665
movslq %r13d, %rax
leaq 0x8c494(%rip), %rcx     # 0x1018a8
addq %rax, 0x720(%rcx)
movq %r12, %rdi
jmp 0x75479
cmpl $0x0, 0x68(%rsp)
jne 0x7503e
movq %rax, 0x10(%rsp)
movq %r14, %rdi
movq 0x60(%rsp), %rsi
callq 0x73f5f
movq %rax, %rbp
testq %rax, %rax
jne 0x75075
jmp 0x7547e
leaq 0x8cebe(%rip), %rax     # 0x102310
movq 0x80(%rax), %rsi
movq 0x8(%rsp), %rdi
callq 0x3c854
jmp 0x75474
leaq 0x56bfa(%rip), %rsi     # 0xcc066
movq %r14, %rdi
callq 0x3cc06
movq 0x10(%rsp), %rdi
callq 0x38413
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)