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

Subversion Repositories cpu65c02_true_cycle

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 20 to Rev 21
    Reverse comparison

Rev 20 → Rev 21

/cpu65c02_true_cycle/trunk/asm/6502_decimal_test.a65
0,0 → 1,362
; Verify decimal mode behavior
; Written by Bruce Clark. This code is public domain.
; see http://www.6502.org/tutorials/decimal_mode.html
;
; Returns:
; ERROR = 0 if the test passed
; ERROR = 1 if the test failed
; modify the code at the DONE label for desired program end
;
; This routine requires 17 bytes of RAM -- 1 byte each for:
; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF
; and 2 bytes for N2H
;
; Variables:
; N1 and N2 are the two numbers to be added or subtracted
; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2
; DA and DNVZC are the actual accumulator and flag results in decimal mode
; HA and HNVZC are the accumulator and flag results when N1 and N2 are
; added or subtracted using binary arithmetic
; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and
; flag results, calculated using binary arithmetic
;
; This program takes approximately 1 minute at 1 MHz (a few seconds more on
; a 65C02 than a 6502 or 65816)
;
 
; Configuration:
cputype = 1 ; 0 = 6502, 1 = 65C02, 2 = 65C816
vld_bcd = 0 ; 0 = allow invalid bcd, 1 = valid bcd only
chk_a = 1 ; check accumulator
chk_n = 1 ; check sign (negative) flag
chk_v = 1 ; check overflow flag
chk_z = 1 ; check zero flag
chk_c = 1 ; check carry flag
 
end_of_test macro
db $db ;execute 65C02 stop instruction
endm
 
data
org 0
; operands - register Y = carry in
N1 ds 1
N2 ds 1
; binary result
HA ds 1
HNVZC ds 1
;04
; decimal result
DA ds 1
DNVZC ds 1
; predicted results
AR ds 1
NF ds 1
;08
VF ds 1
ZF ds 1
CF ds 1
ERROR ds 1
;0C
; workspace
N1L ds 1
N1H ds 1
N2L ds 1
N2H ds 2
 
