; ; 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!