forked from gardners/c65gs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
kernel65.a65
136 lines (123 loc) · 3.65 KB
/
kernel65.a65
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
.org $E000
.advance $F000
reset: ; reset entry point
lda $D800
sta $0400
lda $DC00
sta $0401
jmp reset
; jsr TEST
counterloop:
LDA $1001
ADC #$01
STA $1001
inc $d020
LDA $1002
ADC #$00
STA $1002
LDA $1003
ADC #$00
STA $1003
LDA $1004
ADC #$00
STA $1004
JMP counterloop
.alias error $1027
.alias s1 $1026
.alias s2 $1025
.alias u1 $1024
.alias u2 $1023
TEST: CLD ; Clear decimal mode (just in case) for test
LDA #1
STA ERROR ; Store 1 in ERROR until test passes
LDA #$80
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: RTS
;
; 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 #1 ; Set carry when Y = 1, clear carry when Y = 0
LDA S1 ; Test twos complement subtraction
SBC S2
LDX #0 ; Initialize X to 0
BVC SUB1
INX ; Increment X if V = 1
SUB1: CPY #1 ; 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 #$FF
SBC #$00 ; result = (65280 + U1) - U2, 65280 = $FF00
CMP #$FE
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
irq: RTI
nmi: RTI
; 6502 interrupt and reset vectors
.advance $FFFA
.word nmi
.word reset
.word irq
.outfile "kernel65.bin"