code
org $200
TEST ldy #1 ; initialize Y (used to loop through carry flag values)
sty ERROR ; store 1 in ERROR until the test passes
lda #0 ; initialize N1 and N2
sta N1
sta N2
LOOP1 lda N2 ; N2L = N2 & $0F
and #$0F ; [1] see text
if vld_bcd = 1
cmp #$0a
bcs NEXT2
endif
sta N2L
lda N2 ; N2H = N2 & $F0
and #$F0 ; [2] see text
if vld_bcd = 1
cmp #$a0
bcs NEXT2
endif
sta N2H
ora #$0F ; N2H+1 = (N2 & $F0) + $0F
sta N2H+1
LOOP2 lda N1 ; N1L = N1 & $0F
and #$0F ; [3] see text
if vld_bcd = 1
cmp #$0a
bcs NEXT1
endif
sta N1L
lda N1 ; N1H = N1 & $F0
and #$F0 ; [4] see text
if vld_bcd = 1
cmp #$a0
bcs NEXT1
endif
sta N1H
jsr ADD
jsr A6502
jsr COMPARE
bne DONE
jsr SUB
jsr S6502
jsr COMPARE
bne DONE
NEXT1 inc N1 ; [5] see text
bne LOOP2 ; loop through all 256 values of N1
NEXT2 inc N2 ; [6] see text
bne LOOP1 ; loop through all 256 values of N2
dey
bpl LOOP1 ; loop through both values of the carry flag
lda #0 ; test passed, so store 0 in ERROR
sta ERROR
DONE
lda ERROR
jmp DONE
end_of_test
; Calculate the actual decimal mode accumulator and flags, the accumulator
; and flag results when N1 is added to N2 using binary arithmetic, the
; predicted accumulator result, the predicted carry flag, and the predicted
; V flag
;
ADD sed ; decimal mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
adc N2
sta DA ; actual accumulator result in decimal mode
php
pla
sta DNVZC ; actual flags result in decimal mode
cld ; binary mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
adc N2
sta HA ; accumulator result of N1+N2 using binary arithmetic
php
pla
sta HNVZC ; flags result of N1+N2 using binary arithmetic
cpy #1
lda N1L
adc N2L
cmp #$0A
ldx #0
bcc A1
inx
adc #5 ; add 6 (carry is set)
and #$0F
sec
A1 ora N1H
;
; if N1L + N2L < $0A, then add N2 & $F0
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
;
adc N2H,x
php
bcs A2
cmp #$A0
bcc A3
A2 adc #$5F ; add $60 (carry is set)
sec
A3 sta AR ; predicted accumulator result
php
pla
sta CF ; predicted carry result
pla
;
; note that all 8 bits of the P register are stored in VF
;
sta VF ; predicted V flags
rts
; Calculate the actual decimal mode accumulator and flags, and the
; accumulator and flag results when N2 is subtracted from N1 using binary
; arithmetic
;
SUB sed ; decimal mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
sbc N2
sta DA ; actual accumulator result in decimal mode
php
pla
sta DNVZC ; actual flags result in decimal mode
cld ; binary mode
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1
sbc N2
sta HA ; accumulator result of N1-N2 using binary arithmetic
php
pla
sta HNVZC ; flags result of N1-N2 using binary arithmetic
rts
if cputype != 1
; Calculate the predicted SBC accumulator result for the 6502 and 65816
;
SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1L
sbc N2L
ldx #0
bcs S11
inx
sbc #5 ; subtract 6 (carry is clear)
and #$0F
clc
S11 ora N1H
;
; if N1L - N2L >= 0, then subtract N2 & $F0
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
;
sbc N2H,x
bcs S12
sbc #$5F ; subtract $60 (carry is clear)
S12 sta AR
rts
endif
if cputype = 1
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
;
SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
lda N1L
sbc N2L
ldx #0
bcs S21
inx
and #$0F
clc
S21 ora N1H
;
; if N1L - N2L >= 0, then subtract N2 & $F0
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
;
sbc N2H,x
bcs S22
sbc #$5F ; subtract $60 (carry is clear)
S22 cpx #0
beq S23
sbc #6
S23 sta AR ; predicted accumulator result
rts
endif
; Compare accumulator actual results to predicted results
;
; Return:
; Z flag = 1 (BEQ branch) if same
; Z flag = 0 (BNE branch) if different
;
COMPARE
if chk_a = 1
lda DA
cmp AR
bne C1
endif
if chk_n = 1
lda DNVZC ; [7] see text
eor NF
and #$80 ; mask off N flag
bne C1
endif
if chk_v = 1
lda DNVZC ; [8] see text
eor VF
and #$40 ; mask off V flag
bne C1 ; [9] see text
endif
if chk_z = 1
lda DNVZC
eor ZF ; mask off Z flag
and #2
bne C1 ; [10] see text
endif
if chk_c = 1
lda DNVZC
eor CF
and #1 ; mask off C flag
endif
C1 rts
; These routines store the predicted values for ADC and SBC for the 6502,
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
 
if cputype = 0
 
A6502 lda VF ; 6502
;
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
; the N flag for NF
;
sta NF
lda HNVZC
sta ZF
rts
S6502 jsr SUB1
lda HNVZC
sta NF
sta VF
sta ZF
sta CF
rts
 
endif
if cputype = 1
 
A6502 lda AR ; 65C02
php
pla
sta NF
sta ZF
rts
S6502 jsr SUB2
lda AR
php
pla
sta NF
sta ZF
lda HNVZC
sta VF
sta CF
rts
 
endif
if cputype = 2
 
