ca65 V2.18 - N/A
Main file : ./6502_65C02_functional_tests/ca65/6502_functional_test.ca65
Current file: ./6502_65C02_functional_tests/ca65/6502_functional_test.ca65
000000r 1 ;
000000r 1 ; 6 5 0 2 F U N C T I O N A L T E S T
000000r 1 ;
000000r 1 ; Copyright (C) 2012-2020 Klaus Dormann
000000r 1 ;
000000r 1 ; This program is free software: you can redistribute it and/or modify
000000r 1 ; it under the terms of the GNU General Public License as published by
000000r 1 ; the Free Software Foundation, either version 3 of the License, or
000000r 1 ; (at your option) any later version.
000000r 1 ;
000000r 1 ; This program is distributed in the hope that it will be useful,
000000r 1 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
000000r 1 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
000000r 1 ; GNU General Public License for more details.
000000r 1 ;
000000r 1 ; You should have received a copy of the GNU General Public License
000000r 1 ; along with this program. If not, see .
000000r 1
000000r 1
000000r 1 ; This program is designed to test all opcodes of a 6502 emulator using all
000000r 1 ; addressing modes with focus on propper setting of the processor status
000000r 1 ; register bits.
000000r 1 ;
000000r 1 ; version 05-jan-2020
000000r 1 ; contact info at http://2m5.de or email K@2m5.de
000000r 1 ;
000000r 1 ; assembled with CA65, linked with LD65 (cc65.github.io):
000000r 1 ; ca65 -l 6502_functional_test.lst 6502_functional_test.ca65
000000r 1 ; ld65 6502_functional_test.o -o 6502_functional_test.bin \
000000r 1 ; -m 6502_functional_test.map -C example.cfg
000000r 1 ; example linker config (example.cfg):
000000r 1 ; MEMORY {
000000r 1 ; RAM: start = $0000, size=$8000, type = rw, fill = yes, \
000000r 1 ; fillval = $FF, file = %O;
000000r 1 ; ROM: start = $8000, size=$7FFA, type = ro, fill = yes, \
000000r 1 ; fillval = $FF, file = %O;
000000r 1 ; ROM_VECTORS: start = $FFFA, size=6, type = ro, fill = yes, \
000000r 1 ; fillval = $FF, file = %O;
000000r 1 ; }
000000r 1 ; SEGMENTS {
000000r 1 ; ZEROPAGE: load=RAM, type=rw;
000000r 1 ; DATA: load=RAM, type=rw, offset=$0200;
000000r 1 ; CODE: load=RAM, type=rw, offset=$0400;
000000r 1 ; VECTORS: load=ROM_VECTORS, type=ro;
000000r 1 ; }
000000r 1 ;
000000r 1 ; No IO - should be run from a monitor with access to registers.
000000r 1 ; To run load intel hex image with a load command, than alter PC to 400 hex
000000r 1 ; (code_segment) and enter a go command.
000000r 1 ; Loop on program counter determines error or successful completion of test.
000000r 1 ; Check listing for relevant traps (jump/branch *).
000000r 1 ; Please note that in early tests some instructions will have to be used before
000000r 1 ; they are actually tested!
000000r 1 ;
000000r 1 ; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled.
000000r 1 ; Tests documented behavior of the original NMOS 6502 only! No unofficial
000000r 1 ; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will
000000r 1 ; not be tested. Decimal ops will only be tested with valid BCD operands and
000000r 1 ; N V Z flags will be ignored.
000000r 1 ;
000000r 1 ; Debugging hints:
000000r 1 ; Most of the code is written sequentially. if you hit a trap, check the
000000r 1 ; immediately preceeding code for the instruction to be tested. Results are
000000r 1 ; tested first, flags are checked second by pushing them onto the stack and
000000r 1 ; pulling them to the accumulator after the result was checked. The "real"
000000r 1 ; flags are no longer valid for the tested instruction at this time!
000000r 1 ; If the tested instruction was indexed, the relevant index (X or Y) must
000000r 1 ; also be checked. Opposed to the flags, X and Y registers are still valid.
000000r 1 ;
000000r 1 ; versions:
000000r 1 ; 28-jul-2012 1st version distributed for testing
000000r 1 ; 29-jul-2012 fixed references to location 0, now #0
000000r 1 ; added license - GPLv3
000000r 1 ; 30-jul-2012 added configuration options
000000r 1 ; 01-aug-2012 added trap macro to allow user to change error handling
000000r 1 ; 01-dec-2012 fixed trap in branch field must be a branch
000000r 1 ; 02-mar-2013 fixed PLA flags not tested
000000r 1 ; 19-jul-2013 allowed ROM vectors to be loaded when load_data_direct = 0
000000r 1 ; added test sequence check to detect if tests jump their fence
000000r 1 ; 23-jul-2013 added RAM integrity check option
000000r 1 ; 16-aug-2013 added error report to standard output option
000000r 1 ; 13-dec-2014 added binary/decimal opcode table switch test
000000r 1 ; 14-dec-2014 improved relative address test
000000r 1 ; 23-aug-2015 added option to disable self modifying tests
000000r 1 ; 24-aug-2015 all self modifying immediate opcodes now execute in data RAM
000000r 1 ; added small branch offset pretest
000000r 1 ; 21-oct-2015 added option to disable decimal mode ADC & SBC tests
000000r 1 ; 04-dec-2017 fixed BRK only tested with interrupts enabled
000000r 1 ; added option to skip the remainder of a failing test
000000r 1 ; in report.i65
000000r 1 ; 05-jan-2020 fixed shifts not testing zero result and flag when last 1-bit
000000r 1 ; is shifted out
000000r 1
000000r 1 ; C O N F I G U R A T I O N
000000r 1
000000r 1 ;ROM_vectors writable (0=no, 1=yes)
000000r 1 ;if ROM vectors can not be used interrupts will not be trapped
000000r 1 ;as a consequence BRK can not be tested but will be emulated to test RTI
000000r 1 ROM_vectors = 1
000000r 1
000000r 1 ;load_data_direct (0=move from code segment, 1=load directly)
000000r 1 ;loading directly is preferred but may not be supported by your platform
000000r 1 ;0 produces only consecutive object code, 1 is not suitable for a binary image
000000r 1 load_data_direct = 1
000000r 1
000000r 1 ;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow
000000r 1 ;change) 2 requires extra code and is not recommended. SEI & CLI can only be
000000r 1 ;tested if you allow changing the interrupt status (I_flag = 3)
000000r 1 I_flag = 3
000000r 1
000000r 1 ;configure memory - try to stay away from memory used by the system
000000r 1 ;zero_page memory start address, $52 (82) consecutive Bytes required
000000r 1 ; add 2 if I_flag = 2
000000r 1 zero_page = $a
000000r 1
000000r 1 ;data_segment memory start address, $7B (123) consecutive Bytes required
000000r 1 ; check that this matches the linker configuration file
000000r 1 data_segment = $200
000000r 1 .if (data_segment & $ff) <> 0
000000r 1 .error "low byte of data_segment MUST be $00 !!"
000000r 1 .endif
000000r 1
000000r 1 ;code_segment memory start address, 13.1kB of consecutive space required
000000r 1 ; add 2.5 kB if I_flag = 2
000000r 1 ; check that this matches the linker configuration file
000000r 1 code_segment = $400
000000r 1
000000r 1 ;self modifying code may be disabled to allow running in ROM
000000r 1 ;0=part of the code is self modifying and must reside in RAM
000000r 1 ;1=tests disabled: branch range
000000r 1 disable_selfmod = 0
000000r 1
000000r 1 ;report errors through I/O channel (0=use standard self trap loops, 1=include
000000r 1 ;report.i65 as I/O channel, add 3.5 kB)
000000r 1 report = 0
000000r 1
000000r 1 ;RAM integrity test option. Checks for undesired RAM writes.
000000r 1 ;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k)
000000r 1 ;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM
000000r 1 ram_top = -1
000000r 1
000000r 1 ;disable test decimal mode ADC & SBC, 0=enable, 1=disable,
000000r 1 ;2=disable including decimal flag in processor status
000000r 1 disable_decimal = 0
000000r 1
000000r 1 ;macros for error & success traps to allow user modification
000000r 1 ;example:
000000r 1 ; .macro trap
000000r 1 ; jsr my_error_handler
000000r 1 ; .endmacro
000000r 1 ; .macro trap_eq
000000r 1 ; bne :+
000000r 1 ; trap ;failed equal (zero)
000000r 1 ;:
000000r 1 ; .endmacro
000000r 1 ;
000000r 1 ; my_error_handler should pop the calling address from the stack and report it.
000000r 1 ; putting larger portions of code (more than 3 bytes) inside the trap macro
000000r 1 ; may lead to branch range problems for some tests.
000000r 1 .if report = 0
000000r 1 .macro trap
000000r 1 jmp * ;failed anyway
000000r 1 .endmacro
000000r 1 .macro trap_eq
000000r 1 beq * ;failed equal (zero)
000000r 1 .endmacro
000000r 1 .macro trap_ne
000000r 1 bne * ;failed not equal (non zero)
000000r 1 .endmacro
000000r 1 .macro trap_cs
000000r 1 bcs * ;failed carry set
000000r 1 .endmacro
000000r 1 .macro trap_cc
000000r 1 bcc * ;failed carry clear
000000r 1 .endmacro
000000r 1 .macro trap_mi
000000r 1 bmi * ;failed minus (bit 7 set)
000000r 1 .endmacro
000000r 1 .macro trap_pl
000000r 1 bpl * ;failed plus (bit 7 clear)
000000r 1 .endmacro
000000r 1 .macro trap_vs
000000r 1 bvs * ;failed overflow set
000000r 1 .endmacro
000000r 1 .macro trap_vc
000000r 1 bvc * ;failed overflow clear
000000r 1 .endmacro
000000r 1 ; please observe that during the test the stack gets invalidated
000000r 1 ; therefore a RTS inside the success macro is not possible
000000r 1 .macro success
000000r 1 jmp * ;test passed, no errors
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if report = 1
000000r 1 .macro trap
000000r 1 jsr report_error
000000r 1 .endmacro
000000r 1 .macro trap_eq
000000r 1 bne :+
000000r 1 trap ;failed equal (zero)
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_ne
000000r 1 beq :+
000000r 1 trap ;failed not equal (non zero)
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_cs
000000r 1 bcc :+
000000r 1 trap ;failed carry set
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_cc
000000r 1 bcs :+
000000r 1 trap ;failed carry clear
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_mi
000000r 1 bpl :+
000000r 1 trap ;failed minus (bit 7 set)
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_pl
000000r 1 bmi :+
000000r 1 trap ;failed plus (bit 7 clear)
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_vs
000000r 1 bvc :+
000000r 1 trap ;failed overflow set
000000r 1 :
000000r 1 .endmacro
000000r 1 .macro trap_vc
000000r 1 bvs :+
000000r 1 trap ;failed overflow clear
000000r 1 :
000000r 1 .endmacro
000000r 1 ; please observe that during the test the stack gets invalidated
000000r 1 ; therefore a RTS inside the success macro is not possible
000000r 1 .macro success
000000r 1 jsr report_success
000000r 1 .endmacro
000000r 1 .endif
000000r 1
000000r 1 .define equ =
000000r 1
000000r 1 carry equ %00000001 ;flag bits in status
000000r 1 zero equ %00000010
000000r 1 intdis equ %00000100
000000r 1 decmode equ %00001000
000000r 1 break equ %00010000
000000r 1 reserv equ %00100000
000000r 1 overfl equ %01000000
000000r 1 minus equ %10000000
000000r 1
000000r 1 fc equ carry
000000r 1 fz equ zero
000000r 1 fzc equ carry+zero
000000r 1 fv equ overfl
000000r 1 fvz equ overfl+zero
000000r 1 fn equ minus
000000r 1 fnc equ minus+carry
000000r 1 fnz equ minus+zero
000000r 1 fnzc equ minus+zero+carry
000000r 1 fnv equ minus+overfl
000000r 1
000000r 1 fao equ break+reserv ;bits always on after PHP, BRK
000000r 1 fai equ fao+intdis ;+ forced interrupt disable
000000r 1 faod equ fao+decmode ;+ ignore decimal
000000r 1 faid equ fai+decmode ;+ ignore decimal
000000r 1 m8 equ $ff ;8 bit mask
000000r 1 m8i equ $ff&~intdis ;8 bit mask - interrupt disable
000000r 1
000000r 1 ;macros to allow masking of status bits.
000000r 1 ;masking test of decimal bit
000000r 1 ;masking of interrupt enable/disable on load and compare
000000r 1 ;masking of always on bits after PHP or BRK (unused & break) on compare
000000r 1 .if disable_decimal < 2
000000r 1 .if I_flag = 0
000000r 1 .macro load_flag p1
000000r 1 lda #p1&m8i ;force enable interrupts (mask I)
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 cmp #(p1|fao)&m8i ;I_flag is always enabled + always on bits
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 eor #(p1&m8i|fao) ;mask I, invert expected flags + always on bits
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if I_flag = 1
000000r 1 .macro load_flag p1
000000r 1 lda #p1|intdis ;force disable interrupts
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 cmp #(p1|fai)&m8 ;I_flag is always disabled + always on bits
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 eor #(p1|fai) ;invert expected flags + always on bits + I
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if I_flag = 2
000000r 1 .macro load_flag p1
000000r 1 lda #p1
000000r 1 ora flag_I_on ;restore I-flag
000000r 1 and flag_I_off
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 eor flag_I_on ;I_flag is never changed
000000r 1 cmp #(p1|fao)&m8i ;expected flags + always on bits, mask I
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 eor flag_I_on ;I_flag is never changed
000000r 1 eor #(p1&m8i|fao) ;mask I, invert expected flags + always on bits
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if I_flag = 3
000000r 1 .macro load_flag p1
000000r 1 lda #p1 ;allow test to change I-flag (no mask)
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 cmp #(p1|fao)&m8 ;expected flags + always on bits
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 eor #p1|fao ;invert expected flags + always on bits
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .else
000000r 1 .if I_flag = 0
000000r 1 .macro load_flag p1
000000r 1 lda #p1&m8i ;force enable interrupts (mask I)
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 cmp #(p1|faod)&m8i ;I_flag is always enabled + always on bits
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 eor #(p1&m8i|faod) ;mask I, invert expected flags + always on bits
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if I_flag = 1
000000r 1 .macro load_flag p1
000000r 1 lda #p1|intdis ;force disable interrupts
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 cmp #(p1|faid)&m8 ;I_flag is always disabled + always on bits
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 eor #(p1|faid) ;invert expected flags + always on bits + I
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if I_flag = 2
000000r 1 .macro load_flag p1
000000r 1 lda #p1
000000r 1 ora flag_I_on ;restore I-flag
000000r 1 and flag_I_off
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 eor flag_I_on ;I_flag is never changed
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 cmp #(p1|faod)&m8i ;expected flags + always on bits, mask I
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 eor flag_I_on ;I_flag is never changed
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 eor #(p1&m8i|faod) ;mask I, invert expected flags + always on bits
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .if I_flag = 3
000000r 1 .macro load_flag p1
000000r 1 lda #p1 ;allow test to change I-flag (no mask)
000000r 1 .endmacro
000000r 1 .macro cmp_flag p1
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 cmp #(p1|faod)&m8 ;expected flags + always on bits
000000r 1 .endmacro
000000r 1 .macro eor_flag p1
000000r 1 ora #decmode ;ignore decimal mode bit
000000r 1 eor #p1|faod ;invert expected flags + always on bits
000000r 1 .endmacro
000000r 1 .endif
000000r 1 .endif
000000r 1
000000r 1 ;macros to set (register|memory|zeropage) & status
000000r 1 .macro set_stat p1 ;setting flags in the processor status register
000000r 1 load_flag p1
000000r 1 pha ;use stack to load status
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_a p1,p2 ;precharging accu & status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda #p1 ;precharge accu
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_x p1,p2 ;precharging index & status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 ldx #p1 ;precharge index x
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_y p1,p2 ;precharging index & status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 ldy #p1 ;precharge index y
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_ax p1,p2 ;precharging indexed accu & immediate status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda p1,x ;precharge accu
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_ay p1,p2 ;precharging indexed accu & immediate status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda p1,y ;precharge accu
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_z p1,p2 ;precharging indexed zp & immediate status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda p1,x ;load to zeropage
000000r 1 sta zpt
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_zx p1,p2 ;precharging zp,x & immediate status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda p1,x ;load to indexed zeropage
000000r 1 sta zpt,x
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_abs p1,p2 ;precharging indexed memory & immediate status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda p1,x ;load to memory
000000r 1 sta abst
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 .macro set_absx p1,p2 ;precharging abs,x & immediate status
000000r 1 load_flag p2
000000r 1 pha ;use stack to load status
000000r 1 lda p1,x ;load to indexed memory
000000r 1 sta abst,x
000000r 1 plp
000000r 1 .endmacro
000000r 1
000000r 1 ;macros to test (register|memory|zeropage) & status & (mask)
000000r 1 .macro tst_stat p1 ;testing flags in the processor status register
000000r 1 php ;save status
000000r 1 pla ;use stack to retrieve status
000000r 1 pha
000000r 1 cmp_flag p1
000000r 1 trap_ne
000000r 1 plp ;restore status
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_a p1,p2 ;testing result in accu & flags
000000r 1 php ;save flags
000000r 1 cmp #p1 ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 pha
000000r 1 cmp_flag p2
000000r 1 trap_ne
000000r 1 plp ;restore status
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_x p1,p2 ;testing result in x index & flags
000000r 1 php ;save flags
000000r 1 cpx #p1 ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 pha
000000r 1 cmp_flag p2
000000r 1 trap_ne
000000r 1 plp ;restore status
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_y p1,p2 ;testing result in y index & flags
000000r 1 php ;save flags
000000r 1 cpy #p1 ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 pha
000000r 1 cmp_flag p2
000000r 1 trap_ne
000000r 1 plp ;restore status
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_ax p1,p2,p3 ;indexed testing result in accu & flags
000000r 1 php ;save flags
000000r 1 cmp p1,x ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 eor_flag p3
000000r 1 cmp p2,x ;test flags
000000r 1 trap_ne ;
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_ay p1,p2,p3 ;indexed testing result in accu & flags
000000r 1 php ;save flags
000000r 1 cmp p1,y ;test result
000000r 1 trap_ne ;
000000r 1 pla ;load status
000000r 1 eor_flag p3
000000r 1 cmp p2,y ;test flags
000000r 1 trap_ne
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_z p1,p2,p3 ;indexed testing result in zp & flags
000000r 1 php ;save flags
000000r 1 lda zpt
000000r 1 cmp p1,x ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 eor_flag p3
000000r 1 cmp p2,x ;test flags
000000r 1 trap_ne
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_zx p1,p2,p3 ;testing result in zp,x & flags
000000r 1 php ;save flags
000000r 1 lda zpt,x
000000r 1 cmp p1,x ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 eor_flag p3
000000r 1 cmp p2,x ;test flags
000000r 1 trap_ne
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_abs p1,p2,p3 ;indexed testing result in memory & flags
000000r 1 php ;save flags
000000r 1 lda abst
000000r 1 cmp p1,x ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 eor_flag p3
000000r 1 cmp p2,x ;test flags
000000r 1 trap_ne
000000r 1 .endmacro
000000r 1
000000r 1 .macro tst_absx p1,p2,p3 ;testing result in abs,x & flags
000000r 1 php ;save flags
000000r 1 lda abst,x
000000r 1 cmp p1,x ;test result
000000r 1 trap_ne
000000r 1 pla ;load status
000000r 1 eor_flag p3
000000r 1 cmp p2,x ;test flags
000000r 1 trap_ne
000000r 1 .endmacro
000000r 1
000000r 1 ; RAM integrity test
000000r 1 ; verifies that none of the previous tests has altered RAM outside of the
000000r 1 ; designated write areas.
000000r 1 ; uses zpt word as indirect pointer, zpt+2 word as checksum
000000r 1 .if ram_top > -1
000000r 1 check_ram macro
000000r 1 cld
000000r 1 lda #0
000000r 1 sta zpt ;set low byte of indirect pointer
000000r 1 sta zpt+3 ;checksum high byte
000000r 1 .if disable_selfmod = 0
000000r 1 sta range_adr ;reset self modifying code
000000r 1 .endif
000000r 1 clc
000000r 1 ldx #zp_bss-zero_page ;zeropage - write test area
000000r 1 ccs3: adc zero_page,x
000000r 1 bcc ccs2
000000r 1 inc zpt+3 ;carry to high byte
000000r 1 clc
000000r 1 ccs2: inx
000000r 1 bne ccs3
000000r 1 ldx #hi(abs1) ;set high byte of indirect pointer
000000r 1 stx zpt+1
000000r 1 ldy #lo(abs1) ;data after write & execute test area
000000r 1 ccs5: adc (zpt),y
000000r 1 bcc ccs4
000000r 1 inc zpt+3 ;carry to high byte
000000r 1 clc
000000r 1 ccs4: iny
000000r 1 bne ccs5
000000r 1 inx ;advance RAM high address
000000r 1 stx zpt+1
000000r 1 cpx #ram_top
000000r 1 bne ccs5
000000r 1 sta zpt+2 ;checksum low is
000000r 1 cmp ram_chksm ;checksum low expected
000000r 1 trap_ne ;checksum mismatch
000000r 1 lda zpt+3 ;checksum high is
000000r 1 cmp ram_chksm+1 ;checksum high expected
000000r 1 trap_ne ;checksum mismatch
000000r 1 .endmacro
000000r 1 .else
000000r 1 .macro check_ram
000000r 1 ;RAM check disabled - RAM size not set
000000r 1 .endmacro
000000r 1 .endif
000000r 1
000000r 1 .macro next_test ;make sure, tests don't jump the fence
000000r 1 lda test_case ;previous test
000000r 1 cmp #test_num
000000r 1 trap_ne ;test is out of sequence
000000r 1 test_num .set test_num + 1
000000r 1 lda #test_num ;*** next tests' number
000000r 1 sta test_case
000000r 1 ;check_ram ;uncomment to find altered RAM after each test
000000r 1 .endmacro
000000r 1
000000r 1 .ZEROPAGE
000000r 1 00 00 00 00 .res zero_page, 0
000004r 1 00 00 00 00
000008r 1 00 00
00000Ar 1 .org zero_page
00000A 1
00000A 1 ;break test interrupt save
00000A 1 00 irq_a: .res 1,0 ;a register
00000B 1 00 irq_x: .res 1,0 ;x register
00000C 1 .if I_flag = 2
00000C 1 ;masking for I bit in status
00000C 1 flag_I_on: .res 1,0 ;or mask to load flags
00000C 1 flag_I_off: .res 1,0 ;and mask to load flags
00000C 1 .endif
00000C 1 zpt: ;6 bytes store/modify test area
00000C 1 ;add/subtract operand generation and result/flag prediction
00000C 1 00 adfc: .res 1,0 ;carry flag before op
00000D 1 00 ad1: .res 1,0 ;operand 1 - accumulator
00000E 1 00 ad2: .res 1,0 ;operand 2 - memory / immediate
00000F 1 00 adrl: .res 1,0 ;expected result bits 0-7
000010 1 00 adrh: .res 1,0 ;expected result bit 8 (carry)
000011 1 00 adrf: .res 1,0 ;expected flags NV0000ZC (only binary mode)
000012 1 00 sb2: .res 1,0 ;operand 2 complemented for subtract
000013 1 zp_bss:
000013 1 80 01 zps: .byte $80,1 ;additional shift pattern to test zero result & flag
000015 1 C3 82 41 00 zp1: .byte $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
000019 1 7F zp7f: .byte $7f ;test pattern for compare
00001A 1 ;logical zeropage operands
00001A 1 00 1F 71 80 zpOR: .byte 0,$1f,$71,$80 ;test pattern for OR
00001E 1 0F FF 7F 80 zpAN: .byte $0f,$ff,$7f,$80 ;test pattern for AND
000022 1 FF 0F 8F 8F zpEO: .byte $ff,$0f,$8f,$8f ;test pattern for EOR
000026 1 ;indirect addressing pointers
000026 1 18 02 ind1: .word abs1 ;indirect pointer to pattern in absolute memory
000028 1 19 02 .word abs1+1
00002A 1 1A 02 .word abs1+2
00002C 1 1B 02 .word abs1+3
00002E 1 1C 02 .word abs7f
000030 1 20 01 inw1: .word abs1-$f8 ;indirect pointer for wrap-test pattern
000032 1 03 02 indt: .word abst ;indirect pointer to store area in absolute memory
000034 1 04 02 .word abst+1
000036 1 05 02 .word abst+2
000038 1 06 02 .word abst+3
00003A 1 0B 01 inwt: .word abst-$f8 ;indirect pointer for wrap-test store
00003C 1 5F 02 indAN: .word absAN ;indirect pointer to AND pattern in absolute memory
00003E 1 60 02 .word absAN+1
000040 1 61 02 .word absAN+2
000042 1 62 02 .word absAN+3
000044 1 63 02 indEO: .word absEO ;indirect pointer to EOR pattern in absolute memory
000046 1 64 02 .word absEO+1
000048 1 65 02 .word absEO+2
00004A 1 66 02 .word absEO+3
00004C 1 5B 02 indOR: .word absOR ;indirect pointer to OR pattern in absolute memory
00004E 1 5C 02 .word absOR+1
000050 1 5D 02 .word absOR+2
000052 1 5E 02 .word absOR+3
000054 1 ;add/subtract indirect pointers
000054 1 03 02 adi2: .word ada2 ;indirect pointer to operand 2 in absolute memory
000056 1 04 02 sbi2: .word sba2 ;indirect pointer to complemented operand 2 (SBC)
000058 1 04 01 adiy2: .word ada2-$ff ;with offset for indirect indexed
00005A 1 05 01 sbiy2: .word sba2-$ff
00005C 1 zp_bss_end:
00005C 1
00005C 1 .DATA
00005C 1 .org data_segment
000200 1
000200 1 00 test_case: .res 1,0 ;current test number
000201 1 00 00 ram_chksm: .res 2,0 ;checksum for RAM integrity test
000203 1 ;add/subtract operand copy - abs tests write area
000203 1 abst: ;6 bytes store/modify test area
000203 1 00 ada2: .res 1,0 ;operand 2
000204 1 00 sba2: .res 1,0 ;operand 2 complemented for subtract
000205 1 00 00 00 00 .res 4,0 ;fill remaining bytes
000209 1 data_bss:
000209 1 .if load_data_direct = 1
000209 1 29 00 ex_andi:and #0 ;execute immediate opcodes
00020B 1 60 rts
00020C 1 49 00 ex_eori:eor #0 ;execute immediate opcodes
00020E 1 60 rts
00020F 1 09 00 ex_orai:ora #0 ;execute immediate opcodes
000211 1 60 rts
000212 1 69 00 ex_adci:adc #0 ;execute immediate opcodes
000214 1 60 rts
000215 1 E9 00 ex_sbci:sbc #0 ;execute immediate opcodes
000217 1 60 rts
000218 1 .else
000218 1 ex_andi:.res 3
000218 1 ex_eori:.res 3
000218 1 ex_orai:.res 3
000218 1 ex_adci:.res 3
000218 1 ex_sbci:.res 3
000218 1 .endif
000218 1 ;zps .byte $80,1 ;additional shift patterns test zero result & flag
000218 1 C3 82 41 00 abs1: .byte $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
00021C 1 7F abs7f: .byte $7f ;test pattern for compare
00021D 1 ;loads
00021D 1 80 80 00 02 fLDx: .byte fn,fn,0,fz ;expected flags for load
000221 1 ;shifts
000221 1 rASL: ;expected result ASL & ROL -carry
000221 1 00 02 86 04 rROL: .byte 0,2,$86,$04,$82,0
000225 1 82 00
000227 1 01 03 87 05 rROLc: .byte 1,3,$87,$05,$83,1 ;expected result ROL +carry
00022B 1 83 01
00022D 1 rLSR: ;expected result LSR & ROR -carry
00022D 1 40 00 61 41 rROR: .byte $40,0,$61,$41,$20,0
000231 1 20 00
000233 1 C0 80 E1 C1 rRORc: .byte $c0,$80,$e1,$c1,$a0,$80 ;expected result ROR +carry
000237 1 A0 80
000239 1 fASL: ;expected flags for shifts
000239 1 03 00 81 01 fROL: .byte fzc,0,fnc,fc,fn,fz ;no carry in
00023D 1 80 02
00023F 1 01 00 81 01 fROLc: .byte fc,0,fnc,fc,fn,0 ;carry in
000243 1 80 00
000245 1 fLSR:
000245 1 00 03 01 00 fROR: .byte 0,fzc,fc,0,fc,fz ;no carry in
000249 1 01 02
00024B 1 80 81 81 80 fRORc: .byte fn,fnc,fnc,fn,fnc,fn ;carry in
00024F 1 81 80
000251 1 ;increments (decrements)
000251 1 7F 80 FF 00 rINC: .byte $7f,$80,$ff,0,1 ;expected result for INC/DEC
000255 1 01
000256 1 00 80 80 02 fINC: .byte 0,fn,fn,fz,0 ;expected flags for INC/DEC
00025A 1 00
00025B 1 ;logical memory operand
00025B 1 00 1F 71 80 absOR: .byte 0,$1f,$71,$80 ;test pattern for OR
00025F 1 0F FF 7F 80 absAN: .byte $0f,$ff,$7f,$80 ;test pattern for AND
000263 1 FF 0F 8F 8F absEO: .byte $ff,$0f,$8f,$8f ;test pattern for EOR
000267 1 ;logical accu operand
000267 1 00 F1 1F 00 absORa: .byte 0,$f1,$1f,0 ;test pattern for OR
00026B 1 F0 FF FF FF absANa: .byte $f0,$ff,$ff,$ff ;test pattern for AND
00026F 1 FF F0 F0 0F absEOa: .byte $ff,$f0,$f0,$0f ;test pattern for EOR
000273 1 ;logical results
000273 1 00 FF 7F 80 absrlo: .byte 0,$ff,$7f,$80
000277 1 02 80 00 80 absflo: .byte fz,fn,0,fn
00027B 1 data_bss_end:
00027B 1
00027B 1
00027B 1 .CODE
00027B 1 .org code_segment
000400 1 .P02 ; disable 65SC02, 65C02 and 65816 instructions
000400 1 D8 start: cld
000401 1 A2 FF ldx #$ff
000403 1 9A txs
000404 1 A9 00 lda #0 ;*** test 0 = initialize
000406 1 8D 00 02 sta test_case
000409 1 test_num .set 0
000409 1
000409 1 ;stop interrupts before initializing BSS
000409 1 .if I_flag = 1
000409 1 sei
000409 1 .endif
000409 1
000409 1 ;initialize I/O for report channel
000409 1 .if report = 1
000409 1 jsr report_init
000409 1 .endif
000409 1
000409 1 ;pretest small branch offset
000409 1 A2 05 ldx #5
00040B 1 4C 33 04 jmp psb_test
00040E 1 psb_bwok:
00040E 1 A0 05 ldy #5
000410 1 D0 08 bne psb_forw
000412 1 4C 12 04 trap ;branch should be taken
000415 1 88 dey ;forward landing zone
000416 1 88 dey
000417 1 88 dey
000418 1 88 dey
000419 1 88 dey
00041A 1 psb_forw:
00041A 1 88 dey
00041B 1 88 dey
00041C 1 88 dey
00041D 1 88 dey
00041E 1 88 dey
00041F 1 F0 17 beq psb_fwok
000421 1 4C 21 04 trap ;forward offset
000424 1
000424 1 CA dex ;backward landing zone
000425 1 CA dex
000426 1 CA dex
000427 1 CA dex
000428 1 CA dex
000429 1 psb_back:
000429 1 CA dex
00042A 1 CA dex
00042B 1 CA dex
00042C 1 CA dex
00042D 1 CA dex
00042E 1 F0 DE beq psb_bwok
000430 1 4C 30 04 trap ;backward offset
000433 1 psb_test:
000433 1 D0 F4 bne psb_back
000435 1 4C 35 04 trap ;branch should be taken
000438 1 psb_fwok:
000438 1
000438 1 ;initialize BSS segment
000438 1 .if load_data_direct <> 1
000438 1 ldx #zp_end-zp_init-1
000438 1 ld_zp: lda zp_init,x
000438 1 sta zp_bss,x
000438 1 dex
000438 1 bpl ld_zp
000438 1 ldx #data_end-data_init-1
000438 1 ld_data:lda data_init,x
000438 1 sta data_bss,x
000438 1 dex
000438 1 bpl ld_data
000438 1 .if ROM_vectors = 1
000438 1 ldx #5
000438 1 ld_vect:lda vec_init,x
000438 1 sta vec_bss,x
000438 1 dex
000438 1 bpl ld_vect
000438 1 .endif
000438 1 .endif
000438 1
000438 1 ;retain status of interrupt flag
000438 1 .if I_flag = 2
000438 1 php
000438 1 pla
000438 1 and #4 ;isolate flag
000438 1 sta flag_I_on ;or mask
000438 1 eor #lo(~4) ;reverse
000438 1 sta flag_I_off ;and mask
000438 1 .endif
000438 1
000438 1 ;generate checksum for RAM integrity test
000438 1 .if ram_top > -1
000438 1 lda #0
000438 1 sta zpt ;set low byte of indirect pointer
000438 1 sta ram_chksm+1 ;checksum high byte
000438 1 .if disable_selfmod = 0
000438 1 sta range_adr ;reset self modifying code
000438 1 .endif
000438 1 clc
000438 1 ldx #zp_bss-zero_page ;zeropage - write test area
000438 1 gcs3: adc zero_page,x
000438 1 bcc gcs2
000438 1 inc ram_chksm+1 ;carry to high byte
000438 1 clc
000438 1 gcs2: inx
000438 1 bne gcs3
000438 1 ldx #hi(abs1) ;set high byte of indirect pointer
000438 1 stx zpt+1
000438 1 ldy #lo(abs1) ;data after write & execute test area
000438 1 gcs5: adc (zpt),y
000438 1 bcc gcs4
000438 1 inc ram_chksm+1 ;carry to high byte
000438 1 clc
000438 1 gcs4: iny
000438 1 bne gcs5
000438 1 inx ;advance RAM high address
000438 1 stx zpt+1
000438 1 cpx #ram_top
000438 1 bne gcs5
000438 1 sta ram_chksm ;checksum complete
000438 1 .endif
000438 1 AD 00 02 C9 next_test
00043C 1 00 D0 FE A9
000440 1 01 8D 00 02
000444 1
000444 1 .if disable_selfmod = 0
000444 1 ;testing relative addressing with BEQ
000444 1 A0 FE ldy #$fe ;testing maximum range, not -1/-2 (invalid/self adr)
000446 1 range_loop:
000446 1 88 dey ;next relative address
000447 1 98 tya
000448 1 AA tax ;precharge count to end of loop
000449 1 10 08 bpl range_fw ;calculate relative address
00044B 1 18 clc ;avoid branch self or to relative address of branch
00044C 1 69 02 adc #2
00044E 1 EA nop ;offset landing zone - tolerate +/-5 offset to branch
00044F 1 EA nop
000450 1 EA nop
000451 1 EA nop
000452 1 EA nop
000453 1 range_fw:
000453 1 EA nop
000454 1 EA nop
000455 1 EA nop
000456 1 EA nop
000457 1 EA nop
000458 1 49 7F eor #$7f ;complement except sign
00045A 1 8D E6 04 sta range_adr ;load into test target
00045D 1 A9 00 lda #0 ;should set zero flag in status register
00045F 1 4C E5 04 jmp range_op
000462 1
000462 1 CA dex ; offset landing zone - backward branch too far
000463 1 CA dex
000464 1 CA dex
000465 1 CA dex
000466 1 CA dex
000467 1 ;relative address target field with branch under test in the middle
000467 1 CA dex ;-128 - max backward
000468 1 CA dex
000469 1 CA dex
00046A 1 CA dex
00046B 1 CA dex
00046C 1 CA dex
00046D 1 CA dex
00046E 1 CA dex
00046F 1 CA dex ;-120
000470 1 CA dex
000471 1 CA dex
000472 1 CA dex
000473 1 CA dex
000474 1 CA dex
000475 1 CA dex
000476 1 CA dex
000477 1 CA dex
000478 1 CA dex
000479 1 CA dex ;-110
00047A 1 CA dex
00047B 1 CA dex
00047C 1 CA dex
00047D 1 CA dex
00047E 1 CA dex
00047F 1 CA dex
000480 1 CA dex
000481 1 CA dex
000482 1 CA dex
000483 1 CA dex ;-100
000484 1 CA dex
000485 1 CA dex
000486 1 CA dex
000487 1 CA dex
000488 1 CA dex
000489 1 CA dex
00048A 1 CA dex
00048B 1 CA dex
00048C 1 CA dex
00048D 1 CA dex ;-90
00048E 1 CA dex
00048F 1 CA dex
000490 1 CA dex
000491 1 CA dex
000492 1 CA dex
000493 1 CA dex
000494 1 CA dex
000495 1 CA dex
000496 1 CA dex
000497 1 CA dex ;-80
000498 1 CA dex
000499 1 CA dex
00049A 1 CA dex
00049B 1 CA dex
00049C 1 CA dex
00049D 1 CA dex
00049E 1 CA dex
00049F 1 CA dex
0004A0 1 CA dex
0004A1 1 CA dex ;-70
0004A2 1 CA dex
0004A3 1 CA dex
0004A4 1 CA dex
0004A5 1 CA dex
0004A6 1 CA dex
0004A7 1 CA dex
0004A8 1 CA dex
0004A9 1 CA dex
0004AA 1 CA dex
0004AB 1 CA dex ;-60
0004AC 1 CA dex
0004AD 1 CA dex
0004AE 1 CA dex
0004AF 1 CA dex
0004B0 1 CA dex
0004B1 1 CA dex
0004B2 1 CA dex
0004B3 1 CA dex
0004B4 1 CA dex
0004B5 1 CA dex ;-50
0004B6 1 CA dex
0004B7 1 CA dex
0004B8 1 CA dex
0004B9 1 CA dex
0004BA 1 CA dex
0004BB 1 CA dex
0004BC 1 CA dex
0004BD 1 CA dex
0004BE 1 CA dex
0004BF 1 CA dex ;-40
0004C0 1 CA dex
0004C1 1 CA dex
0004C2 1 CA dex
0004C3 1 CA dex
0004C4 1 CA dex
0004C5 1 CA dex
0004C6 1 CA dex
0004C7 1 CA dex
0004C8 1 CA dex
0004C9 1 CA dex ;-30
0004CA 1 CA dex
0004CB 1 CA dex
0004CC 1 CA dex
0004CD 1 CA dex
0004CE 1 CA dex
0004CF 1 CA dex
0004D0 1 CA dex
0004D1 1 CA dex
0004D2 1 CA dex
0004D3 1 CA dex ;-20
0004D4 1 CA dex
0004D5 1 CA dex
0004D6 1 CA dex
0004D7 1 CA dex
0004D8 1 CA dex
0004D9 1 CA dex
0004DA 1 CA dex
0004DB 1 CA dex
0004DC 1 CA dex
0004DD 1 CA dex ;-10
0004DE 1 CA dex
0004DF 1 CA dex
0004E0 1 CA dex
0004E1 1 CA dex
0004E2 1 CA dex
0004E3 1 CA dex
0004E4 1 CA dex ;-3
0004E5 1 range_op: ;test target with zero flag=0, z=1 if previous dex
0004E5 1 range_adr = *+1 ;modifiable relative address
0004E5 1 F0 3E beq *+64 ;+64 if called without modification
0004E7 1 CA dex ;+0
0004E8 1 CA dex
0004E9 1 CA dex
0004EA 1 CA dex
0004EB 1 CA dex
0004EC 1 CA dex
0004ED 1 CA dex
0004EE 1 CA dex
0004EF 1 CA dex
0004F0 1 CA dex
0004F1 1 CA dex ;+10
0004F2 1 CA dex
0004F3 1 CA dex
0004F4 1 CA dex
0004F5 1 CA dex
0004F6 1 CA dex
0004F7 1 CA dex
0004F8 1 CA dex
0004F9 1 CA dex
0004FA 1 CA dex
0004FB 1 CA dex ;+20
0004FC 1 CA dex
0004FD 1 CA dex
0004FE 1 CA dex
0004FF 1 CA dex
000500 1 CA dex
000501 1 CA dex
000502 1 CA dex
000503 1 CA dex
000504 1 CA dex
000505 1 CA dex ;+30
000506 1 CA dex
000507 1 CA dex
000508 1 CA dex
000509 1 CA dex
00050A 1 CA dex
00050B 1 CA dex
00050C 1 CA dex
00050D 1 CA dex
00050E 1 CA dex
00050F 1 CA dex ;+40
000510 1 CA dex
000511 1 CA dex
000512 1 CA dex
000513 1 CA dex
000514 1 CA dex
000515 1 CA dex
000516 1 CA dex
000517 1 CA dex
000518 1 CA dex
000519 1 CA dex ;+50
00051A 1 CA dex
00051B 1 CA dex
00051C 1 CA dex
00051D 1 CA dex
00051E 1 CA dex
00051F 1 CA dex
000520 1 CA dex
000521 1 CA dex
000522 1 CA dex
000523 1 CA dex ;+60
000524 1 CA dex
000525 1 CA dex
000526 1 CA dex
000527 1 CA dex
000528 1 CA dex
000529 1 CA dex
00052A 1 CA dex
00052B 1 CA dex
00052C 1 CA dex
00052D 1 CA dex ;+70
00052E 1 CA dex
00052F 1 CA dex
000530 1 CA dex
000531 1 CA dex
000532 1 CA dex
000533 1 CA dex
000534 1 CA dex
000535 1 CA dex
000536 1 CA dex
000537 1 CA dex ;+80
000538 1 CA dex
000539 1 CA dex
00053A 1 CA dex
00053B 1 CA dex
00053C 1 CA dex
00053D 1 CA dex
00053E 1 CA dex
00053F 1 CA dex
000540 1 CA dex
000541 1 CA dex ;+90
000542 1 CA dex
000543 1 CA dex
000544 1 CA dex
000545 1 CA dex
000546 1 CA dex
000547 1 CA dex
000548 1 CA dex
000549 1 CA dex
00054A 1 CA dex
00054B 1 CA dex ;+100
00054C 1 CA dex
00054D 1 CA dex
00054E 1 CA dex
00054F 1 CA dex
000550 1 CA dex
000551 1 CA dex
000552 1 CA dex
000553 1 CA dex
000554 1 CA dex
000555 1 CA dex ;+110
000556 1 CA dex
000557 1 CA dex
000558 1 CA dex
000559 1 CA dex
00055A 1 CA dex
00055B 1 CA dex
00055C 1 CA dex
00055D 1 CA dex
00055E 1 CA dex
00055F 1 CA dex ;+120
000560 1 CA dex
000561 1 CA dex
000562 1 CA dex
000563 1 CA dex
000564 1 CA dex
000565 1 CA dex
000566 1 EA nop ;offset landing zone - forward branch too far
000567 1 EA nop
000568 1 EA nop
000569 1 EA nop
00056A 1 EA nop
00056B 1 F0 08 beq range_ok ;+127 - max forward
00056D 1 4C 6D 05 trap ; bad range
000570 1 EA nop ;offset landing zone - tolerate +/-5 offset to branch
000571 1 EA nop
000572 1 EA nop
000573 1 EA nop
000574 1 EA nop
000575 1 range_ok:
000575 1 EA nop
000576 1 EA nop
000577 1 EA nop
000578 1 EA nop
000579 1 EA nop
00057A 1 C0 00 cpy #0
00057C 1 F0 03 beq range_end
00057E 1 4C 46 04 jmp range_loop
000581 1 range_end: ;range test successful
000581 1 .endif
000581 1 AD 00 02 C9 next_test
000585 1 01 D0 FE A9
000589 1 02 8D 00 02
00058D 1
00058D 1 ;partial test BNE & CMP, CPX, CPY immediate
00058D 1 C0 01 cpy #1 ;testing BNE true
00058F 1 D0 03 bne test_bne
000591 1 4C 91 05 trap
000594 1 test_bne:
000594 1 A9 00 lda #0
000596 1 C9 00 cmp #0 ;test compare immediate
000598 1 D0 FE trap_ne
00059A 1 90 FE trap_cc
00059C 1 30 FE trap_mi
00059E 1 C9 01 cmp #1
0005A0 1 F0 FE trap_eq
0005A2 1 B0 FE trap_cs
0005A4 1 10 FE trap_pl
0005A6 1 AA tax
0005A7 1 E0 00 cpx #0 ;test compare x immediate
0005A9 1 D0 FE trap_ne
0005AB 1 90 FE trap_cc
0005AD 1 30 FE trap_mi
0005AF 1 E0 01 cpx #1
0005B1 1 F0 FE trap_eq
0005B3 1 B0 FE trap_cs
0005B5 1 10 FE trap_pl
0005B7 1 A8 tay
0005B8 1 C0 00 cpy #0 ;test compare y immediate
0005BA 1 D0 FE trap_ne
0005BC 1 90 FE trap_cc
0005BE 1 30 FE trap_mi
0005C0 1 C0 01 cpy #1
0005C2 1 F0 FE trap_eq
0005C4 1 B0 FE trap_cs
0005C6 1 10 FE trap_pl
0005C8 1 AD 00 02 C9 next_test
0005CC 1 02 D0 FE A9
0005D0 1 03 8D 00 02
0005D4 1 ;testing stack operations PHA PHP PLA PLP
0005D4 1
0005D4 1 A2 FF ldx #$ff ;initialize stack
0005D6 1 9A txs
0005D7 1 A9 55 lda #$55
0005D9 1 48 pha
0005DA 1 A9 AA lda #$aa
0005DC 1 48 pha
0005DD 1 CD FE 01 cmp $1fe ;on stack ?
0005E0 1 D0 FE trap_ne
0005E2 1 BA tsx
0005E3 1 8A txa ;overwrite accu
0005E4 1 C9 FD cmp #$fd ;sp decremented?
0005E6 1 D0 FE trap_ne
0005E8 1 68 pla
0005E9 1 C9 AA cmp #$aa ;successful retreived from stack?
0005EB 1 D0 FE trap_ne
0005ED 1 68 pla
0005EE 1 C9 55 cmp #$55
0005F0 1 D0 FE trap_ne
0005F2 1 CD FF 01 cmp $1ff ;remains on stack?
0005F5 1 D0 FE trap_ne
0005F7 1 BA tsx
0005F8 1 E0 FF cpx #$ff ;sp incremented?
0005FA 1 D0 FE trap_ne
0005FC 1 AD 00 02 C9 next_test
000600 1 03 D0 FE A9
000604 1 04 8D 00 02
000608 1
000608 1 ;testing branch decisions BPL BMI BVC BVS BCC BCS BNE BEQ
000608 1 A9 FF 48 28 set_stat $ff ;all on
00060C 1 10 1A bpl nbr1 ;branches should not be taken
00060E 1 50 1B bvc nbr2
000610 1 90 1C bcc nbr3
000612 1 D0 1D bne nbr4
000614 1 30 03 bmi br1 ;branches should be taken
000616 1 4C 16 06 trap
000619 1 70 03 br1: bvs br2
00061B 1 4C 1B 06 trap
00061E 1 B0 03 br2: bcs br3
000620 1 4C 20 06 trap
000623 1 F0 0F br3: beq br4
000625 1 4C 25 06 trap
000628 1 nbr1:
000628 1 4C 28 06 trap ;previous bpl taken
00062B 1 nbr2:
00062B 1 4C 2B 06 trap ;previous bvc taken
00062E 1 nbr3:
00062E 1 4C 2E 06 trap ;previous bcc taken
000631 1 nbr4:
000631 1 4C 31 06 trap ;previous bne taken
000634 1 08 br4: php
000635 1 BA tsx
000636 1 E0 FE cpx #$fe ;sp after php?
000638 1 D0 FE trap_ne
00063A 1 68 pla
00063B 1 C9 FF cmp_flag $ff ;returned all flags on?
00063D 1 D0 FE trap_ne
00063F 1 BA tsx
000640 1 E0 FF cpx #$ff ;sp after php?
000642 1 D0 FE trap_ne
000644 1 A9 00 48 28 set_stat 0 ;all off
000648 1 30 1A bmi nbr11 ;branches should not be taken
00064A 1 70 1B bvs nbr12
00064C 1 B0 1C bcs nbr13
00064E 1 F0 1D beq nbr14
000650 1 10 03 bpl br11 ;branches should be taken
000652 1 4C 52 06 trap
000655 1 50 03 br11: bvc br12
000657 1 4C 57 06 trap
00065A 1 90 03 br12: bcc br13
00065C 1 4C 5C 06 trap
00065F 1 D0 0F br13: bne br14
000661 1 4C 61 06 trap
000664 1 nbr11:
000664 1 4C 64 06 trap ;previous bmi taken
000667 1 nbr12:
000667 1 4C 67 06 trap ;previous bvs taken
00066A 1 nbr13:
00066A 1 4C 6A 06 trap ;previous bcs taken
00066D 1 nbr14:
00066D 1 4C 6D 06 trap ;previous beq taken
000670 1 08 br14: php
000671 1 68 pla
000672 1 C9 30 cmp_flag 0 ;flags off except break (pushed by sw) + reserved?
000674 1 D0 FE trap_ne
000676 1 ;crosscheck flags
000676 1 A9 02 48 28 set_stat zero
00067A 1 D0 02 bne brzs1
00067C 1 F0 03 beq brzs2
00067E 1 brzs1:
00067E 1 4C 7E 06 trap ;branch zero/non zero
000681 1 B0 02 brzs2: bcs brzs3
000683 1 90 03 bcc brzs4
000685 1 brzs3:
000685 1 4C 85 06 trap ;branch carry/no carry
000688 1 30 02 brzs4: bmi brzs5
00068A 1 10 03 bpl brzs6
00068C 1 brzs5:
00068C 1 4C 8C 06 trap ;branch minus/plus
00068F 1 70 02 brzs6: bvs brzs7
000691 1 50 03 bvc brzs8
000693 1 brzs7:
000693 1 4C 93 06 trap ;branch overflow/no overflow
000696 1 brzs8:
000696 1 A9 01 48 28 set_stat carry
00069A 1 F0 02 beq brcs1
00069C 1 D0 03 bne brcs2
00069E 1 brcs1:
00069E 1 4C 9E 06 trap ;branch zero/non zero
0006A1 1 90 02 brcs2: bcc brcs3
0006A3 1 B0 03 bcs brcs4
0006A5 1 brcs3:
0006A5 1 4C A5 06 trap ;branch carry/no carry
0006A8 1 30 02 brcs4: bmi brcs5
0006AA 1 10 03 bpl brcs6
0006AC 1 brcs5:
0006AC 1 4C AC 06 trap ;branch minus/plus
0006AF 1 70 02 brcs6: bvs brcs7
0006B1 1 50 03 bvc brcs8
0006B3 1 brcs7:
0006B3 1 4C B3 06 trap ;branch overflow/no overflow
0006B6 1
0006B6 1 brcs8:
0006B6 1 A9 80 48 28 set_stat minus
0006BA 1 F0 02 beq brmi1
0006BC 1 D0 03 bne brmi2
0006BE 1 brmi1:
0006BE 1 4C BE 06 trap ;branch zero/non zero
0006C1 1 B0 02 brmi2: bcs brmi3
0006C3 1 90 03 bcc brmi4
0006C5 1 brmi3:
0006C5 1 4C C5 06 trap ;branch carry/no carry
0006C8 1 10 02 brmi4: bpl brmi5
0006CA 1 30 03 bmi brmi6
0006CC 1 brmi5:
0006CC 1 4C CC 06 trap ;branch minus/plus
0006CF 1 70 02 brmi6: bvs brmi7
0006D1 1 50 03 bvc brmi8
0006D3 1 brmi7:
0006D3 1 4C D3 06 trap ;branch overflow/no overflow
0006D6 1 brmi8:
0006D6 1 A9 40 48 28 set_stat overfl
0006DA 1 F0 02 beq brvs1
0006DC 1 D0 03 bne brvs2
0006DE 1 brvs1:
0006DE 1 4C DE 06 trap ;branch zero/non zero
0006E1 1 B0 02 brvs2: bcs brvs3
0006E3 1 90 03 bcc brvs4
0006E5 1 brvs3:
0006E5 1 4C E5 06 trap ;branch carry/no carry
0006E8 1 30 02 brvs4: bmi brvs5
0006EA 1 10 03 bpl brvs6
0006EC 1 brvs5:
0006EC 1 4C EC 06 trap ;branch minus/plus
0006EF 1 50 02 brvs6: bvc brvs7
0006F1 1 70 03 bvs brvs8
0006F3 1 brvs7:
0006F3 1 4C F3 06 trap ;branch overflow/no overflow
0006F6 1 brvs8:
0006F6 1 A9 FD 48 28 set_stat $ff-zero
0006FA 1 F0 02 beq brzc1
0006FC 1 D0 03 bne brzc2
0006FE 1 brzc1:
0006FE 1 4C FE 06 trap ;branch zero/non zero
000701 1 90 02 brzc2: bcc brzc3
000703 1 B0 03 bcs brzc4
000705 1 brzc3:
000705 1 4C 05 07 trap ;branch carry/no carry
000708 1 10 02 brzc4: bpl brzc5
00070A 1 30 03 bmi brzc6
00070C 1 brzc5:
00070C 1 4C 0C 07 trap ;branch minus/plus
00070F 1 50 02 brzc6: bvc brzc7
000711 1 70 03 bvs brzc8
000713 1 brzc7:
000713 1 4C 13 07 trap ;branch overflow/no overflow
000716 1 brzc8:
000716 1 A9 FE 48 28 set_stat $ff-carry
00071A 1 D0 02 bne brcc1
00071C 1 F0 03 beq brcc2
00071E 1 brcc1:
00071E 1 4C 1E 07 trap ;branch zero/non zero
000721 1 B0 02 brcc2: bcs brcc3
000723 1 90 03 bcc brcc4
000725 1 brcc3:
000725 1 4C 25 07 trap ;branch carry/no carry
000728 1 10 02 brcc4: bpl brcc5
00072A 1 30 03 bmi brcc6
00072C 1 brcc5:
00072C 1 4C 2C 07 trap ;branch minus/plus
00072F 1 50 02 brcc6: bvc brcc7
000731 1 70 03 bvs brcc8
000733 1 brcc7:
000733 1 4C 33 07 trap ;branch overflow/no overflow
000736 1 brcc8:
000736 1 A9 7F 48 28 set_stat $ff-minus
00073A 1 D0 02 bne brpl1
00073C 1 F0 03 beq brpl2
00073E 1 brpl1:
00073E 1 4C 3E 07 trap ;branch zero/non zero
000741 1 90 02 brpl2: bcc brpl3
000743 1 B0 03 bcs brpl4
000745 1 brpl3:
000745 1 4C 45 07 trap ;branch carry/no carry
000748 1 30 02 brpl4: bmi brpl5
00074A 1 10 03 bpl brpl6
00074C 1 brpl5:
00074C 1 4C 4C 07 trap ;branch minus/plus
00074F 1 50 02 brpl6: bvc brpl7
000751 1 70 03 bvs brpl8
000753 1 brpl7:
000753 1 4C 53 07 trap ;branch overflow/no overflow
000756 1 brpl8:
000756 1 A9 BF 48 28 set_stat $ff-overfl
00075A 1 D0 02 bne brvc1
00075C 1 F0 03 beq brvc2
00075E 1 brvc1:
00075E 1 4C 5E 07 trap ;branch zero/non zero
000761 1 90 02 brvc2: bcc brvc3
000763 1 B0 03 bcs brvc4
000765 1 brvc3:
000765 1 4C 65 07 trap ;branch carry/no carry
000768 1 10 02 brvc4: bpl brvc5
00076A 1 30 03 bmi brvc6
00076C 1 brvc5:
00076C 1 4C 6C 07 trap ;branch minus/plus
00076F 1 70 02 brvc6: bvs brvc7
000771 1 50 03 bvc brvc8
000773 1 brvc7:
000773 1 4C 73 07 trap ;branch overflow/no overflow
000776 1 brvc8:
000776 1 AD 00 02 C9 next_test
00077A 1 04 D0 FE A9
00077E 1 05 8D 00 02
000782 1
000782 1 ; test PHA does not alter flags or accumulator but PLA does
000782 1 A2 55 ldx #$55 ;x & y protected
000784 1 A0 AA ldy #$aa
000786 1 A9 FF 48 A9 set_a 1,$ff ;push
00078A 1 01 28
00078C 1 48 pha
00078D 1 08 C9 01 D0 tst_a 1,$ff
000791 1 FE 68 48 C9
000795 1 FF D0 FE 28
000799 1 A9 00 48 A9 set_a 0,0
00079D 1 00 28
00079F 1 48 pha
0007A0 1 08 C9 00 D0 tst_a 0,0
0007A4 1 FE 68 48 C9
0007A8 1 30 D0 FE 28
0007AC 1 A9 FF 48 A9 set_a $ff,$ff
0007B0 1 FF 28
0007B2 1 48 pha
0007B3 1 08 C9 FF D0 tst_a $ff,$ff
0007B7 1 FE 68 48 C9
0007BB 1 FF D0 FE 28
0007BF 1 A9 00 48 A9 set_a 1,0
0007C3 1 01 28
0007C5 1 48 pha
0007C6 1 08 C9 01 D0 tst_a 1,0
0007CA 1 FE 68 48 C9
0007CE 1 30 D0 FE 28
0007D2 1 A9 FF 48 A9 set_a 0,$ff
0007D6 1 00 28
0007D8 1 48 pha
0007D9 1 08 C9 00 D0 tst_a 0,$ff
0007DD 1 FE 68 48 C9
0007E1 1 FF D0 FE 28
0007E5 1 A9 00 48 A9 set_a $ff,0
0007E9 1 FF 28
0007EB 1 48 pha
0007EC 1 08 C9 FF D0 tst_a $ff,0
0007F0 1 FE 68 48 C9
0007F4 1 30 D0 FE 28
0007F8 1 A9 FF 48 A9 set_a 0,$ff ;pull
0007FC 1 00 28
0007FE 1 68 pla
0007FF 1 08 C9 FF D0 tst_a $ff,$ff-zero
000803 1 FE 68 48 C9
000807 1 FD D0 FE 28
00080B 1 A9 00 48 A9 set_a $ff,0
00080F 1 FF 28
000811 1 68 pla
000812 1 08 C9 00 D0 tst_a 0,zero
000816 1 FE 68 48 C9
00081A 1 32 D0 FE 28
00081E 1 A9 FF 48 A9 set_a $fe,$ff
000822 1 FE 28
000824 1 68 pla
000825 1 08 C9 01 D0 tst_a 1,$ff-zero-minus
000829 1 FE 68 48 C9
00082D 1 7D D0 FE 28
000831 1 A9 00 48 A9 set_a 0,0
000835 1 00 28
000837 1 68 pla
000838 1 08 C9 FF D0 tst_a $ff,minus
00083C 1 FE 68 48 C9
000840 1 B0 D0 FE 28
000844 1 A9 FF 48 A9 set_a $ff,$ff
000848 1 FF 28
00084A 1 68 pla
00084B 1 08 C9 00 D0 tst_a 0,$ff-minus
00084F 1 FE 68 48 C9
000853 1 7F D0 FE 28
000857 1 A9 00 48 A9 set_a $fe,0
00085B 1 FE 28
00085D 1 68 pla
00085E 1 08 C9 01 D0 tst_a 1,0
000862 1 FE 68 48 C9
000866 1 30 D0 FE 28
00086A 1 E0 55 cpx #$55 ;x & y unchanged?
00086C 1 D0 FE trap_ne
00086E 1 C0 AA cpy #$aa
000870 1 D0 FE trap_ne
000872 1 AD 00 02 C9 next_test
000876 1 05 D0 FE A9
00087A 1 06 8D 00 02
00087E 1
00087E 1 ; partial pretest EOR #
00087E 1 A9 00 48 A9 set_a $3c,0
000882 1 3C 28
000884 1 49 C3 eor #$c3
000886 1 08 C9 FF D0 tst_a $ff,fn
00088A 1 FE 68 48 C9
00088E 1 B0 D0 FE 28
000892 1 A9 00 48 A9 set_a $c3,0
000896 1 C3 28
000898 1 49 C3 eor #$c3
00089A 1 08 C9 00 D0 tst_a 0,fz
00089E 1 FE 68 48 C9
0008A2 1 32 D0 FE 28
0008A6 1 AD 00 02 C9 next_test
0008AA 1 06 D0 FE A9
0008AE 1 07 8D 00 02
0008B2 1
0008B2 1 ; PC modifying instructions except branches (NOP, JMP, JSR, RTS, BRK, RTI)
0008B2 1 ; testing NOP
0008B2 1 A2 24 ldx #$24
0008B4 1 A0 42 ldy #$42
0008B6 1 A9 00 48 A9 set_a $18,0
0008BA 1 18 28
0008BC 1 EA nop
0008BD 1 08 C9 18 D0 tst_a $18,0
0008C1 1 FE 68 48 C9
0008C5 1 30 D0 FE 28
0008C9 1 E0 24 cpx #$24
0008CB 1 D0 FE trap_ne
0008CD 1 C0 42 cpy #$42
0008CF 1 D0 FE trap_ne
0008D1 1 A2 DB ldx #$db
0008D3 1 A0 BD ldy #$bd
0008D5 1 A9 FF 48 A9 set_a $e7,$ff
0008D9 1 E7 28
0008DB 1 EA nop
0008DC 1 08 C9 E7 D0 tst_a $e7,$ff
0008E0 1 FE 68 48 C9
0008E4 1 FF D0 FE 28
0008E8 1 E0 DB cpx #$db
0008EA 1 D0 FE trap_ne
0008EC 1 C0 BD cpy #$bd
0008EE 1 D0 FE trap_ne
0008F0 1 AD 00 02 C9 next_test
0008F4 1 07 D0 FE A9
0008F8 1 08 8D 00 02
0008FC 1
0008FC 1 ; jump absolute
0008FC 1 A9 00 48 28 set_stat $0
000900 1 A9 46 lda #'F'
000902 1 A2 41 ldx #'A'
000904 1 A0 52 ldy #'R' ;N=0, V=0, Z=0, C=0
000906 1 4C EF 36 jmp test_far
000909 1 EA nop
00090A 1 EA nop
00090B 1 D0 FE trap_ne ;runover protection
00090D 1 E8 inx
00090E 1 E8 inx
00090F 1 far_ret:
00090F 1 F0 FE trap_eq ;returned flags OK?
000911 1 10 FE trap_pl
000913 1 90 FE trap_cc
000915 1 50 FE trap_vc
000917 1 C9 EC cmp #('F'^$aa) ;returned registers OK?
000919 1 D0 FE trap_ne
00091B 1 E0 42 cpx #('A'+1)
00091D 1 D0 FE trap_ne
00091F 1 C0 4F cpy #('R'-3)
000921 1 D0 FE trap_ne
000923 1 CA dex
000924 1 C8 iny
000925 1 C8 iny
000926 1 C8 iny
000927 1 49 AA eor #$aa ;N=0, V=1, Z=0, C=1
000929 1 4C 32 09 jmp test_near
00092C 1 EA nop
00092D 1 EA nop
00092E 1 D0 FE trap_ne ;runover protection
000930 1 E8 inx
000931 1 E8 inx
000932 1 test_near:
000932 1 F0 FE trap_eq ;passed flags OK?
000934 1 30 FE trap_mi
000936 1 90 FE trap_cc
000938 1 50 FE trap_vc
00093A 1 C9 46 cmp #'F' ;passed registers OK?
00093C 1 D0 FE trap_ne
00093E 1 E0 41 cpx #'A'
000940 1 D0 FE trap_ne
000942 1 C0 52 cpy #'R'
000944 1 D0 FE trap_ne
000946 1 AD 00 02 C9 next_test
00094A 1 08 D0 FE A9
00094E 1 09 8D 00 02
000952 1
000952 1 ; jump indirect
000952 1 A9 00 48 28 set_stat 0
000956 1 A9 49 lda #'I'
000958 1 A2 4E ldx #'N'
00095A 1 A0 44 ldy #'D' ;N=0, V=0, Z=0, C=0
00095C 1 6C 1E 37 jmp (ptr_tst_ind)
00095F 1 EA nop
000960 1 D0 FE trap_ne ;runover protection
000962 1 88 dey
000963 1 88 dey
000964 1 ind_ret:
000964 1 08 php ;either SP or Y count will fail, if we do not hit
000965 1 88 dey
000966 1 88 dey
000967 1 88 dey
000968 1 28 plp
000969 1 F0 FE trap_eq ;returned flags OK?
00096B 1 10 FE trap_pl
00096D 1 90 FE trap_cc
00096F 1 50 FE trap_vc
000971 1 C9 E3 cmp #('I'^$aa) ;returned registers OK?
000973 1 D0 FE trap_ne
000975 1 E0 4F cpx #('N'+1)
000977 1 D0 FE trap_ne
000979 1 C0 3E cpy #('D'-6)
00097B 1 D0 FE trap_ne
00097D 1 BA tsx ;SP check
00097E 1 E0 FF cpx #$ff
000980 1 D0 FE trap_ne
000982 1 AD 00 02 C9 next_test
000986 1 09 D0 FE A9
00098A 1 0A 8D 00 02
00098E 1
00098E 1 ; jump subroutine & return from subroutine
00098E 1 A9 00 48 28 set_stat 0
000992 1 A9 4A lda #'J'
000994 1 A2 53 ldx #'S'
000996 1 A0 52 ldy #'R' ;N=0, V=0, Z=0, C=0
000998 1 20 5D 37 jsr test_jsr
00099B 1 jsr_ret = *-1 ;last address of jsr = return address
00099B 1 08 php ;either SP or Y count will fail, if we do not hit
00099C 1 88 dey
00099D 1 88 dey
00099E 1 88 dey
00099F 1 28 plp
0009A0 1 F0 FE trap_eq ;returned flags OK?
0009A2 1 10 FE trap_pl
0009A4 1 90 FE trap_cc
0009A6 1 50 FE trap_vc
0009A8 1 C9 E0 cmp #('J'^$aa) ;returned registers OK?
0009AA 1 D0 FE trap_ne
0009AC 1 E0 54 cpx #('S'+1)
0009AE 1 D0 FE trap_ne
0009B0 1 C0 4C cpy #('R'-6)
0009B2 1 D0 FE trap_ne
0009B4 1 BA tsx ;sp?
0009B5 1 E0 FF cpx #$ff
0009B7 1 D0 FE trap_ne
0009B9 1 AD 00 02 C9 next_test
0009BD 1 0A D0 FE A9
0009C1 1 0B 8D 00 02
0009C5 1
0009C5 1 ; break & return from interrupt
0009C5 1 .if ROM_vectors = 1
0009C5 1 A9 00 load_flag 0 ;with interrupts enabled if allowed!
0009C7 1 48 pha
0009C8 1 A9 42 lda #'B'
0009CA 1 A2 52 ldx #'R'
0009CC 1 A0 4B ldy #'K'
0009CE 1 28 plp ;N=0, V=0, Z=0, C=0
0009CF 1 00 brk
0009D0 1 .else
0009D0 1 lda #>brk_ret0 ;emulated break
0009D0 1 pha
0009D0 1 lda #brk_ret1 ;emulated break
0009F6 1 pha
0009F6 1 lda #bin_rti_ret ;emulated interrupt for rti
00343D 1 48 pha
00343E 1 A9 55 lda #dec_rti_ret ;emulated interrupt for rti
003445 1 48 pha
003446 1 A9 4C lda #jsr_ret
003783 1 D0 FE trap_ne
003785 1 AD FE 01 lda $1fe
003788 1 C9 9A cmp #brk_ret0
0037DA 1 D0 FE trap_ne
0037DC 1 AD FE 01 lda $1fe
0037DF 1 C9 D1 cmp #brk_ret1
00381A 1 D0 FE trap_ne
00381C 1 AD FE 01 lda $1fe
00381F 1 C9 F7 cmp # 1
003835 1 zp_init:
003835 1 zps_: .byte $80,1 ;additional shift pattern to test zero result & flag
003835 1 zp1_: .byte $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
003835 1 zp7f_: .byte $7f ;test pattern for compare
003835 1 ;logical zeropage operands
003835 1 zpOR_: .byte 0,$1f,$71,$80 ;test pattern for OR
003835 1 zpAN_: .byte $0f,$ff,$7f,$80 ;test pattern for AND
003835 1 zpEO_: .byte $ff,$0f,$8f,$8f ;test pattern for EOR
003835 1 ;indirect addressing pointers
003835 1 ind1_: .word abs1 ;indirect pointer to pattern in absolute memory
003835 1 .word abs1+1
003835 1 .word abs1+2
003835 1 .word abs1+3
003835 1 .word abs7f
003835 1 inw1_: .word abs1-$f8 ;indirect pointer for wrap-test pattern
003835 1 indt_: .word abst ;indirect pointer to store area in absolute memory
003835 1 .word abst+1
003835 1 .word abst+2
003835 1 .word abst+3
003835 1 inwt_: .word abst-$f8 ;indirect pointer for wrap-test store
003835 1 indAN_: .word absAN ;indirect pointer to AND pattern in absolute memory
003835 1 .word absAN+1
003835 1 .word absAN+2
003835 1 .word absAN+3
003835 1 indEO_: .word absEO ;indirect pointer to EOR pattern in absolute memory
003835 1 .word absEO+1
003835 1 .word absEO+2
003835 1 .word absEO+3
003835 1 indOR_: .word absOR ;indirect pointer to OR pattern in absolute memory
003835 1 .word absOR+1
003835 1 .word absOR+2
003835 1 .word absOR+3
003835 1 ;add/subtract indirect pointers
003835 1 adi2_: .word ada2 ;indirect pointer to operand 2 in absolute memory
003835 1 sbi2_: .word sba2 ;indirect pointer to complemented operand 2 (SBC)
003835 1 adiy2_: .word ada2-$ff ;with offset for indirect indexed
003835 1 sbiy2_: .word sba2-$ff
003835 1 zp_end:
003835 1 .if (zp_end - zp_init) <> (zp_bss_end - zp_bss)
003835 1 ;force assembler error if size is different
003835 1 .error "mismatch between bss and zeropage data"
003835 1 .endif
003835 1 data_init:
003835 1 ex_and_:and #0 ;execute immediate opcodes
003835 1 rts
003835 1 ex_eor_:eor #0 ;execute immediate opcodes
003835 1 rts
003835 1 ex_ora_:ora #0 ;execute immediate opcodes
003835 1 rts
003835 1 ex_adc_:adc #0 ;execute immediate opcodes
003835 1 rts
003835 1 ex_sbc_:sbc #0 ;execute immediate opcodes
003835 1 rts
003835 1 ;zps: .byte $80,1 ;additional shift patterns test zero result & flag
003835 1 abs1_: .byte $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
003835 1 abs7f_: .byte $7f ;test pattern for compare
003835 1 ;loads
003835 1 fLDx_: .byte fn,fn,0,fz ;expected flags for load
003835 1 ;shifts
003835 1 rASL_: ;expected result ASL & ROL -carry
003835 1 rROL_: .byte 0,2,$86,$04,$82,0
003835 1 rROLc_: .byte 1,3,$87,$05,$83,1 ;expected result ROL +carry
003835 1 rLSR_: ;expected result LSR & ROR -carry
003835 1 rROR_: .byte $40,0,$61,$41,$20,0
003835 1 rRORc_: .byte $c0,$80,$e1,$c1,$a0,$80 ;expected result ROR +carry
003835 1 fASL_: ;expected flags for shifts
003835 1 fROL_: .byte fzc,0,fnc,fc,fn,fz ;no carry in
003835 1 fROLc_: .byte fc,0,fnc,fc,fn,0 ;carry in
003835 1 fLSR_:
003835 1 fROR_: .byte 0,fzc,fc,0,fc,fz ;no carry in
003835 1 fRORc_: .byte fn,fnc,fnc,fn,fnc,fn ;carry in
003835 1 ;increments (decrements)
003835 1 rINC_: .byte $7f,$80,$ff,0,1 ;expected result for INC/DEC
003835 1 fINC_: .byte 0,fn,fn,fz,0 ;expected flags for INC/DEC
003835 1 ;logical memory operand
003835 1 absOR_: .byte 0,$1f,$71,$80 ;test pattern for OR
003835 1 absAN_: .byte $0f,$ff,$7f,$80 ;test pattern for AND
003835 1 absEO_: .byte $ff,$0f,$8f,$8f ;test pattern for EOR
003835 1 ;logical accu operand
003835 1 absORa_:.byte 0,$f1,$1f,0 ;test pattern for OR
003835 1 absANa_:.byte $f0,$ff,$ff,$ff ;test pattern for AND
003835 1 absEOa_:.byte $ff,$f0,$f0,$0f ;test pattern for EOR
003835 1 ;logical results
003835 1 absrlo_:.byte 0,$ff,$7f,$80
003835 1 absflo_:.byte fz,fn,0,fn
003835 1 data_end
003835 1 .if (data_end - data_init) <> (data_bss_end - data_bss)
003835 1 ;force assembler error if size is different
003835 1 .error "mismatch between bss and data"
003835 1 .endif
003835 1
003835 1 vec_init
003835 1 .word nmi_trap
003835 1 .word res_trap
003835 1 .word irq_trap
003835 1 vec_bss equ $fffa
003835 1 .endif ;end of RAM init data
003835 1
003835 1 .if (load_data_direct = 1) & (ROM_vectors = 1)
003835 1 .segment "VECTORS"
003835 1 .org $fffa ;vectors
00FFFA 1 9D 37 .word nmi_trap
00FFFC 1 A3 37 .word res_trap
00FFFE 1 AB 37 .word irq_trap
010000 1 .endif
010000 1