// File: /workspace/github_cpp_makefile_star2_O1/NGageMegaman[P]NEScutre/src/cpu.cpp
// Function: Cpu::read_operand(unsigned char, addr_mode_t*)
uint32_t Cpu::read_operand(uint8_t opcode, addr_mode_t *addr_mode) {
    *addr_mode = IMPLIED;
    //obtenemos la columna de la matriz de opcodes
    uint8_t column = opcode & 0x1f;
    uint8_t row = opcode & 0xe0;
    switch (column) {
	case 0x00:
	    if (opcode == JSR) {
		    return read_operand_absolute(addr_mode, opcode);
        }
	    else if (opcode != BRK && opcode != RTI && opcode != RTS) {
		    return read_operand_imm(addr_mode);
        }
        else { 
            return 0;
        }
	    break;
	case 0x01:
	    return read_operand_indexed_indirect(addr_mode);
	    break;
	case 0x02:
	    if (row >= 0x80)
		return read_operand_imm(addr_mode);
	    else
		return 0;
	    break;
	case 0x04:
	    return read_operand_zero_page(addr_mode);
	    break;
	case 0x05:
	    return read_operand_zero_page(addr_mode);
	    break;
	case 0x06:
	    return read_operand_zero_page(addr_mode);
	    break;
	case 0x09:
	    return read_operand_imm(addr_mode);
	    break;
	case 0x0c:
	    if (opcode == JMP2) 
		    return read_operand_indirect(addr_mode);
	    else 
            return read_operand_absolute(addr_mode, opcode);
	    break;
	case 0x0d:
	    return read_operand_absolute(addr_mode, opcode);
	    break;
	case 0x0e:
	    return read_operand_absolute(addr_mode, opcode);
	    break;
	case 0x10:
	    return read_operand_relative(addr_mode);
	    break;
	case 0x11:
	    return read_operand_indirect_indexed(addr_mode);
	    break;
	case 0x14:
	    return read_operand_zero_page_indexed_x(addr_mode);
	    break;
	case 0x15:
	    return read_operand_zero_page_indexed_x(addr_mode);
	    break;
	case 0x16:
	    return read_operand_zero_page_indexed_x(addr_mode);
	    break;
	case 0x19:
	    return read_operand_absolute_indexed_y(addr_mode);
	    break;
	case 0x1c:
	    return read_operand_absolute_indexed_x(addr_mode);
	    break;
	case 0x1d:
	    return read_operand_absolute_indexed_x(addr_mode);
	    break;
	case 0x1e:
	    if (opcode == LDX5) 
		    return read_operand_absolute_indexed_y(addr_mode);
	    else 
		    return read_operand_absolute_indexed_x(addr_mode);
	    break;
	default:
	    regPC = regPC + 1; //No operand
	    return 0;
    }
}

// Assembly:
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %r14
movl $0xa, (%rdx)
movl %esi, %eax
andb $0x1f, %al
cmpb $0x1e, %al
ja 0x2b8d
movq %rdx, %rbx
movl %esi, %eax
andl $0x1f, %eax
leaq 0x39a6(%rip), %rcx      # 0x6400
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x39e8
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x3b6c
cmpb $-0x42, %sil
jne 0x2a9f
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x3bc6
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x3c4c
leaq 0x8(%r14), %rdi
movl 0x10024(%r14), %eax
incl %eax
movzwl %ax, %esi
callq 0x42ba
movl 0x10024(%r14), %ecx
leal 0x2(%rcx), %edx
movw %dx, 0x10024(%r14)
movsbl %al, %eax
addl %ecx, %eax
addl $0x2, %eax
movl $0x8, (%rbx)
shll $0x10, %eax
jmp 0x2b97
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x397e
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x3afa
xorl %eax, %eax
testb %sil, %sil
jns 0x2b97
jmp 0x2b36
movl %esi, %eax
rolb $0x3, %al
movzbl %al, %ecx
xorl %eax, %eax
leal -0x2(%rcx), %edx
cmpl $0x2, %edx
jb 0x2b97
testl %ecx, %ecx
je 0x2b97
cmpl $0x1, %ecx
je 0x2b77
leaq 0x8(%r14), %rdi
movl 0x10024(%r14), %eax
incl %eax
movzwl %ax, %esi
callq 0x42ba
addw $0x2, 0x10024(%r14)
movl $0x0, (%rbx)
movzbl %al, %eax
jmp 0x2b97
cmpb $0x6c, %sil
jne 0x2b77
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x3a3c
movzbl %sil, %edx
movq %r14, %rdi
movq %rbx, %rsi
addq $0x8, %rsp
popq %rbx
popq %r14
jmp 0x388e
incw 0x10024(%r14)
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
retq
nop