A6502 lda AR ; 65C816
php
pla
sta NF
sta ZF
rts
S6502 jsr SUB1
lda AR
php
pla
sta NF
sta ZF
lda HNVZC
sta VF
sta CF
rts
 
endif
 
org $fffa ;vectors
dw TEST
dw TEST
dw TEST
 
end TEST
/cpu65c02_true_cycle/trunk/asm/6502_interrupt_test.a65
0,0 → 1,1029
;
; 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
load_data_direct = 1
 
;NMI & IRQ are tested with a feedback register
;emulators diag register - set i_drive = 0 for a latch (74HC573)
I_port = $bffc ;feedback port address
I_ddr = 0 ;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 = $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
;D_clear = 0 ;0 = not cleared (NMOS), 1 = cleared (CMOS)
D_clear = 1 ;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
zero_page = $a
 
;data_segment memory start address, 4 consecutive Bytes required
data_segment = $200
 
;code_segment memory start address
code_segment = $400
 
;report errors through I/O channel (0=use standard self trap loops, 1=include
;report.i65 as I/O channel)
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
 
 
carry equ %00000001 ;flag bits in status
zero equ %00000010
intdis equ %00000100
decmode equ %00001000
break equ %00010000
reserv equ %00100000
overfl equ %01000000
minus equ %10000000
 
fc equ carry
fz equ zero
fzc equ carry+zero
fv equ overfl
fvz equ overfl+zero
fn equ minus
fnc equ minus+carry
fnz equ minus+zero
fnzc equ minus+zero+carry
fnv equ minus+overfl
 
fao equ break+reserv ;bits always on after PHP, BRK
fai equ fao+intdis ;+ forced interrupt disable
m8 equ $ff ;8 bit mask
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
org zero_page
;BRK, IRQ, NMI test interrupt save
zpt
irq_a ds 1 ;a register
irq_x ds 1 ;x register
irq_f ds 1 ;flags
nmi_a ds 1 ;a register
nmi_x ds 1 ;x register
nmi_f ds 1 ;flags
zp_bss
 
;fixed stack locations
lst_f equ $1fe ;last flags before interrupt
lst_a equ $1ff ;last accumulator before interrupt
org data_segment
;concurrent NMI, IRQ & BRK test result
nmi_count ds 1 ;lowest number handled first, $ff = never
irq_count ds 1 ;separation-1 = instructions between interrupts
brk_count ds 1
;expected interrupt mask
I_src ds 1 ;bit: 0=BRK, 1=IRQ, 2=NMI
data_bss
 
