1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-06 07:29:29 +00:00

updating Klaus Dormann's functional tests

This commit is contained in:
Irmen de Jong 2020-02-09 11:55:02 +01:00
parent 7fb8feb676
commit b7ebf6c922
17 changed files with 3185 additions and 1305 deletions

View File

@ -1 +1 @@
version=1.6
version=1.7-SNAPSHOT

View File

@ -34,7 +34,8 @@ chk_z = 0 ; check zero flag
chk_c = 1 ; check carry flag
end_of_test macro
db $db ;execute 65C02 stop instruction
brk
; db $db ;execute 65C02 stop instruction
endm
bss
@ -117,14 +118,14 @@ NEXT2 inc N2 ; [6] see text
bpl LOOP1 ; loop through both values of the carry flag
lda #0 ; test passed, so store 0 in ERROR
sta ERROR
DONE
DONE
end_of_test
; Calculate the actual decimal mode accumulator and flags, the accumulator
; and flag results when N1 is added to N2 using binary arithmetic, the
; predicted accumulator result, the predicted carry flag, and the predicted
; V flag
;
; V flag
;
ADD sed ; decimal mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
@ -138,7 +139,7 @@ ADD sed ; decimal mode
lda N1
adc N2
sta HA ; accumulator result of N1+N2 using binary arithmetic
php
pla
sta HNVZC ; flags result of N1+N2 using binary arithmetic
@ -153,10 +154,10 @@ ADD sed ; decimal mode
and #$0F
sec
A1 ora N1H
;
;
; if N1L + N2L < $0A, then add N2 & $F0
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
;
;
adc N2H,x
php
bcs A2
@ -169,16 +170,16 @@ A3 sta AR ; predicted accumulator result
pla
sta CF ; predicted carry result
pla
;
;
; note that all 8 bits of the P register are stored in VF
;
;
sta VF ; predicted V flags
rts
; Calculate the actual decimal mode accumulator and flags, and the
; accumulator and flag results when N2 is subtracted from N1 using binary
; arithmetic
;
;
SUB sed ; decimal mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
@ -192,15 +193,15 @@ SUB sed ; decimal mode
lda N1
sbc N2
sta HA ; accumulator result of N1-N2 using binary arithmetic
php
pla
sta HNVZC ; flags result of N1-N2 using binary arithmetic
rts
if cputype != 1
; Calculate the predicted SBC accumulator result for the 6502 and 65816
;
;
SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1L
sbc N2L
@ -211,17 +212,17 @@ SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
and #$0F
clc
S11 ora N1H
;
;
; if N1L - N2L >= 0, then subtract N2 & $F0
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
;
;
sbc N2H,x
bcs S12
sbc #$5F ; subtract $60 (carry is clear)
S12 sta AR
rts
endif
if cputype = 1
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
;
@ -234,10 +235,10 @@ SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
and #$0F
clc
S21 ora N1H
;
;
; if N1L - N2L >= 0, then subtract N2 & $F0
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
;
;
sbc N2H,x
bcs S22
sbc #$5F ; subtract $60 (carry is clear)
@ -247,14 +248,14 @@ S22 cpx #0
S23 sta AR ; predicted accumulator result
rts
endif
; Compare accumulator actual results to predicted results
;
; Return:
;
; Return:
; Z flag = 1 (BEQ branch) if same
; Z flag = 0 (BNE branch) if different
;
COMPARE
;
COMPARE
if chk_a = 1
lda DA
cmp AR
@ -284,22 +285,22 @@ COMPARE
and #1 ; mask off C flag
endif
C1 rts
; These routines store the predicted values for ADC and SBC for the 6502,
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
if cputype = 0
A6502 lda VF ; 6502
;
;
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
; the N flag for NF
;
;
sta NF
lda HNVZC
sta ZF
rts
S6502 jsr SUB1
lda HNVZC
sta NF
@ -317,7 +318,7 @@ A6502 lda AR ; 65C02
sta NF
sta ZF
rts
S6502 jsr SUB2
lda AR
php
@ -330,7 +331,7 @@ S6502 jsr SUB2
rts
endif
if cputype = 2
if cputype = 2
A6502 lda AR ; 65C816
php
@ -338,7 +339,7 @@ A6502 lda AR ; 65C816
sta NF
sta ZF
rts
S6502 jsr SUB1
lda AR
php

View File

