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

Subversion Repositories cpu65c02_true_cycle

[/] [cpu65c02_true_cycle/] [trunk/] [released/] [asm/] [65C02_extended_opcodes_test.a65c] - Blame information for rev 23

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 23 fpga_is_fu
;
2
; 6 5 C 0 2   E X T E N D E D   O P C O D E S   T E S T
3
;
4
; Copyright (C) 2013-2017  Klaus Dormann
5
;
6
; This program is free software: you can redistribute it and/or modify
7
; it under the terms of the GNU General Public License as published by
8
; the Free Software Foundation, either version 3 of the License, or
9
; (at your option) any later version.
10
;
11
; This program is distributed in the hope that it will be useful,
12
; but WITHOUT ANY WARRANTY; without even the implied warranty of
13
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
; GNU General Public License for more details.
15
;
16
; You should have received a copy of the GNU General Public License
17
; along with this program.  If not, see .
18
 
19
 
20
; This program is designed to test all additional 65C02 opcodes, addressing
21
; modes and functionality not available in the NMOS version of the 6502.
22
; The 6502_functional_test is a prerequisite to this test.
23
; NMI, IRQ, STP & WAI are covered in the 6502_interrupt_test.
24
;
25
; version 04-dec-2017
26
; contact info at http://2m5.de or email K@2m5.de
27
;
28
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
29
; command line switches: -l -m -s2 -w -x -h0
30
;                         |  |  |   |  |  no page headers in listing
31
;                         |  |  |   |  65C02 extensions
32
;                         |  |  |   wide listing (133 char/col)
33
;                         |  |  write intel hex file instead of binary
34
;                         |  expand macros in listing
35
;                         generate pass2 listing
36
;
37
; No IO - should be run from a monitor with access to registers.
38
; To run load intel hex image with a load command, than alter PC to 400 hex
39
; (code_segment) and enter a go command.
40
; Loop on program counter determines error or successful completion of test.
41
; Check listing for relevant traps (jump/branch *).
42
; Please note that in early tests some instructions will have to be used before
43
; they are actually tested!
44
;
45
; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled.
46
; Tests documented behavior of the original 65C02 only!
47
; Decimal ops will only be tested with valid BCD operands and the V flag will
48
; be ignored as it is absolutely useless in decimal mode.
49
;
50
; Debugging hints:
51
;     Most of the code is written sequentially. if you hit a trap, check the
52
;   immediately preceeding code for the instruction to be tested. Results are
53
;   tested first, flags are checked second by pushing them onto the stack and
54
;   pulling them to the accumulator after the result was checked. The "real"
55
;   flags are no longer valid for the tested instruction at this time!
56
;     If the tested instruction was indexed, the relevant index (X or Y) must
57
;   also be checked. Opposed to the flags, X and Y registers are still valid.
58
;
59
; versions:
60
;   19-jul-2013  1st version distributed for testing
61
;   23-jul-2013  fixed BRA out of range due to larger trap macros
62
;                added RAM integrity check
63
;   16-aug-2013  added error report to standard output option
64
;   23-aug-2015  change revoked
65
;   24-aug-2015  all self modifying immediate opcodes now execute in data RAM
66
;   28-aug-2015  fixed decimal adc/sbc immediate only testing carry
67
;   09-feb-2017  fixed RMB/SMB tested when they shouldn't be tested
68
;   04-dec-2017  fixed BRK not tested for actually going through the IRQ vector
69
;                added option to skip the remainder of a failing test
70
;                in report.i65
71
;                added skip override to undefined opcode as NOP test
72
 
73
 
74
; C O N F I G U R A T I O N
75
 
76
;ROM_vectors writable (0=no, 1=yes)
77
;if ROM vectors can not be used interrupts will not be trapped
78
;as a consequence BRK can not be tested but will be emulated to test RTI
79
ROM_vectors = 1
80
 
81
;load_data_direct (0=move from code segment, 1=load directly)
82
;loading directly is preferred but may not be supported by your platform
83
;0 produces only consecutive object code, 1 is not suitable for a binary image
84
load_data_direct = 1
85
 
86
;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow
87
;change) 2 requires extra code and is not recommended.
88
I_flag = 3
89
 
90
;configure memory - try to stay away from memory used by the system
91
;zero_page memory start address, $4e (78) consecutive Bytes required
92
;                                add 2 if I_flag = 2
93
zero_page = $a
94
 
95
;data_segment memory start address, $63 (99) consecutive Bytes required
96
; + 12 Bytes at data_segment + $f9 (JMP indirect page cross test)
97
data_segment = $200
98
    if (data_segment & $ff) != 0
99
        ERROR ERROR ERROR low byte of data_segment MUST be $00 !!
100
    endif
101
 
102
;code_segment memory start address, 10kB of consecutive space required
103
;                                   add 1 kB if I_flag = 2
104
code_segment = $400
105
 
106
;added WDC only opcodes WAI & STP (0=test as NOPs, >0=no test)
107
wdc_op = 1
108
 
109
;added Rockwell & WDC opcodes BBR, BBS, RMB & SMB
110
;(0=test as NOPs, 1=full test, >1=no test)
111
rkwl_wdc_op = 1
112
 
113
;skip testing all undefined opcodes override
114
;0=test as NOP, >0=skip
115
skip_nop = 0
116
 
117
;report errors through I/O channel (0=use standard self trap loops, 1=include
118
;report.i65 as I/O channel, add 3 kB)
119
report = 0
120
 
121
;RAM integrity test option. Checks for undesired RAM writes.
122
;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k)
123
;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM
124
ram_top = -1
125
 
126
        noopt       ;do not take shortcuts
127
 
128
;macros for error & success traps to allow user modification
129
;example:
130
;trap    macro
131
;        jsr my_error_handler
132
;        endm
133
;trap_eq macro
134
;        bne skip\?
135
;        trap           ;failed equal (zero)
136
;skip\?
137
;        endm
138
;
139
; my_error_handler should pop the calling address from the stack and report it.
140
; putting larger portions of code (more than 3 bytes) inside the trap macro
141
; may lead to branch range problems for some tests.
142
    if report = 0
143
trap    macro
144
        jmp *           ;failed anyway
145
        endm
146
trap_eq macro
147
        beq *           ;failed equal (zero)
148
        endm
149
trap_ne macro
150
        bne *           ;failed not equal (non zero)
151
        endm
152
trap_cs macro
153
        bcs *           ;failed carry set
154
        endm
155
trap_cc macro
156
        bcc *           ;failed carry clear
157
        endm
158
trap_mi macro
159
        bmi *           ;failed minus (bit 7 set)
160
        endm
161
trap_pl macro
162
        bpl *           ;failed plus (bit 7 clear)
163
        endm
164
trap_vs macro
165
        bvs *           ;failed overflow set
166
        endm
167
trap_vc macro
168
        bvc *           ;failed overflow clear
169
        endm
170
; please observe that during the test the stack gets invalidated
171
; therefore a RTS inside the success macro is not possible
172
success macro
173
        jmp *           ;test passed, no errors
174
        endm
175
    endif
176
    if report = 1
177
trap    macro
178
        jsr report_error
179
        endm
180
trap_eq macro
181
        bne skip\?
182
        trap           ;failed equal (zero)
183
skip\?
184
        endm
185
trap_ne macro
186
        beq skip\?
187
        trap            ;failed not equal (non zero)
188
skip\?
189
        endm
190
trap_cs macro
191
        bcc skip\?
192
        trap            ;failed carry set
193
skip\?
194
        endm
195
trap_cc macro
196
        bcs skip\?
197
        trap            ;failed carry clear
198
skip\?
199
        endm
200
trap_mi macro
201
        bpl skip\?
202
        trap            ;failed minus (bit 7 set)
203
skip\?
204
        endm
205
trap_pl macro
206
        bmi skip\?
207
        trap            ;failed plus (bit 7 clear)
208
skip\?
209
        endm
210
trap_vs macro
211
        bvc skip\?
212
        trap            ;failed overflow set
213
skip\?
214
        endm
215
trap_vc macro
216
        bvs skip\?
217
        trap            ;failed overflow clear
218
skip\?
219
        endm
220
; please observe that during the test the stack gets invalidated
221
; therefore a RTS inside the success macro is not possible
222
success macro
223
        jsr report_success
224
        endm
225
    endif
226
 
227
 
228
carry   equ %00000001   ;flag bits in status
229
zero    equ %00000010
230
intdis  equ %00000100
231
decmode equ %00001000
232
break   equ %00010000
233
reserv  equ %00100000
234
overfl  equ %01000000
235
minus   equ %10000000
236
 
237
fc      equ carry
238
fz      equ zero
239
fzc     equ carry+zero
240
fv      equ overfl
241
fvz     equ overfl+zero
242
fn      equ minus
243
fnc     equ minus+carry
244
fnz     equ minus+zero
245
fnzc    equ minus+zero+carry
246
fnv     equ minus+overfl
247
 
248
fao     equ break+reserv    ;bits always on after PHP, BRK
249
fai     equ fao+intdis      ;+ forced interrupt disable
250
m8      equ $ff             ;8 bit mask
251
m8i     equ $ff&~intdis     ;8 bit mask - interrupt disable
252
 
253
;macros to allow masking of status bits.
254
;masking of interrupt enable/disable on load and compare
255
;masking of always on bits after PHP or BRK (unused & break) on compare
256
        if I_flag = 0
257
load_flag   macro
258
            lda #\1&m8i         ;force enable interrupts (mask I)
259
            endm
260
cmp_flag    macro
261
            cmp #(\1|fao)&m8i   ;I_flag is always enabled + always on bits
262
            endm
263
eor_flag    macro
264
            eor #(\1&m8i|fao)   ;mask I, invert expected flags + always on bits
265
            endm
266
        endif
267
        if I_flag = 1
268
load_flag   macro
269
            lda #\1|intdis      ;force disable interrupts
270
            endm
271
cmp_flag    macro
272
            cmp #(\1|fai)&m8    ;I_flag is always disabled + always on bits
273
            endm
274
eor_flag    macro
275
            eor #(\1|fai)       ;invert expected flags + always on bits + I
276
            endm
277
        endif
278
        if I_flag = 2
279
load_flag   macro
280
            lda #\1
281
            ora flag_I_on       ;restore I-flag
282
            and flag_I_off
283
            endm
284
cmp_flag    macro
285
            eor flag_I_on       ;I_flag is never changed
286
            cmp #(\1|fao)&m8i   ;expected flags + always on bits, mask I
287
            endm
288
eor_flag    macro
289
            eor flag_I_on       ;I_flag is never changed
290
            eor #(\1&m8i|fao)   ;mask I, invert expected flags + always on bits
291
            endm
292
        endif
293
        if I_flag = 3
294
load_flag   macro
295
            lda #\1             ;allow test to change I-flag (no mask)
296
            endm
297
cmp_flag    macro
298
            cmp #(\1|fao)&m8    ;expected flags + always on bits
299
            endm
300
eor_flag    macro
301
            eor #\1|fao         ;invert expected flags + always on bits
302
            endm
303
        endif
304
 
305
;macros to set (register|memory|zeropage) & status
306
set_stat    macro       ;setting flags in the processor status register
307
            load_flag \1
308
            pha         ;use stack to load status
309
            plp
310
            endm
311
 
312
set_a       macro       ;precharging accu & status
313
            load_flag \2
314
            pha         ;use stack to load status
315
            lda #\1     ;precharge accu
316
            plp
317
            endm
318
 
319
set_x       macro       ;precharging index & status
320
            load_flag \2
321
            pha         ;use stack to load status
322
            ldx #\1     ;precharge index x
323
            plp
324
            endm
325
 
326
set_y       macro       ;precharging index & status
327
            load_flag \2
328
            pha         ;use stack to load status
329
            ldy #\1     ;precharge index y
330
            plp
331
            endm
332
 
333
set_ax      macro       ;precharging indexed accu & immediate status
334
            load_flag \2
335
            pha         ;use stack to load status
336
            lda \1,x    ;precharge accu
337
            plp
338
            endm
339
 
340
set_ay      macro       ;precharging indexed accu & immediate status
341
            load_flag \2
342
            pha         ;use stack to load status
343
            lda \1,y    ;precharge accu
344
            plp
345
            endm
346
 
347
set_z       macro       ;precharging indexed zp & immediate status
348
            load_flag \2
349
            pha         ;use stack to load status
350
            lda \1,x    ;load to zeropage
351
            sta zpt
352
            plp