code
org code_segment
start cld
lda #0 ;clear expected interrupts for 2nd run
sta I_src
ldx #$ff
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
I_clr NMI_bit
endif
endif
endif
; IRQ integrity test
; test for clear flags seen in IRQ vector
lda #2 ;set expected interrupt source IRQ
sta I_src
push_stat 0
I_set IRQ_bit
nop ;allow 6 cycles for interrupt to trip
nop
nop
lda I_src
trap_ne ;IRQ timeout
tsx
cpx #$ff-2 ;original accu & flags remain on stack
trap_ne ;returned SP
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
eor lst_f ;turn off unchanged bits
and #m8-fai ;mask untested other flags
trap_ne ;other flags (N,V,Z,C,D) changed
endif
ldx #$ff ;reset stack pointer
txs
; test all other registers
ldx #'I'
ldy #'R'
lda #2 ;set expected interrupt source IRQ
sta I_src
push_stat 0
I_set IRQ_bit
dey ;Y count will fail, if instructions are skipped
dey
dey
dey
php ;check processor status later
cpx #('I'+1) ;returned registers OK?
trap_ne ;returned X
cpy #('R'-7)
trap_ne ;returned Y
cmp #'Q'
trap_ne ;returned A
tsx
cpx #$ff-3
trap_ne ;returned SP
pla ;flags
eor lst_f
and #$ff-fnz ;ignore flags changed by dey
trap_ne ;returned flags
lda irq_a ;accu seen in IRQ vector
cmp lst_a
trap_ne ;IRQ A received
ldx #$ff ;reset stack pointer
txs
; repeat with reversed registers
ldx #$ff-'I'
ldy #$ff-'R'
lda #2 ;set expected interrupt source IRQ
sta I_src
push_stat $ff-intdis
I_set IRQ_bit
dey ;Y count will fail, if instructions are skipped
dey
dey
dey
php ;check processor status later
cpx #($ff-'I'+1) ;returned registers OK?
trap_ne ;returned X
cpy #($ff-'R'-7)
trap_ne ;returned Y
cmp #'Q'
trap_ne ;returned A
tsx
cpx #$ff-3
trap_ne ;returned SP
pla ;flags
eor lst_f
and #$ff-fnz ;ignore flags changed by dey
trap_ne ;returned flags
lda irq_a ;accu seen in IRQ vector
cmp lst_a
trap_ne ;IRQ A received
ldx #$ff ;reset stack pointer
txs
; retest for set flags seen in IRQ vector
lda #2 ;set expected interrupt source IRQ
sta I_src
push_stat $ff-intdis
I_set IRQ_bit
nop ;allow 6 cycles for interrupt to trip
nop
nop
lda I_src
trap_ne ;IRQ timeout
tsx
cpx #$ff-2 ;original accu & flags remain on stack
trap_ne ;returned SP
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
eor lst_f ;turn off unchanged bits
and #m8-fai ;mask untested other flags
trap_ne ;other flags (N,V,Z,C,D) changed
endif
ldx #$ff ;reset stack pointer
txs
 