@ -1,7 +1,7 @@
;
; 6 5 0 2 F U N C T I O N A L T E S T
;
; Copyright (C) 2012-2015 Klaus Dormann
; Copyright (C) 2012-2020 Klaus Dormann
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
@ -21,10 +21,11 @@
; addressing modes with focus on propper setting of the processor status
; register bits.
;
; version 04-dec-2017
; version 05-jan-2020
; contact info at http://2m5.de or email K@2m5.de
;
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
; assembled with AS65 written by Frank A. Kingswood
; The assembler as65_142.zip can be obtained from my GitHub repository
; command line switches: -l -m -s2 -w -h0
; | | | | no page headers in listing
; | | | wide listing (133 char/col)
@ -76,7 +77,8 @@
; 04-dec-2017 fixed BRK only tested with interrupts enabled
; added option to skip the remainder of a failing test
; in report.i65
; 05-jan-2020 fixed shifts not testing zero result and flag when last 1-bit
; is shifted out
; C O N F I G U R A T I O N
@ -96,17 +98,17 @@ load_data_direct = 1
I_flag = 3
;configure memory - try to stay away from memory used by the system
;zero_page memory start address, $50 (80) consecutive Bytes required
;zero_page memory start address, $52 (82) consecutive Bytes required
; add 2 if I_flag = 2
zero_page = $a
;data_segment memory start address, $6A (106) consecutive Bytes required
;data_segment memory start address, $7B (123) consecutive Bytes required
data_segment = $200
if (data_segment & $ff) != 0
ERROR ERROR ERROR low byte of data_segment MUST be $00 !!
endif
;code_segment memory start address, 13kB of consecutive space required
;code_segment memory start address, 13.1kB of consecutive space required
; add 2.5 kB if I_flag = 2
code_segment = $400
@ -621,7 +623,7 @@ irq_x ds 1 ;x register
flag_I_on ds 1 ;or mask to load flags
flag_I_off ds 1 ;and mask to load flags
endif
zpt ;5 bytes store/modify test area
zpt ;6 bytes store/modify test area
;add/subtract operand generation and result/flag prediction
adfc ds 1 ;carry flag before op
ad1 ds 1 ;operand 1 - accumulator
@ -631,6 +633,7 @@ adrh ds 1 ;expected result bit 8 (carry)
adrf ds 1 ;expected flags NV0000ZC (only binary mode)
sb2 ds 1 ;operand 2 complemented for subtract
zp_bss
zps db $80,1 ;additional shift pattern to test zero result & flag
zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
zp7f db $7f ;test pattern for compare
;logical zeropage operands
@ -672,10 +675,10 @@ zp_bss_end
test_case ds 1 ;current test number
ram_chksm ds 2 ;checksum for RAM integrity test
;add/subtract operand copy - abs tests write area
abst ;5 bytes store/modify test area
abst ;6 bytes store/modify test area
ada2 ds 1 ;operand 2
sba2 ds 1 ;operand 2 complemented for subtract
ds 3 ;fill remaining bytes
ds 4 ;fill remaining bytes
data_bss
if load_data_direct = 1
ex_andi and #0 ;execute immediate opcodes
@ -695,34 +698,35 @@ ex_orai ds 3
ex_adci ds 3
ex_sbci ds 3
endif
;zps db $80,1 ;additional shift patterns test zero result & flag
abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
abs7f db $7f ;test pattern for compare
;loads
fLDx db fn,fn,0,fz ;expected flags for load
fLDx db fn,fn,0,fz ;expected flags for load
;shifts
rASL ;expected result ASL & ROL -carry
rROL db $86,$04,$82,0 ; "
rROLc db $87,$05,$83,1 ;expected result ROL +carry
rLSR ;expected result LSR & ROR -carry
rROR db $61,$41,$20,0 ; "
rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carry
fASL ;expected flags for shifts
fROL db fnc,fc,fn,fz ;no carry in
fROLc db fnc,fc,fn,0 ;carry in
fLSR
fROR db fc,0,fc,fz ;no carry in
fRORc db fnc,fn,fnc,fn ;carry in
rASL ;expected result ASL & ROL -carry
rROL db 0,2,$86,$04,$82,0
rROLc db 1,3,$87,$05,$83,1 ;expected result ROL +carry
rLSR ;expected result LSR & ROR -carry
rROR db $40,0,$61,$41,$20,0
rRORc db $c0,$80,$e1,$c1,$a0,$80 ;expected result ROR +carry
fASL ;expected flags for shifts
fROL db fzc,0,fnc,fc,fn,fz ;no carry in
fROLc db fc,0,fnc,fc,fn,0 ;carry in
fLSR
fROR db 0,fzc,fc,0,fc,fz ;no carry in
fRORc db fn,fnc,fnc,fn,fnc,fn ;carry in
;increments (decrements)
rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC
fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC
rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC
fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC
;logical memory operand
absOR db 0,$1f,$71,$80 ;test pattern for OR
absAN db $0f,$ff,$7f,$80 ;test pattern for AND
absEO db $ff,$0f,$8f,$8f ;test pattern for EOR
absOR db 0,$1f,$71,$80 ;test pattern for OR
absAN db $0f,$ff,$7f,$80 ;test pattern for AND
absEO db $ff,$0f,$8f,$8f ;test pattern for EOR
;logical accu operand
absORa db 0,$f1,$1f,0 ;test pattern for OR
absANa db $f0,$ff,$ff,$ff ;test pattern for AND
absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR
absORa db 0,$f1,$1f,0 ;test pattern for OR
absANa db $f0,$ff,$ff,$ff ;test pattern for AND
absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR
;logical results
absrlo db 0,$ff,$7f,$80
absflo db fz,fn,0,fn
@ -4070,91 +4074,91 @@ tstay6 lda abst,y
; testing shifts - ASL LSR ROL ROR all addressing modes
; shifts - accumulator
ldx #3
ldx #5
tasl
set_ax zp1,0
set_ax zps,0
asl a
tst_ax rASL,fASL,0
dex
bpl tasl
ldx #3
ldx #5
tasl1
set_ax zp1,$ff
set_ax zps,$ff
asl a
tst_ax rASL,fASL,$ff-fnzc
dex
bpl tasl1
ldx #3
ldx #5
tlsr
set_ax zp1,0
set_ax zps,0
lsr a
tst_ax rLSR,fLSR,0
dex
bpl tlsr
ldx #3
ldx #5
tlsr1
set_ax zp1,$ff
set_ax zps,$ff
lsr a
tst_ax rLSR,fLSR,$ff-fnzc
dex
bpl tlsr1
ldx #3
ldx #5
trol
set_ax zp1,0
set_ax zps,0
rol a
tst_ax rROL,fROL,0
dex
bpl trol
ldx #3
ldx #5
trol1
set_ax zp1,$ff-fc
set_ax zps,$ff-fc
rol a
tst_ax rROL,fROL,$ff-fnzc
dex
bpl trol1
ldx #3
ldx #5
trolc
set_ax zp1,fc
set_ax zps,fc
rol a
tst_ax rROLc,fROLc,0
dex
bpl trolc
ldx #3
ldx #5
trolc1
set_ax zp1,$ff
set_ax zps,$ff
rol a
tst_ax rROLc,fROLc,$ff-fnzc
dex
bpl trolc1
ldx #3
ldx #5
tror
set_ax zp1,0
set_ax zps,0
ror a
tst_ax rROR,fROR,0
dex
bpl tror
ldx #3
ldx #5
tror1
set_ax zp1,$ff-fc
set_ax zps,$ff-fc
ror a
tst_ax rROR,fROR,$ff-fnzc
dex
bpl tror1
ldx #3
ldx #5
trorc
set_ax zp1,fc
set_ax zps,fc
ror a
tst_ax rRORc,fRORc,0
dex
bpl trorc
ldx #3
ldx #5
trorc1
set_ax zp1,$ff
set_ax zps,$ff
ror a
tst_ax rRORc,fRORc,$ff-fnzc
dex
@ -4162,91 +4166,91 @@ trorc1
next_test
; shifts - zeropage
ldx #3
ldx #5
tasl2
set_z zp1,0
set_z zps,0
asl zpt
tst_z rASL,fASL,0
dex
bpl tasl2
ldx #3
ldx #5
tasl3
set_z zp1,$ff
set_z zps,$ff
asl zpt
tst_z rASL,fASL,$ff-fnzc
dex
bpl tasl3
ldx #3
ldx #5
tlsr2
set_z zp1,0
set_z zps,0
lsr zpt
tst_z rLSR,fLSR,0
dex
bpl tlsr2
ldx #3
ldx #5
tlsr3
set_z zp1,$ff
set_z zps,$ff
lsr zpt
tst_z rLSR,fLSR,$ff-fnzc
dex
bpl tlsr3
ldx #3
ldx #5
trol2
set_z zp1,0
set_z zps,0
rol zpt
tst_z rROL,fROL,0
dex
bpl trol2
ldx #3
ldx #5
trol3
set_z zp1,$ff-fc
set_z zps,$ff-fc
rol zpt
tst_z rROL,fROL,$ff-fnzc
dex
bpl trol3
ldx #3
ldx #5
trolc2
set_z zp1,fc
set_z zps,fc
rol zpt
tst_z rROLc,fROLc,0
dex
bpl trolc2
ldx #3
ldx #5
trolc3
set_z zp1,$ff
set_z zps,$ff
rol zpt
tst_z rROLc,fROLc,$ff-fnzc
dex
bpl trolc3
ldx #3
ldx #5
tror2
set_z zp1,0
set_z zps,0
ror zpt
tst_z rROR,fROR,0
dex
bpl tror2
ldx #3
ldx #5
tror3
set_z zp1,$ff-fc
set_z zps,$ff-fc
ror zpt
tst_z rROR,fROR,$ff-fnzc
dex
bpl tror3
ldx #3
ldx #5
trorc2
set_z zp1,fc
set_z zps,fc
ror zpt
tst_z rRORc,fRORc,0
dex
bpl trorc2
ldx #3
ldx #5
trorc3
set_z zp1,$ff
set_z zps,$ff
ror zpt
tst_z rRORc,fRORc,$ff-fnzc
dex
@ -4254,91 +4258,91 @@ trorc3
next_test
; shifts - absolute
ldx #3
ldx #5
tasl4
set_abs zp1,0
set_abs zps,0
asl abst
tst_abs rASL,fASL,0
dex
bpl tasl4
ldx #3
ldx #5
tasl5
set_abs zp1,$ff
set_abs zps,$ff
asl abst
tst_abs rASL,fASL,$ff-fnzc
dex
bpl tasl5
ldx #3
ldx #5
tlsr4
set_abs zp1,0
set_abs zps,0
lsr abst
tst_abs rLSR,fLSR,0
dex
bpl tlsr4
ldx #3
ldx #5
tlsr5
set_abs zp1,$ff
set_abs zps,$ff
lsr abst
tst_abs rLSR,fLSR,$ff-fnzc
dex
bpl tlsr5
ldx #3
ldx #5
trol4
set_abs zp1,0
set_abs zps,0
rol abst
tst_abs rROL,fROL,0
dex
bpl trol4
ldx #3
ldx #5
trol5
set_abs zp1,$ff-fc
set_abs zps,$ff-fc
rol abst
tst_abs rROL,fROL,$ff-fnzc
dex
bpl trol5
ldx #3
ldx #5
trolc4
set_abs zp1,fc
set_abs zps,fc
rol abst
tst_abs rROLc,fROLc,0
dex
bpl trolc4
ldx #3
ldx #5
trolc5
set_abs zp1,$ff
set_abs zps,$ff
rol abst
tst_abs rROLc,fROLc,$ff-fnzc
dex
bpl trolc5
ldx #3
ldx #5
tror4
set_abs zp1,0
set_abs zps,0
ror abst
tst_abs rROR,fROR,0
dex
bpl tror4
ldx #3
ldx #5
tror5
set_abs zp1,$ff-fc
set_abs zps,$ff-fc
ror abst
tst_abs rROR,fROR,$ff-fnzc
dex
bpl tror5
ldx #3
ldx #5
trorc4
set_abs zp1,fc
set_abs zps,fc
ror abst
tst_abs rRORc,fRORc,0
dex
bpl trorc4
ldx #3
ldx #5
trorc5
set_abs zp1,$ff
set_abs zps,$ff
ror abst
tst_abs rRORc,fRORc,$ff-fnzc
dex
@ -4346,91 +4350,91 @@ trorc5
next_test
; shifts - zp indexed
ldx #3
ldx #5
tasl6
set_zx zp1,0
set_zx zps,0
asl zpt,x
tst_zx rASL,fASL,0
dex
bpl tasl6
ldx #3
ldx #5
tasl7
set_zx zp1,$ff
set_zx zps,$ff
asl zpt,x
tst_zx rASL,fASL,$ff-fnzc
dex
bpl tasl7
ldx #3
ldx #5
tlsr6
set_zx zp1,0
set_zx zps,0
lsr zpt,x
tst_zx rLSR,fLSR,0
dex
bpl tlsr6
ldx #3
ldx #5
tlsr7
set_zx zp1,$ff
set_zx zps,$ff
lsr zpt,x
tst_zx rLSR,fLSR,$ff-fnzc
dex
bpl tlsr7
ldx #3
ldx #5
trol6
set_zx zp1,0
set_zx zps,0
rol zpt,x
tst_zx rROL,fROL,0
dex
bpl trol6
ldx #3
ldx #5
trol7
set_zx zp1,$ff-fc
set_zx zps,$ff-fc
rol zpt,x
tst_zx rROL,fROL,$ff-fnzc
dex
bpl trol7
ldx #3
ldx #5
trolc6
set_zx zp1,fc
set_zx zps,fc
rol zpt,x
tst_zx rROLc,fROLc,0
dex
bpl trolc6
ldx #3
ldx #5
trolc7
set_zx zp1,$ff
set_zx zps,$ff
rol zpt,x
tst_zx rROLc,fROLc,$ff-fnzc
dex
bpl trolc7
ldx #3
ldx #5
tror6
set_zx zp1,0
set_zx zps,0
ror zpt,x
tst_zx rROR,fROR,0
dex
bpl tror6
ldx #3
ldx #5
tror7
set_zx zp1,$ff-fc
set_zx zps,$ff-fc
ror zpt,x
tst_zx rROR,fROR,$ff-fnzc
dex
bpl tror7
ldx #3
ldx #5
trorc6
set_zx zp1,fc
set_zx zps,fc
ror zpt,x
tst_zx rRORc,fRORc,0
dex
bpl trorc6
ldx #3
ldx #5
trorc7
set_zx zp1,$ff
set_zx zps,$ff
ror zpt,x
tst_zx rRORc,fRORc,$ff-fnzc
dex
@ -4438,91 +4442,91 @@ trorc7
next_test
; shifts - abs indexed
ldx #3
ldx #5
tasl8
set_absx zp1,0
set_absx zps,0
asl abst,x
tst_absx rASL,fASL,0
dex
bpl tasl8
ldx #3
ldx #5
tasl9
set_absx zp1,$ff
set_absx zps,$ff
asl abst,x
tst_absx rASL,fASL,$ff-fnzc
dex
bpl tasl9
ldx #3
ldx #5
tlsr8
set_absx zp1,0
set_absx zps,0
lsr abst,x
tst_absx rLSR,fLSR,0
dex
bpl tlsr8
ldx #3
ldx #5
tlsr9
set_absx zp1,$ff
set_absx zps,$ff
lsr abst,x
tst_absx rLSR,fLSR,$ff-fnzc
dex
bpl tlsr9
ldx #3
ldx #5
trol8
set_absx zp1,0
set_absx zps,0
rol abst,x
tst_absx rROL,fROL,0
dex
bpl trol8
ldx #3
ldx #5
trol9
set_absx zp1,$ff-fc
set_absx zps,$ff-fc
rol abst,x
tst_absx rROL,fROL,$ff-fnzc
dex
bpl trol9
ldx #3
ldx #5
trolc8
set_absx zp1,fc
set_absx zps,fc
rol abst,x
tst_absx rROLc,fROLc,0
dex
bpl trolc8
ldx #3
ldx #5
trolc9
set_absx zp1,$ff
set_absx zps,$ff
rol abst,x
tst_absx rROLc,fROLc,$ff-fnzc
dex
bpl trolc9
ldx #3
ldx #5
tror8
set_absx zp1,0
set_absx zps,0
ror abst,x
tst_absx rROR,fROR,0
dex
bpl tror8
ldx #3
ldx #5
tror9
set_absx zp1,$ff-fc
set_absx zps,$ff-fc
ror abst,x
tst_absx rROR,fROR,$ff-fnzc
dex
bpl tror9
ldx #3
ldx #5
trorc8
set_absx zp1,fc
set_absx zps,fc
ror abst,x
tst_absx rRORc,fRORc,0
dex
bpl trorc8
ldx #3
ldx #5
trorc9
set_absx zp1,$ff
set_absx zps,$ff
ror abst,x
tst_absx rRORc,fRORc,$ff-fnzc
dex
@ -5997,6 +6001,7 @@ break2 ;BRK pass 2
;copy of data to initialize BSS segment
if load_data_direct != 1
zp_init
zps_ db $80,1 ;additional shift pattern to test zero result & flag
zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
zp7f_ db $7f ;test pattern for compare
;logical zeropage operands
@ -6048,34 +6053,35 @@ ex_adc_ adc #0 ;execute immediate opcodes
rts
ex_sbc_ sbc #0 ;execute immediate opcodes
rts
;zps db $80,1 ;additional shift patterns test zero result & flag
abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
abs7f_ db $7f ;test pattern for compare
;loads
fLDx_ db fn,fn,0,fz ;expected flags for load
fLDx_ db fn,fn,0,fz ;expected flags for load
;shifts
rASL_ ;expected result ASL & ROL -carry
rROL_ db $86,$04,$82,0 ; "
rROLc_ db $87,$05,$83,1 ;expected result ROL +carry
rLSR_ ;expected result LSR & ROR -carry
rROR_ db $61,$41,$20,0 ; "
rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carry
fASL_ ;expected flags for shifts
fROL_ db fnc,fc,fn,fz ;no carry in
fROLc_ db fnc,fc,fn,0 ;carry in
rASL_ ;expected result ASL & ROL -carry
rROL_ db 0,2,$86,$04,$82,0
rROLc_ db 1,3,$87,$05,$83,1 ;expected result ROL +carry
rLSR_ ;expected result LSR & ROR -carry
rROR_ db $40,0,$61,$41,$20,0
rRORc_ db $c0,$80,$e1,$c1,$a0,$80 ;expected result ROR +carry
fASL_ ;expected flags for shifts
fROL_ db fzc,0,fnc,fc,fn,fz ;no carry in
fROLc_ db fc,0,fnc,fc,fn,0 ;carry in
fLSR_
fROR_ db fc,0,fc,fz ;no carry in
fRORc_ db fnc,fn,fnc,fn ;carry in
fROR_ db 0,fzc,fc,0,fc,fz ;no carry in
fRORc_ db fn,fnc,fnc,fn,fnc,fn ;carry in
;increments (decrements)
rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC
fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC
rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC
fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC
;logical memory operand
absOR_ db 0,$1f,$71,$80 ;test pattern for OR
absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND
absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR
absOR_ db 0,$1f,$71,$80 ;test pattern for OR
absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND
absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR
;logical accu operand
absORa_ db 0,$f1,$1f,0 ;test pattern for OR
absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND
absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR
absORa_ db 0,$f1,$1f,0 ;test pattern for OR
absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND
absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR
;logical results
absrlo_ db 0,$ff,$7f,$80
absflo_ db fz,fn,0,fn

