mirror of
https://github.com/rkujawa/rk65c02.git
synced 2024-12-04 19:50:19 +00:00
1b936f087e
This test case is probably way too complex.
106 lines
3.3 KiB
ArmAsm
106 lines
3.3 KiB
ArmAsm
; stolen from: http://www.6502.org/tutorials/vflag.html
|
|
; adapted to vasm and std syntax by rkujawa
|
|
;
|
|
; Demonstrate that the V flag works as described
|
|
;
|
|
; Returns with ERROR = 0 if the test passes, ERROR = 1 if the test fails
|
|
;
|
|
; Five (additional) memory locations are used: ERROR, S1, S2, U1, and U2
|
|
; which can be located anywhere convenient in RAM
|
|
;
|
|
.org 0xC000
|
|
.set S1, 0x10
|
|
.set S2, 0x11
|
|
.set U1, 0x12
|
|
.set U2, 0x13
|
|
.set ERROR, 0x20
|
|
|
|
TEST: cld ; Clear decimal mode (just in case) for test
|
|
lda #1
|
|
sta ERROR ; Store 1 in ERROR until test passes
|
|
lda #0x80
|
|
sta S1 ; Initalize S1 and S2 to -128 ($80)
|
|
sta S2
|
|
lda #0
|
|
sta U1 ; Initialize U1 and U2 to 0
|
|
sta U2
|
|
ldy #1 ; Initialize Y (used to set and clear the carry flag) to 1
|
|
LOOP: jsr ADD ; Test ADC
|
|
cpx #1
|
|
beq DONE ; End if V and unsigned result do not agree (X = 1)
|
|
jsr SUB ; Test SBC
|
|
cpx #1
|
|
beq DONE ; End if V and unsigned result do not agree (X = 1)
|
|
inc S1
|
|
inc U1
|
|
bne LOOP ; Loop until all 256 possibilities of S1 and U1 are tested
|
|
inc S2
|
|
inc U2
|
|
bne LOOP ; Loop until all 256 possibilities of S2 and U2 are tested
|
|
dey
|
|
bpl LOOP ; Loop until both possiblities of the carry flag are tested
|
|
lda #0
|
|
sta ERROR ; All tests pass, so store 0 in ERROR
|
|
DONE: stp
|
|
;
|
|
; Test ADC
|
|
;
|
|
; X is initialized to 0
|
|
; X is incremented when V = 1
|
|
; X is incremented when the unsigned result predicts an overflow
|
|
; Therefore, if the V flag and the unsigned result agree, X will be
|
|
; incremented zero or two times (returning X = 0 or X = 2), and if they do
|
|
; not agree X will be incremented once (returning X = 1)
|
|
;
|
|
ADD: cpy #1 ; Set carry when Y = 1, clear carry when Y = 0
|
|
lda S1 ; Test twos complement addition
|
|
adc S2
|
|
ldx #0 ; Initialize X to 0
|
|
bvc ADD1
|
|
inx ; Increment X if V = 1
|
|
ADD1: cpy #1 ; Set carry when Y = 1, clear carry when Y = 0
|
|
lda U1 ; Test unsigned addition
|
|
adc U2
|
|
bcs ADD3 ; Carry is set if U1 + U2 >= 256
|
|
bmi ADD2 ; U1 + U2 < 256, A >= 128 if U1 + U2 >= 128
|
|
inx ; Increment X if U1 + U2 < 128
|
|
ADD2: rts
|
|
ADD3: bpl ADD4 ; U1 + U2 >= 256, A <= 127 if U1 + U2 <= 383 ($17F)
|
|
inx ; Increment X if U1 + U2 > 383
|
|
ADD4: rts
|
|
|
|
;
|
|
; Test SBC
|
|
;
|
|
; X is initialized to 0
|
|
; X is incremented when V = 1
|
|
; X is incremented when the unsigned result predicts an overflow
|
|
; Therefore, if the V flag and the unsigned result agree, X will be
|
|
; incremented zero or two times (returning X = 0 or X = 2), and if they do
|
|
; not agree X will be incremented once (returning X = 1)
|
|
;
|
|
SUB: cpy #0x1 ; Set carry when Y = 1, clear carry when Y = 0
|
|
lda S1 ; Test twos complement subtraction
|
|
sbc S2
|
|
ldx #0x0 ; Initialize X to 0
|
|
bvc SUB1
|
|
inx ; Increment X if V = 1
|
|
SUB1: cpy #0x1 ; Set carry when Y = 1, clear carry when Y = 0
|
|
lda U1 ; Test unsigned subtraction
|
|
sbc U2
|
|
pha ; Save the low byte of result on the stack
|
|
lda #0xFF
|
|
sbc #0 ; result = (65280 + U1) - U2, 65280 = $FF00
|
|
cmp #0xFE
|
|
bne SUB4 ; Branch if result >= 65280 ($FF00) or result < 65024 ($FE00)
|
|
pla ; Get the low byte of result
|
|
bmi SUB3 ; result < 65280 ($FF00), A >= 128 if result >= 65152 ($FE80)
|
|
SUB2: inx ; Increment X if result < 65152 ($FE80)
|
|
SUB3: rts
|
|
SUB4: pla ; Get the low byte of result (does not affect the carry flag)
|
|
bcc SUB2 ; The carry flag is clear if result < 65024 ($FE00)
|
|
bpl SUB5 ; result >= 65280 ($FF00), A <= 127 if result <= 65407 ($FF7F)
|
|
inx ; Increment X if result > 65407 ($FF7F)
|
|
SUB5: rts
|
|
|