// File: /workspace/github_c_makefile_star2_O1/zhou-yuxin[P]redis-aof-no-cow/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 $0x68, %rsp
movq %rdi, %r13
movl 0x38(%rdi), %eax
cmpl $0x3, %eax
movq %rdi, 0x10(%rsp)
jl 0x78bcc
movl $0x1, %ecx
movq %rcx, 0x58(%rsp)
movl $0x2, %r12d
movl $0x0, (%rsp)
movq $0x0, 0x8(%rsp)
movl $0x0, 0x18(%rsp)
movq $0x0, 0x30(%rsp)
movl %r12d, %ebp
notl %ebp
addl %eax, %ebp
movq 0x40(%r13), %r13
movslq %r12d, %r14
movq (%r13,%r14,8), %rax
movq 0x8(%rax), %r15
movq $0x0, 0x40(%rsp)
xorl %eax, %eax
movl %eax, 0x20(%rsp)
movl %eax, 0x38(%rsp)
movq %r15, %rdi
leaq 0x46dc9(%rip), %rsi     # 0xbf725
callq 0x26300
testl %eax, %eax
sete %al
cmpl $0x2, %ebp
setge %bl
movl $0x0, %ecx
andb %al, %bl
jne 0x789af
movq %r15, %rdi
leaq 0x47ed4(%rip), %rsi     # 0xc0853
callq 0x26300
cmpl $0x3, %ebp
jl 0x78992
movl $0x1, %ecx
testl %eax, %eax
je 0x789af
movq %r15, %rdi
leaq 0x46d9a(%rip), %rsi     # 0xbf736
callq 0x26300
cmpl $0x3, %ebp
jl 0x78a13
movl $0x2, %ecx
testl %eax, %eax
jne 0x78a13
movl %ecx, %ebp
movq 0x8(%r13,%r14,8), %rsi
movq 0x10(%rsp), %r13
movq %r13, %rdi
leaq 0x20(%rsp), %rdx
leaq 0x38(%rsp), %rcx
callq 0x77966
testl %eax, %eax
jne 0x78ab3
movq 0x40(%r13), %rax
movq 0x10(%rax,%r14,8), %rsi
movl 0x38(%rsp), %r15d
movq %r13, %rdi
leaq 0x60(%rsp), %rdx
movl $0x1, %ecx
movl %r15d, %r8d
callq 0x778a6
testl %eax, %eax
jne 0x78ab3
testb %bl, %bl
je 0x78ae2
movl $0x2, %r14d
jmp 0x78b51
movq %r15, %rdi
leaq 0x4d7f0(%rip), %rsi     # 0xc620d
callq 0x26300
testl %ebp, %ebp
jle 0x78a98
testl %eax, %eax
jne 0x78a98
leal 0x1(%r14), %r12d
movq 0x8(%r13,%r14,8), %rax
movq 0x8(%rax), %r15
movq %r15, %rdi
leaq 0x5651c(%rip), %rsi     # 0xcef5d
callq 0x26300
movl $0x4, %r14d
testl %eax, %eax
je 0x78b38
movq %r15, %rdi
leaq 0x56504(%rip), %rsi     # 0xcef62
callq 0x26300
testl %eax, %eax
je 0x78bad
movq %r15, %rdi
leaq 0x51c28(%rip), %rsi     # 0xca69d
callq 0x26300
testl %eax, %eax
movq 0x10(%rsp), %r13
je 0x78bbf
movq %r13, %rdi
leaq 0x564d5(%rip), %rsi     # 0xcef66
callq 0x3ffcb
jmp 0x78ab3
leaq 0x8e811(%rip), %rax     # 0x1072b0
movq 0x80(%rax), %rsi
movq 0x10(%rsp), %r13
movq %r13, %rdi
callq 0x3fc19
movq 0x8(%rsp), %rdi
callq 0x3b3df
movl $0x1, %r14d
testb $0x3, %r14b
jne 0x78fde
incl %r12d
movl 0x38(%r13), %eax
cmpl %eax, %r12d
jl 0x78928
jmp 0x78bdd
movslq %r15d, %rax
movq 0x60(%rsp), %rcx
addq %rcx, %rax
decq %rax
movq 0x30(%rsp), %rcx
cmpq %rax, %rcx
cmovbeq %rax, %rcx
movq %rcx, 0x30(%rsp)
movq 0x40(%r13), %rax
movq 0x18(%rax,%r14,8), %rsi
movq %r13, %rdi
leaq 0x40(%rsp), %rdx
xorl %ecx, %ecx
callq 0x44b44
testl %eax, %eax
je 0x78b42
movq 0x8(%rsp), %rdi
callq 0x3b3df
movl $0x1, %r14d
movq $0x0, 0x58(%rsp)
jmp 0x78ac3
movl $0x0, 0x18(%rsp)
jmp 0x78bb5
movq $0x0, 0x58(%rsp)
movl $0x3, %r14d
movl (%rsp), %eax
movslq %eax, %rbx
incl %eax
movl %eax, (%rsp)
shlq $0x5, %rbx
leaq 0x20(%rbx), %rsi
movq 0x8(%rsp), %rdi
callq 0x3b349
movq 0x60(%rsp), %rcx
movq %rcx, (%rax,%rbx)
movq 0x40(%rsp), %rcx
movq %rcx, 0x8(%rax,%rbx)
movl %ebp, 0x10(%rax,%rbx)
movl 0x18(%rsp), %ecx
movl %ecx, 0x14(%rax,%rbx)
movl 0x38(%rsp), %ecx
movl %ecx, 0x18(%rax,%rbx)
movl 0x20(%rsp), %edx
movq %rax, 0x8(%rsp)
movl %edx, 0x1c(%rax,%rbx)
addl %r14d, %r12d
xorl %r14d, %r14d
jmp 0x78ac3
movl $0x1, 0x18(%rsp)
movq 0x10(%rsp), %r13
jmp 0x78ac3
movl $0x2, 0x18(%rsp)
jmp 0x78ac3
xorl %esi, %esi
xorl %eax, %eax
movq $0x0, 0x8(%rsp)
xorl %ebp, %ebp
jmp 0x78bed
cmpl $0x0, 0x58(%rsp)
sete %al
movl (%rsp), %ebp
movq 0x30(%rsp), %rsi
testb %al, %al
je 0x78c06
movq %r13, %rdi
callq 0x77a1e
movq %rax, %rbx
testq %rax, %rax
jne 0x78c38
jmp 0x78fde
movq 0x10(%r13), %rdi
movq 0x40(%r13), %rax
movq 0x8(%rax), %rsi
callq 0x44f5f
testq %rax, %rax
je 0x78c36
movq %rax, %rbx
movq %r13, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x441ab
testl %eax, %eax
jne 0x78fde
jmp 0x78c38
xorl %ebx, %ebx
movq %rbx, (%rsp)
movslq %ebp, %r12
movq %r13, %rdi
movq %r12, %rsi
callq 0x4063b
testl %r12d, %r12d
jle 0x78f8c
movl %ebp, %r12d
xorl %r15d, %r15d
xorl %ebx, %ebx
movq (%rsp), %rbp
movq %r12, 0x18(%rsp)
movq %r15, %rax
shlq $0x5, %rax
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax), %r14
movl 0x10(%rcx,%rax), %eax
decl %eax
cmpl $0x1, %eax
ja 0x78cd4
cmpl $0x0, 0x1c(%r14)
je 0x78cf6
movq 0x8(%rbp), %rdi
movq (%r14), %rsi
movslq 0x18(%r14), %r12
movq %r12, %rdx
callq 0x77663
movq %rax, %rbp
cmpl $0x2, 0x10(%r14)
movq 0x8(%r14), %r13
jne 0x78e03
movl 0x14(%r14), %ecx
movq %rbp, %rdi
movq %r13, %rsi
movq %r12, %rdx
leaq 0x40(%rsp), %r8
callq 0x77763
testl %eax, %eax
je 0x78e2d
movq 0x40(%rsp), %r13
jmp 0x78e30
movq $0x0, 0x38(%rsp)
testq %rbp, %rbp
je 0x78d45
movq %rbp, %rdi
leaq 0x38(%rsp), %rsi
leaq 0x40(%rsp), %rdx
callq 0x77ac6
jmp 0x78d47
movslq 0x18(%r14), %rcx
testq %rcx, %rcx
je 0x78e96
movq 0x8(%rbp), %rax
movq (%r14), %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 0x78d10
jmp 0x78e99
xorl %eax, %eax
movb $0x0, 0x28(%rsp)
movq $0x0, 0x20(%rsp)
movq (%r14), %rcx
testq %rax, %rax
je 0x78d90
movq %rcx, %rdx
shrq $0x3, %rdx
movq 0x38(%rsp), %rsi
leaq (%rax,%rdx), %rdi
xorl %r8d, %r8d
leaq (%rdx,%r8), %r9
cmpq %rsi, %r9
jae 0x78d90
movb (%rdi,%r8), %r9b
movb %r9b, 0x20(%rsp,%r8)
cmpq $0x7, %r8
ja 0x78d90
incq %r8
testq %rax, %rax
jne 0x78d70
cmpl $0x0, 0x1c(%r14)
je 0x78db7
movq (%r14), %rsi
andq $-0x8, %rcx
subq %rcx, %rsi
movslq 0x18(%r14), %rdx
leaq 0x20(%rsp), %rdi
callq 0x77663
movq %rax, %rsi
jmp 0x78f08
movslq 0x18(%r14), %rax
testq %rax, %rax
je 0x78f06
movq (%r14), %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 0x78dd0
jmp 0x78f08
movq %rbp, 0x30(%rsp)
movl 0x14(%r14), %ecx
movq %r13, %rdi
xorl %esi, %esi
movq %r12, %rdx
leaq 0x40(%rsp), %r8
callq 0x77763
testl %eax, %eax
je 0x78e27
movq 0x40(%rsp), %r13
movq (%rsp), %rbp
jmp 0x78e39
addq %rbp, %r13
movq (%rsp), %rbp
movq %r13, 0x30(%rsp)
testl %eax, %eax
je 0x78e5e
cmpl $0x2, 0x14(%r14)
jne 0x78e5e
leaq 0x8e465(%rip), %rax     # 0x1072b0
movq 0x50(%rax), %rsi
movq 0x10(%rsp), %r13
movq %r13, %rdi
callq 0x3fc19
jmp 0x78e8c
movl %ebx, %r12d
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
movq 0x30(%rsp), %rsi
callq 0x40606
movq 0x8(%rbp), %rdi
movq (%r14), %rsi
movslq 0x18(%r14), %rdx
movq %r13, %rcx
movq %rbx, %r13
movl %r12d, %ebx
callq 0x775e5
movq 0x18(%rsp), %r12
jmp 0x78f7c
xorl %r13d, %r13d
cmpl $0x2, 0x10(%r14)
movq 0x8(%r14), %rbp
jne 0x78ec8
movl 0x14(%r14), %eax
movq %r13, %rdi
movq %rbp, %rsi
movq %rcx, %rdx
movl %eax, %ecx
leaq 0x40(%rsp), %r8
callq 0x776c3
testl %eax, %eax
je 0x78f12
movq 0x40(%rsp), %rbp
jmp 0x78f15
movq $-0x1, %rdx
shlq %cl, %rdx
cmpl $0x40, %ecx
notq %rdx
movq %rdx, %rcx
movq $-0x1, %rax
cmoveq %rax, %rcx
xorl %eax, %eax
cmpq %rbp, %rcx
jae 0x78f22
movl 0x14(%r14), %esi
movl $0x1, %eax
testl %esi, %esi
je 0x78f1a
cmpl $0x1, %esi
jne 0x78f22
movq %rcx, 0x40(%rsp)
jmp 0x78f22
xorl %esi, %esi
movq %r13, %rdi
callq 0x40606
jmp 0x78f7e
addq %r13, %rbp
movq %rbp, %r13
jmp 0x78f2c
andq %rbp, %rdx
movq %rdx, 0x40(%rsp)
cmpq %rbp, %rcx
jae 0x78f2c
movq 0x40(%rsp), %rbp
testl %eax, %eax
je 0x78f51
cmpl $0x2, 0x14(%r14)
jne 0x78f51
leaq 0x8e372(%rip), %rax     # 0x1072b0
movq 0x50(%rax), %rsi
movq 0x10(%rsp), %r13
movq %r13, %rdi
callq 0x3fc19
jmp 0x78f78
movq 0x10(%rsp), %rdi
movq %r13, %rsi
movq %rdi, %r13
callq 0x40606
movq (%rsp), %rax
movq 0x8(%rax), %rdi
movq (%r14), %rsi
movslq 0x18(%r14), %rdx
movq %rbp, %rcx
callq 0x775e5
movq (%rsp), %rbp
incl %ebx
incq %r15
cmpq %r12, %r15
jne 0x78c64
jmp 0x78f8e
xorl %ebx, %ebx
testl %ebx, %ebx
je 0x78fd4
movq 0x10(%r13), %rdi
movq 0x40(%r13), %rax
movq 0x8(%rax), %rsi
callq 0x45220
movq 0x10(%r13), %rax
movq 0x40(%r13), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
leaq 0x46577(%rip), %rsi     # 0xbf530
movl $0x8, %edi
callq 0x800c9
movslq %ebx, %rax
leaq 0x8d88b(%rip), %rcx     # 0x106858
addq %rax, 0x710(%rcx)
movq 0x8(%rsp), %rdi
callq 0x3b3df
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)