353
            endm
354
 
355
set_zx      macro       ;precharging zp,x & immediate status
356
            load_flag \2
357
            pha         ;use stack to load status
358
            lda \1,x    ;load to indexed zeropage
359
            sta zpt,x
360
            plp
361
            endm
362
 
363
set_abs     macro       ;precharging indexed memory & immediate status
364
            load_flag \2
365
            pha         ;use stack to load status
366
            lda \1,x    ;load to memory
367
            sta abst
368
            plp
369
            endm
370
 
371
set_absx    macro       ;precharging abs,x & immediate status
372
            load_flag \2
373
            pha         ;use stack to load status
374
            lda \1,x    ;load to indexed memory
375
            sta abst,x
376
            plp
377
            endm
378
 
379
;macros to test (register|memory|zeropage) & status & (mask)
380
tst_stat    macro       ;testing flags in the processor status register
381
            php         ;save status
382
            pla         ;use stack to retrieve status
383
            pha
384
            cmp_flag \1
385
            trap_ne
386
            plp         ;restore status
387
            endm
388
 
389
tst_a       macro       ;testing result in accu & flags
390
            php         ;save flags
391
            cmp #\1     ;test result
392
            trap_ne
393
            pla         ;load status
394
            pha
395
            cmp_flag \2
396
            trap_ne
397
            plp         ;restore status
398
            endm
399
 
400
tst_as      macro       ;testing result in accu & flags, save accu
401
            pha
402
            php         ;save flags
403
            cmp #\1     ;test result
404
            trap_ne
405
            pla         ;load status
406
            pha
407
            cmp_flag \2
408
            trap_ne
409
            plp         ;restore status
410
            pla
411
            endm
412
 
413
tst_x       macro       ;testing result in x index & flags
414
            php         ;save flags
415
            cpx #\1     ;test result
416
            trap_ne
417
            pla         ;load status
418
            pha
419
            cmp_flag \2
420
            trap_ne
421
            plp         ;restore status
422
            endm
423
 
424
tst_y       macro       ;testing result in y index & flags
425
            php         ;save flags
426
            cpy #\1     ;test result
427
            trap_ne
428
            pla         ;load status
429
            pha
430
            cmp_flag \2
431
            trap_ne
432
            plp         ;restore status
433
            endm
434
 
435
tst_ax      macro       ;indexed testing result in accu & flags
436
            php         ;save flags
437
            cmp \1,x    ;test result
438
            trap_ne
439
            pla         ;load status
440
            eor_flag \3
441
            cmp \2,x    ;test flags
442
            trap_ne     ;
443
            endm
444
 
445
tst_ay      macro       ;indexed testing result in accu & flags
446
            php         ;save flags
447
            cmp \1,y    ;test result
448
            trap_ne     ;
449
            pla         ;load status
450
            eor_flag \3
451
            cmp \2,y    ;test flags
452
            trap_ne
453
            endm
454
 
455
tst_z       macro       ;indexed testing result in zp & flags
456
            php         ;save flags
457
            lda zpt
458
            cmp \1,x    ;test result
459
            trap_ne
460
            pla         ;load status
461
            eor_flag \3
462
            cmp \2,x    ;test flags
463
            trap_ne
464
            endm
465
 
466
tst_zx      macro       ;testing result in zp,x & flags
467
            php         ;save flags
468
            lda zpt,x
469
            cmp \1,x    ;test result
470
            trap_ne
471
            pla         ;load status
472
            eor_flag \3
473
            cmp \2,x    ;test flags
474
            trap_ne
475
            endm
476
 
477
tst_abs     macro       ;indexed testing result in memory & flags
478
            php         ;save flags
479
            lda abst
480
            cmp \1,x    ;test result
481
            trap_ne
482
            pla         ;load status
483
            eor_flag \3
484
            cmp \2,x    ;test flags
485
            trap_ne
486
            endm
487
 
488
tst_absx    macro       ;testing result in abs,x & flags
489
            php         ;save flags
490
            lda abst,x
491
            cmp \1,x    ;test result
492
            trap_ne
493
            pla         ;load status
494
            eor_flag \3
495
            cmp \2,x    ;test flags
496
            trap_ne
497
            endm
498
 
499
; RAM integrity test
500
;   verifies that none of the previous tests has altered RAM outside of the
501
;   designated write areas.
502
;   uses zpt word as indirect pointer, zpt+2 word as checksum
503
        if ram_top > -1
504
check_ram   macro
505
            cld
506
            lda #0
507
            sta zpt         ;set low byte of indirect pointer
508
            sta zpt+3       ;checksum high byte
509
            ldx #11         ;reset modifiable RAM
510
ccs1\?      sta jxi_tab,x   ;JMP indirect page cross area
511
            dex
512
            bpl ccs1\?
513
            clc
514
            ldx #zp_bss-zero_page ;zeropage - write test area
515
ccs3\?      adc zero_page,x
516
            bcc ccs2\?
517
            inc zpt+3       ;carry to high byte
518
            clc
519
ccs2\?      inx
520
            bne ccs3\?
521
            ldx #hi(abs1)   ;set high byte of indirect pointer
522
            stx zpt+1
523
            ldy #lo(abs1)   ;data after write & execute test area
524
ccs5\?      adc (zpt),y
525
            bcc ccs4\?
526
            inc zpt+3       ;carry to high byte
527
            clc
528
ccs4\?      iny
529
            bne ccs5\?
530
            inx             ;advance RAM high address
531
            stx zpt+1
532
            cpx #ram_top
533
            bne ccs5\?
534
            sta zpt+2       ;checksum low is
535
            cmp ram_chksm   ;checksum low expected
536
            trap_ne         ;checksum mismatch
537
            lda zpt+3       ;checksum high is
538
            cmp ram_chksm+1 ;checksum high expected
539
            trap_ne         ;checksum mismatch
540
            endm
541
        else
542
check_ram   macro
543
            ;RAM check disabled - RAM size not set
544
            endm
545
        endif
546
 
547
next_test   macro           ;make sure, tests don't jump the fence
548
            lda test_case   ;previous test
549
            cmp #test_num
550
            trap_ne         ;test is out of sequence
551
test_num = test_num + 1
552
            lda #test_num   ;*** next tests' number
553
            sta test_case
554
            ;check_ram       ;uncomment to find altered RAM after each test
555
            endm
556
 
557
    if load_data_direct = 1
558
        data
559
    else
560
        bss                 ;uninitialized segment, copy of data at end of code!
561
    endif
562
        org zero_page
563
;break test interrupt save
564
irq_a   ds  1               ;a register
565
irq_x   ds  1               ;x register
566
    if I_flag = 2
567
;masking for I bit in status
568
flag_I_on   ds  1           ;or mask to load flags
569
flag_I_off  ds  1           ;and mask to load flags
570
    endif
571
zpt                         ;5 bytes store/modify test area
572
;add/subtract operand generation and result/flag prediction
573
adfc    ds  1               ;carry flag before op
574
ad1     ds  1               ;operand 1 - accumulator
575
ad2     ds  1               ;operand 2 - memory / immediate
576
adrl    ds  1               ;expected result bits 0-7
577
adrh    ds  1               ;expected result bit 8 (carry)
578
adrf    ds  1               ;expected flags NV0000ZC (-V in decimal mode)
579
sb2     ds  1               ;operand 2 complemented for subtract
580
zp_bss
581
zp1     db  $c3,$82,$41,0   ;test patterns for LDx BIT ROL ROR ASL LSR
582
zp7f    db  $7f             ;test pattern for compare
583
;logical zeropage operands
584
zpOR    db  0,$1f,$71,$80   ;test pattern for OR
585
zpAN    db  $0f,$ff,$7f,$80 ;test pattern for AND
586
zpEO    db  $ff,$0f,$8f,$8f ;test pattern for EOR
587
;indirect addressing pointers
588
ind1    dw  abs1            ;indirect pointer to pattern in absolute memory
589
        dw  abs1+1
590
        dw  abs1+2
591
        dw  abs1+3
592
        dw  abs7f
593
inw1    dw  abs1-$f8        ;indirect pointer for wrap-test pattern
594
indt    dw  abst            ;indirect pointer to store area in absolute memory
595
        dw  abst+1
596
        dw  abst+2
597
        dw  abst+3
598
inwt    dw  abst-$f8        ;indirect pointer for wrap-test store
599
indAN   dw  absAN           ;indirect pointer to AND pattern in absolute memory
600
        dw  absAN+1
601
        dw  absAN+2
602
        dw  absAN+3
603
indEO   dw  absEO           ;indirect pointer to EOR pattern in absolute memory
604
        dw  absEO+1
605
        dw  absEO+2
606
        dw  absEO+3
607
indOR   dw  absOR           ;indirect pointer to OR pattern in absolute memory
608
        dw  absOR+1
609
        dw  absOR+2
610
        dw  absOR+3
611
;add/subtract indirect pointers
612
adi2    dw  ada2            ;indirect pointer to operand 2 in absolute memory
613
sbi2    dw  sba2            ;indirect pointer to complemented operand 2 (SBC)
614
adiy2   dw  ada2-$ff        ;with offset for indirect indexed
615
sbiy2   dw  sba2-$ff
616
zp_bss_end
617
 
618
        org data_segment
619
pg_x    ds  2               ;high JMP indirect address for page cross bug
620
test_case   ds  1           ;current test number
621
ram_chksm   ds  2           ;checksum for RAM integrity test
622
;add/subtract operand copy - abs tests write area
623
abst                        ;5 bytes store/modify test area
624
ada2    ds  1               ;operand 2
625
sba2    ds  1               ;operand 2 complemented for subtract
626
        ds  3               ;fill remaining bytes
627
data_bss
628
    if load_data_direct = 1
629
ex_adci adc #0              ;execute immediate opcodes
630
        rts
631
ex_sbci sbc #0              ;execute immediate opcodes
632
        rts
633
    else
634
ex_adci ds  3
635
ex_sbci ds  3
636
    endif
637
abs1    db  $c3,$82,$41,0   ;test patterns for LDx BIT ROL ROR ASL LSR
638
abs7f   db  $7f             ;test pattern for compare
639
;loads
640
fLDx    db  fn,fn,0,fz      ;expected flags for load
641
;shifts
642
rASL                        ;expected result ASL & ROL -carry
643
rROL    db  $86,$04,$82,0   ; "
644
rROLc   db  $87,$05,$83,1   ;expected result ROL +carry
645
rLSR                        ;expected result LSR & ROR -carry
646
rROR    db  $61,$41,$20,0   ; "
647
rRORc   db  $e1,$c1,$a0,$80 ;expected result ROR +carry
648
fASL                        ;expected flags for shifts
649
fROL    db  fnc,fc,fn,fz    ;no carry in
650
fROLc   db  fnc,fc,fn,0     ;carry in
651
fLSR
652
fROR    db  fc,0,fc,fz      ;no carry in
653
fRORc   db  fnc,fn,fnc,fn   ;carry in
654
;increments (decrements)
655
rINC    db  $7f,$80,$ff,0,1 ;expected result for INC/DEC
656
fINC    db  0,fn,fn,fz,0    ;expected flags for INC/DEC
657
;logical memory operand
658
absOR   db  0,$1f,$71,$80   ;test pattern for OR
659
absAN   db  $0f,$ff,$7f,$80 ;test pattern for AND
660
absEO   db  $ff,$0f,$8f,$8f ;test pattern for EOR
661
;logical accu operand
662
absORa  db  0,$f1,$1f,0     ;test pattern for OR
663
absANa  db  $f0,$ff,$ff,$ff ;test pattern for AND
664
absEOa  db  $ff,$f0,$f0,$0f ;test pattern for EOR
665
;logical results
666
absrlo  db  0,$ff,$7f,$80
667
absflo  db  fz,fn,0,fn
668
data_bss_end
669
;define area for page crossing JMP (abs) & JMP (abs,x) test
670
jxi_tab equ data_segment + $100 - 7     ;JMP (jxi_tab,x) x=6
671
ji_tab  equ data_segment + $100 - 3     ;JMP (ji_tab+2)
672
jxp_tab equ data_segment + $100         ;JMP (jxp_tab-255) x=255
673
 
674
 
675
        code
676
        org code_segment
677
start   cld
678
        ldx #$ff
679
        txs
680
        lda #0          ;*** test 0 = initialize
681
        sta test_case
682
test_num = 0
683
 
684
;stop interrupts before initializing BSS
685
    if I_flag = 1
686
        sei
