// File: /workspace/github_c_makefile_star2_O2/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 $0x88, %rsp
movq %rdi, %r12
pushq $0x2
popq %rbp
movq $0x0, 0x70(%rsp)
pushq $0x1
popq %rax
movq %rax, 0x78(%rsp)
movl $0x0, 0x1c(%rsp)
xorl %r14d, %r14d
xorl %r13d, %r13d
movq %rdi, 0x8(%rsp)
movq %r12, %rcx
movl 0x38(%r12), %r12d
movslq %r13d, %rax
movq %rax, 0x20(%rsp)
cmpl %r12d, %ebp
jge 0x69101
movl %r13d, 0x4c(%rsp)
movq %r14, 0x10(%rsp)
movl %ebp, %eax
movq 0x40(%rcx), %rbx
movl %ebp, 0x38(%rsp)
movslq %ebp, %r14
movq (%rbx,%r14,8), %rcx
movq 0x8(%rcx), %r13
andq $0x0, 0x50(%rsp)
notl %eax
andl $0x0, 0x28(%rsp)
addl %eax, %r12d
andl $0x0, 0x40(%rsp)
movq %r13, %rdi
leaq 0x4576a(%rip), %rsi     # 0xae665
callq 0x262f0
testl %eax, %eax
sete %al
cmpl $0x2, %r12d
setge %r15b
xorl %ebp, %ebp
andb %al, %r15b
jne 0x68f54
movq %r13, %rdi
leaq 0x46897(%rip), %rsi     # 0xaf7b5
callq 0x262f0
cmpl $0x3, %r12d
jl 0x68f30
pushq $0x1
popq %rbp
testl %eax, %eax
je 0x68f54
movq %r13, %rdi
leaq 0x4573c(%rip), %rsi     # 0xae676
callq 0x262f0
cmpl $0x3, %r12d
jl 0x6905f
pushq $0x2
popq %rbp
testl %eax, %eax
jne 0x6905f
movq 0x8(%rbx,%r14,8), %rsi
movq 0x8(%rsp), %r12
movq %r12, %rdi
leaq 0x28(%rsp), %rdx
leaq 0x40(%rsp), %rcx
callq 0x680d9
testl %eax, %eax
jne 0x6947b
movq 0x40(%r12), %rax
movq 0x10(%rax,%r14,8), %rsi
movl 0x40(%rsp), %r13d
movq %r12, %rdi
leaq 0x80(%rsp), %rdx
pushq $0x1
popq %rcx
movl %r13d, %r8d
callq 0x67ffd
testl %eax, %eax
jne 0x6947b
testb %r15b, %r15b
je 0x68faf
pushq $0x2
popq %rbx
jmp 0x68ffe
movslq %r13d, %rax
movq 0x80(%rsp), %rcx
addq %rcx, %rax
decq %rax
movq 0x70(%rsp), %rcx
cmpq %rax, %rcx
cmovbeq %rax, %rcx
movq %rcx, 0x70(%rsp)
movq 0x40(%r12), %rax
movq 0x18(%rax,%r14,8), %rsi
movq $0x0, 0x78(%rsp)
movq %r12, %rdi
leaq 0x50(%rsp), %rdx
xorl %ecx, %ecx
callq 0x3ab03
pushq $0x3
popq %rbx
testl %eax, %eax
jne 0x6947b
movq 0x20(%rsp), %r15
leal 0x1(%r15), %r13d
shlq $0x5, %r15
leaq 0x20(%r15), %rsi
movq 0x10(%rsp), %rdi
callq 0x32863
movq %rax, %r14
movq 0x80(%rsp), %rax
movq %rax, (%r14,%r15)
movq 0x50(%rsp), %rax
movq %rax, 0x8(%r14,%r15)
movl %ebp, 0x10(%r14,%r15)
movl 0x1c(%rsp), %eax
movl %eax, 0x14(%r14,%r15)
movl 0x40(%rsp), %eax
movl %eax, 0x18(%r14,%r15)
movl 0x28(%rsp), %eax
movl %eax, 0x1c(%r14,%r15)
movl 0x38(%rsp), %ebp
addl %ebx, %ebp
incl %ebp
jmp 0x68ea4
movq %r13, %rdi
leaq 0x4b7f4(%rip), %rsi     # 0xb485d
callq 0x262f0
testl %r12d, %r12d
jle 0x69452
testl %eax, %eax
jne 0x69452
movl 0x38(%rsp), %ebp
incl %ebp
movq 0x8(%rbx,%r14,8), %rax
movq 0x8(%rax), %r15
movq %r15, %rdi
leaq 0x53d95(%rip), %rsi     # 0xbce2d
callq 0x262f0
testl %eax, %eax
movq 0x8(%rsp), %r12
je 0x690d9
movq %r15, %rdi
leaq 0x53d82(%rip), %rsi     # 0xbce32
callq 0x262f0
testl %eax, %eax
movl 0x4c(%rsp), %r13d
je 0x690f0
movq %r15, %rdi
leaq 0x4f645(%rip), %rsi     # 0xb870d
callq 0x262f0
testl %eax, %eax
jne 0x6946c
pushq $0x2
jmp 0x690f2
movl $0x0, 0x1c(%rsp)
movq 0x10(%rsp), %r14
movl 0x4c(%rsp), %r13d
jmp 0x69058
pushq $0x1
popq %rax
movl %eax, 0x1c(%rsp)
movq 0x10(%rsp), %r14
jmp 0x69058
cmpl $0x0, 0x78(%rsp)
je 0x69142
movq 0x8(%rsp), %rbx
movq 0x10(%rbx), %rdi
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x3aebb
testq %rax, %rax
movq 0x20(%rsp), %r12
je 0x69166
movq %rax, %rbp
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x3a311
testl %eax, %eax
jne 0x69485
jmp 0x69168
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq 0x70(%rsp), %rsi
callq 0x6818d
movq %rax, %rbp
testq %rax, %rax
movq 0x20(%rsp), %r12
jne 0x69168
jmp 0x69485
xorl %ebp, %ebp
movq %rbx, %rdi
movq %r12, %rsi
callq 0x370d9
xorl %ecx, %ecx
testl %r12d, %r12d
cmovlel %ecx, %r12d
xorl %r15d, %r15d
movq %rbp, 0x20(%rsp)
cmpq %r12, %rcx
je 0x69403
movq %rcx, %rax
shlq $0x5, %rax
leaq (%r14,%rax), %r13
movl 0x10(%r14,%rax), %ebx
leal -0x1(%rbx), %eax
cmpl $0x1, %eax
ja 0x69206
movq %rcx, 0x38(%rsp)
movl %r15d, 0x10(%rsp)
movq %r12, %r15
cmpl $0x0, 0x1c(%r13)
je 0x6922d
movq 0x8(%rbp), %rdi
movq (%r13), %rsi
movslq 0x18(%r13), %r12
movq %r12, %rdx
callq 0x67e20
movq 0x8(%r13), %rbp
cmpl $0x2, %ebx
jne 0x692f7
movl 0x14(%r13), %ecx
movq %rax, %rdi
movq %rax, %rbx
movq %rbp, %rsi
movq %r12, %rdx
leaq 0x50(%rsp), %r8
callq 0x67ed6
testl %eax, %eax
je 0x6935f
movq 0x50(%rsp), %rbp
jmp 0x69362
movq %rcx, %rbx
andq $0x0, 0x40(%rsp)
testq %rbp, %rbp
je 0x6927a
movq %rbp, %rdi
leaq 0x40(%rsp), %rsi
leaq 0x50(%rsp), %rdx
callq 0x68235
movq 0x40(%rsp), %rcx
jmp 0x6927e
movq 0x8(%rbp), %rdi
movq (%r13), %rsi
movslq 0x18(%r13), %r12
movq %r12, %rdx
callq 0x67dea
movq 0x8(%r13), %rbp
cmpl $0x2, %ebx
jne 0x6932b
movl 0x14(%r13), %ecx
movq %rax, %rdi
movq %rax, %rbx
movq %rbp, %rsi
movq %r12, %rdx
leaq 0x50(%rsp), %r8
callq 0x67e46
testl %eax, %eax
je 0x693a0
movq 0x50(%rsp), %rbp
jmp 0x693a3
xorl %ecx, %ecx
xorl %eax, %eax
andq $0x0, 0x28(%rsp)
movb $0x0, 0x30(%rsp)
movq (%r13), %rdx
testq %rax, %rax
je 0x692bb
movq %rdx, %rsi
shrq $0x3, %rsi
addq %rsi, %rax
xorl %edi, %edi
cmpq $0x9, %rdi
je 0x692bb
leaq (%rsi,%rdi), %r8
cmpq %rcx, %r8
jae 0x692bb
movb (%rax,%rdi), %r8b
movb %r8b, 0x28(%rsp,%rdi)
incq %rdi
jmp 0x6929e
movq (%r13), %rsi
andq $-0x8, %rdx
subq %rdx, %rsi
cmpl $0x0, 0x1c(%r13)
movslq 0x18(%r13), %rdx
leaq 0x28(%rsp), %rdi
je 0x692dd
callq 0x67e20
jmp 0x692e2
callq 0x67dea
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x370a6
movq %rbx, %rcx
jmp 0x693fb
movq %rax, %rbx
movl 0x14(%r13), %ecx
movq %rbp, %rdi
xorl %esi, %esi
movq %r12, %rdx
leaq 0x50(%rsp), %r8
callq 0x67ed6
testl %eax, %eax
je 0x69319
movq 0x50(%rsp), %rbp
movq 0x8(%rsp), %rdi
movq %r15, %r12
movl 0x10(%rsp), %r15d
movq %rbx, %rsi
jmp 0x69372
movq %rax, %rbx
movl 0x14(%r13), %ecx
movq %rbp, %rdi
xorl %esi, %esi
movq %r12, %rdx
leaq 0x50(%rsp), %r8
callq 0x67e46
testl %eax, %eax
je 0x6934d
movq 0x50(%rsp), %rbp
movq 0x8(%rsp), %rdi
movq %r15, %r12
movl 0x10(%rsp), %r15d
movq %rbx, %rsi
jmp 0x693b3
addq %rbx, %rbp
movq 0x8(%rsp), %rdi
movq %r15, %r12
movq %rbp, %rsi
movl 0x10(%rsp), %r15d
testl %eax, %eax
je 0x6937d
cmpl $0x2, 0x14(%r13)
je 0x693be
callq 0x370a6
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%r13), %rsi
movslq 0x18(%r13), %rdx
movq %rbp, %rcx
movq %rax, %rbp
callq 0x67da7
jmp 0x693f3
addq %rbx, %rbp
movq 0x8(%rsp), %rdi
movq %r15, %r12
movq %rbp, %rsi
movl 0x10(%rsp), %r15d
testl %eax, %eax
je 0x693d0
cmpl $0x2, 0x14(%r13)
jne 0x693d0
leaq 0x90f4b(%rip), %rax     # 0xfa310
movq 0x50(%rax), %rsi
callq 0x36987
jmp 0x693ee
callq 0x370a6
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%r13), %rsi
movslq 0x18(%r13), %rdx
movq %rbp, %rcx
callq 0x67da7
movq 0x20(%rsp), %rbp
movq 0x38(%rsp), %rcx
incl %r15d
incq %rcx
jmp 0x69184
testl %r15d, %r15d
je 0x6944d
movq 0x8(%rsp), %rbx
movq 0x10(%rbx), %rdi
movq 0x40(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x3b125
movq 0x10(%rbx), %rax
movq 0x40(%rbx), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
leaq 0x4503c(%rip), %rsi     # 0xae470
pushq $0x8
popq %rdi
callq 0x6fb58
movslq %r15d, %rax
leaq 0x90462(%rip), %rcx     # 0xf98a8
addq %rax, 0x720(%rcx)
movq %r14, %rdi
jmp 0x69480
leaq 0x90eb7(%rip), %rax     # 0xfa310
movq 0x80(%rax), %rsi
movq 0x8(%rsp), %rdi
callq 0x36987
jmp 0x6947b
leaq 0x539c3(%rip), %rsi     # 0xbce36
movq %r12, %rdi
callq 0x36b6f
movq 0x10(%rsp), %rdi
callq 0x328f9
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop