add msbasic
This commit is contained in:
1 parent
d37d434228
commit
c5a028c8c6
104 files changed
+25598
-13802
No files matched your search
@@ -1,4 +1,4 @@
|
||||
as65_142
|
||||
|
||||
*.bin
|
||||
as65_142
|
||||
|
||||
*.bin
|
||||
*.lst
|
||||
@@ -1,375 +1,375 @@
|
||||
; 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 = 0 ; 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
|
||||
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
|
||||
lda #1
|
||||
sta $dc02
|
||||
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 lda #'*'
|
||||
sta $dc00
|
||||
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
|
||||
lda #0
|
||||
jsr RCHAR
|
||||
lda #1
|
||||
cmp ERROR
|
||||
beq _E
|
||||
lda #'P'
|
||||
jmp _E2
|
||||
_E lda #'F'
|
||||
_E2 jsr RCHAR
|
||||
end_of_test
|
||||
|
||||
RCHAR sta $dc00
|
||||
lda #'\r'
|
||||
sta $dc00
|
||||
lda #'\n'
|
||||
sta $dc00
|
||||
rts
|
||||
|
||||
; 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
|
||||
; 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 = 0 ; 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
|
||||
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
|
||||
lda #1
|
||||
sta $bc02
|
||||
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 lda #'*'
|
||||
sta $bc00
|
||||
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
|
||||
lda #0
|
||||
jsr RCHAR
|
||||
lda #1
|
||||
cmp ERROR
|
||||
beq _E
|
||||
lda #'P'
|
||||
jmp _E2
|
||||
_E lda #'F'
|
||||
_E2 jsr RCHAR
|
||||
end_of_test
|
||||
|
||||
RCHAR sta $bc00
|
||||
lda #'\r'
|
||||
sta $bc00
|
||||
lda #'\n'
|
||||
sta $bc00
|
||||
rts
|
||||
|
||||
; 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
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,29 +1,29 @@
|
||||
This is a set of functional tests for the 6502/65C02 type processors.
|
||||
|
||||
The 6502_functional_test.a65 is an assembler sourcecode to test all valid
|
||||
opcodes and addressing modes of the original NMOS 6502 cpu.
|
||||
|
||||
The 65C02_extended_opcodes_test.a65c tests all additional opcodes of the
|
||||
65C02 processor including undefined opcodes.
|
||||
|
||||
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 assembler used is no longer available on the author's website. as65_142.zip
|
||||
is now included in this repository.
|
||||
|
||||
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!
|
||||
|
||||
|
||||
This is a set of functional tests for the 6502/65C02 type processors.
|
||||
|
||||
The 6502_functional_test.a65 is an assembler sourcecode to test all valid
|
||||
opcodes and addressing modes of the original NMOS 6502 cpu.
|
||||
|
||||
The 65C02_extended_opcodes_test.a65c tests all additional opcodes of the
|
||||
65C02 processor including undefined opcodes.
|
||||
|
||||
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 assembler used is no longer available on the author's website. as65_142.zip
|
||||
is now included in this repository.
|
||||
|
||||
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!
|
||||
|
||||
|
||||
@@ -1,224 +1,224 @@
|
||||
;**** report 6502 funtional test errors to standard I/O ****
|
||||
;
|
||||
;this include file is part of the 6502 functional tests
|
||||
;it is used when you configure report = 1 in the tests
|
||||
;
|
||||
;to adopt the standard output vectors of your test environment
|
||||
;you must modify the rchar and rget subroutines in this include
|
||||
;
|
||||
;I/O hardware may have to be initialized in report_init
|
||||
|
||||
;print message macro - \1 = message location
|
||||
rprt macro
|
||||
ldx #0
|
||||
lda \1
|
||||
loop\?
|
||||
jsr rchar
|
||||
inx
|
||||
lda \1,x
|
||||
bne loop\?
|
||||
endm
|
||||
|
||||
;initialize I/O as required (example: configure & enable ACIA)
|
||||
report_init
|
||||
;nothing to initialize
|
||||
rprt rmsg_start
|
||||
rts
|
||||
|
||||
;show stack (with saved registers), zeropage and absolute memory workspace
|
||||
;after an error was trapped in the test program
|
||||
report_error
|
||||
;save registers
|
||||
php
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
cld
|
||||
;show stack with index to registers at error
|
||||
rprt rmsg_stack
|
||||
tsx
|
||||
inx
|
||||
lda #1 ;address high
|
||||
jsr rhex
|
||||
txa ;address low
|
||||
jsr rhex
|
||||
rstack jsr rspace
|
||||
lda $100,x ;stack data
|
||||
jsr rhex
|
||||
inx
|
||||
bne rstack
|
||||
jsr rcrlf ;new line
|
||||
;show zero page workspace
|
||||
lda #0
|
||||
jsr rhex
|
||||
lda #zpt
|
||||
tax
|
||||
jsr rhex
|
||||
rzp jsr rspace
|
||||
lda 0,x
|
||||
jsr rhex
|
||||
inx
|
||||
cpx #zp_bss
|
||||
bne rzp
|
||||
jsr rcrlf
|
||||
jmp rend ; Skip Workspace since 65k is large
|
||||
;show absolute workspace
|
||||
lda #hi(data_segment)
|
||||
jsr rhex
|
||||
lda #lo(data_segment)
|
||||
jsr rhex
|
||||
ldx #0
|
||||
rabs jsr rspace
|
||||
lda data_segment,x
|
||||
jsr rhex
|
||||
inx
|
||||
cpx #(data_bss-data_segment)
|
||||
bne rabs
|
||||
;ask to continue
|
||||
rend
|
||||
rprt rmsg_cont
|
||||
rerr1 jsr rget
|
||||
cmp #'S'
|
||||
beq rskip
|
||||
cmp #'C'
|
||||
bne rerr1
|
||||
;restore registers
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
plp
|
||||
rts
|
||||
;skip the current test
|
||||
rskip lda #$f0 ;already end of tests?
|
||||
cmp test_case
|
||||
beq rerr1 ;skip is not available
|
||||
ldx #$ff ;clear stack
|
||||
txs
|
||||
inc test_case ;next test
|
||||
lda #lo(start) ;find begin of test
|
||||
sta zpt
|
||||
lda #hi(start)
|
||||
sta zpt+1
|
||||
rskipl1 ldy #4 ;search pattern
|
||||
rskipl2 lda (zpt),y ;next byte
|
||||
cmp rmark,y
|
||||
bne rskipnx ;no match
|
||||
dey
|
||||
bmi rskipf ;found pattern
|
||||
cpy #1 ;skip immediate value
|
||||
bne rskipl2
|
||||
dey
|
||||
beq rskipl2
|
||||
|
||||
rskipnx inc zpt ;next RAM location
|
||||
bne rskipl1
|
||||
inc zpt+1
|
||||
bne rskipl1
|
||||
|
||||
rskipf ldy #1 ;pattern found - check test number
|
||||
lda (zpt),y ;test number
|
||||
cmp #$f0 ;end of last test?
|
||||
beq rskipe ;ask to rerun all
|
||||
cmp test_case ;is next test?
|
||||
bne rskipnx ;continue searching
|
||||
rskipe jmp (zpt) ;start next test or rerun at end of tests
|
||||
|
||||
rmark lda #0 ;begin of test search pattern
|
||||
sta test_case
|
||||
|
||||
;show test has ended, ask to repeat
|
||||
report_success
|
||||
if rep_int = 1
|
||||
rprt rmsg_priority
|
||||
lda data_segment ;show interrupt sequence
|
||||
jsr rhex
|
||||
jsr rspace
|
||||
lda data_segment+1
|
||||
jsr rhex
|
||||
jsr rspace
|
||||
lda data_segment+2
|
||||
jsr rhex
|
||||
endif
|
||||
rprt rmsg_success
|
||||
rsuc1 jsr rget
|
||||
cmp #'R'
|
||||
bne rsuc1
|
||||
rts
|
||||
|
||||
;input subroutine
|
||||
;get a character from standard input
|
||||
;adjust according to the needs in your test environment
|
||||
rget ;get character in A
|
||||
;rget1
|
||||
; lda $bff1 ;wait RDRF
|
||||
; and #8
|
||||
; beq rget1
|
||||
;not a real ACIA - so RDRF is not checked
|
||||
; lda $bff0 ;read acia rx reg
|
||||
; lda $f004 ;Kowalski simulator default
|
||||
lda $dc01 ;KILIAN
|
||||
;the load can be replaced by a call to a kernal routine
|
||||
; jsr $ffcf ;example: CHRIN for a C64
|
||||
cmp #'a' ;lower case
|
||||
bcc rget1
|
||||
and #$5f ;convert to upper case
|
||||
rget1 rts
|
||||
|
||||
;output subroutines
|
||||
rcrlf lda #10
|
||||
jsr rchar
|
||||
lda #13
|
||||
bne rchar
|
||||
|
||||
rspace lda #' '
|
||||
bne rchar
|
||||
|
||||
rhex pha ;report hex byte in A
|
||||
lsr a ;high nibble first
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr rnib
|
||||
pla ;now low nibble
|
||||
and #$f
|
||||
|
||||
rnib clc ;report nibble in A
|
||||
adc #'0' ;make printable 0-9
|
||||
cmp #'9'+1
|
||||
bcc rchar
|
||||
adc #6 ;make printable A-F
|
||||
|
||||
;send a character to standard output
|
||||
;adjust according to the needs in your test environment
|
||||
;register X needs to be preserved!
|
||||
rchar ;report character in A
|
||||
; pha ;wait TDRF
|
||||
;rchar1 lda $bff1
|
||||
; and #$10
|
||||
; beq rchar1
|
||||
; pla
|
||||
;not a real ACIA - so TDRF is not checked
|
||||
; sta $bff0 ;write acia tx reg
|
||||
; sta $f001 ;Kowalski simulator default
|
||||
sta $dc00 ;KILIAN
|
||||
;the store can be replaced by a call to a kernal routine
|
||||
; jsr $ffd2 ;example: CHROUT for a C64
|
||||
rts
|
||||
|
||||
rmsg_start
|
||||
db 10,13,"Started testing",10,13,0
|
||||
rmsg_stack
|
||||
db 10,13,"regs Y X A PS PCLPCH",10,13,0
|
||||
rmsg_cont
|
||||
db 10,13,"press C to continue or S to skip current test",10,13,0
|
||||
rmsg_success
|
||||
db 10,13,"All tests completed, press R to repeat",10,13,0
|
||||
if rep_int = 1
|
||||
rmsg_priority
|
||||
db 10,13,"interrupt sequence (NMI IRQ BRK) ",0
|
||||
endif
|
||||
;**** report 6502 funtional test errors to standard I/O ****
|
||||
;
|
||||
;this include file is part of the 6502 functional tests
|
||||
;it is used when you configure report = 1 in the tests
|
||||
;
|
||||
;to adopt the standard output vectors of your test environment
|
||||
;you must modify the rchar and rget subroutines in this include
|
||||
;
|
||||
;I/O hardware may have to be initialized in report_init
|
||||
|
||||
;print message macro - \1 = message location
|
||||
rprt macro
|
||||
ldx #0
|
||||
lda \1
|
||||
loop\?
|
||||
jsr rchar
|
||||
inx
|
||||
lda \1,x
|
||||
bne loop\?
|
||||
endm
|
||||
|
||||
;initialize I/O as required (example: configure & enable ACIA)
|
||||
report_init
|
||||
;nothing to initialize
|
||||
rprt rmsg_start
|
||||
rts
|
||||
|
||||
;show stack (with saved registers), zeropage and absolute memory workspace
|
||||
;after an error was trapped in the test program
|
||||
report_error
|
||||
;save registers
|
||||
php
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
cld
|
||||
;show stack with index to registers at error
|
||||
rprt rmsg_stack
|
||||
tsx
|
||||
inx
|
||||
lda #1 ;address high
|
||||
jsr rhex
|
||||
txa ;address low
|
||||
jsr rhex
|
||||
rstack jsr rspace
|
||||
lda $100,x ;stack data
|
||||
jsr rhex
|
||||
inx
|
||||
bne rstack
|
||||
jsr rcrlf ;new line
|
||||
;show zero page workspace
|
||||
lda #0
|
||||
jsr rhex
|
||||
lda #zpt
|
||||
tax
|
||||
jsr rhex
|
||||
rzp jsr rspace
|
||||
lda 0,x
|
||||
jsr rhex
|
||||
inx
|
||||
cpx #zp_bss
|
||||
bne rzp
|
||||
jsr rcrlf
|
||||
jmp rend ; Skip Workspace since 65k is large
|
||||
;show absolute workspace
|
||||
lda #hi(data_segment)
|
||||
jsr rhex
|
||||
lda #lo(data_segment)
|
||||
jsr rhex
|
||||
ldx #0
|
||||
rabs jsr rspace
|
||||
lda data_segment,x
|
||||
jsr rhex
|
||||
inx
|
||||
cpx #(data_bss-data_segment)
|
||||
bne rabs
|
||||
;ask to continue
|
||||
rend
|
||||
rprt rmsg_cont
|
||||
rerr1 jsr rget
|
||||
cmp #'S'
|
||||
beq rskip
|
||||
cmp #'C'
|
||||
bne rerr1
|
||||
;restore registers
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
plp
|
||||
rts
|
||||
;skip the current test
|
||||
rskip lda #$f0 ;already end of tests?
|
||||
cmp test_case
|
||||
beq rerr1 ;skip is not available
|
||||
ldx #$ff ;clear stack
|
||||
txs
|
||||
inc test_case ;next test
|
||||
lda #lo(start) ;find begin of test
|
||||
sta zpt
|
||||
lda #hi(start)
|
||||
sta zpt+1
|
||||
rskipl1 ldy #4 ;search pattern
|
||||
rskipl2 lda (zpt),y ;next byte
|
||||
cmp rmark,y
|
||||
bne rskipnx ;no match
|
||||
dey
|
||||
bmi rskipf ;found pattern
|
||||
cpy #1 ;skip immediate value
|
||||
bne rskipl2
|
||||
dey
|
||||
beq rskipl2
|
||||
|
||||
rskipnx inc zpt ;next RAM location
|
||||
bne rskipl1
|
||||
inc zpt+1
|
||||
bne rskipl1
|
||||
|
||||
rskipf ldy #1 ;pattern found - check test number
|
||||
lda (zpt),y ;test number
|
||||
cmp #$f0 ;end of last test?
|
||||
beq rskipe ;ask to rerun all
|
||||
cmp test_case ;is next test?
|
||||
bne rskipnx ;continue searching
|
||||
rskipe jmp (zpt) ;start next test or rerun at end of tests
|
||||
|
||||
rmark lda #0 ;begin of test search pattern
|
||||
sta test_case
|
||||
|
||||
;show test has ended, ask to repeat
|
||||
report_success
|
||||
if rep_int = 1
|
||||
rprt rmsg_priority
|
||||
lda data_segment ;show interrupt sequence
|
||||
jsr rhex
|
||||
jsr rspace
|
||||
lda data_segment+1
|
||||
jsr rhex
|
||||
jsr rspace
|
||||
lda data_segment+2
|
||||
jsr rhex
|
||||
endif
|
||||
rprt rmsg_success
|
||||
rsuc1 jsr rget
|
||||
cmp #'R'
|
||||
bne rsuc1
|
||||
rts
|
||||
|
||||
;input subroutine
|
||||
;get a character from standard input
|
||||
;adjust according to the needs in your test environment
|
||||
rget ;get character in A
|
||||
;rget1
|
||||
; lda $bff1 ;wait RDRF
|
||||
; and #8
|
||||
; beq rget1
|
||||
;not a real ACIA - so RDRF is not checked
|
||||
; lda $bff0 ;read acia rx reg
|
||||
; lda $f004 ;Kowalski simulator default
|
||||
lda $bc01 ;KILIAN
|
||||
;the load can be replaced by a call to a kernal routine
|
||||
; jsr $ffcf ;example: CHRIN for a C64
|
||||
cmp #'a' ;lower case
|
||||
bcc rget1
|
||||
and #$5f ;convert to upper case
|
||||
rget1 rts
|
||||
|
||||
;output subroutines
|
||||
rcrlf lda #10
|
||||
jsr rchar
|
||||
lda #13
|
||||
bne rchar
|
||||
|
||||
rspace lda #' '
|
||||
bne rchar
|
||||
|
||||
rhex pha ;report hex byte in A
|
||||
lsr a ;high nibble first
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr rnib
|
||||
pla ;now low nibble
|
||||
and #$f
|
||||
|
||||
rnib clc ;report nibble in A
|
||||
adc #'0' ;make printable 0-9
|
||||
cmp #'9'+1
|
||||
bcc rchar
|
||||
adc #6 ;make printable A-F
|
||||
|
||||
;send a character to standard output
|
||||
;adjust according to the needs in your test environment
|
||||
;register X needs to be preserved!
|
||||
rchar ;report character in A
|
||||
; pha ;wait TDRF
|
||||
;rchar1 lda $bff1
|
||||
; and #$10
|
||||
; beq rchar1
|
||||
; pla
|
||||
;not a real ACIA - so TDRF is not checked
|
||||
; sta $bff0 ;write acia tx reg
|
||||
; sta $f001 ;Kowalski simulator default
|
||||
sta $bc00 ;KILIAN
|
||||
;the store can be replaced by a call to a kernal routine
|
||||
; jsr $ffd2 ;example: CHROUT for a C64
|
||||
rts
|
||||
|
||||
rmsg_start
|
||||
db 10,13,"Started testing",10,13,0
|
||||
rmsg_stack
|
||||
db 10,13,"regs Y X A PS PCLPCH",10,13,0
|
||||
rmsg_cont
|
||||
db 10,13,"press C to continue or S to skip current test",10,13,0
|
||||
rmsg_success
|
||||
db 10,13,"All tests completed, press R to repeat",10,13,0
|
||||
if rep_int = 1
|
||||
rmsg_priority
|
||||
db 10,13,"interrupt sequence (NMI IRQ BRK) ",0
|
||||
endif
|
||||
|
||||
Reference in new issue
Block a user