687
    endif
688
 
689
;initialize I/O for report channel
690
    if report = 1
691
        jsr report_init
692
    endif
693
 
694
;initialize BSS segment
695
    if load_data_direct != 1
696
        ldx #zp_end-zp_init-1
697
ld_zp   lda zp_init,x
698
        sta zp_bss,x
699
        dex
700
        bpl ld_zp
701
        ldx #data_end-data_init-1
702
ld_data lda data_init,x
703
        sta data_bss,x
704
        dex
705
        bpl ld_data
706
      if ROM_vectors = 1
707
        ldx #5
708
ld_vect lda vec_init,x
709
        sta vec_bss,x
710
        dex
711
        bpl ld_vect
712
      endif
713
    endif
714
 
715
;retain status of interrupt flag
716
    if I_flag = 2
717
        php
718
        pla
719
        and #4          ;isolate flag
720
        sta flag_I_on   ;or mask
721
        eor #lo(~4)     ;reverse
722
        sta flag_I_off  ;and mask
723
    endif
724
 
725
;generate checksum for RAM integrity test
726
    if ram_top > -1
727
        lda #0
728
        sta zpt         ;set low byte of indirect pointer
729
        sta ram_chksm+1 ;checksum high byte
730
        ldx #11         ;reset modifiable RAM
731
gcs1    sta jxi_tab,x   ;JMP indirect page cross area
732
        dex
733
        bpl gcs1
734
        clc
735
        ldx #zp_bss-zero_page ;zeropage - write test area
736
gcs3    adc zero_page,x
737
        bcc gcs2
738
        inc ram_chksm+1 ;carry to high byte
739
        clc
740
gcs2    inx
741
        bne gcs3
742
        ldx #hi(abs1)   ;set high byte of indirect pointer
743
        stx zpt+1
744
        ldy #lo(abs1)   ;data after write & execute test area
745
gcs5    adc (zpt),y
746
        bcc gcs4
747
        inc ram_chksm+1 ;carry to high byte
748
        clc
749
gcs4    iny
750
        bne gcs5
751
        inx             ;advance RAM high address
752
        stx zpt+1
753
        cpx #ram_top
754
        bne gcs5
755
        sta ram_chksm   ;checksum complete
756
    endif
757
        next_test
758
 
759
;testing stack operations PHX PHY PLX PLY
760
        lda #$99        ;protect a
761
        ldx #$ff        ;initialize stack
762
        txs
763
        ldx #$55
764
        phx
765
        ldx #$aa
766
        phx
767
        cpx $1fe        ;on stack ?
768
        trap_ne
769
        tsx
770
        cpx #$fd        ;sp decremented?
771
        trap_ne
772
        ply
773
        cpy #$aa        ;successful retreived from stack?
774
        trap_ne
775
        ply
776
        cpy #$55
777
        trap_ne
778
        cpy $1ff        ;remains on stack?
779
        trap_ne
780
        tsx
781
        cpx #$ff        ;sp incremented?
782
        trap_ne
783
 
784
        ldy #$a5
785
        phy
786
        ldy #$5a
787
        phy
788
        cpy $1fe        ;on stack ?
789
        trap_ne
790
        tsx
791
        cpx #$fd        ;sp decremented?
792
        trap_ne
793
        plx
794
        cpx #$5a        ;successful retreived from stack?
795
        trap_ne
796
        plx
797
        cpx #$a5
798
        trap_ne
799
        cpx $1ff        ;remains on stack?
800
        trap_ne
801
        tsx
802
        cpx #$ff        ;sp incremented?
803
        trap_ne
804
        cmp #$99        ;unchanged?
805
        trap_ne
806
        next_test
807
 
808
; test PHX does not alter flags or X but PLX does
809
        ldy #$aa        ;protect y
810
        set_x 1,$ff     ;push
811
        phx
812
        tst_x 1,$ff
813
        set_x 0,0
814
        phx
815
        tst_x 0,0
816
        set_x $ff,$ff
817
        phx
818
        tst_x $ff,$ff
819
        set_x 1,0
820
        phx
821
        tst_x 1,0
822
        set_x 0,$ff
823
        phx
824
        tst_x 0,$ff
825
        set_x $ff,0
826
        phx
827
        tst_x $ff,0
828
        set_x 0,$ff     ;pull
829
        plx
830
        tst_x $ff,$ff-zero
831
        set_x $ff,0
832
        plx
833
        tst_x 0,zero
834
        set_x $fe,$ff
835
        plx
836
        tst_x 1,$ff-zero-minus
837
        set_x 0,0
838
        plx
839
        tst_x $ff,minus
840
        set_x $ff,$ff
841
        plx
842
        tst_x 0,$ff-minus
843
        set_x $fe,0
844
        plx
845
        tst_x 1,0
846
        cpy #$aa        ;Y unchanged
847
        trap_ne
848
        next_test
849
 
850
; test PHY does not alter flags or Y but PLY does
851
        ldx #$55        ;x & a protected
852
        set_y 1,$ff     ;push
853
        phy
854
        tst_y 1,$ff
855
        set_y 0,0
856
        phy
857
        tst_y 0,0
858
        set_y $ff,$ff
859
        phy
860
        tst_y $ff,$ff
861
        set_y 1,0
862
        phy
863
        tst_y 1,0
864
        set_y 0,$ff
865
        phy
866
        tst_y 0,$ff
867
        set_y $ff,0
868
        phy
869
        tst_y $ff,0
870
        set_y 0,$ff     ;pull
871
        ply
872
        tst_y $ff,$ff-zero
873
        set_y $ff,0
874
        ply
875
        tst_y 0,zero
876
        set_y $fe,$ff
877
        ply
878
        tst_y 1,$ff-zero-minus
879
        set_y 0,0
880
        ply
881
        tst_y $ff,minus
882
        set_y $ff,$ff
883
        ply
884
        tst_y 0,$ff-minus
885
        set_y $fe,0
886
        ply
887
        tst_y 1,0
888
        cpx #$55        ;x unchanged?
889
        trap_ne
890
        next_test
891
 
892
; PC modifying instructions (BRA, BBR, BBS, 1, 2, 3 byte NOPs, JMP(abs,x))
893
; testing unconditional branch BRA
894
 
895
        ldx #$81        ;protect unused registers
896
        ldy #$7e
897
        set_a 0,$ff
898
        bra br1         ;branch should always be taken
899
        trap
900
br1
901
        tst_a 0,$ff
902
        set_a $ff,0
903
        bra br2         ;branch should always be taken
904
        trap
905
br2
906
        tst_a $ff,0
907
        cpx #$81
908
        trap_ne
909
        cpy #$7e
910
        trap_ne
911
        next_test
912
 
913
        ldy #0          ;branch range test
914
        bra bra0
915
 
916
bra1    cpy #1
917
        trap_ne         ;long range backward
918
        iny
919
        bra bra2
920
 
921
bra3    cpy #3
922
        trap_ne         ;long range backward
923
        iny
924
        bra bra4
925
 
926
bra5    cpy #5
927
        trap_ne         ;long range backward
928
        iny
929
        ldy #0
930
        bra brf0
931
 
932
        iny
933
        iny
934
        iny
935
        iny
936
brf0    bra brf1
937
 
938
        iny
939
        iny
940
        iny
941
brf1    iny
942
        bra brf2
943
 
944
        iny
945
        iny
946
brf2    iny
947
        iny
948
        bra brf3
949
 
950
        iny
951
brf3    iny
952
        iny
953
        iny
954
        bra brf4
955
 
956
brf4    iny
957
        iny
958
        iny
959
        iny
960
        cpy #10
961
        trap_ne     ;short range forward
962
        bra brb0
963
 
964
brb4    dey
965
        dey
966
        dey
967
        dey
968
        bra brb5
969
 
970
brb3    dey
971
        dey
972
        dey
973
        bra brb4
974
 
975
brb2    dey
976
        dey
977
        bra brb3
978
 
979
brb1    dey
980
        bra brb2
981
 
982
brb0    bra brb1
983
 
984
brb5    cpy #0
985
        trap_ne     ;short range backward
986
        bra bra6
987
 
988
bra4    cpy #4
989
        trap_ne     ;long range forward
990
        iny
991
        bra bra5
992
 
993
bra2    cpy #2
994
        trap_ne     ;long range forward
995
        iny
996
        bra bra3
997
 
998
bra0    cpy #0
999
        trap_ne     ;long range forward
1000
        iny
1001
        bra bra1
1002
 
1003
bra6
1004
        next_test
1005
 
1006
    if rkwl_wdc_op = 1
1007
; testing BBR & BBS
1008
 
1009
bbt     macro           ;\1 = bitnum
1010
        lda #(1<<\1)    ;testing 1 bit on
1011
        sta zpt
1012
        set_a $33,0     ;with flags off
1013
        bbr \1,zpt,fail1\?
1014
        bbs \1,zpt,ok1\?
1015
        trap            ;bbs branch not taken
1016
fail1\?
1017
        trap            ;bbr branch taken
1018
ok1\?
1019
        tst_a $33,0
1020
        set_a $cc,$ff   ;with flags on
1021
        bbr \1,zpt,fail2\?
1022
        bbs \1,zpt,ok2\?
1023
        trap            ;bbs branch not taken
1024
fail2\?
1025
        trap            ;bbr branch taken
1026
ok2\?
1027
        tst_a $cc,$ff
1028
        lda zpt
1029
        cmp #(1<<\1)
1030
        trap_ne         ;zp altered
1031
        lda #$ff-(1<<\1) ;testing 1 bit off
1032
        sta zpt
1033
        set_a $33,0     ;with flags off
1034
        bbs \1,zpt,fail3\?
1035
        bbr \1,zpt,ok3\?
1036
        trap            ;bbr branch not taken
1037
fail3\?
1038
        trap            ;bbs branch taken
1039
ok3\?
1040
        tst_a $33,0
1041
        set_a $cc,$ff   ;with flags on
1042
        bbs \1,zpt,fail4\?
1043
        bbr \1,zpt,ok4\?
1044
        trap            ;bbr branch not taken
1045
fail4\?
1046
        trap            ;bbs branch taken
1047
ok4\?
1048
        tst_a $cc,$ff
1049
        lda zpt
1050
        cmp #$ff-(1<<\1)
1051
        trap_ne         ;zp altered
1052
        endm
1053
 
1054
        ldx #$11        ;test bbr/bbs integrity
1055
        ldy #$22
1056
        bbt 0
1057
        bbt 1
1058
        bbt 2
1059
        bbt 3
1060
        bbt 4
1061
        bbt 5
1062
        bbt 6
1063
        bbt 7
1064
        cpx #$11
1065
        trap_ne         ;x overwritten
1066
        cpy #$22
1067
        trap_ne         ;y overwritten
1068
        next_test
1069
 
1070
bbrc    macro           ;\1 = bitnum
1071
        bbr \1,zpt,skip\?
1072
        eor #(1<<\1)
1073
skip\?
1074
        endm
1075
bbsc    macro           ;\1 = bitnum
1076
        bbs \1,zpt,skip\?
1077
        eor #(1<<\1)
1078
skip\?
1079
        endm
1080
 
1081
        lda #0          ;combined bit test
1082
        sta zpt
1083
bbcl    lda #0
1084
        bbrc 0
1085
        bbrc 1
1086
        bbrc 2
1087
        bbrc 3
1088
        bbrc 4
1089
        bbrc 5
1090
        bbrc 6
1091
        bbrc 7
1092
        eor zpt
1093
        trap_ne         ;failed bbr bitnum in accu
1094
        lda #$ff
1095
        bbsc 0
1096
        bbsc 1
1097
        bbsc 2
1098
        bbsc 3
1099
        bbsc 4
1100
        bbsc 5
1101
        bbsc 6
1102
        bbsc 7
1103
        eor zpt
1104
        trap_ne         ;failed bbs bitnum in accu
1105
        inc zpt
1106
        bne bbcl
1107
        next_test
1108
    endif
1109
 
1110
; testing NOP
1111
 
1112
nop_test    macro       ;\1 = opcode, \2 = # of bytes
1113
            ldy #$42
1114
            ldx #4-\2
1115
            db  \1          ;test nop length
1116
        if \2 = 1
1117
            dex
1118
            dex
1119
        endif
1120
        if \2 = 2
1121
            iny
1122
            dex
1123
        endif
1124
        if \2 = 3
1125
            iny
1126
            iny
1127
        endif
1128
            dex
1129
            trap_ne         ;wrong number of bytes
