mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-12-29 12:30:54 +00:00
364 lines
18 KiB
Plaintext
364 lines
18 KiB
Plaintext
AS65 Assembler for R6502 [1.42]. Copyright 1994-2007, Frank A. Kingswood Page 1
|
|
----------------------------------------------------- 6502_decimal_test.a65 ------------------------------------------------------
|
|
|
|
355 lines read, no errors in pass 1.
|
|
; 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:
|
|
0001 = cputype = 1 ; 0 = 6502, 1 = 65C02, 2 = 65C816
|
|
0001 = vld_bcd = 1 ; 0 = allow invalid bcd, 1 = valid bcd only
|
|
0000 = chk_a = 0 ; check accumulator
|
|
0000 = chk_n = 0 ; check sign (negative) flag
|
|
0000 = chk_v = 0 ; check overflow flag
|
|
0001 = chk_z = 1 ; check zero flag
|
|
0000 = chk_c = 0 ; check carry flag
|
|
|
|
end_of_test macro
|
|
db $db ;execute 65C02 stop instruction
|
|
endm
|
|
|
|
bss
|
|
0000 = org 0
|
|
; operands - register Y = carry in
|
|
0000 = N1 ds 1
|
|
0001 = N2 ds 1
|
|
; binary result
|
|
0002 = HA ds 1
|
|
0003 = HNVZC ds 1
|
|
;04
|
|
; decimal result
|
|
0004 = DA ds 1
|
|
0005 = DNVZC ds 1
|
|
; predicted results
|
|
0006 = AR ds 1
|
|
0007 = NF ds 1
|
|
;08
|
|
0008 = VF ds 1
|
|
0009 = ZF ds 1
|
|
000a = CF ds 1
|
|
000b = ERROR ds 1
|
|
;0C
|
|
; workspace
|
|
000c = N1L ds 1
|
|
000d = N1H ds 1
|
|
000e = N2L ds 1
|
|
000f = N2H ds 2
|
|
|
|
code
|
|
0200 = org $200
|
|
0200 : a001 TEST ldy #1 ; initialize Y (used to loop through carry flag values)
|
|
0202 : 840b sty ERROR ; store 1 in ERROR until the test passes
|
|
0204 : a900 lda #0 ; initialize N1 and N2
|
|
0206 : 8500 sta N1
|
|
0208 : 8501 sta N2
|
|
020a : a501 LOOP1 lda N2 ; N2L = N2 & $0F
|
|
020c : 290f and #$0F ; [1] see text
|
|
if vld_bcd = 1
|
|
020e : c90a cmp #$0a
|
|
0210 : b03e bcs NEXT2
|
|
endif
|
|
0212 : 850e sta N2L
|
|
0214 : a501 lda N2 ; N2H = N2 & $F0
|
|
0216 : 29f0 and #$F0 ; [2] see text
|
|
if vld_bcd = 1
|
|
0218 : c9a0 cmp #$a0
|
|
021a : b034 bcs NEXT2
|
|
endif
|
|
021c : 850f sta N2H
|
|
021e : 090f ora #$0F ; N2H+1 = (N2 & $F0) + $0F
|
|
0220 : 8510 sta N2H+1
|
|
0222 : a500 LOOP2 lda N1 ; N1L = N1 & $0F
|
|
0224 : 290f and #$0F ; [3] see text
|
|
if vld_bcd = 1
|
|
0226 : c90a cmp #$0a
|
|
0228 : b022 bcs NEXT1
|
|
endif
|
|
022a : 850c sta N1L
|
|
022c : a500 lda N1 ; N1H = N1 & $F0
|
|
022e : 29f0 and #$F0 ; [4] see text
|
|
if vld_bcd = 1
|
|
0230 : c9a0 cmp #$a0
|
|
0232 : b018 bcs NEXT1
|
|
endif
|
|
0234 : 850d sta N1H
|
|
0236 : 205c02 jsr ADD
|
|
0239 : 20e302 jsr A6502
|
|
023c : 20da02 jsr COMPARE
|
|
023f : d01a bne DONE
|
|
0241 : 20a002 jsr SUB
|
|
0244 : 20ec02 jsr S6502
|
|
0247 : 20da02 jsr COMPARE
|
|
024a : d00f bne DONE
|
|
024c : e600 NEXT1 inc N1 ; [5] see text
|
|
024e : d0d2 bne LOOP2 ; loop through all 256 values of N1
|
|
0250 : e601 NEXT2 inc N2 ; [6] see text
|
|
0252 : d0b6 bne LOOP1 ; loop through all 256 values of N2
|
|
0254 : 88 dey
|
|
0255 : 10b3 bpl LOOP1 ; loop through both values of the carry flag
|
|
0257 : a900 lda #0 ; test passed, so store 0 in ERROR
|
|
0259 : 850b sta ERROR
|
|
025b : DONE
|
|
end_of_test
|
|
025b : db > db $db ;execute 65C02 stop instruction
|
|
|
|
|
|
; 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
|
|
;
|
|
025c : f8 ADD sed ; decimal mode
|
|
025d : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|
025f : a500 lda N1
|
|
0261 : 6501 adc N2
|
|
0263 : 8504 sta DA ; actual accumulator result in decimal mode
|
|
0265 : 08 php
|
|
0266 : 68 pla
|
|
0267 : 8505 sta DNVZC ; actual flags result in decimal mode
|
|
0269 : d8 cld ; binary mode
|
|
026a : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|
026c : a500 lda N1
|
|
026e : 6501 adc N2
|
|
0270 : 8502 sta HA ; accumulator result of N1+N2 using binary arithmetic
|
|
|
|
0272 : 08 php
|
|
0273 : 68 pla
|
|
0274 : 8503 sta HNVZC ; flags result of N1+N2 using binary arithmetic
|
|
0276 : c001 cpy #1
|
|
0278 : a50c lda N1L
|
|
027a : 650e adc N2L
|
|
027c : c90a cmp #$0A
|
|
027e : a200 ldx #0
|
|
0280 : 9006 bcc A1
|
|
0282 : e8 inx
|
|
0283 : 6905 adc #5 ; add 6 (carry is set)
|
|
0285 : 290f and #$0F
|
|
0287 : 38 sec
|
|
0288 : 050d A1 ora N1H
|
|
;
|
|
; if N1L + N2L < $0A, then add N2 & $F0
|
|
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
|
|
;
|
|
028a : 750f adc N2H,x
|
|
028c : 08 php
|
|
028d : b004 bcs A2
|
|
028f : c9a0 cmp #$A0
|
|
0291 : 9003 bcc A3
|
|
0293 : 695f A2 adc #$5F ; add $60 (carry is set)
|
|
0295 : 38 sec
|
|
0296 : 8506 A3 sta AR ; predicted accumulator result
|
|
0298 : 08 php
|
|
0299 : 68 pla
|
|
029a : 850a sta CF ; predicted carry result
|
|
029c : 68 pla
|
|
;
|
|
; note that all 8 bits of the P register are stored in VF
|
|
;
|
|
029d : 8508 sta VF ; predicted V flags
|
|
029f : 60 rts
|
|
|
|
; Calculate the actual decimal mode accumulator and flags, and the
|
|
; accumulator and flag results when N2 is subtracted from N1 using binary
|
|
; arithmetic
|
|
;
|
|
02a0 : f8 SUB sed ; decimal mode
|
|
02a1 : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|
02a3 : a500 lda N1
|
|
02a5 : e501 sbc N2
|
|
02a7 : 8504 sta DA ; actual accumulator result in decimal mode
|
|
02a9 : 08 php
|
|
02aa : 68 pla
|
|
02ab : 8505 sta DNVZC ; actual flags result in decimal mode
|
|
02ad : d8 cld ; binary mode
|
|
02ae : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|
02b0 : a500 lda N1
|
|
02b2 : e501 sbc N2
|
|
02b4 : 8502 sta HA ; accumulator result of N1-N2 using binary arithmetic
|
|
|
|
02b6 : 08 php
|
|
02b7 : 68 pla
|
|
02b8 : 8503 sta HNVZC ; flags result of N1-N2 using binary arithmetic
|
|
02ba : 60 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
|
|
;
|
|
02bb : c001 SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|
02bd : a50c lda N1L
|
|
02bf : e50e sbc N2L
|
|
02c1 : a200 ldx #0
|
|
02c3 : b004 bcs S21
|
|
02c5 : e8 inx
|
|
02c6 : 290f and #$0F
|
|
02c8 : 18 clc
|
|
02c9 : 050d S21 ora N1H
|
|
;
|
|
; if N1L - N2L >= 0, then subtract N2 & $F0
|
|
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
|
;
|
|
02cb : f50f sbc N2H,x
|
|
02cd : b002 bcs S22
|
|
02cf : e95f sbc #$5F ; subtract $60 (carry is clear)
|
|
02d1 : e000 S22 cpx #0
|
|
02d3 : f002 beq S23
|
|
02d5 : e906 sbc #6
|
|
02d7 : 8506 S23 sta AR ; predicted accumulator result
|
|
02d9 : 60 rts
|
|
endif
|
|
|
|
; Compare accumulator actual results to predicted results
|
|
;
|
|
; Return:
|
|
; Z flag = 1 (BEQ branch) if same
|
|
; Z flag = 0 (BNE branch) if different
|
|
;
|
|
02da : 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
|
|
02da : a505 lda DNVZC
|
|
02dc : 4509 eor ZF ; mask off Z flag
|
|
02de : 2902 and #2
|
|
02e0 : d000 bne C1 ; [10] see text
|
|
endif
|
|
if chk_c = 1
|
|
lda DNVZC
|
|
eor CF
|
|
and #1 ; mask off C flag
|
|
endif
|
|
02e2 : 60 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
|
|
|
|
02e3 : a506 A6502 lda AR ; 65C02
|
|
02e5 : 08 php
|
|
02e6 : 68 pla
|
|
02e7 : 8507 sta NF
|
|
02e9 : 8509 sta ZF
|
|
02eb : 60 rts
|
|
|
|
02ec : 20bb02 S6502 jsr SUB2
|
|
02ef : a506 lda AR
|
|
02f1 : 08 php
|
|
02f2 : 68 pla
|
|
02f3 : 8507 sta NF
|
|
02f5 : 8509 sta ZF
|
|
02f7 : a503 lda HNVZC
|
|
02f9 : 8508 sta VF
|
|
02fb : 850a sta CF
|
|
02fd : 60 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
|
|
|
|
02ec = end TEST
|
|
|
|
No errors in pass 2.
|