2015-02-15 19:10:27 +00:00
|
|
|
/*
|
2015-02-16 04:08:01 +00:00
|
|
|
* Apple // emulator for *nix
|
2015-02-15 19:10:27 +00:00
|
|
|
*
|
|
|
|
* This software package is subject to the GNU General Public License
|
|
|
|
* version 2 or later (your choice) as published by the Free Software
|
|
|
|
* Foundation.
|
|
|
|
*
|
|
|
|
* THERE ARE NO WARRANTIES WHATSOEVER.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 65c02 CPU opcodes emulated with ARM.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cpu-regs.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define DecodeFlags \
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65_flags_decode); \
|
|
|
|
ldrb F_Reg, [r1, r0];
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define EncodeFlags \
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65_flags_encode); \
|
2015-02-18 04:33:27 +00:00
|
|
|
ldrb r0, [r1, F_Reg];
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define CommonSaveCPUState \
|
|
|
|
/* save EA */ \
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r0, SYM(cpu65_ea); \
|
2015-02-15 19:10:27 +00:00
|
|
|
strh EffectiveAddr, [r0]; \
|
|
|
|
/* save stack pointer */ \
|
|
|
|
ldr r0, SYM(cpu65_sp); \
|
|
|
|
strb SP_Reg, [r0]; \
|
|
|
|
/* save X */ \
|
|
|
|
ldr r0, SYM(cpu65_x); \
|
|
|
|
strb X_Reg, [r0]; \
|
|
|
|
/* save Y */ \
|
|
|
|
ldr r0, SYM(cpu65_y); \
|
|
|
|
strb Y_Reg, [r0]; \
|
|
|
|
/* save A */ \
|
|
|
|
ldr r0, SYM(cpu65_a); \
|
|
|
|
strb A_Reg, [r0]; \
|
|
|
|
/* save flags */ \
|
|
|
|
EncodeFlags \
|
|
|
|
ldr r1, SYM(cpu65_f); \
|
|
|
|
strb r0, [r1]
|
|
|
|
|
|
|
|
// Tracing is necessary for some CPU tests and to verify operation against other emulators
|
|
|
|
#if CPU_TRACING
|
|
|
|
# define TRACE_PROLOGUE \
|
|
|
|
ldr r1, SYM(cpu65_pc); \
|
|
|
|
strh PC_Reg, [r1]; \
|
|
|
|
bl CALL(cpu65_trace_prologue);
|
|
|
|
# define TRACE_ARG \
|
|
|
|
bl CALL(cpu65_trace_arg);
|
|
|
|
# define TRACE_ARG1 \
|
|
|
|
bl CALL(cpu65_trace_arg1);
|
|
|
|
# define TRACE_ARG2 \
|
|
|
|
bl CALL(cpu65_trace_arg2);
|
|
|
|
# define TRACE_EPILOGUE \
|
|
|
|
CommonSaveCPUState; \
|
2015-02-19 07:08:16 +00:00
|
|
|
push {r0, EffectiveAddr, PC_Reg, lr}; \
|
2015-02-15 19:10:27 +00:00
|
|
|
bl CALL(cpu65_trace_epilogue); \
|
2015-02-19 07:08:16 +00:00
|
|
|
pop {r0, EffectiveAddr, PC_Reg, lr};
|
2015-02-15 19:10:27 +00:00
|
|
|
#else
|
|
|
|
# define TRACE_PROLOGUE
|
|
|
|
# define TRACE_ARG
|
|
|
|
# define TRACE_ARG1
|
|
|
|
# define TRACE_ARG2
|
|
|
|
# define TRACE_EPILOGUE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2015-02-19 07:08:16 +00:00
|
|
|
#define CPUStatsReset \
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65_opcode); \
|
2015-02-15 19:10:27 +00:00
|
|
|
strb r0, [r1]; /* r0 should be next opcode */ \
|
2015-02-16 04:08:01 +00:00
|
|
|
eor r9, r9, r9; \
|
|
|
|
ldr r1, SYM(cpu65_opcycles); \
|
2015-02-15 19:10:27 +00:00
|
|
|
strb r9, [r1]; \
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr r1, SYM(cpu65_rw); \
|
2015-02-15 19:10:27 +00:00
|
|
|
strb r9, [r1];
|
2015-02-19 07:08:16 +00:00
|
|
|
#define CPUStatsSetRead \
|
|
|
|
ldr r1, SYM(cpu65_rw); \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldrb r9, [r1]; \
|
2015-02-16 04:08:01 +00:00
|
|
|
orr r9, r9, #1; \
|
2015-02-15 19:10:27 +00:00
|
|
|
strb r9, [r1];
|
2015-02-19 07:08:16 +00:00
|
|
|
|
|
|
|
#define CPUStatsSetWrite \
|
|
|
|
ldr r1, SYM(cpu65_rw); \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldrb r9, [r1]; \
|
2015-02-16 04:08:01 +00:00
|
|
|
orr r9, r9, #2; \
|
2015-02-15 19:10:27 +00:00
|
|
|
strb r9, [r1]; \
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65_d); \
|
2015-02-15 19:10:27 +00:00
|
|
|
strb r0, [r1];
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// CPU (6502) helper macros
|
|
|
|
|
2015-02-19 07:08:16 +00:00
|
|
|
// Add 16bit x with <=16bit amt
|
2015-02-18 04:33:27 +00:00
|
|
|
#define AddUint16(x, amt) \
|
|
|
|
add x, x, amt; \
|
|
|
|
bic x, #0x10000;
|
|
|
|
|
2015-02-19 07:08:16 +00:00
|
|
|
// Increment 16bit x
|
2015-02-18 04:33:27 +00:00
|
|
|
#define IncUint16(x) \
|
|
|
|
AddUint16(x, #1)
|
|
|
|
|
2015-02-19 07:08:16 +00:00
|
|
|
// Add 8bit x with <=8bit amt
|
|
|
|
#define AddUint8(x, amt) \
|
|
|
|
add x, x, amt; \
|
|
|
|
bic SP_Reg, #0x0100;
|
|
|
|
|
|
|
|
// Increment 8bit x
|
|
|
|
#define IncUint8(x) \
|
|
|
|
AddUint8(x, #1)
|
|
|
|
|
|
|
|
// Subtract 8bit x by <=8bit amt
|
|
|
|
#define SubUint8(x, amt) \
|
|
|
|
subs x, x, amt; \
|
|
|
|
movmi x, #0xFF;
|
2015-02-18 04:33:27 +00:00
|
|
|
|
2015-02-19 07:08:16 +00:00
|
|
|
// Decrement 8bit x
|
|
|
|
#define DecUint8(x) \
|
|
|
|
SubUint8(x, #1)
|
2015-02-18 04:33:27 +00:00
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
#define GetFromPC_B \
|
|
|
|
mov EffectiveAddr, PC_Reg; \
|
2015-02-18 04:33:27 +00:00
|
|
|
IncUint16(PC_Reg) \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1; \
|
|
|
|
TRACE_ARG
|
|
|
|
|
2015-02-18 04:33:27 +00:00
|
|
|
#define hi_byte r0
|
|
|
|
#define lo_byte r9
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
#define GetFromPC_W \
|
|
|
|
mov EffectiveAddr, PC_Reg; \
|
2015-02-18 04:33:27 +00:00
|
|
|
AddUint16(PC_Reg, #2) \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1; \
|
|
|
|
TRACE_ARG2 \
|
2015-02-18 04:33:27 +00:00
|
|
|
mov lo_byte, r0; \
|
|
|
|
IncUint16(EffectiveAddr) \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1; \
|
|
|
|
TRACE_ARG1; \
|
2015-02-18 04:33:27 +00:00
|
|
|
mov hi_byte, hi_byte, LSL #8; \
|
|
|
|
orr r0, hi_byte, lo_byte;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define JumpNextInstruction \
|
|
|
|
TRACE_PROLOGUE \
|
|
|
|
GetFromPC_B \
|
2015-02-19 07:08:16 +00:00
|
|
|
CPUStatsReset \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, SYM(cpu65__opcodes); \
|
|
|
|
ldr r1, [r1, r0, LSL PTR_SHIFT]; \
|
|
|
|
bx r1;
|
|
|
|
|
|
|
|
#define GetFromEA_B \
|
2015-02-19 07:08:16 +00:00
|
|
|
CPUStatsSetRead \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
2015-02-16 04:08:01 +00:00
|
|
|
blx r1;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define GetFromEA_W \
|
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1; \
|
2015-02-18 04:33:27 +00:00
|
|
|
mov lo_byte, r0; \
|
|
|
|
IncUint16(EffectiveAddr) \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1; \
|
2015-02-18 04:33:27 +00:00
|
|
|
mov hi_byte, hi_byte, LSL #8; \
|
|
|
|
orr r0, hi_byte, lo_byte;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define PutToEA_B \
|
2015-02-19 07:08:16 +00:00
|
|
|
CPUStatsSetWrite \
|
2015-02-15 19:10:27 +00:00
|
|
|
ldr r1, SYM(cpu65_vmem_w); \
|
|
|
|
ldr r1, [r1, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1;
|
|
|
|
|
|
|
|
#define GetFromMem_B(x) \
|
|
|
|
mov EffectiveAddr, x; \
|
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1;
|
|
|
|
|
|
|
|
#define GetFromMem_W(x) \
|
|
|
|
mov EffectiveAddr, x; \
|
2015-02-18 04:33:27 +00:00
|
|
|
GetFromEA_W
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define Continue \
|
|
|
|
b continue;
|
|
|
|
|
|
|
|
#define cbw \
|
|
|
|
/* Virtual x86: Convert Byte-to-Word */ \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov r0, r0, ASR #24;
|
|
|
|
|
2015-02-20 00:03:29 +00:00
|
|
|
#define _IncOpCycles \
|
|
|
|
ldr mem_cycle_count, SYM(cpu65_opcycles); \
|
|
|
|
ldrb scratch_count, [mem_cycle_count]; \
|
|
|
|
add scratch_count, scratch_count, #1;
|
|
|
|
|
|
|
|
#define IncOpCycles \
|
|
|
|
_IncOpCycles \
|
|
|
|
strb scratch_count, [mem_cycle_count];
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
#define pc_hi_byte r9
|
|
|
|
#define mem_cycle_count r1
|
|
|
|
#define scratch_count r12
|
|
|
|
#define pc_hi_prev r9
|
|
|
|
#define pc_hi_next r0
|
|
|
|
#define BranchXCycles \
|
2015-02-20 00:03:29 +00:00
|
|
|
_IncOpCycles \
|
2015-02-15 19:10:27 +00:00
|
|
|
mov pc_hi_prev, PC_Reg; \
|
|
|
|
mov pc_hi_prev, pc_hi_prev, LSR #8; \
|
|
|
|
cbw; \
|
|
|
|
add PC_Reg, PC_Reg, r0; /* branch PC */ \
|
2015-02-19 07:08:16 +00:00
|
|
|
mov PC_Reg, PC_Reg, LSL #16; /* 16bit under/overflow protection */ \
|
|
|
|
mov PC_Reg, PC_Reg, LSR #16; \
|
2015-02-15 19:10:27 +00:00
|
|
|
mov pc_hi_next, PC_Reg; \
|
|
|
|
mov pc_hi_next, pc_hi_next, LSR #8; \
|
|
|
|
teq pc_hi_next, pc_hi_prev; \
|
|
|
|
addne scratch_count, scratch_count, #1; /* +1 branch taken */ \
|
|
|
|
strb scratch_count, [mem_cycle_count];
|
|
|
|
|
|
|
|
#define arm_flags r12
|
|
|
|
#define lahf \
|
2015-02-20 00:03:29 +00:00
|
|
|
/* Virtual x86: Load %AH (r12) from ARM CPU Flags */ \
|
2015-02-20 07:25:33 +00:00
|
|
|
mrs arm_flags, APSR; \
|
|
|
|
mov arm_flags, arm_flags, LSR #28;
|
|
|
|
|
|
|
|
#define bt \
|
|
|
|
/* Virtual x86: Bit Test (and set ... carry flag only) */ \
|
|
|
|
tst F_Reg, #C_Flag; \
|
|
|
|
mrs arm_flags, APSR; \
|
|
|
|
biceq arm_flags, arm_flags, #0x20000000; \
|
|
|
|
orrne arm_flags, arm_flags, #0x20000000; \
|
|
|
|
msr APSR_nzcvq, arm_flags;
|
|
|
|
|
|
|
|
#define btc \
|
|
|
|
/* Virtual x86: Bit Test and Clear (carry flag only) */ \
|
|
|
|
tst F_Reg, #C_Flag; \
|
|
|
|
mrs arm_flags, APSR; \
|
|
|
|
bicne arm_flags, arm_flags, #0x20000000; \
|
|
|
|
/*orreq arm_flags, arm_flags, #0x20000000;*/ \
|
|
|
|
msr APSR_nzcvq, arm_flags;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define FlagC \
|
|
|
|
lahf; \
|
|
|
|
and arm_flags, arm_flags, #C_Flag; \
|
|
|
|
bic F_Reg, F_Reg, #C_Flag; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define FlagZ \
|
|
|
|
lahf; \
|
|
|
|
and arm_flags, arm_flags, #Z_Flag; \
|
|
|
|
bic F_Reg, F_Reg, #Z_Flag; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define FlagN \
|
|
|
|
lahf; \
|
|
|
|
and arm_flags, arm_flags, #N_Flag; \
|
|
|
|
bic F_Reg, F_Reg, #N_Flag; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define FlagNZ \
|
|
|
|
lahf; \
|
|
|
|
and arm_flags, arm_flags, #NZ_Flags; \
|
|
|
|
bic F_Reg, F_Reg, #NZ_Flags; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define FlagNZC \
|
|
|
|
lahf; \
|
|
|
|
and arm_flags, arm_flags, #NZC_Flags; \
|
|
|
|
bic F_Reg, F_Reg, #NZC_Flags; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define FlagNVZ \
|
|
|
|
lahf; \
|
|
|
|
and arm_flags, arm_flags, #NVZ_Flags; \
|
|
|
|
bic F_Reg, F_Reg, #NVZ_Flags; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define FlagNVZC \
|
|
|
|
lahf; \
|
|
|
|
bic F_Reg, F_Reg, #NVZC_Flags; \
|
|
|
|
orr F_Reg, F_Reg, arm_flags;
|
|
|
|
|
|
|
|
#define stack_loc r1
|
|
|
|
#ifdef APPLE2_VM
|
|
|
|
#define RestoreAltZP \
|
|
|
|
ldr stack_loc, SYM(base_stackzp); \
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr stack_loc, [stack_loc]; \
|
2015-02-15 19:10:27 +00:00
|
|
|
add stack_loc, stack_loc, #0x100; \
|
|
|
|
add stack_loc, stack_loc, SP_Reg;
|
|
|
|
#else
|
|
|
|
#define RestoreAltZP
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define Push(x) \
|
|
|
|
RestoreAltZP \
|
|
|
|
strb x, [stack_loc]; \
|
2015-02-19 07:08:16 +00:00
|
|
|
DecUint8(SP_Reg)
|
|
|
|
#warning TODO FIXME ... need to write a 65c02 stack underflow vm test ... also how does AppleWin handle 65c02 underflow?
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define Pop(x) \
|
2015-02-19 07:08:16 +00:00
|
|
|
IncUint8(SP_Reg) \
|
2015-02-15 19:10:27 +00:00
|
|
|
RestoreAltZP \
|
|
|
|
ldrb x, [stack_loc];
|
2015-02-19 07:08:16 +00:00
|
|
|
#warning TODO FIXME ... need to write a 65c02 stack overflow vm test ... also how does AppleWin handle 65c02 overflow?
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// addressing macros
|
|
|
|
|
|
|
|
/* Immediate Addressing - the operand is contained in the second byte of the
|
|
|
|
instruction. */
|
|
|
|
#define _GetImm \
|
|
|
|
mov EffectiveAddr, PC_Reg; \
|
2015-02-18 04:33:27 +00:00
|
|
|
IncUint16(PC_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#if CPU_TRACING
|
|
|
|
#define GetImm \
|
|
|
|
_GetImm \
|
|
|
|
ldr r1, [reg_vmem_r, EffectiveAddr, LSL PTR_SHIFT]; \
|
|
|
|
blx r1; \
|
|
|
|
TRACE_ARG
|
|
|
|
#else
|
|
|
|
#define GetImm \
|
|
|
|
_GetImm
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Absolute Addressing - the second byte of the instruction is the low
|
|
|
|
order address, and the third byte is the high order byte. */
|
|
|
|
#define GetAbs \
|
|
|
|
GetFromPC_W; \
|
|
|
|
mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
/* Zero Page Addressing - the second byte of the instruction is an
|
|
|
|
address on the zero page */
|
|
|
|
#define GetZPage \
|
|
|
|
GetFromPC_B; \
|
|
|
|
mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
/* Zero Page Indexed Addressing - The effective address is calculated by
|
|
|
|
adding the second byte to the contents of the index register. Due
|
|
|
|
to the zero page addressing nature of this mode, no carry is added
|
|
|
|
to the high address byte, and the crossing of page boundaries does
|
|
|
|
not occur. */
|
|
|
|
#define GetZPage_X \
|
|
|
|
GetFromPC_B; \
|
|
|
|
add r0, r0, X_Reg; \
|
|
|
|
mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
#define GetZPage_Y \
|
|
|
|
GetFromPC_B; \
|
|
|
|
add r0, r0, Y_Reg; \
|
|
|
|
mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
#define ea_hi_prev r1
|
|
|
|
#define ea_hi_next r9
|
|
|
|
#define AddIndexRegAndTestPageBoundary(IndexReg) \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov ea_hi_prev, r0, LSR #8; \
|
2015-02-15 19:10:27 +00:00
|
|
|
add r0, r0, IndexReg; \
|
2015-02-22 05:04:44 +00:00
|
|
|
bic r0, #0x10000; \
|
|
|
|
mov ea_hi_next, r0, LSR #8; \
|
2015-02-15 19:10:27 +00:00
|
|
|
teq ea_hi_prev, ea_hi_next; \
|
|
|
|
beq 9f;
|
|
|
|
|
|
|
|
/* Absolute Indexed Addressing - The effective address is formed by
|
|
|
|
adding the contents of X or Y to the address contained in the
|
|
|
|
second and third bytes of the instruction. */
|
|
|
|
|
|
|
|
#define GetAbs_X \
|
|
|
|
GetFromPC_W \
|
|
|
|
AddIndexRegAndTestPageBoundary(X_Reg) \
|
2015-02-20 00:03:29 +00:00
|
|
|
IncOpCycles \
|
2015-02-15 19:10:27 +00:00
|
|
|
9: mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
#define GetAbs_X_STx \
|
|
|
|
GetFromPC_W \
|
|
|
|
AddIndexRegAndTestPageBoundary(X_Reg) \
|
2015-02-20 00:03:29 +00:00
|
|
|
/* IncOpCycles */ \
|
2015-02-15 19:10:27 +00:00
|
|
|
9: mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
#define GetAbs_Y \
|
|
|
|
GetFromPC_W \
|
|
|
|
AddIndexRegAndTestPageBoundary(Y_Reg) \
|
2015-02-20 00:03:29 +00:00
|
|
|
IncOpCycles \
|
2015-02-15 19:10:27 +00:00
|
|
|
9: mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
#define GetAbs_Y_STA \
|
|
|
|
GetFromPC_W \
|
|
|
|
AddIndexRegAndTestPageBoundary(Y_Reg) \
|
2015-02-20 00:03:29 +00:00
|
|
|
/* IncOpCycles */ \
|
2015-02-15 19:10:27 +00:00
|
|
|
9: mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
/* Zero Page Indirect Addressing (65c02) - The second byte of the
|
|
|
|
instruction points to a memory location on page zero containing the
|
|
|
|
low order byte of the effective address. The next location on page
|
|
|
|
zero contains the high order byte of the address. */
|
|
|
|
#define GetIndZPage \
|
|
|
|
GetFromPC_B \
|
|
|
|
mov EffectiveAddr, r0; \
|
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r12, r0; \
|
|
|
|
add EffectiveAddr, EffectiveAddr, #1; \
|
|
|
|
bic EffectiveAddr, #0x100; \
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r0, r0, LSL #8; \
|
|
|
|
orr r0, r12, r0; \
|
2015-02-15 19:10:27 +00:00
|
|
|
mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
/* Zero Page Indexed Indirect Addressing - The second byte is added to
|
|
|
|
the contents of the X index register; the carry is discarded. The
|
|
|
|
result of this addition points to a memory location on page zero
|
|
|
|
whose contents is the low order byte of the effective address. The
|
|
|
|
next memory location in page zero contains the high-order byte of
|
|
|
|
the effective address. Both memory locations specifying the high
|
|
|
|
and low-order bytes must be in page zero. */
|
|
|
|
#define GetIndZPage_X \
|
|
|
|
GetFromPC_B \
|
|
|
|
mov EffectiveAddr, r0; \
|
2015-02-22 05:04:44 +00:00
|
|
|
add EffectiveAddr, EffectiveAddr, X_Reg; \
|
|
|
|
bic EffectiveAddr, #0x100; \
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r12, r0; \
|
|
|
|
add EffectiveAddr, EffectiveAddr, #1; \
|
|
|
|
bic EffectiveAddr, #0x100; \
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r0, r0, LSL #8; \
|
|
|
|
orr r0, r12, r0; \
|
2015-02-15 19:10:27 +00:00
|
|
|
mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
/* Indirect Indexed Addressing - The second byte of the instruction
|
|
|
|
points to a memory location in page zero. The contents of this
|
|
|
|
memory location are added to the contents of the Y index register,
|
|
|
|
the result being the low order byte of the effective address. The
|
|
|
|
carry from this addition is added to the contents of the next page
|
|
|
|
zero memory location, the result being the high order byte of the
|
|
|
|
effective address. */
|
|
|
|
#define _GetIndZPage_Y \
|
|
|
|
GetFromPC_B \
|
|
|
|
mov EffectiveAddr, r0; \
|
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r12, r0; \
|
|
|
|
add EffectiveAddr, EffectiveAddr, #1; \
|
|
|
|
bic EffectiveAddr, #0x100; \
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r0, r0, LSL #8; \
|
|
|
|
orr r0, r12, r0; \
|
2015-02-15 19:10:27 +00:00
|
|
|
AddIndexRegAndTestPageBoundary(Y_Reg)
|
|
|
|
|
|
|
|
#define GetIndZPage_Y \
|
|
|
|
_GetIndZPage_Y \
|
2015-02-20 00:03:29 +00:00
|
|
|
IncOpCycles \
|
2015-02-15 19:10:27 +00:00
|
|
|
9: mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
#define GetIndZPage_Y_STA \
|
|
|
|
_GetIndZPage_Y \
|
2015-02-22 05:04:44 +00:00
|
|
|
/*IncOpCycles*/ \
|
2015-02-15 19:10:27 +00:00
|
|
|
9: mov EffectiveAddr, r0;
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// 65c02 instruction macros
|
|
|
|
|
2015-02-22 05:04:44 +00:00
|
|
|
#if 0
|
|
|
|
#error this attempts to leverage ARM 32bit flags, but does so incorrectly ... possibly there is some efficiency gains here if correctness can be assured
|
2015-02-15 19:10:27 +00:00
|
|
|
#define DoADC_b \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov A_Reg, A_Reg, LSL #24; \
|
2015-02-20 07:25:33 +00:00
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
\
|
|
|
|
/* clear ARM 'C' */ \
|
|
|
|
adcs r1, r1, #0; \
|
|
|
|
\
|
|
|
|
/* set HI-C */ \
|
|
|
|
tst F_Reg, #C_Flag; \
|
|
|
|
adcnes A_Reg, A_Reg, #0x01000000; \
|
|
|
|
\
|
|
|
|
/* lahf; */ \
|
|
|
|
/* and arm_flags, arm_flags, #VC_Flags; */ \
|
|
|
|
/* mov arm_flags_int, arm_flags; */ \
|
|
|
|
\
|
2015-02-16 04:08:01 +00:00
|
|
|
adcs A_Reg, A_Reg, r0; \
|
2015-02-15 19:10:27 +00:00
|
|
|
FlagNVZC \
|
2015-02-20 07:25:33 +00:00
|
|
|
/* merge intermediate V,C */ \
|
|
|
|
/* orr F_Reg, F_Reg, arm_flags_int; */ \
|
2015-02-16 04:08:01 +00:00
|
|
|
mov A_Reg, A_Reg, LSR #24;
|
2015-02-22 05:04:44 +00:00
|
|
|
#else
|
|
|
|
#define sign_a r1
|
|
|
|
#define sign_0 r9
|
|
|
|
#define DoADC_b \
|
|
|
|
GetFromEA_B \
|
|
|
|
/* save operand sign bits */ \
|
|
|
|
mov sign_a, A_Reg, LSR #7; \
|
|
|
|
mov sign_0, r0, LSR #7; \
|
|
|
|
/* perform ADC with incoming carry */\
|
|
|
|
tst F_Reg, #C_Flag; \
|
|
|
|
addne A_Reg, A_Reg, #1; \
|
|
|
|
add A_Reg, A_Reg, r0; \
|
|
|
|
/* clear and set flags */ \
|
|
|
|
bic F_Reg, F_Reg, #NVZC_Flags; \
|
|
|
|
tst A_Reg, #0x100; \
|
|
|
|
orrne F_Reg, F_Reg, #C_Flag; \
|
|
|
|
bic A_Reg, #0x100; \
|
|
|
|
\
|
|
|
|
tst A_Reg, #0x80; \
|
|
|
|
orrne F_Reg, F_Reg, #N_Flag; \
|
|
|
|
\
|
|
|
|
teq sign_a, sign_0; \
|
|
|
|
bne 1f; \
|
|
|
|
mov sign_0, A_Reg, LSR #7; \
|
|
|
|
cmp sign_a, sign_0; \
|
|
|
|
orrne F_Reg, F_Reg, #V_Flag; \
|
|
|
|
\
|
|
|
|
1: tst A_Reg, #0xFF; \
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag;
|
|
|
|
#endif
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
#define DebugBCDCheck \
|
|
|
|
tst A_Reg, #0x80; \
|
|
|
|
tstne A_Reg, #0x60; \
|
|
|
|
blne CALL(debug_illegal_bcd); \
|
|
|
|
tst A_Reg, #0x08; \
|
|
|
|
tstne A_Reg, #0x06; \
|
|
|
|
blne CALL(debug_illegal_bcd); \
|
|
|
|
tst r0, #0x80; \
|
|
|
|
tstne r0, #0x60; \
|
|
|
|
blne CALL(debug_illegal_bcd); \
|
|
|
|
tst r0, #0x08; \
|
|
|
|
tstne r0, #0x06; \
|
|
|
|
blne CALL(debug_illegal_bcd);
|
|
|
|
#else
|
|
|
|
#define DebugBCDCheck
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define DoAND \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov A_Reg, A_Reg, LSL #24; \
|
2015-02-20 07:25:33 +00:00
|
|
|
ands A_Reg, A_Reg, r0; \
|
|
|
|
FlagNZ \
|
|
|
|
mov A_Reg, A_Reg, LSR #24;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define _DoASL(x) \
|
|
|
|
mov x, x, LSL #24; \
|
|
|
|
adcs x, x, x; \
|
|
|
|
FlagNZC \
|
|
|
|
mov x, x, LSR #24;
|
|
|
|
|
|
|
|
#define DoASL \
|
|
|
|
GetFromEA_B \
|
|
|
|
_DoASL(r0) \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define _DoBIT \
|
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r1, A_Reg; \
|
|
|
|
and r1, r1, r0;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define DoBIT \
|
|
|
|
_DoBIT \
|
2015-02-22 05:04:44 +00:00
|
|
|
bic F_Reg, F_Reg, #NVZ_Flags; \
|
|
|
|
tst r1, #0xFF; \
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag; \
|
|
|
|
tst r0, #0x40; \
|
|
|
|
orrne F_Reg, F_Reg, #V_Flag; \
|
|
|
|
tst r0, #0x80; \
|
|
|
|
orrne F_Reg, F_Reg, #N_Flag;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define DoCMP \
|
|
|
|
GetFromEA_B \
|
|
|
|
/* TODO FIXME : maybe actually use cmp or cmn instruction? */ \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov r1, A_Reg, LSL #24; \
|
|
|
|
subs r1, r1, r0; \
|
|
|
|
/*cmc;*/ \
|
|
|
|
FlagNZC
|
|
|
|
|
|
|
|
#define DoCPX \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov r1, X_Reg, LSL #24; \
|
|
|
|
subs r1, r1, r0; \
|
|
|
|
/*cmc;*/ \
|
|
|
|
FlagNZC
|
|
|
|
|
|
|
|
#define DoCPY \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov r1, Y_Reg, LSL #24; \
|
|
|
|
subs r1, r1, r0; \
|
|
|
|
/*cmc;*/ \
|
|
|
|
FlagNZC
|
|
|
|
|
|
|
|
#define _DoDEC(x) \
|
|
|
|
mov r1, #1; \
|
|
|
|
mov r1, r1, LSL #24; \
|
|
|
|
mov x, x, LSL #24; \
|
|
|
|
subs x, x, r1; \
|
|
|
|
FlagNZ \
|
2015-02-16 04:08:01 +00:00
|
|
|
mov x, x, LSR #24;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define DoDEC \
|
|
|
|
GetFromEA_B \
|
|
|
|
_DoDEC(r0) \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoEOR \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov A_Reg, A_Reg, LSL #24; \
|
|
|
|
eors A_Reg, A_Reg, r0; \
|
|
|
|
FlagNZ \
|
|
|
|
mov A_Reg, A_Reg, LSR #24;
|
|
|
|
|
|
|
|
#define _DoINC(x) \
|
|
|
|
mov r1, #1; \
|
|
|
|
mov r1, r1, LSL #24; \
|
|
|
|
mov x, x, LSL #24; \
|
|
|
|
adds x, x, r1; \
|
|
|
|
FlagNZ \
|
2015-02-16 04:08:01 +00:00
|
|
|
mov x, x, LSR #24;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define DoINC \
|
|
|
|
GetFromEA_B \
|
|
|
|
_DoINC(r0) \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoLDA \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov A_Reg, r0; \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
orrs r0, r0, r0; \
|
|
|
|
FlagNZ
|
|
|
|
|
|
|
|
#define DoLDX \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov X_Reg, r0; \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
orrs r0, r0, r0; \
|
|
|
|
FlagNZ
|
|
|
|
|
|
|
|
#define DoLDY \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov Y_Reg, r0; \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
orrs r0, r0, r0; \
|
|
|
|
FlagNZ
|
|
|
|
|
2015-02-16 18:24:02 +00:00
|
|
|
#define _DoLSR(x) \
|
|
|
|
lsrs x, x, #1; \
|
|
|
|
FlagNZC
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
#define DoLSR \
|
|
|
|
GetFromEA_B \
|
2015-02-16 18:24:02 +00:00
|
|
|
_DoLSR(r0) \
|
2015-02-15 19:10:27 +00:00
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoORA \
|
|
|
|
GetFromEA_B \
|
|
|
|
mov r0, r0, LSL #24; \
|
|
|
|
mov A_Reg, A_Reg, LSL #24; \
|
|
|
|
orrs A_Reg, A_Reg, r0; \
|
|
|
|
FlagNZ \
|
|
|
|
mov A_Reg, A_Reg, LSR #24;
|
|
|
|
|
2015-02-16 18:24:02 +00:00
|
|
|
#define _DoPLx(x) \
|
|
|
|
Pop(x); \
|
|
|
|
mov r0, x, LSL #24; \
|
2015-02-22 05:04:44 +00:00
|
|
|
orrs r0, r0, r0; \
|
2015-02-16 18:24:02 +00:00
|
|
|
FlagNZ
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
#define _DoROL(x) \
|
|
|
|
mov x, x, LSL #8; \
|
2015-02-16 04:08:01 +00:00
|
|
|
tst F_Reg, #C_Flag; \
|
2015-02-15 19:10:27 +00:00
|
|
|
orrne x, x, #0x80; \
|
|
|
|
lsls x, x, #17; \
|
|
|
|
FlagNZC \
|
|
|
|
mov x, x, LSR #24;
|
|
|
|
|
|
|
|
#define DoROL \
|
|
|
|
GetFromEA_B \
|
|
|
|
_DoROL(r0) \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
|
|
|
|
#define _DoROR(x) \
|
2015-02-16 04:08:01 +00:00
|
|
|
tst F_Reg, #C_Flag; \
|
2015-02-15 19:10:27 +00:00
|
|
|
orrne x, x, #0x100; \
|
2015-02-22 05:04:44 +00:00
|
|
|
ror x, x, #1; \
|
|
|
|
bic F_Reg, F_Reg, #NZC_Flags; \
|
|
|
|
tst x, #ROR_BIT; \
|
|
|
|
bicne x, #ROR_BIT; \
|
|
|
|
orrne F_Reg, F_Reg, #C_Flag; \
|
|
|
|
tst x, #0xFF; \
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag; \
|
|
|
|
tst x, #0x80; \
|
|
|
|
orrne F_Reg, F_Reg, #N_Flag;
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define DoROR \
|
|
|
|
GetFromEA_B \
|
|
|
|
_DoROR(r0) \
|
|
|
|
PutToEA_B
|
|
|
|
|
2015-02-22 05:04:44 +00:00
|
|
|
#if 0
|
|
|
|
#error this attempts to leverage ARM 32bit flags, but does so incorrectly ... possibly there is some efficiency gains here if correctness can be assured
|
2015-02-15 19:10:27 +00:00
|
|
|
#define DoSBC_b \
|
|
|
|
GetFromEA_B \
|
|
|
|
mvn r0, r0; \
|
2015-02-22 05:04:44 +00:00
|
|
|
adcs r1, r1, #0; \
|
2015-02-15 19:10:27 +00:00
|
|
|
bt; \
|
|
|
|
adcs A_Reg, A_Reg, r0; \
|
|
|
|
FlagNVZC
|
2015-02-22 05:04:44 +00:00
|
|
|
#else
|
|
|
|
#define DoSBC_b \
|
|
|
|
GetFromEA_B \
|
|
|
|
/* save operand sign bits */ \
|
|
|
|
mov sign_a, A_Reg, LSR #7; \
|
|
|
|
mov sign_0, r0, LSR #7; \
|
|
|
|
/* perform SBC with incoming borrow */\
|
|
|
|
sub A_Reg, A_Reg, r0; \
|
|
|
|
tst F_Reg, #C_Flag; \
|
|
|
|
subeq A_Reg, A_Reg, #1; \
|
|
|
|
/* clear and set flags */ \
|
|
|
|
bic F_Reg, F_Reg, #NVZC_Flags; \
|
|
|
|
tst A_Reg, #0x80000000; \
|
|
|
|
orreq F_Reg, F_Reg, #C_Flag; \
|
|
|
|
mov A_Reg, A_Reg, LSL #24; \
|
|
|
|
mov A_Reg, A_Reg, LSR #24; \
|
|
|
|
\
|
|
|
|
tst A_Reg, #0x80; \
|
|
|
|
orrne F_Reg, F_Reg, #N_Flag; \
|
|
|
|
\
|
|
|
|
teq sign_a, sign_0; \
|
|
|
|
beq 1f; \
|
|
|
|
mov sign_0, A_Reg, LSR #7; \
|
|
|
|
cmp sign_a, sign_0; \
|
|
|
|
orrne F_Reg, F_Reg, #V_Flag; \
|
|
|
|
\
|
|
|
|
1: tst A_Reg, #0xFF; \
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag;
|
|
|
|
#endif
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
#define DoSTA \
|
|
|
|
mov r0, A_Reg; \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoSTX \
|
|
|
|
mov r0, X_Reg; \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoSTY \
|
|
|
|
mov r0, Y_Reg; \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoSTZ \
|
|
|
|
mov r0, #0; \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoTRB \
|
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
tst r0, A_Reg; \
|
2015-02-15 19:10:27 +00:00
|
|
|
FlagZ \
|
|
|
|
mvn r1, A_Reg; \
|
|
|
|
and r0, r0, r1; \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
#define DoTSB \
|
|
|
|
GetFromEA_B \
|
2015-02-22 05:04:44 +00:00
|
|
|
tst r0, A_Reg; \
|
2015-02-15 19:10:27 +00:00
|
|
|
FlagZ \
|
|
|
|
orr r0, A_Reg, r0; \
|
|
|
|
PutToEA_B
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
6502 routines and instructions
|
|
|
|
---------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
ADC instructions
|
|
|
|
ADd memory to accumulator with Carry
|
|
|
|
---------------------------------- */
|
|
|
|
|
2015-02-22 21:46:58 +00:00
|
|
|
#define carry r9
|
|
|
|
#define lo_nyb r1
|
2015-02-20 00:03:29 +00:00
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
// Decimal mode
|
|
|
|
ENTRY(op_ADC_dec)
|
2015-02-20 00:03:29 +00:00
|
|
|
IncOpCycles
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_B
|
|
|
|
DebugBCDCheck
|
2015-02-22 21:46:58 +00:00
|
|
|
// isolate lo nybbles
|
|
|
|
mov lo_nyb, A_Reg
|
|
|
|
mov r9, r0
|
|
|
|
and lo_nyb, lo_nyb, #0x0F
|
|
|
|
and r9, r9, #0x0F
|
|
|
|
// lo nybble addition with carry
|
|
|
|
tst F_Reg, #C_Flag
|
|
|
|
addne r9, r9, #1
|
|
|
|
add lo_nyb, lo_nyb, r9
|
|
|
|
// prep 65c02 flags
|
2015-02-20 00:03:29 +00:00
|
|
|
bic F_Reg, #NVZC_Flags
|
2015-02-22 21:46:58 +00:00
|
|
|
// lo nybble DAA (Decimal Adjustment after Addition), saving carry (+0, +1, +2)
|
|
|
|
cmp lo_nyb, #0x09
|
|
|
|
addhi lo_nyb, lo_nyb, #6
|
|
|
|
mov carry, lo_nyb, LSR #4
|
|
|
|
and lo_nyb, lo_nyb, #0x0F
|
|
|
|
// isolate hi nybbles
|
|
|
|
mov A_Reg, A_Reg, LSR #4
|
|
|
|
mov r0, r0, LSR #4
|
|
|
|
// hi nybble addition with carry
|
|
|
|
add r0, r0, carry
|
|
|
|
add r0, A_Reg, r0
|
|
|
|
// hi nybble DAA
|
|
|
|
cmp r0, #0x09
|
|
|
|
addhi r0, #6
|
|
|
|
orrhi F_Reg, #C_Flag
|
|
|
|
// merge nybbles
|
|
|
|
mov r0, r0, LSL #4
|
|
|
|
orr A_Reg, r0, lo_nyb
|
|
|
|
// NZ flags
|
|
|
|
tst A_Reg, #0x80
|
|
|
|
orrne F_Reg, F_Reg, #N_Flag
|
|
|
|
tst A_Reg, #0xFF
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
|
|
|
#define maybe_DoADC_d \
|
|
|
|
tst F_Reg, #D_Flag; /* Decimal mode? */ \
|
|
|
|
bne CALL(op_ADC_dec) /* Yes, jump to decimal version */
|
|
|
|
|
|
|
|
ENTRY(op_ADC_imm) // 0x69
|
|
|
|
GetImm
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ADC_zpage) // 0x65
|
|
|
|
GetZPage
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ADC_zpage_x) // 0x75
|
|
|
|
GetZPage_X
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_ADC_zpage_y)
|
2015-02-16 04:08:01 +00:00
|
|
|
b CALL(op_NOP)
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ENTRY(op_ADC_abs) // 0x6d
|
|
|
|
GetAbs
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ADC_abs_x) // 0x7d
|
|
|
|
GetAbs_X
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ADC_abs_y) // 0x79
|
|
|
|
GetAbs_Y
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ADC_ind_x) // 0x61
|
|
|
|
GetIndZPage_X
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ADC_ind_y) // 0x71
|
|
|
|
GetIndZPage_Y
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x72
|
|
|
|
ENTRY(op_ADC_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
maybe_DoADC_d
|
|
|
|
DoADC_b
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
AND instructions
|
|
|
|
logical AND memory with accumulator
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_AND_imm) // 0x29
|
|
|
|
GetImm
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_AND_zpage) // 0x25
|
|
|
|
GetZPage
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_AND_zpage_x) // 0x35
|
|
|
|
GetZPage_X
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_AND_zpage_y)
|
|
|
|
b CALL(op_NOP)
|
|
|
|
|
|
|
|
ENTRY(op_AND_abs) // 0x2d
|
|
|
|
GetAbs
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_AND_abs_x) // 0x3d
|
|
|
|
GetAbs_X
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_AND_abs_y) // 0x39
|
|
|
|
GetAbs_Y
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_AND_ind_x) // 0x21
|
|
|
|
GetIndZPage_X
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_AND_ind_y) // 0x31
|
|
|
|
GetIndZPage_Y
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x32
|
|
|
|
ENTRY(op_AND_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
DoAND
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
ASL instructions
|
|
|
|
Arithmetic Shift one bit Left, memory or accumulator
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_ASL_acc) // 0x0a
|
|
|
|
_DoASL(A_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ASL_zpage) // 0x06
|
|
|
|
GetZPage
|
|
|
|
DoASL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ASL_zpage_x) // 0x16
|
|
|
|
GetZPage_X
|
|
|
|
DoASL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ASL_abs) // 0x0e
|
|
|
|
GetAbs
|
|
|
|
DoASL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ASL_abs_x) // 0x1e
|
|
|
|
GetAbs_X
|
|
|
|
DoASL
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
BBRx instructions
|
|
|
|
UNIMPLEMENTED : These are documented in the W65C02S datasheet ...
|
|
|
|
+ 1 cycle if branch within page
|
|
|
|
+ 2 cycles if branch across page boundary
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BBR0_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR1_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR2_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR3_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR4_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR5_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR6_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBR7_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BBSx instructions
|
|
|
|
UNIMPLEMENTED : These are documented in the W65C02S datasheet ...
|
|
|
|
+ 1 cycle if branch within page
|
|
|
|
+ 2 cycles if branch across page boundary
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BBS0_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS1_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS2_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS3_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS4_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS5_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS6_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BBS7_65c02)
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
BCC instruction
|
|
|
|
Branch on Carry Clear
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BCC) // 0x90
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #C_Flag
|
|
|
|
bne continue // branch not taken
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BCS instruction
|
|
|
|
Branch on Carry Set
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BCS) // 0xB0
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #C_Flag
|
|
|
|
beq continue // branch not taken
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BEQ instruction
|
|
|
|
Branch if EQual
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BEQ) // 0xF0
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #Z_Flag
|
|
|
|
beq continue // branch not taken
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
BIT instructions
|
|
|
|
BIt Test
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BIT_zpage) // 0x24
|
|
|
|
GetZPage
|
|
|
|
DoBIT
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_BIT_abs) // 0x2c
|
|
|
|
GetAbs
|
|
|
|
DoBIT
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x34
|
|
|
|
ENTRY(op_BIT_zpage_x)
|
|
|
|
GetZPage_X
|
|
|
|
DoBIT
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x3C
|
|
|
|
ENTRY(op_BIT_abs_x)
|
|
|
|
GetAbs_X
|
|
|
|
DoBIT
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* BIT immediate is anomalous in that it does not affect the
|
|
|
|
* N and V flags, unlike in other addressing modes.
|
|
|
|
*/
|
|
|
|
// 65c02 : 0x89
|
|
|
|
ENTRY(op_BIT_imm)
|
|
|
|
GetImm
|
|
|
|
_DoBIT
|
2015-02-22 05:04:44 +00:00
|
|
|
tst r1, #0xFF
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag
|
|
|
|
bicne F_Reg, F_Reg, #Z_Flag
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
BMI instruction
|
|
|
|
Branch on result MInus
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BMI) // 0x30
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #N_Flag
|
2015-02-16 04:08:01 +00:00
|
|
|
beq continue
|
2015-02-15 19:10:27 +00:00
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BNE instruction
|
|
|
|
Branch on result Not Equal
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BNE) // 0xD0
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #Z_Flag
|
2015-02-16 04:08:01 +00:00
|
|
|
bne continue
|
2015-02-15 19:10:27 +00:00
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BPL instruction
|
|
|
|
Branch on result PLus
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BPL) // 0x10
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #N_Flag
|
|
|
|
bne continue
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BRA instruction
|
|
|
|
BRanch Always
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
// 65c02 : 0x80
|
|
|
|
ENTRY(op_BRA)
|
|
|
|
GetFromPC_B
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
BRK instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_UNK) /* make undefined opcodes fault */
|
|
|
|
ENTRY(op_BRK)
|
2015-02-18 04:33:27 +00:00
|
|
|
IncUint16(PC_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
mov r0, PC_Reg
|
|
|
|
mov r0, r0, ROR #8
|
|
|
|
Push(r0)
|
|
|
|
mov r0, r0, LSR #24
|
|
|
|
Push(r0)
|
|
|
|
orr F_Reg, F_Reg, #BX_Flags
|
|
|
|
EncodeFlags
|
|
|
|
Push(r0)
|
|
|
|
orr F_Reg, F_Reg, #I_Flag
|
2015-02-20 00:03:29 +00:00
|
|
|
ldr EffectiveAddr, SYM(interrupt_vector)
|
2015-02-16 04:08:01 +00:00
|
|
|
ldrh EffectiveAddr, [EffectiveAddr]
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_W
|
|
|
|
mov PC_Reg, r0
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
BVC instruction
|
|
|
|
Branch on oVerflow Clear
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BVC) // 0x50
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #V_Flag
|
|
|
|
bne continue
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
BVS instruction
|
|
|
|
Branch on oVerflow Set
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_BVS) // 0x70
|
|
|
|
GetFromPC_B
|
|
|
|
tst F_Reg, #V_Flag
|
|
|
|
beq continue
|
|
|
|
BranchXCycles
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
CLC instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CLC) // 0x18
|
|
|
|
bic F_Reg, #C_Flag
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
CLD instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CLD) // 0xd8
|
|
|
|
bic F_Reg, #D_Flag
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
CLI instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CLI) // 0x58
|
|
|
|
bic F_Reg, #I_Flag
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
CLV instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CLV) // 0xB8
|
|
|
|
bic F_Reg, #V_Flag
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
CMP instructions
|
|
|
|
CoMPare memory and accumulator
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CMP_imm) // 0xc9
|
|
|
|
GetImm
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CMP_zpage) // 0xc5
|
|
|
|
GetZPage
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CMP_zpage_x) // 0xd5
|
|
|
|
GetZPage_X
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_CMP_zpage_y)
|
2015-02-16 04:08:01 +00:00
|
|
|
b CALL(op_NOP)
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ENTRY(op_CMP_abs) // 0xcd
|
|
|
|
GetAbs
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CMP_abs_x) // 0xdd
|
|
|
|
GetAbs_X
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CMP_abs_y) // 0xd9
|
|
|
|
GetAbs_Y
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CMP_ind_x) // 0xc1
|
|
|
|
GetIndZPage_X
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CMP_ind_y) // 0xd1
|
|
|
|
GetIndZPage_Y
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0xD2
|
|
|
|
ENTRY(op_CMP_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
DoCMP
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
CPX instructions
|
|
|
|
ComPare memory and X register
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CPX_imm) // 0xe0
|
|
|
|
GetImm
|
|
|
|
DoCPX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CPX_zpage) // 0xe4
|
|
|
|
GetZPage
|
|
|
|
DoCPX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CPX_abs) // 0xec
|
|
|
|
GetAbs
|
|
|
|
DoCPX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
CPY instructions
|
|
|
|
ComPare memory and Y register
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_CPY_imm) // 0xc0
|
|
|
|
GetImm
|
|
|
|
DoCPY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CPY_zpage) // 0xc4
|
|
|
|
GetZPage
|
|
|
|
DoCPY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_CPY_abs) // 0xcc
|
|
|
|
GetAbs
|
|
|
|
DoCPY
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
DEA: DEcrement Accumulator
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_DEC_acc)
|
|
|
|
ENTRY(op_DEA) // 0x3A
|
|
|
|
_DoDEC(A_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
DEC instructions
|
|
|
|
DECrement memory or accumulator by one
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_DEC_zpage) // 0xc6
|
|
|
|
GetZPage
|
|
|
|
DoDEC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_DEC_zpage_x) // 0xd6
|
|
|
|
GetZPage_X
|
|
|
|
DoDEC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_DEC_abs) // 0xce
|
|
|
|
GetAbs
|
|
|
|
DoDEC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_DEC_abs_x) // 0xde
|
|
|
|
GetAbs_X
|
|
|
|
DoDEC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
DEX instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_DEX) // 0xca
|
|
|
|
_DoDEC(X_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
DEY instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_DEY) // 0x88
|
|
|
|
_DoDEC(Y_Reg)
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
EOR instructions
|
|
|
|
Exclusive OR memory with accumulator
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_EOR_imm) // 0x49
|
|
|
|
GetImm
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_EOR_zpage) // 0x45
|
|
|
|
GetZPage
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_EOR_zpage_x) // 0x55
|
|
|
|
GetZPage_X
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_EOR_zpage_y)
|
2015-02-16 04:08:01 +00:00
|
|
|
b CALL(op_NOP)
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ENTRY(op_EOR_abs) // 0x4d
|
|
|
|
GetAbs
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_EOR_abs_x) // 0x5d
|
|
|
|
GetAbs_X
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_EOR_abs_y) // 0x59
|
|
|
|
GetAbs_Y
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_EOR_ind_x) // 0x41
|
|
|
|
GetIndZPage_X
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_EOR_ind_y) // 0x51
|
|
|
|
GetIndZPage_Y
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x52
|
|
|
|
ENTRY(op_EOR_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
DoEOR
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
INA : INcrement Accumulator
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_INC_acc)
|
|
|
|
ENTRY(op_INA) // 0x1A
|
|
|
|
_DoINC(A_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
INC instructions
|
|
|
|
INCrement memory
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_INC_zpage) // 0xe6
|
|
|
|
GetZPage
|
|
|
|
DoINC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_INC_zpage_x) // 0xf6
|
|
|
|
GetZPage_X
|
|
|
|
DoINC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_INC_abs) // 0xee
|
|
|
|
GetAbs
|
|
|
|
DoINC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_INC_abs_x) // 0xfe
|
|
|
|
GetAbs_X
|
|
|
|
DoINC
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
INX instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_INX) // 0xe8
|
|
|
|
_DoINC(X_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
INY instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_INY) // 0xc8
|
|
|
|
_DoINC(Y_Reg)
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
JMP instructions
|
|
|
|
JuMP to new location
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_JMP_abs)
|
|
|
|
GetAbs
|
|
|
|
mov PC_Reg, EffectiveAddr
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_JMP_ind) // 0x6c
|
|
|
|
GetFromPC_W
|
2015-02-22 05:04:44 +00:00
|
|
|
mov r1, r0, LSL #24
|
|
|
|
teq r1, #0xFF000000
|
2015-02-15 19:10:27 +00:00
|
|
|
beq jmp_special
|
|
|
|
GetFromMem_W(r0)
|
|
|
|
mov PC_Reg, r0
|
|
|
|
Continue
|
|
|
|
jmp_special: // see JMP indirect note in _Understanding the Apple IIe_ 4-25
|
|
|
|
mov PC_Reg, r0
|
2015-02-22 05:04:44 +00:00
|
|
|
subs PC_Reg, PC_Reg, #0xFF
|
|
|
|
movmi PC_Reg, PC_Reg, LSL #16
|
|
|
|
movmi PC_Reg, PC_Reg, LSR #16
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromMem_B(PC_Reg)
|
|
|
|
mov r9, r0, LSL #8
|
2015-02-22 05:04:44 +00:00
|
|
|
add PC_Reg, PC_Reg, #0xFF
|
|
|
|
bic PC_Reg, #0x10000
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromMem_B(PC_Reg)
|
|
|
|
orr r0, r9, r0
|
|
|
|
mov PC_Reg, r0
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x7C
|
|
|
|
ENTRY(op_JMP_abs_ind_x)
|
|
|
|
GetFromPC_W
|
|
|
|
mov EffectiveAddr, r0
|
|
|
|
mov r0, X_Reg
|
2015-02-22 05:04:44 +00:00
|
|
|
#warning HACK FIXME TODO : need to check the Bible here ... is this a signed addition (in which case we need to cbw)
|
|
|
|
//cbw
|
|
|
|
add EffectiveAddr, EffectiveAddr, r0
|
|
|
|
mov EffectiveAddr, EffectiveAddr, LSL #16 // 16bit under/overflow protection
|
|
|
|
mov EffectiveAddr, EffectiveAddr, LSR #16
|
2015-02-16 04:08:01 +00:00
|
|
|
GetFromMem_W(EffectiveAddr)
|
2015-02-15 19:10:27 +00:00
|
|
|
mov PC_Reg, r0
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
JSR instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_JSR) // 0x20
|
|
|
|
GetAbs
|
|
|
|
mov r0, PC_Reg
|
2015-02-19 07:08:16 +00:00
|
|
|
sub r0, r0, #1
|
|
|
|
mov r0, r0, LSL #16 // handle underflow -- can this happen in second mem page?
|
2015-02-18 04:33:27 +00:00
|
|
|
mov r0, r0, ROR #24
|
2015-02-15 19:10:27 +00:00
|
|
|
Push(r0) // push hi_byte
|
|
|
|
mov r0, r0, LSR #24
|
|
|
|
Push(r0) // push lo_byte
|
|
|
|
mov PC_Reg, EffectiveAddr
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
LDA instructions
|
|
|
|
LoaD Accumulator with memory
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_LDA_imm) // 0xa9
|
|
|
|
GetImm
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDA_zpage) // 0xa5
|
|
|
|
GetZPage
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDA_zpage_x) // 0xb5
|
|
|
|
GetZPage_X
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_LDA_zpage_y)
|
|
|
|
b CALL(op_NOP)
|
|
|
|
|
|
|
|
ENTRY(op_LDA_abs) // 0xad
|
|
|
|
GetAbs
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDA_abs_x) // 0xbd
|
|
|
|
GetAbs_X
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDA_abs_y) // 0xb9
|
|
|
|
GetAbs_Y
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDA_ind_x) // 0xa1
|
|
|
|
GetIndZPage_X
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDA_ind_y) // 0xb1
|
|
|
|
GetIndZPage_Y
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0xB2
|
|
|
|
ENTRY(op_LDA_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
DoLDA
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
LDX instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_LDX_imm) // 0xa2
|
|
|
|
GetImm
|
|
|
|
DoLDX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDX_zpage) // 0xa6
|
|
|
|
GetZPage
|
|
|
|
DoLDX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// HACK : is this used? need to study coverage ...
|
|
|
|
ENTRY(op_LDX_zpage_y) // 0xb6
|
|
|
|
GetZPage_Y
|
|
|
|
DoLDX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDX_abs) // 0xae
|
|
|
|
GetAbs
|
|
|
|
DoLDX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDX_abs_y) // 0xbe
|
|
|
|
GetAbs_Y
|
|
|
|
DoLDX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
LDY instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_LDY_imm) // 0xa0
|
|
|
|
GetImm
|
|
|
|
DoLDY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDY_zpage) // 0xa4
|
|
|
|
GetZPage
|
|
|
|
DoLDY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDY_zpage_x) // 0xb4
|
|
|
|
GetZPage_X
|
|
|
|
DoLDY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDY_abs) // 0xac
|
|
|
|
GetAbs
|
|
|
|
DoLDY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LDY_abs_x) // 0xbc
|
|
|
|
GetAbs_X
|
|
|
|
DoLDY
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
LSR instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_LSR_acc) // 0x4a
|
2015-02-16 18:24:02 +00:00
|
|
|
_DoLSR(A_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LSR_zpage) // 0x46
|
|
|
|
GetZPage
|
|
|
|
DoLSR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LSR_zpage_x) // 0x56
|
|
|
|
GetZPage_X
|
|
|
|
DoLSR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LSR_abs) // 0x4e
|
|
|
|
GetAbs
|
|
|
|
DoLSR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_LSR_abs_x) // 0x5e
|
|
|
|
GetAbs_X
|
|
|
|
DoLSR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
NOP instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_NOP) // 0xea
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
ORA instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_ORA_imm) // 0x09
|
|
|
|
GetImm
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ORA_zpage) // 0x05
|
|
|
|
GetZPage
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ORA_zpage_x) // 0x15
|
|
|
|
GetZPage_X
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_ORA_zpage_y)
|
|
|
|
b CALL(op_NOP)
|
|
|
|
|
|
|
|
ENTRY(op_ORA_abs) // 0x0d
|
|
|
|
GetAbs
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ORA_abs_x) // 0x1d
|
|
|
|
GetAbs_X
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ORA_abs_y) // 0x19
|
|
|
|
GetAbs_Y
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ORA_ind_x) // 0x01
|
|
|
|
GetIndZPage_X
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ORA_ind_y) // 0x11
|
|
|
|
GetIndZPage_Y
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x12
|
|
|
|
ENTRY(op_ORA_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
DoORA
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
PHA instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PHA) // 0x48
|
|
|
|
Push(A_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PHP instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PHP) // 0x08
|
|
|
|
EncodeFlags
|
|
|
|
Push(r0)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PHX instruction
|
|
|
|
65c02 : 0xDA
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PHX)
|
|
|
|
Push(X_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PHY instruction
|
|
|
|
65c02 : 0x5A
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PHY)
|
|
|
|
Push(Y_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PLA instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PLA) // 0x68
|
2015-02-16 18:24:02 +00:00
|
|
|
_DoPLx(A_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PLP instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PLP) // 0x28
|
|
|
|
Pop(r0)
|
|
|
|
DecodeFlags
|
|
|
|
orr F_Reg, F_Reg, #BX_Flags
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PLX instruction
|
|
|
|
65c02 : 0xFA
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PLX)
|
2015-02-16 18:24:02 +00:00
|
|
|
_DoPLx(X_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
PLY instruction
|
|
|
|
65c02 : 0x7A
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_PLY)
|
2015-02-16 18:24:02 +00:00
|
|
|
_DoPLx(Y_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
ROL instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_ROL_acc) // 0x2a
|
|
|
|
_DoROL(A_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROL_zpage) // 0x26
|
|
|
|
GetZPage
|
|
|
|
DoROL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROL_zpage_x) // 0x36
|
|
|
|
GetZPage_X
|
|
|
|
DoROL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROL_abs) // 0x2e
|
|
|
|
GetAbs
|
|
|
|
DoROL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROL_abs_x) // 0x3e
|
|
|
|
GetAbs_X
|
|
|
|
DoROL
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
ROR instructions
|
|
|
|
---------------------------------- */
|
|
|
|
ENTRY(op_ROR_acc) // 0x6a
|
|
|
|
_DoROR(A_Reg)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROR_zpage) // 0x66
|
|
|
|
GetZPage
|
|
|
|
DoROR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROR_zpage_x) // 0x76
|
|
|
|
GetZPage_X
|
|
|
|
DoROR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROR_abs) // 0x6e
|
|
|
|
GetAbs
|
|
|
|
DoROR
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_ROR_abs_x) // 0x7e
|
|
|
|
GetAbs_X
|
|
|
|
DoROR
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
RTI instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_RTI) // 0x40
|
|
|
|
Pop(r0)
|
|
|
|
DecodeFlags
|
|
|
|
orr F_Reg, F_Reg, #BX_Flags
|
|
|
|
Pop(lo_byte)
|
|
|
|
Pop(hi_byte)
|
|
|
|
mov hi_byte, hi_byte, LSL #8
|
2015-02-18 04:33:27 +00:00
|
|
|
orr PC_Reg, hi_byte, lo_byte
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
RTS instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_RTS) // 0x60
|
|
|
|
Pop(lo_byte)
|
|
|
|
Pop(hi_byte)
|
|
|
|
mov hi_byte, hi_byte, LSL #8
|
2015-02-18 04:33:27 +00:00
|
|
|
orr PC_Reg, hi_byte, lo_byte
|
|
|
|
IncUint16(PC_Reg)
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
SBC instructions
|
|
|
|
SuBtract memory from accumulator with Borrow
|
|
|
|
---------------------------------- */
|
2015-02-22 21:46:58 +00:00
|
|
|
#define borrow carry
|
2015-02-15 19:10:27 +00:00
|
|
|
ENTRY(op_SBC_dec)
|
2015-02-20 00:03:29 +00:00
|
|
|
IncOpCycles
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_B
|
|
|
|
DebugBCDCheck
|
2015-02-22 21:46:58 +00:00
|
|
|
// isolate lo nybbles
|
|
|
|
mov lo_nyb, A_Reg
|
|
|
|
mov r9, r0
|
|
|
|
and lo_nyb, lo_nyb, #0x0F
|
|
|
|
and r9, r9, #0x0F
|
|
|
|
// lo nybble subtraction with borrow
|
|
|
|
sub lo_nyb, lo_nyb, r9
|
|
|
|
and lo_nyb, lo_nyb, #0xFF
|
|
|
|
tst F_Reg, #C_Flag
|
|
|
|
subeq lo_nyb, lo_nyb, #1
|
|
|
|
andeq lo_nyb, lo_nyb, #0xFF
|
|
|
|
// prep 65c02 flags
|
|
|
|
bic F_Reg, #NVZC_Flags
|
2015-02-20 00:03:29 +00:00
|
|
|
orr F_Reg, #C_Flag
|
2015-02-22 21:46:58 +00:00
|
|
|
// lo nybble DAS (Decimal Adjustment after Subtraction), saving borrow
|
|
|
|
eor borrow, borrow, borrow
|
|
|
|
cmp lo_nyb, #0x09
|
|
|
|
movhi borrow, #1
|
|
|
|
subhi lo_nyb, lo_nyb, #6
|
|
|
|
andhi lo_nyb, lo_nyb, #0x0F
|
|
|
|
// isolate hi nybbles
|
|
|
|
mov A_Reg, A_Reg, LSR #4
|
|
|
|
mov r0, r0, LSR #4
|
|
|
|
// hi nybble subtraction with borrow
|
|
|
|
sub r0, A_Reg, r0
|
|
|
|
and r0, r0, #0xFF
|
|
|
|
sub r0, r0, borrow
|
|
|
|
and r0, r0, #0xFF
|
|
|
|
// hi nybble DAS
|
|
|
|
cmp r0, #0x09
|
|
|
|
subhi r0, #6
|
|
|
|
bichi F_Reg, #C_Flag
|
|
|
|
andhi r0, r0, #0x0F
|
|
|
|
// merge nybbles
|
|
|
|
mov r0, r0, LSL #4
|
|
|
|
orr A_Reg, r0, lo_nyb
|
|
|
|
// NZ flags
|
|
|
|
tst A_Reg, #0x80
|
|
|
|
orrne F_Reg, F_Reg, #N_Flag
|
|
|
|
tst A_Reg, #0xFF
|
|
|
|
orreq F_Reg, F_Reg, #Z_Flag
|
2015-02-15 19:10:27 +00:00
|
|
|
Continue
|
|
|
|
|
|
|
|
#define maybe_DoSBC_d \
|
|
|
|
tst F_Reg, #D_Flag; /* Decimal mode? */ \
|
|
|
|
bne CALL(op_SBC_dec) /* Yes, jump to decimal version */
|
|
|
|
|
|
|
|
ENTRY(op_SBC_imm) // 0xe9
|
|
|
|
GetImm
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SBC_zpage) // 0xe5
|
|
|
|
GetZPage
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SBC_zpage_x) // 0xf5
|
|
|
|
GetZPage_X
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_SBC_zpage_y)
|
2015-02-16 04:08:01 +00:00
|
|
|
b CALL(op_NOP)
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ENTRY(op_SBC_abs) // 0xed
|
|
|
|
GetAbs
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SBC_abs_x) // 0xfd
|
|
|
|
GetAbs_X
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SBC_abs_y) // 0xf9
|
|
|
|
GetAbs_Y
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SBC_ind_x) // 0xe1
|
|
|
|
GetIndZPage_X
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SBC_ind_y) // 0xf1
|
|
|
|
GetIndZPage_Y
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0xF2
|
|
|
|
ENTRY(op_SBC_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
maybe_DoSBC_d
|
|
|
|
DoSBC_b
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
SEC instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_SEC) // 0x38
|
|
|
|
orr F_Reg, #C_Flag
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
SED instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_SED) // 0xf8
|
|
|
|
orr F_Reg, #D_Flag
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
SEI instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_SEI) // 0x78
|
|
|
|
orr F_Reg, #I_Flag
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
SMBx instructions -- Available in Rockwell 65C02 but not NCR 65C02
|
|
|
|
UNIMPLEMENTED : These are documented in the W65C02S datasheet ...
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_SMB0_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB1_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB2_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB3_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB4_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB5_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB6_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_SMB7_65c02)
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
STA instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_STA_zpage) // 0x85
|
|
|
|
GetZPage
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STA_zpage_x) // 0x95
|
|
|
|
GetZPage_X
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// UNIMPLEMENTED : W65C02S datasheet
|
|
|
|
ENTRY(op_STA_zpage_y)
|
|
|
|
b CALL(op_NOP)
|
|
|
|
|
|
|
|
ENTRY(op_STA_abs) // 0x8d
|
|
|
|
GetAbs
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STA_abs_x) // 0x9d
|
|
|
|
GetAbs_X_STx
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STA_abs_y) // 0x99
|
|
|
|
GetAbs_Y_STA
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STA_ind_x) // 0x81
|
|
|
|
GetIndZPage_X
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STA_ind_y) // 0x91
|
|
|
|
GetIndZPage_Y_STA
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x92
|
|
|
|
ENTRY(op_STA_ind_zpage)
|
|
|
|
GetIndZPage
|
|
|
|
DoSTA
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
STP instruction
|
|
|
|
UNIMPLEMENTED : This is documented in the W65C02S datasheet ...
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_STP_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
RMBx instructions -- Available in Rockwell 65C02 but not NCR 65C02
|
|
|
|
UNIMPLEMENTED : These are documented in the W65C02S datasheet ...
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_RMB0_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB1_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB2_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB3_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB4_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB5_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB6_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_RMB7_65c02)
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
STX instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_STX_zpage) // 0x86
|
|
|
|
GetZPage
|
|
|
|
DoSTX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// HACK : is this used? need to study coverage ...
|
|
|
|
ENTRY(op_STX_zpage_y) // 0x96
|
|
|
|
GetZPage_Y
|
|
|
|
DoSTX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STX_abs) // 0x8e
|
|
|
|
GetAbs
|
|
|
|
DoSTX
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
STY instructions
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_STY_zpage) // 0x84
|
|
|
|
GetZPage
|
|
|
|
DoSTY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STY_zpage_x) // 0x94
|
|
|
|
GetZPage_X
|
|
|
|
DoSTY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
ENTRY(op_STY_abs) // 0x8c
|
|
|
|
GetAbs
|
|
|
|
DoSTY
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
STZ instructions
|
|
|
|
65c02 only
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
// 65c02 : 0x64
|
|
|
|
ENTRY(op_STZ_zpage)
|
|
|
|
GetZPage
|
|
|
|
DoSTZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x74
|
|
|
|
ENTRY(op_STZ_zpage_x)
|
|
|
|
GetZPage_X
|
|
|
|
DoSTZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x9C
|
|
|
|
ENTRY(op_STZ_abs)
|
|
|
|
GetAbs
|
|
|
|
DoSTZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x9E
|
|
|
|
ENTRY(op_STZ_abs_x)
|
|
|
|
GetAbs_X_STx
|
|
|
|
DoSTZ
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
TAX instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_TAX) // 0xaa
|
|
|
|
mov X_Reg, A_Reg
|
|
|
|
mov r0, A_Reg, LSL #24
|
|
|
|
orrs r0, r0, r0
|
|
|
|
FlagNZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TAY instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_TAY) // 0xa8
|
|
|
|
mov Y_Reg, A_Reg
|
|
|
|
mov r0, A_Reg, LSL #24
|
|
|
|
orrs r0, r0, r0
|
|
|
|
FlagNZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TRB instructions
|
|
|
|
65c02 only
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
// 65c02 : 0x1C
|
|
|
|
ENTRY(op_TRB_abs)
|
|
|
|
GetAbs
|
|
|
|
DoTRB
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x14
|
|
|
|
ENTRY(op_TRB_zpage)
|
|
|
|
GetZPage
|
|
|
|
DoTRB
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TSB instructions
|
|
|
|
65c02 only
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
// 65c02 : 0x0C
|
|
|
|
ENTRY(op_TSB_abs)
|
|
|
|
GetAbs
|
|
|
|
DoTSB
|
|
|
|
Continue
|
|
|
|
|
|
|
|
// 65c02 : 0x04
|
|
|
|
ENTRY(op_TSB_zpage)
|
|
|
|
GetZPage
|
|
|
|
DoTSB
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TSX instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_TSX) // 0xba
|
|
|
|
mov X_Reg, SP_Reg
|
|
|
|
mov r0, SP_Reg, LSL #24
|
|
|
|
orrs r0, r0, r0
|
|
|
|
FlagNZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TXA instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_TXA) // 0x8a
|
|
|
|
mov A_Reg, X_Reg
|
|
|
|
mov r0, X_Reg, LSL #24
|
|
|
|
orrs r0, r0, r0
|
|
|
|
FlagNZ
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TXS instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_TXS) // 0x9a
|
|
|
|
mov SP_Reg, X_Reg
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
TYA instruction
|
|
|
|
---------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(op_TYA) // 0x98
|
|
|
|
mov A_Reg, Y_Reg
|
|
|
|
mov r0, Y_Reg, LSL #24
|
|
|
|
orrs r0, r0, r0
|
|
|
|
FlagNZ
|
|
|
|
Continue
|
|
|
|
|
2015-02-16 04:08:01 +00:00
|
|
|
.ltorg
|
|
|
|
|
2015-02-15 19:10:27 +00:00
|
|
|
/* ----------------------------------
|
|
|
|
??? instruction - 65c02
|
|
|
|
Defined as NOPs by spec
|
|
|
|
---------------------------------- */
|
|
|
|
ENTRY(op_UNK_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
/* ----------------------------------
|
|
|
|
WAI instruction - 65c02
|
|
|
|
UNIMPLEMENTED : This is documented in the W65C02S datasheet ...
|
|
|
|
---------------------------------- */
|
|
|
|
ENTRY(op_WAI_65c02)
|
|
|
|
Continue
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark cpu main entry
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
CPU continue
|
|
|
|
Keep executing until we've executed >= cpu65_cycles_to_execute
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#define cycles_exe r0
|
|
|
|
continue:
|
|
|
|
ldr r1, SYM(cpu65__opcycles)
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r0, SYM(cpu65_opcode)
|
|
|
|
ldrb r0, [r0]
|
2015-02-15 19:10:27 +00:00
|
|
|
ldrb cycles_exe, [r1, r0]
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65_opcycles)
|
2015-02-19 07:08:16 +00:00
|
|
|
ldrb r9, [r1]
|
|
|
|
add cycles_exe, cycles_exe, r9
|
2015-02-15 19:10:27 +00:00
|
|
|
strb cycles_exe, [r1]
|
|
|
|
TRACE_EPILOGUE
|
|
|
|
|
|
|
|
ldr r1, SYM(gc_cycles_timer_0)
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr r9, [r1]
|
|
|
|
sub r9, r9, cycles_exe
|
|
|
|
str r9, [r1]
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ldr r1, SYM(gc_cycles_timer_1)
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr r9, [r1]
|
|
|
|
sub r9, r9, cycles_exe
|
|
|
|
str r9, [r1]
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ldr r1, SYM(cpu65_cycle_count)
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr r9, [r1]
|
|
|
|
add r9, r9, cycles_exe
|
|
|
|
str r9, [r1]
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
ldr r1, SYM(cpu65_cycles_to_execute)
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr r9, [r1]
|
|
|
|
subs r9, r9, cycles_exe
|
|
|
|
str r9, [r1]
|
2015-02-15 19:10:27 +00:00
|
|
|
bmi exit_cpu65_run
|
|
|
|
beq exit_cpu65_run
|
|
|
|
|
2015-02-19 07:08:16 +00:00
|
|
|
continue1: ldr r1, SYM(cpu65__signal)
|
2015-02-16 04:08:01 +00:00
|
|
|
ldrb r0, [r1]
|
2015-02-19 07:08:16 +00:00
|
|
|
orrs r0, r0, r0
|
2015-02-15 19:10:27 +00:00
|
|
|
bne exception
|
|
|
|
JumpNextInstruction
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
Exception handlers
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
exception: tst r0, #ResetSig
|
|
|
|
beq ex_irq
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(joy_button0) // OpenApple
|
|
|
|
ldrb r0, [r1]
|
|
|
|
tst r0, #0xFF
|
2015-02-15 19:10:27 +00:00
|
|
|
bne exit_reinit
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(joy_button1) // ClosedApple
|
|
|
|
ldrb r0, [r1]
|
|
|
|
tst r0, #0xFF
|
2015-02-15 19:10:27 +00:00
|
|
|
bne exit_reinit
|
|
|
|
|
2015-02-24 20:11:16 +00:00
|
|
|
ex_reset: eor r0, r0, r0
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65__signal)
|
|
|
|
strb r0, [r1]
|
|
|
|
ldr EffectiveAddr, SYM(reset_vector)
|
|
|
|
ldrh EffectiveAddr, [EffectiveAddr]
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_W
|
|
|
|
mov PC_Reg, r0
|
|
|
|
JumpNextInstruction
|
|
|
|
|
|
|
|
ex_irq: tst F_Reg, #I_Flag // Already interrupted?
|
|
|
|
beq 1f
|
|
|
|
JumpNextInstruction
|
|
|
|
1: mov r0, PC_Reg
|
|
|
|
mov r0, r0, ROR #8
|
|
|
|
Push(r0)
|
|
|
|
mov r0, r0, LSR #24
|
|
|
|
Push(r0)
|
|
|
|
orr F_Reg, F_Reg, #X_Flag
|
|
|
|
EncodeFlags
|
|
|
|
Push(r0)
|
|
|
|
orr F_Reg, F_Reg, #BI_Flags
|
|
|
|
//bic F_Reg, F_Reg, #D_Flag // AppleWin clears Decimal bit?
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr EffectiveAddr, SYM(interrupt_vector)
|
|
|
|
ldrh EffectiveAddr, [EffectiveAddr]
|
2015-02-15 19:10:27 +00:00
|
|
|
GetFromEA_W
|
|
|
|
mov PC_Reg, r0
|
|
|
|
JumpNextInstruction
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
65c02 CPU processing loop entry point
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(cpu65_run)
|
2015-02-19 07:08:16 +00:00
|
|
|
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
|
2015-02-15 19:10:27 +00:00
|
|
|
// Restore CPU state when being called from C.
|
2015-02-19 07:08:16 +00:00
|
|
|
ldr reg_vmem_r, SYM(cpu65_vmem_r)
|
2015-02-16 04:08:01 +00:00
|
|
|
ldr r1, SYM(cpu65_ea)
|
2015-02-15 19:10:27 +00:00
|
|
|
ldrh EffectiveAddr, [r1]
|
|
|
|
ldr r1, SYM(cpu65_pc)
|
|
|
|
ldrh PC_Reg, [r1]
|
|
|
|
ldr r1, SYM(cpu65_a)
|
|
|
|
ldrb A_Reg, [r1]
|
|
|
|
ldr r1, SYM(cpu65_f)
|
|
|
|
ldrb r0, [r1]
|
|
|
|
DecodeFlags
|
|
|
|
ldr r1, SYM(cpu65_x)
|
|
|
|
ldrb X_Reg, [r1]
|
|
|
|
ldr r1, SYM(cpu65_y)
|
|
|
|
ldrb Y_Reg, [r1]
|
|
|
|
ldr r1, SYM(cpu65_sp)
|
|
|
|
ldrb SP_Reg, [r1]
|
|
|
|
ldr r1, SYM(emul_reinitialize)
|
|
|
|
ldrb r0, [r1]
|
2015-02-24 20:11:16 +00:00
|
|
|
teq r0, #0
|
|
|
|
eorne r0, r0, r0
|
2015-02-16 04:08:01 +00:00
|
|
|
strneb r0, [r1]
|
2015-02-15 19:10:27 +00:00
|
|
|
bne ex_reset
|
|
|
|
b continue1
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
65c02 CPU processing loop exit point
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
exit_cpu65_run:
|
|
|
|
// Save CPU state when returning from being called from C
|
|
|
|
ldr r1, SYM(cpu65_pc)
|
|
|
|
strh PC_Reg, [r1]
|
|
|
|
CommonSaveCPUState
|
2015-02-19 07:08:16 +00:00
|
|
|
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
exit_reinit: ldr r1, SYM(cpu65__signal)
|
|
|
|
mov r0, #0
|
|
|
|
strb r0, [r1]
|
|
|
|
ldr r1, SYM(emul_reinitialize)
|
|
|
|
mov r0, #1
|
|
|
|
strb r0, [r1]
|
2015-02-19 07:08:16 +00:00
|
|
|
pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}
|
2015-02-15 19:10:27 +00:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
Debugger hooks
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
ENTRY(cpu65_direct_write)
|
2015-02-16 17:42:13 +00:00
|
|
|
#warning FIXME TODO implement cpu65_direct_write ...
|
2015-02-18 04:33:27 +00:00
|
|
|
mov r0, #42
|
2015-02-16 17:42:13 +00:00
|
|
|
ldr r0, [r0] // segfault
|
2015-02-19 07:08:16 +00:00
|
|
|
mov pc, lr
|
|
|
|
|
|
|
|
interrupt_vector: .hword 0xFFFE
|
|
|
|
reset_vector: .hword 0xFFFC
|
|
|
|
.ltorg
|
2015-02-15 19:10:27 +00:00
|
|
|
|