1130
            set_a $ff-\1,0
1131
            db  \1          ;test nop integrity - flags off
1132
            nop
1133
            nop
1134
            tst_a $ff-\1,0
1135
            set_a $aa-\1,$ff
1136
            db  \1          ;test nop integrity - flags on
1137
            nop
1138
            nop
1139
            tst_a $aa-\1,$ff
1140
            cpy #$42
1141
            trap_ne         ;y changed
1142
            cpx #0
1143
            trap_ne         ;x changed
1144
            endm
1145
 
1146
    if skip_nop = 0
1147
        nop_test $02,2
1148
        nop_test $22,2
1149
        nop_test $42,2
1150
        nop_test $62,2
1151
        nop_test $82,2
1152
        nop_test $c2,2
1153
        nop_test $e2,2
1154
        nop_test $44,2
1155
        nop_test $54,2
1156
        nop_test $d4,2
1157
        nop_test $f4,2
1158
        nop_test $5c,3
1159
        nop_test $dc,3
1160
        nop_test $fc,3
1161
        nop_test $03,1
1162
        nop_test $13,1
1163
        nop_test $23,1
1164
        nop_test $33,1
1165
        nop_test $43,1
1166
        nop_test $53,1
1167
        nop_test $63,1
1168
        nop_test $73,1
1169
        nop_test $83,1
1170
        nop_test $93,1
1171
        nop_test $a3,1
1172
        nop_test $b3,1
1173
        nop_test $c3,1
1174
        nop_test $d3,1
1175
        nop_test $e3,1
1176
        nop_test $f3,1
1177
        nop_test $0b,1
1178
        nop_test $1b,1
1179
        nop_test $2b,1
1180
        nop_test $3b,1
1181
        nop_test $4b,1
1182
        nop_test $5b,1
1183
        nop_test $6b,1
1184
        nop_test $7b,1
1185
        nop_test $8b,1
1186
        nop_test $9b,1
1187
        nop_test $ab,1
1188
        nop_test $bb,1
1189
        nop_test $eb,1
1190
        nop_test $fb,1
1191
    if rkwl_wdc_op = 0      ;NOPs not available on Rockwell & WDC 65C02
1192
        nop_test $07,1
1193
        nop_test $17,1
1194
        nop_test $27,1
1195
        nop_test $37,1
1196
        nop_test $47,1
1197
        nop_test $57,1
1198
        nop_test $67,1
1199
        nop_test $77,1
1200
        nop_test $87,1
1201
        nop_test $97,1
1202
        nop_test $a7,1
1203
        nop_test $b7,1
1204
        nop_test $c7,1
1205
        nop_test $d7,1
1206
        nop_test $e7,1
1207
        nop_test $f7,1
1208
        nop_test $0f,1
1209
        nop_test $1f,1
1210
        nop_test $2f,1
1211
        nop_test $3f,1
1212
        nop_test $4f,1
1213
        nop_test $5f,1
1214
        nop_test $6f,1
1215
        nop_test $7f,1
1216
        nop_test $8f,1
1217
        nop_test $9f,1
1218
        nop_test $af,1
1219
        nop_test $bf,1
1220
        nop_test $cf,1
1221
        nop_test $df,1
1222
        nop_test $ef,1
1223
        nop_test $ff,1
1224
    endif
1225
    if  wdc_op = 0          ;NOPs not available on WDC 65C02 (WAI, STP)
1226
        nop_test $cb,1
1227
        nop_test $db,1
1228
    endif
1229
        next_test
1230
    endif
1231
 
1232
; jump indirect (test page cross bug is fixed)
1233
        ldx #3          ;prepare table
1234
ji1     lda ji_adr,x
1235
        sta ji_tab,x
1236
        dex
1237
        bpl ji1
1238
        lda #hi(ji_px) ;high address if page cross bug
1239
        sta pg_x
1240
        set_stat 0
1241
        lda #'I'
1242
        ldx #'N'
1243
        ldy #'D'        ;N=0, V=0, Z=0, C=0
1244
        jmp (ji_tab)
1245
        nop
1246
        trap_ne         ;runover protection
1247
 
1248
        dey
1249
        dey
1250
ji_ret  php             ;either SP or Y count will fail, if we do not hit
1251
        dey
1252
        dey
1253
        dey
1254
        plp
1255
        trap_eq         ;returned flags OK?
1256
        trap_pl
1257
        trap_cc
1258
        trap_vc
1259
        cmp #('I'^$aa)  ;returned registers OK?
1260
        trap_ne
1261
        cpx #('N'+1)
1262
        trap_ne
1263
        cpy #('D'-6)
1264
        trap_ne
1265
        tsx             ;SP check
1266
        cpx #$ff
1267
        trap_ne
1268
        next_test
1269
 
1270
; jump indexed indirect
1271
        ldx #11         ;prepare table
1272
jxi1    lda jxi_adr,x
1273
        sta jxi_tab,x
1274
        dex
1275
        bpl jxi1
1276
        lda #hi(jxi_px) ;high address if page cross bug
1277
        sta pg_x
1278
        set_stat 0
1279
        lda #'X'
1280
        ldx #4
1281
        ldy #'I'        ;N=0, V=0, Z=0, C=0
1282
        jmp (jxi_tab,x)
1283
        nop
1284
        trap_ne         ;runover protection
1285
 
1286
        dey
1287
        dey
1288
jxi_ret php             ;either SP or Y count will fail, if we do not hit
1289
        dey
1290
        dey
1291
        dey
1292
        plp
1293
        trap_eq         ;returned flags OK?
1294
        trap_pl
1295
        trap_cc
1296
        trap_vc
1297
        cmp #('X'^$aa)  ;returned registers OK?
1298
        trap_ne
1299
        cpx #6
1300
        trap_ne
1301
        cpy #('I'-6)
1302
        trap_ne
1303
        tsx             ;SP check
1304
        cpx #$ff
1305
        trap_ne
1306
 
1307
        lda #lo(jxp_ok) ;test with index causing a page cross
1308
        sta jxp_tab
1309
        lda #hi(jxp_ok)
1310
        sta jxp_tab+1
1311
        lda #lo(jxp_px)
1312
        sta pg_x
1313
        lda #hi(jxp_px)
1314
        sta pg_x+1
1315
        ldx #$ff
1316
        jmp (jxp_tab-$ff,x)
1317
 
1318
jxp_px
1319
        trap            ;page cross by index to wrong page
1320
 
1321
jxp_ok
1322
        next_test
1323
 
1324
    if ROM_vectors = 1
1325
; test BRK clears decimal mode
1326
        load_flag 0     ;with interrupts enabled if allowed!
1327
        pha
1328
        lda #'B'
1329
        ldx #'R'
1330
        ldy #'K'
1331
        plp             ;N=0, V=0, Z=0, C=0
1332
        brk
1333
        dey             ;should not be executed
1334
brk_ret0                ;address of break return
1335
        php             ;either SP or Y count will fail, if we do not hit
1336
        dey
1337
        dey
1338
        dey
1339
        cmp #'B'^$aa    ;returned registers OK?
1340
        ;the IRQ vector was never executed if A & X stay unmodified
1341
        trap_ne
1342
        cpx #'R'+1
1343
        trap_ne
1344
        cpy #'K'-6
1345
        trap_ne
1346
        pla             ;returned flags OK (unchanged)?
1347
        cmp_flag 0
1348
        trap_ne
1349
        tsx             ;sp?
1350
        cpx #$ff
1351
        trap_ne
1352
;pass 2
1353
        load_flag $ff   ;with interrupts disabled if allowed!
1354
        pha
1355
        lda #$ff-'B'
1356
        ldx #$ff-'R'
1357
        ldy #$ff-'K'
1358
        plp             ;N=1, V=1, Z=1, C=1
1359
        brk
1360
        dey             ;should not be executed
1361
brk_ret1                ;address of break return
1362
        php             ;either SP or Y count will fail, if we do not hit
1363
        dey
1364
        dey
1365
        dey
1366
        cmp #($ff-'B')^$aa  ;returned registers OK?
1367
        ;the IRQ vector was never executed if A & X stay unmodified
1368
        trap_ne
1369
        cpx #$ff-'R'+1
1370
        trap_ne
1371
        cpy #$ff-'K'-6
1372
        trap_ne
1373
        pla             ;returned flags OK (unchanged)?
1374
        cmp_flag $ff
1375
        trap_ne
1376
        tsx             ;sp?
1377
        cpx #$ff
1378
        trap_ne
1379
        next_test
1380
    endif
1381
 
1382
; testing accumulator increment/decrement INC A & DEC A
1383
        ldx #$ac    ;protect x & y
1384
        ldy #$dc
1385
        set_a $fe,$ff
1386
        inc a           ;ff
1387
        tst_as $ff,$ff-zero
1388
        inc a           ;00
1389
        tst_as 0,$ff-minus
1390
        inc a           ;01
1391
        tst_as 1,$ff-minus-zero
1392
        dec a           ;00
1393
        tst_as 0,$ff-minus
1394
        dec a           ;ff
1395
        tst_as $ff,$ff-zero
1396
        dec a           ;fe
1397
        set_a $fe,0
1398
        inc a           ;ff
1399
        tst_as $ff,minus
1400
        inc a           ;00
1401
        tst_as 0,zero
1402
        inc a           ;01
1403
        tst_as 1,0
1404
        dec a           ;00
1405
        tst_as 0,zero
1406
        dec a           ;ff
1407
        tst_as $ff,minus
1408
        cpx #$ac
1409
        trap_ne     ;x altered during test
1410
        cpy #$dc
1411
        trap_ne     ;y altered during test
1412
        tsx
1413
        cpx #$ff
1414
        trap_ne     ;sp push/pop mismatch
1415
        next_test
1416
 
1417
; testing load / store accumulator LDA / STA (zp)
1418
        ldx #$99    ;protect x & y
1419
        ldy #$66
1420
        set_stat 0
1421
        lda (ind1)
1422
        php         ;test stores do not alter flags
1423
        eor #$c3
1424
        plp
1425
        sta (indt)
1426
        php         ;flags after load/store sequence
1427
        eor #$c3
1428
        cmp #$c3    ;test result
1429
        trap_ne
1430
        pla         ;load status
1431
        eor_flag 0
1432
        cmp fLDx    ;test flags
1433
        trap_ne
1434
        set_stat 0
1435
        lda (ind1+2)
1436
        php         ;test stores do not alter flags
1437
        eor #$c3
1438
        plp
1439
        sta (indt+2)
1440
        php         ;flags after load/store sequence
1441
        eor #$c3
1442
        cmp #$82    ;test result
1443
        trap_ne
1444
        pla         ;load status
1445
        eor_flag 0
1446
        cmp fLDx+1  ;test flags
1447
        trap_ne
1448
        set_stat 0
1449
        lda (ind1+4)
1450
        php         ;test stores do not alter flags
1451
        eor #$c3
1452
        plp
1453
        sta (indt+4)
1454
        php         ;flags after load/store sequence
1455
        eor #$c3
1456
        cmp #$41    ;test result
1457
        trap_ne
1458
        pla         ;load status
1459
        eor_flag 0
1460
        cmp fLDx+2  ;test flags
1461
        trap_ne
1462
        set_stat 0
1463
        lda (ind1+6)
1464
        php         ;test stores do not alter flags
1465
        eor #$c3
1466
        plp
1467
        sta (indt+6)
1468
        php         ;flags after load/store sequence
1469
        eor #$c3
1470
        cmp #0      ;test result
1471
        trap_ne
1472
        pla         ;load status
1473
        eor_flag 0
1474
        cmp fLDx+3  ;test flags
1475
        trap_ne
1476
        cpx #$99
1477
        trap_ne     ;x altered during test
1478
        cpy #$66
1479
        trap_ne     ;y altered during test
1480
 
1481
        ldy #3      ;testing store result
1482
        ldx #0
1483
tstai1  lda abst,y
1484
        eor #$c3
1485
        cmp abs1,y
1486
        trap_ne     ;store to indirect data
1487
        txa
1488
        sta abst,y  ;clear
1489
        dey
1490
        bpl tstai1
1491
 
1492
        ldx #$99    ;protect x & y
1493
        ldy #$66
1494
        set_stat $ff
1495
        lda (ind1)
1496
        php         ;test stores do not alter flags
1497
        eor #$c3
1498
        plp
1499
        sta (indt)
1500
        php         ;flags after load/store sequence
1501
        eor #$c3
