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

Subversion Repositories cpu6502_true_cycle

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 fpga_is_fu
;
2
; 6 5 0 2   I N T E R R U P T   T E S T
3
;
4
; Copyright (C) 2013  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 IRQ and NMI of a 6502 emulator. It requires
21
; an internal or external feedback register to the IRQ & NMI inputs
22
;
23
; version 15-aug-2014
24
; contact info at http://2m5.de or email K@2m5.de
25
;
26
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
27
; command line switches: -l -m -s2 -w -h0
28
;                         |  |  |   |  no page headers in listing
29
;                         |  |  |   wide listing (133 char/col)
30
;                         |  |  write intel hex file instead of binary
31
;                         |  expand macros in listing
32
;                         generate pass2 listing
33
;
34
; No IO - should be run from a monitor with access to registers.
35
; To run load intel hex image with a load command, than alter PC to 400 hex and
36
; enter a go command.
37
; Loop on program counter determines error or successful completion of test.
38
; Check listing for relevant traps (jump/branch *).
39
;
40
; Debugging hints:
41
;     Most of the code is written sequentially. if you hit a trap, check the
42
;   immediately preceeding code for the instruction to be tested. Results are
43
;   tested first, flags are checked second by pushing them onto the stack and
44
;   pulling them to the accumulator after the result was checked. The "real"
45
;   flags are no longer valid for the tested instruction at this time!
46
;     If the tested instruction was indexed, the relevant index (X or Y) must
47
;   also be checked. Opposed to the flags, X and Y registers are still valid.
48
;
49
; versions:
50
;   19-jul-2013  1st version distributed for testing
51
;   16-aug-2013  added error report to standard output option
52
;   15-aug-2014  added filter to feedback (bit 7 will cause diag stop in emu)
53
 
54
 
55
; C O N F I G U R A T I O N
56
;
57
;ROM_vectors MUST be writable & the I_flag MUST be alterable
58
 
59
;load_data_direct (0=move from code segment, 1=load directly)
60
;loading directly is preferred but may not be supported by your platform
61
;0 produces only consecutive object code, 1 is not suitable for a binary image
62
load_data_direct = 1
63
 
64
;NMI & IRQ are tested with a feedback register
65
;emulators diag register - set i_drive = 0 for a latch (74HC573)
66
I_port      = $bffc     ;feedback port address
67
I_ddr       = 0         ;feedback DDR address, 0 = no DDR
68
I_drive     = 1         ;0 = totem pole, 1 = open collector
69
IRQ_bit     = 0         ;bit number of feedback to IRQ
70
NMI_bit     = 1         ;bit number of feedback to NMI, -1 if not available
71
I_filter    = $7f       ;filtering bit 7 = diag stop
72
 
73
;typical IO chip port B - set i_drive = 0 to avoid pullup resistors
74
;I_port      = $bfb2     ;feedback port address
75
;I_ddr       = $bfb3     ;feedback DDR address, 0 = no DDR
76
;I_drive     = 1         ;0 = totem pole, 1 = open collector
77
;IRQ_bit     = 0         ;bit number of feedback to IRQ
78
;NMI_bit     = 1         ;bit number of feedback to NMI, -1 if not available
79
;I_filter    = $ff       ;no bits filtered
80
 
81
;decimal mode flag during IRQ, NMI & BRK
82
;D_clear     = 0         ;0 = not cleared (NMOS), 1 = cleared (CMOS)
83
D_clear     = 1         ;0 = not cleared (NMOS), 1 = cleared (CMOS)
84
 
85
;configure memory - try to stay away from memory used by the system
86
;zero_page memory start address, 6 consecutive Bytes required
87
zero_page = $a
88
 
89
;data_segment memory start address, 4 consecutive Bytes required
90
data_segment = $200
91
 
92
;code_segment memory start address
93
code_segment = $400
94
 
95
;report errors through I/O channel (0=use standard self trap loops, 1=include
96
;report.i65 as I/O channel)
97
report = 0
98
 
99
        noopt       ;do not take shortcuts
100
 
101
;macros for error & success traps to allow user modification
102
;example:
103
;trap    macro
104
;        jsr my_error_handler
105
;        endm
106
;trap_eq macro
107
;        bne skip\?
108
;        trap           ;failed equal (zero)
109
;skip\?
110
;        endm
111
;
112
; my_error_handler should pop the calling address from the stack and report it.
113
; putting larger portions of code (more than 3 bytes) inside the trap macro
114
; may lead to branch range problems for some tests.
115
    if report = 0
