/* ======================================================================== */ /* ============================= CONFIGURATION ============================ */ /* ======================================================================== */ #undef FLAG_SET_E #undef FLAG_SET_M #undef FLAG_SET_X #if EXECUTION_MODE == EXECUTION_MODE_E #define FLAG_SET_E 1 #define FLAG_SET_M 1 #define FLAG_SET_X 1 #elif EXECUTION_MODE == EXECUTION_MODE_M0X0 #define FLAG_SET_E 0 #define FLAG_SET_M 0 #define FLAG_SET_X 0 #elif EXECUTION_MODE == EXECUTION_MODE_M0X1 #define FLAG_SET_E 0 #define FLAG_SET_M 0 #define FLAG_SET_X 1 #elif EXECUTION_MODE == EXECUTION_MODE_M1X0 #define FLAG_SET_E 0 #define FLAG_SET_M 1 #define FLAG_SET_X 0 #elif EXECUTION_MODE == EXECUTION_MODE_M1X1 #define FLAG_SET_E 0 #define FLAG_SET_M 1 #define FLAG_SET_X 1 #endif #undef VECTOR_IRQ #undef VECTOR_NMI #undef VECTOR_ABORT #undef VECTOR_BRK #undef VECTOR_COP #if FLAG_SET_E #define VECTOR_IRQ VECTOR_IRQ_E #define VECTOR_NMI VECTOR_NMI_E #define VECTOR_ABORT VECTOR_ABORT_E #define VECTOR_BRK VECTOR_BRK_E #define VECTOR_COP VECTOR_COP_E #else /* FLAG_SET_E */ #define VECTOR_IRQ VECTOR_IRQ_N #define VECTOR_NMI VECTOR_NMI_N #define VECTOR_ABORT VECTOR_ABORT_N #define VECTOR_BRK VECTOR_BRK_N #define VECTOR_COP VECTOR_COP_N #endif /* ======================================================================== */ /* ================================= MEMORY =============================== */ /* ======================================================================== */ #define ADDRESS_65816(A) ((A)&0x00ffffff) INLINE uint g65816i_read_8_normal(g65816i_cpu_struct *cpustate, uint address) { address = ADDRESS_65816(address); return g65816_read_8(address); } INLINE uint g65816i_read_8_immediate(g65816i_cpu_struct *cpustate, uint address) { address = ADDRESS_65816(address); return g65816_read_8_immediate(address); } INLINE uint g65816i_read_8_direct(g65816i_cpu_struct *cpustate, uint address) { #if FLAG_SET_E /* force address into zero page */ address = REGISTER_D + MAKE_UINT_8(address - REGISTER_D); #else address = ADDRESS_65816(address); #endif return g65816_read_8(address); } INLINE uint g65816i_read_8_vector(g65816i_cpu_struct *cpustate, uint address) { if (READ_VECTOR) return READ_VECTOR(cpustate->program, address); else return g65816i_read_8_normal(cpustate, address); } INLINE void g65816i_write_8_normal(g65816i_cpu_struct *cpustate, uint address, uint value) { address = ADDRESS_65816(address); g65816_write_8(address, MAKE_UINT_8(value)); } INLINE void g65816i_write_8_direct(g65816i_cpu_struct *cpustate, uint address, uint value) { #if FLAG_SET_E /* force address into zero page */ address = REGISTER_D + MAKE_UINT_8(address - REGISTER_D); #else address = ADDRESS_65816(address); #endif g65816_write_8(address, MAKE_UINT_8(value)); } INLINE uint g65816i_read_16_normal(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_normal(cpustate, address) | (g65816i_read_8_normal(cpustate, address+1)<<8); } INLINE uint g65816i_read_16_immediate(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_immediate(cpustate, address) | (g65816i_read_8_immediate(cpustate, address+1)<<8); } INLINE uint g65816i_read_16_direct(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_direct(cpustate, address) | (g65816i_read_8_direct(cpustate, address+1)<<8); } INLINE uint g65816i_read_16_vector(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_vector(cpustate, address) | (g65816i_read_8_vector(cpustate, address+1)<<8); } INLINE void g65816i_write_16_normal(g65816i_cpu_struct *cpustate, uint address, uint value) { g65816i_write_8_normal(cpustate, address, value&0xff); g65816i_write_8_normal(cpustate, address+1, value>>8); } INLINE void g65816i_write_16_direct(g65816i_cpu_struct *cpustate, uint address, uint value) { g65816i_write_8_direct(cpustate, address, value&0xff); g65816i_write_8_direct(cpustate, address+1, value>>8); } INLINE uint g65816i_read_24_normal(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_normal(cpustate, address) | (g65816i_read_8_normal(cpustate, address+1)<<8) | (g65816i_read_8_normal(cpustate, address+2)<<16); } INLINE uint g65816i_read_24_immediate(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_immediate(cpustate, address) | (g65816i_read_8_immediate(cpustate, address+1)<<8) | (g65816i_read_8_immediate(cpustate, address+2)<<16); } INLINE uint g65816i_read_24_direct(g65816i_cpu_struct *cpustate, uint address) { return g65816i_read_8_direct(cpustate, address) | (g65816i_read_8_direct(cpustate, address+1)<<8) | (g65816i_read_8_direct(cpustate, address+2)<<16); } /* ======================================================================== */ /* ================================= STACK ================================ */ /* ======================================================================== */ INLINE void g65816i_push_8(g65816i_cpu_struct *cpustate, uint value) { g65816i_write_8_normal(cpustate, REGISTER_S, value); #if FLAG_SET_E REGISTER_S = MAKE_UINT_8(REGISTER_S-1) | 0x100; #else REGISTER_S = MAKE_UINT_16(REGISTER_S-1); #endif } INLINE uint g65816i_pull_8(g65816i_cpu_struct *cpustate) { #if FLAG_SET_E REGISTER_S = MAKE_UINT_8(REGISTER_S+1) | 0x100; #else REGISTER_S = MAKE_UINT_16(REGISTER_S+1); #endif return g65816i_read_8_normal(cpustate, REGISTER_S); } INLINE void g65816i_push_16(g65816i_cpu_struct *cpustate, uint value) { g65816i_push_8(cpustate, value>>8); g65816i_push_8(cpustate, value&0xff); } INLINE uint g65816i_pull_16(g65816i_cpu_struct *cpustate) { uint res = g65816i_pull_8(cpustate); return res | (g65816i_pull_8(cpustate) << 8); } INLINE void g65816i_push_24(g65816i_cpu_struct *cpustate, uint value) { g65816i_push_8(cpustate, value>>16); g65816i_push_8(cpustate, (value>>8)&0xff); g65816i_push_8(cpustate, value&0xff); } INLINE uint g65816i_pull_24(g65816i_cpu_struct *cpustate) { uint res = g65816i_pull_8(cpustate); res |= g65816i_pull_8(cpustate) << 8; return ((res + 1) & 0xffff) | (g65816i_pull_8(cpustate) << 16); } /* ======================================================================== */ /* ============================ PROGRAM COUNTER =========================== */ /* ======================================================================== */ INLINE void g65816i_jump_16(g65816i_cpu_struct *cpustate, uint address) { REGISTER_PC = MAKE_UINT_16(address); g65816i_jumping(REGISTER_PC); } INLINE void g65816i_jump_24(g65816i_cpu_struct *cpustate, uint address) { REGISTER_PB = address&0xff0000; REGISTER_PC = MAKE_UINT_16(address); g65816i_jumping(REGISTER_PC); } INLINE void g65816i_branch_8(g65816i_cpu_struct *cpustate, uint offset) { #if FLAG_SET_E uint old_pc = REGISTER_PC; REGISTER_PC = MAKE_UINT_16(REGISTER_PC + MAKE_INT_8(offset)); if((REGISTER_PC^old_pc)&0xff00) CLK(1); #else REGISTER_PC = MAKE_UINT_16(REGISTER_PC + MAKE_INT_8(offset)); #endif g65816i_branching(REGISTER_PC); } INLINE void g65816i_branch_16(g65816i_cpu_struct *cpustate, uint offset) { REGISTER_PC = MAKE_UINT_16(REGISTER_PC + offset); g65816i_branching(REGISTER_PC); } /* ======================================================================== */ /* ============================ STATUS REGISTER =========================== */ /* ======================================================================== */ #if !FLAG_SET_E INLINE void g65816i_set_flag_mx(g65816i_cpu_struct *cpustate, uint value) { #if FLAG_SET_M if(!(value & FLAGPOS_M)) { REGISTER_A |= REGISTER_B; REGISTER_B = 0; FLAG_M = MFLAG_CLEAR; } #else if(value & FLAGPOS_M) { REGISTER_B = REGISTER_A & 0xff00; REGISTER_A = MAKE_UINT_8(REGISTER_A); FLAG_M = MFLAG_SET; } #endif #if FLAG_SET_X if(!(value & FLAGPOS_X)) { FLAG_X = XFLAG_CLEAR; } #else if(value & FLAGPOS_X) { REGISTER_X = MAKE_UINT_8(REGISTER_X); REGISTER_Y = MAKE_UINT_8(REGISTER_Y); FLAG_X = XFLAG_SET; } #endif g65816i_set_execution_mode(cpustate, (FLAG_M>>4) | (FLAG_X>>4)); } #endif INLINE void g65816i_set_flag_e(g65816i_cpu_struct *cpustate, uint value) { #if FLAG_SET_E if(!value) { FLAG_E = EFLAG_CLEAR; g65816i_set_execution_mode(cpustate, EXECUTION_MODE_M1X1); } #else if(value) { #if !FLAG_SET_M REGISTER_B = REGISTER_A & 0xff00; REGISTER_A &= 0x00ff; FLAG_M = MFLAG_SET; #endif #if !FLAG_SET_X REGISTER_X = MAKE_UINT_8(REGISTER_X); REGISTER_Y = MAKE_UINT_8(REGISTER_Y); FLAG_X = XFLAG_SET; #endif REGISTER_S = MAKE_UINT_8(REGISTER_S) | 0x100; FLAG_E = EFLAG_SET; g65816i_set_execution_mode(cpustate, EXECUTION_MODE_E); } #endif } //INLINE void g65816i_check_maskable_interrupt(void); INLINE void g65816i_set_flag_i(g65816i_cpu_struct *cpustate, uint value) { value &= FLAGPOS_I; if(!FLAG_I || value) { FLAG_I = value; return; } FLAG_I = value; // g65816i_check_maskable_interrupt(); } /* Get the Processor Status Register */ INLINE uint g65816i_get_reg_p(g65816i_cpu_struct *cpustate) { return (FLAG_N&0x80) | ((FLAG_V>>1)&0x40) | FLAG_M | FLAG_X | FLAG_D | FLAG_I | ((!FLAG_Z)<<1) | ((FLAG_C>>8)&1); } INLINE void g65816i_set_reg_p(g65816i_cpu_struct *cpustate, uint value) { #if FLAG_SET_E FLAG_N = value; FLAG_V = value << 1; FLAG_D = value & FLAGPOS_D; FLAG_Z = !(value & FLAGPOS_Z); FLAG_C = value << 8; g65816i_set_flag_i(cpustate, value); #else FLAG_N = value; FLAG_V = value << 1; FLAG_D = value & FLAGPOS_D; FLAG_Z = !(value & FLAGPOS_Z); FLAG_C = value << 8; g65816i_set_flag_mx(cpustate, value); g65816i_set_flag_i(cpustate, value); #endif } /* ======================================================================== */ /* =============================== INTERRUPTS ============================= */ /* ======================================================================== */ INLINE void g65816i_interrupt_hardware(g65816i_cpu_struct *cpustate, uint vector) { #if FLAG_SET_E CLK(7); g65816i_push_16(cpustate, REGISTER_PC); g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate) & ~FLAGPOS_B); FLAG_D = DFLAG_CLEAR; g65816i_set_flag_i(cpustate, IFLAG_SET); REGISTER_PB = 0; g65816i_jump_16(cpustate, g65816i_read_16_vector(cpustate, vector)); if(INT_ACK) INT_ACK(cpustate->device, 0); #else CLK(8); g65816i_push_8(cpustate, REGISTER_PB>>16); g65816i_push_16(cpustate, REGISTER_PC); g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate)); FLAG_D = DFLAG_CLEAR; g65816i_set_flag_i(cpustate, IFLAG_SET); REGISTER_PB = 0; g65816i_jump_16(cpustate, g65816i_read_16_vector(cpustate, vector)); if(INT_ACK) INT_ACK(cpustate->device, 0); #endif } INLINE void g65816i_interrupt_software(g65816i_cpu_struct *cpustate, uint vector) { #if FLAG_SET_E CLK(7); g65816i_push_16(cpustate, REGISTER_PC); g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate)); FLAG_D = DFLAG_CLEAR; g65816i_set_flag_i(cpustate, IFLAG_SET); REGISTER_PB = 0; g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, vector)); #else CLK(8); g65816i_push_8(cpustate, REGISTER_PB>>16); g65816i_push_16(cpustate, REGISTER_PC); g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate)); FLAG_D = DFLAG_CLEAR; g65816i_set_flag_i(cpustate, IFLAG_SET); REGISTER_PB = 0; g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, vector)); #endif } INLINE void g65816i_interrupt_nmi(g65816i_cpu_struct *cpustate) { #if FLAG_SET_E CLK(7); g65816i_push_16(cpustate, REGISTER_PC); g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate) & ~FLAGPOS_B); FLAG_D = DFLAG_CLEAR; REGISTER_PB = 0; g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, VECTOR_NMI)); #else CLK(8); g65816i_push_8(cpustate, REGISTER_PB>>16); g65816i_push_16(cpustate, REGISTER_PC); g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate)); FLAG_D = DFLAG_CLEAR; REGISTER_PB = 0; g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, VECTOR_NMI)); #endif } INLINE void g65816i_check_maskable_interrupt(g65816i_cpu_struct *cpustate) { if(!(CPU_STOPPED & STOP_LEVEL_STOP) && LINE_IRQ && !FLAG_I) { g65816i_interrupt_hardware(cpustate, VECTOR_IRQ); CPU_STOPPED &= ~STOP_LEVEL_WAI; LINE_IRQ=0; } } /* ======================================================================== */ /* ========================== EFFECTIVE ADDRESSES ========================= */ /* ======================================================================== */ /* Effective-address based memory access macros */ #define read_8_NORM(A) g65816i_read_8_normal(cpustate, A) #define read_8_IMM(A) g65816i_read_8_immediate(cpustate, A) #define read_8_D(A) g65816i_read_8_direct(cpustate, A) #define read_8_A(A) g65816i_read_8_normal(cpustate, A) #define read_8_AL(A) g65816i_read_8_normal(cpustate, A) #define read_8_DX(A) g65816i_read_8_direct(cpustate, A) #define read_8_DY(A) g65816i_read_8_direct(cpustate, A) #define read_8_AX(A) g65816i_read_8_normal(cpustate, A) #define read_8_ALX(A) g65816i_read_8_normal(cpustate, A) #define read_8_AY(A) g65816i_read_8_normal(cpustate, A) #define read_8_DI(A) g65816i_read_8_normal(cpustate, A) #define read_8_DLI(A) g65816i_read_8_normal(cpustate, A) #define read_8_AI(A) g65816i_read_8_normal(cpustate, A) #define read_8_ALI(A) g65816i_read_8_normal(cpustate, A) #define read_8_DXI(A) g65816i_read_8_normal(cpustate, A) #define read_8_DIY(A) g65816i_read_8_normal(cpustate, A) #define read_8_DLIY(A) g65816i_read_8_normal(cpustate, A) #define read_8_AXI(A) g65816i_read_8_normal(cpustate, A) #define read_8_S(A) g65816i_read_8_normal(cpustate, A) #define read_8_SIY(A) g65816i_read_8_normal(cpustate, A) #define read_16_NORM(A) g65816i_read_16_normal(cpustate, A) #define read_16_IMM(A) g65816i_read_16_immediate(cpustate, A) #define read_16_D(A) g65816i_read_16_direct(cpustate, A) #define read_16_A(A) g65816i_read_16_normal(cpustate, A) #define read_16_AL(A) g65816i_read_16_normal(cpustate, A) #define read_16_DX(A) g65816i_read_16_direct(cpustate, A) #define read_16_DY(A) g65816i_read_16_direct(cpustate, A) #define read_16_AX(A) g65816i_read_16_normal(cpustate, A) #define read_16_ALX(A) g65816i_read_16_normal(cpustate, A) #define read_16_AY(A) g65816i_read_16_normal(cpustate, A) #define read_16_DI(A) g65816i_read_16_normal(cpustate, A) #define read_16_DLI(A) g65816i_read_16_normal(cpustate, A) #define read_16_AI(A) g65816i_read_16_normal(cpustate, A) #define read_16_ALI(A) g65816i_read_16_normal(cpustate, A) #define read_16_DXI(A) g65816i_read_16_normal(cpustate, A) #define read_16_DIY(A) g65816i_read_16_normal(cpustate, A) #define read_16_DLIY(A) g65816i_read_16_normal(cpustate, A) #define read_16_AXI(A) g65816i_read_16_normal(cpustate, A) #define read_16_S(A) g65816i_read_16_normal(cpustate, A) #define read_16_SIY(A) g65816i_read_16_normal(cpustate, A) #define read_24_NORM(A) g65816i_read_24_normal(cpustate, A) #define read_24_IMM(A) g65816i_read_24_immediate(cpustate, A) #define read_24_D(A) g65816i_read_24_direct(cpustate, A) #define read_24_A(A) g65816i_read_24_normal(cpustate, A) #define read_24_AL(A) g65816i_read_24_normal(cpustate, A) #define read_24_DX(A) g65816i_read_24_direct(cpustate, A) #define read_24_DY(A) g65816i_read_24_direct(cpustate, A) #define read_24_AX(A) g65816i_read_24_normal(cpustate, A) #define read_24_ALX(A) g65816i_read_24_normal(cpustate, A) #define read_24_AY(A) g65816i_read_24_normal(cpustate, A) #define read_24_DI(A) g65816i_read_24_normal(cpustate, A) #define read_24_DLI(A) g65816i_read_24_normal(cpustate, A) #define read_24_AI(A) g65816i_read_24_normal(cpustate, A) #define read_24_ALI(A) g65816i_read_24_normal(cpustate, A) #define read_24_DXI(A) g65816i_read_24_normal(cpustate, A) #define read_24_DIY(A) g65816i_read_24_normal(cpustate, A) #define read_24_DLIY(A) g65816i_read_24_normal(cpustate, A) #define read_24_AXI(A) g65816i_read_24_normal(cpustate, A) #define read_24_S(A) g65816i_read_24_normal(cpustate, A) #define read_24_SIY(A) g65816i_read_24_normal(cpustate, A) #define write_8_NORM(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_D(A, V) g65816i_write_8_direct(cpustate, A, V) #define write_8_A(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_AL(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_DX(A, V) g65816i_write_8_direct(cpustate, A, V) #define write_8_DY(A, V) g65816i_write_8_direct(cpustate, A, V) #define write_8_AX(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_ALX(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_AY(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_DI(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_DLI(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_AI(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_ALI(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_DXI(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_DIY(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_DLIY(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_AXI(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_S(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_8_SIY(A, V) g65816i_write_8_normal(cpustate, A, V) #define write_16_NORM(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_D(A, V) g65816i_write_16_direct(cpustate, A, V) #define write_16_A(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_AL(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_DX(A, V) g65816i_write_16_direct(cpustate, A, V) #define write_16_DY(A, V) g65816i_write_16_direct(cpustate, A, V) #define write_16_AX(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_ALX(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_AY(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_DI(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_DLI(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_AI(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_ALI(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_DXI(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_DIY(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_DLIY(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_AXI(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_S(A, V) g65816i_write_16_normal(cpustate, A, V) #define write_16_SIY(A, V) g65816i_write_16_normal(cpustate, A, V) #define OPER_8_IMM(cpustate) read_8_IMM(EA_IMM8(cpustate)) #define OPER_8_D(cpustate) read_8_D(EA_D(cpustate)) #define OPER_8_A(cpustate) read_8_A(EA_A(cpustate)) #define OPER_8_AL(cpustate) read_8_AL(EA_AL(cpustate)) #define OPER_8_DX(cpustate) read_8_DX(EA_DX(cpustate)) #define OPER_8_DY(cpustate) read_8_DY(EA_DY(cpustate)) #define OPER_8_AX(cpustate) read_8_AX(EA_AX(cpustate)) #define OPER_8_ALX(cpustate) read_8_ALX(EA_ALX(cpustate)) #define OPER_8_AY(cpustate) read_8_AY(EA_AY(cpustate)) #define OPER_8_DI(cpustate) read_8_DI(EA_DI(cpustate)) #define OPER_8_DLI(cpustate) read_8_DLI(EA_DLI(cpustate)) #define OPER_8_AI(cpustate) read_8_AI(EA_AI(cpustate)) #define OPER_8_ALI(cpustate) read_8_ALI(EA_ALI(cpustate)) #define OPER_8_DXI(cpustate) read_8_DXI(EA_DXI(cpustate)) #define OPER_8_DIY(cpustate) read_8_DIY(EA_DIY(cpustate)) #define OPER_8_DLIY(cpustate) read_8_DLIY(EA_DLIY(cpustate)) #define OPER_8_AXI(cpustate) read_8_AXI(EA_AXI(cpustate)) #define OPER_8_S(cpustate) read_8_S(EA_S(cpustate)) #define OPER_8_SIY(cpustate) read_8_SIY(EA_SIY(cpustate)) #define OPER_16_IMM(cpustate) read_16_IMM(EA_IMM16(cpustate)) #define OPER_16_D(cpustate) read_16_D(EA_D(cpustate)) #define OPER_16_A(cpustate) read_16_A(EA_A(cpustate)) #define OPER_16_AL(cpustate) read_16_AL(EA_AL(cpustate)) #define OPER_16_DX(cpustate) read_16_DX(EA_DX(cpustate)) #define OPER_16_DY(cpustate) read_16_DY(EA_DY(cpustate)) #define OPER_16_AX(cpustate) read_16_AX(EA_AX(cpustate)) #define OPER_16_ALX(cpustate) read_16_ALX(EA_ALX(cpustate)) #define OPER_16_AY(cpustate) read_16_AY(EA_AY(cpustate)) #define OPER_16_DI(cpustate) read_16_DI(EA_DI(cpustate)) #define OPER_16_DLI(cpustate) read_16_DLI(EA_DLI(cpustate)) #define OPER_16_AI(cpustate) read_16_AI(EA_AI(cpustate)) #define OPER_16_ALI(cpustate) read_16_ALI(EA_ALI(cpustate)) #define OPER_16_DXI(cpustate) read_16_DXI(EA_DXI(cpustate)) #define OPER_16_DIY(cpustate) read_16_DIY(EA_DIY(cpustate)) #define OPER_16_DLIY(cpustate) read_16_DLIY(EA_DLIY(cpustate)) #define OPER_16_AXI(cpustate) read_16_AXI(EA_AXI(cpustate)) #define OPER_16_S(cpustate) read_16_S(EA_S(cpustate)) #define OPER_16_SIY(cpustate) read_16_SIY(EA_SIY(cpustate)) #define OPER_24_IMM(cpustate) read_24_IMM(EA_IMM24(cpustate)) #define OPER_24_D(cpustate) read_24_D(EA_D(cpustate)) #define OPER_24_A(cpustate) read_24_A(EA_A(cpustate)) #define OPER_24_AL(cpustate) read_24_AL(EA_AL(cpustate)) #define OPER_24_DX(cpustate) read_24_DX(EA_DX(cpustate)) #define OPER_24_DY(cpustate) read_24_DY(EA_DY(cpustate)) #define OPER_24_AX(cpustate) read_24_AX(EA_AX(cpustate)) #define OPER_24_ALX(cpustate) read_24_ALX(EA_ALX(cpustate)) #define OPER_24_AY(cpustate) read_24_AY(EA_AY(cpustate)) #define OPER_24_DI(cpustate) read_24_DI(EA_DI(cpustate)) #define OPER_24_DLI(cpustate) read_24_DLI(EA_DLI(cpustate)) #define OPER_24_AI(cpustate) read_24_AI(EA_AI(cpustate)) #define OPER_24_ALI(cpustate) read_24_ALI(EA_ALI(cpustate)) #define OPER_24_DXI(cpustate) read_24_DXI(EA_DXI(cpustate)) #define OPER_24_DIY(cpustate) read_24_DIY(EA_DIY(cpustate)) #define OPER_24_DLIY(cpustate) read_24_DLIY(EA_DLIY(cpustate)) #define OPER_24_AXI(cpustate) read_24_AXI(EA_AXI(cpustate)) #define OPER_24_S(cpustate) read_24_S(EA_S(cpustate)) #define OPER_24_SIY(cpustate) read_24_SIY(EA_SIY(cpustate)) INLINE uint EA_IMM8(g65816i_cpu_struct *cpustate) {REGISTER_PC += 1; return REGISTER_PB | MAKE_UINT_16(REGISTER_PC-1);} INLINE uint EA_IMM16(g65816i_cpu_struct *cpustate) {REGISTER_PC += 2; return REGISTER_PB | MAKE_UINT_16(REGISTER_PC-2);} INLINE uint EA_IMM24(g65816i_cpu_struct *cpustate) {REGISTER_PC += 3; return REGISTER_PB | MAKE_UINT_16(REGISTER_PC-3);} INLINE uint EA_D(g65816i_cpu_struct *cpustate) {if(MAKE_UINT_8(REGISTER_D)) CLK(1); return MAKE_UINT_16(REGISTER_D + OPER_8_IMM(cpustate));} INLINE uint EA_A(g65816i_cpu_struct *cpustate) {return REGISTER_DB | OPER_16_IMM(cpustate);} INLINE uint EA_AL(g65816i_cpu_struct *cpustate) {return OPER_24_IMM(cpustate);} INLINE uint EA_DX(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(REGISTER_D + OPER_8_IMM(cpustate) + REGISTER_X);} INLINE uint EA_DY(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(REGISTER_D + OPER_8_IMM(cpustate) + REGISTER_Y);} INLINE uint EA_AX(g65816i_cpu_struct *cpustate) {uint tmp = EA_A(cpustate); if((tmp^(tmp+REGISTER_X))&0xff00) CLK(1); return tmp + REGISTER_X;} INLINE uint EA_ALX(g65816i_cpu_struct *cpustate) {return EA_AL(cpustate) + REGISTER_X;} INLINE uint EA_AY(g65816i_cpu_struct *cpustate) {uint tmp = EA_A(cpustate); if((tmp^(tmp+REGISTER_X))&0xff00) CLK(1); return tmp + REGISTER_Y;} INLINE uint EA_DI(g65816i_cpu_struct *cpustate) {return REGISTER_DB | OPER_16_D(cpustate);} INLINE uint EA_DLI(g65816i_cpu_struct *cpustate) {return OPER_24_D(cpustate);} INLINE uint EA_AI(g65816i_cpu_struct *cpustate) {return read_16_A(OPER_16_IMM(cpustate));} INLINE uint EA_ALI(g65816i_cpu_struct *cpustate) {return OPER_24_A(cpustate);} INLINE uint EA_DXI(g65816i_cpu_struct *cpustate) {return REGISTER_DB | OPER_16_DX(cpustate);} INLINE uint EA_DIY(g65816i_cpu_struct *cpustate) {uint tmp = REGISTER_DB | OPER_16_D(cpustate); if((tmp^(tmp+REGISTER_X))&0xff00) CLK(1); return tmp + REGISTER_Y;} INLINE uint EA_DLIY(g65816i_cpu_struct *cpustate) {return OPER_24_D(cpustate) + REGISTER_Y;} INLINE uint EA_AXI(g65816i_cpu_struct *cpustate) {return read_16_AXI(MAKE_UINT_16(OPER_16_IMM(cpustate) + REGISTER_X));} INLINE uint EA_S(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(REGISTER_S + OPER_8_IMM(cpustate));} INLINE uint EA_SIY(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(read_16_SIY(REGISTER_S + OPER_8_IMM(cpustate)) + REGISTER_Y) | REGISTER_DB;} /* ======================================================================== */ /* =========================== OPERATION MACROS =========================== */ /* ======================================================================== */ /* M6502 Add With Carry */ #undef OP_ADC #if FLAG_SET_M #define OP_ADC(MODE) \ { \ unsigned tmp16; \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ SRC = OPER_8_##MODE(cpustate); \ if(FLAG_D) \ { \ INT32 result, r0, r1, carry; \ r0 = REGISTER_A; \ r1 = SRC; \ carry = CFLAG_AS_1(); \ result = (r0 & 0x0f) + (r1 & 0x0f) + (carry << 0); \ if (result > 0x09) result += 0x06; \ carry = result > 0x0f; \ result = (r0 & 0xf0) + (r1 & 0xf0) + (carry << 4) + (result & 0x0f); \ FLAG_V = ~(r0 ^ SRC) & (r0 ^ result) & 0x80; \ if (result > 0x9f) result += 0x60; \ FLAG_C = (result > 0xff) ? 0x100 : 0; \ FLAG_N = (result & 0x80); \ FLAG_Z = REGISTER_A = MAKE_UINT_8(result); \ } \ else \ { \ FLAG_C = tmp16 = REGISTER_A + SRC + CFLAG_AS_1(); \ FLAG_V = VFLAG_ADD_8(SRC, REGISTER_A, FLAG_C); \ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(tmp16); \ } \ } #else #define OP_ADC(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ SRC = OPER_16_##MODE(cpustate); \ INT32 result, r0, r1, carry; \ r0 = REGISTER_A; \ r1 = SRC; \ carry = CFLAG_AS_1(); \ if (!FLAG_D) \ { \ result = r0 + r1 + carry; \ } \ else \ { \ result = (r0 & 0x000f) + (r1 & 0x000f) + (carry << 0); \ if(result > 0x0009) result += 0x0006; \ carry = result > 0x000f; \ result = (r0 & 0x00f0) + (r1 & 0x00f0) + (carry << 4) + (result & 0x000f); \ if(result > 0x009f) result += 0x0060; \ carry = result > 0x00ff; \ result = (r0 & 0x0f00) + (r1 & 0x0f00) + (carry << 8) + (result & 0x00ff); \ if(result > 0x09ff) result += 0x0600; \ carry = result > 0x0fff; \ result = (r0 & 0xf000) + (r1 & 0xf000) + (carry << 12) + (result & 0x0fff); \ } \ FLAG_V = ~(r0 ^ r1) & (r0 ^ result) & 0x8000; \ FLAG_V >>= 8; \ if (FLAG_D && result > 0x9fff) result += 0x6000; \ FLAG_C = (result > 0xffff) ? 0x100 : 0; \ FLAG_Z = REGISTER_A = MAKE_UINT_16(result); \ FLAG_N = NFLAG_16(REGISTER_A); #endif /* M6502 Logical AND with accumulator */ #undef OP_AND #if FLAG_SET_M #define OP_AND(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_N = FLAG_Z = REGISTER_A &= OPER_8_##MODE(cpustate) #else #define OP_AND(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_Z = REGISTER_A &= OPER_16_##MODE(cpustate); \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* M6502 Arithmetic Shift Left accumulator */ #undef OP_ASL #if FLAG_SET_M #define OP_ASL() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_C = REGISTER_A << 1; \ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(FLAG_C) #else #define OP_ASL() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_C = REGISTER_A << 1; \ FLAG_Z = REGISTER_A = MAKE_UINT_16(FLAG_C); \ FLAG_N = NFLAG_16(FLAG_C); \ FLAG_C = CFLAG_16(FLAG_C) #endif /* M6502 Arithmetic Shift Left operand */ #undef OP_ASLM #if FLAG_SET_M #define OP_ASLM(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_C = read_8_##MODE(DST) << 1; \ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ write_8_##MODE(DST, FLAG_Z) #else #define OP_ASLM(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_C = read_16_##MODE(DST) << 1; \ FLAG_Z = MAKE_UINT_16(FLAG_C); \ FLAG_N = NFLAG_16(FLAG_C); \ FLAG_C = CFLAG_16(FLAG_C); \ write_16_##MODE(DST, FLAG_Z) #endif /* M6502 Branch on Condition Code */ #undef OP_BCC #define OP_BCC(COND) \ DST = OPER_8_IMM(cpustate); \ if(COND) \ { \ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \ g65816i_branch_8(cpustate, DST); \ BREAKOUT; \ } \ CLK(CLK_OP + CLK_RELATIVE_8); \ /* M6502 Set flags according to bits */ #undef OP_BIT #if FLAG_SET_M #define OP_BIT(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_N = OPER_8_##MODE(cpustate); \ FLAG_Z = FLAG_N & REGISTER_A; \ FLAG_V = FLAG_N << 1 #else #define OP_BIT(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_N = OPER_16_##MODE(cpustate); \ FLAG_Z = FLAG_N & REGISTER_A; \ FLAG_N = NFLAG_16(FLAG_N); \ FLAG_V = FLAG_N << 1 #endif /* G65816 Set flags according to bits (immediate addressing mode) */ #undef OP_BITI #if FLAG_SET_M #define OP_BITI() \ CLK(CLK_OP + CLK_R8 + CLK_IMM); \ FLAG_Z = REGISTER_A & OPER_8_IMM(cpustate) #else #define OP_BITI() \ CLK(CLK_OP + CLK_R16 + CLK_IMM); \ FLAG_Z = REGISTER_A & OPER_16_IMM(cpustate) #endif /* M6502 Cause a Break interrupt */ #undef OP_BRK #define OP_BRK() \ REGISTER_PC++; \ g65816i_interrupt_software(cpustate, VECTOR_BRK) /* G65816 Branch Always */ #undef OP_BRA #define OP_BRA() \ CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_8); \ g65816i_branch_8(cpustate, OPER_8_IMM(cpustate)) /* G65816 Branch Always Long */ #undef OP_BRL #define OP_BRL() \ CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_16); \ g65816i_branch_16(cpustate, OPER_16_IMM(cpustate)) /* M6502 Clear Carry flag */ #undef OP_CLC #define OP_CLC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_C = CFLAG_CLEAR /* M6502 Clear Decimal flag */ #undef OP_CLD #define OP_CLD() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_D = DFLAG_CLEAR /* M6502 Clear Interrupt Mask flag */ #undef OP_CLI #define OP_CLI() \ CLK(CLK_OP + CLK_IMPLIED); \ g65816i_set_flag_i(cpustate, IFLAG_CLEAR) /* M6502 Clear oVerflow flag */ #undef OP_CLV #define OP_CLV() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_V = VFLAG_CLEAR /* M6502 Compare operand to accumulator */ /* Unusual behavior: C flag is inverted */ #undef OP_CMP #if FLAG_SET_M #define OP_CMP(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_C = REGISTER_A - OPER_8_##MODE(cpustate); \ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ FLAG_C ^= CFLAG_SET #else #define OP_CMP(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_C = REGISTER_A - OPER_16_##MODE(cpustate); \ FLAG_Z = MAKE_UINT_16(FLAG_C); \ FLAG_N = NFLAG_16(FLAG_C); \ FLAG_C = ~CFLAG_16(FLAG_C) #endif /* M6502 Compare operand to index register */ /* Unusual behavior: C flag is inverted */ #undef OP_CMPX #if FLAG_SET_X #define OP_CMPX(REG, MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_C = REG - OPER_8_##MODE(cpustate); \ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ FLAG_C ^= CFLAG_SET #else #define OP_CMPX(REG, MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_C = REG - OPER_16_##MODE(cpustate); \ FLAG_Z = MAKE_UINT_16(FLAG_C); \ FLAG_N = NFLAG_16(FLAG_C); \ FLAG_C = ~CFLAG_16(FLAG_C) #endif /* G65816 Coprocessor operation */ #undef OP_COP #define OP_COP() \ REGISTER_PC++; \ g65816i_interrupt_software(cpustate, VECTOR_COP) /* M6502 Decrement accumulator */ #undef OP_DEC #if FLAG_SET_M #define OP_DEC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(REGISTER_A - 1) #else #define OP_DEC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_A = MAKE_UINT_16(REGISTER_A - 1); \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* M6502 Decrement operand */ #undef OP_DECM #if FLAG_SET_M #define OP_DECM(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) - 1); \ write_8_##MODE(DST, FLAG_Z) #else #define OP_DECM(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) - 1); \ FLAG_N = NFLAG_16(FLAG_Z); \ write_16_##MODE(DST, FLAG_Z) #endif /* M6502 Decrement index register */ #undef OP_DECX #if FLAG_SET_X #define OP_DECX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG - 1) #else #define OP_DECX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REG = MAKE_UINT_16(REG - 1); \ FLAG_N = NFLAG_16(REG) #endif /* M6502 Exclusive Or operand to accumulator */ #undef OP_EOR #if FLAG_SET_M #define OP_EOR(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_N = FLAG_Z = REGISTER_A ^= OPER_8_##MODE(cpustate) #else #define OP_EOR(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_Z = REGISTER_A ^= OPER_16_##MODE(cpustate); \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* M6502 Increment accumulator */ #undef OP_INC #if FLAG_SET_M #define OP_INC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(REGISTER_A + 1) #else #define OP_INC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_A = MAKE_UINT_16(REGISTER_A + 1); \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* M6502 Increment operand */ #undef OP_INCM #if FLAG_SET_M #define OP_INCM(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) + 1); \ write_8_##MODE(DST, FLAG_Z) #else #define OP_INCM(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) + 1); \ FLAG_N = NFLAG_16(FLAG_Z); \ write_16_##MODE(DST, FLAG_Z) #endif /* M6502 Increment index register */ #undef OP_INCX #if FLAG_SET_X #define OP_INCX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG + 1) #else #define OP_INCX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REG = MAKE_UINT_16(REG + 1); \ FLAG_N = NFLAG_16(REG) #endif /* G65816 Jump Long */ #undef OP_JMLAI #define OP_JMLAI() \ CLK(CLK_OP + CLK_AI + 1); \ g65816i_jump_24(cpustate, read_24_A(OPER_16_IMM(cpustate))) /* M6502 Jump */ #undef OP_JMP #define OP_JMP(MODE) \ CLK(CLK_OP + CLK_##MODE); \ g65816i_jump_16(cpustate, EA_##MODE(cpustate)) /* M6502 Jump absolute indexed indirect */ #undef OP_JMPAXI #define OP_JMPAXI() \ CLK(CLK_OP + CLK_AXI); \ g65816i_jump_16(cpustate, read_16_AXI(REGISTER_PB | (MAKE_UINT_16(OPER_16_IMM(cpustate) + REGISTER_X)))) /* G65816 Jump absolute long */ #undef OP_JMPAL #define OP_JMPAL() \ CLK(CLK_OP + CLK_AL); \ g65816i_jump_24(cpustate, EA_AL(cpustate)) /* G65816 Jump to Subroutine Long */ /* Unusual behavior: stacks PC-1 */ #undef OP_JSL #define OP_JSL(MODE) \ CLK(CLK_OP + CLK_W24 + CLK_##MODE + 1); \ DST = EA_##MODE(cpustate); \ g65816i_push_8(cpustate, REGISTER_PB>>16); \ g65816i_push_16(cpustate, REGISTER_PC-1); \ g65816i_jump_24(cpustate, DST) /* M6502 Jump to Subroutine */ /* Unusual behavior: stacks PC-1 */ #undef OP_JSR #define OP_JSR(MODE) \ CLK(CLK_OP + CLK_W16 + CLK_##MODE); \ DST = EA_##MODE(cpustate); \ g65816i_push_16(cpustate, REGISTER_PC-1); \ g65816i_jump_16(cpustate, DST) /* M6502 Jump to Subroutine */ /* Unusual behavior: stacks PC-1 */ #undef OP_JSRAXI #define OP_JSRAXI() \ CLK(CLK_OP + CLK_W16 + CLK_AXI); \ DST = read_16_AXI(REGISTER_PB | (MAKE_UINT_16(OPER_16_IMM(cpustate) + REGISTER_X))); \ g65816i_push_16(cpustate, REGISTER_PC-1); \ g65816i_jump_16(cpustate, DST) /* M6502 Load accumulator with operand */ #undef OP_LDA #if FLAG_SET_M #define OP_LDA(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_N = FLAG_Z = REGISTER_A = OPER_8_##MODE(cpustate) #else #define OP_LDA(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_Z = REGISTER_A = OPER_16_##MODE(cpustate); \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* M6502 Load index register with operand */ #undef OP_LDX #if FLAG_SET_X #define OP_LDX(REG, MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_N = FLAG_Z = REG = OPER_8_##MODE(cpustate) #else #define OP_LDX(REG, MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_Z = REG = OPER_16_##MODE(cpustate); \ FLAG_N = NFLAG_16(REG) #endif /* M6502 Logical Shift Right accumulator */ #undef OP_LSR #if FLAG_SET_M #define OP_LSR() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_N = 0; \ FLAG_C = REGISTER_A << 8; \ FLAG_Z = REGISTER_A >>= 1 #else #define OP_LSR() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_N = 0; \ FLAG_C = REGISTER_A << 8; \ FLAG_Z = REGISTER_A >>= 1 #endif /* M6502 Logical Shift Right operand */ #undef OP_LSRM #if FLAG_SET_M #define OP_LSRM(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_N = 0; \ FLAG_Z = read_8_##MODE(DST); \ FLAG_C = FLAG_Z << 8; \ FLAG_Z >>= 1; \ write_8_##MODE(DST, FLAG_Z) #else #define OP_LSRM(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_N = 0; \ FLAG_Z = read_16_##MODE(DST); \ FLAG_C = FLAG_Z << 8; \ FLAG_Z >>= 1; \ write_16_##MODE(DST, FLAG_Z) #endif /* G65816 Move Block Negative */ #undef OP_MVN #if FLAG_SET_M #if FLAG_SET_X #define OP_MVN() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_8(REGISTER_X+1); \ REGISTER_Y = MAKE_UINT_8(REGISTER_Y+1); \ REGISTER_A--; \ REGISTER_A &= 0xff; \ if ((REGISTER_A&0xff) != 0xff) \ {\ REGISTER_PC -= 3; \ }\ else \ { \ REGISTER_B -= 0x100;\ REGISTER_B &= 0xff00; \ if ((REGISTER_B & 0xff00) != 0xff00)\ { \ REGISTER_PC -= 3;\ } \ } #else #define OP_MVN() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_16(REGISTER_X+1); \ REGISTER_Y = MAKE_UINT_16(REGISTER_Y+1); \ REGISTER_A--; \ REGISTER_A &= 0xff; \ if ((REGISTER_A&0xff) != 0xff) \ {\ REGISTER_PC -= 3; \ }\ else \ { \ REGISTER_B -= 0x100;\ REGISTER_B &= 0xff00; \ if ((REGISTER_B & 0xff00) != 0xff00)\ { \ REGISTER_PC -= 3;\ } \ } #endif #else #if FLAG_SET_X #define OP_MVN() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ REGISTER_A |= REGISTER_B; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_8(REGISTER_X+1); \ REGISTER_Y = MAKE_UINT_8(REGISTER_Y+1); \ REGISTER_A--; \ if ((REGISTER_A&0xffff) != 0xffff) \ {\ REGISTER_PC -= 3; \ } #else #define OP_MVN() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ REGISTER_A |= REGISTER_B; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_16(REGISTER_X+1); \ REGISTER_Y = MAKE_UINT_16(REGISTER_Y+1); \ REGISTER_A--; \ if ((REGISTER_A&0xffff) != 0xffff) \ {\ REGISTER_PC -= 3; \ } #endif #endif /* G65816 Move Block Positive */ #undef OP_MVP #if FLAG_SET_M #if FLAG_SET_X #define OP_MVP() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_8(REGISTER_X-1); \ REGISTER_Y = MAKE_UINT_8(REGISTER_Y-1); \ REGISTER_A--; \ REGISTER_A &= 0xff; \ if ((REGISTER_A&0xff) != 0xff) \ {\ REGISTER_PC -= 3; \ }\ else \ { \ REGISTER_B -= 0x100;\ REGISTER_B &= 0xff00; \ if ((REGISTER_B & 0xff00) != 0xff00)\ { \ REGISTER_PC -= 3;\ } \ } #else #define OP_MVP() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_16(REGISTER_X-1); \ REGISTER_Y = MAKE_UINT_16(REGISTER_Y-1); \ REGISTER_A--; \ REGISTER_A &= 0xff; \ if ((REGISTER_A&0xff) != 0xff) \ {\ REGISTER_PC -= 3; \ }\ else \ { \ REGISTER_B -= 0x100;\ REGISTER_B &= 0xff00; \ if ((REGISTER_B & 0xff00) != 0xff00)\ { \ REGISTER_PC -= 3;\ } \ } #endif #else #if FLAG_SET_X #define OP_MVP() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ REGISTER_A |= REGISTER_B; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_8(REGISTER_X-1); \ REGISTER_Y = MAKE_UINT_8(REGISTER_Y-1); \ REGISTER_A--; \ if ((REGISTER_A&0xffff) != 0xffff) \ {\ REGISTER_PC -= 3; \ } #else #define OP_MVP() \ DST = OPER_8_IMM(cpustate)<<16; \ SRC = OPER_8_IMM(cpustate)<<16; \ REGISTER_DB = DST; \ REGISTER_A |= REGISTER_B; \ CLK(7); \ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \ REGISTER_X = MAKE_UINT_16(REGISTER_X-1); \ REGISTER_Y = MAKE_UINT_16(REGISTER_Y-1); \ REGISTER_A--; \ if ((REGISTER_A&0xffff) != 0xffff) \ {\ REGISTER_PC -= 3; \ } #endif #endif /* M6502 No Operation */ #undef OP_NOP #define OP_NOP() \ CLK(CLK_OP + CLK_IMPLIED) /* M6502 Logical OR operand to accumulator */ #undef OP_ORA #if FLAG_SET_M #define OP_ORA(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ FLAG_N = FLAG_Z = REGISTER_A |= OPER_8_ ## MODE(cpustate) #else #define OP_ORA(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ FLAG_Z = REGISTER_A |= OPER_16_##MODE(cpustate); \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* G65816 Push Effective Address */ #undef OP_PEA #define OP_PEA() \ CLK(CLK_OP + CLK_R16 + CLK_W16); \ g65816i_push_16(cpustate, OPER_16_IMM(cpustate)) /* G65816 Push Effective Indirect Address */ #undef OP_PEI #define OP_PEI() \ CLK(CLK_OP + CLK_R16 + CLK_W16 + CLK_D); \ g65816i_push_16(cpustate, EA_DI(cpustate)) /* G65816 Push Effective PC-Relative Address */ #undef OP_PER #define OP_PER() \ CLK(CLK_OP + CLK_R16 + CLK_W16 + 1); \ SRC = OPER_16_IMM(cpustate); \ g65816i_push_16(cpustate, REGISTER_PC + SRC) /* M6502 Push accumulator to the stack */ #undef OP_PHA #if FLAG_SET_M #define OP_PHA() \ CLK(CLK_OP + CLK_W8 + 1); \ g65816i_push_8(cpustate, REGISTER_A) #else #define OP_PHA() \ CLK(CLK_OP + CLK_W16 + 1); \ g65816i_push_16(cpustate, REGISTER_A) #endif /* M6502 Push index register to the stack */ #undef OP_PHX #if FLAG_SET_X #define OP_PHX(REG) \ CLK(CLK_OP + CLK_W8 + 1); \ g65816i_push_8(cpustate, REG) #else #define OP_PHX(REG) \ CLK(CLK_OP + CLK_W16 + 1); \ g65816i_push_16(cpustate, REG) #endif /* G65816 Push data bank register */ #undef OP_PHB #define OP_PHB() \ CLK(CLK_OP + CLK_W8 + 1); \ g65816i_push_8(cpustate, REGISTER_DB>>16) /* G65816 Push direct register */ #undef OP_PHD #define OP_PHD() \ CLK(CLK_OP + CLK_W16 + 1); \ g65816i_push_16(cpustate, REGISTER_D) /* G65816 Push program bank register */ #undef OP_PHK #define OP_PHK() \ CLK(CLK_OP + CLK_W8 + 1); \ g65816i_push_8(cpustate, REGISTER_PB>>16) /* M6502 Push the Processor Status Register to the stack */ #undef OP_PHP #define OP_PHP() \ CLK(CLK_OP + CLK_W8 + 1); \ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate)) /* M6502 Pull accumulator from the stack */ #undef OP_PLA #if FLAG_SET_M #define OP_PLA() \ CLK(CLK_OP + CLK_R8 + 2); \ FLAG_N = FLAG_Z = REGISTER_A = g65816i_pull_8(cpustate) #else #define OP_PLA() \ CLK(CLK_OP + CLK_R16 + 2); \ FLAG_Z = REGISTER_A = g65816i_pull_16(cpustate); \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* M6502 Pull index register from the stack */ #undef OP_PLX #if FLAG_SET_X #define OP_PLX(REG) \ CLK(CLK_OP + CLK_R8 + 2); \ FLAG_N = FLAG_Z = REG = g65816i_pull_8(cpustate) #else #define OP_PLX(REG) \ CLK(CLK_OP + CLK_R16 + 2); \ FLAG_Z = REG = g65816i_pull_16(cpustate); \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* G65816 Pull data bank register */ #undef OP_PLB #define OP_PLB() \ CLK(CLK_OP + CLK_R8 + 2); \ FLAG_N = FLAG_Z = g65816i_pull_8(cpustate); \ REGISTER_DB = FLAG_Z << 16 /* G65816 Pull direct register */ #undef OP_PLD #define OP_PLD() \ CLK(CLK_OP + CLK_R16 + 2); \ FLAG_Z = REGISTER_D = g65816i_pull_16(cpustate); \ FLAG_N = NFLAG_16(FLAG_Z) /* M6502 Pull the Processor Status Register from the stack */ #undef OP_PLP #define OP_PLP() \ CLK(CLK_OP + CLK_R8 + 2); \ g65816i_set_reg_p(cpustate, g65816i_pull_8(cpustate)) /* G65816 Reset Program status word */ #undef OP_REP #define OP_REP() \ CLK(CLK_OP + CLK_R8 + 1); \ g65816i_set_reg_p(cpustate, g65816i_get_reg_p(cpustate) & ~OPER_8_IMM(cpustate)) /* M6502 Rotate Left the accumulator */ #undef OP_ROL #if FLAG_SET_M #define OP_ROL() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_C = (REGISTER_A<<1) | CFLAG_AS_1(); \ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(FLAG_C) #else #define OP_ROL() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_C = (REGISTER_A<<1) | CFLAG_AS_1(); \ FLAG_Z = REGISTER_A = MAKE_UINT_16(FLAG_C); \ FLAG_N = NFLAG_16(FLAG_C); \ FLAG_C = CFLAG_16(FLAG_C) #endif /* M6502 Rotate Left an operand */ #undef OP_ROLM #if FLAG_SET_M #define OP_ROLM(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_C = (read_8_##MODE(DST)<<1) | CFLAG_AS_1(); \ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ write_8_##MODE(DST, FLAG_Z) #else #define OP_ROLM(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_C = (read_16_##MODE(DST)<<1) | CFLAG_AS_1(); \ FLAG_Z = MAKE_UINT_16(FLAG_C); \ FLAG_N = NFLAG_16(FLAG_C); \ FLAG_C = CFLAG_16(FLAG_C); \ write_16_##MODE(DST, FLAG_Z) #endif /* M6502 Rotate Right the accumulator */ #undef OP_ROR #if FLAG_SET_M #define OP_ROR() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_A |= FLAG_C & 0x100; \ FLAG_C = REGISTER_A << 8; \ FLAG_N = FLAG_Z = REGISTER_A >>= 1 #else #define OP_ROR() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_A |= (FLAG_C<<8) & 0x10000; \ FLAG_C = REGISTER_A << 8; \ FLAG_Z = REGISTER_A >>= 1; \ FLAG_N = NFLAG_16(REGISTER_A) #endif /* M6502 Rotate Right an operand */ #undef OP_RORM #if FLAG_SET_M #define OP_RORM(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = read_8_##MODE(DST) | (FLAG_C & 0x100); \ FLAG_C = FLAG_Z << 8; \ FLAG_N = FLAG_Z >>= 1; \ write_8_##MODE(DST, FLAG_Z) #else #define OP_RORM(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = read_16_##MODE(DST) | ((FLAG_C<<8) & 0x10000); \ FLAG_C = FLAG_Z << 8; \ FLAG_Z >>= 1; \ FLAG_N = NFLAG_16(FLAG_Z); \ write_16_##MODE(DST, FLAG_Z) #endif /* M6502 Return from Interrupt */ #undef OP_RTI #if FLAG_SET_E #define OP_RTI() \ CLK(7); \ g65816i_set_reg_p(cpustate, g65816i_pull_8(cpustate)); \ g65816i_jump_16(cpustate, g65816i_pull_16(cpustate)) #else #define OP_RTI() \ CLK(8); \ g65816i_set_reg_p(cpustate, g65816i_pull_8(cpustate)); \ g65816i_jump_16(cpustate, g65816i_pull_16(cpustate)); \ REGISTER_PB = g65816i_pull_8(cpustate) << 16 #endif /* G65816 Return from Subroutine Long */ /* Unusual behavior: Gets PC and increments */ #undef OP_RTL #define OP_RTL() \ CLK(6); \ g65816i_jump_24(cpustate, g65816i_pull_24(cpustate)) /* M6502 Return from Subroutine */ /* Unusual behavior: Gets PC and increments */ #undef OP_RTS #define OP_RTS() \ CLK(6); \ g65816i_jump_16(cpustate, g65816i_pull_16(cpustate)+1) /* M6502 Subtract with Carry */ /* Unusual behavior: C flag is inverted */ #undef OP_SBC #if FLAG_SET_M #define OP_SBC(MODE) \ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ SRC = OPER_8_##MODE(cpustate); \ if(!FLAG_D) \ { \ FLAG_C = ~FLAG_C; \ FLAG_C = REGISTER_A - SRC - CFLAG_AS_1(); \ FLAG_V = VFLAG_SUB_8(SRC, REGISTER_A, FLAG_C); \ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(FLAG_C); \ FLAG_C = ~FLAG_C; \ BREAKOUT; \ } \ else \ { \ INT32 result, r0, r1, carry; \ r0 = REGISTER_A; \ r1 = SRC; \ r1 ^= 0xff; \ carry = CFLAG_AS_1(); \ result = (r0 & 0x0f) + (r1 & 0x0f) + (carry << 0); \ if (result <= 0x0f) result -= 0x06; \ carry = result > 0x0f; \ result = (r0 & 0xf0) + (r1 & 0xf0) + (carry << 4) + (result & 0x0f); \ FLAG_V = ~(r0 ^ r1) & (r0 ^ result) & 0x80; \ if (result <= 0xff) result -= 0x60; \ FLAG_C = (result > 0xff) ? 0x100 : 0; \ FLAG_N = (result & 0x80); \ FLAG_Z = REGISTER_A = MAKE_UINT_8(result); \ } #else #define OP_SBC(MODE) \ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ SRC = OPER_16_##MODE(cpustate); \ INT32 result, r0, r1, carry; \ r0 = REGISTER_A; \ r1 = SRC; \ r1 ^= 0xffff; \ carry = CFLAG_AS_1(); \ if (!FLAG_D) \ { \ result = r0 + r1 + carry; \ } \ else \ { \ result = (r0 & 0x000f) + (r1 & 0x000f) + (carry << 0); \ if(result <= 0x000f) result -= 0x0006; \ carry = result > 0x000f; \ result = (r0 & 0x00f0) + (r1 & 0x00f0) + (carry << 4) + (result & 0x000f); \ if(result <= 0x00ff) result -= 0x0060; \ carry = result > 0x00ff; \ result = (r0 & 0x0f00) + (r1 & 0x0f00) + (carry << 8) + (result & 0x00ff); \ if(result <= 0x0fff) result -= 0x0600; \ carry = result > 0x0fff; \ result = (r0 & 0xf000) + (r1 & 0xf000) + (carry << 12) + (result & 0x0fff); \ } \ FLAG_V = ~(r0 ^ r1) & (r0 ^ result) & 0x8000; \ FLAG_V >>= 8; \ if (FLAG_D && result <= 0xffff) result -= 0x6000; \ FLAG_C = (result > 0xffff) ? 0x100 : 0; \ FLAG_Z = REGISTER_A = MAKE_UINT_16(result); \ FLAG_N = NFLAG_16(REGISTER_A); #endif /* M6502 Set Carry flag */ #undef OP_SEC #define OP_SEC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_C = CFLAG_SET /* M6502 Set Decimal flag */ #undef OP_SED #define OP_SED() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_D = DFLAG_SET /* M6502 Set Interrupt Mask flag */ #undef OP_SEI #define OP_SEI() \ CLK(CLK_OP + CLK_IMPLIED); \ g65816i_set_flag_i(cpustate, IFLAG_SET) /* G65816 Set Program status word */ #undef OP_SEP #define OP_SEP() \ CLK(CLK_OP + CLK_R8 + 1); \ g65816i_set_reg_p(cpustate, g65816i_get_reg_p(cpustate) | OPER_8_IMM(cpustate)) /* M6502 Store accumulator to memory */ #undef OP_STA #if FLAG_SET_M #define OP_STA(MODE) \ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \ write_8_##MODE(EA_##MODE(cpustate), REGISTER_A) #else #define OP_STA(MODE) \ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \ write_16_##MODE(EA_##MODE(cpustate), REGISTER_A) #endif /* M6502 Store index register to memory */ #undef OP_STX #if FLAG_SET_X #define OP_STX(REG, MODE) \ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \ write_8_##MODE(EA_##MODE(cpustate), REG) #else #define OP_STX(REG, MODE) \ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \ write_16_##MODE(EA_##MODE(cpustate), REG) #endif /* M6502 Store zero to memory */ #undef OP_STZ #if FLAG_SET_M #define OP_STZ(MODE) \ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \ write_8_##MODE(EA_##MODE(cpustate), 0) #else #define OP_STZ(MODE) \ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \ write_16_##MODE(EA_##MODE(cpustate), 0) #endif /* G65816 Stop the clock */ #undef OP_STP #define OP_STP() \ USE_ALL_CLKS(); \ CPU_STOPPED |= STOP_LEVEL_STOP /* M6502 Transfer accumulator to index */ #undef OP_TAX #if FLAG_SET_M #if FLAG_SET_X #define OP_TAX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REG = REGISTER_A; \ FLAG_N = NFLAG_8(FLAG_Z) #else /* FLAG_SET_X */ #define OP_TAX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REG = REGISTER_B | REGISTER_A; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* FLAG_SET_X */ #else /* FLAG_SET_M */ #if FLAG_SET_X #define OP_TAX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REG = MAKE_UINT_8(REGISTER_A); \ FLAG_N = NFLAG_8(FLAG_Z) #else /* FLAG_SET_X */ #define OP_TAX(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REG = REGISTER_A; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* FLAG_SET_X */ #endif /* FLAG_SET_M */ /* M6502 Transfer index to accumulator */ #undef OP_TXA #if FLAG_SET_M #define OP_TXA(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_A = MAKE_UINT_8(REG); \ FLAG_N = NFLAG_8(FLAG_Z) #else #define OP_TXA(REG) \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_A = REG; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* G65816 Transfer C to direct register */ #undef OP_TCD #if FLAG_SET_M #define OP_TCD() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_D = REGISTER_A | REGISTER_B; \ FLAG_N = NFLAG_16(FLAG_Z) #else #define OP_TCD() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_D = REGISTER_A; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* G65816 Transfer direct register to C */ #undef OP_TDC #if FLAG_SET_M #define OP_TDC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_D; \ FLAG_N = NFLAG_16(FLAG_Z); \ REGISTER_A = MAKE_UINT_8(REGISTER_D); \ REGISTER_B = REGISTER_D & 0xff00 #else #define OP_TDC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_A = REGISTER_D; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* G65816 Transfer C to stack pointer */ #undef OP_TCS #if FLAG_SET_E #define OP_TCS() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_S = MAKE_UINT_8(REGISTER_A) | 0x100 #else #define OP_TCS() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_S = REGISTER_A | REGISTER_B #endif /* G65816 Transfer stack pointer to C */ #undef OP_TSC #if FLAG_SET_M #define OP_TSC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_S; \ FLAG_N = NFLAG_16(FLAG_Z); \ REGISTER_A = MAKE_UINT_8(REGISTER_S); \ REGISTER_B = REGISTER_S & 0xff00 #else #define OP_TSC() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_A = REGISTER_S; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* M6502 Transfer stack pointer to X */ #undef OP_TSX #if FLAG_SET_X #define OP_TSX() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_X = MAKE_UINT_8(REGISTER_S); \ FLAG_N = NFLAG_8(FLAG_Z) #else #define OP_TSX() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_X = REGISTER_S; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* M6502 Transfer X to stack pointer */ #undef OP_TXS #if FLAG_SET_E #define OP_TXS() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_S = MAKE_UINT_8(REGISTER_X) | 0x100 #else #define OP_TXS() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_S = REGISTER_X #endif /* G65816 Transfer X to Y */ #undef OP_TXY #if FLAG_SET_X #define OP_TXY() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_Y = REGISTER_X; \ FLAG_N = NFLAG_8(FLAG_Z) #else #define OP_TXY() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_Y = REGISTER_X; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* G65816 Transfer Y to X */ #undef OP_TYX #if FLAG_SET_X #define OP_TYX() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_X = REGISTER_Y; \ FLAG_N = NFLAG_8(FLAG_Z) #else #define OP_TYX() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_X = REGISTER_Y; \ FLAG_N = NFLAG_16(FLAG_Z) #endif /* G65816 Test and reset bit */ #undef OP_TRB #if FLAG_SET_M #define OP_TRB(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = read_8_##MODE(DST); \ write_8_##MODE(DST, FLAG_Z & ~REGISTER_A); \ FLAG_Z &= REGISTER_A #else #define OP_TRB(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = read_16_##MODE(DST); \ write_16_##MODE(DST, FLAG_Z & ~REGISTER_A); \ FLAG_Z &= REGISTER_A #endif /* G65816 Test and set bit */ #undef OP_TSB #if FLAG_SET_M #define OP_TSB(MODE) \ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = read_8_##MODE(DST); \ write_8_##MODE(DST, FLAG_Z | REGISTER_A); \ FLAG_Z &= REGISTER_A #else #define OP_TSB(MODE) \ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ DST = EA_##MODE(cpustate); \ FLAG_Z = read_16_##MODE(DST); \ write_16_##MODE(DST, FLAG_Z | REGISTER_A); \ FLAG_Z &= REGISTER_A #endif /* G65816 Wait for interrupt */ #undef OP_WAI #define OP_WAI() \ USE_ALL_CLKS(); \ CPU_STOPPED |= STOP_LEVEL_WAI /* G65816 William D. Mensch, JR. (65816 designer) - future expansion */ #undef OP_WDM #define OP_WDM() \ CLK(CLK_OP + CLK_IMPLIED); \ REGISTER_PC++ /* G65816 Exchange accum high and low bytes */ #undef OP_XBA #if FLAG_SET_M #define OP_XBA() \ CLK(CLK_OP + CLK_IMPLIED); \ FLAG_Z = REGISTER_B>>8; \ REGISTER_B = REGISTER_A<<8; \ REGISTER_A = FLAG_Z; \ FLAG_N = NFLAG_8(FLAG_Z) #else #define OP_XBA() \ CLK(CLK_OP + CLK_IMPLIED + 1); \ FLAG_Z = REGISTER_A >> 8; \ REGISTER_A = MAKE_UINT_16(REGISTER_A<<8) | FLAG_Z; \ FLAG_N = NFLAG_8(FLAG_Z) #endif /* G65816 Exchange carry and emulation bits */ #undef OP_XCE #define OP_XCE() \ CLK(CLK_OP + CLK_IMPLIED); \ SRC = CFLAG_AS_1(); \ FLAG_C = FLAG_E<<8; \ g65816i_set_flag_e(cpustate, SRC) /* ======================================================================== */ /* ======================== OPCODE & FUNCTION TABLES ====================== */ /* ======================================================================== */ #undef OP #undef O #undef TABLE_OPCODES #undef TABLE_FUNCTION #if FLAG_SET_E #define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _E(g65816i_cpu_struct *cpustate) {OPERATION;} #define O(CODE) g65816i_ ## CODE ## _E #define TABLE_OPCODES void (*const g65816i_opcodes_E[256])(g65816i_cpu_struct *cpustate) #define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _E ARGS #else #if !FLAG_SET_M && !FLAG_SET_X #define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M0X0(g65816i_cpu_struct *cpustate) {OPERATION;} #define O(CODE) g65816i_ ## CODE ## _M0X0 #define TABLE_OPCODES void (*const g65816i_opcodes_M0X0[256])(g65816i_cpu_struct *cpustate) #define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M0X0 ARGS #elif !FLAG_SET_M && FLAG_SET_X #define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M0X1(g65816i_cpu_struct *cpustate) {OPERATION;} #define O(CODE) g65816i_ ## CODE ## _M0X1 #define TABLE_OPCODES void (*const g65816i_opcodes_M0X1[256])(g65816i_cpu_struct *cpustate) #define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M0X1 ARGS #elif FLAG_SET_M && !FLAG_SET_X #define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M1X0(g65816i_cpu_struct *cpustate) {OPERATION;} #define O(CODE) g65816i_ ## CODE ## _M1X0 #define TABLE_OPCODES void (*const g65816i_opcodes_M1X0[256])(g65816i_cpu_struct *cpustate) #define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M1X0 ARGS #elif FLAG_SET_M && FLAG_SET_X #define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M1X1(g65816i_cpu_struct *cpustate) {OPERATION;} #define O(CODE) g65816i_ ## CODE ## _M1X1 #define TABLE_OPCODES void (*const g65816i_opcodes_M1X1[256])(g65816i_cpu_struct *cpustate) #define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M1X1 ARGS #endif #endif #define BREAKOUT return /* OP FUNCTION Comment */ OP(00, OP_BRK ( ) ) /* BRK */ OP(01, OP_ORA ( DXI ) ) /* ORA dxi */ OP(02, OP_COP ( ) ) /* COP (G) */ OP(03, OP_ORA ( S ) ) /* ORA s (G) */ OP(04, OP_TSB ( D ) ) /* TSB d (C) */ OP(05, OP_ORA ( D ) ) /* ORA d */ OP(06, OP_ASLM ( D ) ) /* ASL d */ OP(07, OP_ORA ( DLI ) ) /* ORA dli (G) */ OP(08, OP_PHP ( ) ) /* PHP */ OP(09, OP_ORA ( IMM ) ) /* ORA imm */ OP(0a, OP_ASL ( ) ) /* ASL acc */ OP(0b, OP_PHD ( ) ) /* PHD (G) */ OP(0c, OP_TSB ( A ) ) /* TSB a (C) */ OP(0d, OP_ORA ( A ) ) /* ORA a */ OP(0e, OP_ASLM ( A ) ) /* ASL a */ OP(0f, OP_ORA ( AL ) ) /* ORA al (G) */ OP(10, OP_BCC ( COND_PL() ) ) /* BPL */ OP(11, OP_ORA ( DIY ) ) /* ORA diy */ OP(12, OP_ORA ( DI ) ) /* ORA di (C) */ OP(13, OP_ORA ( SIY ) ) /* ORA siy (G) */ OP(14, OP_TRB ( D ) ) /* TRB d (C) */ OP(15, OP_ORA ( DX ) ) /* ORA dx */ OP(16, OP_ASLM ( DX ) ) /* ASL dx */ OP(17, OP_ORA ( DLIY ) ) /* ORA dliy(C) */ OP(18, OP_CLC ( ) ) /* CLC */ OP(19, OP_ORA ( AY ) ) /* ORA ay */ OP(1a, OP_INC ( ) ) /* INA (C) */ OP(1b, OP_TCS ( ) ) /* TCS (G) */ OP(1c, OP_TRB ( A ) ) /* TRB a (C) */ OP(1d, OP_ORA ( AX ) ) /* ORA ax */ OP(1e, OP_ASLM ( AX ) ) /* ASL ax */ OP(1f, OP_ORA ( ALX ) ) /* ORA alx (G) */ OP(20, OP_JSR ( A ) ) /* JSR a */ OP(21, OP_AND ( DXI ) ) /* AND dxi */ OP(22, OP_JSL ( AL ) ) /* JSL al (G) */ OP(23, OP_AND ( S ) ) /* AND s (G) */ OP(24, OP_BIT ( D ) ) /* BIT d */ OP(25, OP_AND ( D ) ) /* AND d */ OP(26, OP_ROLM ( D ) ) /* ROL d */ OP(27, OP_AND ( DLI ) ) /* AND dli (G) */ OP(28, OP_PLP ( ) ) /* PLP */ OP(29, OP_AND ( IMM ) ) /* AND imm */ OP(2a, OP_ROL ( ) ) /* ROL acc */ OP(2b, OP_PLD ( ) ) /* PLD (G) */ OP(2c, OP_BIT ( A ) ) /* BIT a */ OP(2d, OP_AND ( A ) ) /* AND a */ OP(2e, OP_ROLM ( A ) ) /* ROL a */ OP(2f, OP_AND ( AL ) ) /* AND al (G) */ OP(30, OP_BCC ( COND_MI() ) ) /* BMI */ OP(31, OP_AND ( DIY ) ) /* AND diy */ OP(32, OP_AND ( DI ) ) /* AND di (C) */ OP(33, OP_AND ( SIY ) ) /* AND siy */ OP(34, OP_BIT ( DX ) ) /* BIT dx (C) */ OP(35, OP_AND ( DX ) ) /* AND dx */ OP(36, OP_ROLM ( DX ) ) /* ROL dx */ OP(37, OP_AND ( DLIY ) ) /* AND dliy(G) */ OP(38, OP_SEC ( ) ) /* SEC */ OP(39, OP_AND ( AY ) ) /* AND ay */ OP(3a, OP_DEC ( ) ) /* DEA (C) */ OP(3b, OP_TSC ( ) ) /* TSC (G) */ OP(3c, OP_BIT ( AX ) ) /* BIT abx (C) */ OP(3d, OP_AND ( AX ) ) /* AND ax */ OP(3e, OP_ROLM ( AX ) ) /* ROL ax */ OP(3f, OP_AND ( ALX ) ) /* AND alx (G) */ OP(40, OP_RTI ( ) ) /* RTI */ OP(41, OP_EOR ( DXI ) ) /* EOR dxi */ OP(42, OP_WDM ( ) ) /* WDM */ OP(43, OP_EOR ( S ) ) /* EOR s (G) */ OP(44, OP_MVP ( ) ) /* MVP (G) */ OP(45, OP_EOR ( D ) ) /* EOR d */ OP(46, OP_LSRM ( D ) ) /* LSR d */ OP(47, OP_EOR ( DLI ) ) /* EOR dli (G) */ OP(48, OP_PHA ( ) ) /* PHA */ OP(49, OP_EOR ( IMM ) ) /* EOR imm */ OP(4a, OP_LSR ( ) ) /* LSR acc */ OP(4b, OP_PHK ( ) ) /* PHK (G) */ OP(4c, OP_JMP ( A ) ) /* JMP a */ OP(4d, OP_EOR ( A ) ) /* EOR a */ OP(4e, OP_LSRM ( A ) ) /* LSR a */ OP(4f, OP_EOR ( AL ) ) /* EOR al (G) */ OP(50, OP_BCC ( COND_VC() ) ) /* BVC */ OP(51, OP_EOR ( DIY ) ) /* EOR diy */ OP(52, OP_EOR ( DI ) ) /* EOR di (C) */ OP(53, OP_EOR ( SIY ) ) /* EOR siy (G) */ OP(54, OP_MVN ( ) ) /* MVN (G) */ OP(55, OP_EOR ( DX ) ) /* EOR dx */ OP(56, OP_LSRM ( DX ) ) /* LSR dx */ OP(57, OP_EOR ( DLIY ) ) /* EOR dliy(G) */ OP(58, OP_CLI ( ) ) /* CLI */ OP(59, OP_EOR ( AY ) ) /* EOR ay */ OP(5a, OP_PHX ( REGISTER_Y ) ) /* PHY (C) */ OP(5b, OP_TCD ( ) ) /* TCD (G) */ OP(5c, OP_JMPAL( ) ) /* JMP al (G) */ OP(5d, OP_EOR ( AX ) ) /* EOR ax */ OP(5e, OP_LSRM ( AX ) ) /* LSR ax */ OP(5f, OP_EOR ( ALX ) ) /* EOR alx (G) */ OP(60, OP_RTS ( ) ) /* RTS */ OP(61, OP_ADC ( DXI ) ) /* ADC dxi */ OP(62, OP_PER ( ) ) /* PER (G) */ OP(63, OP_ADC ( S ) ) /* ADC s (G) */ OP(64, OP_STZ ( D ) ) /* STZ d (C) */ OP(65, OP_ADC ( D ) ) /* ADC d */ OP(66, OP_RORM ( D ) ) /* ROR d */ OP(67, OP_ADC ( DLI ) ) /* ADC dli (G) */ OP(68, OP_PLA ( ) ) /* PLA */ OP(69, OP_ADC ( IMM ) ) /* ADC imm */ OP(6a, OP_ROR ( ) ) /* ROR acc */ OP(6b, OP_RTL ( ) ) /* RTL (G) */ OP(6c, OP_JMP ( AI ) ) /* JMP ai */ OP(6d, OP_ADC ( A ) ) /* ADC a */ OP(6e, OP_RORM ( A ) ) /* ROR a */ OP(6f, OP_ADC ( AL ) ) /* ADC al (G) */ OP(70, OP_BCC ( COND_VS() ) ) /* BVS */ OP(71, OP_ADC ( DIY ) ) /* ADC diy */ OP(72, OP_ADC ( DI ) ) /* ADC di (G) */ OP(73, OP_ADC ( SIY ) ) /* ADC siy (G) */ OP(74, OP_STZ ( DX ) ) /* STZ dx (C) */ OP(75, OP_ADC ( DX ) ) /* ADC dx */ OP(76, OP_RORM ( DX ) ) /* ROR dx */ OP(77, OP_ADC ( DLIY ) ) /* ADC dliy(G) */ OP(78, OP_SEI ( ) ) /* SEI */ OP(79, OP_ADC ( AY ) ) /* ADC ay */ OP(7a, OP_PLX ( REGISTER_Y ) ) /* PLY (C) */ OP(7b, OP_TDC ( ) ) /* TDC (G) */ OP(7c, OP_JMPAXI( ) ) /* JMP axi (C) */ OP(7d, OP_ADC ( AX ) ) /* ADC ax */ OP(7e, OP_RORM ( AX ) ) /* ROR ax */ OP(7f, OP_ADC ( ALX ) ) /* ADC alx (G) */ OP(80, OP_BRA ( ) ) /* BRA (C) */ OP(81, OP_STA ( DXI ) ) /* STA dxi */ OP(82, OP_BRL ( ) ) /* BRL (G) */ OP(83, OP_STA ( S ) ) /* STA s (G) */ OP(84, OP_STX ( REGISTER_Y, D ) ) /* STY d */ OP(85, OP_STA ( D ) ) /* STA d */ OP(86, OP_STX ( REGISTER_X, D ) ) /* STX d */ OP(87, OP_STA ( DLI ) ) /* STA dli (G) */ OP(88, OP_DECX ( REGISTER_Y ) ) /* DEY */ OP(89, OP_BITI ( ) ) /* BIT imm (C) */ OP(8a, OP_TXA ( REGISTER_X ) ) /* TXA */ OP(8b, OP_PHB ( ) ) /* PHB (G) */ OP(8c, OP_STX ( REGISTER_Y, A ) ) /* STY a */ OP(8d, OP_STA ( A ) ) /* STA a */ OP(8e, OP_STX ( REGISTER_X, A ) ) /* STX a */ OP(8f, OP_STA ( AL ) ) /* STA al (G) */ OP(90, OP_BCC ( COND_CC() ) ) /* BCC */ OP(91, OP_STA ( DIY ) ) /* STA diy */ OP(92, OP_STA ( DI ) ) /* STA di (C) */ OP(93, OP_STA ( SIY ) ) /* STA siy (G) */ OP(94, OP_STX ( REGISTER_Y, DX ) ) /* STY dx */ OP(95, OP_STA ( DX ) ) /* STA dx */ OP(96, OP_STX ( REGISTER_X, DY ) ) /* STX dy */ OP(97, OP_STA ( DLIY ) ) /* STA dliy(G) */ OP(98, OP_TXA ( REGISTER_Y ) ) /* TYA */ OP(99, OP_STA ( AY ) ) /* STA ay */ OP(9a, OP_TXS ( ) ) /* TXS */ OP(9b, OP_TXY ( ) ) /* TXY (G) */ OP(9c, OP_STZ ( A ) ) /* STZ a (C) */ OP(9d, OP_STA ( AX ) ) /* STA ax */ OP(9e, OP_STZ ( AX ) ) /* STZ ax (C) */ OP(9f, OP_STA ( ALX ) ) /* STA alx (G) */ OP(a0, OP_LDX ( REGISTER_Y, IMM ) ) /* LDY imm */ OP(a1, OP_LDA ( DXI ) ) /* LDA dxi */ OP(a2, OP_LDX ( REGISTER_X, IMM ) ) /* LDX imm */ OP(a3, OP_LDA ( S ) ) /* LDA s (G) */ OP(a4, OP_LDX ( REGISTER_Y, D ) ) /* LDY d */ OP(a5, OP_LDA ( D ) ) /* LDA d */ OP(a6, OP_LDX ( REGISTER_X, D ) ) /* LDX d */ OP(a7, OP_LDA ( DLI ) ) /* LDA dli (G) */ OP(a8, OP_TAX ( REGISTER_Y ) ) /* TAY */ OP(a9, OP_LDA ( IMM ) ) /* LDA imm */ OP(aa, OP_TAX ( REGISTER_X ) ) /* TAX */ OP(ab, OP_PLB ( ) ) /* PLB (G) */ OP(ac, OP_LDX ( REGISTER_Y, A ) ) /* LDY a */ OP(ad, OP_LDA ( A ) ) /* LDA a */ OP(ae, OP_LDX ( REGISTER_X, A ) ) /* LDX a */ OP(af, OP_LDA ( AL ) ) /* LDA al (G) */ OP(b0, OP_BCC ( COND_CS() ) ) /* BCS */ OP(b1, OP_LDA ( DIY ) ) /* LDA diy */ OP(b2, OP_LDA ( DI ) ) /* LDA di (C) */ OP(b3, OP_LDA ( SIY ) ) /* LDA siy (G) */ OP(b4, OP_LDX ( REGISTER_Y, DX ) ) /* LDY dx */ OP(b5, OP_LDA ( DX ) ) /* LDA dx */ OP(b6, OP_LDX ( REGISTER_X, DY ) ) /* LDX dy */ OP(b7, OP_LDA ( DLIY ) ) /* LDA dliy(G) */ OP(b8, OP_CLV ( ) ) /* CLV */ OP(b9, OP_LDA ( AY ) ) /* LDA ay */ OP(ba, OP_TSX ( ) ) /* TSX */ OP(bb, OP_TYX ( ) ) /* TYX (G) */ OP(bc, OP_LDX ( REGISTER_Y, AX ) ) /* LDY ax */ OP(bd, OP_LDA ( AX ) ) /* LDA ax */ OP(be, OP_LDX ( REGISTER_X, AY ) ) /* LDX ay */ OP(bf, OP_LDA ( ALX ) ) /* LDA alx (G) */ OP(c0, OP_CMPX ( REGISTER_Y, IMM ) ) /* CPY imm */ OP(c1, OP_CMP ( DXI ) ) /* CMP dxi */ OP(c2, OP_REP ( ) ) /* REP (G) */ OP(c3, OP_CMP ( S ) ) /* CMP s (G) */ OP(c4, OP_CMPX ( REGISTER_Y, D ) ) /* CPY d */ OP(c5, OP_CMP ( D ) ) /* CMP d */ OP(c6, OP_DECM ( D ) ) /* DEC d */ OP(c7, OP_CMP ( DLI ) ) /* CMP dli (G) */ OP(c8, OP_INCX ( REGISTER_Y ) ) /* INY */ OP(c9, OP_CMP ( IMM ) ) /* CMP imm */ OP(ca, OP_DECX ( REGISTER_X ) ) /* DEX */ OP(cb, OP_WAI ( ) ) /* WAI (G) */ OP(cc, OP_CMPX ( REGISTER_Y, A ) ) /* CPY a */ OP(cd, OP_CMP ( A ) ) /* CMP a */ OP(ce, OP_DECM ( A ) ) /* DEC a */ OP(cf, OP_CMP ( AL ) ) /* CMP al (G) */ OP(d0, OP_BCC ( COND_NE() ) ) /* BNE */ OP(d1, OP_CMP ( DIY ) ) /* CMP diy */ OP(d2, OP_CMP ( DI ) ) /* CMP di (C) */ OP(d3, OP_CMP ( SIY ) ) /* CMP siy (G) */ OP(d4, OP_PEI ( ) ) /* PEI (G) */ OP(d5, OP_CMP ( DX ) ) /* CMP dx */ OP(d6, OP_DECM ( DX ) ) /* DEC dx */ OP(d7, OP_CMP ( DLIY ) ) /* CMP dliy(G) */ OP(d8, OP_CLD ( ) ) /* CLD */ OP(d9, OP_CMP ( AY ) ) /* CMP ay */ OP(da, OP_PHX ( REGISTER_X ) ) /* PHX (C) */ OP(db, OP_STP ( ) ) /* STP (G) */ OP(dc, OP_JMLAI( ) ) /* JML ai (G) */ OP(dd, OP_CMP ( AX ) ) /* CMP ax */ OP(de, OP_DECM ( AX ) ) /* DEC ax */ OP(df, OP_CMP ( ALX ) ) /* CMP alx (G) */ OP(e0, OP_CMPX ( REGISTER_X, IMM ) ) /* CPX imm */ OP(e1, OP_SBC ( DXI ) ) /* SBC dxi */ OP(e2, OP_SEP ( ) ) /* SEP imm (G) */ OP(e3, OP_SBC ( S ) ) /* SBC s (G) */ OP(e4, OP_CMPX ( REGISTER_X, D ) ) /* CPX d */ OP(e5, OP_SBC ( D ) ) /* SBC d */ OP(e6, OP_INCM ( D ) ) /* INC d */ OP(e7, OP_SBC ( DLI ) ) /* SBC dli (G) */ OP(e8, OP_INCX ( REGISTER_X ) ) /* INX */ OP(e9, OP_SBC ( IMM ) ) /* SBC imm */ OP(ea, OP_NOP ( ) ) /* NOP */ OP(eb, OP_XBA ( ) ) /* XBA (G) */ OP(ec, OP_CMPX ( REGISTER_X, A ) ) /* CPX a */ OP(ed, OP_SBC ( A ) ) /* SBC a */ OP(ee, OP_INCM ( A ) ) /* INC a */ OP(ef, OP_SBC ( AL ) ) /* SBC al (G) */ OP(f0, OP_BCC ( COND_EQ() ) ) /* BEQ */ OP(f1, OP_SBC ( DIY ) ) /* SBC diy */ OP(f2, OP_SBC ( DI ) ) /* SBC di (C) */ OP(f3, OP_SBC ( SIY ) ) /* SBC siy (G) */ OP(f4, OP_PEA ( ) ) /* PEA (G) */ OP(f5, OP_SBC ( DX ) ) /* SBC dx */ OP(f6, OP_INCM ( DX ) ) /* INC dx */ OP(f7, OP_SBC ( DLIY ) ) /* SBC dliy(G) */ OP(f8, OP_SED ( ) ) /* SED */ OP(f9, OP_SBC ( AY ) ) /* SBC ay */ OP(fa, OP_PLX ( REGISTER_X ) ) /* PLX (C) */ OP(fb, OP_XCE ( ) ) /* XCE (G) */ OP(fc, OP_JSRAXI( ) ) /* JSR axi (G) */ OP(fd, OP_SBC ( AX ) ) /* SBC ax */ OP(fe, OP_INCM ( AX ) ) /* INC ax */ OP(ff, OP_SBC ( ALX ) ) /* SBC alx (G) */ extern TABLE_OPCODES; TABLE_OPCODES = { O(00),O(01),O(02),O(03),O(04),O(05),O(06),O(07), O(08),O(09),O(0a),O(0b),O(0c),O(0d),O(0e),O(0f), O(10),O(11),O(12),O(13),O(14),O(15),O(16),O(17), O(18),O(19),O(1a),O(1b),O(1c),O(1d),O(1e),O(1f), O(20),O(21),O(22),O(23),O(24),O(25),O(26),O(27), O(28),O(29),O(2a),O(2b),O(2c),O(2d),O(2e),O(2f), O(30),O(31),O(32),O(33),O(34),O(35),O(36),O(37), O(38),O(39),O(3a),O(3b),O(3c),O(3d),O(3e),O(3f), O(40),O(41),O(42),O(43),O(44),O(45),O(46),O(47), O(48),O(49),O(4a),O(4b),O(4c),O(4d),O(4e),O(4f), O(50),O(51),O(52),O(53),O(54),O(55),O(56),O(57), O(58),O(59),O(5a),O(5b),O(5c),O(5d),O(5e),O(5f), O(60),O(61),O(62),O(63),O(64),O(65),O(66),O(67), O(68),O(69),O(6a),O(6b),O(6c),O(6d),O(6e),O(6f), O(70),O(71),O(72),O(73),O(74),O(75),O(76),O(77), O(78),O(79),O(7a),O(7b),O(7c),O(7d),O(7e),O(7f), O(80),O(81),O(82),O(83),O(84),O(85),O(86),O(87), O(88),O(89),O(8a),O(8b),O(8c),O(8d),O(8e),O(8f), O(90),O(91),O(92),O(93),O(94),O(95),O(96),O(97), O(98),O(99),O(9a),O(9b),O(9c),O(9d),O(9e),O(9f), O(a0),O(a1),O(a2),O(a3),O(a4),O(a5),O(a6),O(a7), O(a8),O(a9),O(aa),O(ab),O(ac),O(ad),O(ae),O(af), O(b0),O(b1),O(b2),O(b3),O(b4),O(b5),O(b6),O(b7), O(b8),O(b9),O(ba),O(bb),O(bc),O(bd),O(be),O(bf), O(c0),O(c1),O(c2),O(c3),O(c4),O(c5),O(c6),O(c7), O(c8),O(c9),O(ca),O(cb),O(cc),O(cd),O(ce),O(cf), O(d0),O(d1),O(d2),O(d3),O(d4),O(d5),O(d6),O(d7), O(d8),O(d9),O(da),O(db),O(dc),O(dd),O(de),O(df), O(e0),O(e1),O(e2),O(e3),O(e4),O(e5),O(e6),O(e7), O(e8),O(e9),O(ea),O(eb),O(ec),O(ed),O(ee),O(ef), O(f0),O(f1),O(f2),O(f3),O(f4),O(f5),O(f6),O(f7), O(f8),O(f9),O(fa),O(fb),O(fc),O(fd),O(fe),O(ff) }; /* Assert or clear a line on the CPU */ TABLE_FUNCTION(void, set_line, (g65816i_cpu_struct *cpustate, int line, int state)) { switch(line) { case G65816_LINE_IRQ: switch(state) { case CLEAR_LINE: LINE_IRQ = 0; return; case ASSERT_LINE: case HOLD_LINE: LINE_IRQ = 1; } if(FLAG_I) { if(CPU_STOPPED & STOP_LEVEL_WAI) { CPU_STOPPED &= ~STOP_LEVEL_WAI; } return; } return; case G65816_LINE_NMI: if(state == CLEAR_LINE) { LINE_NMI = 0; return; } if(!LINE_NMI) { LINE_NMI = 1; CPU_STOPPED &= ~STOP_LEVEL_WAI; if(!CPU_STOPPED) g65816i_interrupt_nmi(cpustate); } return; case G65816_LINE_SO: FLAG_V = VFLAG_SET; break; case G65816_LINE_RESET: case G65816_LINE_ABORT: case G65816_LINE_RDY: return; } LINE_IRQ=1; } /* Get a register from the CPU core */ TABLE_FUNCTION(uint, get_reg, (g65816i_cpu_struct *cpustate, int regnum)) { switch(regnum) { case G65816_A: return REGISTER_B | REGISTER_A; case G65816_X: return REGISTER_X; case G65816_Y: return REGISTER_Y; case STATE_GENSP: return REGISTER_S; case G65816_S: return REGISTER_S; case STATE_GENPC: return REGISTER_PC; case G65816_PC: return REGISTER_PC; case G65816_PB: return REGISTER_PB >> 16; case G65816_DB: return REGISTER_DB >> 16; case G65816_D: return REGISTER_D; case G65816_P: return g65816i_get_reg_p(cpustate); case G65816_NMI_STATE: return LINE_NMI; case G65816_IRQ_STATE: return LINE_IRQ; case STATE_GENPCBASE: return REGISTER_PPC; } return 0; } TABLE_FUNCTION(void, set_reg, (g65816i_cpu_struct *cpustate, int regnum, uint val)) { switch(regnum) { case STATE_GENPC: case G65816_PC: REGISTER_PC = MAKE_UINT_16(val); break; #if FLAG_SET_E case STATE_GENSP: case G65816_S: REGISTER_S = MAKE_UINT_8(val) | 0x100; break; #else case STATE_GENSP: case G65816_S: REGISTER_S = MAKE_UINT_16(val); break; #endif case G65816_P: g65816i_set_reg_p(cpustate, val); break; #if FLAG_SET_M case G65816_A: REGISTER_A = MAKE_UINT_8(val); REGISTER_B = val&0xff00; break; #else case G65816_A: REGISTER_A = MAKE_UINT_16(val); break; #endif #if FLAG_SET_X case G65816_X: REGISTER_X = MAKE_UINT_8(val); break; case G65816_Y: REGISTER_Y = MAKE_UINT_8(val); break; #else case G65816_X: REGISTER_X = MAKE_UINT_16(val); break; case G65816_Y: REGISTER_Y = MAKE_UINT_16(val); break; #endif case G65816_DB: REGISTER_DB = MAKE_UINT_8(val); break; case G65816_PB: REGISTER_PB = MAKE_UINT_8(val); break; case G65816_NMI_STATE: FTABLE_SET_LINE(cpustate, G65816_LINE_NMI, val == 0 ? CLEAR_LINE : ASSERT_LINE); break; case G65816_IRQ_STATE: FTABLE_SET_LINE(cpustate, G65816_LINE_IRQ, val == 0 ? CLEAR_LINE : ASSERT_LINE); break; } } INLINE int g65816i_correct_mode(g65816i_cpu_struct *cpustate) { #if EXECUTION_MODE == EXECUTION_MODE_E return (FLAG_E == EFLAG_SET); #elif EXECUTION_MODE == EXECUTION_MODE_M0X0 return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_CLEAR) && (FLAG_X == XFLAG_CLEAR); #elif EXECUTION_MODE == EXECUTION_MODE_M0X1 return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_CLEAR) && (FLAG_X == XFLAG_SET); #elif EXECUTION_MODE == EXECUTION_MODE_M1X0 return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_SET) && (FLAG_X == XFLAG_CLEAR); #elif EXECUTION_MODE == EXECUTION_MODE_M1X1 return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_SET) && (FLAG_X == XFLAG_SET); #else #error Invalid EXECUTION_MODE #endif } TABLE_FUNCTION(int, execute, (g65816i_cpu_struct *cpustate, int clocks)) { // do a check here also in case we're in STOP_WAI mode - this'll clear it when the IRQ happens g65816i_check_maskable_interrupt(cpustate); if (!CPU_STOPPED) { CLOCKS = clocks; do { /* Note that I'm doing a per-instruction interrupt * check until this core is working well enough * to start trying fancy stuff. */ g65816i_check_maskable_interrupt(cpustate); REGISTER_PPC = REGISTER_PC; G65816_CALL_DEBUGGER(REGISTER_PB | REGISTER_PC); REGISTER_PC++; REGISTER_IR = read_8_IMM(REGISTER_PB | REGISTER_PPC); FTABLE_OPCODES[REGISTER_IR](cpustate); } while((CLOCKS > 0) && g65816i_correct_mode(cpustate)); return clocks - CLOCKS; } return clocks; }