1502
        cmp #$c3    ;test result
1503
        trap_ne
1504
        pla         ;load status
1505
        eor_flag lo~fnz ;mask bits not altered
1506
        cmp fLDx    ;test flags
1507
        trap_ne
1508
        set_stat $ff
1509
        lda (ind1+2)
1510
        php         ;test stores do not alter flags
1511
        eor #$c3
1512
        plp
1513
        sta (indt+2)
1514
        php         ;flags after load/store sequence
1515
        eor #$c3
1516
        cmp #$82    ;test result
1517
        trap_ne
1518
        pla         ;load status
1519
        eor_flag lo~fnz ;mask bits not altered
1520
        cmp fLDx+1  ;test flags
1521
        trap_ne
1522
        set_stat $ff
1523
        lda (ind1+4)
1524
        php         ;test stores do not alter flags
1525
        eor #$c3
1526
        plp
1527
        sta (indt+4)
1528
        php         ;flags after load/store sequence
1529
        eor #$c3
1530
        cmp #$41    ;test result
1531
        trap_ne
1532
        pla         ;load status
1533
        eor_flag lo~fnz ;mask bits not altered
1534
        cmp fLDx+2  ;test flags
1535
        trap_ne
1536
        set_stat $ff
1537
        lda (ind1+6)
1538
        php         ;test stores do not alter flags
1539
        eor #$c3
1540
        plp
1541
        sta (indt+6)
1542
        php         ;flags after load/store sequence
1543
        eor #$c3
1544
        cmp #0      ;test result
1545
        trap_ne
1546
        pla         ;load status
1547
        eor_flag lo~fnz ;mask bits not altered
1548
        cmp fLDx+3  ;test flags
1549
        trap_ne
1550
        cpx #$99
1551
        trap_ne     ;x altered during test
1552
        cpy #$66
1553
        trap_ne     ;y altered during test
1554
 
1555
        ldy #3      ;testing store result
1556
        ldx #0
1557
tstai2  lda abst,y
1558
        eor #$c3
1559
        cmp abs1,y
1560
        trap_ne     ;store to indirect data
1561
        txa
1562
        sta abst,y  ;clear
1563
        dey
1564
        bpl tstai2
1565
        tsx
1566
        cpx #$ff
1567
        trap_ne     ;sp push/pop mismatch
1568
        next_test
1569
 
1570
; testing STZ - zp / abs / zp,x / abs,x
1571
        ldy #123    ;protect y
1572
        ldx #4      ;precharge test area
1573
        lda #7
1574
tstz1   sta zpt,x
1575
        asl a
1576
        dex
1577
        bpl tstz1
1578
        ldx #4
1579
        set_a $55,$ff
1580
        stz zpt
1581
        stz zpt+1
1582
        stz zpt+2
1583
        stz zpt+3
1584
        stz zpt+4
1585
        tst_a $55,$ff
1586
tstz2   lda zpt,x   ;verify zeros stored
1587
        trap_ne     ;non zero after STZ zp
1588
        dex
1589
        bpl tstz2
1590
        ldx #4      ;precharge test area
1591
        lda #7
1592
tstz3   sta zpt,x
1593
        asl a
1594
        dex
1595
        bpl tstz3
1596
        ldx #4
1597
        set_a $aa,0
1598
        stz zpt
1599
        stz zpt+1
1600
        stz zpt+2
1601
        stz zpt+3
1602
        stz zpt+4
1603
        tst_a $aa,0
1604
tstz4   lda zpt,x   ;verify zeros stored
1605
        trap_ne     ;non zero after STZ zp
1606
        dex
1607
        bpl tstz4
1608
 
1609
        ldx #4      ;precharge test area
1610
        lda #7
1611
tstz5   sta abst,x
1612
        asl a
1613
        dex
1614
        bpl tstz5
1615
        ldx #4
1616
        set_a $55,$ff
1617
        stz abst
1618
        stz abst+1
1619
        stz abst+2
1620
        stz abst+3
1621
        stz abst+4
1622
        tst_a $55,$ff
1623
tstz6   lda abst,x   ;verify zeros stored
1624
        trap_ne     ;non zero after STZ abs
1625
        dex
1626
        bpl tstz6
1627
        ldx #4      ;precharge test area
1628
        lda #7
1629
tstz7   sta abst,x
1630
        asl a
1631
        dex
1632
        bpl tstz7
1633
        ldx #4
1634
        set_a $aa,0
1635
        stz abst
1636
        stz abst+1
1637
        stz abst+2
1638
        stz abst+3
1639
        stz abst+4
1640
        tst_a $aa,0
1641
tstz8   lda abst,x   ;verify zeros stored
1642
        trap_ne     ;non zero after STZ abs
1643
        dex
1644
        bpl tstz8
1645
 
1646
        ldx #4      ;precharge test area
1647
        lda #7
1648
tstz11  sta zpt,x
1649
        asl a
1650
        dex
1651
        bpl tstz11
1652
        ldx #4
1653
tstz15
1654
        set_a $55,$ff
1655
        stz zpt,x
1656
        tst_a $55,$ff
1657
        dex
1658
        bpl tstz15
1659
        ldx #4
1660
tstz12  lda zpt,x   ;verify zeros stored
1661
        trap_ne     ;non zero after STZ zp
1662
        dex
1663
        bpl tstz12
1664
        ldx #4      ;precharge test area
1665
        lda #7
1666
tstz13  sta zpt,x
1667
        asl a
1668
        dex
1669
        bpl tstz13
1670
        ldx #4
1671
tstz16
1672
        set_a $aa,0
1673
        stz zpt,x
1674
        tst_a $aa,0
1675
        dex
1676
        bpl tstz16
1677
        ldx #4
1678
tstz14  lda zpt,x   ;verify zeros stored
1679
        trap_ne     ;non zero after STZ zp
1680
        dex
1681
        bpl tstz14
1682
 
1683
        ldx #4      ;precharge test area
1684
        lda #7
1685
tstz21  sta abst,x
1686
        asl a
1687
        dex
1688
        bpl tstz21
1689
        ldx #4
1690
tstz25
1691
        set_a $55,$ff
1692
        stz abst,x
1693
        tst_a $55,$ff
1694
        dex
1695
        bpl tstz25
1696
        ldx #4
1697
tstz22  lda abst,x   ;verify zeros stored
1698
        trap_ne     ;non zero after STZ zp
1699
        dex
1700
        bpl tstz22
1701
        ldx #4      ;precharge test area
1702
        lda #7
1703
tstz23  sta abst,x
1704
        asl a
1705
        dex
1706
        bpl tstz23
1707
        ldx #4
1708
tstz26
1709
        set_a $aa,0
1710
        stz abst,x
1711
        tst_a $aa,0
1712
        dex
1713
        bpl tstz26
1714
        ldx #4
1715
tstz24  lda abst,x   ;verify zeros stored
1716
        trap_ne     ;non zero after STZ zp
1717
        dex
1718
        bpl tstz24
1719
 
1720
        cpy #123
1721
        trap_ne     ;y altered during test
1722
        tsx
1723
        cpx #$ff
1724
        trap_ne     ;sp push/pop mismatch
1725
        next_test
1726
 
1727
; testing BIT - zp,x / abs,x / #
1728
        ldy #$42
1729
        ldx #3
1730
        set_a $ff,0
1731
        bit zp1,x   ;00 - should set Z / clear  NV
1732
        tst_a $ff,fz
1733
        dex
1734
        set_a 1,0
1735
        bit zp1,x   ;41 - should set V (M6) / clear NZ
1736
        tst_a 1,fv
1737
        dex
1738
        set_a 1,0
1739
        bit zp1,x   ;82 - should set N (M7) & Z / clear V
1740
        tst_a 1,fnz
1741
        dex
1742
        set_a 1,0
1743
        bit zp1,x   ;c3 - should set N (M7) & V (M6) / clear Z
1744
        tst_a 1,fnv
1745
 
1746
        set_a 1,$ff
1747
        bit zp1,x   ;c3 - should set N (M7) & V (M6) / clear Z
1748
        tst_a 1,~fz
1749
        inx
1750
        set_a 1,$ff
1751
        bit zp1,x   ;82 - should set N (M7) & Z / clear V
1752
        tst_a 1,~fv
1753
        inx
1754
        set_a 1,$ff
1755
        bit zp1,x   ;41 - should set V (M6) / clear NZ
1756
        tst_a 1,~fnz
1757
        inx
1758
        set_a $ff,$ff
1759
        bit zp1,x   ;00 - should set Z / clear  NV
1760
        tst_a $ff,~fnv
1761
 
1762
        set_a $ff,0
1763
        bit abs1,x  ;00 - should set Z / clear  NV
1764
        tst_a $ff,fz
1765
        dex
1766
        set_a 1,0
1767
        bit abs1,x  ;41 - should set V (M6) / clear NZ
1768
        tst_a 1,fv
1769
        dex
1770
        set_a 1,0
1771
        bit abs1,x  ;82 - should set N (M7) & Z / clear V
1772
        tst_a 1,fnz
1773
        dex
1774
        set_a 1,0
1775
        bit abs1,x  ;c3 - should set N (M7) & V (M6) / clear Z
1776
        tst_a 1,fnv
1777
 
1778
        set_a 1,$ff
1779
        bit abs1,x  ;c3 - should set N (M7) & V (M6) / clear Z
1780
        tst_a 1,~fz
1781
        inx
1782
        set_a 1,$ff
1783
        bit abs1,x  ;82 - should set N (M7) & Z / clear V
1784
        tst_a 1,~fv
1785
        inx
1786
        set_a 1,$ff
1787
        bit abs1,x  ;41 - should set V (M6) / clear NZ
1788
        tst_a 1,~fnz
1789
        inx
1790
        set_a $ff,$ff
1791
        bit abs1,x  ;00 - should set Z / clear  NV
1792
        tst_a $ff,~fnv
1793
 
1794
        set_a $ff,0
1795
        bit #$00    ;00 - should set Z
1796
        tst_a $ff,fz
1797
        dex
1798
        set_a 1,0
1799
        bit #$41    ;41 - should clear Z
1800
        tst_a 1,0
1801
; *** DEBUG INFO ***
1802
; if it fails the previous test and your BIT # has set the V flag
1803
; see http://forum.6502.org/viewtopic.php?f=2&t=2241&p=27243#p27239
1804
; why it shouldn't alter N or V flags on a BIT #
1805
        dex
1806
        set_a 1,0
1807
        bit #$82    ;82 - should set Z
1808
        tst_a 1,fz
1809
        dex
1810
        set_a 1,0
1811
        bit #$c3    ;c3 - should clear Z
1812
        tst_a 1,0
1813
 
1814
        set_a 1,$ff
1815
        bit #$c3    ;c3 - clear Z
1816
        tst_a 1,~fz
1817
        inx
1818
        set_a 1,$ff
1819
        bit #$82    ;82 - should set Z
1820
        tst_a 1,$ff
1821
        inx
1822
        set_a 1,$ff
1823
        bit #$41    ;41 - should clear Z
1824
        tst_a 1,~fz
1825
        inx
1826
        set_a $ff,$ff
1827
        bit #$00   ;00 - should set Z
1828
        tst_a $ff,$ff
1829
 
1830
        cpx #3
1831
        trap_ne     ;x altered during test
1832
        cpy #$42
1833
        trap_ne     ;y altered during test
1834
        tsx
1835
        cpx #$ff
1836
        trap_ne     ;sp push/pop mismatch
1837
        next_test
1838
 
1839
; testing TRB, TSB - zp / abs
1840
 
1841
trbt    macro       ;\1 = memory, \2 = flags
1842
        sty \1
1843
        load_flag \2
1844
        pha
1845
        lda zpt+1
1846
        plp
1847
        trb \1
1848
        php
1849
        cmp zpt+1
1850
        trap_ne     ;accu was changed
1851
        pla
1852
        pha
1853
        ora #fz     ;mask Z
1854
        cmp_flag \2|fz
1855
        trap_ne     ;flags changed except Z
1856
        pla
1857
        and #fz
1858
        cmp zpt+2
1859
        trap_ne     ;Z flag invalid
1860
        lda zpt+3
1861
        cmp zpt
1862
        trap_ne     ;altered bits in memory wrong
1863
        endm
1864
 
1865
tsbt    macro       ;\1 = memory, \2 = flags
1866
        sty \1
1867
        load_flag \2
1868
        pha
1869
        lda zpt+1
1870
        plp
1871
        tsb \1
1872
        php
