OpenCores
URL https://opencores.org/ocsvn/cpu6502_true_cycle/cpu6502_true_cycle/trunk

Subversion Repositories cpu6502_true_cycle

[/] [cpu6502_true_cycle/] [trunk/] [asm/] [6502_decimal_test.a65] - Blame information for rev 25

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 fpga_is_fu
; Verify decimal mode behavior
2
; Written by Bruce Clark.  This code is public domain.
3
; see http://www.6502.org/tutorials/decimal_mode.html
4
;
5
; Returns:
6
;   ERROR = 0 if the test passed
7
;   ERROR = 1 if the test failed
8
;   modify the code at the DONE label for desired program end
9
;
10
; This routine requires 17 bytes of RAM -- 1 byte each for:
11
;   AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF
12
; and 2 bytes for N2H
13
;
14
; Variables:
15
;   N1 and N2 are the two numbers to be added or subtracted
16
;   N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2
17
;   DA and DNVZC are the actual accumulator and flag results in decimal mode
18
;   HA and HNVZC are the accumulator and flag results when N1 and N2 are
19
;     added or subtracted using binary arithmetic
20
;   AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and
21
;     flag results, calculated using binary arithmetic
22
;
23
; This program takes approximately 1 minute at 1 MHz (a few seconds more on
24
; a 65C02 than a 6502 or 65816)
25
;
26
 
27
; Configuration:
28
cputype = 1         ; 0 = 6502, 1 = 65C02, 2 = 65C816
29
vld_bcd = 0         ; 0 = allow invalid bcd, 1 = valid bcd only
30
chk_a   = 1         ; check accumulator
31
chk_n   = 1         ; check sign (negative) flag
32
chk_v   = 1         ; check overflow flag
33
chk_z   = 1         ; check zero flag
34
chk_c   = 1         ; check carry flag
35
 
36
end_of_test macro
37
                db  $db     ;execute 65C02 stop instruction
38
            endm
39
 
40
        data
41
        org 0
42
; operands - register Y = carry in
43
N1      ds  1
44
N2      ds  1
45
; binary result
46
HA      ds  1
47
HNVZC   ds  1
48
                    ;04
49
; decimal result
50
DA      ds  1
51
DNVZC   ds  1
52
; predicted results
53
AR      ds  1
54
NF      ds  1
55
                    ;08
56
VF      ds  1
57
ZF      ds  1
58
CF      ds  1
59
ERROR   ds  1
60
                    ;0C
61
; workspace
62
N1L     ds  1
63
N1H     ds  1
64
N2L     ds  1
65
N2H     ds  2
66
 
67
        code
68
        org $200
69
TEST    ldy #1    ; initialize Y (used to loop through carry flag values)
70
        sty ERROR ; store 1 in ERROR until the test passes
71
        lda #0    ; initialize N1 and N2
72
        sta N1
73
        sta N2
74
LOOP1   lda N2    ; N2L = N2 & $0F
75
        and #$0F  ; [1] see text
76
        if  vld_bcd = 1
77
            cmp #$0a
78
            bcs NEXT2
79
        endif
80
        sta N2L
81
        lda N2    ; N2H = N2 & $F0
82
        and #$F0  ; [2] see text
83
        if  vld_bcd = 1
84
            cmp #$a0
85
            bcs NEXT2
86
        endif
87
        sta N2H
88
        ora #$0F  ; N2H+1 = (N2 & $F0) + $0F
89
        sta N2H+1
90
LOOP2   lda N1    ; N1L = N1 & $0F
91
        and #$0F  ; [3] see text
92
        if  vld_bcd = 1
93
            cmp #$0a
94
            bcs NEXT1
95
        endif
96
        sta N1L
97
        lda N1    ; N1H = N1 & $F0
98
        and #$F0  ; [4] see text
99
        if  vld_bcd = 1
100
            cmp #$a0
101
            bcs NEXT1
102
        endif
103
        sta N1H
104
        jsr ADD
105
        jsr A6502
106
        jsr COMPARE
107
        bne DONE
108
        jsr SUB
109
        jsr S6502
110
        jsr COMPARE
111
        bne DONE
112
NEXT1   inc N1    ; [5] see text
113
        bne LOOP2 ; loop through all 256 values of N1
114
NEXT2   inc N2    ; [6] see text
115
        bne LOOP1 ; loop through all 256 values of N2
116
        dey
117
        bpl LOOP1 ; loop through both values of the carry flag
118
        lda #0    ; test passed, so store 0 in ERROR
119
        sta ERROR
120
DONE
121
                lda ERROR
122
                jmp DONE
123
        end_of_test
124
 
125
; Calculate the actual decimal mode accumulator and flags, the accumulator
126
; and flag results when N1 is added to N2 using binary arithmetic, the
127
; predicted accumulator result, the predicted carry flag, and the predicted
128
; V flag
129
;
130
ADD     sed       ; decimal mode
131
        cpy #1    ; set carry if Y = 1, clear carry if Y = 0
132
        lda N1
133
        adc N2
134
        sta DA    ; actual accumulator result in decimal mode
135
        php
136
        pla
137
        sta DNVZC ; actual flags result in decimal mode
138
        cld       ; binary mode
139
        cpy #1    ; set carry if Y = 1, clear carry if Y = 0
140
        lda N1
141
        adc N2
142
        sta HA    ; accumulator result of N1+N2 using binary arithmetic
143
 
144
        php
145
        pla
146
        sta HNVZC ; flags result of N1+N2 using binary arithmetic
147
        cpy #1
148
        lda N1L
149
        adc N2L
150
        cmp #$0A
