// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %rbx
pushq %rax
leaq 0x987a(%rip), %rax      # 0x164de
movzwl (%rax), %eax
incl %eax
movzwl %ax, %edi
callq 0xa6ec
movl %eax, %ebp
andb $0x7, %al
movl %ebp, %ebx
shrb $0x3, %bl
andb $0x7, %bl
movzbl %al, %edi
callq 0xc6a2
cmpb $0x40, %bpl
jae 0xccd7
leaq 0x983e(%rip), %rcx      # 0x164d0
movb (%rcx), %sil
movl %esi, %edi
andb $0x10, %dil
movb (%rax), %dl
movzbl %bl, %r8d
leaq 0x3650(%rip), %r9       # 0x102f8
movslq (%r9,%r8,4), %r8
addq %r9, %r8
jmpq *%r8
movl %edx, %esi
rolb %sil
movb %sil, (%rax)
movb (%rcx), %sil
andb $-0x11, %sil
shrb $0x3, %dl
andb $0x10, %dl
orb %sil, %dl
movb %dl, (%rcx)
cmpb $0x0, (%rax)
sete %al
jmp 0xcde2
shrb $0x6, %bpl
cmpb $0x3, %bpl
je 0xccf7
movzbl %bpl, %ecx
cmpl $0x2, %ecx
jne 0xcd04
movb $-0x2, %dl
movl %ebx, %ecx
rolb %cl, %dl
andb %dl, (%rax)
jmp 0xcdee
movb $0x1, %dl
movl %ebx, %ecx
shlb %cl, %dl
orb %dl, (%rax)
jmp 0xcdee
movzbl (%rax), %eax
movzbl %bl, %ecx
btl %ecx, %eax
setae %al
leaq 0x97b9(%rip), %rcx      # 0x164d0
movb (%rcx), %dl
andb $0x1f, %dl
shlb $0x7, %al
orb %dl, %al
orb $0x20, %al
jmp 0xcdec
andb $-0x11, %sil
shrb $0x3, %dl
andb $0x10, %dl
orb %sil, %dl
movb %dl, (%rcx)
movb (%rax), %dl
addb %dl, %dl
jmp 0xcddb
andb $-0x11, %sil
shrb $0x3, %dl
andb $0x10, %dl
orb %sil, %dl
movb %dl, (%rcx)
movb (%rax), %dl
addb %dl, %dl
shrb $0x4, %dil
jmp 0xcd70
andb $-0x11, %sil
shlb $0x4, %dl
andb $0x10, %dl
orb %sil, %dl
movb %dl, (%rcx)
movb (%rax), %dl
shrb %dl
shlb $0x3, %dil
orb %dl, %dil
movb %dil, (%rax)
jmp 0xcddd
andb $-0x11, %sil
shlb $0x4, %dl
andb $0x10, %dl
orb %sil, %dl
movb %dl, (%rcx)
movb (%rax), %dl
movl %edx, %esi
shrb %sil
movb %sil, (%rax)
cmpb $0x2, %dl
setb %al
jmp 0xcde0
movl %edx, %esi
shrb %sil
movb %sil, (%rax)
movb (%rcx), %sil
andb $-0x11, %sil
movl %edx, %edi
shlb $0x4, %dil
andb $0x10, %dil
orb %sil, %dil
movb %dil, (%rcx)
shlb $0x7, %dl
orb %dl, (%rax)
jmp 0xcddd
andb $-0x11, %sil
shlb $0x4, %dl
andb $0x10, %dl
orb %sil, %dl
movb %dl, (%rcx)
movb (%rax), %dl
movl %edx, %esi
andb $-0x80, %sil
shrb %dl
orb %sil, %dl
movb %dl, (%rax)
sete %al
movb (%rcx), %dl
andb $0x7f, %dl
shlb $0x7, %al
orb %dl, %al
andb $-0x61, %al
movb %al, (%rcx)
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %rbp
retq
movl %edx, %esi
rolb $0x4, %sil
movb %sil, (%rax)
testb %dl, %dl
sete %al
shlb $0x7, %al
jmp 0xcdea