; BRK integrity test
; test for clear flags seen in IRQ vector
lda #1 ;set expected interrupt source BRK
sta I_src
set_stat 0
pha ;save entry registers
php
brk
nop ;should not be executed
nop ;allow 6 cycles for interrupt to trip
nop
nop
lda I_src
trap_ne ;IRQ timeout
tsx
cpx #$ff-2 ;original accu & flags remain on stack
trap_ne ;returned SP
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
eor lst_f ;turn off unchanged bits
and #m8-fai ;mask untested other flags
trap_ne ;other flags (N,V,Z,C,D) changed
endif
ldx #$ff ;reset stack pointer
txs
; test all other registers
ldx #'B'
ldy #'R'
lda #1 ;set expected interrupt source BRK
sta I_src
set_stat 0
pha ;save entry
php
brk
dey ;should not be executed
dey ;Y count will fail, if return address is wrong
dey
dey
dey
php ;check processor status later
cpx #('B'+1) ;returned registers OK?
trap_ne ;returned X
cpy #('R'-7)
trap_ne ;returned Y
cmp #'K'
trap_ne ;returned A
tsx
cpx #$ff-3
trap_ne ;returned SP
pla ;flags
eor lst_f
and #$ff-fnz ;ignore flags changed by dey
trap_ne ;returned flags
lda irq_a ;accu seen in IRQ vector
cmp lst_a
trap_ne ;IRQ A received
ldx #$ff ;reset stack pointer
txs
; repeat with reversed registers
ldx #$ff-'B'
ldy #$ff-'R'
lda #1 ;set expected interrupt source BRK
sta I_src
set_stat $ff
pha ;save entry registers
php
brk
dey ;should not be executed
dey ;Y count will fail, if return address is wrong
dey
dey
dey
php ;check processor status later
cpx #($ff-'B'+1) ;returned registers OK?
trap_ne ;returned X
cpy #($ff-'R'-7)
trap_ne ;returned Y
cmp #'K'
trap_ne ;returned A
tsx
cpx #$ff-3
trap_ne ;returned SP
pla ;flags
eor lst_f
and #$ff-fnz ;ignore flags changed by dey
trap_ne ;returned flags
lda irq_a ;accu seen in IRQ vector
cmp lst_a
trap_ne ;IRQ A received
ldx #$ff ;reset stack pointer
txs
; retest for set flags seen in IRQ vector
lda #1 ;set expected interrupt source BRK
sta I_src
set_stat $ff
pha ;save entry registers
php
brk
nop ;should not be executed
nop ;allow 6 cycles for interrupt to trip
nop
nop
lda I_src
trap_ne ;IRQ timeout
tsx
cpx #$ff-2 ;original accu & flags remain on stack
trap_ne ;returned SP
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
eor lst_f ;turn off unchanged bits
and #m8-fai ;mask untested other flags
trap_ne ;other flags (N,V,Z,C,D) changed
endif
ldx #$ff ;reset stack pointer
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
lda #4 ;set expected interrupt source NMI
sta I_src
push_stat 0
I_set NMI_bit
nop ;allow 6 cycles for interrupt to trip
nop
nop
lda I_src
trap_ne ;NMI timeout
tsx
cpx #$ff-2 ;original accu & flags remain on stack
trap_ne ;returned SP
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
eor lst_f ;turn off unchanged bits
and #m8-fai ;mask untested other flags
trap_ne ;other flags (N,V,Z,C,D) changed
endif
ldx #$ff ;reset stack pointer
txs
; test all other registers
ldx #'N'
ldy #'M'
lda #4 ;set expected interrupt source NMI
sta I_src
push_stat 0
I_set NMI_bit
dey ;Y count will fail, if instructions are skipped
dey
dey
dey
php ;check processor status later
cpx #('N'+1) ;returned registers OK?
trap_ne ;returned X
cpy #('M'-7)
trap_ne ;returned Y
cmp #'I'
trap_ne ;returned A
tsx
cpx #$ff-3
trap_ne ;returned SP
pla ;flags
eor lst_f
and #$ff-fnz ;ignore flags changed by dey
trap_ne ;returned flags
lda nmi_a ;accu seen in NMI vector
cmp lst_a
trap_ne ;NMI A received
ldx #$ff ;reset stack pointer
txs
; repeat with reversed registers
ldx #$ff-'N'
ldy #$ff-'M'
lda #4 ;set expected interrupt source NMI
sta I_src
push_stat $ff-intdis
I_set NMI_bit
dey ;Y count will fail, if instructions are skipped
dey
dey
dey
php ;check processor status later
cpx #($ff-'N'+1) ;returned registers OK?
trap_ne ;returned X
cpy #($ff-'M'-7)
trap_ne ;returned Y
cmp #'I'
trap_ne ;returned A
tsx
cpx #$ff-3
trap_ne ;returned SP
pla ;flags
eor lst_f
and #$ff-fnz ;ignore flags changed by dey
trap_ne ;returned flags
lda nmi_a ;accu seen in NMI vector
cmp lst_a
trap_ne ;NMI A received
ldx #$ff ;reset stack pointer
txs
; retest for set flags seen in NMI vector
lda #4 ;set expected interrupt source NMI
sta I_src
push_stat $ff-intdis
I_set NMI_bit
nop ;allow 6 cycles for interrupt to trip
nop
nop
lda I_src
trap_ne ;NMI timeout
tsx
cpx #$ff-2 ;original accu & flags remain on stack
trap_ne ;returned SP
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
eor lst_f ;turn off unchanged bits
and #m8-fai ;mask untested other flags
trap_ne ;other flags (N,V,Z,C,D) changed
endif
ldx #$ff ;reset stack pointer
txs
 
; test IRQ & NMI with interrupts disabled
ldx #0
lda #4 ;set expected interrupt NMI only
sta I_src
push_stat intdis
I_set 8 ;both interrupts pending
inx
inx
inx
lda I_src ;test NMI done?
trap_ne
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
 
;test overlapping NMI, IRQ & BRK
ldx #0
lda #7
sta I_src
lda #$ff ;measure timing
sta nmi_count
sta irq_count
sta brk_count
push_stat 0
I_set 8 ;trigger NMI + IRQ
endif
brk
inx
inx
inx
inx
inx
inx
inx
inx
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
 
