Appalm/src/6502.asm
2019-04-21 06:53:32 -07:00

2123 lines
39 KiB
NASM
Executable File

/********************************************************************************\
* *
* 6502 emulation *
* *
\********************************************************************************/
/*
* STRICT_IND_EMU tries to enforce exact addressing rules as it applies to zero page
* access. Disabling should improve performance and still work in 99.9% of the case.
*/
#define STRICT_IND_EMU 0
/*
* Define some macros for memory model specific 4addresses.
*/
#define GLOBAL %a5
#define OPTABLE(o) (opTable6502+(o))@END.w
#define STATE_6502 state6502@END.w
#define STATE_6502_1 (state6502+4)@END.w
#define STATE_6502_2 (state6502+8)@END.w
#define STATUS_6502 status6502@END.w
#define CC_68K_TO_6502 cc_68k_to_6502@END.w
#define CC_6502_TO_68K cc_6502_to_68k@END.w
/*
* Register allocations.
* Note: SP and CC share the same register.
* Use SWAP to get access to the seperate 16 bit halves.
*/
#define DATA %d0
#define INSTRNS %d1
#define ACC %d2
#define X %d3
#define Y %d4
#define SP_CC %d5
#define CC %d5
#define SP %d5
#define EA %d6
#define PAGE %d7
#define PC %a0
#define OPBASE %a1
#define MEMBASE %a2
#define WRMEM %a3
#define RDMEM %a4
#define ADDR %a6
/*
* Condition code bits.
*/
#define CC_C_68K 0x01
#define CC_V_68K 0x02
#define CC_Z_68K 0x04
#define CC_N_68K 0x08
#define CC_X_68K 0x10
#define CC_C_6502 0x01
#define CC_Z_6502 0x02
#define CC_I_6502 0x04
#define CC_D_6502 0x08
#define CC_B_6502 0x10
#define CC_1_6502 0x20
#define CC_V_6502 0x40
#define CC_N_6502 0x80
/*
* Effective address calculations.
*/
#define EA_IMM \
move.b (PC)+, DATA
#define EA_ZP \
clr.w EA; \
mov.b (PC)+, EA
#define EA_ZP_X \
move.w X, EA; \
add.b (PC)+, EA
#define EA_ZP_Y \
move.w Y, EA; \
add.b (PC)+, EA
#if STRICT_IND_EMU
#define EA_ZP_IND \
clr.w PAGE; \
move.b (PC)+, PAGE; \
move.b (MEMBASE,PAGE.w), DATA; \
addq.b #1, PAGE; \
move.b (MEMBASE,PAGE.w), PAGE; \
lsl.w #2, PAGE; \
move.w PAGE, EA; \
lsl.w #6, EA; \
move.b DATA, EA
#define EA_IND_X \
move.w X, PAGE; \
add.b (PC)+, PAGE; \
move.b (MEMBASE,PAGE.w), DATA; \
addq.b #1, PAGE; \
move.b (MEMBASE,PAGE.w), PAGE; \
lsl.w #2, PAGE; \
move.w PAGE, EA; \
lsl.w #6, EA; \
move.b DATA, EA
#define EA_IND_Y \
clr.w PAGE; \
move.b (PC)+, PAGE; \
move.b (MEMBASE,PAGE.w), DATA; \
addq.b #1, PAGE; \
move.b (MEMBASE,PAGE.w), EA; \
lsl.w #8, EA; \
move.b DATA, EA; \
add.w Y, EA; \
move.w EA, PAGE; \
clr.b PAGE; \
lsr.w #6, PAGE
#else
#define EA_ZP_IND \
clr.w PAGE; \
move.b (PC)+, PAGE; \
lea 1(MEMBASE,PAGE.w), ADDR; \
move.b (ADDR), PAGE; \
lsl.w #2, PAGE; \
move.w PAGE, EA; \
lsl.w #6, EA; \
move.b -(ADDR), EA
#define EA_IND_X \
move.w X, PAGE; \
add.b (PC)+, PAGE; \
lea 1(MEMBASE,PAGE.w), ADDR; \
move.b (ADDR), PAGE; \
lsl.w #2, PAGE; \
move.w PAGE, EA; \
lsl.w #6, EA; \
move.b -(ADDR), EA
#define EA_IND_Y \
clr.w PAGE; \
move.b (PC)+, PAGE; \
lea 1(MEMBASE,PAGE.w), ADDR; \
move.b (ADDR), EA; \
lsl.w #8, EA; \
move.b -(ADDR), EA; \
add.w Y, EA; \
move.w EA, PAGE; \
clr.b PAGE; \
lsr.w #6, PAGE
#endif
#define EA_ABS \
clr.w PAGE; \
move.b (PC)+, DATA; \
move.b (PC)+, PAGE; \
lsl.w #2, PAGE; \
move.w PAGE, EA; \
lsl.w #6, EA; \
move.b DATA, EA
#define EA_ABS_X \
move.b (PC)+, DATA; \
move.b (PC)+, EA; \
lsl.w #8, EA; \
move.b DATA, EA; \
add.w X, EA; \
move.w EA, PAGE; \
clr.b PAGE; \
lsr.w #6, PAGE
#define EA_ABS_Y \
move.b (PC)+, DATA; \
move.b (PC)+, EA; \
lsl.w #8, EA; \
move.b DATA, EA; \
add.w Y, EA; \
move.w EA, PAGE; \
clr.b PAGE; \
lsr.w #6, PAGE
/*
* Basic memory read.
*/
#define RD_MEM \
move.w (RDMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(RDMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
jsr (ADDR); \
bra.b 1f; \
0:; \
move.b (MEMBASE,EA.l), DATA; \
1:
#define LDA_MEM \
move.w (RDMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(RDMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
jsr (ADDR); \
move.b DATA, ACC; \
bra.b 1f; \
0:; \
move.b (MEMBASE,EA.l), ACC; \
1:
#define LDX_MEM \
move.w (RDMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(RDMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
jsr (ADDR); \
move.b DATA, X; \
bra.b 1f; \
0:; \
move.b (MEMBASE,EA.l), X; \
1:
#define LDY_MEM \
move.w (RDMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(RDMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
jsr (ADDR); \
move.b DATA, Y; \
bra.b 1f; \
0:; \
move.b (MEMBASE,EA.l), Y; \
1:
/*
* Basic memory write.
*/
#define WR_MEM \
move.w DATA, ADDR; \
move.w (WRMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(WRMEM, PAGE.w), DATA; \
exg ADDR, DATA; \
and.l #0xFF, DATA; \
jsr (ADDR); \
bra.b 1f; \
0:; \
move.w ADDR, DATA; \
move.b DATA, (MEMBASE, EA.l); \
1:
#define STA_MEM \
move.w (WRMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(WRMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
clr.l DATA; \
move.b ACC, DATA; \
jsr (ADDR); \
bra.b 1f; \
0:; \
move.b ACC, (MEMBASE, EA.l); \
1:
#define STX_MEM \
move.w (WRMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(WRMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
clr.l DATA; \
move.b X, DATA; \
jsr (ADDR); \
bra.b 1f; \
0:; \
move.b X, (MEMBASE, EA.l); \
1:
#define STY_MEM \
move.w (WRMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(WRMEM, PAGE.w), DATA; \
move.l DATA, ADDR; \
clr.l DATA; \
move.b Y, DATA; \
jsr (ADDR); \
bra.b 1f; \
0:; \
move.b Y, (MEMBASE, EA.l); \
1:
/*
* Memory write when the data is already in the ADDR register.
*/
#define WRA_MEM \
move.w (WRMEM, PAGE.w), DATA; \
beq.b 0f; \
swap DATA; \
move.w 2(WRMEM, PAGE.w), DATA; \
exg ADDR, DATA; \
and.l #0xFF, DATA; \
jsr (ADDR); \
bra.b 1f; \
0:; \
move.w ADDR, DATA; \
move.b DATA, (MEMBASE, EA.l); \
1:
/*
* Decrement instruction count and fetch next instruction.
*/
#define NEXT_OP \
dbf.w INSTRNS, opfetch; \
bra.w exit6502
/*
* Update CC flags.
*/
#define UPDATE_Z_STATUS \
move.w %sr, DATA; \
and.b #0x04, DATA; \
and.b #0x1D, CC; \
or.b DATA, CC
#define UPDATE_NZ_STATUS \
move.w %sr, DATA; \
and.b #0x0C, DATA; \
and.b #0x13, CC; \
or.b DATA, CC
#define UPDATE_NZC_STATUS \
move.w %sr, DATA; \
and.b #0x1D, DATA; \
and.b #0x02, CC; \
or.b DATA, CC
/*
* Opcodes.
*/
#define OP_BIT \
and.b #0x11, CC; \
move.w CC, ADDR; \
btst #7, DATA; \
sne CC; \
and.b #0x08, CC; \
add.w CC, ADDR; \
btst #6, DATA; \
sne CC; \
and.b #0x02, CC; \
add.w CC, ADDR; \
and.b ACC, DATA; \
move.w %sr, CC; \
and.b #0x04, CC; \
add.w ADDR, CC
#define OP_TRB \
and.b #0x11, CC; \
move.w CC, ADDR; \
btst #7, DATA; \
sne CC; \
and.b #0x08, CC; \
add.w CC, ADDR; \
btst #6, DATA; \
sne CC; \
and.b #0x02, CC; \
add.w CC, ADDR; \
not.b ACC; \
and.b ACC, DATA; \
move.w %sr, CC; \
and.b #0x04, CC; \
add.w ADDR, CC; \
not.b ACC
#define OP_TSB \
and.b #0x11, CC; \
btst #7, DATA; \
sne CC; \
and.b #0x08, CC; \
add.w CC, ADDR; \
btst #6, DATA; \
sne CC; \
and.b #0x02, CC; \
add.w CC, ADDR; \
or.b ACC, DATA; \
move.w %sr, CC; \
and.b #0x04, CC; \
add.w ADDR, CC
#define OP_ADC_BIN \
or.b #0x04, CC; \
move.w CC, %ccr; \
addx.b DATA, ACC; \
move.w %sr, CC
#define OP_ADC_BCD \
or.b #0x04, CC; \
move.w CC, %ccr; \
abcd DATA, ACC; \
move.w %sr, CC
#define OP_SBC_BIN \
eor.b #0x11, CC; \
or.b #0x04, CC; \
move.w CC, %ccr; \
subx.b DATA, ACC; \
move.w %sr, CC; \
eor.b #0x11, CC
#define OP_SBC_BCD \
eor.b #0x11, CC; \
or.b #0x04, CC; \
move.w CC, %ccr; \
sbcd DATA, ACC; \
move.w %sr, CC; \
eor.b #0x11, CC
.data
.even
/*
* Condition Code/Status Register translation tables.
*/
cc_6502_to_68k:
.byte 0x00; .byte 0x02; .byte 0x08; .byte 0x0A;
.byte 0x11; .byte 0x13; .byte 0x19; .byte 0x1B;
.byte 0x04; .byte 0x06; .byte 0x0C; .byte 0x0E;
.byte 0x15; .byte 0x17; .byte 0x1D; .byte 0x1F;
cc_68k_to_6502:
.byte 0x00; .byte 0x01; .byte 0x40; .byte 0x41;
.byte 0x02; .byte 0x03; .byte 0x42; .byte 0x43;
.byte 0x80; .byte 0x81; .byte 0xC0; .byte 0xC1;
.byte 0x82; .byte 0x83; .byte 0xC2; .byte 0xC3;
.text
.even
/*
* uCode.
*/
UNIMPLEMENTED:
move.l PC, DATA
subq.l #1, DATA
move.l DATA, PC
sub.l MEMBASE, DATA
swap DATA
move.b (PC), DATA
movem.l #0x1FFC, STATE_6502_2(GLOBAL) /* Save 6502 state */
movem.l (%sp)+, #0x7FFE /* Restore all registers */
rts
NOP:
NEXT_OP
CLD:
and.b #~CC_D_6502, STATUS_6502(GLOBAL)
bsr.w set_bcd_ops
NEXT_OP
SED:
or.b #CC_D_6502, STATUS_6502(GLOBAL)
bsr.w set_bcd_ops
NEXT_OP
CLC:
and.b #0xEE, CC
NEXT_OP
SEC:
or.b #0x11, CC
NEXT_OP
CLV:
and.b #0xFD, CC
NEXT_OP
SEI:
or.b #CC_I_6502, STATUS_6502(GLOBAL)
NEXT_OP
CLI:
and.b #~CC_I_6502, STATUS_6502(GLOBAL)
NEXT_OP
PHP:
move.b CC, DATA
and.w #0x0F, DATA
lea CC_68K_TO_6502(GLOBAL), ADDR
move.b (ADDR,DATA.w), DATA
or.b STATUS_6502(GLOBAL), DATA
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
NEXT_OP
PHA:
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b ACC, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
NEXT_OP
PHX:
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b X, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
NEXT_OP
PLP:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
swap SP_CC
clr.w CC
move.b DATA, CC
and.b #0x3C, DATA /* Mask out mapped state */
and.b #0xC3, CC
move.b DATA, STATUS_6502(GLOBAL)
rol.b #2, CC
lea CC_6502_TO_68K(GLOBAL), ADDR
move.b (ADDR,CC.w), CC
bsr.w set_bcd_ops
NEXT_OP
PLA:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.w SP, ADDR
swap SP_CC
move.b (MEMBASE,ADDR.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
PLX:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.w SP, ADDR
swap SP_CC
move.b (MEMBASE,ADDR.w), X
UPDATE_NZ_STATUS
NEXT_OP
BRK:
sub.l MEMBASE, PC /* Push PC + 2 */
move.w PC, DATA
addq #1, DATA
ror.w #8, DATA
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b DATA, (MEMBASE,SP.w)
lsr.w #8, DATA
subq.b #1, SP
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
or.b #CC_B_6502, STATUS_6502(GLOBAL) /* Set BRK flag */
move.b CC, DATA /* Push P */
and.w #0x0F, DATA
lea CC_68K_TO_6502(GLOBAL), ADDR
move.b (ADDR,DATA.w), DATA
or.b STATUS_6502(GLOBAL), DATA
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
or.b #CC_I_6502, STATUS_6502(GLOBAL) /* Set INT flag */
move.l #0xFFFE, DATA /* Load PC from 0xFFFE */
move.w (MEMBASE,DATA.l), DATA
ror.w #8, DATA
move.l DATA, PC
add.l MEMBASE, PC
NEXT_OP
JMP_ABS:
move.b 1(PC), DATA
lsl.w #8, DATA
move.b (PC), DATA
lea (MEMBASE,DATA.l), PC
NEXT_OP
JMP_IND: /* 65C02 version */
move.b 1(PC), DATA
lsl.w #8, DATA
move.b (PC), DATA
lea 1(MEMBASE,DATA.l), ADDR
move.b (ADDR), DATA
lsl.w #8, DATA
move.b -(ADDR), DATA
lea (MEMBASE,DATA.l), PC
NEXT_OP
JSR:
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b 1(PC), DATA
lsl.w #8, DATA
move.b (PC)+, DATA
move.l DATA, ADDR
sub.l MEMBASE, PC
move.w PC, DATA
move.l ADDR, PC
add.l MEMBASE, PC
ror.w #8, DATA
move.b DATA, (MEMBASE,SP.w)
lsr.w #8, DATA
subq.b #1, SP
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
NEXT_OP
RTS:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
addq.b #1, SP
lsl.w #8, DATA
move.b (MEMBASE,SP.w), DATA
rol.w #8, DATA
lea 1(MEMBASE,DATA.l), PC
swap SP_CC
NEXT_OP
RTI:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
swap SP_CC
clr.w CC
move.b DATA, CC
and.b #0x3C, DATA /* Mask out mapped state */
move.b DATA, STATUS_6502(GLOBAL)
and.b #0xC3, CC
rol.b #2, CC
lea CC_6502_TO_68K(GLOBAL), ADDR
move.b (ADDR,CC.w), CC
bsr.w set_bcd_ops
swap SP_CC
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
addq.b #1, SP
lsl.w #8, DATA
move.b (MEMBASE,SP.w), DATA
rol.w #8, DATA
lea (MEMBASE,DATA.l), PC
swap SP_CC
NEXT_OP
/*
* Special version of PC adjustment routines that check for specific ranges.
* Very Apple ][ specific :-(
*/
BRK_CHK:
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
sub.l MEMBASE, PC /* Push PC + 2 */
move.w PC, DATA
addq #1, DATA
ror.w #8, DATA
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b DATA, (MEMBASE,SP.w)
lsr.w #8, DATA
subq.b #1, SP
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
or.b #CC_B_6502, STATUS_6502(GLOBAL) /* Set BRK flag */
move.b CC, DATA /* Push P */
and.w #0x0F, DATA
lea CC_68K_TO_6502(GLOBAL), ADDR
move.b (ADDR,DATA.w), DATA
or.b STATUS_6502(GLOBAL), DATA
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
or.b #CC_I_6502, STATUS_6502(GLOBAL) /* Set INT flag */
move.l #0xFFFE, DATA /* Load PC from 0xFFFE */
move.w (MEMBASE,DATA.l), DATA
ror.w #8, DATA
move.l DATA, PC
add.l MEMBASE, PC
NEXT_OP
JMP_ABS_CHK:
move.b 1(PC), DATA
lsl.w #8, DATA
move.b (PC), DATA
cmp.w #0xD000, DATA
bcs.b 0f
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
0:
lea (MEMBASE,DATA.l), PC
NEXT_OP
JMP_IND_CHK: /* 65C02 version */
move.b 1(PC), DATA
lsl.w #8, DATA
move.b (PC), DATA
cmp.w #0xD000, DATA
bcs.b 0f
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
0:
lea 1(MEMBASE,DATA.l), ADDR
move.b (ADDR), DATA
lsl.w #8, DATA
move.b -(ADDR), DATA
cmp.w #0xD000, DATA
bcs.b 1f
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
1:
lea (MEMBASE,DATA.l), PC
NEXT_OP
JSR_CHK:
swap SP_CC /* SP is high 16 bits of SP_CC */
move.b 1(PC), DATA
lsl.w #8, DATA
move.b (PC)+, DATA
cmp.w #0xD000, DATA
bcs.b 0f
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
0:
move.l DATA, ADDR
sub.l MEMBASE, PC
move.w PC, DATA
move.l ADDR, PC
add.l MEMBASE, PC
ror.w #8, DATA
move.b DATA, (MEMBASE,SP.w)
lsr.w #8, DATA
subq.b #1, SP
move.b DATA, (MEMBASE,SP.w)
subq.b #1, SP
swap SP_CC
NEXT_OP
RTS_CHK:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
addq.b #1, SP
lsl.w #8, DATA
move.b (MEMBASE,SP.w), DATA
rol.w #8, DATA
cmp.w #0xEFFF, DATA
bcs.b 0f
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
0:
lea 1(MEMBASE,DATA.l), PC
swap SP_CC
NEXT_OP
RTI_CHK:
swap SP_CC /* SP is high 16 bits of SP_CC */
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
swap SP_CC
clr.w CC
move.b DATA, CC
and.b #0x3C, DATA /* Mask out mapped state */
move.b DATA, STATUS_6502(GLOBAL)
and.b #0xC3, CC
rol.b #2, CC
lea CC_6502_TO_68K(GLOBAL), ADDR
move.b (ADDR,CC.w), CC
bsr.w set_bcd_ops
swap SP_CC
addq.b #1, SP
move.b (MEMBASE,SP.w), DATA
addq.b #1, SP
lsl.w #8, DATA
move.b (MEMBASE,SP.w), DATA
rol.w #8, DATA
cmp.w #0xD000, DATA
bcs.b 0f
movem.l #0x1FFF, STATE_6502(GLOBAL)
bsr.w updateLanguageCardMapping
movem.l STATE_6502(GLOBAL), #0x1FFF
0:
lea (MEMBASE,DATA.l), PC
swap SP_CC
NEXT_OP
BRA:
move.b (PC)+, DATA
ext.w DATA
add.w DATA, PC
NEXT_OP
BCS:
move.b (PC)+, DATA
btst #0, CC
beq.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BCC:
move.b (PC)+, DATA
btst #0, CC
bne.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BEQ:
move.b (PC)+, DATA
btst #2, CC
beq.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BNE:
move.b (PC)+, DATA
btst #2, CC
bne.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BMI:
move.b (PC)+, DATA
btst #3, CC
beq.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BPL:
move.b (PC)+, DATA
btst #3, CC
bne.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BVS:
move.b (PC)+, DATA
btst #1, CC
beq.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
BVC:
move.b (PC)+, DATA
btst #1, CC
bne.b .+6
ext.w DATA
add.w DATA, PC
NEXT_OP
LDA_IMM:
move.b (PC)+, ACC
UPDATE_NZ_STATUS
NEXT_OP
LDA_ZP:
EA_ZP
move.b (MEMBASE,EA.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
LDA_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
LDA_ZP_IND:
EA_ZP_IND
LDA_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDA_IND_Y:
EA_IND_Y
LDA_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDA_IND_X:
EA_IND_X
LDA_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDA_ABS:
EA_ABS
LDA_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDA_ABS_Y:
EA_ABS_Y
LDA_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDA_ABS_X:
EA_ABS_X
LDA_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDY_IMM:
move.b (PC)+, Y
UPDATE_NZ_STATUS
NEXT_OP
LDY_ZP:
EA_ZP
move.b (MEMBASE,EA.w), Y
UPDATE_NZ_STATUS
NEXT_OP
LDY_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), Y
UPDATE_NZ_STATUS
NEXT_OP
LDY_ABS:
EA_ABS
LDY_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDY_ABS_X:
EA_ABS_X
LDY_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDX_IMM:
move.b (PC)+, X
UPDATE_NZ_STATUS
NEXT_OP
LDX_ZP:
EA_ZP
move.b (MEMBASE,EA.w), X
UPDATE_NZ_STATUS
NEXT_OP
LDX_ZP_Y:
EA_ZP_Y
move.b (MEMBASE,EA.w), X
UPDATE_NZ_STATUS
NEXT_OP
LDX_ABS:
EA_ABS
LDX_MEM
UPDATE_NZ_STATUS
NEXT_OP
LDX_ABS_Y:
EA_ABS_Y
LDX_MEM
UPDATE_NZ_STATUS
NEXT_OP
STA_ZP:
EA_ZP
move.b ACC, (MEMBASE,EA.w)
NEXT_OP
STA_ZP_X:
EA_ZP_X
move.b ACC, (MEMBASE,EA.w)
NEXT_OP
STA_IND_Y:
EA_IND_Y
STA_MEM
NEXT_OP
STA_IND_X:
EA_IND_X
STA_MEM
NEXT_OP
STA_ABS:
EA_ABS
STA_MEM
NEXT_OP
STA_ABS_Y:
EA_ABS_Y
STA_MEM
NEXT_OP
STA_ABS_X:
EA_ABS_X
STA_MEM
NEXT_OP
STY_ZP:
EA_ZP
move.b Y, (MEMBASE,EA.w)
NEXT_OP
STY_ZP_X:
EA_ZP_X
move.b Y, (MEMBASE,EA.w)
NEXT_OP
STY_ABS:
EA_ABS
STY_MEM
NEXT_OP
STX_ZP_Y:
EA_ZP_Y
move.b X, (MEMBASE,EA.w)
NEXT_OP
STX_ZP:
EA_ZP
move.b X, (MEMBASE,EA.w)
NEXT_OP
STX_ABS:
EA_ABS
STX_MEM
NEXT_OP
STZ_ZP:
EA_ZP
move.b #0, (MEMBASE,EA.w)
NEXT_OP
STZ_ABS:
EA_ABS
clr.w DATA
WR_MEM
NEXT_OP
STZ_ABS_X:
EA_ABS_X
clr.w DATA
WR_MEM
NEXT_OP
TAY:
move.b ACC, Y
UPDATE_NZ_STATUS
NEXT_OP
TYA:
move.b Y, ACC
UPDATE_NZ_STATUS
NEXT_OP
TAX:
move.b ACC, X
UPDATE_NZ_STATUS
NEXT_OP
TXA:
move.b X, ACC
UPDATE_NZ_STATUS
NEXT_OP
TXS:
swap SP_CC
move.b X, SP
swap SP_CC
NEXT_OP
TSX:
swap SP_CC
move.b SP, DATA
swap SP_CC
move.b DATA, X
UPDATE_NZ_STATUS
NEXT_OP
BIT_IMM:
EA_IMM
OP_BIT
NEXT_OP
BIT_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
OP_BIT
NEXT_OP
BIT_ABS:
EA_ABS
RD_MEM
OP_BIT
NEXT_OP
TRB_ABS:
EA_ABS
RD_MEM
OP_TRB
WR_MEM
NEXT_OP
TSB_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
OP_TSB
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
TSB_ABS:
EA_ABS
RD_MEM
OP_TSB
WR_MEM
NEXT_OP
AND_IMM:
and.b (PC)+, ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_ZP:
EA_ZP
and.b (MEMBASE,EA.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_ZP_X:
EA_ZP_X
and.b (MEMBASE,EA.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_ABS:
EA_ABS
RD_MEM
and.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_ABS_Y:
EA_ABS_Y
RD_MEM
and.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_ABS_X:
EA_ABS_X
RD_MEM
and.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_IND_Y:
EA_IND_Y
RD_MEM
and.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
AND_IND_X:
EA_IND_X
RD_MEM
and.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_IMM:
or.b (PC)+, ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_ZP:
EA_ZP
or.b (MEMBASE,EA.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_ZP_X:
EA_ZP_X
or.b (MEMBASE,EA.w), ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_ABS:
EA_ABS
RD_MEM
or.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_ABS_Y:
EA_ABS_Y
RD_MEM
or.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_ABS_X:
EA_ABS_X
RD_MEM
or.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_IND_Y:
EA_IND_Y
RD_MEM
or.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
ORA_IND_X:
EA_IND_X
RD_MEM
or.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_IMM:
EA_IMM
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_ABS:
EA_ABS
RD_MEM
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_ABS_Y:
EA_ABS_Y
RD_MEM
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_ABS_X:
EA_ABS_X
RD_MEM
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_IND_Y:
EA_IND_Y
RD_MEM
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
EOR_IND_X:
EA_IND_X
RD_MEM
eor.b DATA, ACC
UPDATE_NZ_STATUS
NEXT_OP
INC_ZP:
EA_ZP
addq.b #1, (MEMBASE,EA.w)
UPDATE_NZ_STATUS
NEXT_OP
INC_ZP_X:
EA_ZP_X
addq.b #1, (MEMBASE,EA.w)
UPDATE_NZ_STATUS
NEXT_OP
INC_ABS:
EA_ABS
RD_MEM
addq.b #1, DATA
move.w DATA, ADDR
UPDATE_NZ_STATUS
WRA_MEM
NEXT_OP
INC_ABS_X:
EA_ABS_X
RD_MEM
addq.b #1, DATA
move.w DATA, ADDR
UPDATE_NZ_STATUS
WRA_MEM
NEXT_OP
INA:
addq.b #1, ACC
UPDATE_NZ_STATUS
NEXT_OP
INY:
addq.b #1, Y
UPDATE_NZ_STATUS
NEXT_OP
INX:
addq.b #1, X
UPDATE_NZ_STATUS
NEXT_OP
DEC_ZP:
EA_ZP
subq.b #1, (MEMBASE,EA.w)
UPDATE_NZ_STATUS
NEXT_OP
DEC_ZP_X:
EA_ZP_X
subq.b #1, (MEMBASE,EA.w)
UPDATE_NZ_STATUS
NEXT_OP
DEC_ABS:
EA_ABS
RD_MEM
subq.b #1, DATA
move.w DATA, ADDR
UPDATE_NZ_STATUS
WRA_MEM
NEXT_OP
DEC_ABS_X:
EA_ABS_X
RD_MEM
subq.b #1, DATA
move.w DATA, ADDR
UPDATE_NZ_STATUS
WRA_MEM
NEXT_OP
DEA:
subq.b #1, ACC
UPDATE_NZ_STATUS
NEXT_OP
DEY:
subq.b #1, Y
UPDATE_NZ_STATUS
NEXT_OP
DEX:
subq.b #1, X
UPDATE_NZ_STATUS
NEXT_OP
ADC_BIN_IMM:
EA_IMM
OP_ADC_BIN
NEXT_OP
ADC_BIN_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
OP_ADC_BIN
NEXT_OP
ADC_BIN_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
OP_ADC_BIN
NEXT_OP
ADC_BIN_ABS:
EA_ABS
RD_MEM
OP_ADC_BIN
NEXT_OP
ADC_BIN_ABS_X:
EA_ABS_X
RD_MEM
OP_ADC_BIN
NEXT_OP
ADC_BIN_ABS_Y:
EA_ABS_Y
RD_MEM
OP_ADC_BIN
NEXT_OP
ADC_BIN_IND_X:
EA_IND_X
RD_MEM
OP_ADC_BIN
NEXT_OP
ADC_BIN_IND_Y:
EA_IND_Y
RD_MEM
OP_ADC_BIN
NEXT_OP
ADC_BCD_IMM:
EA_IMM
OP_ADC_BCD
NEXT_OP
ADC_BCD_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
OP_ADC_BCD
NEXT_OP
ADC_BCD_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
OP_ADC_BCD
NEXT_OP
ADC_BCD_ABS:
EA_ABS
RD_MEM
OP_ADC_BCD
NEXT_OP
ADC_BCD_ABS_X:
EA_ABS_X
RD_MEM
OP_ADC_BCD
NEXT_OP
ADC_BCD_ABS_Y:
EA_ABS_Y
RD_MEM
OP_ADC_BCD
NEXT_OP
ADC_BCD_IND_X:
EA_IND_X
RD_MEM
OP_ADC_BCD
NEXT_OP
ADC_BCD_IND_Y:
EA_IND_Y
RD_MEM
OP_ADC_BCD
NEXT_OP
SBC_BIN_IMM:
EA_IMM
OP_SBC_BIN
NEXT_OP
SBC_BIN_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
OP_SBC_BIN
NEXT_OP
SBC_BIN_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
OP_SBC_BIN
NEXT_OP
SBC_BIN_ABS:
EA_ABS
RD_MEM
OP_SBC_BIN
NEXT_OP
SBC_BIN_ABS_X:
EA_ABS_X
RD_MEM
OP_SBC_BIN
NEXT_OP
SBC_BIN_ABS_Y:
EA_ABS_Y
RD_MEM
OP_SBC_BIN
NEXT_OP
SBC_BIN_IND_X:
EA_IND_X
RD_MEM
OP_SBC_BIN
NEXT_OP
SBC_BIN_IND_Y:
EA_IND_Y
RD_MEM
OP_SBC_BIN
NEXT_OP
SBC_BCD_IMM:
EA_IMM
OP_SBC_BCD
NEXT_OP
SBC_BCD_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
OP_SBC_BCD
NEXT_OP
SBC_BCD_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
OP_SBC_BCD
NEXT_OP
SBC_BCD_ABS:
EA_ABS
RD_MEM
OP_SBC_BCD
NEXT_OP
SBC_BCD_ABS_X:
EA_ABS_X
RD_MEM
OP_SBC_BCD
NEXT_OP
SBC_BCD_ABS_Y:
EA_ABS_Y
RD_MEM
OP_SBC_BCD
NEXT_OP
SBC_BCD_IND_X:
EA_IND_X
RD_MEM
OP_SBC_BCD
NEXT_OP
SBC_BCD_IND_Y:
EA_IND_Y
RD_MEM
OP_SBC_BCD
NEXT_OP
CMP_IMM:
move.w ACC, DATA
sub.b (PC)+, DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CMP_ZP:
EA_ZP
move.w ACC, DATA
sub.b (MEMBASE,EA.w), DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CMP_ZP_IND:
EA_ZP_IND
RD_MEM
move.w ACC, ADDR
sub.b DATA, ACC
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, ACC
NEXT_OP
CMP_ZP_X:
EA_ZP_X
move.w ACC, DATA
sub.b (MEMBASE,EA.w), DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CMP_IND_Y:
EA_IND_Y
RD_MEM
move.w ACC, ADDR
sub.b DATA, ACC
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, ACC
NEXT_OP
CMP_IND_X:
EA_IND_X
RD_MEM
move.w ACC, ADDR
sub.b DATA, ACC
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, ACC
NEXT_OP
CMP_ABS:
EA_ABS
RD_MEM
move.w ACC, ADDR
sub.b DATA, ACC
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, ACC
NEXT_OP
CMP_ABS_Y:
EA_ABS_Y
RD_MEM
move.w ACC, ADDR
sub.b DATA, ACC
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, ACC
NEXT_OP
CMP_ABS_X:
EA_ABS_X
RD_MEM
move.w ACC, ADDR
sub.b DATA, ACC
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, ACC
NEXT_OP
CPY_IMM:
move.w Y, DATA
sub.b (PC)+, DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CPY_ZP:
EA_ZP
move.w Y, DATA
sub.b (MEMBASE,EA.w), DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CPY_ABS:
EA_ABS
RD_MEM
move.w Y, ADDR
sub.b DATA, Y
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, Y
NEXT_OP
CPX_IMM:
move.w X, DATA
sub.b (PC)+, DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CPX_ZP:
EA_ZP
move.w X, DATA
sub.b (MEMBASE,EA.w), DATA
UPDATE_NZC_STATUS
eor.b #0x11, CC
NEXT_OP
CPX_ABS:
EA_ABS
RD_MEM
move.w X, ADDR
sub.b DATA, X
UPDATE_NZC_STATUS
eor.b #0x11, CC
move.w ADDR, X
NEXT_OP
ASL_ACC:
asl.b #1, ACC
UPDATE_NZC_STATUS
NEXT_OP
ASL_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
asl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
ASL_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
asl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
ASL_ABS:
EA_ABS
RD_MEM
asl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
ASL_ABS_X:
EA_ABS_X
RD_MEM
asl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
LSR_ACC:
lsr.b #1, ACC
UPDATE_NZC_STATUS
NEXT_OP
LSR_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
lsr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
LSR_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
lsr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
LSR_ABS:
EA_ABS
RD_MEM
lsr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
LSR_ABS_X:
EA_ABS_X
RD_MEM
lsr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
ROL_ACC:
move.w CC, %ccr
roxl.b #1, ACC
UPDATE_NZC_STATUS
NEXT_OP
ROL_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
move.w CC, %ccr
roxl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
ROL_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
move.w CC, %ccr
roxl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
ROL_ABS:
EA_ABS
RD_MEM
move.w CC, %ccr
roxl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
ROL_ABS_X:
EA_ABS_X
RD_MEM
move.w CC, %ccr
roxl.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
ROR_ACC:
move.w CC, %ccr
roxr.b #1, ACC
UPDATE_NZC_STATUS
NEXT_OP
ROR_ZP:
EA_ZP
move.b (MEMBASE,EA.w), DATA
move.w CC, %ccr
roxr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
ROR_ZP_X:
EA_ZP_X
move.b (MEMBASE,EA.w), DATA
move.w CC, %ccr
roxr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
move.w ADDR, DATA
move.b DATA, (MEMBASE,EA.w)
NEXT_OP
ROR_ABS:
EA_ABS
RD_MEM
move.w CC, %ccr
roxr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
ROR_ABS_X:
EA_ABS_X
RD_MEM
move.w CC, %ccr
roxr.b #1, DATA
move.w DATA, ADDR
UPDATE_NZC_STATUS
WRA_MEM
NEXT_OP
/*
* Execute 6502 instructions for # of clocks.
*/
.global run6502
run6502:
movem.l #0x7FFE, -(%sp) /* Save all registers */
movem.l STATE_6502_2(GLOBAL), #0x1FFC /* Load 6502 state */
clr.l DATA
sub.l ADDR, ADDR
move.l 60(%sp), INSTRNS /* Load instruction count */
NEXT_OP
opfetch:
clr.w DATA
move.b (PC)+, DATA /* Load opcode */
add.w DATA, DATA
move.w (OPBASE, DATA.w), ADDR
jmp 2(%pc,ADDR.w)
exit6502: /* This MUST follow the previous*/
movem.l #0x1FFC, STATE_6502_2(GLOBAL) /* jmp from opfetch */
movem.l (%sp)+, #0x7FFE
clr.l %d0
rts
#define OP_OFFSET(op) ((op)-exit6502)
/*
* Initialize the CPU state and opcode arrays.
*/
.globl reset6502
reset6502:
movem.l #0xFFFA, -(%sp) /* Save all registers */
/*
* Init CPU state.
*/
move.l 60(%sp), MEMBASE /* Load Pointer to memory */
move.l #0xFFFC, %d0
move.w (MEMBASE,%d0.l), %d0
rol.w #8, %d0
move.l %d0, PC
add.l MEMBASE, PC
lea OPTABLE(0)(GLOBAL), OPBASE
move.l 64(%sp), WRMEM
move.l 68(%sp), RDMEM
move.b #CC_1_6502, STATUS_6502(GLOBAL)
clr.l ACC
clr.l X
clr.l Y
move.l #0x01FF0000, SP_CC
clr.l EA
clr.l PAGE
movem.l #0x1FFC, STATE_6502_2(GLOBAL) /* Save 6502 state */
lea OPTABLE(0)(GLOBAL), %a0
/*
* Set ADC and SBC based on DECIMAL flag.
*/
bsr set_bcd_ops
movem.l (%sp)+, #0x5FFF /* Restore all registers */
rts
/*
* Update the opcode pointers based on the BCD decimal flag.
*/
set_bcd_ops:
btst #3, STATUS_6502(GLOBAL)
bne bcd_ops
move.w #OP_OFFSET(ADC_BIN_IMM), 0x69*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_ZP), 0x65*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_ZP_X), 0x75*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_ABS), 0x6D*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_ABS_X), 0x7D*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_ABS_Y), 0x79*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_IND_X), 0x61*2(OPBASE)
move.w #OP_OFFSET(ADC_BIN_IND_Y), 0x71*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_IMM), 0xE9*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_ZP), 0xE5*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_ZP_X), 0xF5*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_ABS), 0xED*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_ABS_X), 0xFD*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_ABS_Y), 0xF9*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_IND_X), 0xE1*2(OPBASE)
move.w #OP_OFFSET(SBC_BIN_IND_Y), 0xF1*2(OPBASE)
rts
bcd_ops:
move.w #OP_OFFSET(ADC_BCD_IMM), 0x69*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_ZP), 0x65*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_ZP_X), 0x75*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_ABS), 0x6D*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_ABS_X), 0x7D*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_ABS_Y), 0x79*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_IND_X), 0x61*2(OPBASE)
move.w #OP_OFFSET(ADC_BCD_IND_Y), 0x71*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_IMM), 0xE9*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_ZP), 0xE5*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_ZP_X), 0xF5*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_ABS), 0xED*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_ABS_X), 0xFD*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_ABS_Y), 0xF9*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_IND_X), 0xE1*2(OPBASE)
move.w #OP_OFFSET(SBC_BCD_IND_Y), 0xF1*2(OPBASE)
rts
/*
* Update to checked Program Counter range.
*/
.global setPcCheckFuncs
setPcCheckFuncs:
move.w #OP_OFFSET(BRK_CHK), OPTABLE(0x00*2)(GLOBAL)
move.w #OP_OFFSET(JSR_CHK), OPTABLE(0x20*2)(GLOBAL)
move.w #OP_OFFSET(RTI_CHK), OPTABLE(0x40*2)(GLOBAL)
move.w #OP_OFFSET(JMP_ABS_CHK), OPTABLE(0x4C*2)(GLOBAL)
move.w #OP_OFFSET(RTS_CHK), OPTABLE(0x60*2)(GLOBAL)
move.w #OP_OFFSET(JMP_IND_CHK), OPTABLE(0x6C*2)(GLOBAL)
rts
/*
* Update to unchecked Program Counter range.
*/
.global clrPcCheckFuncs
clrPcCheckFuncs:
move.w #OP_OFFSET(BRK), OPTABLE(0x00*2)(GLOBAL)
move.w #OP_OFFSET(JSR), OPTABLE(0x20*2)(GLOBAL)
move.w #OP_OFFSET(RTI), OPTABLE(0x40*2)(GLOBAL)
move.w #OP_OFFSET(JMP_ABS), OPTABLE(0x4C*2)(GLOBAL)
move.w #OP_OFFSET(RTS), OPTABLE(0x60*2)(GLOBAL)
move.w #OP_OFFSET(JMP_IND), OPTABLE(0x6C*2)(GLOBAL)
rts
.data
.even
.global opTable6502
opTable6502:
/*
* 0x00 - 0x0F
*/
.word OP_OFFSET(BRK)
.word OP_OFFSET(ORA_IND_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(TSB_ZP)
.word OP_OFFSET(ORA_ZP)
.word OP_OFFSET(ASL_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(PHP)
.word OP_OFFSET(ORA_IMM)
.word OP_OFFSET(ASL_ACC)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(TSB_ABS)
.word OP_OFFSET(ORA_ABS)
.word OP_OFFSET(ASL_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x10 - 0x1F
*/
.word OP_OFFSET(BPL)
.word OP_OFFSET(ORA_IND_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(ORA_ZP_X)
.word OP_OFFSET(ASL_ZP_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CLC)
.word OP_OFFSET(ORA_ABS_Y)
.word OP_OFFSET(INA)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(TRB_ABS)
.word OP_OFFSET(ORA_ABS_X)
.word OP_OFFSET(ASL_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x20 - 0x2F
*/
.word OP_OFFSET(JSR)
.word OP_OFFSET(AND_IND_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(BIT_ZP)
.word OP_OFFSET(AND_ZP)
.word OP_OFFSET(ROL_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(PLP)
.word OP_OFFSET(AND_IMM)
.word OP_OFFSET(ROL_ACC)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(BIT_ABS)
.word OP_OFFSET(AND_ABS)
.word OP_OFFSET(ROL_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x30 - 0x3F
*/
.word OP_OFFSET(BMI)
.word OP_OFFSET(AND_IND_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(AND_ZP_X)
.word OP_OFFSET(ROL_ZP_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(SEC)
.word OP_OFFSET(AND_ABS_Y)
.word OP_OFFSET(DEA)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(AND_ABS_X)
.word OP_OFFSET(ROL_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x40 - 0x4F
*/
.word OP_OFFSET(RTI)
.word OP_OFFSET(EOR_IND_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(EOR_ZP)
.word OP_OFFSET(LSR_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(PHA)
.word OP_OFFSET(EOR_IMM)
.word OP_OFFSET(LSR_ACC)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(JMP_ABS)
.word OP_OFFSET(EOR_ABS)
.word OP_OFFSET(LSR_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x50 - 0x5F
*/
.word OP_OFFSET(BVC)
.word OP_OFFSET(EOR_IND_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(EOR_ZP_X)
.word OP_OFFSET(LSR_ZP_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CLI)
.word OP_OFFSET(EOR_ABS_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(EOR_ABS_X)
.word OP_OFFSET(LSR_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x60 - 0x6F
*/
.word OP_OFFSET(RTS)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(STZ_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(ROR_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(PLA)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(ROR_ACC)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(JMP_IND)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(ROR_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x70 - 0x7F
*/
.word OP_OFFSET(BVS)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(ROR_ZP_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(SEI)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(ROR_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x80 - 0x8F
*/
.word OP_OFFSET(BRA)
.word OP_OFFSET(STA_IND_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(STY_ZP)
.word OP_OFFSET(STA_ZP)
.word OP_OFFSET(STX_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(DEY)
.word OP_OFFSET(BIT_IMM)
.word OP_OFFSET(TXA)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(STY_ABS)
.word OP_OFFSET(STA_ABS)
.word OP_OFFSET(STX_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0x90 - 0x9F
*/
.word OP_OFFSET(BCC)
.word OP_OFFSET(STA_IND_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(STY_ZP_X)
.word OP_OFFSET(STA_ZP_X)
.word OP_OFFSET(STX_ZP_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(TYA)
.word OP_OFFSET(STA_ABS_Y)
.word OP_OFFSET(TXS)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(STZ_ABS)
.word OP_OFFSET(STA_ABS_X)
.word OP_OFFSET(STZ_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0xA0 - 0xAF
*/
.word OP_OFFSET(LDY_IMM)
.word OP_OFFSET(LDA_IND_X)
.word OP_OFFSET(LDX_IMM)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(LDY_ZP)
.word OP_OFFSET(LDA_ZP)
.word OP_OFFSET(LDX_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(TAY)
.word OP_OFFSET(LDA_IMM)
.word OP_OFFSET(TAX)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(LDY_ABS)
.word OP_OFFSET(LDA_ABS)
.word OP_OFFSET(LDX_ABS)
.word exit6502-UNIMPLEMENTED
/*
* 0xB0 - 0xBF
*/
.word OP_OFFSET(BCS)
.word OP_OFFSET(LDA_IND_Y)
.word OP_OFFSET(LDA_ZP_IND)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(LDY_ZP_X)
.word OP_OFFSET(LDA_ZP_X)
.word OP_OFFSET(LDX_ZP_Y)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CLV)
.word OP_OFFSET(LDA_ABS_Y)
.word OP_OFFSET(TSX)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(LDY_ABS_X)
.word OP_OFFSET(LDA_ABS_X)
.word OP_OFFSET(LDX_ABS_Y)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0xC0 - 0xCF
*/
.word OP_OFFSET(CPY_IMM)
.word OP_OFFSET(CMP_IND_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CPY_ZP)
.word OP_OFFSET(CMP_ZP)
.word OP_OFFSET(DEC_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(INY)
.word OP_OFFSET(CMP_IMM)
.word OP_OFFSET(DEX)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CPY_ABS)
.word OP_OFFSET(CMP_ABS)
.word OP_OFFSET(DEC_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0xD0 - 0xDF
*/
.word OP_OFFSET(BNE)
.word OP_OFFSET(CMP_IND_Y)
.word OP_OFFSET(CMP_ZP_IND)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CMP_ZP_X)
.word OP_OFFSET(DEC_ZP_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CLD)
.word OP_OFFSET(CMP_ABS_Y)
.word OP_OFFSET(PHX)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CMP_ABS_X)
.word OP_OFFSET(DEC_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0xE0 - 0xEF
*/
.word OP_OFFSET(CPX_IMM)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CPX_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(INC_ZP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(INX)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(NOP)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(CPX_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(INC_ABS)
.word OP_OFFSET(UNIMPLEMENTED)
/*
* 0xF0 - 0xFF
*/
.word OP_OFFSET(BEQ)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(INC_ZP_X)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(SED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(PLX)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(UNIMPLEMENTED)
.word OP_OFFSET(INC_ABS_X)
.word OP_OFFSET(UNIMPLEMENTED)
.even
.comm state6502, 13*4
.comm status6502, 1