116
trap    macro
117
        jmp *           ;failed anyway
118
        endm
119
trap_eq macro
120
        beq *           ;failed equal (zero)
121
        endm
122
trap_ne macro
123
        bne *           ;failed not equal (non zero)
124
        endm
125
; please observe that during the test the stack gets invalidated
126
; therefore a RTS inside the success macro is not possible
127
success macro
128
        jmp *           ;test passed, no errors
129
        endm
130
    endif
131
    if report = 1
132
trap    macro
133
        jsr report_error
134
        endm
135
trap_eq macro
136
        bne skip\?
137
        trap           ;failed equal (zero)
138
skip\?
139
        endm
140
trap_ne macro
141
        beq skip\?
142
        trap            ;failed not equal (non zero)
143
skip\?
144
        endm
145
; please observe that during the test the stack gets invalidated
146
; therefore a RTS inside the success macro is not possible
147
success macro
148
        jsr report_success
149
        endm
150
    endif
151
 
152
 
153
carry   equ %00000001   ;flag bits in status
154
zero    equ %00000010
155
intdis  equ %00000100
156
decmode equ %00001000
157
break   equ %00010000
158
reserv  equ %00100000
159
overfl  equ %01000000
160
minus   equ %10000000
161
 
162
fc      equ carry
163
fz      equ zero
164
fzc     equ carry+zero
165
fv      equ overfl
166
fvz     equ overfl+zero
167
fn      equ minus
168
fnc     equ minus+carry
169
fnz     equ minus+zero
170
fnzc    equ minus+zero+carry
171
fnv     equ minus+overfl
172
 
173
fao     equ break+reserv    ;bits always on after PHP, BRK
174
fai     equ fao+intdis      ;+ forced interrupt disable
175
m8      equ $ff             ;8 bit mask
176
m8i     equ $ff&~intdis     ;8 bit mask - interrupt disable
177
 
178
;macros to set status
179
push_stat   macro       ;setting flags in the processor status register
180
            lda #\1
181
            pha         ;use stack to load status
182
            endm
183
 
184
set_stat    macro       ;setting flags in the processor status register
185
            lda #\1
186
            pha         ;use stack to load status
187
            plp
188
            endm
189
 
190
    if load_data_direct = 1
191
        data
192
    else
193
        bss                 ;uninitialized segment, copy of data at end of code!
194
    endif
195
        org zero_page
196
;BRK, IRQ, NMI test interrupt save
197
zpt
198
irq_a   ds  1               ;a register
199
irq_x   ds  1               ;x register
200
irq_f   ds  1               ;flags
201
nmi_a   ds  1               ;a register
202
nmi_x   ds  1               ;x register
203
nmi_f   ds  1               ;flags
204
zp_bss
205
 
206
;fixed stack locations
207
lst_f   equ $1fe            ;last flags before interrupt
208
lst_a   equ $1ff            ;last accumulator before interrupt
209
 
210
        org data_segment
211
;concurrent NMI, IRQ & BRK test result
212
nmi_count   ds  1           ;lowest number handled first, $ff = never
213
irq_count   ds  1           ;separation-1 = instructions between interrupts
214
brk_count   ds  1
215
;expected interrupt mask
216
I_src       ds  1           ;bit: 0=BRK, 1=IRQ, 2=NMI
217
data_bss
218
 
219
        code
220
        org code_segment
221
start   cld
222
        lda #0           ;clear expected interrupts for 2nd run
223
        sta I_src
224
        ldx #$ff
225
        txs
226
 
227
;initialize I/O for report channel
228
    if report = 1
229
        jsr report_init
230
    endif
231
 
232
; load system vectors
233
    if load_data_direct != 1
234
        ldx #5
235
ld_vect lda vec_init,x
236
        sta vec_bss,x
237
        dex
238
        bpl ld_vect
239
    endif
240
 
241
; IRQ & NMI test - requires a feedback register
242
    if I_drive > 1
243
        ERROR           ;invalid interrupt drive!
244
    endif
245
  if NMI_bit < 0
246
    if I_drive = 0      ;totem pole (push/pull, 0 -> I_port to force interrupt)
247
I_set   macro  ibit     ;ibit = interrupt bit
248
        lda I_port      ;turn on interrupt by bit
249
        and #I_filter-(1<<\1)
250
        plp             ;set flags
251
        pha             ;save to verify
252
        php
