// File: NGageMegaman[P]NEScutre/src/cpu.cpp
// Function: Cpu::execute()
void Cpu::execute() {
    addr_mode_t addr_mode;
    uint8_t opcode = mem.read_byte(regPC);
    uint32_t addrop = read_operand(opcode, &addr_mode);
    uint16_t address = addrop >> 16;
    uint8_t operand = addrop & 0xFF;

    switch (opcode) {
	case ADC1: case ADC2: case ADC3: case ADC4:
	case ADC5: case ADC6: case ADC7: case ADC8:
	    ADC_execute(operand);
	    break;
	case AND1: case AND2: case AND3: case AND4:
	case AND5: case AND6: case AND7: case AND8:
	    AND_execute(operand);
	    break;
	case ASL2:
	    ASL_A_execute();
	    break;
	case ASL1: case ASL3: case ASL4: case ASL5:
	    ASL_mem_execute(address, operand);
	    break;
	case BCC:
	    BCC_execute(address);
	    break;
	case BCS:
	    BCS_execute(address);
	    break;
	case BEQ:
	    BEQ_execute(address);
	    break;
	case BIT1: case BIT2:
	    BIT_execute(operand);
	    break;
	case BMI:
	    BMI_execute(address);
	    break;
	case BNE:
	    BNE_execute(address);
	    break;
	case BPL:
	    BPL_execute(address);
	    break;
	case BRK:
	    BRK_execute();
	    break;
	case BVC:
	    BVC_execute(address);
	    break;
	case BVS:
	    BVS_execute(address);
	    break;
	case CLC:
	    CLC_execute();
	    break;
	case CLD:
	    CLD_execute();
	    break;
	case CLI:
	    CLI_execute();
	    break;
	case CLV:
	    CLV_execute();
	    break;
	case CMP1: case CMP2: case CMP3: case CMP4:
	case CMP5: case CMP6: case CMP7: case CMP8:
	    CMP_execute(operand);
	    break;
	case CPX1: case CPX2: case CPX3:
	    CPX_execute(operand);
	    break;
	case CPY1: case CPY2: case CPY3:
	    CPY_execute(operand);
	    break;
	case DEC1: case DEC2: case DEC3: case DEC4:
	    DEC_execute(address, operand);
	    break;
	case DEX:
	    DEX_execute();
	    break;
	case DEY:
	    DEY_execute();
	    break;
	case EOR1: case EOR2: case EOR3: case EOR4: 
	case EOR5: case EOR6: case EOR7: case EOR8: 
	    EOR_execute(operand);
	    break;
	case INC1: case INC2: case INC3: case INC4:
	    INC_execute(address, operand);
	    break;
	case INX:
	    INX_execute();
	    break;
	case INY:
	    INY_execute();
	    break;
	case JMP1: case JMP2:
	    JMP_execute(address);
	    break;
	case JSR:
	    JSR_execute(address);
	    break;
	case LDA1: case LDA2: case LDA3: case LDA4:
	case LDA5: case LDA6: case LDA7: case LDA8:
	    LDA_execute(operand);
	    break;
	case LDX1: case LDX2: case LDX3: case LDX4: case LDX5:
	    LDX_execute(operand);
	    break;
	case LDY1: case LDY2: case LDY3: case LDY4: case LDY5:
	    LDY_execute(operand);
	    break;
	case LSR1: case LSR3: case LSR4: case LSR5:
	    LSR_mem_execute(address, operand);
	    break;
	case LSR2:
	    LSR_A_execute();
	    break;
	case ORA1: case ORA2: case ORA3: case ORA4:
	case ORA5: case ORA6: case ORA7: case ORA8:
	    ORA_execute(operand);
	    break;
	case PHA:
	    PHA_execute();
	    break;
	case PHP:
	    PHP_execute();
	    break;
	case PLA:
	    PLA_execute();
	    break;
	case PLP:
	    PLP_execute();
	case ROL1: case ROL3: case ROL4: case ROL5:
	    ROL_mem_execute(address, operand);
	    break;
	case ROL2:
	    ROL_A_execute();
	    break;
	case ROR1: case ROR3: case ROR4: case ROR5:
	    ROR_mem_execute(address, operand);
	    break;
	case ROR2:
	    ROR_A_execute();
	    break;
	case RTI:
	    RTI_execute();
	    break;
	case RTS:
	    RTS_execute();
	    break;
	case SBC1: case SBC2: case SBC3: case SBC4:
	case SBC5: case SBC6: case SBC7: case SBC8:
	    SBC_execute(operand);
	    break;
	case SEC:
	    SEC_execute();
	    break;
	case SED:
	    SED_execute();
	    break;
	case SEI:
	    SEI_execute();
	    break;
	case STA1: case STA2: case STA3:
	case STA4: case STA5: case STA6: case STA7:
	    STA_execute(address);
	    break;
	case STX1: case STX2: case STX3:
	    STX_execute(address);
	    break;
	case STY1: case STY2: case STY3:
	    STY_execute(address);
	    break;
	case TAX:
	    TAX_execute();
	    break;
	case TAY:
	    TAY_execute();
	    break;
	case TSX:
	    TSX_execute();
	    break;
	case TXA:
	    TXA_execute();
	    break;
	case TXS:
	    TXS_execute();
	    break;
	case TYA:
	    TYA_execute();
	    break;
	default : 
	    NOP_execute();
    }
    add_clock_cycles(opcode, address, addr_mode);
    //debug_dump(opcode);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
movq %rax, %rdi
addq $0x8, %rdi
movzwl 0x10024(%rax), %esi
callq 0x4a20
movq -0x28(%rbp), %rdi
movb %al, -0xd(%rbp)
movzbl -0xd(%rbp), %esi
leaq -0xc(%rbp), %rdx
callq 0x1940
movl %eax, -0x14(%rbp)
movw -0x12(%rbp), %ax
movw %ax, -0x16(%rbp)
movb -0x14(%rbp), %al
movb %al, -0x17(%rbp)
movzbl -0xd(%rbp), %eax
movq %rax, -0x20(%rbp)
subq $0xff, %rax
je 0x1911
movq -0x20(%rbp), %rax
leaq 0x5ab9(%rip), %rcx      # 0x7004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x1bf0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x1d20
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x1d80
jmp 0x191a
movq -0x28(%rbp), %rdi
movw -0x16(%rbp), %ax
movzwl %ax, %esi
movzbl -0x17(%rbp), %edx
callq 0x1df0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x1e80
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x1ec0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x1f00
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x1f40
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x1fb0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x1ff0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x2030
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2070
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x2160
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x21a0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x21e0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2200
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2220
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2240
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x2260
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x22d0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x2340
jmp 0x191a
movq -0x28(%rbp), %rdi
movw -0x16(%rbp), %ax
movzwl %ax, %esi
movzbl -0x17(%rbp), %edx
callq 0x23b0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2430
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2480
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x24d0
jmp 0x191a
movq -0x28(%rbp), %rdi
movw -0x16(%rbp), %ax
movzwl %ax, %esi
movzbl -0x17(%rbp), %edx
callq 0x2530
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x25b0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2600
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x2650
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x2670
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x26e0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x2730
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x2780
jmp 0x191a
movq -0x28(%rbp), %rdi
movw -0x16(%rbp), %ax
movzwl %ax, %esi
movzbl -0x17(%rbp), %edx
callq 0x27d0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2860
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x28d0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2930
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2960
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2a00
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2a60
movq -0x28(%rbp), %rdi
movw -0x16(%rbp), %ax
movzwl %ax, %esi
movzbl -0x17(%rbp), %edx
callq 0x2b40
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2be0
jmp 0x191a
movq -0x28(%rbp), %rdi
movw -0x16(%rbp), %ax
movzwl %ax, %esi
movzbl -0x17(%rbp), %edx
callq 0x2c60
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2d00
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2d80
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x2e80
jmp 0x191a
movq -0x28(%rbp), %rdi
movzbl -0x17(%rbp), %esi
callq 0x2ee0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3020
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3040
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3060
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x3080
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x30c0
jmp 0x191a
movq -0x28(%rbp), %rdi
movzwl -0x16(%rbp), %esi
callq 0x3100
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3140
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3190
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x31e0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3230
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3280
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x32b0
jmp 0x191a
movq -0x28(%rbp), %rdi
callq 0x3300
movq -0x28(%rbp), %rdi
movb -0xd(%rbp), %dl
movw -0x16(%rbp), %ax
movl -0xc(%rbp), %ecx
movzbl %dl, %esi
movzwl %ax, %edx
callq 0x3310
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)