// File: /workspace/github_cpp_makefile_star2_O2/rockytriton[P]dreamsys_emu_gb/src/op_handler.cpp
// Function: dsemu::cpu::handleLD(dsemu::cpu::OpCode const&)
int handleLD(const OpCode &op) {
    RegParamType srcType = RegParamType::RPTHi;
    RegParamType dstType;

    Register *src;
    Register *dst;

    ushort srcValue = 0;
    ushort dstValue = 0;

    PTM::iterator dit = paramTypeMap.find(op.params[0]);
    PTM::iterator sit = paramTypeMap.find(op.params[1]);

    if (sit == paramTypeMap.end()) {
        if (op.params[1] == N) {
            srcValue = bus::read(regPC + 1);
        } else if (op.params[1] == NN) {
            srcValue = bus::read(regPC + 1);
            srcValue |= bus::read(regPC + 2) << 8;

            if (srcValue == 0x1200 || srcValue == 0x0012) {
                cout << "LDing ... " << Short(srcValue) << endl;
                //cpuSpeed = 500;
            }

        } else {
            cout << "Unknown LD Source Type " << endl;
            exit(-1);
        }
    } else {
        src = sit->second.first;
        srcType = sit->second.second;

        switch(srcType) {
            case RPT16: {
                ushort *p = (ushort *)src;
                srcValue = *p;
            } break;
            case RPTHi: {
                srcValue = src->hi;
            } break;
            case RPTLo: {
                srcValue = src->lo;
            } break;
        }
    }

    if (dit == paramTypeMap.end()) {
        dst = nullptr;
        dstType = RegParamType::RPT16;

        if (op.params[0] == N) {
            //
            //exit(-1);
            dstValue = bus::read(regPC + 1);
        } else if (op.params[0] == NN){
            //
            //exit(-1);
            dstValue = bus::read(regPC + 1);
            dstValue |= bus::read(regPC + 2) << 8;
            
        } else {
            cout << "Unknown LD Dest Type " << endl;
            exit(-1);
        }
    } else {
        dst = dit->second.first;
        dstType = dit->second.second;

        switch(dstType) {
            case RPT16: {
                ushort *p = (ushort *)dst;
                dstValue = *p;
            } break;
            case RPTHi: {
                dstValue = dst->hi;
            } break;
            case RPTLo: {
                dstValue = dst->lo;
            } break;
        }
    }

    switch(op.mode) {
        case ATypeRA: {

            ushort addr = getAddrValue(op.params[0], dstValue);

            if (srcType == RPT16) {
                bus::write(addr, srcValue);
            } else {
                bus::write(addr, (byte)srcValue);
            }
        }
            break;
        case ATypeAR: {
            ushort addr = getAddrValue(op.params[1], srcValue);

            if (dstType == RPTLo) {
                dst->lo = bus::read(addr); ;
            } else if (dstType == RPTHi) {
                dst->hi = bus::read(addr); ;
            } else {
                *((ushort *)dst) = bus::read(addr); ;
            }
            
            break;
        } break;
        case ATypeRR:
        case ATypeIR:
            {
                if (dstType == RPTLo) {
                    dst->lo = srcValue;
                } else if (dstType == RPTHi) {
                    dst->hi = srcValue;
                } else {
                    *((ushort *)dst) = srcValue;
                }
            } break;

        case ATypeSP:
        {
            if (op.params[0] == HL) {
                char i = (char)bus::read(regPC + 1);
                setReg16Value(regHL, getReg16Value(regSP) + i);

                setFlag(FlagN, 0);
                setFlag(FlagZ, 0);
                setFlag(FlagC, ((getReg16Value(regSP)+i)&0xFF) < (getReg16Value(regSP)&0xFF));
                setFlag(FlagH, ((getReg16Value(regSP)+i)&0xF) < (getReg16Value(regSP)&0xF));
                
            } else {
                setReg16Value(regSP, getReg16Value(regHL));
            }
        } break;

        default:
            cout << "INVALID OP FLAG: " << dstValue << endl;
            exit(-1);
            return 0;
            
    }
    return 0;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %r15
leaq 0x1c(%rdi), %rbx
leaq 0x29d0f(%rip), %r13     # 0x365c8
movq %r13, %rdi
movq %rbx, %rsi
callq 0xe8d2
movq %rax, %r12
leaq 0x20(%r15), %r14
movq %r13, %rdi
movq %r14, %rsi
callq 0xe8d2
leaq 0x29cf3(%rip), %r13     # 0x365d0
pushq $0x1
popq %rdx
cmpq %r13, %rax
movq %r14, 0x10(%rsp)
je 0xc91b
movq 0x28(%rax), %rcx
movl 0x30(%rax), %eax
cmpl $0x2, %eax
je 0xc9ca
cmpl $0x1, %eax
je 0xc9c0
testl %eax, %eax
jne 0xc9d3
movzwl (%rcx), %ebp
movl $0x0, 0xc(%rsp)
jmp 0xc9d9
movl (%r14), %eax
cmpl $0xd, %eax
movl %edx, 0xc(%rsp)
je 0xc94c
cmpl $0xc, %eax
jne 0xcc24
leaq 0x9ba7(%rip), %rax      # 0x164de
movzwl (%rax), %eax
incl %eax
movzwl %ax, %edi
callq 0xa6ec
movzbl %al, %ebp
jmp 0xc9d9
leaq 0x9b8b(%rip), %r14      # 0x164de
movzwl (%r14), %edi
incl %edi
movl $0xffff, %eax           # imm = 0xFFFF
andl %eax, %edi
callq 0xa6ec
movl %eax, %ebp
movzwl (%r14), %edi
movl $0xffff, %r14d          # imm = 0xFFFF
addl $0x2, %edi
andl %r14d, %edi
callq 0xa6ec
movzbl %al, %eax
shll $0x8, %eax
movzbl %bpl, %ebp
orl %eax, %ebp
cmpw $0x1200, %bp            # imm = 0x1200
je 0xc999
movl %ebp, %eax
andl %r14d, %eax
cmpl $0x12, %eax
jne 0xc9d9
movq 0x9630(%rip), %rdi      # 0x15fd0
leaq 0x3a45(%rip), %rsi      # 0x103ec
callq 0x3260
movq %rax, %rdi
movl %ebp, %esi
callq 0xb2b0
movq %rax, %rdi
callq 0x3130
jmp 0xc9d9
movl %edx, 0xc(%rsp)
movzbl 0x1(%rcx), %ebp
jmp 0xc9d9
movl %edx, 0xc(%rsp)
movzbl (%rcx), %ebp
jmp 0xc9d9
xorl %ebp, %ebp
movl %eax, 0xc(%rsp)
cmpq %r13, %r12
je 0xca08
movq 0x28(%r12), %r13
movl 0x30(%r12), %r14d
cmpl $0x2, %r14d
je 0xca7d
cmpl $0x1, %r14d
je 0xca74
testl %r14d, %r14d
jne 0xca88
movzwl (%r13), %r12d
jmp 0xca6f
movl (%rbx), %eax
cmpl $0xd, %eax
je 0xca32
cmpl $0xc, %eax
jne 0xcc34
leaq 0x9abf(%rip), %rax      # 0x164de
movzwl (%rax), %eax
incl %eax
movzwl %ax, %edi
callq 0xa6ec
movzbl %al, %r12d
jmp 0xca6c
leaq 0x9aa5(%rip), %r14      # 0x164de
movzwl (%r14), %edi
incl %edi
movl $0xffff, %r13d          # imm = 0xFFFF
andl %r13d, %edi
callq 0xa6ec
movl %eax, %r12d
movzwl (%r14), %edi
addl $0x2, %edi
andl %r13d, %edi
callq 0xa6ec
movzbl %al, %eax
shll $0x8, %eax
movzbl %r12b, %r12d
orl %eax, %r12d
xorl %r13d, %r13d
xorl %r14d, %r14d
jmp 0xca8b
movzbl 0x1(%r13), %r12d
pushq $0x1
jmp 0xca84
movzbl (%r13), %r12d
pushq $0x2
popq %r14
jmp 0xca8b
xorl %r12d, %r12d
movl 0x18(%r15), %eax
leal -0x1(%rax), %ecx
cmpl $0x2, %ecx
jb 0xcad5
cmpl $0x3, %eax
je 0xcaf2
cmpl $0xd, %eax
je 0xcb26
cmpl $0x5, %eax
jne 0xcc03
movl (%rbx), %edi
movswl %r12w, %esi
callq 0xc831
cmpl $0x0, 0xc(%rsp)
je 0xcbd7
movzbl %bpl, %esi
movzwl %ax, %edi
callq 0xa76c
jmp 0xcbf2
cmpl $0x1, %r14d
je 0xcbb4
cmpl $0x2, %r14d
jne 0xcbba
movb %bpl, (%r13)
jmp 0xcbf2
movq 0x10(%rsp), %rax
movl (%rax), %edi
movswl %bp, %esi
callq 0xc831
movzwl %ax, %edi
callq 0xa6ec
cmpl $0x1, %r14d
je 0xcbe4
cmpl $0x2, %r14d
jne 0xcbea
movb %al, (%r13)
jmp 0xcbf2
cmpl $0x9, (%rbx)
jne 0xcbc1
leaq 0x99a8(%rip), %rax      # 0x164de
movzwl (%rax), %eax
incl %eax
movzwl %ax, %edi
callq 0xa6ec
leaq 0x9992(%rip), %rcx      # 0x164dc
movzwl (%rcx), %ecx
movzbl %al, %eax
movsbl %al, %esi
addl %ecx, %esi
leaq 0x9974(%rip), %rdx      # 0x164d0
movb (%rdx), %dil
andb $0x2f, %dil
addl %ecx, %eax
movl $0xff, %r8d
movl %eax, %r9d
andl %r8d, %r9d
andl %ecx, %r8d
cmpl %r8d, %r9d
leaq 0x9958(%rip), %r8       # 0x164d6
leal 0x10(%rdi), %r9d
movzbl %dil, %edi
movzbl %r9b, %r9d
cmovael %edi, %r9d
movw %si, (%r8)
andl $0xf, %eax
andl $0xf, %ecx
movl %r9d, %esi
andb $0x1f, %sil
orb $0x20, %r9b
cmpl %ecx, %eax
movzbl %r9b, %eax
movzbl %sil, %ecx
cmovbl %eax, %ecx
movb %cl, (%rdx)
jmp 0xcbf2
movb %bpl, 0x1(%r13)
jmp 0xcbf2
movw %bp, (%r13)
jmp 0xcbf2
leaq 0x990e(%rip), %rax      # 0x164d6
movzwl (%rax), %eax
leaq 0x990a(%rip), %rcx      # 0x164dc
movw %ax, (%rcx)
jmp 0xcbf2
movzwl %ax, %edi
movzwl %bp, %esi
callq 0xa748
jmp 0xcbf2
movb %al, 0x1(%r13)
jmp 0xcbf2
movzbl %al, %eax
movw %ax, (%r13)
xorl %eax, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x93c6(%rip), %rdi      # 0x15fd0
leaq 0x3814(%rip), %rsi      # 0x10425
callq 0x3260
movzwl %r12w, %esi
movq %rax, %rdi
callq 0x33c0
jmp 0xcc47
movq 0x93a5(%rip), %rdi      # 0x15fd0
leaq 0x37c5(%rip), %rsi      # 0x103f7
jmp 0xcc42
movq 0x9395(%rip), %rdi      # 0x15fd0
leaq 0x37cd(%rip), %rsi      # 0x1040f
callq 0x3260
movq %rax, %rdi
callq 0x3130
pushq $-0x1
popq %rdi
callq 0x32d0