253
        sta I_port      ;interrupt next instruction plus outbound delay
254
        endm
255
I_clr   macro  ibit     ;ibit = interrupt bit
256
        lda I_port      ;turn off interrupt by bit
257
        and #I_filter
258
        ora #(1<
259
        sta I_port
260
        endm
261
        I_clr   IRQ_bit ;turn off IRQ
262
      if I_ddr != 0     ;with DDR
263
        lda I_ddr       ;set DDR for IRQ to enabled
264
        and #I_filter
265
        ora #(1<
266
        sta I_ddr
267
      endif
268
    else                ;open collector, 0 -> I_DDR or I_port to force interrupt
269
      if I_ddr != 0     ;with DDR
270
I_set   macro  ibit     ;ibit = interrupt bit
271
        lda I_ddr       ;turn on interrupt by bit
272
        and #I_filter
273
        ora #(1<<\1)
274
        plp             ;set flags
275
        pha             ;save to verify
276
        php
277
        sta I_ddr       ;interrupt next instruction plus outbound delay
278
        endm
279
I_clr   macro  ibit     ;ibit = interrupt bit
280
        lda I_ddr       ;turn off interrupt by bit
281
        and #I_filter-(1<
282
        sta I_ddr
283
        endm
284
        I_clr   IRQ_bit ;turn off IRQ
285
        lda I_port      ;precharge IRQ
286
        and #I_filter-(1<
287
        sta I_port
288
      else              ;no DDR
289
I_set   macro  ibit     ;ibit = interrupt bit
290
        lda I_port      ;turn on interrupt by bit
291
        and #I_filter
292
        ora #(1<<\1)
293
        plp             ;set flags
294
        pha             ;save to verify
295
        php
296
        sta I_port      ;interrupt next instruction plus outbound delay
297
        endm
298
I_clr   macro  ibit     ;ibit = interrupt bit
299
        lda I_port      ;turn off interrupt by bit
300
        and #I_filter-(1<
301
        sta I_port
302
        endm
303
        I_clr   IRQ_bit ;turn off IRQ
304
      endif
305
    endif
306
  else
307
    if I_drive = 0      ;totem pole (push/pull, 0 -> I_port to force interrupt)
308
I_set   macro  ibit     ;ibit = interrupt bit
309
        lda I_port      ;turn on interrupt by bit
310
        if ibit > 7     ;set both NMI & IRQ
311
          and #I_filter-(1<
312
        else
313
          and #I_filter-(1<<\1)
314
        endif
315
        plp             ;set flags
316
        pha             ;save to verify
317
        php
318
        sta I_port      ;interrupt next instruction plus outbound delay
319
        endm
320
I_clr   macro  ibit     ;ibit = interrupt bit
321
        lda I_port      ;turn off interrupt by bit
322
        and #I_filter
323
        ora #(1<
324
        sta I_port
325
        endm
326
        I_clr   IRQ_bit ;turn off IRQ & NMI
327
        I_clr   NMI_bit
328
      if I_ddr != 0     ;with DDR
329
        lda I_ddr       ;set DDR for IRQ & NMI to enabled
330
        and #I_filter
331
        ora #(1<
332
        sta I_ddr
333
      endif
334
    else                ;open collector, 0 -> I_DDR or I_port to force interrupt
335
      if I_ddr != 0     ;with DDR
336
I_set   macro  ibit     ;ibit = interrupt bit
337
        lda I_ddr       ;turn on interrupt by bit
338
        and #I_filter
339
        if ibit > 7     ;set both NMI & IRQ
340
          ora #(1<
341
        else
342
          ora #(1<<\1)
343
        endif
344
        plp             ;set flags
345
        pha             ;save to verify
346
        php
347
        sta I_ddr       ;interrupt next instruction plus outbound delay
348
        endm
349
I_clr   macro  ibit     ;ibit = interrupt bit
350
        lda I_ddr       ;turn off interrupt by bit
351
        and #I_filter-(1<
352
        sta I_ddr
353
        endm
354
        I_clr   IRQ_bit ;turn off IRQ & NMI
355
        I_clr   NMI_bit
356
        lda I_port      ;precharge IRQ & NMI
357
        and #I_filter-(1<
358
        sta I_port
359
      else              ;no DDR
360
I_set   macro  ibit     ;ibit = interrupt bit
361
        lda I_port      ;turn on interrupt by bit
362
        and #I_filter
363
        if ibit > 7     ;set both NMI & IRQ
364
          ora #(1<
365
        else
366
          ora #(1<<\1)
367
        endif
368
        plp             ;set flags
369
        pha             ;save to verify
370
        php
371
        sta I_port      ;interrupt next instruction plus outbound delay
372
        endm
373
I_clr   macro  ibit     ;ibit = interrupt bit
374
        lda I_port      ;turn off interrupt by bit
375
        and #I_filter-(1<
376
        sta I_port
377
        endm
378
        I_clr   IRQ_bit ;turn off IRQ & NMI
379
        I_clr   NMI_bit
380
      endif
381
    endif
382
  endif
383
 
384
; IRQ integrity test
385
; test for clear flags seen in IRQ vector
386
        lda #2          ;set expected interrupt source IRQ
387
        sta I_src
388
        push_stat 0
389
        I_set IRQ_bit
390
        nop             ;allow 6 cycles for interrupt to trip
391
        nop
392
        nop
393
        lda I_src
394
        trap_ne         ;IRQ timeout
395
        tsx
396
        cpx #$ff-2      ;original accu & flags remain on stack
397
        trap_ne         ;returned SP
398
        lda irq_f       ;flags seen in IRQ vector
399
      if D_clear = 1
400
        and #decmode
401
        trap_ne         ;D-flag not cleared
402
        lda irq_f
403
        eor lst_f       ;turn off unchanged bits
404
        and #m8-fai-decmode ;mask untested other flags
405
        trap_ne         ;other flags (N,V,Z,C) changed
406
      else
407
        eor lst_f       ;turn off unchanged bits
408
        and #m8-fai     ;mask untested other flags
409
        trap_ne         ;other flags (N,V,Z,C,D) changed
410
      endif
411
        ldx #$ff        ;reset stack pointer
412
        txs
413
; test all other registers
414
        ldx #'I'
415
        ldy #'R'
416
        lda #2          ;set expected interrupt source IRQ
417
        sta I_src
418
        push_stat 0
419
        I_set IRQ_bit
420
        dey             ;Y count will fail, if instructions are skipped
421
        dey
422
        dey
423
        dey
424
        php             ;check processor status later
425
        cpx #('I'+1)    ;returned registers OK?
426
        trap_ne         ;returned X
427
        cpy #('R'-7)
428
        trap_ne         ;returned Y
429
        cmp #'Q'
430
        trap_ne         ;returned A
431
        tsx
432
        cpx #$ff-3
433
        trap_ne         ;returned SP
434
        pla             ;flags
435
        eor lst_f
436
        and #$ff-fnz    ;ignore flags changed by dey
437
        trap_ne         ;returned flags
438
        lda irq_a       ;accu seen in IRQ vector
439
        cmp lst_a
440
        trap_ne         ;IRQ A received
441
        ldx #$ff        ;reset stack pointer
442
        txs
443
; repeat with reversed registers
444
        ldx #$ff-'I'
445
        ldy #$ff-'R'
446
        lda #2          ;set expected interrupt source IRQ
447
        sta I_src
448
        push_stat $ff-intdis
449
        I_set IRQ_bit
450
        dey             ;Y count will fail, if instructions are skipped
451
        dey
452
        dey
453
        dey
454
        php             ;check processor status later
455
        cpx #($ff-'I'+1)    ;returned registers OK?
456
        trap_ne         ;returned X
457
        cpy #($ff-'R'-7)
458
        trap_ne         ;returned Y
459
        cmp #'Q'
460
        trap_ne         ;returned A
461
        tsx
462
        cpx #$ff-3
463
        trap_ne         ;returned SP
464
        pla             ;flags
465
        eor lst_f
466
        and #$ff-fnz    ;ignore flags changed by dey
467
        trap_ne         ;returned flags
468
        lda irq_a       ;accu seen in IRQ vector
469
        cmp lst_a
470
        trap_ne         ;IRQ A received
471
        ldx #$ff        ;reset stack pointer
472
        txs
473
; retest for set flags seen in IRQ vector
474
        lda #2          ;set expected interrupt source IRQ
475
        sta I_src
476
        push_stat $ff-intdis
477
        I_set IRQ_bit
478
        nop             ;allow 6 cycles for interrupt to trip
479
        nop
480
        nop
481
        lda I_src
482
        trap_ne         ;IRQ timeout
483
        tsx
484
        cpx #$ff-2      ;original accu & flags remain on stack
485
        trap_ne         ;returned SP
486
        lda irq_f       ;flags seen in IRQ vector
487
      if D_clear = 1
488
        and #decmode
489
        trap_ne         ;D-flag not cleared
490
        lda irq_f
491
        eor lst_f       ;turn off unchanged bits
492
        and #m8-fai-decmode ;mask untested other flags
493
        trap_ne         ;other flags (N,V,Z,C) changed
494
      else
495
        eor lst_f       ;turn off unchanged bits
496
        and #m8-fai     ;mask untested other flags
497
        trap_ne         ;other flags (N,V,Z,C,D) changed
498
      endif
499
        ldx #$ff        ;reset stack pointer
500
        txs
501
 
502
; BRK integrity test
503
; test for clear flags seen in IRQ vector
504
        lda #1          ;set expected interrupt source BRK
505
        sta I_src
506
        set_stat 0
507
        pha             ;save entry registers
508
        php
509
        brk
510
        nop             ;should not be executed
511
        nop             ;allow 6 cycles for interrupt to trip
512
        nop
513
        nop
514
        lda I_src
515
        trap_ne         ;IRQ timeout
516
        tsx
517
        cpx #$ff-2      ;original accu & flags remain on stack
518
        trap_ne         ;returned SP
519
        lda irq_f       ;flags seen in IRQ vector
520
      if D_clear = 1
521
        and #decmode
522
        trap_ne         ;D-flag not cleared
523
        lda irq_f
524
        eor lst_f       ;turn off unchanged bits
525
        and #m8-fai-decmode ;mask untested other flags
526
        trap_ne         ;other flags (N,V,Z,C) changed
527
      else
528
        eor lst_f       ;turn off unchanged bits
529
        and #m8-fai     ;mask untested other flags
530
        trap_ne         ;other flags (N,V,Z,C,D) changed
531
      endif
532
        ldx #$ff        ;reset stack pointer
533
        txs
534
; test all other registers
535
        ldx #'B'
536
        ldy #'R'
537
        lda #1          ;set expected interrupt source BRK
538
        sta I_src
539
        set_stat 0
540
        pha             ;save entry
541
        php
542
        brk
543
        dey             ;should not be executed
544
        dey             ;Y count will fail, if return address is wrong
545
        dey
546
        dey
547
        dey
548
        php             ;check processor status later
549
        cpx #('B'+1)    ;returned registers OK?
550
        trap_ne         ;returned X
551
        cpy #('R'-7)
552
        trap_ne         ;returned Y
553
        cmp #'K'
554
        trap_ne         ;returned A
555
        tsx
556
        cpx #$ff-3
557
        trap_ne         ;returned SP
558
        pla             ;flags
559
        eor lst_f
560
        and #$ff-fnz    ;ignore flags changed by dey
561
        trap_ne         ;returned flags
562
        lda irq_a       ;accu seen in IRQ vector
563
        cmp lst_a
564
        trap_ne         ;IRQ A received
565
        ldx #$ff        ;reset stack pointer
566
        txs
567
; repeat with reversed registers
568
        ldx #$ff-'B'
569
        ldy #$ff-'R'
570
        lda #1          ;set expected interrupt source BRK
571
        sta I_src
572
        set_stat $ff
573
        pha             ;save entry registers
574
        php
575
        brk
576
        dey             ;should not be executed
577
        dey             ;Y count will fail, if return address is wrong
578
        dey
579
        dey
580
        dey
581
        php             ;check processor status later
582
        cpx #($ff-'B'+1)    ;returned registers OK?
583
        trap_ne         ;returned X
584
        cpy #($ff-'R'-7)
585
        trap_ne         ;returned Y
586
        cmp #'K'
587
        trap_ne         ;returned A
588
        tsx
589
        cpx #$ff-3
590
        trap_ne         ;returned SP
591
        pla             ;flags
592
        eor lst_f
593
        and #$ff-fnz    ;ignore flags changed by dey
594
        trap_ne         ;returned flags
595
        lda irq_a       ;accu seen in IRQ vector
596
        cmp lst_a
597
        trap_ne         ;IRQ A received
598
        ldx #$ff        ;reset stack pointer
599
        txs
600
; retest for set flags seen in IRQ vector
601
        lda #1          ;set expected interrupt source BRK
602
        sta I_src
603
        set_stat $ff
604
        pha             ;save entry registers
605
        php
606
        brk
607
        nop             ;should not be executed
608
        nop             ;allow 6 cycles for interrupt to trip
609
        nop
610
        nop
611
        lda I_src
612
        trap_ne         ;IRQ timeout