; S U C C E S S ************************************************
; -------------
success ;if you get here everything went well
; -------------
; 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
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
ldx #$ff
txs
ldy #3
lda #0 ;IRQ not expected
sta I_src
set_stat intdis
wai
dey
dey
dey
trap_ne ;skipped opcodes!
 
success
; WAI with interrupts enabled
ldx #$ff
txs
ldy #7
lda #2 ;IRQ expected
sta I_src
set_stat 0
wai
dey
dey
dey
lda I_src
trap_ne ;IRQ vector not called
dey
trap_ne ;skipped opcodes!
 
success
; 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
nop
nop
stp ;expected end of operation
nop
nop
trap ;overran STP
 
;end of manual tests
 
;---------------------------------------------------------------------------
;trap in case of unexpected IRQ, NMI, BRK, RESET - IRQ, NMI, BRK test target
dey
dey
nmi_trap
if NMI_bit < 0
dey
dey
dey
trap ;unexpected NMI
else
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
sta nmi_a ;save regsters during NMI
stx nmi_x
pla
pha
sta nmi_f
lda I_src ;NMI expected?
and #4
trap_eq ;unexpexted NMI - check stack for conditions
pla ;test I-flag was set
pha
and #intdis
trap_eq ;I-flag not set
pla ;return with other flags reversed
eor #m8-fai-decmode
pha
tsx
lda $102,x ;test break on stack
and #break
trap_ne ;unexpected B-flag! - this may fail on a real 6502
;due to a hardware bug on concurrent BRK & NMI
lda I_src ;mark expected NMI has occured
and #$ff-4
sta I_src
I_clr NMI_bit
ldx nmi_x
inx
stx nmi_count
lda #'I' ;mark (NM)I
plp ;should be reversed by rti
rti
endif
 
res_trap
trap ;unexpected RESET
dey
dey
irq_trap ;BRK & IRQ test
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
sta irq_a ;save registers during IRQ/BRK
stx irq_x
pla
pha
sta irq_f
lda I_src ;IRQ expected?
and #3
trap_eq ;unexpexted IRQ/BRK - check stack for conditions
pla ;test I-flag was set
pha
and #intdis
trap_eq ;I-flag not set
pla ;return with other flags reversed
eor #m8-fai-decmode
pha
tsx
lda $102,x ;test break on stack
and #break
bne brk_trap
lda I_src ;IRQ expected?
and #2
trap_eq ;unexpexted IRQ - check stack for conditions
lda I_src ;mark expected IRQ has occured
and #$ff-2
sta I_src
I_clr IRQ_bit
ldx irq_x
inx
stx irq_count
lda #'Q' ;mark (IR)Q
plp ;should be reversed by rti
rti
brk_trap
lda I_src ;break expected?
and #1
trap_eq ;unexpected BRK - check stack for conditions
lda I_src ;mark expected BRK has occured
and #$ff-1
sta I_src
ldx irq_x
inx
stx brk_count
lda irq_a
lda #'K' ;mark (BR)K
plp ;should be reversed by rti
rti
if report = 1
rep_int = 1
include "report.i65"
endif
 
