mirror of
https://github.com/freewilll/apple2-go.git
synced 2024-12-31 15:31:05 +00:00
1375 lines
72 KiB
Plaintext
1375 lines
72 KiB
Plaintext
|
AS65 Assembler for R6502 [1.42]. Copyright 1994-2007, Frank A. Kingswood Page 1
|
|||
|
---------------------------------------------------- 6502_interrupt_test.a65 -----------------------------------------------------
|
|||
|
|
|||
|
1025 lines read, no errors in pass 1.
|
|||
|
;
|
|||
|
; 6 5 0 2 I N T E R R U P T T E S T
|
|||
|
;
|
|||
|
; Copyright (C) 2013 Klaus Dormann
|
|||
|
;
|
|||
|
; This program is free software: you can redistribute it and/or modify
|
|||
|
; it under the terms of the GNU General Public License as published by
|
|||
|
; the Free Software Foundation, either version 3 of the License, or
|
|||
|
; (at your option) any later version.
|
|||
|
;
|
|||
|
; This program is distributed in the hope that it will be useful,
|
|||
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
|
; GNU General Public License for more details.
|
|||
|
;
|
|||
|
; You should have received a copy of the GNU General Public License
|
|||
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
|
|||
|
|
|||
|
; This program is designed to test IRQ and NMI of a 6502 emulator. It requires
|
|||
|
; an internal or external feedback register to the IRQ & NMI inputs
|
|||
|
;
|
|||
|
; version 15-aug-2014
|
|||
|
; contact info at http://2m5.de or email K@2m5.de
|
|||
|
;
|
|||
|
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
|
|||
|
; command line switches: -l -m -s2 -w -h0
|
|||
|
; | | | | no page headers in listing
|
|||
|
; | | | wide listing (133 char/col)
|
|||
|
; | | write intel hex file instead of binary
|
|||
|
; | expand macros in listing
|
|||
|
; generate pass2 listing
|
|||
|
;
|
|||
|
; No IO - should be run from a monitor with access to registers.
|
|||
|
; To run load intel hex image with a load command, than alter PC to 400 hex and
|
|||
|
; enter a go command.
|
|||
|
; Loop on program counter determines error or successful completion of test.
|
|||
|
; Check listing for relevant traps (jump/branch *).
|
|||
|
;
|
|||
|
; Debugging hints:
|
|||
|
; Most of the code is written sequentially. if you hit a trap, check the
|
|||
|
; immediately preceeding code for the instruction to be tested. Results are
|
|||
|
; tested first, flags are checked second by pushing them onto the stack and
|
|||
|
; pulling them to the accumulator after the result was checked. The "real"
|
|||
|
; flags are no longer valid for the tested instruction at this time!
|
|||
|
; If the tested instruction was indexed, the relevant index (X or Y) must
|
|||
|
; also be checked. Opposed to the flags, X and Y registers are still valid.
|
|||
|
;
|
|||
|
; versions:
|
|||
|
; 19-jul-2013 1st version distributed for testing
|
|||
|
; 16-aug-2013 added error report to standard output option
|
|||
|
; 15-aug-2014 added filter to feedback (bit 7 will cause diag stop in emu)
|
|||
|
|
|||
|
|
|||
|
; C O N F I G U R A T I O N
|
|||
|
;
|
|||
|
;ROM_vectors MUST be writable & the I_flag MUST be alterable
|
|||
|
|
|||
|
;load_data_direct (0=move from code segment, 1=load directly)
|
|||
|
;loading directly is preferred but may not be supported by your platform
|
|||
|
;0 produces only consecutive object code, 1 is not suitable for a binary image
|
|||
|
0001 = load_data_direct = 1
|
|||
|
|
|||
|
;NMI & IRQ are tested with a feedback register
|
|||
|
;emulators diag register - set i_drive = 0 for a latch (74HC573)
|
|||
|
bffc = I_port = $bffc ;feedback port address
|
|||
|
0000 = I_ddr = 0 ;feedback DDR address, 0 = no DDR
|
|||
|
0001 = I_drive = 1 ;0 = totem pole, 1 = open collector
|
|||
|
0000 = IRQ_bit = 0 ;bit number of feedback to IRQ
|
|||
|
0001 = NMI_bit = 1 ;bit number of feedback to NMI, -1 if not available
|
|||
|
007f = I_filter = $7f ;filtering bit 7 = diag stop
|
|||
|
|
|||
|
;typical IO chip port B - set i_drive = 0 to avoid pullup resistors
|
|||
|
;I_port = $bfb2 ;feedback port address
|
|||
|
;I_ddr = $bfb3 ;feedback DDR address, 0 = no DDR
|
|||
|
;I_drive = 1 ;0 = totem pole, 1 = open collector
|
|||
|
;IRQ_bit = 0 ;bit number of feedback to IRQ
|
|||
|
;NMI_bit = 1 ;bit number of feedback to NMI, -1 if not available
|
|||
|
;I_filter = $ff ;no bits filtered
|
|||
|
|
|||
|
;decimal mode flag during IRQ, NMI & BRK
|
|||
|
0000 = D_clear = 0 ;0 = not cleared (NMOS), 1 = cleared (CMOS)
|
|||
|
|
|||
|
;configure memory - try to stay away from memory used by the system
|
|||
|
;zero_page memory start address, 6 consecutive Bytes required
|
|||
|
0000 = zero_page = $0
|
|||
|
|
|||
|
;data_segment memory start address, 4 consecutive Bytes required
|
|||
|
0200 = data_segment = $200
|
|||
|
|
|||
|
;code_segment memory start address
|
|||
|
0800 = code_segment = $800
|
|||
|
|
|||
|
;report errors through I/O channel (0=use standard self trap loops, 1=include
|
|||
|
;report.i65 as I/O channel)
|
|||
|
0000 = report = 0
|
|||
|
|
|||
|
noopt ;do not take shortcuts
|
|||
|
|
|||
|
;macros for error & success traps to allow user modification
|
|||
|
;example:
|
|||
|
;trap macro
|
|||
|
; jsr my_error_handler
|
|||
|
; endm
|
|||
|
;trap_eq macro
|
|||
|
; bne skip\?
|
|||
|
; trap ;failed equal (zero)
|
|||
|
;skip\?
|
|||
|
; endm
|
|||
|
;
|
|||
|
; my_error_handler should pop the calling address from the stack and report it.
|
|||
|
; putting larger portions of code (more than 3 bytes) inside the trap macro
|
|||
|
; may lead to branch range problems for some tests.
|
|||
|
if report = 0
|
|||
|
trap macro
|
|||
|
jmp * ;failed anyway
|
|||
|
endm
|
|||
|
trap_eq macro
|
|||
|
beq * ;failed equal (zero)
|
|||
|
endm
|
|||
|
trap_ne macro
|
|||
|
bne * ;failed not equal (non zero)
|
|||
|
endm
|
|||
|
; please observe that during the test the stack gets invalidated
|
|||
|
; therefore a RTS inside the success macro is not possible
|
|||
|
success macro
|
|||
|
jmp * ;test passed, no errors
|
|||
|
endm
|
|||
|
endif
|
|||
|
if report = 1
|
|||
|
trap macro
|
|||
|
jsr report_error
|
|||
|
endm
|
|||
|
trap_eq macro
|
|||
|
bne skip\?
|
|||
|
trap ;failed equal (zero)
|
|||
|
skip\?
|
|||
|
endm
|
|||
|
trap_ne macro
|
|||
|
beq skip\?
|
|||
|
trap ;failed not equal (non zero)
|
|||
|
skip\?
|
|||
|
endm
|
|||
|
; please observe that during the test the stack gets invalidated
|
|||
|
; therefore a RTS inside the success macro is not possible
|
|||
|
success macro
|
|||
|
jsr report_success
|
|||
|
endm
|
|||
|
endif
|
|||
|
|
|||
|
|
|||
|
0001 = carry equ %00000001 ;flag bits in status
|
|||
|
0002 = zero equ %00000010
|
|||
|
0004 = intdis equ %00000100
|
|||
|
0008 = decmode equ %00001000
|
|||
|
0010 = break equ %00010000
|
|||
|
0020 = reserv equ %00100000
|
|||
|
0040 = overfl equ %01000000
|
|||
|
0080 = minus equ %10000000
|
|||
|
|
|||
|
0001 = fc equ carry
|
|||
|
0002 = fz equ zero
|
|||
|
0003 = fzc equ carry+zero
|
|||
|
0040 = fv equ overfl
|
|||
|
0042 = fvz equ overfl+zero
|
|||
|
0080 = fn equ minus
|
|||
|
0081 = fnc equ minus+carry
|
|||
|
0082 = fnz equ minus+zero
|
|||
|
0083 = fnzc equ minus+zero+carry
|
|||
|
00c0 = fnv equ minus+overfl
|
|||
|
|
|||
|
0030 = fao equ break+reserv ;bits always on after PHP, BRK
|
|||
|
0034 = fai equ fao+intdis ;+ forced interrupt disable
|
|||
|
00ff = m8 equ $ff ;8 bit mask
|
|||
|
00fb = m8i equ $ff&~intdis ;8 bit mask - interrupt disable
|
|||
|
|
|||
|
;macros to set status
|
|||
|
push_stat macro ;setting flags in the processor status register
|
|||
|
lda #\1
|
|||
|
pha ;use stack to load status
|
|||
|
endm
|
|||
|
|
|||
|
set_stat macro ;setting flags in the processor status register
|
|||
|
lda #\1
|
|||
|
pha ;use stack to load status
|
|||
|
plp
|
|||
|
endm
|
|||
|
|
|||
|
if load_data_direct = 1
|
|||
|
data
|
|||
|
else
|
|||
|
bss ;uninitialized segment, copy of data at end of code!
|
|||
|
endif
|
|||
|
0000 = org zero_page
|
|||
|
;BRK, IRQ, NMI test interrupt save
|
|||
|
0000 : zpt
|
|||
|
0000 : 00 irq_a ds 1 ;a register
|
|||
|
0001 : 00 irq_x ds 1 ;x register
|
|||
|
0002 : 00 irq_f ds 1 ;flags
|
|||
|
0003 : 00 nmi_a ds 1 ;a register
|
|||
|
0004 : 00 nmi_x ds 1 ;x register
|
|||
|
0005 : 00 nmi_f ds 1 ;flags
|
|||
|
0006 : zp_bss
|
|||
|
|
|||
|
;fixed stack locations
|
|||
|
01fe = lst_f equ $1fe ;last flags before interrupt
|
|||
|
01ff = lst_a equ $1ff ;last accumulator before interrupt
|
|||
|
|
|||
|
0200 = org data_segment
|
|||
|
;concurrent NMI, IRQ & BRK test result
|
|||
|
0200 : 00 nmi_count ds 1 ;lowest number handled first, $ff = never
|
|||
|
0201 : 00 irq_count ds 1 ;separation-1 = instructions between interrupts
|
|||
|
0202 : 00 brk_count ds 1
|
|||
|
;expected interrupt mask
|
|||
|
0203 : 00 I_src ds 1 ;bit: 0=BRK, 1=IRQ, 2=NMI
|
|||
|
0204 : data_bss
|
|||
|
|
|||
|
code
|
|||
|
0800 = org code_segment
|
|||
|
0800 : d8 start cld
|
|||
|
0801 : a900 lda #0 ;clear expected interrupts for 2nd run
|
|||
|
0803 : 8d0302 sta I_src
|
|||
|
0806 : a2ff ldx #$ff
|
|||
|
0808 : 9a txs
|
|||
|
|
|||
|
;initialize I/O for report channel
|
|||
|
if report = 1
|
|||
|
jsr report_init
|
|||
|
endif
|
|||
|
|
|||
|
; load system vectors
|
|||
|
if load_data_direct != 1
|
|||
|
ldx #5
|
|||
|
ld_vect lda vec_init,x
|
|||
|
sta vec_bss,x
|
|||
|
dex
|
|||
|
bpl ld_vect
|
|||
|
endif
|
|||
|
|
|||
|
; IRQ & NMI test - requires a feedback register
|
|||
|
if I_drive > 1
|
|||
|
ERROR ;invalid interrupt drive!
|
|||
|
endif
|
|||
|
if NMI_bit < 0
|
|||
|
if I_drive = 0 ;totem pole (push/pull, 0 -> I_port to force interrupt)
|
|||
|
I_set macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn on interrupt by bit
|
|||
|
and #I_filter-(1<<\1)
|
|||
|
plp ;set flags
|
|||
|
pha ;save to verify
|
|||
|
php
|
|||
|
sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
endm
|
|||
|
I_clr macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn off interrupt by bit
|
|||
|
and #I_filter
|
|||
|
ora #(1<<ibit)
|
|||
|
sta I_port
|
|||
|
endm
|
|||
|
I_clr IRQ_bit ;turn off IRQ
|
|||
|
if I_ddr != 0 ;with DDR
|
|||
|
lda I_ddr ;set DDR for IRQ to enabled
|
|||
|
and #I_filter
|
|||
|
ora #(1<<IRQ_bit)
|
|||
|
sta I_ddr
|
|||
|
endif
|
|||
|
else ;open collector, 0 -> I_DDR or I_port to force interrupt
|
|||
|
if I_ddr != 0 ;with DDR
|
|||
|
I_set macro ibit ;ibit = interrupt bit
|
|||
|
lda I_ddr ;turn on interrupt by bit
|
|||
|
and #I_filter
|
|||
|
ora #(1<<\1)
|
|||
|
plp ;set flags
|
|||
|
pha ;save to verify
|
|||
|
php
|
|||
|
sta I_ddr ;interrupt next instruction plus outbound delay
|
|||
|
endm
|
|||
|
I_clr macro ibit ;ibit = interrupt bit
|
|||
|
lda I_ddr ;turn off interrupt by bit
|
|||
|
and #I_filter-(1<<ibit)
|
|||
|
sta I_ddr
|
|||
|
endm
|
|||
|
I_clr IRQ_bit ;turn off IRQ
|
|||
|
lda I_port ;precharge IRQ
|
|||
|
and #I_filter-(1<<IRQ_bit)
|
|||
|
sta I_port
|
|||
|
else ;no DDR
|
|||
|
I_set macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn on interrupt by bit
|
|||
|
and #I_filter
|
|||
|
ora #(1<<\1)
|
|||
|
plp ;set flags
|
|||
|
pha ;save to verify
|
|||
|
php
|
|||
|
sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
endm
|
|||
|
I_clr macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn off interrupt by bit
|
|||
|
and #I_filter-(1<<ibit)
|
|||
|
sta I_port
|
|||
|
endm
|
|||
|
I_clr IRQ_bit ;turn off IRQ
|
|||
|
endif
|
|||
|
endif
|
|||
|
else
|
|||
|
if I_drive = 0 ;totem pole (push/pull, 0 -> I_port to force interrupt)
|
|||
|
I_set macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn on interrupt by bit
|
|||
|
if ibit > 7 ;set both NMI & IRQ
|
|||
|
and #I_filter-(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
else
|
|||
|
and #I_filter-(1<<\1)
|
|||
|
endif
|
|||
|
plp ;set flags
|
|||
|
pha ;save to verify
|
|||
|
php
|
|||
|
sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
endm
|
|||
|
I_clr macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn off interrupt by bit
|
|||
|
and #I_filter
|
|||
|
ora #(1<<ibit)
|
|||
|
sta I_port
|
|||
|
endm
|
|||
|
I_clr IRQ_bit ;turn off IRQ & NMI
|
|||
|
I_clr NMI_bit
|
|||
|
if I_ddr != 0 ;with DDR
|
|||
|
lda I_ddr ;set DDR for IRQ & NMI to enabled
|
|||
|
and #I_filter
|
|||
|
ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
sta I_ddr
|
|||
|
endif
|
|||
|
else ;open collector, 0 -> I_DDR or I_port to force interrupt
|
|||
|
if I_ddr != 0 ;with DDR
|
|||
|
I_set macro ibit ;ibit = interrupt bit
|
|||
|
lda I_ddr ;turn on interrupt by bit
|
|||
|
and #I_filter
|
|||
|
if ibit > 7 ;set both NMI & IRQ
|
|||
|
ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
else
|
|||
|
ora #(1<<\1)
|
|||
|
endif
|
|||
|
plp ;set flags
|
|||
|
pha ;save to verify
|
|||
|
php
|
|||
|
sta I_ddr ;interrupt next instruction plus outbound delay
|
|||
|
endm
|
|||
|
I_clr macro ibit ;ibit = interrupt bit
|
|||
|
lda I_ddr ;turn off interrupt by bit
|
|||
|
and #I_filter-(1<<ibit)
|
|||
|
sta I_ddr
|
|||
|
endm
|
|||
|
I_clr IRQ_bit ;turn off IRQ & NMI
|
|||
|
I_clr NMI_bit
|
|||
|
lda I_port ;precharge IRQ & NMI
|
|||
|
and #I_filter-(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
sta I_port
|
|||
|
else ;no DDR
|
|||
|
I_set macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn on interrupt by bit
|
|||
|
and #I_filter
|
|||
|
if ibit > 7 ;set both NMI & IRQ
|
|||
|
ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
else
|
|||
|
ora #(1<<\1)
|
|||
|
endif
|
|||
|
plp ;set flags
|
|||
|
pha ;save to verify
|
|||
|
php
|
|||
|
sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
endm
|
|||
|
I_clr macro ibit ;ibit = interrupt bit
|
|||
|
lda I_port ;turn off interrupt by bit
|
|||
|
and #I_filter-(1<<ibit)
|
|||
|
sta I_port
|
|||
|
endm
|
|||
|
I_clr IRQ_bit ;turn off IRQ & NMI
|
|||
|
0809 : adfcbf > lda I_port ;turn off interrupt by bit
|
|||
|
080c : 297e > and #I_filter-(1<<IRQ_bit )
|
|||
|
080e : 8dfcbf > sta I_port
|
|||
|
|
|||
|
I_clr NMI_bit
|
|||
|
0811 : adfcbf > lda I_port ;turn off interrupt by bit
|
|||
|
0814 : 297d > and #I_filter-(1<<NMI_bit)
|
|||
|
0816 : 8dfcbf > sta I_port
|
|||
|
|
|||
|
endif
|
|||
|
endif
|
|||
|
endif
|
|||
|
|
|||
|
; IRQ integrity test
|
|||
|
; test for clear flags seen in IRQ vector
|
|||
|
0819 : a902 lda #2 ;set expected interrupt source IRQ
|
|||
|
081b : 8d0302 sta I_src
|
|||
|
push_stat 0
|
|||
|
081e : a900 > lda #0
|
|||
|
0820 : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set IRQ_bit
|
|||
|
0821 : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0824 : 297f > and #I_filter
|
|||
|
> if IRQ_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
0826 : 0901 > ora #(1<<IRQ_bit)
|
|||
|
> endif
|
|||
|
0828 : 28 > plp ;set flags
|
|||
|
0829 : 48 > pha ;save to verify
|
|||
|
082a : 08 > php
|
|||
|
082b : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
082e : ea nop ;allow 6 cycles for interrupt to trip
|
|||
|
082f : ea nop
|
|||
|
0830 : ea nop
|
|||
|
0831 : ad0302 lda I_src
|
|||
|
trap_ne ;IRQ timeout
|
|||
|
0834 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0836 : ba tsx
|
|||
|
0837 : e0fd cpx #$ff-2 ;original accu & flags remain on stack
|
|||
|
trap_ne ;returned SP
|
|||
|
0839 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
083b : a502 lda irq_f ;flags seen in IRQ vector
|
|||
|
if D_clear = 1
|
|||
|
and #decmode
|
|||
|
trap_ne ;D-flag not cleared
|
|||
|
lda irq_f
|
|||
|
eor lst_f ;turn off unchanged bits
|
|||
|
and #m8-fai-decmode ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C) changed
|
|||
|
else
|
|||
|
083d : 4dfe01 eor lst_f ;turn off unchanged bits
|
|||
|
0840 : 29cb and #m8-fai ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C,D) changed
|
|||
|
0842 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
endif
|
|||
|
0844 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
0846 : 9a txs
|
|||
|
; test all other registers
|
|||
|
0847 : a249 ldx #'I'
|
|||
|
0849 : a052 ldy #'R'
|
|||
|
084b : a902 lda #2 ;set expected interrupt source IRQ
|
|||
|
084d : 8d0302 sta I_src
|
|||
|
push_stat 0
|
|||
|
0850 : a900 > lda #0
|
|||
|
0852 : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set IRQ_bit
|
|||
|
0853 : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0856 : 297f > and #I_filter
|
|||
|
> if IRQ_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
0858 : 0901 > ora #(1<<IRQ_bit)
|
|||
|
> endif
|
|||
|
085a : 28 > plp ;set flags
|
|||
|
085b : 48 > pha ;save to verify
|
|||
|
085c : 08 > php
|
|||
|
085d : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
0860 : 88 dey ;Y count will fail, if instructions are skipped
|
|||
|
0861 : 88 dey
|
|||
|
0862 : 88 dey
|
|||
|
0863 : 88 dey
|
|||
|
0864 : 08 php ;check processor status later
|
|||
|
0865 : e04a cpx #('I'+1) ;returned registers OK?
|
|||
|
trap_ne ;returned X
|
|||
|
0867 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0869 : c04b cpy #('R'-7)
|
|||
|
trap_ne ;returned Y
|
|||
|
086b : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
086d : c951 cmp #'Q'
|
|||
|
trap_ne ;returned A
|
|||
|
086f : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0871 : ba tsx
|
|||
|
0872 : e0fc cpx #$ff-3
|
|||
|
trap_ne ;returned SP
|
|||
|
0874 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0876 : 68 pla ;flags
|
|||
|
0877 : 4dfe01 eor lst_f
|
|||
|
087a : 297d and #$ff-fnz ;ignore flags changed by dey
|
|||
|
trap_ne ;returned flags
|
|||
|
087c : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
087e : a500 lda irq_a ;accu seen in IRQ vector
|
|||
|
0880 : cdff01 cmp lst_a
|
|||
|
trap_ne ;IRQ A received
|
|||
|
0883 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0885 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
0887 : 9a txs
|
|||
|
; repeat with reversed registers
|
|||
|
0888 : a2b6 ldx #$ff-'I'
|
|||
|
088a : a0ad ldy #$ff-'R'
|
|||
|
088c : a902 lda #2 ;set expected interrupt source IRQ
|
|||
|
088e : 8d0302 sta I_src
|
|||
|
push_stat $ff-intdis
|
|||
|
0891 : a9fb > lda #$ff-intdis
|
|||
|
0893 : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set IRQ_bit
|
|||
|
0894 : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0897 : 297f > and #I_filter
|
|||
|
> if IRQ_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
0899 : 0901 > ora #(1<<IRQ_bit)
|
|||
|
> endif
|
|||
|
089b : 28 > plp ;set flags
|
|||
|
089c : 48 > pha ;save to verify
|
|||
|
089d : 08 > php
|
|||
|
089e : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
08a1 : 88 dey ;Y count will fail, if instructions are skipped
|
|||
|
08a2 : 88 dey
|
|||
|
08a3 : 88 dey
|
|||
|
08a4 : 88 dey
|
|||
|
08a5 : 08 php ;check processor status later
|
|||
|
08a6 : e0b7 cpx #($ff-'I'+1) ;returned registers OK?
|
|||
|
trap_ne ;returned X
|
|||
|
08a8 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08aa : c0a6 cpy #($ff-'R'-7)
|
|||
|
trap_ne ;returned Y
|
|||
|
08ac : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08ae : c951 cmp #'Q'
|
|||
|
trap_ne ;returned A
|
|||
|
08b0 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08b2 : ba tsx
|
|||
|
08b3 : e0fc cpx #$ff-3
|
|||
|
trap_ne ;returned SP
|
|||
|
08b5 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08b7 : 68 pla ;flags
|
|||
|
08b8 : 4dfe01 eor lst_f
|
|||
|
08bb : 297d and #$ff-fnz ;ignore flags changed by dey
|
|||
|
trap_ne ;returned flags
|
|||
|
08bd : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08bf : a500 lda irq_a ;accu seen in IRQ vector
|
|||
|
08c1 : cdff01 cmp lst_a
|
|||
|
trap_ne ;IRQ A received
|
|||
|
08c4 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08c6 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
08c8 : 9a txs
|
|||
|
; retest for set flags seen in IRQ vector
|
|||
|
08c9 : a902 lda #2 ;set expected interrupt source IRQ
|
|||
|
08cb : 8d0302 sta I_src
|
|||
|
push_stat $ff-intdis
|
|||
|
08ce : a9fb > lda #$ff-intdis
|
|||
|
08d0 : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set IRQ_bit
|
|||
|
08d1 : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
08d4 : 297f > and #I_filter
|
|||
|
> if IRQ_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
08d6 : 0901 > ora #(1<<IRQ_bit)
|
|||
|
> endif
|
|||
|
08d8 : 28 > plp ;set flags
|
|||
|
08d9 : 48 > pha ;save to verify
|
|||
|
08da : 08 > php
|
|||
|
08db : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
08de : ea nop ;allow 6 cycles for interrupt to trip
|
|||
|
08df : ea nop
|
|||
|
08e0 : ea nop
|
|||
|
08e1 : ad0302 lda I_src
|
|||
|
trap_ne ;IRQ timeout
|
|||
|
08e4 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08e6 : ba tsx
|
|||
|
08e7 : e0fd cpx #$ff-2 ;original accu & flags remain on stack
|
|||
|
trap_ne ;returned SP
|
|||
|
08e9 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
08eb : a502 lda irq_f ;flags seen in IRQ vector
|
|||
|
if D_clear = 1
|
|||
|
and #decmode
|
|||
|
trap_ne ;D-flag not cleared
|
|||
|
lda irq_f
|
|||
|
eor lst_f ;turn off unchanged bits
|
|||
|
and #m8-fai-decmode ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C) changed
|
|||
|
else
|
|||
|
08ed : 4dfe01 eor lst_f ;turn off unchanged bits
|
|||
|
08f0 : 29cb and #m8-fai ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C,D) changed
|
|||
|
08f2 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
endif
|
|||
|
08f4 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
08f6 : 9a txs
|
|||
|
|
|||
|
; BRK integrity test
|
|||
|
; test for clear flags seen in IRQ vector
|
|||
|
08f7 : a901 lda #1 ;set expected interrupt source BRK
|
|||
|
08f9 : 8d0302 sta I_src
|
|||
|
set_stat 0
|
|||
|
08fc : a900 > lda #0
|
|||
|
08fe : 48 > pha ;use stack to load status
|
|||
|
08ff : 28 > plp
|
|||
|
|
|||
|
0900 : 48 pha ;save entry registers
|
|||
|
0901 : 08 php
|
|||
|
0902 : 00 brk
|
|||
|
0903 : ea nop ;should not be executed
|
|||
|
0904 : ea nop ;allow 6 cycles for interrupt to trip
|
|||
|
0905 : ea nop
|
|||
|
0906 : ea nop
|
|||
|
0907 : ad0302 lda I_src
|
|||
|
trap_ne ;IRQ timeout
|
|||
|
090a : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
090c : ba tsx
|
|||
|
090d : e0fd cpx #$ff-2 ;original accu & flags remain on stack
|
|||
|
trap_ne ;returned SP
|
|||
|
090f : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0911 : a502 lda irq_f ;flags seen in IRQ vector
|
|||
|
if D_clear = 1
|
|||
|
and #decmode
|
|||
|
trap_ne ;D-flag not cleared
|
|||
|
lda irq_f
|
|||
|
eor lst_f ;turn off unchanged bits
|
|||
|
and #m8-fai-decmode ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C) changed
|
|||
|
else
|
|||
|
0913 : 4dfe01 eor lst_f ;turn off unchanged bits
|
|||
|
0916 : 29cb and #m8-fai ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C,D) changed
|
|||
|
0918 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
endif
|
|||
|
091a : a2ff ldx #$ff ;reset stack pointer
|
|||
|
091c : 9a txs
|
|||
|
; test all other registers
|
|||
|
091d : a242 ldx #'B'
|
|||
|
091f : a052 ldy #'R'
|
|||
|
0921 : a901 lda #1 ;set expected interrupt source BRK
|
|||
|
0923 : 8d0302 sta I_src
|
|||
|
set_stat 0
|
|||
|
0926 : a900 > lda #0
|
|||
|
0928 : 48 > pha ;use stack to load status
|
|||
|
0929 : 28 > plp
|
|||
|
|
|||
|
092a : 48 pha ;save entry
|
|||
|
092b : 08 php
|
|||
|
092c : 00 brk
|
|||
|
092d : 88 dey ;should not be executed
|
|||
|
092e : 88 dey ;Y count will fail, if return address is wrong
|
|||
|
092f : 88 dey
|
|||
|
0930 : 88 dey
|
|||
|
0931 : 88 dey
|
|||
|
0932 : 08 php ;check processor status later
|
|||
|
0933 : e043 cpx #('B'+1) ;returned registers OK?
|
|||
|
trap_ne ;returned X
|
|||
|
0935 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0937 : c04b cpy #('R'-7)
|
|||
|
trap_ne ;returned Y
|
|||
|
0939 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
093b : c94b cmp #'K'
|
|||
|
trap_ne ;returned A
|
|||
|
093d : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
093f : ba tsx
|
|||
|
0940 : e0fc cpx #$ff-3
|
|||
|
trap_ne ;returned SP
|
|||
|
0942 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0944 : 68 pla ;flags
|
|||
|
0945 : 4dfe01 eor lst_f
|
|||
|
0948 : 297d and #$ff-fnz ;ignore flags changed by dey
|
|||
|
trap_ne ;returned flags
|
|||
|
094a : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
094c : a500 lda irq_a ;accu seen in IRQ vector
|
|||
|
094e : cdff01 cmp lst_a
|
|||
|
trap_ne ;IRQ A received
|
|||
|
0951 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0953 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
0955 : 9a txs
|
|||
|
; repeat with reversed registers
|
|||
|
0956 : a2bd ldx #$ff-'B'
|
|||
|
0958 : a0ad ldy #$ff-'R'
|
|||
|
095a : a901 lda #1 ;set expected interrupt source BRK
|
|||
|
095c : 8d0302 sta I_src
|
|||
|
set_stat $ff
|
|||
|
095f : a9ff > lda #$ff
|
|||
|
0961 : 48 > pha ;use stack to load status
|
|||
|
0962 : 28 > plp
|
|||
|
|
|||
|
0963 : 48 pha ;save entry registers
|
|||
|
0964 : 08 php
|
|||
|
0965 : 00 brk
|
|||
|
0966 : 88 dey ;should not be executed
|
|||
|
0967 : 88 dey ;Y count will fail, if return address is wrong
|
|||
|
0968 : 88 dey
|
|||
|
0969 : 88 dey
|
|||
|
096a : 88 dey
|
|||
|
096b : 08 php ;check processor status later
|
|||
|
096c : e0be cpx #($ff-'B'+1) ;returned registers OK?
|
|||
|
trap_ne ;returned X
|
|||
|
096e : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0970 : c0a6 cpy #($ff-'R'-7)
|
|||
|
trap_ne ;returned Y
|
|||
|
0972 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0974 : c94b cmp #'K'
|
|||
|
trap_ne ;returned A
|
|||
|
0976 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0978 : ba tsx
|
|||
|
0979 : e0fc cpx #$ff-3
|
|||
|
trap_ne ;returned SP
|
|||
|
097b : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
097d : 68 pla ;flags
|
|||
|
097e : 4dfe01 eor lst_f
|
|||
|
0981 : 297d and #$ff-fnz ;ignore flags changed by dey
|
|||
|
trap_ne ;returned flags
|
|||
|
0983 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0985 : a500 lda irq_a ;accu seen in IRQ vector
|
|||
|
0987 : cdff01 cmp lst_a
|
|||
|
trap_ne ;IRQ A received
|
|||
|
098a : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
098c : a2ff ldx #$ff ;reset stack pointer
|
|||
|
098e : 9a txs
|
|||
|
; retest for set flags seen in IRQ vector
|
|||
|
098f : a901 lda #1 ;set expected interrupt source BRK
|
|||
|
0991 : 8d0302 sta I_src
|
|||
|
set_stat $ff
|
|||
|
0994 : a9ff > lda #$ff
|
|||
|
0996 : 48 > pha ;use stack to load status
|
|||
|
0997 : 28 > plp
|
|||
|
|
|||
|
0998 : 48 pha ;save entry registers
|
|||
|
0999 : 08 php
|
|||
|
099a : 00 brk
|
|||
|
099b : ea nop ;should not be executed
|
|||
|
099c : ea nop ;allow 6 cycles for interrupt to trip
|
|||
|
099d : ea nop
|
|||
|
099e : ea nop
|
|||
|
099f : ad0302 lda I_src
|
|||
|
trap_ne ;IRQ timeout
|
|||
|
09a2 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
09a4 : ba tsx
|
|||
|
09a5 : e0fd cpx #$ff-2 ;original accu & flags remain on stack
|
|||
|
trap_ne ;returned SP
|
|||
|
09a7 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
09a9 : a502 lda irq_f ;flags seen in IRQ vector
|
|||
|
if D_clear = 1
|
|||
|
and #decmode
|
|||
|
trap_ne ;D-flag not cleared
|
|||
|
lda irq_f
|
|||
|
eor lst_f ;turn off unchanged bits
|
|||
|
and #m8-fai-decmode ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C) changed
|
|||
|
else
|
|||
|
09ab : 4dfe01 eor lst_f ;turn off unchanged bits
|
|||
|
09ae : 29cb and #m8-fai ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C,D) changed
|
|||
|
09b0 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
endif
|
|||
|
09b2 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
09b4 : 9a txs
|
|||
|
|
|||
|
if NMI_bit < 0
|
|||
|
; test IRQ with interrupts disabled
|
|||
|
ldx #0
|
|||
|
lda #0
|
|||
|
sta I_src
|
|||
|
push_stat intdis
|
|||
|
I_set IRQ_bit ;IRQ pending
|
|||
|
inx
|
|||
|
inx
|
|||
|
inx
|
|||
|
ldx #0
|
|||
|
lda #2 ;now re-enable IRQ
|
|||
|
sta I_src
|
|||
|
cli
|
|||
|
inx
|
|||
|
inx
|
|||
|
inx
|
|||
|
lda I_src ;test IRQ done?
|
|||
|
trap_ne
|
|||
|
ldx #$ff ;purge stack
|
|||
|
txs
|
|||
|
|
|||
|
ldx #0 ;now overlap IRQ & BRK
|
|||
|
lda #3
|
|||
|
sta I_src
|
|||
|
lda #$ff ;measure timing
|
|||
|
sta nmi_count
|
|||
|
sta irq_count
|
|||
|
sta brk_count
|
|||
|
push_stat 0
|
|||
|
I_set IRQ_bit ;trigger IRQ
|
|||
|
else
|
|||
|
; NMI integrity test
|
|||
|
; test for clear flags seen in NMI vector
|
|||
|
09b5 : a904 lda #4 ;set expected interrupt source NMI
|
|||
|
09b7 : 8d0302 sta I_src
|
|||
|
push_stat 0
|
|||
|
09ba : a900 > lda #0
|
|||
|
09bc : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set NMI_bit
|
|||
|
09bd : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
09c0 : 297f > and #I_filter
|
|||
|
> if NMI_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
09c2 : 0902 > ora #(1<<NMI_bit)
|
|||
|
> endif
|
|||
|
09c4 : 28 > plp ;set flags
|
|||
|
09c5 : 48 > pha ;save to verify
|
|||
|
09c6 : 08 > php
|
|||
|
09c7 : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
09ca : ea nop ;allow 6 cycles for interrupt to trip
|
|||
|
09cb : ea nop
|
|||
|
09cc : ea nop
|
|||
|
09cd : ad0302 lda I_src
|
|||
|
trap_ne ;NMI timeout
|
|||
|
09d0 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
09d2 : ba tsx
|
|||
|
09d3 : e0fd cpx #$ff-2 ;original accu & flags remain on stack
|
|||
|
trap_ne ;returned SP
|
|||
|
09d5 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
09d7 : a505 lda nmi_f ;flags seen in NMI vector
|
|||
|
if D_clear = 1
|
|||
|
and #decmode
|
|||
|
trap_ne ;D-flag not cleared
|
|||
|
lda nmi_f
|
|||
|
eor lst_f ;turn off unchanged bits
|
|||
|
and #m8-fai-decmode ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C) changed
|
|||
|
else
|
|||
|
09d9 : 4dfe01 eor lst_f ;turn off unchanged bits
|
|||
|
09dc : 29cb and #m8-fai ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C,D) changed
|
|||
|
09de : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
endif
|
|||
|
09e0 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
09e2 : 9a txs
|
|||
|
; test all other registers
|
|||
|
09e3 : a24e ldx #'N'
|
|||
|
09e5 : a04d ldy #'M'
|
|||
|
09e7 : a904 lda #4 ;set expected interrupt source NMI
|
|||
|
09e9 : 8d0302 sta I_src
|
|||
|
push_stat 0
|
|||
|
09ec : a900 > lda #0
|
|||
|
09ee : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set NMI_bit
|
|||
|
09ef : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
09f2 : 297f > and #I_filter
|
|||
|
> if NMI_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
09f4 : 0902 > ora #(1<<NMI_bit)
|
|||
|
> endif
|
|||
|
09f6 : 28 > plp ;set flags
|
|||
|
09f7 : 48 > pha ;save to verify
|
|||
|
09f8 : 08 > php
|
|||
|
09f9 : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
09fc : 88 dey ;Y count will fail, if instructions are skipped
|
|||
|
09fd : 88 dey
|
|||
|
09fe : 88 dey
|
|||
|
09ff : 88 dey
|
|||
|
0a00 : 08 php ;check processor status later
|
|||
|
0a01 : e04f cpx #('N'+1) ;returned registers OK?
|
|||
|
trap_ne ;returned X
|
|||
|
0a03 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a05 : c046 cpy #('M'-7)
|
|||
|
trap_ne ;returned Y
|
|||
|
0a07 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a09 : c949 cmp #'I'
|
|||
|
trap_ne ;returned A
|
|||
|
0a0b : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a0d : ba tsx
|
|||
|
0a0e : e0fc cpx #$ff-3
|
|||
|
trap_ne ;returned SP
|
|||
|
0a10 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a12 : 68 pla ;flags
|
|||
|
0a13 : 4dfe01 eor lst_f
|
|||
|
0a16 : 297d and #$ff-fnz ;ignore flags changed by dey
|
|||
|
trap_ne ;returned flags
|
|||
|
0a18 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a1a : a503 lda nmi_a ;accu seen in NMI vector
|
|||
|
0a1c : cdff01 cmp lst_a
|
|||
|
trap_ne ;NMI A received
|
|||
|
0a1f : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a21 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
0a23 : 9a txs
|
|||
|
; repeat with reversed registers
|
|||
|
0a24 : a2b1 ldx #$ff-'N'
|
|||
|
0a26 : a0b2 ldy #$ff-'M'
|
|||
|
0a28 : a904 lda #4 ;set expected interrupt source NMI
|
|||
|
0a2a : 8d0302 sta I_src
|
|||
|
push_stat $ff-intdis
|
|||
|
0a2d : a9fb > lda #$ff-intdis
|
|||
|
0a2f : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set NMI_bit
|
|||
|
0a30 : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0a33 : 297f > and #I_filter
|
|||
|
> if NMI_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
0a35 : 0902 > ora #(1<<NMI_bit)
|
|||
|
> endif
|
|||
|
0a37 : 28 > plp ;set flags
|
|||
|
0a38 : 48 > pha ;save to verify
|
|||
|
0a39 : 08 > php
|
|||
|
0a3a : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
0a3d : 88 dey ;Y count will fail, if instructions are skipped
|
|||
|
0a3e : 88 dey
|
|||
|
0a3f : 88 dey
|
|||
|
0a40 : 88 dey
|
|||
|
0a41 : 08 php ;check processor status later
|
|||
|
0a42 : e0b2 cpx #($ff-'N'+1) ;returned registers OK?
|
|||
|
trap_ne ;returned X
|
|||
|
0a44 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a46 : c0ab cpy #($ff-'M'-7)
|
|||
|
trap_ne ;returned Y
|
|||
|
0a48 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a4a : c949 cmp #'I'
|
|||
|
trap_ne ;returned A
|
|||
|
0a4c : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a4e : ba tsx
|
|||
|
0a4f : e0fc cpx #$ff-3
|
|||
|
trap_ne ;returned SP
|
|||
|
0a51 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a53 : 68 pla ;flags
|
|||
|
0a54 : 4dfe01 eor lst_f
|
|||
|
0a57 : 297d and #$ff-fnz ;ignore flags changed by dey
|
|||
|
trap_ne ;returned flags
|
|||
|
0a59 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a5b : a503 lda nmi_a ;accu seen in NMI vector
|
|||
|
0a5d : cdff01 cmp lst_a
|
|||
|
trap_ne ;NMI A received
|
|||
|
0a60 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a62 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
0a64 : 9a txs
|
|||
|
; retest for set flags seen in NMI vector
|
|||
|
0a65 : a904 lda #4 ;set expected interrupt source NMI
|
|||
|
0a67 : 8d0302 sta I_src
|
|||
|
push_stat $ff-intdis
|
|||
|
0a6a : a9fb > lda #$ff-intdis
|
|||
|
0a6c : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set NMI_bit
|
|||
|
0a6d : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0a70 : 297f > and #I_filter
|
|||
|
> if NMI_bit > 7 ;set both NMI & IRQ
|
|||
|
> ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
0a72 : 0902 > ora #(1<<NMI_bit)
|
|||
|
> endif
|
|||
|
0a74 : 28 > plp ;set flags
|
|||
|
0a75 : 48 > pha ;save to verify
|
|||
|
0a76 : 08 > php
|
|||
|
0a77 : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
0a7a : ea nop ;allow 6 cycles for interrupt to trip
|
|||
|
0a7b : ea nop
|
|||
|
0a7c : ea nop
|
|||
|
0a7d : ad0302 lda I_src
|
|||
|
trap_ne ;NMI timeout
|
|||
|
0a80 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a82 : ba tsx
|
|||
|
0a83 : e0fd cpx #$ff-2 ;original accu & flags remain on stack
|
|||
|
trap_ne ;returned SP
|
|||
|
0a85 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0a87 : a505 lda nmi_f ;flags seen in NMI vector
|
|||
|
if D_clear = 1
|
|||
|
and #decmode
|
|||
|
trap_ne ;D-flag not cleared
|
|||
|
lda nmi_f
|
|||
|
eor lst_f ;turn off unchanged bits
|
|||
|
and #m8-fai-decmode ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C) changed
|
|||
|
else
|
|||
|
0a89 : 4dfe01 eor lst_f ;turn off unchanged bits
|
|||
|
0a8c : 29cb and #m8-fai ;mask untested other flags
|
|||
|
trap_ne ;other flags (N,V,Z,C,D) changed
|
|||
|
0a8e : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
endif
|
|||
|
0a90 : a2ff ldx #$ff ;reset stack pointer
|
|||
|
0a92 : 9a txs
|
|||
|
|
|||
|
; test IRQ & NMI with interrupts disabled
|
|||
|
0a93 : a200 ldx #0
|
|||
|
0a95 : a904 lda #4 ;set expected interrupt NMI only
|
|||
|
0a97 : 8d0302 sta I_src
|
|||
|
push_stat intdis
|
|||
|
0a9a : a904 > lda #intdis
|
|||
|
0a9c : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set 8 ;both interrupts pending
|
|||
|
0a9d : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0aa0 : 297f > and #I_filter
|
|||
|
> if 8 > 7 ;set both NMI & IRQ
|
|||
|
0aa2 : 0903 > ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
> ora #(1<<8 )
|
|||
|
> endif
|
|||
|
0aa4 : 28 > plp ;set flags
|
|||
|
0aa5 : 48 > pha ;save to verify
|
|||
|
0aa6 : 08 > php
|
|||
|
0aa7 : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
0aaa : e8 inx
|
|||
|
0aab : e8 inx
|
|||
|
0aac : e8 inx
|
|||
|
0aad : ad0302 lda I_src ;test NMI done?
|
|||
|
trap_ne
|
|||
|
0ab0 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0ab2 : a200 ldx #0
|
|||
|
0ab4 : a902 lda #2 ;now re-enable IRQ
|
|||
|
0ab6 : 8d0302 sta I_src
|
|||
|
0ab9 : 58 cli
|
|||
|
0aba : e8 inx
|
|||
|
0abb : e8 inx
|
|||
|
0abc : e8 inx
|
|||
|
0abd : ad0302 lda I_src ;test IRQ done?
|
|||
|
trap_ne
|
|||
|
0ac0 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0ac2 : a2ff ldx #$ff ;purge stack
|
|||
|
0ac4 : 9a txs
|
|||
|
|
|||
|
;test overlapping NMI, IRQ & BRK
|
|||
|
0ac5 : a200 ldx #0
|
|||
|
0ac7 : a907 lda #7
|
|||
|
0ac9 : 8d0302 sta I_src
|
|||
|
0acc : a9ff lda #$ff ;measure timing
|
|||
|
0ace : 8d0002 sta nmi_count
|
|||
|
0ad1 : 8d0102 sta irq_count
|
|||
|
0ad4 : 8d0202 sta brk_count
|
|||
|
push_stat 0
|
|||
|
0ad7 : a900 > lda #0
|
|||
|
0ad9 : 48 > pha ;use stack to load status
|
|||
|
|
|||
|
I_set 8 ;trigger NMI + IRQ
|
|||
|
0ada : adfcbf > lda I_port ;turn on interrupt by bit
|
|||
|
0add : 297f > and #I_filter
|
|||
|
> if 8 > 7 ;set both NMI & IRQ
|
|||
|
0adf : 0903 > ora #(1<<IRQ_bit|1<<NMI_bit)
|
|||
|
> else
|
|||
|
> ora #(1<<8 )
|
|||
|
> endif
|
|||
|
0ae1 : 28 > plp ;set flags
|
|||
|
0ae2 : 48 > pha ;save to verify
|
|||
|
0ae3 : 08 > php
|
|||
|
0ae4 : 8dfcbf > sta I_port ;interrupt next instruction plus outbound delay
|
|||
|
|
|||
|
endif
|
|||
|
0ae7 : 00 brk
|
|||
|
0ae8 : e8 inx
|
|||
|
0ae9 : e8 inx
|
|||
|
0aea : e8 inx
|
|||
|
0aeb : e8 inx
|
|||
|
0aec : e8 inx
|
|||
|
0aed : e8 inx
|
|||
|
0aee : e8 inx
|
|||
|
0aef : e8 inx
|
|||
|
0af0 : ad0302 lda I_src ;test all done?
|
|||
|
;may fail due to a bug on a real NMOS 6502 - NMI could mask BRK
|
|||
|
trap_ne ;lost an interrupt
|
|||
|
0af3 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
|
|||
|
; S U C C E S S ************************************************
|
|||
|
; -------------
|
|||
|
success ;if you get here everything went well
|
|||
|
0af5 : 4cf50a > jmp * ;test passed, no errors
|
|||
|
|
|||
|
; -------------
|
|||
|
; S U C C E S S ************************************************
|
|||
|
; check data_segment +0 to +2 for sequence of concurrent interrupts
|
|||
|
; e.g. 0x200 = NMI, 0x201 = IRQ, 0x202 = BRK, lower values = earlier
|
|||
|
0af8 : 4c0008 jmp start ;run again
|
|||
|
|
|||
|
; manual tests for the WAI opcode of the 65c02
|
|||
|
|
|||
|
wai macro
|
|||
|
db $cb ;WAI opcode
|
|||
|
endm
|
|||
|
|
|||
|
; requires single step operation, report = 0
|
|||
|
; set PC to the 1st instruction of the test
|
|||
|
; step to the WAI opcode, then manually tie the IRQ input low
|
|||
|
; continue to step until you see the PC advance, then remove IRQ
|
|||
|
; allow the routine to complete.
|
|||
|
|
|||
|
; WAI with interrupts disabled
|
|||
|
0afb : a2ff ldx #$ff
|
|||
|
0afd : 9a txs
|
|||
|
0afe : a003 ldy #3
|
|||
|
0b00 : a900 lda #0 ;IRQ not expected
|
|||
|
0b02 : 8d0302 sta I_src
|
|||
|
set_stat intdis
|
|||
|
0b05 : a904 > lda #intdis
|
|||
|
0b07 : 48 > pha ;use stack to load status
|
|||
|
0b08 : 28 > plp
|
|||
|
|
|||
|
wai
|
|||
|
0b09 : cb > db $cb ;WAI opcode
|
|||
|
|
|||
|
0b0a : 88 dey
|
|||
|
0b0b : 88 dey
|
|||
|
0b0c : 88 dey
|
|||
|
trap_ne ;skipped opcodes!
|
|||
|
0b0d : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
|
|||
|
success
|
|||
|
0b0f : 4c0f0b > jmp * ;test passed, no errors
|
|||
|
|
|||
|
|
|||
|
; WAI with interrupts enabled
|
|||
|
0b12 : a2ff ldx #$ff
|
|||
|
0b14 : 9a txs
|
|||
|
0b15 : a007 ldy #7
|
|||
|
0b17 : a902 lda #2 ;IRQ expected
|
|||
|
0b19 : 8d0302 sta I_src
|
|||
|
set_stat 0
|
|||
|
0b1c : a900 > lda #0
|
|||
|
0b1e : 48 > pha ;use stack to load status
|
|||
|
0b1f : 28 > plp
|
|||
|
|
|||
|
wai
|
|||
|
0b20 : cb > db $cb ;WAI opcode
|
|||
|
|
|||
|
0b21 : 88 dey
|
|||
|
0b22 : 88 dey
|
|||
|
0b23 : 88 dey
|
|||
|
0b24 : ad0302 lda I_src
|
|||
|
trap_ne ;IRQ vector not called
|
|||
|
0b27 : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
0b29 : 88 dey
|
|||
|
trap_ne ;skipped opcodes!
|
|||
|
0b2a : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
|
|||
|
success
|
|||
|
0b2c : 4c2c0b > jmp * ;test passed, no errors
|
|||
|
|
|||
|
|
|||
|
; manual test for the STP opcode of the 65c02
|
|||
|
|
|||
|
stp macro
|
|||
|
db $db ;STP opcode
|
|||
|
endm
|
|||
|
|
|||
|
; set PC to the 1st instruction of the test, then run
|
|||
|
0b2f : ea nop
|
|||
|
0b30 : ea nop
|
|||
|
stp ;expected end of operation
|
|||
|
0b31 : db > db $db ;STP opcode
|
|||
|
|
|||
|
0b32 : ea nop
|
|||
|
0b33 : ea nop
|
|||
|
trap ;overran STP
|
|||
|
0b34 : 4c340b > jmp * ;failed anyway
|
|||
|
|
|||
|
|
|||
|
;end of manual tests
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
;trap in case of unexpected IRQ, NMI, BRK, RESET - IRQ, NMI, BRK test target
|
|||
|
0b37 : 88 dey
|
|||
|
0b38 : 88 dey
|
|||
|
0b39 : nmi_trap
|
|||
|
if NMI_bit < 0
|
|||
|
dey
|
|||
|
dey
|
|||
|
dey
|
|||
|
trap ;unexpected NMI
|
|||
|
else
|
|||
|
0b39 : 08 php ;either SP or Y count will fail, if we do not hit
|
|||
|
0b3a : 88 dey
|
|||
|
0b3b : 88 dey
|
|||
|
0b3c : 88 dey
|
|||
|
0b3d : 8503 sta nmi_a ;save regsters during NMI
|
|||
|
0b3f : 8604 stx nmi_x
|
|||
|
0b41 : 68 pla
|
|||
|
0b42 : 48 pha
|
|||
|
0b43 : 8505 sta nmi_f
|
|||
|
0b45 : ad0302 lda I_src ;NMI expected?
|
|||
|
0b48 : 2904 and #4
|
|||
|
trap_eq ;unexpexted NMI - check stack for conditions
|
|||
|
0b4a : f0fe > beq * ;failed equal (zero)
|
|||
|
|
|||
|
0b4c : 68 pla ;test I-flag was set
|
|||
|
0b4d : 48 pha
|
|||
|
0b4e : 2904 and #intdis
|
|||
|
trap_eq ;I-flag not set
|
|||
|
0b50 : f0fe > beq * ;failed equal (zero)
|
|||
|
|
|||
|
0b52 : 68 pla ;return with other flags reversed
|
|||
|
0b53 : 49c3 eor #m8-fai-decmode
|
|||
|
0b55 : 48 pha
|
|||
|
0b56 : ba tsx
|
|||
|
0b57 : bd0201 lda $102,x ;test break on stack
|
|||
|
0b5a : 2910 and #break
|
|||
|
trap_ne ;unexpected B-flag! - this may fail on a real 6502
|
|||
|
0b5c : d0fe > bne * ;failed not equal (non zero)
|
|||
|
|
|||
|
;due to a hardware bug on concurrent BRK & NMI
|
|||
|
0b5e : ad0302 lda I_src ;mark expected NMI has occured
|
|||
|
0b61 : 29fb and #$ff-4
|
|||
|
0b63 : 8d0302 sta I_src
|
|||
|
I_clr NMI_bit
|
|||
|
0b66 : adfcbf > lda I_port ;turn off interrupt by bit
|
|||
|
0b69 : 297d > and #I_filter-(1<<NMI_bit)
|
|||
|
0b6b : 8dfcbf > sta I_port
|
|||
|
|
|||
|
0b6e : a604 ldx nmi_x
|
|||
|
0b70 : e8 inx
|
|||
|
0b71 : 8e0002 stx nmi_count
|
|||
|
0b74 : a949 lda #'I' ;mark (NM)I
|
|||
|
0b76 : 28 plp ;should be reversed by rti
|
|||
|
0b77 : 40 rti
|
|||
|
endif
|
|||
|
|
|||
|
0b78 : res_trap
|
|||
|
trap ;unexpected RESET
|
|||
|
0b78 : 4c780b > jmp * ;failed anyway
|
|||
|
|
|||
|
|
|||
|
0b7b : 88 dey
|
|||
|
0b7c : 88 dey
|
|||
|
0b7d : irq_trap ;BRK & IRQ test
|
|||
|
0b7d : 08 php ;either SP or Y count will fail, if we do not hit
|
|||
|
0b7e : 88 dey
|
|||
|
0b7f : 88 dey
|
|||
|
0b80 : 88 dey
|
|||
|
0b81 : 8500 sta irq_a ;save registers during IRQ/BRK
|
|||
|
0b83 : 8601 stx irq_x
|
|||
|
0b85 : 68 pla
|
|||
|
0b86 : 48 pha
|
|||
|
0b87 : 8502 sta irq_f
|
|||
|
0b89 : ad0302 lda I_src ;IRQ expected?
|
|||
|
0b8c : 2903 and #3
|
|||
|
trap_eq ;unexpexted IRQ/BRK - check stack for conditions
|
|||
|
0b8e : f0fe > beq * ;failed equal (zero)
|
|||
|
|
|||
|
0b90 : 68 pla ;test I-flag was set
|
|||
|
0b91 : 48 pha
|
|||
|
0b92 : 2904 and #intdis
|
|||
|
trap_eq ;I-flag not set
|
|||
|
0b94 : f0fe > beq * ;failed equal (zero)
|
|||
|
|
|||
|
0b96 : 68 pla ;return with other flags reversed
|
|||
|
0b97 : 49c3 eor #m8-fai-decmode
|
|||
|
0b99 : 48 pha
|
|||
|
0b9a : ba tsx
|
|||
|
0b9b : bd0201 lda $102,x ;test break on stack
|
|||
|
0b9e : 2910 and #break
|
|||
|
0ba0 : d021 bne brk_trap
|
|||
|
|
|||
|
0ba2 : ad0302 lda I_src ;IRQ expected?
|
|||
|
0ba5 : 2902 and #2
|
|||
|
trap_eq ;unexpexted IRQ - check stack for conditions
|
|||
|
0ba7 : f0fe > beq * ;failed equal (zero)
|
|||
|
|
|||
|
0ba9 : ad0302 lda I_src ;mark expected IRQ has occured
|
|||
|
0bac : 29fd and #$ff-2
|
|||
|
0bae : 8d0302 sta I_src
|
|||
|
I_clr IRQ_bit
|
|||
|
0bb1 : adfcbf > lda I_port ;turn off interrupt by bit
|
|||
|
0bb4 : 297e > and #I_filter-(1<<IRQ_bit)
|
|||
|
0bb6 : 8dfcbf > sta I_port
|
|||
|
|
|||
|
0bb9 : a601 ldx irq_x
|
|||
|
0bbb : e8 inx
|
|||
|
0bbc : 8e0102 stx irq_count
|
|||
|
0bbf : a951 lda #'Q' ;mark (IR)Q
|
|||
|
0bc1 : 28 plp ;should be reversed by rti
|
|||
|
0bc2 : 40 rti
|
|||
|
|
|||
|
0bc3 : brk_trap
|
|||
|
0bc3 : ad0302 lda I_src ;break expected?
|
|||
|
0bc6 : 2901 and #1
|
|||
|
trap_eq ;unexpected BRK - check stack for conditions
|
|||
|
0bc8 : f0fe > beq * ;failed equal (zero)
|
|||
|
|
|||
|
0bca : ad0302 lda I_src ;mark expected BRK has occured
|
|||
|
0bcd : 29fe and #$ff-1
|
|||
|
0bcf : 8d0302 sta I_src
|
|||
|
0bd2 : a601 ldx irq_x
|
|||
|
0bd4 : e8 inx
|
|||
|
0bd5 : 8e0202 stx brk_count
|
|||
|
0bd8 : a500 lda irq_a
|
|||
|
0bda : a94b lda #'K' ;mark (BR)K
|
|||
|
0bdc : 28 plp ;should be reversed by rti
|
|||
|
0bdd : 40 rti
|
|||
|
|
|||
|
if report = 1
|
|||
|
rep_int = 1
|
|||
|
include "report.i65"
|
|||
|
endif
|
|||
|
|
|||
|
|
|||
|
;system vectors
|
|||
|
if (load_data_direct = 1)
|
|||
|
fffa = org $fffa
|
|||
|
fffa : 390b dw nmi_trap
|
|||
|
fffc : 780b dw res_trap
|
|||
|
fffe : 7d0b dw irq_trap
|
|||
|
else
|
|||
|
vec_init
|
|||
|
vec_bss equ $fffa
|
|||
|
dw nmi_trap
|
|||
|
dw res_trap
|
|||
|
dw irq_trap
|
|||
|
endif
|
|||
|
|
|||
|
fffa = end start
|
|||
|
|
|||
|
|
|||
|
No errors in pass 2.
|
|||
|
Wrote binary from address $0000 through $ffff.
|
|||
|
Total size 65536 bytes.
|
|||
|
Program start address is at $0800 (2048).
|
|||
|
|