613
        tsx
614
        cpx #$ff-2      ;original accu & flags remain on stack
615
        trap_ne         ;returned SP
616
        lda irq_f       ;flags seen in IRQ vector
617
      if D_clear = 1
618
        and #decmode
619
        trap_ne         ;D-flag not cleared
620
        lda irq_f
621
        eor lst_f       ;turn off unchanged bits
622
        and #m8-fai-decmode ;mask untested other flags
623
        trap_ne         ;other flags (N,V,Z,C) changed
624
      else
625
        eor lst_f       ;turn off unchanged bits
626
        and #m8-fai     ;mask untested other flags
627
        trap_ne         ;other flags (N,V,Z,C,D) changed
628
      endif
629
        ldx #$ff        ;reset stack pointer
630
        txs
631
 
632
    if NMI_bit < 0
633
; test IRQ with interrupts disabled
634
        ldx #0
635
        lda #0
636
        sta I_src
637
        push_stat intdis
638
        I_set IRQ_bit   ;IRQ pending
639
        inx
640
        inx
641
        inx
642
        ldx #0
643
        lda #2          ;now re-enable IRQ
644
        sta I_src
645
        cli
646
        inx
647
        inx
648
        inx
649
        lda I_src       ;test IRQ done?
650
        trap_ne
651
        ldx #$ff        ;purge stack
652
        txs
653
 
654
        ldx #0          ;now overlap IRQ & BRK
655
        lda #3
656
        sta I_src
657
        lda #$ff        ;measure timing
658
        sta nmi_count
659
        sta irq_count
660
        sta brk_count
661
        push_stat 0
662
        I_set IRQ_bit   ;trigger IRQ
663
    else
664
; NMI integrity test
665
; test for clear flags seen in NMI vector
666
        lda #4          ;set expected interrupt source NMI
667
        sta I_src
668
        push_stat 0
669
        I_set NMI_bit
670
        nop             ;allow 6 cycles for interrupt to trip
671
        nop
672
        nop
673
        lda I_src
674
        trap_ne         ;NMI timeout
675
        tsx
676
        cpx #$ff-2      ;original accu & flags remain on stack
677
        trap_ne         ;returned SP
678
        lda nmi_f       ;flags seen in NMI vector
679
      if D_clear = 1
680
        and #decmode
681
        trap_ne         ;D-flag not cleared
682
        lda nmi_f
683
        eor lst_f       ;turn off unchanged bits
684
        and #m8-fai-decmode ;mask untested other flags
685
        trap_ne         ;other flags (N,V,Z,C) changed
686
      else
687
        eor lst_f       ;turn off unchanged bits
688
        and #m8-fai     ;mask untested other flags
689
        trap_ne         ;other flags (N,V,Z,C,D) changed
690
      endif
691
        ldx #$ff        ;reset stack pointer
692
        txs
693
; test all other registers
694
        ldx #'N'
695
        ldy #'M'
696
        lda #4          ;set expected interrupt source NMI
697
        sta I_src
698
        push_stat 0
699
        I_set NMI_bit
700
        dey             ;Y count will fail, if instructions are skipped
701
        dey
702
        dey
703
        dey
704
        php             ;check processor status later
705
        cpx #('N'+1)    ;returned registers OK?
706
        trap_ne         ;returned X
707
        cpy #('M'-7)
708
        trap_ne         ;returned Y
709
        cmp #'I'
710
        trap_ne         ;returned A
711
        tsx
712
        cpx #$ff-3
713
        trap_ne         ;returned SP
714
        pla             ;flags
715
        eor lst_f
716
        and #$ff-fnz    ;ignore flags changed by dey
717
        trap_ne         ;returned flags
718
        lda nmi_a       ;accu seen in NMI vector
719
        cmp lst_a
720
        trap_ne         ;NMI A received
721
        ldx #$ff        ;reset stack pointer
722
        txs
723
; repeat with reversed registers
724
        ldx #$ff-'N'
725
        ldy #$ff-'M'
726
        lda #4          ;set expected interrupt source NMI
727
        sta I_src
728
        push_stat $ff-intdis
729
        I_set NMI_bit
730
        dey             ;Y count will fail, if instructions are skipped
731
        dey
732
        dey
733
        dey
734
        php             ;check processor status later
735
        cpx #($ff-'N'+1)    ;returned registers OK?
736
        trap_ne         ;returned X
737
        cpy #($ff-'M'-7)
738
        trap_ne         ;returned Y
