// File: 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 %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movb %sil, %al
movq %rdi, -0x10(%rbp)
movb %al, -0x11(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movl $0xa, (%rax)
movb -0x11(%rbp), %al
andb $0x1f, %al
movb %al, -0x21(%rbp)
movb -0x11(%rbp), %al
andb $-0x20, %al
movb %al, -0x22(%rbp)
movzbl -0x21(%rbp), %eax
movq %rax, -0x30(%rbp)
subq $0x1e, %rax
ja 0x1bc8
movq -0x30(%rbp), %rax
leaq 0x5a6b(%rip), %rcx      # 0x7400
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movzbl -0x11(%rbp), %eax
cmpl $0x20, %eax
jne 0x19c0
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
movzbl -0x11(%rbp), %edx
callq 0x3bd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movzbl -0x11(%rbp), %eax
cmpl $0x0, %eax
je 0x19f0
movzbl -0x11(%rbp), %eax
cmpl $0x40, %eax
je 0x19f0
movzbl -0x11(%rbp), %eax
cmpl $0x60, %eax
je 0x19f0
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3cd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movl $0x0, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3d30
movl %eax, -0x4(%rbp)
jmp 0x1be4
movzbl -0x22(%rbp), %eax
cmpl $0x80, %eax
jl 0x1a31
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3cd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movl $0x0, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3de0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3de0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3de0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3cd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movzbl -0x11(%rbp), %eax
cmpl $0x6c, %eax
jne 0x1aaf
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3e80
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
movzbl -0x11(%rbp), %edx
callq 0x3bd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
movzbl -0x11(%rbp), %edx
callq 0x3bd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
movzbl -0x11(%rbp), %edx
callq 0x3bd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3f40
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x3fd0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x4090
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x4090
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x4090
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x4130
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x41f0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x41f0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movzbl -0x11(%rbp), %eax
cmpl $0xbe, %eax
jne 0x1bb6
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x4130
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x41f0
movl %eax, -0x4(%rbp)
jmp 0x1be4
movq -0x38(%rbp), %rax
movzwl 0x10024(%rax), %ecx
addl $0x1, %ecx
movw %cx, 0x10024(%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax)