Files

2209 lines
25 KiB
NASM
Raw Permalink Normal View History

2023-03-13 08:36:51 +00:00
;
; 65C02 Engine
; Written by Daryl Rictor
; (c) 2012
;
; Xl,Xh = PC
; Yl, Yh = Stack ptr
; Zl, Zh = memory access
; GPIOR0 = EEPROM write control
.def AR = R18 ; must be above R15
.def XR = R14
.def YR = R15
.def SR = R19
.def AVSR = R20
.def IRV = R21
.def IFLAG = R5
;SR bit weights
.set ss = 0x80
.set so = 0x40
.set sx = 0x20
.set sb = 0x10
.set sd = 0x08
.set si = 0x04
.set sz = 0x02
.set sc = 0x01
;SR bit positions
.set ssp = 7
.set sop = 6
.set sxp = 5
.set sbp = 4
.set sdp = 3
.set sip = 2
.set szp = 1
.set scp = 0
;AVR bit weights
.set ai = 0x80
.set at = 0x40
.set ah = 0x20
.set as = 0x10
.set av = 0x08
.set an = 0x04
.set az = 0x02
.set ac = 0x01
;AVR Sreg Bit positions
.set aip = 7
.set atp = 6
.set ahp = 5
.set asp = 4
.set avp = 3
.set anp = 2
.set azp = 1
.set acp = 0
; zero page RAM location
.set ZP = 0x01 ; zero page in SRAM
;**********************
; general macros
;**********************
.macro SVSR
in avsr, SREG
.endmacro
.macro LDSR
out sreg, avsr
.endmacro
.macro AV2SR
mov zl, avsr
ldi zh, high(tav2sr*2)
lpm i, Z
andi sr, sx+sb+sd+si
or sr, i
.endmacro
.macro SR2AV
mov zl, sr
ldi zh, high(tsr2av*2)
lpm avsr, Z
out sreg, avsr ; used to update I flag
.endmacro
;*******************************
; CPU execution macro
;*******************************
.macro EXEC
sbrc IFLAG, 0 ; if IRQ triggered
rcall INTJMP
movw ZL, XL ;
adiw XL, 1 ;
cp zh, mmap ; IO page
brcs RAM
ROM: ; and IO, which will return EA - nop
lpm zl, Z
ldi zh, high(opctbl)
lsl zl
adc zh, zero ; pointer to opcode jump
ijmp ; call opc code
RAM:
inc zh
ld zl, Z
ldi zh, high(opctbl)
lsl zl
adc zh, zero ; pointer to opcode jump
ijmp ; call opc code
INTJMP:
jmp cpu_irq ; execute it now
.endmacro
;**********************
; Memory Access macros
;**********************
.macro READ
cp zh, mmap ; IO page
breq IO
brcs RAM
ROM:
lpm i, Z
rjmp done
IO:
cpi zl, 0x20
brcs IOR1
ldi zh, 0x00
ld i, Z
mov zh, mmap
rjmp done
IOR1:
mov i, irv ; interrupt vector
rjmp done
RAM:
inc zh
ld i, Z
dec zh
done:
.endmacro
.macro READZ
cp zh, mmap ; IO page
breq IO
brcs RAM
ROM:
lpm zl, Z
rjmp done
IO:
cpi zl, 0x20
brcs IOR1
ldi zh, 0x00
rjmp RAM1
IOR1:
mov zl, irv ; interrupt vector
rjmp done
RAM:
inc zh
RAM1:
ld zl, Z
done:
.endmacro
.macro READ2
cp zh, mmap ; IO page
breq IO
brcs RAM
ROM:
lpm i, Z+
lpm j, Z
rjmp done
IO:
cpi zl, 0x20 ; *** reading 0x1f will result in no read of 0x20
brcc IOR21
mov i, irv ; interrupt vector
mov j, zero
rjmp done
IOR21:
ldi ZH, 0xff ; *** reading IO 0xff will result in reading 0xff and RAM 0x100 vs. ROM
RAM:
inc zh
ld i, Z+
ld j, Z
done:
movw ZL, i
.endmacro
.macro READZP
ldi ZH, ZP
ld i, Z
.endmacro
.macro READ2ZP
ldi ZH, ZP
ld i, Z
inc zl
ld j, Z
movw ZL, i
.endmacro
.macro WRITE
cp zh, mmap ; IO page
breq IO
brcc done ; ROM
RAM:
inc zh
st Z, i
rjmp done
IO:
cpi zl, 0x20 ; writes to 0x00 - 0x1f will result in EEPROM Write
brcc IOW1
in i, gpior0 ; if GPIOR0 is set to 5A and write to $3F0x or $3F1x,
cpi i, 0x5a ; then do a write eeprom sequence
brne done ; besure to set GPIOR0 <> 5A for safety
sbi eecr, EEMPE
sbi eecr, EEPE
rjmp done
IOW1:
clr ZH
st Z, i
done:
.endmacro
.macro WRITEZP
st Z, i
.endmacro
;**********************
; address mode macros
;**********************
.macro _ABS
READ2
adiw XL, 0x02
.endmacro
.macro _ABSX
READ2
add ZL, XR
adc ZH, ZERO ; test for overflow
adiw XL, 0x02
.endmacro
.macro _ABSY
READ2
add ZL, YR
adc ZH, ZERO ; test for overflow
adiw XL, 0x02
.endmacro
.macro _IMM
; imm Z already set
adiw XL, 0x01
.endmacro
.macro _IMP
.endmacro
.macro _INDX
READZ
add ZL, XR
READ2ZP
adiw XL, 0x01
.endmacro
.macro _INDY
READZ
READ2ZP
add ZL, YR
adc ZH, zero
adiw XL, 0x01
.endmacro
.macro _IZPG
READZ
READ2ZP
adiw XL, 0x01
.endmacro
.macro _REL
movw zl, XL
READZ
sec ; add 1 to PC using C flag
tst zl
brmi back
adc XL, zl
adc XH, zero
rjmp done
back:
adc XL, zl
brcs done
dec XH
done:
.endmacro
.macro _ZPG
READZ
adiw XL, 0x01
.endmacro
.macro _ZPGX
READZ
add ZL, XR
adiw XL, 0x01
.endmacro
.macro _ZPGY
READZ
add ZL, YR
adiw XL, 0x01
.endmacro
;**********************
; opcode macros
;**********************
.macro _ADC
READZ
LDSR
adc ar, zl
sbrs sr, sdp ; check decimal mode
rjmp _ADC1
in j, sreg ; save flags
ldi i, 0x66
add AR, i
brcc BCDA0
ori j, 0x01 ; c flag set
BCDA0:
sbrc j, 0 ; c flag
andi i, 0x0F ;
brhc BCDA1
ori j, 0x20 ; HC=1
BCDA1:
sbrc j, 5 ; HC
andi i, 0xF0
sub AR, i
ror j ; restore C
tst ar ; set N,Z
_ADC1:
SVSR
bst avsr, avp ; get V flag
bld avsr, atp ; move to T flag
.endmacro
.macro _ADCZ
READZP
LDSR
adc ar, i
sbrs sr, sdp ; check decimal mode
rjmp _ADC1
in j, sreg ; save flags
ldi i, 0x66
add AR, i
brcc BCDA0
ori j, 0x01 ; c flag set
BCDA0:
sbrc j, 0 ; c flag
andi i, 0x0F ;
brhc BCDA1
ori j, 0x20 ; HC=1
BCDA1:
sbrc j, 5 ; HC
andi i, 0xF0
sub AR, i
ror j ; restore C
tst ar ; set N,Z
_ADC1:
SVSR
bst avsr, avp ; get V flag
bld avsr, atp ; move to T flag
.endmacro
.macro _AND
READZ
LDSR
and ar, zl
SVSR
.endmacro
.macro _ANDZ
READZP
LDSR
and ar, i
SVSR
.endmacro
.macro _ASL
READ
LDSR
lsl i
SVSR
WRITE
.endmacro
.macro _ASLZ
READZP
LDSR
lsl i
SVSR
WRITEZP
.endmacro
.macro _BBR ; passed bit test byte as parameter
movw zl, XL ;
adiw XL, 0x02 ; move PC to next instruction
READ2 ; i=zp addr, j= branch
READZP
andi i, @0 ; test bit
brne done
tst j ; test for forward or backward
brmi back
add XL, j
adc XH, zero
rjmp done
back:
add XL, j
brcs done
dec XH
done:
.endmacro
.macro _BBS ; passed bit test byte as parameter
movw zl, XL
adiw XL, 0x02 ; move PC to next instruction
READ2
READZP
andi i, @0 ; test bit
breq done
tst j ; test for forward or backward
brmi back
add XL, j
adc XH, zero
rjmp done
back:
add XL, j
brcs done
dec XH
done:
.endmacro
.macro _BIT
READZ
mov j, zl
LDSR
and zl, ar
SVSR
bst j, ssp
bld avsr, anp
bst j, sop
bld avsr, atp ; V to T
.endmacro
.macro _BITZ
READZP
mov j, i
LDSR
and i, ar
SVSR
bst j, ssp
bld avsr, anp
bst j, sop
bld avsr, atp ; V to T
.endmacro
.macro _CMP
READZ
LDSR
cp ar, zl
SVSR
eor avsr, one ; toggle C bit
.endmacro
.macro _CMPZ
READZP
LDSR
cp ar, i
SVSR
eor avsr, one ; toggle C bit
.endmacro
.macro _CPX
READZ
LDSR
cp xr, zl
SVSR
eor avsr, one ; toggle C bit
.endmacro
.macro _CPXZ
READZP
LDSR
cp xr, i
SVSR
eor avsr, one ; toggle C bit
.endmacro
.macro _CPY
READZ
LDSR
cp yr, zl
SVSR
eor avsr, one ; toggle C bit
.endmacro
.macro _CPYZ
READZP
LDSR
cp yr, i
SVSR
eor avsr, one ; toggle C bit
.endmacro
.macro _DEC
READ
LDSR
dec i
SVSR
WRITE
.endmacro
.macro _DECZ
READZP
LDSR
dec i
SVSR
WRITEZP
.endmacro
.macro _EOR
READZ
LDSR
eor ar, zl
SVSR
.endmacro
.macro _EORZ
READZP
LDSR
eor ar, i
SVSR
.endmacro
.macro _INC
READ
LDSR
inc i
SVSR
WRITE
.endmacro
.macro _INCZ
READZP
LDSR
inc i
SVSR
WRITEZP
.endmacro
.macro _LDA
READZ
LDSR
mov ar, zl
tst ar
SVSR
.endmacro
.macro _LDAZ
READZP
LDSR
mov ar, i
tst ar
SVSR
.endmacro
.macro _LDX
READZ
LDSR
mov xr, zl
tst xr
SVSR
.endmacro
.macro _LDXZ
READZP
LDSR
mov xr, i
tst xr
SVSR
.endmacro
.macro _LDY
READZ
LDSR
mov yr, zl
tst yr
SVSR
.endmacro
.macro _LDYZ
READZP
LDSR
mov yr, i
tst yr
SVSR
.endmacro
.macro _LSR
READ
LDSR
lsr i
SVSR
WRITE
.endmacro
.macro _LSRZ
READZP
LDSR
lsr i
SVSR
WRITEZP
.endmacro
.macro _ORA
READZ
LDSR
or ar, zl
SVSR
.endmacro
.macro _ORAZ
READZP
LDSR
or ar, i
SVSR
.endmacro
.macro _RMB ; passed bit pos byte as parameter
movw zl, XL
_ZPG
READZP
andi i, @0 ; reset bit
WRITEZP
.endmacro
.macro _ROL
READ
LDSR
rol i
SVSR
WRITE
.endmacro
.macro _ROLZ
READZP
LDSR
rol i
SVSR
WRITEZP
.endmacro
.macro _ROR
READ
LDSR
ror i
SVSR
WRITE
.endmacro
.macro _RORZ
READZP
LDSR
ror i
SVSR
WRITEZP
.endmacro
.macro _SBC
READZ
eor avsr, one ; toggle C bit
LDSR
SEZ
sbc ar, zl
sbrs sr, sdp ; check decimal mode
rjmp _SBC1
in i, sreg
sub_0:
brhc sub_1 ; if half carry not clear
subi ar, 0x06 ; LSD = LSD - 6
sub_1:
sbrs i, 0 ; if previous carry not set
rjmp sub_2 ; skip upper digit fix
subi ar, 0x60 ; subtract 6 from MSD
rol i ; set carry in bit 0 of i
eor i, one ; toggle C bit
sub_2:
ror i ; restore carry flag
tst ar ; set N,V,Z
_SBC1:
SVSR
bst avsr, avp ; mov V flag
bld avsr, atp ; to T flag
eor avsr, one ; toggle C bit
.endmacro
.macro _SBCZ
READZP
eor avsr, one ; toggle C bit
LDSR
SEZ
sbc ar, i
sbrs sr, sdp ; check decimal mode
rjmp _SBC1
in i, sreg
sub_0:
brhc sub_1 ; if half carry not clear
subi ar, 0x06 ; LSD = LSD - 6
sub_1:
sbrs i, 0 ; if previous carry not set
rjmp sub_2 ; skip upper digit fix
subi ar, 0x60 ; subtract 6 from MSD
rol i ; set carry in bit 0 of i
eor i, one ; toggle C bit
sub_2:
ror i ; restore carry flag
tst ar ; set N,V,Z
_SBC1:
SVSR
bst avsr, avp ; mov V flag
bld avsr, atp ; to T flag
eor avsr, one ; toggle C bit
.endmacro
.macro _SMB ; passed bit pos byte as parameter
movw zl, XL
_ZPG
READZP
ori i, @0 ; set bit
WRITEZP
.endmacro
.macro _STA
mov i, ar
WRITE
.endmacro
.macro _STAZ
mov i, ar
ldi ZH, ZP
WRITEZP
.endmacro
.macro _STP
.endmacro
.macro _STX
mov i, xr
WRITE
.endmacro
.macro _STXZ
mov i, xr
ldi ZH, ZP
WRITEZP
.endmacro
.macro _STY
mov i, yr
WRITE
.endmacro
.macro _STYZ
mov i, yr
ldi ZH, ZP
WRITEZP
.endmacro
.macro _STZ
ldi i, 0x00
WRITE
.endmacro
.macro _STZZ
ldi i, 0x00
ldi ZH, ZP
WRITEZP
.endmacro
.macro _TRB
READ
cbr avsr, az ; Z
mov j, ar
and j, i
brne fin
ori avsr, az ; Z set
fin:
mov j, ar
com j
and i, j
WRITE
.endmacro
.macro _TRBZ
READZP
cbr avsr, az ; Z
mov j, ar
and j, i
brne fin
ori avsr, az ; Z set
fin:
mov j, ar
com j
and i, j
WRITEZP
.endmacro
.macro _TSB
READ
cbr avsr, az ; Z
mov j, ar
and j, i
brne fin
ori avsr, az ; Z set
fin:
or i, ar
WRITE
.endmacro
.macro _TSBZ
READZP
cbr avsr, az ; Z
mov j, ar
and j, i
brne fin
ori avsr, az ; Z set
fin:
or i, ar
WRITEZP
.endmacro
.macro _WAI
.endmacro
;**********************
; Opcode execute code
;**********************
_INV:
EXEC
_INV2:
adiw XL, 1
EXEC
_INV3:
adiw XL, 2
EXEC
_BRK_IMP: ;00
adiw XL, 1
st Y, XH
dec yl
st Y, XL
dec yl
AV2SR
ori sr, sb ; brk bit
st Y, sr
dec yl
andi sr, ss+so+sx+si+sz+sc ; clr D & B
ori sr, si ; set I
ldi ZL, 0xfe
ldi ZH, 0xff
lpm XL, Z+
lpm XH, Z
EXEC
_ORA_INDX: ;01
movw zl, XL
_INDX
_ORA
EXEC
_TSB_ZPG: ;04
movw zl, XL
_ZPG
_TSBZ
EXEC
_ORA_ZPG: ;05
movw zl, XL
_ZPG
_ORAZ
EXEC
_ASL_ZPG: ;06
movw zl, XL
_ZPG
_ASLZ
EXEC
_RMB0_ZPG: ;07
_RMB 0xFE
EXEC
_PHP_IMP: ;08
AV2SR
st Y, sr
dec yl
EXEC
_ORA_IMM: ;09
movw zl, XL
_IMM
_ORA
EXEC
_ASL_IMP: ;0A
LDSR
lsl ar
SVSR
EXEC
_TSB_ABS: ;0C
movw zl, XL
_ABS
_TSB
EXEC
_ORA_ABS: ;0D
movw zl, XL
_ABS
_ORA
EXEC
_ASL_ABS: ;0E
movw zl, XL
_ABS
_ASL
EXEC
_BBR0_REL: ;0F
_BBR 0x01
EXEC
_BPL_REL: ;10
sbrc avsr, anp
rjmp _BPL1
_REL
EXEC
_BPL1:
adiw xl, 1
EXEC
_ORA_INDY: ;11
movw zl, XL
_INDY
_ORA
EXEC
_ORA_IND: ;12
movw zl, XL
_IZPG
_ORA
EXEC
_TRB_ZPG: ;14
movw zl, XL
_ZPG
_TRBZ
EXEC
_ORA_ZPGX: ;15
movw zl, XL
_ZPGX
_ORAZ
EXEC
_ASL_ZPGX: ;16
movw zl, XL
_ZPGX
_ASLZ
EXEC
_RMB1_ZPG: ;17
_RMB 0xFD
EXEC
_CLC_IMP: ;18
cbr avsr, ac
EXEC
_ORA_ABSY: ;19
movw zl, XL
_ABSY
_ORA
EXEC
_INC_IMP: ;1A
LDSR
inc ar
SVSR
EXEC
_TRB_ABS: ;1C
movw zl, XL
_ABS
_TRB
EXEC
_ORA_ABSX: ;1D
movw zl, XL
_ABSX
_ORA
EXEC
_ASL_ABSX: ;1E
movw zl, XL
_ABSX
_ASL
EXEC
_BBR1_REL: ;1F
_BBR 0x02
EXEC
_JSR_ABS: ;20
movw zl, XL
READ2
adiw XL, 0x01
st Y, XH
dec yl
st Y, XL
dec yl
movw XL, i
EXEC
_AND_INDX: ;21
movw zl, XL
_INDX
_AND
EXEC
_BIT_ZPG: ;24
movw zl, XL
_ZPG
_BITZ
EXEC
_AND_ZPG: ;25
movw zl, XL
_ZPG
_ANDZ
EXEC
_ROL_ZPG: ;26
movw zl, XL
_ZPG
_ROLZ
EXEC
_RMB2_ZPG: ;27
_RMB 0xFB
EXEC
_PLP_IMP: ;28
inc yl
ld sr, Y
ori sr, sb ; ***???
ori sr, sx ; ensure always 1
SR2AV
EXEC
_AND_IMM: ;29
movw zl, XL
_IMM
_AND
EXEC
_ROL_IMP: ;2A
LDSR
rol ar
SVSR
EXEC
_BIT_ABS: ;2C
movw zl, XL
_ABS
_BIT
EXEC
_AND_ABS: ;2D
movw zl, XL
_ABS
_AND
EXEC
_ROL_ABS: ;2E
movw zl, XL
_ABS
_ROL
EXEC
_BBR2_REL: ;2F
_BBR 0x04
EXEC
_BMI_REL: ;30
sbrs avsr, anp
rjmp _BMI1
_REL
EXEC
_BMI1:
adiw xl, 1
EXEC
_AND_INDY: ;31
movw zl, XL
_INDY
_AND
EXEC
_AND_IND: ;32
movw zl, XL
_IZPG
_AND
EXEC
_BIT_ZPGX: ;34
movw zl, XL
_ZPGX
_BITZ
EXEC
_AND_ZPGX: ;35
movw zl, XL
_ZPGX
_ANDZ
EXEC
_ROL_ZPGX: ;36
movw zl, XL
_ZPGX
_ROLZ
EXEC
_RMB3_ZPG: ;37
_RMB 0xF7
EXEC
_SEC_IMP: ;38
ori avsr, ac
EXEC
_AND_ABSY: ;39
movw zl, XL
_ABSY
_AND
EXEC
_DEC_IMP: ;3A
LDSR
dec ar
SVSR
EXEC
_BIT_ABSX: ;3C
movw zl, XL
_ABSX
_BIT
EXEC
_AND_ABSX: ;3D
movw zl, XL
_ABSX
_AND
EXEC
_ROL_ABSX: ;3E
movw zl, XL
_ABSX
_ROL
EXEC
_BBR3_REL: ;3F
_BBR 0x08
EXEC
_RTI_IMP: ;40
inc yl
ld sr, Y
inc yl
ld XL, Y
inc yl
ld XH, Y
SR2AV
EXEC
_EOR_INDX: ;41
movw zl, XL
_INDX
_EOR
EXEC
_EOR_ZPG: ;45
movw zl, XL
_ZPG
_EORZ
EXEC
_LSR_ZPG: ;46
movw zl, XL
_ZPG
_LSRZ
EXEC
_RMB4_ZPG: ;47
_RMB 0xEF
EXEC
_PHA_IMP: ;48
st Y, ar
dec yl
EXEC
_EOR_IMM: ;49
movw zl, XL
_IMM
_EOR
EXEC
_LSR_IMP: ;4A
LDSR
lsr ar
SVSR
EXEC
_JMP_ABS: ;4C
movw zl, XL
READ2
movw xl, i
EXEC
_EOR_ABS: ;4D
movw zl, XL
_ABS
_EOR
EXEC
_LSR_ABS: ;4E
movw zl, XL
_ABS
_LSR
EXEC
_BBR4_REL: ;4F
_BBR 0x10
EXEC
_BVC_REL: ;50
sbrc avsr, atp
rjmp _BVC1
_REL
EXEC
_BVC1:
adiw xl, 1
EXEC
_EOR_INDY: ;51
movw zl, XL
_INDY
_EOR
EXEC
_EOR_IND: ;52
movw zl, XL
_IZPG
_EOR
EXEC
_EOR_ZPGX: ;55
movw zl, XL
_ZPGX
_EORZ
EXEC
_LSR_ZPGX: ;56
movw zl, XL
_ZPGX
_LSRZ
EXEC
_RMB5_ZPG: ;57
_RMB 0xDF
EXEC
_CLI_IMP: ;58
andi sr, ss+so+sx+sb+sd+sz+sc
sei
EXEC
_EOR_ABSY: ;59
movw zl, XL
_ABSY
_EOR
EXEC
_PHY_IMP: ;5A
st Y, yr
dec yl
EXEC
_EOR_ABSX: ;5D
movw zl, XL
_ABSX
_EOR
EXEC
_LSR_ABSX: ;5E
movw zl, XL
_ABSX
_LSR
EXEC
_BBR5_REL: ;5F
_BBR 0x20
EXEC
_RTS_IMP: ;60
inc yl
ld XL, Y
inc yl
ld XH, Y
adiw XL, 0x01
EXEC
_ADC_INDX: ;61
movw zl, XL
_INDX
_ADC
EXEC
_STZ_ZPG: ;64
movw zl, XL
_ZPG
_STZZ
EXEC
_ADC_ZPG: ;65
movw zl, XL
_ZPG
_ADCZ
EXEC
_ROR_ZPG: ;66
movw zl, XL
_ZPG
_RORZ
EXEC
_RMB6_ZPG: ;67
_RMB 0xBF
EXEC
_PLA_IMP: ;68
inc yl
ld ar, Y
LDSR
tst ar
SVSR
EXEC
_ADC_IMM: ;69
movw zl, XL
_IMM
_ADC
EXEC
_ROR_IMP: ;6A
LDSR
ror ar
SVSR
EXEC
_JMP_JIND: ;6C
movw zl, XL
READ2
READ2
movw XL, i
EXEC
_ADC_ABS: ;6D
movw zl, XL
_ABS
_ADC
EXEC
_ROR_ABS: ;6E
movw zl, XL
_ABS
_ROR
EXEC
_BBR6_REL: ;6F
_BBR 0x40
EXEC
_BVS_REL: ;70
sbrs avsr, atp
rjmp _BVS1
_REL
EXEC
_BVS1:
adiw xl, 1
EXEC
_ADC_INDY: ;71
movw zl, XL
_INDY
_ADC
EXEC
_ADC_IND: ;72
movw zl, XL
_IZPG
_ADC
EXEC
_STZ_ZPGX: ;74
movw zl, XL
_ZPGX
_STZZ
EXEC
_ADC_ZPGX: ;75
movw zl, XL
_ZPGX
_ADCZ
EXEC
_ROR_ZPGX: ;76
movw zl, XL
_ZPGX
_RORZ
EXEC
_RMB7_ZPG: ;77
_RMB 0x7F
EXEC
_SEI_IMP: ;78
ori sr, si
cli
EXEC
_ADC_ABSY: ;79
movw zl, XL
_ABSY
_ADC
EXEC
_PLY_IMP: ;7A
inc yl
ld yr, Y
LDSR
tst yr
SVSR
EXEC
_JMP_JINDX: ;7C
movw zl, XL
READ2
add ZL, XR
adc ZH, ZERO
READ2
movw XL, i
EXEC
_ADC_ABSX: ;7D
movw zl, XL
_ABSX
_ADC
EXEC
_ROR_ABSX: ;7E
movw zl, XL
_ABSX
_ROR
EXEC
_BBR7_REL: ;7F
_BBR 0x80
EXEC
_BRA_REL: ;80
_REL
EXEC
_STA_INDX: ;81
movw zl, XL
_INDX
_STA
EXEC
_STY_ZPG: ;84
movw zl, XL
_ZPG
_STYZ
EXEC
_STA_ZPG: ;85
movw zl, XL
_ZPG
_STAZ
EXEC
_STX_ZPG: ;86
movw zl, XL
_ZPG
_STXZ
EXEC
_SMB0_ZPG: ;87
_SMB 0x01
EXEC
_DEY_IMP: ;88
LDSR
dec yr
SVSR
EXEC
_BIT_IMM: ;89
movw zl, XL
_IMM
READZ
and zl, ar
in i, SREG ; save zero bit
andi i, az ; mask zero bit
andi avsr, 0xFd ; clear zero bit
or avsr, i
EXEC
_TXA_IMP: ;8A
LDSR
mov ar, xr
tst ar
SVSR
EXEC
_STY_ABS: ;8C
movw zl, XL
_ABS
_STY
EXEC
_STA_ABS: ;8D
movw zl, XL
_ABS
_STA
EXEC
_STX_ABS: ;8E
movw zl, XL
_ABS
_STX
EXEC
_BBS0_REL: ;8F
_BBS 0x01
EXEC
_BCC_REL: ;90
sbrc avsr, acp
rjmp _BCC1
_REL
EXEC
_BCC1:
adiw xl, 1
EXEC
_STA_INDY: movw zl, XL ;91
_INDY
_STA
EXEC
_STA_IND: ;92
movw zl, XL
_IZPG
_STA
EXEC
_STY_ZPGX: ;94
movw zl, XL
_ZPGX
_STYZ
EXEC
_STA_ZPGX: ;95
movw zl, XL
_ZPGX
_STAZ
EXEC
_STX_ZPGY: ;96
movw zl, XL
_ZPGY
_STXZ
EXEC
_SMB1_ZPG: ;97
_SMB 0x02
EXEC
_TYA_IMP: ;98
LDSR
mov ar, yr
tst ar
SVSR
EXEC
_STA_ABSY: ;99
movw zl, XL
_ABSY
_STA
EXEC
_TXS_IMP: ;9A
mov YL, xr
EXEC
_STZ_ABS: ;9C
movw zl, XL
_ABS
_STZ
EXEC
_STA_ABSX: ;9D
movw zl, XL
_ABSX
_STA
EXEC
_STZ_ABSX: ;9E
movw zl, XL
_ABSX
_STZ
EXEC
_BBS1_REL: ;9F
_BBS 0x02
EXEC
_LDY_IMM: ;A0
movw zl, XL
_IMM
_LDY
EXEC
_LDA_INDX: ;A1
movw zl, XL
_INDX
_LDA
EXEC
_LDX_IMM: ;A2
movw zl, XL
_IMM
_LDX
EXEC
_LDY_ZPG: ;A4
movw zl, XL
_ZPG
_LDYZ
EXEC
_LDA_ZPG: ;A5
movw zl, XL
_ZPG
_LDAZ
EXEC
_LDX_ZPG: ;A6
movw zl, XL
_ZPG
_LDXZ
EXEC
_SMB2_ZPG: ;A7
_SMB 0x04
EXEC
_TAY_IMP: ;A8
LDSR
mov yr, ar
tst yr
SVSR
EXEC
_LDA_IMM: ;A9
movw zl, XL
_IMM
_LDA
EXEC
_TAX_IMP: ;AA
LDSR
mov xr, ar
tst xr
SVSR
EXEC
_LDY_ABS: ;AC
movw zl, XL
_ABS
_LDY
EXEC
_LDA_ABS: ;AD
movw zl, XL
_ABS
_LDA
EXEC
_LDX_ABS: ;AE
movw zl, XL
_ABS
_LDX
EXEC
_BBS2_REL: ;AF
_BBS 0x04
EXEC
_BCS_REL: ;B0
sbrs avsr, acp
rjmp _BCS1
_REL
EXEC
_BCS1:
adiw xl, 1
EXEC
_LDA_INDY: ;B1
movw zl, XL
_INDY
_LDA
EXEC
_LDA_IND: ;B2
movw zl, XL
_IZPG
_LDA
EXEC
_LDY_ZPGX: ;B4
movw zl, XL
_ZPGX
_LDYZ
EXEC
_LDA_ZPGX: ;B5
movw zl, XL
_ZPGX
_LDAZ
EXEC
_LDX_ZPGY: ;B6
movw zl, XL
_ZPGY
_LDXZ
EXEC
_SMB3_ZPG: ;B7
_SMB 0x08
EXEC
_CLV_IMP: ;B8
cbr avsr, at
EXEC
_LDA_ABSY: ;B9
movw zl, XL
_ABSY
_LDA
EXEC
_TSX_IMP: ;BA
LDSR
mov xr, YL
tst xr
SVSR
EXEC
_LDY_ABSX: ;BC
movw zl, XL
_ABSX
_LDY
EXEC
_LDA_ABSX: ;BD
movw zl, XL
_ABSX
_LDA
EXEC
_LDX_ABSY: ;BE
movw zl, XL
_ABSY
_LDX
EXEC
_BBS3_REL: ;BF
_BBS 0x08
EXEC
_CPY_IMM: ;C0
movw zl, XL
_IMM
_CPY
EXEC
_CMP_INDX: ;C1
movw zl, XL
_INDX
_CMP
EXEC
_CPY_ZPG: ;C4
movw zl, XL
_ZPG
_CPYZ
EXEC
_CMP_ZPG: ;C5
movw zl, XL
_ZPG
_CMPZ
EXEC
_DEC_ZPG: ;C6
movw zl, XL
_ZPG
_DECZ
EXEC
_SMB4_ZPG: ;C7
_SMB 0x10
EXEC
_INY_IMP: ;C8
LDSR
inc yr
SVSR
EXEC
_CMP_IMM: ;C9
movw zl, XL
_IMM
_CMP
EXEC
_DEX_IMP: ;CA
LDSR
dec xr
SVSR
EXEC
_WAI_IMP: ;CB
sbiw xl, 0x01
EXEC
_CPY_ABS: ;CC
movw zl, XL
_ABS
_CPY
EXEC
_CMP_ABS: ;CD
movw zl, XL
_ABS
_CMP
EXEC
_DEC_ABS: ;CE
movw zl, XL
_ABS
_DEC
EXEC
_BBS4_REL: ;CF
_BBS 0x10
EXEC
_BNE_REL: ;D0
sbrc avsr, azp
rjmp _BNE1
_REL
EXEC
_BNE1:
adiw XL, 1
EXEC
_CMP_INDY: ;D1
movw zl, XL
_INDY
_CMP
EXEC
_CMP_IND: ;D2
movw zl, XL
_IZPG
_CMP
EXEC
_CMP_ZPGX: ;D5
movw zl, XL
_ZPGX
_CMPZ
EXEC
_DEC_ZPGX: ;D6
movw zl, XL
_ZPGX
_DECZ
EXEC
_SMB5_ZPG: ;D7
_SMB 0x20
EXEC
_CLD_IMP: ;D8
andi sr, ss+so+sx+sb+si+sz+sc
EXEC
_CMP_ABSY: ;D9
movw zl, XL
_ABSY
_CMP
EXEC
_PHX_IMP: ;DA
st Y, xr
dec yl
EXEC
_STP_IMP: ;DB
loop:
rjmp loop
_CMP_ABSX: ;DD
movw zl, XL
_ABSX
_CMP
EXEC
_DEC_ABSX: ;DE
movw zl, XL
_ABSX
_DEC
EXEC
_BBS5_REL: ;DF
_BBS 0x20
EXEC
_CPX_IMM: ;E0
movw zl, XL
_IMM
_CPX
EXEC
_SBC_INDX: ;E1
movw zl, XL
_INDX
_SBC
EXEC
_CPX_ZPG: ;E4
movw zl, XL
_ZPG
_CPXZ
EXEC
_SBC_ZPG: ;E5
movw zl, XL
_ZPG
_SBCZ
EXEC
_INC_ZPG: ;E6
movw zl, XL
_ZPG
_INCZ
EXEC
_SMB6_ZPG: ;E7
_SMB 0x40
EXEC
_INX_IMP: ;E8
LDSR
inc xr
SVSR
EXEC
_SBC_IMM: ;E9
movw zl, XL
_IMM
_SBC
EXEC
_NOP_IMP: ;EA
EXEC
_CPX_ABS: ;EC
movw zl, XL
_ABS
_CPX
EXEC
_SBC_ABS: ;ED
movw zl, XL
_ABS
_SBC
EXEC
_INC_ABS: ;EE
movw zl, XL
_ABS
_INC
EXEC
_BBS6_REL: ;EF
_BBS 0x40
EXEC
_BEQ_REL: ;F0
sbrs avsr, azp
rjmp _BEQ1
_REL
EXEC
_BEQ1:
adiw xl, 1
EXEC
_SBC_INDY: ;F1
movw zl, XL
_INDY
_SBC
EXEC
_SBC_IND: ;F2
movw zl, XL
_IZPG
_SBC
EXEC
_SBC_ZPGX: ;F5
movw zl, XL
_ZPGX
_SBCZ
EXEC
_INC_ZPGX: ;F6
movw zl, XL
_ZPGX
_INCZ
EXEC
_SMB7_ZPG: ;F7
_SMB 0x80
EXEC
_SED_IMP: ;F8
ori sr, sd
EXEC
_SBC_ABSY: ;F9
movw zl, XL
_ABSY
_SBC
EXEC
_PLX_IMP: ;FA
LDSR
inc yl
ld xr, Y
tst xr
SVSR
EXEC
_SBC_ABSX: ;FD
movw zl, XL
_ABSX
_SBC
EXEC
_INC_ABSX: ;FE
movw zl, XL
_ABSX
_INC
EXEC
_BBS7_REL: ;FF
_BBS 0x80
EXEC
;**********************
; CPU State code
;**********************
CPU_INIT:
clr AR
clr XR
clr YR
clr IRV
ldi YL, 0xff
ldi YH, 0x02 ; $01xx
ldi ZL, 0xfc
ldi ZH, 0xff
lpm XL, Z+
lpm XH, Z
ldi sr, sx
SVSR
clr IFLAG ; IRQ flag off
out gpior0, zero ; EEPROM Write off
ret
CPU_RESET:
rcall CPU_INIT
ret
cpu_irq:
clr IFLAG ; clear IRQ trigger
sbrc sr, sip
ret
cli ; dis irq's
st Y, XH
dec yl
st Y, XL
dec yl
AV2SR
andi sr, ss+so+sx+sd+si+sz+sc ; B=0
st Y, sr
dec yl
ori sr, si ; set I
ldi ZL, 0xfe
ldi ZH, 0xff
lpm XL, Z+
lpm XH, Z
ret
cpu_nmi:
st Y, XH
dec yl
st Y, XL
dec yl
AV2SR
st Y, sr
dec yl
ldi ZL, 0xfa
ldi ZH, 0xff
lpm XL, Z+
lpm XH, Z
ret
;**********************
; Execute one opcode
;**********************
Main:
EXEC
rjmp main ; this will never execute!
;**********************
; 1.2 fixed CLV bug
; 1.3 mem access is 16k RAM x 48k ROM
; 1.4 added BCD support for ADC and SBC - flags untested
; 1.5 fixed TXS - removed SR changes
; 1.6 fixed BCD math in ADC and SBC
; 1.7 removed B flag in SR being cleared on RTI
; 1.8 moved V flag to T in AVST
; 1.9 removed IOJMP and optimized IRQ flag handling
; 2.0 optimized opcode fetch, READ and READZ
; 2.1 added READZP and WRITEZP and ZP-mirrored opcode instructions
; 2.2 added lookup tables to convert SR to AVSR and AVSR to SR
; 2.3 added BBRx, BBSx, RBMx, SMBx, STP, WAI opcodes - WDC 65C02 fully supported
; 2.4 Added lookup table for excution in IO and created macro for execution
; Moved Emulator to $8000 in Flash as it outgrew space from $0000-$1FFF.
; Unused opcodes now use the proper # of bytes, per WDC datasheet
; 2.5 Corrected some opcode behavior - now passed Klaus' test suites!