739
        cmp #'I'
740
        trap_ne         ;returned A
741
        tsx
742
        cpx #$ff-3
743
        trap_ne         ;returned SP
744
        pla             ;flags
745
        eor lst_f
746
        and #$ff-fnz    ;ignore flags changed by dey
747
        trap_ne         ;returned flags
748
        lda nmi_a       ;accu seen in NMI vector
749
        cmp lst_a
750
        trap_ne         ;NMI A received
751
        ldx #$ff        ;reset stack pointer
752
        txs
753
; retest for set flags seen in NMI vector
754
        lda #4          ;set expected interrupt source NMI
755
        sta I_src
756
        push_stat $ff-intdis
757
        I_set NMI_bit
758
        nop             ;allow 6 cycles for interrupt to trip
759
        nop
760
        nop
761
        lda I_src
762
        trap_ne         ;NMI timeout
763
        tsx
764
        cpx #$ff-2      ;original accu & flags remain on stack
765
        trap_ne         ;returned SP
766
        lda nmi_f       ;flags seen in NMI vector
767
      if D_clear = 1
768
        and #decmode
769
        trap_ne         ;D-flag not cleared
770
        lda nmi_f
771
        eor lst_f       ;turn off unchanged bits
772
        and #m8-fai-decmode ;mask untested other flags
773
        trap_ne         ;other flags (N,V,Z,C) changed
774
      else
775
        eor lst_f       ;turn off unchanged bits
776
        and #m8-fai     ;mask untested other flags
777
        trap_ne         ;other flags (N,V,Z,C,D) changed
778
      endif
779
        ldx #$ff        ;reset stack pointer
780
        txs
781
 
782
; test IRQ & NMI with interrupts disabled
783
        ldx #0
784
        lda #4          ;set expected interrupt NMI only
785
        sta I_src
786
        push_stat intdis
787
        I_set 8         ;both interrupts pending
788
        inx
789
        inx
790
        inx
791
        lda I_src       ;test NMI done?
792
        trap_ne
793
        ldx #0
794
        lda #2          ;now re-enable IRQ
795
        sta I_src
796
        cli
797
        inx
798
        inx
799
        inx
800
        lda I_src       ;test IRQ done?
801
        trap_ne
802
        ldx #$ff        ;purge stack
803
        txs
804
 
805
;test overlapping NMI, IRQ & BRK
806
        ldx #0
807
        lda #7
808
        sta I_src
809
        lda #$ff        ;measure timing
810
        sta nmi_count
811
        sta irq_count
812
        sta brk_count
813
        push_stat 0
814
        I_set 8         ;trigger NMI + IRQ
815
    endif
816
        brk
817
        inx
818
        inx
819
        inx
820
        inx
821
        inx
822
        inx
823
        inx
824
        inx
825
        lda I_src       ;test all done?
826
;may fail due to a bug on a real NMOS 6502 - NMI could mask BRK
827
        trap_ne         ;lost an interrupt
828
 
829
; S U C C E S S ************************************************
830
; -------------
831
        success         ;if you get here everything went well
832
; -------------
833
; S U C C E S S ************************************************
834
; check data_segment +0 to +2 for sequence of concurrent interrupts
835
; e.g. 0x200 = NMI, 0x201 = IRQ, 0x202 = BRK, lower values = earlier
836
        jmp start       ;run again
837
 
838
; manual tests for the WAI opcode of the 65c02
839
 
840
wai     macro
841
        db  $cb         ;WAI opcode
842
        endm
843
 
844
; requires single step operation, report = 0
845
;   set PC to the 1st instruction of the test
846
;   step to the WAI opcode, then manually tie the IRQ input low
847
;   continue to step until you see the PC advance, then remove IRQ
848
;   allow the routine to complete.
849
 
850
; WAI with interrupts disabled
851
        ldx #$ff
852
        txs
853
        ldy #3
854
        lda #0          ;IRQ not expected
855
        sta I_src
856
        set_stat intdis
857
        wai
858
        dey
859
        dey
860
        dey
861
        trap_ne         ;skipped opcodes!
862
 
863
        success
864
 
865
; WAI with interrupts enabled
866
        ldx #$ff
867
        txs
868
        ldy #7
869
        lda #2          ;IRQ expected
870
        sta I_src
871
        set_stat 0
872
        wai
873
        dey
874
        dey
875
        dey
876
        lda I_src
877
        trap_ne         ;IRQ vector not called
878
        dey