View File

@ -0,0 +1,356 @@
; Verify decimal mode behavior
; Written by Bruce Clark. This code is public domain.
; see http://www.6502.org/tutorials/decimal_mode.html
;
; Returns:
; ERROR = 0 if the test passed
; ERROR = 1 if the test failed
; modify the code at the DONE label for desired program end
;
; This routine requires 17 bytes of RAM -- 1 byte each for:
; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF
; and 2 bytes for N2H
;
; Variables:
; N1 and N2 are the two numbers to be added or subtracted
; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2
; DA and DNVZC are the actual accumulator and flag results in decimal mode
; HA and HNVZC are the accumulator and flag results when N1 and N2 are
; added or subtracted using binary arithmetic
; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and
; flag results, calculated using binary arithmetic
;
; This program takes approximately 1 minute at 1 MHz (a few seconds more on
; a 65C02 than a 6502 or 65816)
;
; Configuration:
cputype = 1 ; 0 = 6502, 1 = 65C02, 2 = 65C816
vld_bcd = 0 ; 0 = allow invalid bcd, 1 = valid bcd only
chk_a = 1 ; check accumulator
chk_n = 0 ; check sign (negative) flag
chk_v = 0 ; check overflow flag
chk_z = 0 ; check zero flag
chk_c = 1 ; check carry flag
end_of_test macro
brk
; db $db ;execute 65C02 stop instruction
endm
bss
org 0
; operands - register Y = carry in
N1 ds 1
N2 ds 1
; binary result
HA ds 1
HNVZC ds 1
;04
; decimal result
DA ds 1
DNVZC ds 1
; predicted results
AR ds 1
NF ds 1
;08
VF ds 1
ZF ds 1
CF ds 1
ERROR ds 1
;0C
; workspace
N1L ds 1
N1H ds 1
N2L ds 1
N2H ds 2
code
org $200
TEST ldy #1 ; initialize Y (used to loop through carry flag values)
sty ERROR ; store 1 in ERROR until the test passes
lda #0 ; initialize N1 and N2
sta N1
sta N2
LOOP1 lda N2 ; N2L = N2 & $0F
and #$0F ; [1] see text
if vld_bcd = 1
cmp #$0a
bcs NEXT2
endif
sta N2L
lda N2 ; N2H = N2 & $F0
and #$F0 ; [2] see text
if vld_bcd = 1
cmp #$a0
bcs NEXT2
endif
sta N2H
ora #$0F ; N2H+1 = (N2 & $F0) + $0F
sta N2H+1
LOOP2 lda N1 ; N1L = N1 & $0F
and #$0F ; [3] see text
if vld_bcd = 1
cmp #$0a
bcs NEXT1
endif
sta N1L
lda N1 ; N1H = N1 & $F0
and #$F0 ; [4] see text
if vld_bcd = 1
cmp #$a0
bcs NEXT1
endif
sta N1H
jsr ADD
jsr A6502
jsr COMPARE
bne DONE
jsr SUB
jsr S6502
jsr COMPARE
bne DONE
NEXT1 inc N1 ; [5] see text
bne LOOP2 ; loop through all 256 values of N1
NEXT2 inc N2 ; [6] see text
bne LOOP1 ; loop through all 256 values of N2
dey
bpl LOOP1 ; loop through both values of the carry flag
lda #0 ; test passed, so store 0 in ERROR
sta ERROR
DONE
end_of_test
; Calculate the actual decimal mode accumulator and flags, the accumulator
; and flag results when N1 is added to N2 using binary arithmetic, the
; predicted accumulator result, the predicted carry flag, and the predicted
; V flag
;
ADD sed ; decimal mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
adc N2
sta DA ; actual accumulator result in decimal mode
php
pla
sta DNVZC ; actual flags result in decimal mode
cld ; binary mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
adc N2
sta HA ; accumulator result of N1+N2 using binary arithmetic
php
pla
sta HNVZC ; flags result of N1+N2 using binary arithmetic
cpy #1
lda N1L
adc N2L
cmp #$0A
ldx #0
bcc A1
inx
adc #5 ; add 6 (carry is set)
and #$0F
sec
A1 ora N1H
;
; if N1L + N2L < $0A, then add N2 & $F0
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
;
adc N2H,x
php
bcs A2
cmp #$A0
bcc A3
A2 adc #$5F ; add $60 (carry is set)
sec
A3 sta AR ; predicted accumulator result
php
pla
sta CF ; predicted carry result
pla
;
; note that all 8 bits of the P register are stored in VF
;
sta VF ; predicted V flags
rts
; Calculate the actual decimal mode accumulator and flags, and the
; accumulator and flag results when N2 is subtracted from N1 using binary
; arithmetic
;
SUB sed ; decimal mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
sbc N2
sta DA ; actual accumulator result in decimal mode
php
pla
sta DNVZC ; actual flags result in decimal mode
cld ; binary mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
sbc N2
sta HA ; accumulator result of N1-N2 using binary arithmetic
php
pla
sta HNVZC ; flags result of N1-N2 using binary arithmetic
rts
if cputype != 1
; Calculate the predicted SBC accumulator result for the 6502 and 65816
;
SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1L
sbc N2L
ldx #0
bcs S11
inx
sbc #5 ; subtract 6 (carry is clear)
and #$0F
clc
S11 ora N1H
;
; if N1L - N2L >= 0, then subtract N2 & $F0
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
;
sbc N2H,x
bcs S12
sbc #$5F ; subtract $60 (carry is clear)
S12 sta AR
rts
endif
if cputype = 1
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
;
SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1L
sbc N2L
ldx #0
bcs S21
inx
and #$0F
clc
S21 ora N1H
;
; if N1L - N2L >= 0, then subtract N2 & $F0
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
;
sbc N2H,x
bcs S22
sbc #$5F ; subtract $60 (carry is clear)
S22 cpx #0
beq S23
sbc #6
S23 sta AR ; predicted accumulator result
rts
endif
; Compare accumulator actual results to predicted results
;
; Return:
; Z flag = 1 (BEQ branch) if same
; Z flag = 0 (BNE branch) if different
;
COMPARE
if chk_a = 1
lda DA
cmp AR
bne C1
endif
if chk_n = 1
lda DNVZC ; [7] see text
eor NF
and #$80 ; mask off N flag
bne C1
endif
if chk_v = 1
lda DNVZC ; [8] see text
eor VF
and #$40 ; mask off V flag
bne C1 ; [9] see text
endif
if chk_z = 1
lda DNVZC
eor ZF ; mask off Z flag
and #2
bne C1 ; [10] see text
endif
if chk_c = 1
lda DNVZC
eor CF
and #1 ; mask off C flag
endif
C1 rts
; These routines store the predicted values for ADC and SBC for the 6502,
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
if cputype = 0
A6502 lda VF ; 6502
;
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
; the N flag for NF
;
sta NF
lda HNVZC
sta ZF
rts
S6502 jsr SUB1
lda HNVZC
sta NF
sta VF
sta ZF
sta CF
rts
endif
if cputype = 1
A6502 lda AR ; 65C02
php
pla
sta NF
sta ZF
rts
S6502 jsr SUB2
lda AR
php
pla
sta NF
sta ZF
lda HNVZC
sta VF
sta CF
rts
endif
if cputype = 2
A6502 lda AR ; 65C816
php
pla
sta NF
sta ZF
rts
S6502 jsr SUB1
lda AR
php
pla
sta NF
sta ZF
lda HNVZC
sta VF
sta CF
rts
endif
end TEST