151
        ldx #0
152
        bcc A1
153
        inx
154
        adc #5    ; add 6 (carry is set)
155
        and #$0F
156
        sec
157
A1      ora N1H
158
;
159
; if N1L + N2L <  $0A, then add N2 & $F0
160
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
161
;
162
        adc N2H,x
163
        php
164
        bcs A2
165
        cmp #$A0
166
        bcc A3
167
A2      adc #$5F  ; add $60 (carry is set)
168
        sec
169
A3      sta AR    ; predicted accumulator result
170
        php
171
        pla
172
        sta CF    ; predicted carry result
173
        pla
174
;
175
; note that all 8 bits of the P register are stored in VF
176
;
177
        sta VF    ; predicted V flags
178
        rts
179
 
180
; Calculate the actual decimal mode accumulator and flags, and the
181
; accumulator and flag results when N2 is subtracted from N1 using binary
182
; arithmetic
183
;
184
SUB     sed       ; decimal mode
185
        cpy #1    ; set carry if Y = 1, clear carry if Y = 0
186
        lda N1
187
        sbc N2
188
        sta DA    ; actual accumulator result in decimal mode
189
        php
190
        pla
191
        sta DNVZC ; actual flags result in decimal mode
192
        cld       ; binary mode
193
        cpy #1    ; set carry if Y = 1, clear carry if Y = 0
194
        lda N1
195
        sbc N2
196
        sta HA    ; accumulator result of N1-N2 using binary arithmetic
197
 
198
        php
199
        pla
200
        sta HNVZC ; flags result of N1-N2 using binary arithmetic
201
        rts
202
 
203
        if cputype != 1
204
; Calculate the predicted SBC accumulator result for the 6502 and 65816
205
;
206
SUB1        cpy #1    ; set carry if Y = 1, clear carry if Y = 0
207
            lda N1L
208
            sbc N2L
209
            ldx #0
210
            bcs S11
211
            inx
212
            sbc #5    ; subtract 6 (carry is clear)
213
            and #$0F
214
            clc
215
S11         ora N1H
216
;
217
; if N1L - N2L >= 0, then subtract N2 & $F0
218
; if N1L - N2L <  0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
219
;
220
            sbc N2H,x
221
            bcs S12
222
            sbc #$5F  ; subtract $60 (carry is clear)
223
S12         sta AR
224
            rts
225
        endif
226
 
227
        if cputype = 1
228
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
229
;
230
SUB2        cpy #1    ; set carry if Y = 1, clear carry if Y = 0
231
            lda N1L
232
            sbc N2L
233
            ldx #0
234
            bcs S21
235
            inx
236
            and #$0F
237
            clc
238
S21         ora N1H
239
;
240
; if N1L - N2L >= 0, then subtract N2 & $F0
241
; if N1L - N2L <  0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
242
;
243
            sbc N2H,x
244
            bcs S22
245
            sbc #$5F   ; subtract $60 (carry is clear)
246
S22         cpx #0
247
            beq S23
248
            sbc #6
249
S23         sta AR     ; predicted accumulator result
250
            rts
251
        endif
252
 
253
; Compare accumulator actual results to predicted results
254
;
255
; Return:
256
;   Z flag = 1 (BEQ branch) if same
257
;   Z flag = 0 (BNE branch) if different
258
;
259
COMPARE
260
        if chk_a = 1
261
            lda DA
262
            cmp AR
263
            bne C1
264
        endif
265
        if chk_n = 1
266
            lda DNVZC ; [7] see text
267
            eor NF
268
            and #$80  ; mask off N flag
269
            bne C1
270
        endif
271
        if chk_v = 1
272
            lda DNVZC ; [8] see text
273
            eor VF
274
            and #$40  ; mask off V flag
275
            bne C1    ; [9] see text
276
        endif
277
        if chk_z = 1
278
            lda DNVZC
279
            eor ZF    ; mask off Z flag
280
            and #2
281
            bne C1    ; [10] see text
282
        endif
283
        if chk_c = 1
284
            lda DNVZC
285
            eor CF
286
            and #1    ; mask off C flag
287
        endif
288
C1      rts
289
 
290
; These routines store the predicted values for ADC and SBC for the 6502,
291
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
292
 
293
        if cputype = 0
294
 
295
A6502       lda VF      ; 6502
296
;
297
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
298
; the N flag for NF
299
;
300
            sta NF
301
            lda HNVZC
302
            sta ZF
303
            rts
304
 
305
S6502       jsr SUB1
306
            lda HNVZC
307
            sta NF
308
            sta VF
309
            sta ZF
310
            sta CF
311
            rts
312
 
313
        endif
314
        if  cputype = 1
315
 
316
A6502       lda AR      ; 65C02
317
            php
318
            pla
319
            sta NF
320
            sta ZF
321
            rts
322
 
323
S6502       jsr SUB2
324
            lda AR
325
            php
326
            pla
327
            sta NF
328
            sta ZF
329
            lda HNVZC
330
            sta VF
331
            sta CF
332
            rts
333
 
334
        endif
335
        if  cputype = 2
336
 
337
A6502       lda AR      ; 65C816
338
            php
339
            pla
340
            sta NF
341
            sta ZF
342
            rts
343
 
344
S6502       jsr SUB1
345
            lda AR
346
            php
347
            pla
348
            sta NF
349
            sta ZF
350
            lda HNVZC
351
            sta VF
352
            sta CF
353
            rts
354
 
355
        endif
356
 
357
        org $fffa       ;vectors
358
        dw  TEST
359
        dw  TEST
360
        dw  TEST
361
 
362
        end TEST

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.