1873
        cmp zpt+1
1874
        trap_ne     ;accu was changed
1875
        pla
1876
        pha
1877
        ora #fz     ;mask Z
1878
        cmp_flag \2|fz
1879
        trap_ne     ;flags changed except Z
1880
        pla
1881
        and #fz
1882
        cmp zpt+2
1883
        trap_ne     ;Z flag invalid
1884
        lda zpt+4
1885
        cmp zpt
1886
        trap_ne     ;altered bits in memory wrong
1887
        endm
1888
 
1889
        ldx #$c0
1890
        ldy #0      ;op1 - memory save
1891
        ;   zpt     ;op1 - memory modifiable
1892
        stz zpt+1   ;op2 - accu
1893
        ;   zpt+2   ;and flags
1894
        ;   zpt+3   ;memory after reset
1895
        ;   zpt+4   ;memory after set
1896
 
1897
tbt1    tya
1898
        and zpt+1   ;set Z by anding the 2 operands
1899
        php
1900
        pla
1901
        and #fz     ;mask Z
1902
        sta zpt+2
1903
        tya         ;reset op1 bits by op2
1904
        eor #$ff
1905
        ora zpt+1
1906
        eor #$ff
1907
        sta zpt+3
1908
        tya         ;set op1 bits by op2
1909
        ora zpt+1
1910
        sta zpt+4
1911
 
1912
        trbt zpt,$ff
1913
        trbt abst,$ff
1914
        trbt zpt,0
1915
        trbt abst,0
1916
        tsbt zpt,$ff
1917
        tsbt abst,$ff
1918
        tsbt zpt,0
1919
        tsbt abst,0
1920
 
1921
        iny         ;iterate op1
1922
        bne tbt3
1923
        inc zpt+1   ;iterate op2
1924
        beq tbt2
1925
tbt3    jmp tbt1
1926
tbt2
1927
        cpx #$c0
1928
        trap_ne     ;x altered during test
1929
        tsx
1930
        cpx #$ff
1931
        trap_ne     ;sp push/pop mismatch
1932
        next_test
1933
 
1934
    if rkwl_wdc_op = 1
1935
; testing RMB, SMB - zp
1936
rmbt    macro       ;\1 = bitnum
1937
        lda #$ff
1938
        sta zpt
1939
        set_a $a5,0
1940
        rmb \1,zpt
1941
        tst_a $a5,0
1942
        lda zpt
1943
        cmp #$ff-(1<<\1)
1944
        trap_ne     ;wrong bits set or cleared
1945
        lda #1<<\1
1946
        sta zpt
1947
        set_a $5a,$ff
1948
        rmb \1,zpt
1949
        tst_a $5a,$ff
1950
        lda zpt
1951
        trap_ne     ;wrong bits set or cleared
1952
        endm
1953
smbt    macro       ;\1 = bitnum
1954
        lda #$ff-(1<<\1)
1955
        sta zpt
1956
        set_a $a5,0
1957
        smb \1,zpt
1958
        tst_a $a5,0
1959
        lda zpt
1960
        cmp #$ff
1961
        trap_ne     ;wrong bits set or cleared
1962
        lda #0
1963
        sta zpt
1964
        set_a $5a,$ff
1965
        smb \1,zpt
1966
        tst_a $5a,$ff
1967
        lda zpt
1968
        cmp #1<<\1
1969
        trap_ne     ;wrong bits set or cleared
1970
        endm
1971
 
1972
        ldx #$ba    ;protect x & y
1973
        ldy #$d0
1974
        rmbt 0
1975
        rmbt 1
1976
        rmbt 2
1977
        rmbt 3
1978
        rmbt 4
1979
        rmbt 5
1980
        rmbt 6
1981
        rmbt 7
1982
        smbt 0
1983
        smbt 1
1984
        smbt 2
1985
        smbt 3
1986
        smbt 4
1987
        smbt 5
1988
        smbt 6
1989
        smbt 7
1990
        cpx #$ba
1991
        trap_ne     ;x altered during test
1992
        cpy #$d0
1993
        trap_ne     ;y altered during test
1994
        tsx
1995
        cpx #$ff
1996
        trap_ne     ;sp push/pop mismatch
1997
        next_test
1998
    endif
1999
 
2000
; testing CMP - (zp)
2001
        ldx #$de    ;protect x & y
2002
        ldy #$ad
2003
        set_a $80,0
2004
        cmp (ind1+8)
2005
        tst_a $80,fc
2006
        set_a $7f,0
2007
        cmp (ind1+8)
2008
        tst_a $7f,fzc
2009
        set_a $7e,0
2010
        cmp (ind1+8)
2011
        tst_a $7e,fn
2012
        set_a $80,$ff
2013
        cmp (ind1+8)
2014
        tst_a $80,~fnz
2015
        set_a $7f,$ff
2016
        cmp (ind1+8)
2017
        tst_a $7f,~fn
2018
        set_a $7e,$ff
2019
        cmp (ind1+8)
2020
        tst_a $7e,~fzc
2021
        cpx #$de
2022
        trap_ne     ;x altered during test
2023
        cpy #$ad
2024
        trap_ne     ;y altered during test
2025
        tsx
2026
        cpx #$ff
2027
        trap_ne     ;sp push/pop mismatch
2028
        next_test
2029
 
2030
; testing logical instructions - AND EOR ORA (zp)
2031
        ldx #$42    ;protect x & y
2032
 
2033
        ldy #0      ;AND
2034
        lda indAN   ;set indirect address
2035
        sta zpt
2036
        lda indAN+1
2037
        sta zpt+1
2038
tand1
2039
        set_ay  absANa,0
2040
        and (zpt)
2041
        tst_ay  absrlo,absflo,0
2042
        inc zpt
2043
        iny
2044
        cpy #4
2045
        bne tand1
2046
        dey
2047
        dec zpt
2048
tand2
2049
        set_ay  absANa,$ff
2050
        and (zpt)
2051
        tst_ay  absrlo,absflo,$ff-fnz
2052
        dec zpt
2053
        dey
2054
        bpl tand2
2055
 
2056
        ldy #0      ;EOR
2057
        lda indEO   ;set indirect address
2058
        sta zpt
2059
        lda indEO+1
2060
        sta zpt+1
2061
teor1
2062
        set_ay  absEOa,0
2063
        eor (zpt)
2064
        tst_ay  absrlo,absflo,0
2065
        inc zpt
2066
        iny
2067
        cpy #4
2068
        bne teor1
2069
        dey
2070
        dec zpt
2071
teor2
2072
        set_ay  absEOa,$ff
2073
        eor (zpt)
2074
        tst_ay  absrlo,absflo,$ff-fnz
2075
        dec zpt
2076
        dey
2077
        bpl teor2
2078
 
2079
        ldy #0      ;ORA
2080
        lda indOR   ;set indirect address
2081
        sta zpt
2082
        lda indOR+1
2083
        sta zpt+1
2084
tora1
2085
        set_ay  absORa,0
2086
        ora (zpt)
2087
        tst_ay  absrlo,absflo,0
2088
        inc zpt
2089
        iny
2090
        cpy #4
2091
        bne tora1
2092
        dey
2093
        dec zpt
2094
tora2
2095
        set_ay  absORa,$ff
2096
        ora (zpt)
2097
        tst_ay  absrlo,absflo,$ff-fnz
2098
        dec zpt
2099
        dey
2100
        bpl tora2
2101
 
2102
        cpx #$42
2103
        trap_ne     ;x altered during test
2104
        tsx
2105
        cpx #$ff
2106
        trap_ne     ;sp push/pop mismatch
2107
        next_test
2108
 
2109
    if I_flag = 3
2110
        cli
2111
    endif
2112
 
2113
; full binary add/subtract test - (zp) only
2114
; iterates through all combinations of operands and carry input
2115
; uses increments/decrements to predict result & result flags
2116
        cld
2117
        ldx #ad2        ;for indexed test
2118
        ldy #$ff        ;max range
2119
        lda #0          ;start with adding zeroes & no carry
2120
        sta adfc        ;carry in - for diag
2121
        sta ad1         ;operand 1 - accumulator
2122
        sta ad2         ;operand 2 - memory or immediate
2123
        sta ada2        ;non zp
2124
        sta adrl        ;expected result bits 0-7
2125
        sta adrh        ;expected result bit 8 (carry out)
2126
        lda #$ff        ;complemented operand 2 for subtract
2127
        sta sb2
2128
        sta sba2        ;non zp
2129
        lda #2          ;expected Z-flag
2130
        sta adrf
2131
tadd    clc             ;test with carry clear
2132
        jsr chkadd
2133
        inc adfc        ;now with carry
2134
        inc adrl        ;result +1
2135
        php             ;save N & Z from low result
2136
        php
2137
        pla             ;accu holds expected flags
2138
        and #$82        ;mask N & Z
2139
        plp
2140
        bne tadd1
2141
        inc adrh        ;result bit 8 - carry
2142
tadd1   ora adrh        ;merge C to expected flags
2143
        sta adrf        ;save expected flags except overflow
2144
        sec             ;test with carry set
2145
        jsr chkadd
2146
        dec adfc        ;same for operand +1 but no carry
2147
        inc ad1
2148
        bne tadd        ;iterate op1
2149
        lda #0          ;preset result to op2 when op1 = 0
2150
        sta adrh
2151
        inc ada2
2152
        inc ad2
2153
        php             ;save NZ as operand 2 becomes the new result
2154
        pla
2155
        and #$82        ;mask N00000Z0
2156
        sta adrf        ;no need to check carry as we are adding to 0
2157
        dec sb2         ;complement subtract operand 2
2158
        dec sba2
2159
        lda ad2
2160
        sta adrl
2161
        bne tadd        ;iterate op2
2162
 
2163
        cpx #ad2
2164
        trap_ne         ;x altered during test
2165
        cpy #$ff
2166
        trap_ne         ;y altered during test
2167
        tsx
2168
        cpx #$ff
2169
        trap_ne         ;sp push/pop mismatch
2170
        next_test
2171
 
2172
; decimal add/subtract test
2173
; *** WARNING - tests documented behavior only! ***
2174
;   only valid BCD operands are tested, the V flag is ignored
2175
;   although V is declared as beeing valid on the 65C02 it has absolutely
2176
;   no use in BCD math. No sign = no overflow!
2177
; iterates through all valid combinations of operands and carry input
2178
; uses increments/decrements to predict result & carry flag
2179
        sed
2180
        ldx #ad2        ;for indexed test
2181
        ldy #$ff        ;max range
2182
        lda #$99        ;start with adding 99 to 99 with carry
2183
        sta ad1         ;operand 1 - accumulator
2184
        sta ad2         ;operand 2 - memory or immediate
2185
        sta ada2        ;non zp
2186
        sta adrl        ;expected result bits 0-7
2187
        lda #1          ;set carry in & out
2188
        sta adfc        ;carry in - for diag
2189
        sta adrh        ;expected result bit 8 (carry out)
2190
        lda #$81        ;set N & C (99 + 99 + C = 99 + C)
2191
        sta adrf
2192
        lda #0          ;complemented operand 2 for subtract
2193
        sta sb2
2194
        sta sba2        ;non zp
2195
tdad    sec             ;test with carry set
2196
        jsr chkdad
2197
        dec adfc        ;now with carry clear
2198
        lda adrl        ;decimal adjust result
2199
        bne tdad1       ;skip clear carry & preset result 99 (9A-1)
2200
        dec adrh
2201
        lda #$99
2202
        sta adrl
2203
        bne tdad3
2204
tdad1   and #$f         ;lower nibble mask
2205
        bne tdad2       ;no decimal adjust needed
2206
        dec adrl        ;decimal adjust (?0-6)
2207
        dec adrl
2208
        dec adrl
2209
        dec adrl
2210
        dec adrl
2211
        dec adrl
2212
tdad2   dec adrl        ;result -1
2213
tdad3   php             ;save valid flags
2214
        pla
2215
        and #$82        ;N-----Z-
2216
        ora adrh        ;N-----ZC
2217
        sta adrf
2218
        clc             ;test with carry clear
2219
        jsr chkdad
2220
        inc adfc        ;same for operand -1 but with carry
2221
        lda ad1         ;decimal adjust operand 1
2222
        beq tdad5       ;iterate operand 2
2223
        and #$f         ;lower nibble mask
2224
        bne tdad4       ;skip decimal adjust
2225
        dec ad1         ;decimal adjust (?0-6)
2226
        dec ad1