Binary file not shown.

View File

@ -0,0 +1,9 @@
AS65 Assembler for R6502 [1.42]. Page 1
--------------------------- 6502_decimal_test.a65 ----------------------------
356 lines read, no errors in pass 1.
No errors in pass 2.
Wrote binary from address $0200 through $02e9.
Total size 234 bytes.
Program start address is at $0200 (512).

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
AS65 Assembler for R6502 [1.42]. Page 1
--------------------------- 65C02_decimal_test.a65 ---------------------------
356 lines read, no errors in pass 1.
No errors in pass 2.
Wrote binary from address $0200 through $02f1.
Total size 242 bytes.
Program start address is at $0200 (512).

View File

@ -10,14 +10,18 @@ The 6502_interrupt_test.a65 is a simple test to check the interrupt system
of both processors. A feedback register is required to inject IRQ and NMI
requests.
The 6502_decimal_test.a65 is Bruce Clark's code to accurately test decimal mode
of the various 6502 cores (6502, 65c02 & 65816 in 8-bit mode) with added
configuration options (invalid bcd or not, which flags to ignore).
Detailed information about how to configure, assemble and run the tests is
included in each source file.
The tests have primarily been written to test my own ATMega16 6502 emulator
project. You can find it here: http://2m5.de/6502_Emu/index.htm
The assembler used is no longer available on the author's website. as65_142.zip
is now included in this repository.
A discussion about the tests can be found here:
http://forum.6502.org/viewtopic.php?f=2&t=2241
And no, I will not switch to another assembler. However, GitHub user amb5l has
a CA65 compatible version in his repository.
Good luck debugging your emulator, simulator, fpga core, discrete
logic implementation or whatever you have!