;system vectors
if (load_data_direct = 1)
org $fffa
dw nmi_trap
; dw res_trap
dw start
dw irq_trap
else
vec_init
vec_bss equ $fffa
dw nmi_trap
; dw res_trap
dw start
dw irq_trap
endif
end start
/cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_92_DRAFT.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_92_DRAFT.pdf Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/HTML.rar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/HTML.rar =================================================================== --- cpu65c02_true_cycle/trunk/doc/HTML.rar (revision 20) +++ cpu65c02_true_cycle/trunk/doc/HTML.rar (nonexistent)
cpu65c02_true_cycle/trunk/doc/HTML.rar Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_7.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_7.pdf =================================================================== --- cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_7.pdf (revision 20) +++ cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_7.pdf (nonexistent)
cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_7.pdf Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_94.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_94.pdf =================================================================== --- cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_94.pdf (nonexistent) +++ cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_94.pdf (revision 21)
cpu65c02_true_cycle/trunk/doc/65C02_opcodes_cycles_testet_V0_94.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/HTML_r65c02_tc.7z =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/HTML_r65c02_tc.7z =================================================================== --- cpu65c02_true_cycle/trunk/doc/HTML_r65c02_tc.7z (nonexistent) +++ cpu65c02_true_cycle/trunk/doc/HTML_r65c02_tc.7z (revision 21)
cpu65c02_true_cycle/trunk/doc/HTML_r65c02_tc.7z Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_9.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_9.pdf =================================================================== --- cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_9.pdf (nonexistent) +++ cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_9.pdf (revision 21)
cpu65c02_true_cycle/trunk/doc/R65C02 IP Core Specification_V0_9.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/src/R65C02 IP Core Specification_V0_7.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/src/R65C02 IP Core Specification_V0_7.doc =================================================================== --- cpu65c02_true_cycle/trunk/doc/src/R65C02 IP Core Specification_V0_7.doc (revision 20) +++ cpu65c02_true_cycle/trunk/doc/src/R65C02 IP Core Specification_V0_7.doc (nonexistent)
cpu65c02_true_cycle/trunk/doc/src/R65C02 IP Core Specification_V0_7.doc Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/src/65C02_opcodes_cycles_testet_V0_92_DRAFT.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/src/65C02_opcodes_cycles_testet_V0_92_DRAFT.doc =================================================================== --- cpu65c02_true_cycle/trunk/doc/src/65C02_opcodes_cycles_testet_V0_92_DRAFT.doc (revision 20) +++ cpu65c02_true_cycle/trunk/doc/src/65C02_opcodes_cycles_testet_V0_92_DRAFT.doc (nonexistent)
cpu65c02_true_cycle/trunk/doc/src/65C02_opcodes_cycles_testet_V0_92_DRAFT.doc Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/doc/src/65C02_OP code_table_A01.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: cpu65c02_true_cycle/trunk/doc/src/65C02_OP code_table_A01.doc =================================================================== --- cpu65c02_true_cycle/trunk/doc/src/65C02_OP code_table_A01.doc (revision 20) +++ cpu65c02_true_cycle/trunk/doc/src/65C02_OP code_table_A01.doc (nonexistent)
cpu65c02_true_cycle/trunk/doc/src/65C02_OP code_table_A01.doc Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: cpu65c02_true_cycle/trunk/rtl/vhdl/r65c02_tc_config.vhd =================================================================== --- cpu65c02_true_cycle/trunk/rtl/vhdl/r65c02_tc_config.vhd (revision 20) +++ cpu65c02_true_cycle/trunk/rtl/vhdl/r65c02_tc_config.vhd (nonexistent) @@ -1,38 +0,0 @@ --- Generation properties: --- Format : flat --- Generic mappings : exclude --- Leaf-level entities : direct binding --- Regular libraries : use work --- View name : include --- -library work; -configuration r65c02_tc_config of R65C02_TC is - for struct - for all : core - use entity work.core(struct); - for struct - for all : regbank_axy - use entity work.regbank_axy(struct); - for struct - end for; - end for; - for all : reg_pc - use entity work.reg_pc(struct); - for struct - end for; - end for; - for all : reg_sp - use entity work.reg_sp(struct); - for struct - end for; - end for; - for all : fsm_execution_unit - use entity work.fsm_execution_unit(fsm); - end for; - for all : fsm_intnmi - use entity work.fsm_intnmi(fsm); - end for; - end for; - end for; - end for; -end r65c02_tc_config;

powered by: WebSVN 2.1.0

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