2227
        dec ad1
2228
        dec ad1
2229
        dec ad1
2230
        dec ad1
2231
tdad4   dec ad1         ;operand 1 -1
2232
        jmp tdad        ;iterate op1
2233
 
2234
tdad5   lda #$99        ;precharge op1 max
2235
        sta ad1
2236
        lda ad2         ;decimal adjust operand 2
2237
        beq tdad7       ;end of iteration
2238
        and #$f         ;lower nibble mask
2239
        bne tdad6       ;skip decimal adjust
2240
        dec ad2         ;decimal adjust (?0-6)
2241
        dec ad2
2242
        dec ad2
2243
        dec ad2
2244
        dec ad2
2245
        dec ad2
2246
        inc sb2         ;complemented decimal adjust for subtract (?9+6)
2247
        inc sb2
2248
        inc sb2
2249
        inc sb2
2250
        inc sb2
2251
        inc sb2
2252
tdad6   dec ad2         ;operand 2 -1
2253
        inc sb2         ;complemented operand for subtract
2254
        lda sb2
2255
        sta sba2        ;copy as non zp operand
2256
        lda ad2
2257
        sta ada2        ;copy as non zp operand
2258
        sta adrl        ;new result since op1+carry=00+carry +op2=op2
2259
        php             ;save flags
2260
        pla
2261
        and #$82        ;N-----Z-
2262
        ora #1          ;N-----ZC
2263
        sta adrf
2264
        inc adrh        ;result carry
2265
        jmp tdad        ;iterate op2
2266
 
2267
tdad7   cpx #ad2
2268
        trap_ne         ;x altered during test
2269
        cpy #$ff
2270
        trap_ne         ;y altered during test
2271
        tsx
2272
        cpx #$ff
2273
        trap_ne         ;sp push/pop mismatch
2274
        cld
2275
 
2276
        lda test_case
2277
        cmp #test_num
2278
        trap_ne         ;previous test is out of sequence
2279
        lda #$f0        ;mark opcode testing complete
2280
        sta test_case
2281
 
2282
; final RAM integrity test
2283
;   verifies that none of the previous tests has altered RAM outside of the
2284
;   designated write areas.
2285
        check_ram
2286
; *** DEBUG INFO ***
2287
; to debug checksum errors uncomment check_ram in the next_test macro to
2288
; narrow down the responsible opcode.
2289
; may give false errors when monitor, OS or other background activity is
2290
; allowed during previous tests.
2291
 
2292
 
2293
; S U C C E S S ************************************************
2294
; -------------
2295
        success         ;if you get here everything went well
2296
; -------------
2297
; S U C C E S S ************************************************
2298
        jmp start       ;run again
2299
 
2300
; core subroutine of the decimal add/subtract test
2301
; *** WARNING - tests documented behavior only! ***
2302
;   only valid BCD operands are tested, V flag is ignored
2303
; iterates through all valid combinations of operands and carry input
2304
; uses increments/decrements to predict result & carry flag
2305
chkdad
2306
; decimal ADC / SBC zp
2307
        php             ;save carry for subtract
2308
        lda ad1
2309
        adc ad2         ;perform add
2310
        php
2311
        cmp adrl        ;check result
2312
        trap_ne         ;bad result
2313
        pla             ;check flags
2314
        and #$83        ;mask N-----ZC
2315
        cmp adrf
2316
        trap_ne         ;bad flags
2317
        plp
2318
        php             ;save carry for next add
2319
        lda ad1
2320
        sbc sb2         ;perform subtract
2321
        php
2322
        cmp adrl        ;check result
2323
        trap_ne         ;bad result
2324
        pla             ;check flags
2325
        and #$83        ;mask N-----ZC
2326
        cmp adrf
2327
        trap_ne         ;bad flags
2328
        plp
2329
; decimal ADC / SBC abs
2330
        php             ;save carry for subtract
2331
        lda ad1
2332
        adc ada2        ;perform add
2333
        php
2334
        cmp adrl        ;check result
2335
        trap_ne         ;bad result
2336
        pla             ;check flags
2337
        and #$83        ;mask N-----ZC
2338
        cmp adrf
2339
        trap_ne         ;bad flags
2340
        plp
2341
        php             ;save carry for next add
2342
        lda ad1
2343
        sbc sba2        ;perform subtract
2344
        php
2345
        cmp adrl        ;check result
2346
        trap_ne         ;bad result
2347
        pla             ;check flags
2348
        and #$83        ;mask N-----ZC
2349
        cmp adrf
2350
        trap_ne         ;bad flags
2351
        plp
2352
; decimal ADC / SBC #
2353
        php             ;save carry for subtract
2354
        lda ad2
2355
        sta ex_adci+1   ;set ADC # operand
2356
        lda ad1
2357
        jsr ex_adci     ;execute ADC # in RAM
2358
        php
2359
        cmp adrl        ;check result
2360
        trap_ne         ;bad result
2361
        pla             ;check flags
2362
        and #$83        ;mask N-----ZC
2363
        cmp adrf
2364
        trap_ne         ;bad flags
2365
        plp
2366
        php             ;save carry for next add
2367
        lda sb2
2368
        sta ex_sbci+1   ;set SBC # operand
2369
        lda ad1
2370
        jsr ex_sbci     ;execute SBC # in RAM
2371
        php
2372
        cmp adrl        ;check result
2373
        trap_ne         ;bad result
2374
        pla             ;check flags
2375
        and #$83        ;mask N-----ZC
2376
        cmp adrf
2377
        trap_ne         ;bad flags
2378
        plp
2379
; decimal ADC / SBC zp,x
2380
        php             ;save carry for subtract
2381
        lda ad1
2382
        adc 0,x         ;perform add
2383
        php
2384
        cmp adrl        ;check result
2385
        trap_ne         ;bad result
2386
        pla             ;check flags
2387
        and #$83        ;mask N-----ZC
2388
        cmp adrf
2389
        trap_ne         ;bad flags
2390
        plp
2391
        php             ;save carry for next add
2392
        lda ad1
2393
        sbc sb2-ad2,x   ;perform subtract
2394
        php
2395
        cmp adrl        ;check result
2396
        trap_ne         ;bad result
2397
        pla             ;check flags
2398
        and #$83        ;mask N-----ZC
2399
        cmp adrf
2400
        trap_ne         ;bad flags
2401
        plp
2402
; decimal ADC / SBC abs,x
2403
        php             ;save carry for subtract
2404
        lda ad1
2405
        adc ada2-ad2,x  ;perform add
2406
        php
2407
        cmp adrl        ;check result
2408
        trap_ne         ;bad result
2409
        pla             ;check flags
2410
        and #$83        ;mask N-----ZC
2411
        cmp adrf
2412
        trap_ne         ;bad flags
2413
        plp
2414
        php             ;save carry for next add
2415
        lda ad1
2416
        sbc sba2-ad2,x  ;perform subtract
2417
        php
2418
        cmp adrl        ;check result
2419
        trap_ne         ;bad result
2420
        pla             ;check flags
2421
        and #$83        ;mask N-----ZC
2422
        cmp adrf
2423
        trap_ne         ;bad flags
2424
        plp
2425
; decimal ADC / SBC abs,y
2426
        php             ;save carry for subtract
2427
        lda ad1
2428
        adc ada2-$ff,y  ;perform add
2429
        php
2430
        cmp adrl        ;check result
2431
        trap_ne         ;bad result
2432
        pla             ;check flags
2433
        and #$83        ;mask N-----ZC
2434
        cmp adrf
2435
        trap_ne         ;bad flags
2436
        plp
2437
        php             ;save carry for next add
2438
        lda ad1
2439
        sbc sba2-$ff,y  ;perform subtract
2440
        php
2441
        cmp adrl        ;check result
2442
        trap_ne         ;bad result
2443
        pla             ;check flags
2444
        and #$83        ;mask N-----ZC
2445
        cmp adrf
2446
        trap_ne         ;bad flags
2447
        plp
2448
; decimal ADC / SBC (zp,x)
2449
        php             ;save carry for subtract
2450
        lda ad1
2451
        adc (lo adi2-ad2,x) ;perform add
2452
        php
2453
        cmp adrl        ;check result
2454
        trap_ne         ;bad result
2455
        pla             ;check flags
2456
        and #$83        ;mask N-----ZC
2457
        cmp adrf
2458
        trap_ne         ;bad flags
2459
        plp
2460
        php             ;save carry for next add
2461
        lda ad1
2462
        sbc (lo sbi2-ad2,x) ;perform subtract
2463
        php
2464
        cmp adrl        ;check result
2465
        trap_ne         ;bad result
2466
        pla             ;check flags
2467
        and #$83        ;mask N-----ZC
2468
        cmp adrf
2469
        trap_ne         ;bad flags
2470
        plp
2471
; decimal ADC / SBC (abs),y
2472
        php             ;save carry for subtract
2473
        lda ad1
2474
        adc (adiy2),y   ;perform add
2475
        php
2476
        cmp adrl        ;check result
2477
        trap_ne         ;bad result
2478
        pla             ;check flags
2479
        and #$83        ;mask N-----ZC
2480
        cmp adrf
2481
        trap_ne         ;bad flags
2482
        plp
2483
        php             ;save carry for next add
2484
        lda ad1
2485
        sbc (sbiy2),y   ;perform subtract
2486
        php
2487
        cmp adrl        ;check result
2488
        trap_ne         ;bad result
2489
        pla             ;check flags
2490
        and #$83        ;mask N-----ZC
2491
        cmp adrf
2492
        trap_ne         ;bad flags
2493
        plp
2494
; decimal ADC / SBC (zp)
2495
        php             ;save carry for subtract
2496
        lda ad1
2497
        adc (adi2)      ;perform add
2498
        php
2499
        cmp adrl        ;check result
2500
        trap_ne         ;bad result
2501
        pla             ;check flags
2502
        and #$83        ;mask N-----ZC
2503
        cmp adrf
2504
        trap_ne         ;bad flags
2505
        plp
2506
        php             ;save carry for next add
2507
        lda ad1
2508
        sbc (sbi2)      ;perform subtract
2509
        php
2510
        cmp adrl        ;check result
2511
        trap_ne         ;bad result
2512
        pla             ;check flags
2513
        and #$83        ;mask N-----ZC
2514
        cmp adrf
2515
        trap_ne         ;bad flags
2516
        plp
2517
        rts
2518
 
2519
; core subroutine of the full binary add/subtract test
2520
; iterates through all combinations of operands and carry input
2521
; uses increments/decrements to predict result & result flags
2522
chkadd  lda adrf        ;add V-flag if overflow
2523
        and #$83        ;keep N-----ZC / clear V
2524
        pha
2525
        lda ad1         ;test sign unequal between operands
2526
        eor ad2
2527
        bmi ckad1       ;no overflow possible - operands have different sign
2528
        lda ad1         ;test sign equal between operands and result
2529
        eor adrl
2530
        bpl ckad1       ;no overflow occured - operand and result have same sign
2531
        pla
2532
        ora #$40        ;set V
2533
        pha
2534
ckad1   pla
2535
        sta adrf        ;save expected flags
2536
; binary ADC / SBC (zp)
2537
        php             ;save carry for subtract
2538
        lda ad1
2539
        adc (adi2)      ;perform add
2540
        php
2541
        cmp adrl        ;check result
2542
        trap_ne         ;bad result
2543
        pla             ;check flags
2544
        and #$c3        ;mask NV----ZC
2545
        cmp adrf
2546
        trap_ne         ;bad flags
2547
        plp
2548
        php             ;save carry for next add
2549
        lda ad1
2550
        sbc (sbi2)      ;perform subtract
2551
        php
2552
        cmp adrl        ;check result
2553
        trap_ne         ;bad result
2554
        pla             ;check flags
2555
        and #$c3        ;mask NV----ZC
2556
        cmp adrf
2557
        trap_ne         ;bad flags
2558
        plp
2559
        rts
2560
 
2561
; target for the jump indirect test
2562
ji_adr  dw test_ji
2563
        dw ji_ret
2564
 
2565
        dey
2566
        dey
2567
test_ji
2568
        php             ;either SP or Y count will fail, if we do not hit
2569
        dey
2570
        dey
2571
        dey
2572
        plp
2573
        trap_cs         ;flags loaded?
2574
        trap_vs
2575
        trap_mi
2576
        trap_eq
2577
        cmp #'I'        ;registers loaded?
2578
        trap_ne
2579
        cpx #'N'
2580
        trap_ne