View File

@ -111,13 +111,14 @@ class Test6502CpuBasics {
@Test
fun testBCD6502() {
// this test only works on 6502, not on the 65c02
val cpu = Cpu6502()
val bus = Bus()
bus.add(cpu)
val ram = Ram(0, 0xffff)
ram[Cpu6502.RESET_vector] = 0x00
ram[Cpu6502.RESET_vector +1] = 0x10
val bytes = javaClass.getResource("bcdtest6502.bin").readBytes() // only works on 6502, not on the 65c02
val bytes = javaClass.getResource("bcdtest6502.bin").readBytes()
ram.load(bytes, 0x1000)
bus.add(ram)
bus.reset()

View File

@ -1,77 +0,0 @@
import razorvine.ksim65.Bus
import razorvine.ksim65.components.Ram
import razorvine.ksim65.Cpu6502
import razorvine.ksim65.Cpu65C02
import java.lang.Exception
import kotlin.test.*
class Test6502Functional {
private class SuccessfulTestResult: Exception()
@Test
fun testFunctional6502() {
val cpu = Cpu6502()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/6502_functional_test.bin", 0)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0400
cpu.addBreakpoint(0x3469) { _, _ ->
// reaching this address means successful test result
if(cpu.currentOpcode==0x4c)
throw SuccessfulTestResult()
Cpu6502.BreakpointResultAction(null, null)
}
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful ${cpu.totalCycles}")
return
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, cpu.regPC-20, cpu.regPC+20)
println(d.first.joinToString ("\n"))
fail("test failed")
}
@Test
fun testFunctional65C02() {
val cpu = Cpu65C02()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/65C02_extended_opcodes_test.bin", 0)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0400
cpu.addBreakpoint(0x24f1) { _, _ ->
// reaching this address means successful test result
if(cpu.currentOpcode==0x4c)
throw SuccessfulTestResult()
Cpu6502.BreakpointResultAction(null, null)
}
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful")
return
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, cpu.regPC-20, cpu.regPC+20)
println(d.first.joinToString ("\n"))
fail("test failed")
}
}

