// File: 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
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x8(%rbp)
movl $0x1, -0xc(%rbp)
movw $0x0, -0x22(%rbp)
movw $0x0, -0x24(%rbp)
movq -0x8(%rbp), %rsi
addq $0x1c, %rsi
leaq 0x34f87(%rip), %rdi     # 0x4f688
callq 0x1d9d0
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rsi
addq $0x1c, %rsi
addq $0x4, %rsi
leaq 0x34f6b(%rip), %rdi     # 0x4f688
callq 0x1d9d0
movq %rax, -0x38(%rbp)
leaq 0x34f5b(%rip), %rdi     # 0x4f688
callq 0x1da30
movq %rax, -0x40(%rbp)
leaq -0x38(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x1da00
testb $0x1, %al
jne 0x1a74c
jmp 0x1a84c
movq -0x8(%rbp), %rax
cmpl $0xc, 0x20(%rax)
jne 0x1a777
leaq 0x14e41(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x1, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %eax
movw %ax, -0x22(%rbp)
jmp 0x1a84a
movq -0x8(%rbp), %rax
cmpl $0xd, 0x20(%rax)
jne 0x1a81c
leaq 0x14e12(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x1, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %eax
movw %ax, -0x22(%rbp)
leaq 0x14df6(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x2, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %ecx
shll $0x8, %ecx
movzwl -0x22(%rbp), %eax
orl %ecx, %eax
movw %ax, -0x22(%rbp)
movzwl -0x22(%rbp), %eax
cmpl $0x1200, %eax           # imm = 0x1200
je 0x1a7da
movzwl -0x22(%rbp), %eax
cmpl $0x12, %eax
jne 0x1a81a
movq 0x147ef(%rip), %rdi     # 0x2efd0
leaq 0x9c40(%rip), %rsi      # 0x24428
callq 0x32c0
movq %rax, -0x70(%rbp)
leaq -0x42(%rbp), %rdi
movzwl -0x22(%rbp), %esi
callq 0x13840
movq -0x70(%rbp), %rdi
movzwl -0x42(%rbp), %esi
callq 0x137b0
movq %rax, %rdi
movq 0x1479b(%rip), %rsi     # 0x2efb0
callq 0x3310
jmp 0x1a848
movq 0x147ad(%rip), %rdi     # 0x2efd0
leaq 0x9c09(%rip), %rsi      # 0x24433
callq 0x32c0
movq %rax, %rdi
movq 0x14777(%rip), %rsi     # 0x2efb0
callq 0x3310
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3390
jmp 0x1a84a
jmp 0x1a8c0
leaq -0x38(%rbp), %rdi
movq %rdi, -0x80(%rbp)
callq 0x1da60
movq -0x80(%rbp), %rdi
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
callq 0x1da60
movl 0x10(%rax), %eax
movl %eax, -0xc(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x74(%rbp)
testl %eax, %eax
je 0x1a890
jmp 0x1a87c
movl -0x74(%rbp), %eax
subl $0x1, %eax
je 0x1a8a5
jmp 0x1a886
movl -0x74(%rbp), %eax
subl $0x2, %eax
je 0x1a8b3
jmp 0x1a8be
movq -0x18(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movw (%rax), %ax
movw %ax, -0x22(%rbp)
jmp 0x1a8be
movq -0x18(%rbp), %rax
movzbl 0x1(%rax), %eax
movw %ax, -0x22(%rbp)
jmp 0x1a8be
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
movw %ax, -0x22(%rbp)
jmp 0x1a8c0
leaq 0x34dc1(%rip), %rdi     # 0x4f688
callq 0x1da30
movq %rax, -0x58(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x1da00
testb $0x1, %al
jne 0x1a8e6
jmp 0x1a99d
movq $0x0, -0x20(%rbp)
movl $0x0, -0x10(%rbp)
movq -0x8(%rbp), %rax
cmpl $0xc, 0x1c(%rax)
jne 0x1a91d
leaq 0x14c98(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x1, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %eax
movw %ax, -0x24(%rbp)
jmp 0x1a998
movq -0x8(%rbp), %rax
cmpl $0xd, 0x1c(%rax)
jne 0x1a96a
leaq 0x14c70(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x1, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %eax
movw %ax, -0x24(%rbp)
leaq 0x14c54(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x2, %eax
movzwl %ax, %edi
callq 0x13450
movzbl %al, %ecx
shll $0x8, %ecx
movzwl -0x24(%rbp), %eax
orl %ecx, %eax
movw %ax, -0x24(%rbp)
jmp 0x1a996
movq 0x1465f(%rip), %rdi     # 0x2efd0
leaq 0x9ad3(%rip), %rsi      # 0x2444b
callq 0x32c0
movq %rax, %rdi
movq 0x14629(%rip), %rsi     # 0x2efb0
callq 0x3310
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3390
jmp 0x1a998
jmp 0x1aa20
leaq -0x30(%rbp), %rdi
movq %rdi, -0x90(%rbp)
callq 0x1da60
movq -0x90(%rbp), %rdi
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
callq 0x1da60
movl 0x10(%rax), %eax
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0x84(%rbp)
testl %eax, %eax
je 0x1a9f0
jmp 0x1a9d6
movl -0x84(%rbp), %eax
subl $0x1, %eax
je 0x1aa05
jmp 0x1a9e3
movl -0x84(%rbp), %eax
subl $0x2, %eax
je 0x1aa13
jmp 0x1aa1e
movq -0x20(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movw (%rax), %ax
movw %ax, -0x24(%rbp)
jmp 0x1aa1e
movq -0x20(%rbp), %rax
movzbl 0x1(%rax), %eax
movw %ax, -0x24(%rbp)
jmp 0x1aa1e
movq -0x20(%rbp), %rax
movzbl (%rax), %eax
movw %ax, -0x24(%rbp)
jmp 0x1aa20
movq -0x8(%rbp), %rax
movl 0x18(%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x98(%rbp)
subl $0xc, %eax
ja 0x1ac57
movq -0x98(%rbp), %rax
leaq 0x98ab(%rip), %rcx      # 0x242f4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rax
movl 0x1c(%rax), %edi
movswl -0x24(%rbp), %esi
callq 0x1a600
movw %ax, -0x62(%rbp)
cmpl $0x0, -0xc(%rbp)
jne 0x1aa7e
movw -0x62(%rbp), %ax
movzwl %ax, %edi
movzwl -0x22(%rbp), %esi
callq 0x13530
jmp 0x1aa91
movw -0x62(%rbp), %cx
movw -0x22(%rbp), %ax
movzwl %cx, %edi
movzbl %al, %esi
callq 0x13590
jmp 0x1ac8f
movq -0x8(%rbp), %rax
movl 0x20(%rax), %edi
movswl -0x22(%rbp), %esi
callq 0x1a600
movw %ax, -0x64(%rbp)
cmpl $0x2, -0x10(%rbp)
jne 0x1aac3
movzwl -0x64(%rbp), %edi
callq 0x13450
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, (%rax)
jmp 0x1aaf5
cmpl $0x1, -0x10(%rbp)
jne 0x1aadd
movzwl -0x64(%rbp), %edi
callq 0x13450
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, 0x1(%rax)
jmp 0x1aaf3
movzwl -0x64(%rbp), %edi
callq 0x13450
movzbl %al, %eax
movw %ax, %cx
movq -0x20(%rbp), %rax
movw %cx, (%rax)
jmp 0x1aaf5
jmp 0x1ac8f
cmpl $0x2, -0x10(%rbp)
jne 0x1ab0e
movw -0x22(%rbp), %ax
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, (%rax)
jmp 0x1ab30
cmpl $0x1, -0x10(%rbp)
jne 0x1ab23
movw -0x22(%rbp), %ax
movb %al, %cl
movq -0x20(%rbp), %rax
movb %cl, 0x1(%rax)
jmp 0x1ab2e
movw -0x22(%rbp), %cx
movq -0x20(%rbp), %rax
movw %cx, (%rax)
jmp 0x1ab30
jmp 0x1ac8f
movq -0x8(%rbp), %rax
cmpl $0x9, 0x1c(%rax)
jne 0x1ac3a
leaq 0x14a54(%rip), %rax     # 0x2f59e
movzwl (%rax), %eax
addl $0x1, %eax
movzwl %ax, %edi
callq 0x13450
movb %al, -0x65(%rbp)
leaq 0x14a3a(%rip), %rdi     # 0x2f59c
callq 0x15070
movzwl %ax, %eax
movsbl -0x65(%rbp), %ecx
addl %ecx, %eax
leaq 0x14a1f(%rip), %rdi     # 0x2f596
movzwl %ax, %esi
callq 0x15030
movl $0x6, %edi
xorl %esi, %esi
callq 0x1da80
movl $0x7, %edi
xorl %esi, %esi
callq 0x1da80
leaq 0x149fe(%rip), %rdi     # 0x2f59c
callq 0x15070
movzwl %ax, %eax
movsbl -0x65(%rbp), %ecx
addl %ecx, %eax
andl $0xff, %eax
movl %eax, -0xa0(%rbp)
leaq 0x149de(%rip), %rdi     # 0x2f59c
callq 0x15070
movw %ax, %cx
movl -0xa0(%rbp), %eax
movzwl %cx, %ecx
andl $0xff, %ecx
cmpl %ecx, %eax
setl %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x4, %edi
callq 0x1da80
leaq 0x149ab(%rip), %rdi     # 0x2f59c
callq 0x15070
movzwl %ax, %eax
movsbl -0x65(%rbp), %ecx
addl %ecx, %eax
andl $0xf, %eax
movl %eax, -0x9c(%rbp)
leaq 0x1498d(%rip), %rdi     # 0x2f59c
callq 0x15070
movw %ax, %cx
movl -0x9c(%rbp), %eax
movzwl %cx, %ecx
andl $0xf, %ecx
cmpl %ecx, %eax
setl %al
movzbl %al, %esi
andl $0x1, %esi
movl $0x5, %edi
callq 0x1da80
jmp 0x1ac55
leaq 0x14955(%rip), %rdi     # 0x2f596
callq 0x15070
leaq 0x1494f(%rip), %rdi     # 0x2f59c
movzwl %ax, %esi
callq 0x15030
jmp 0x1ac8f
movq 0x14372(%rip), %rdi     # 0x2efd0
leaq 0x97fc(%rip), %rsi      # 0x24461
callq 0x32c0
movq %rax, %rdi
movzwl -0x24(%rbp), %esi
callq 0x3470
movq %rax, %rdi
movq 0x14330(%rip), %rsi     # 0x2efb0
callq 0x3310
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x3390
xorl %eax, %eax
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)