879
        trap_ne         ;skipped opcodes!
880
 
881
        success
882
 
883
; manual test for the STP opcode of the 65c02
884
 
885
stp     macro
886
        db  $db         ;STP opcode
887
        endm
888
 
889
; set PC to the 1st instruction of the test, then run
890
        nop
891
        nop
892
        stp             ;expected end of operation
893
        nop
894
        nop
895
        trap            ;overran STP
896
 
897
;end of manual tests
898
 
899
;---------------------------------------------------------------------------
900
;trap in case of unexpected IRQ, NMI, BRK, RESET - IRQ, NMI, BRK test target
901
        dey
902
        dey
903
nmi_trap
904
    if NMI_bit < 0
905
        dey
906
        dey
907
        dey
908
        trap            ;unexpected NMI
909
    else
910
        php             ;either SP or Y count will fail, if we do not hit
911
        dey
912
        dey
913
        dey
914
        sta nmi_a       ;save regsters during NMI
915
        stx nmi_x
916
        pla
917
        pha
918
        sta nmi_f
919
        lda I_src       ;NMI expected?
920
        and #4
921
        trap_eq         ;unexpexted NMI - check stack for conditions
922
        pla             ;test I-flag was set
923
        pha
924
        and #intdis
925
        trap_eq         ;I-flag not set
926
        pla             ;return with other flags reversed
927
        eor #m8-fai-decmode
928
        pha
929
        tsx
930
        lda $102,x     ;test break on stack
931
        and #break
932
        trap_ne         ;unexpected B-flag! - this may fail on a real 6502
933
                        ;due to a hardware bug on concurrent BRK & NMI
934
        lda I_src       ;mark expected NMI has occured
935
        and #$ff-4
936
        sta I_src
937
        I_clr   NMI_bit
938
        ldx nmi_x
939
        inx
940
        stx nmi_count
941
        lda #'I'        ;mark (NM)I
942
        plp             ;should be reversed by rti
943
        rti
944
    endif
945
 
946
res_trap
947
        trap            ;unexpected RESET
948
 
949
        dey
950
        dey
951
irq_trap                ;BRK & IRQ test
952
        php             ;either SP or Y count will fail, if we do not hit
953
        dey
954
        dey
955
        dey
956
        sta irq_a       ;save registers during IRQ/BRK
957
        stx irq_x
958
        pla
959
        pha
960
        sta irq_f
961
        lda I_src       ;IRQ expected?
962
        and #3
963
        trap_eq         ;unexpexted IRQ/BRK - check stack for conditions
964
        pla             ;test I-flag was set
965
        pha
966
        and #intdis
967
        trap_eq         ;I-flag not set
968
        pla             ;return with other flags reversed
969
        eor #m8-fai-decmode
970
        pha
971
        tsx
972
        lda $102,x      ;test break on stack
973
        and #break
974
        bne brk_trap
975
 
976
        lda I_src       ;IRQ expected?
977
        and #2
978
        trap_eq         ;unexpexted IRQ - check stack for conditions
979
        lda I_src       ;mark expected IRQ has occured
980
        and #$ff-2
981
        sta I_src
982
        I_clr   IRQ_bit
983
        ldx irq_x
984
        inx
985
        stx irq_count
986
        lda #'Q'        ;mark (IR)Q
987
        plp             ;should be reversed by rti
988
        rti
989
 
990
brk_trap
991
        lda I_src       ;break expected?
992
        and #1
993
        trap_eq         ;unexpected BRK - check stack for conditions
994
        lda I_src       ;mark expected BRK has occured
995
        and #$ff-1
996
        sta I_src
997
        ldx irq_x
998
        inx
999
        stx brk_count
1000
        lda irq_a
1001
        lda #'K'        ;mark (BR)K
1002
        plp             ;should be reversed by rti
1003
        rti
1004
 
1005
    if report = 1
1006
rep_int = 1
1007
        include "report.i65"
1008
    endif
1009
 
1010
 
1011
;system vectors
1012
    if (load_data_direct = 1)
1013
        org $fffa
1014
        dw  nmi_trap
1015
;        dw  res_trap
1016
        dw  start
1017
        dw  irq_trap
1018
    else
1019
vec_init
1020
vec_bss equ $fffa
1021
        dw  nmi_trap
1022
;        dw  res_trap
1023
        dw  start
1024
        dw  irq_trap
1025
    endif
1026
 
1027
        end start
1028
 
1029
 

powered by: WebSVN 2.1.0

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