View File

@ -0,0 +1,192 @@
import razorvine.ksim65.Bus
import razorvine.ksim65.components.Ram
import razorvine.ksim65.Cpu6502
import razorvine.ksim65.Cpu65C02
import razorvine.ksim65.hexW
import java.lang.Exception
import kotlin.math.max
import kotlin.math.min
import kotlin.test.*
/**
* This runs the 'functional 6502/65c02' tests from Klaus2m5
* (Klaus Dormann, sourced from here https://github.com/Klaus2m5/6502_65C02_functional_tests)
*/
class Test6502Klaus2m5Functional {
private class SuccessfulTestResult: Exception()
@Test
fun testFunctional6502() {
val cpu = Cpu6502()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/6502_functional_test.bin", 0)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0400
cpu.addBreakpoint(0x3469) { _, _ ->
// reaching this address means successful test result
if(cpu.currentOpcode==0x4c)
throw SuccessfulTestResult()
Cpu6502.BreakpointResultAction(null, null)
}
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful ${cpu.totalCycles}")
return
} catch(nx: NotImplementedError) {
println("encountered a not yet implemented feature: ${nx.message}")
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
@Test
fun testFunctional65C02() {
val cpu = Cpu65C02()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/65C02_extended_opcodes_test.bin", 0)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0400
cpu.addBreakpoint(0x24f1) { _, _ ->
// reaching this address means successful test result
if(cpu.currentOpcode==0x4c)
throw SuccessfulTestResult()
Cpu6502.BreakpointResultAction(null, null)
}
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful")
return
} catch(nx: NotImplementedError) {
println("encountered a not yet implemented feature: ${nx.message}")
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
@Test
//@Ignore("todo: fix the interrupt tests") // TODO the test code is not correct
fun testInterrupts6502() {
val cpu = Cpu6502()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/6502_interrupt_test.bin", 0)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0400
// cpu.addBreakpoint(0x3469) { _, _ ->
// // reaching this address means successful test result
// if(cpu.currentOpcode==0x4c)
// throw SuccessfulTestResult()
// Cpu6502.BreakpointResultAction(null, null)
// }
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful ${cpu.totalCycles}")
return
} catch(nx: NotImplementedError) {
println("encountered a not yet implemented feature: ${nx.message}")
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
@Test
fun testDecimal6502() {
val cpu = Cpu6502()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/6502_decimal_test.bin", 0x0200)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0200
cpu.breakpointForBRK = { cpu, address ->
if(address in 513..2047) {
val error=bus.read(0x000b) // the 'ERROR' variable is stored here
if(error==0.toShort())
throw SuccessfulTestResult()
}
Cpu6502.BreakpointResultAction(null, null)
}
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful ${cpu.totalCycles}")
return
} catch(nx: NotImplementedError) {
println("encountered a not yet implemented feature: ${nx.message}")
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
@Test
fun testDecimal65C02() {
val cpu = Cpu65C02()
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("src/test/kotlin/6502_functional_tests/bin_files/65C02_decimal_test.bin", 0x0200)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0200
cpu.breakpointForBRK = { cpu, address ->
if(address in 513..2047) {
val error=bus.read(0x000b) // the 'ERROR' variable is stored here
if(error==0.toShort())
throw SuccessfulTestResult()
}
Cpu6502.BreakpointResultAction(null, null)
}
try {
while (cpu.totalCycles < 100000000) {
cpu.clock()
}
} catch (sx: SuccessfulTestResult) {
println("test successful ${cpu.totalCycles}")
return
} catch(nx: NotImplementedError) {
println("encountered a not yet implemented feature: ${nx.message}")
}
println(cpu.snapshot())
val d = cpu.disassemble(ram, max(0, cpu.regPC-20), min(65535, cpu.regPC+20))
println(d.first.joinToString ("\n"))
fail("test failed")
}
}