// File: rockytriton[P]dreamsys_emu_gb/src/op_handler.cpp
// Function: dsemu::cpu::handleCB(dsemu::cpu::OpCode const&)
int handleCB(const OpCode &op) {
    int code = bus::read(regPC + 1);
    byte reg = code & 7;
    byte bitOp = (code >> 6) & 3;
    byte bit = (code >> 3) & 7;
    byte *pReg = regFromBits(reg);

    if (bitOp) {
        switch(bitOp) {
            case 1:
                setFlag(FlagZ, !((*pReg) & (1 << bit)));
                setFlag(FlagN, false);
                setFlag(FlagH, true);
                break;
            case 2:
                (*pReg) &= ~(1 << bit);
                break;
            case 3:
                (*pReg) |= (1 << bit);
                break;
            default:
                cout << "INVALID BIT " << endl;
                exit(-1);
        }

        return 0;
    }

    bitOp = bit;
    int cBit = getFlag(FlagC);

    //cout << "BIT OP: " << Byte(bitOp) << endl;

    switch (bitOp) {
        case 0: //RLC
            //(*pReg) <<= (1 + getFlag(FlagC));
            {
                byte old = !!((*pReg) & 0x80);
                (*pReg) <<= 1;
                (*pReg) |= old;
                setFlag(FlagC, old);
                setFlag(FlagZ, !(*pReg));
            }
            break;
        case 1: //RRC
            //(*pReg) >>= (1 + getFlag(FlagC));
            {
                byte old = !!((*pReg) & 1);
                (*pReg) >>= 1;
                setFlag(FlagC, old);
                (*pReg) |= (old << 7);
                setFlag(FlagZ, !(*pReg));
            }
            break;
        case 2: //RL
            setFlag(FlagC, !!((*pReg) & 0x80));
            (*pReg) <<= 1;
            (*pReg) |= cBit;
            setFlag(FlagZ, !(*pReg));
            break;
        case 3: //RR
           // (*pReg) >>= 1;
            setFlag(FlagC, (*pReg) & 1);
            (*pReg) >>= 1;
            (*pReg) |= (cBit << 7);
            setFlag(FlagZ, !(*pReg));
            break;
        case 4: //SLA
            setFlag(FlagC, !!((*pReg) & 0x80));
            (*pReg) <<= 1;
            setFlag(FlagZ, !(*pReg));
            //(*pReg) |= cBit;
            break;
        case 5: //SRA 
            {
            setFlag(FlagC, (*pReg) & 1);
            byte old = (*pReg) & 0x80;
            (*pReg) >>= 1;
            (*pReg) |= old;
            setFlag(FlagZ, !(*pReg));
        }break;
        case 7: //SRL
            setFlag(FlagC, (*pReg) & 1);
            //cout << "SLR " << Byte(*pReg);
            (*pReg) >>= 1;
            setFlag(FlagZ, !(*pReg));
            //cout << " = " << Byte(*pReg) << endl;
            break;
        case 6: //SWAP
            //setFlag(FlagC, 0);
            (*pReg) = (((*pReg) & 0xF0) >> 4) | (((*pReg) & 0xF) << 4);
            regAF.lo = (!(*pReg)) << 7;
            break;
        default:
            cout << "INVALID BIT2 " << endl;
            exit(-1);
    }

    setFlag(FlagH, 0);
    setFlag(FlagN, 0);
    return 0;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
leaq 0x148db(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x1, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %eax
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0x7, %eax
movb %al, -0x15(%rbp)
movl -0x14(%rbp), %eax
sarl $0x6, %eax
andl $0x3, %eax
movb %al, -0x16(%rbp)
movl -0x14(%rbp), %eax
sarl $0x3, %eax
andl $0x7, %eax
movb %al, -0x17(%rbp)
movzbl -0x15(%rbp), %edi
callq 0x1a2a0
movq %rax, -0x20(%rbp)
cmpb $0x0, -0x16(%rbp)
je 0x1ade7
movzbl -0x16(%rbp), %eax
movl %eax, -0x2c(%rbp)
subl $0x1, %eax
je 0x1ad31
jmp 0x1ad1d
movl -0x2c(%rbp), %eax
subl $0x2, %eax
je 0x1ad7c
jmp 0x1ad27
movl -0x2c(%rbp), %eax
subl $0x3, %eax
je 0x1ad97
jmp 0x1adaf
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
movzbl -0x17(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
movl $0x6, %edi
xorl %esi, %esi
callq 0x1da80
movl $0x5, %edi
movl $0x1, %esi
callq 0x1da80
jmp 0x1addb
movzbl -0x17(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
xorl $-0x1, %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
andl %edx, %ecx
movb %cl, (%rax)
jmp 0x1addb
movzbl -0x17(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
jmp 0x1addb
movq 0x1421a(%rip), %rdi     # 0x2efd0
leaq 0x96b6(%rip), %rsi      # 0x24473
callq 0x32c0
movq %rax, %rdi
movq 0x141e4(%rip), %rsi     # 0x2efb0
callq 0x3310
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3390
movl $0x0, -0x4(%rbp)
jmp 0x1b152
movb -0x17(%rbp), %al
movb %al, -0x16(%rbp)
movl $0x4, %edi
callq 0x1dac0
movzbl %al, %eax
movl %eax, -0x24(%rbp)
movzbl -0x16(%rbp), %eax
movq %rax, -0x38(%rbp)
subq $0x7, %rax
ja 0x1b107
movq -0x38(%rbp), %rax
leaq 0x950e(%rip), %rcx      # 0x24328
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x25(%rbp)
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
shll %ecx
movb %cl, (%rax)
movzbl -0x25(%rbp), %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
cmpb $0x0, -0x25(%rbp)
setne %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x26(%rbp)
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
sarl %ecx
movb %cl, (%rax)
cmpb $0x0, -0x26(%rbp)
setne %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movzbl -0x26(%rbp), %edx
shll $0x7, %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
shll %ecx
movb %cl, (%rax)
movl -0x24(%rbp), %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
sarl %ecx
movb %cl, (%rax)
movl -0x24(%rbp), %edx
shll $0x7, %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
shll %ecx
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x80, %eax
movb %al, -0x27(%rbp)
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
sarl %ecx
movb %cl, (%rax)
movzbl -0x27(%rbp), %edx
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
orl %edx, %ecx
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
movq -0x20(%rbp), %rax
movzbl (%rax), %ecx
sarl %ecx
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x7, %edi
callq 0x1da80
jmp 0x1b133
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
andl $0xf0, %eax
sarl $0x4, %eax
movq -0x20(%rbp), %rcx
movzbl (%rcx), %ecx
andl $0xf, %ecx
shll $0x4, %ecx
orl %ecx, %eax
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, (%rax)
movq -0x20(%rbp), %rax
cmpb $0x0, (%rax)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
shll $0x7, %eax
movb %al, %cl
leaq 0x1448d(%rip), %rax     # 0x2f590
movb %cl, (%rax)
jmp 0x1b133
movq 0x13ec2(%rip), %rdi     # 0x2efd0
leaq 0x936b(%rip), %rsi      # 0x24480
callq 0x32c0
movq %rax, %rdi
movq 0x13e8c(%rip), %rsi     # 0x2efb0
callq 0x3310
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3390
movl $0x5, %edi
xorl %esi, %esi
callq 0x1da80
movl $0x6, %edi
xorl %esi, %esi
callq 0x1da80
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)