2581
        cpy #('D'-3)
2582
        trap_ne
2583
        pha             ;save a,x
2584
        txa
2585
        pha
2586
        tsx
2587
        cpx #$fd        ;check SP
2588
        trap_ne
2589
        pla             ;restore x
2590
        tax
2591
        set_stat $ff
2592
        pla             ;restore a
2593
        inx             ;return registers with modifications
2594
        eor #$aa        ;N=1, V=1, Z=0, C=1
2595
        jmp (ji_tab+2)
2596
        nop
2597
        nop
2598
        trap            ;runover protection
2599
        jmp start       ;catastrophic error - cannot continue
2600
 
2601
; target for the jump indirect test
2602
jxi_adr dw  trap_ind
2603
        dw  trap_ind
2604
        dw  test_jxi    ;+4
2605
        dw  jxi_ret     ;+6
2606
        dw  trap_ind
2607
        dw  trap_ind
2608
 
2609
        dey
2610
        dey
2611
test_jxi
2612
        php             ;either SP or Y count will fail, if we do not hit
2613
        dey
2614
        dey
2615
        dey
2616
        plp
2617
        trap_cs         ;flags loaded?
2618
        trap_vs
2619
        trap_mi
2620
        trap_eq
2621
        cmp #'X'        ;registers loaded?
2622
        trap_ne
2623
        cpx #4
2624
        trap_ne
2625
        cpy #('I'-3)
2626
        trap_ne
2627
        pha             ;save a,x
2628
        txa
2629
        pha
2630
        tsx
2631
        cpx #$fd        ;check SP
2632
        trap_ne
2633
        pla             ;restore x
2634
        tax
2635
        set_stat $ff
2636
        pla             ;restore a
2637
        inx             ;return registers with modifications
2638
        inx
2639
        eor #$aa        ;N=1, V=1, Z=0, C=1
2640
        jmp (jxi_tab,x)
2641
        nop
2642
        nop
2643
        trap            ;runover protection
2644
        jmp start       ;catastrophic error - cannot continue
2645
 
2646
; JMP (abs,x) with bad x
2647
        nop
2648
        nop
2649
trap_ind
2650
        nop
2651
        nop
2652
        trap            ;near miss indexed indirect jump
2653
        jmp start       ;catastrophic error - cannot continue
2654
 
2655
;trap in case of unexpected IRQ, NMI, BRK, RESET
2656
nmi_trap
2657
        trap            ;check stack for conditions at NMI
2658
        jmp start       ;catastrophic error - cannot continue
2659
res_trap
2660
        trap            ;unexpected RESET
2661
        jmp start       ;catastrophic error - cannot continue
2662
 
2663
        dey
2664
        dey
2665
irq_trap                ;BRK test or unextpected BRK or IRQ
2666
        php             ;either SP or Y count will fail, if we do not hit
2667
        dey
2668
        dey
2669
        dey
2670
        ;next traps could be caused by unexpected BRK or IRQ
2671
        ;check stack for BREAK and originating location
2672
        ;possible jump/branch into weeds (uninitialized space)
2673
        cmp #$ff-'B'    ;BRK pass 2 registers loaded?
2674
        beq break2
2675
        cmp #'B'        ;BRK pass 1 registers loaded?
2676
        trap_ne
2677
        cpx #'R'
2678
        trap_ne
2679
        cpy #'K'-3
2680
        trap_ne
2681
        sta irq_a       ;save registers during break test
2682
        stx irq_x
2683
        tsx             ;test break on stack
2684
        lda $102,x
2685
        cmp_flag 0      ;break test should have B=1 & unused=1 on stack
2686
        trap_ne         ;possible no break flag on stack
2687
        pla
2688
        cmp_flag intdis ;should have added interrupt disable
2689
        trap_ne
2690
        tsx
2691
        cpx #$fc        ;sp -3? (return addr, flags)
2692
        trap_ne
2693
        lda $1ff        ;propper return on stack
2694
        cmp #hi(brk_ret0)
2695
        trap_ne
2696
        lda $1fe
2697
        cmp #lo(brk_ret0)
2698
        trap_ne
2699
        load_flag $ff
2700
        pha
2701
        ldx irq_x
2702
        inx             ;return registers with modifications
2703
        lda irq_a
2704
        eor #$aa
2705
        plp             ;N=1, V=1, Z=1, C=1 but original flags should be restored
2706
        rti
2707
        trap            ;runover protection
2708
        jmp start       ;catastrophic error - cannot continue
2709
 
2710
break2                  ;BRK pass 2
2711
        cpx #$ff-'R'
2712
        trap_ne
2713
        cpy #$ff-'K'-3
2714
        trap_ne
2715
        sta irq_a       ;save registers during break test
2716
        stx irq_x
2717
        tsx             ;test break on stack
2718
        lda $102,x
2719
        cmp_flag $ff    ;break test should have B=1
2720
        trap_ne         ;possibly no break flag on stack
2721
        pla
2722
        cmp_flag $ff-decmode ;actual passed flags should have decmode cleared
2723
        trap_ne
2724
        tsx
2725
        cpx #$fc        ;sp -3? (return addr, flags)
2726
        trap_ne
2727
        lda $1ff        ;propper return on stack
2728
        cmp #hi(brk_ret1)
2729
        trap_ne
2730
        lda $1fe
2731
        cmp #lo(brk_ret1)
2732
        trap_ne
2733
        load_flag intdis
2734
        pha
2735
        ldx irq_x
2736
        inx             ;return registers with modifications
2737
        lda irq_a
2738
        eor #$aa
2739
        plp             ;N=0, V=0, Z=0, C=0 but original flags should be restored
2740
        rti
2741
        trap            ;runover protection
2742
        jmp start       ;catastrophic error - cannot continue
2743
 
2744
    if report = 1
2745
        include "report.i65"
2746
    endif
2747
 
2748
;copy of data to initialize BSS segment
2749
    if load_data_direct != 1
2750
zp_init
2751
zp1_    db  $c3,$82,$41,0   ;test patterns for LDx BIT ROL ROR ASL LSR
2752
zp7f_   db  $7f             ;test pattern for compare
2753
;logical zeropage operands
2754
zpOR_   db  0,$1f,$71,$80   ;test pattern for OR
2755
zpAN_   db  $0f,$ff,$7f,$80 ;test pattern for AND
2756
zpEO_   db  $ff,$0f,$8f,$8f ;test pattern for EOR
2757
;indirect addressing pointers
2758
ind1_   dw  abs1            ;indirect pointer to pattern in absolute memory
2759
        dw  abs1+1
2760
        dw  abs1+2
2761
        dw  abs1+3
2762
        dw  abs7f
2763
inw1_   dw  abs1-$f8        ;indirect pointer for wrap-test pattern
2764
indt_   dw  abst            ;indirect pointer to store area in absolute memory
2765
        dw  abst+1
2766
        dw  abst+2
2767
        dw  abst+3
2768
inwt_   dw  abst-$f8        ;indirect pointer for wrap-test store
2769
indAN_  dw  absAN           ;indirect pointer to AND pattern in absolute memory
2770
        dw  absAN+1
2771
        dw  absAN+2
2772
        dw  absAN+3
2773
indEO_  dw  absEO           ;indirect pointer to EOR pattern in absolute memory
2774
        dw  absEO+1
2775
        dw  absEO+2
2776
        dw  absEO+3
2777
indOR_  dw  absOR           ;indirect pointer to OR pattern in absolute memory
2778
        dw  absOR+1
2779
        dw  absOR+2
2780
        dw  absOR+3
2781
;add/subtract indirect pointers
2782
adi2_   dw  ada2            ;indirect pointer to operand 2 in absolute memory
2783
sbi2_   dw  sba2            ;indirect pointer to complemented operand 2 (SBC)
2784
adiy2_  dw  ada2-$ff        ;with offset for indirect indexed
2785
sbiy2_  dw  sba2-$ff
2786
zp_end
2787
    if (zp_end - zp_init) != (zp_bss_end - zp_bss)
2788
        ;force assembler error if size is different
2789
        ERROR ERROR ERROR   ;mismatch between bss and zeropage data
2790
    endif
2791
data_init
2792
ex_adc_ adc #0              ;execute immediate opcodes
2793
        rts
2794
ex_sbc_ sbc #0              ;execute immediate opcodes
2795
        rts
2796
abs1_   db  $c3,$82,$41,0   ;test patterns for LDx BIT ROL ROR ASL LSR
2797
abs7f_  db  $7f             ;test pattern for compare
2798
;loads
2799
fLDx_   db  fn,fn,0,fz      ;expected flags for load
2800
;shifts
2801
rASL_                       ;expected result ASL & ROL -carry
2802
rROL_   db  $86,$04,$82,0   ; "
2803
rROLc_  db  $87,$05,$83,1   ;expected result ROL +carry
2804
rLSR_                       ;expected result LSR & ROR -carry
2805
rROR_   db  $61,$41,$20,0   ; "
2806
rRORc_  db  $e1,$c1,$a0,$80 ;expected result ROR +carry
2807
fASL_                       ;expected flags for shifts
2808
fROL_   db  fnc,fc,fn,fz    ;no carry in
2809
fROLc_  db  fnc,fc,fn,0     ;carry in
2810
fLSR_
2811
fROR_   db  fc,0,fc,fz      ;no carry in
2812
fRORc_  db  fnc,fn,fnc,fn   ;carry in
2813
;increments (decrements)
2814
rINC_   db  $7f,$80,$ff,0,1 ;expected result for INC/DEC
2815
fINC_   db  0,fn,fn,fz,0    ;expected flags for INC/DEC
2816
;logical memory operand
2817
absOR_  db  0,$1f,$71,$80   ;test pattern for OR
2818
absAN_  db  $0f,$ff,$7f,$80 ;test pattern for AND
2819
absEO_  db  $ff,$0f,$8f,$8f ;test pattern for EOR
2820
;logical accu operand
2821
absORa_ db  0,$f1,$1f,0     ;test pattern for OR
2822
absANa_ db  $f0,$ff,$ff,$ff ;test pattern for AND
2823
absEOa_ db  $ff,$f0,$f0,$0f ;test pattern for EOR
2824
;logical results
2825
absrlo_ db  0,$ff,$7f,$80
2826
absflo_ db  fz,fn,0,fn
2827
data_end
2828
    if (data_end - data_init) != (data_bss_end - data_bss)
2829
        ;force assembler error if size is different
2830
        ERROR ERROR ERROR   ;mismatch between bss and data
2831
    endif
2832
 
2833
vec_init
2834
        dw  nmi_trap
2835
;        dw  res_trap
2836
        dw  start
2837
        dw  irq_trap
2838
vec_bss equ $fffa
2839
    endif                   ;end of RAM init data
2840
 
2841
; code at end of image due to the need to add blank space as required
2842
    if ($ff & (ji_ret - * - 2)) < ($ff & (jxi_ret - * - 2))
2843
; JMP (abs) when $xxff and $xx00 are from same page
2844
        ds  lo(ji_ret - * - 2)
2845
        nop
2846
        nop
2847
ji_px   nop             ;low address byte matched with ji_ret
2848
        nop
2849
        trap            ;jmp indirect page cross bug
2850
 
2851
; JMP (abs,x) when $xxff and $xx00 are from same page
2852
        ds  lo(jxi_ret - * - 2)
2853
        nop
2854
        nop
2855
jxi_px  nop             ;low address byte matched with jxi_ret
2856
        nop
2857
        trap            ;jmp indexed indirect page cross bug
2858
    else
2859
; JMP (abs,x) when $xxff and $xx00 are from same page
2860
        ds  lo(jxi_ret - * - 2)
2861
        nop
2862
        nop
2863
jxi_px  nop             ;low address byte matched with jxi_ret
2864
        nop
2865
        trap            ;jmp indexed indirect page cross bug
2866
 
2867
; JMP (abs) when $xxff and $xx00 are from same page
2868
        ds  lo(ji_ret - * - 2)
2869
        nop
2870
        nop
2871
ji_px   nop             ;low address byte matched with ji_ret
2872
        nop
2873
        trap            ;jmp indirect page cross bug
2874
    endif
2875
 
2876
    if (load_data_direct = 1) & (ROM_vectors = 1)
2877
        org $fffa       ;vectors
2878
        dw  nmi_trap
2879
;        dw  res_trap
2880
        dw  start
2881
        dw  irq_trap
2882
    endif
2883
 
2884
        end start

powered by: WebSVN 2.1.0

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