840 lines
22 KiB
NASM
840 lines
22 KiB
NASM
; 6502 Instruction Testing File
|
|
; Contains all official and unofficial instructions with all valid addressing modes
|
|
|
|
.org $8000
|
|
|
|
; ADC - Add With Carry
|
|
adc_tests:
|
|
ADC #$10 ; Immediate
|
|
ADC $10 ; Zero Page
|
|
ADC $10,X ; Zero Page,X
|
|
ADC $1000 ; Absolute
|
|
ADC $1000,X ; Absolute,X
|
|
ADC $1000,Y ; Absolute,Y
|
|
ADC ($10,X) ; Indirect,X
|
|
ADC ($10),Y ; Indirect,Y
|
|
|
|
; ALR (unofficial) - AND + LSR
|
|
alr_tests:
|
|
ALR #$10 ; Immediate
|
|
|
|
; AND - Logical AND
|
|
and_tests:
|
|
AND #$10 ; Immediate
|
|
AND $10 ; Zero Page
|
|
AND $10,X ; Zero Page,X
|
|
AND $1000 ; Absolute
|
|
AND $1000,X ; Absolute,X
|
|
AND $1000,Y ; Absolute,Y
|
|
AND ($10,X) ; Indirect,X
|
|
AND ($10),Y ; Indirect,Y
|
|
|
|
; ANC (unofficial) - AND + set C as bit 7
|
|
anc_tests:
|
|
ANC #$10 ; Immediate
|
|
|
|
; ARR (unofficial) - AND + ROR
|
|
arr_tests:
|
|
ARR #$10 ; Immediate
|
|
|
|
; ASL - Arithmetic Shift Left
|
|
asl_tests:
|
|
ASL A ; Accumulator
|
|
ASL $10 ; Zero Page
|
|
ASL $10,X ; Zero Page,X
|
|
ASL $1000 ; Absolute
|
|
ASL $1000,X ; Absolute,X
|
|
|
|
; AXS (unofficial) - Store A&X into memory
|
|
;; axs_tests:
|
|
;; AXS #$10 ; Immediate
|
|
;; AXS $10 ; Zero Page
|
|
;; AXS $10,Y ; Zero Page,Y
|
|
;; AXS $1000 ; Absolute
|
|
|
|
; Branch Instructions
|
|
branch_tests:
|
|
BCC label1 ; Relative
|
|
BCS label1 ; Relative
|
|
BEQ label1 ; Relative
|
|
BMI label1 ; Relative
|
|
BNE label1 ; Relative
|
|
BPL label1 ; Relative
|
|
BVC label1 ; Relative
|
|
BVS label1 ; Relative
|
|
label1:
|
|
|
|
; BIT - Bit Test
|
|
bit_tests:
|
|
BIT $10 ; Zero Page
|
|
BIT $1000 ; Absolute
|
|
|
|
; BRK - Force Interrupt
|
|
brk_tests:
|
|
BRK ; Implicit
|
|
|
|
; CLC/CLD/CLI/CLV - Clear flags
|
|
clear_tests:
|
|
CLC ; Implicit
|
|
CLD ; Implicit
|
|
CLI ; Implicit
|
|
CLV ; Implicit
|
|
|
|
; CMP - Compare
|
|
cmp_tests:
|
|
CMP #$10 ; Immediate
|
|
CMP $10 ; Zero Page
|
|
CMP $10,X ; Zero Page,X
|
|
CMP $1000 ; Absolute
|
|
CMP $1000,X ; Absolute,X
|
|
CMP $1000,Y ; Absolute,Y
|
|
CMP ($10,X) ; Indirect,X
|
|
CMP ($10),Y ; Indirect,Y
|
|
|
|
; CPX - Compare X Register
|
|
cpx_tests:
|
|
CPX #$10 ; Immediate
|
|
CPX $10 ; Zero Page
|
|
CPX $1000 ; Absolute
|
|
|
|
; CPY - Compare Y Register
|
|
cpy_tests:
|
|
CPY #$10 ; Immediate
|
|
CPY $10 ; Zero Page
|
|
CPY $1000 ; Absolute
|
|
|
|
; DCP (unofficial) - DEC + CMP
|
|
dcp_tests:
|
|
DCP $10 ; Zero Page
|
|
DCP $10,X ; Zero Page,X
|
|
DCP $1000 ; Absolute
|
|
DCP $1000,X ; Absolute,X
|
|
DCP $1000,Y ; Absolute,Y
|
|
DCP ($10,X) ; Indirect,X
|
|
DCP ($10),Y ; Indirect,Y
|
|
|
|
; DEC - Decrement Memory
|
|
dec_tests:
|
|
DEC $10 ; Zero Page
|
|
DEC $10,X ; Zero Page,X
|
|
DEC $1000 ; Absolute
|
|
DEC $1000,X ; Absolute,X
|
|
|
|
; DEX/DEY - Decrement Register
|
|
dex_dey_tests:
|
|
DEX ; Implicit
|
|
DEY ; Implicit
|
|
|
|
; EOR - Exclusive OR
|
|
eor_tests:
|
|
EOR #$10 ; Immediate
|
|
EOR $10 ; Zero Page
|
|
EOR $10,X ; Zero Page,X
|
|
EOR $1000 ; Absolute
|
|
EOR $1000,X ; Absolute,X
|
|
EOR $1000,Y ; Absolute,Y
|
|
EOR ($10,X) ; Indirect,X
|
|
EOR ($10),Y ; Indirect,Y
|
|
|
|
; ISC/ISB (unofficial) - INC + SBC
|
|
isc_tests:
|
|
ISC $10 ; Zero Page
|
|
ISC $10,X ; Zero Page,X
|
|
ISC $1000 ; Absolute
|
|
ISC $1000,X ; Absolute,X
|
|
ISC $1000,Y ; Absolute,Y
|
|
ISC ($10,X) ; Indirect,X
|
|
ISC ($10),Y ; Indirect,Y
|
|
|
|
; INC - Increment Memory
|
|
inc_tests:
|
|
INC $10 ; Zero Page
|
|
INC $10,X ; Zero Page,X
|
|
INC $1000 ; Absolute
|
|
INC $1000,X ; Absolute,X
|
|
|
|
; INX/INY - Increment Register
|
|
inx_iny_tests:
|
|
INX ; Implicit
|
|
INY ; Implicit
|
|
|
|
; JMP - Jump
|
|
jmp_tests:
|
|
JMP $1000 ; Absolute
|
|
JMP ($1000) ; Absolute Indirect
|
|
|
|
; JSR - Jump to Subroutine
|
|
jsr_tests:
|
|
JSR $1000 ; Absolute
|
|
|
|
; KIL (unofficial) - Halt the CPU
|
|
;; kil_tests:
|
|
;; KIL ; Implicit
|
|
|
|
; LAX (unofficial) - LDA + LDX
|
|
lax_tests:
|
|
LAX #$10 ; Immediate
|
|
LAX $10 ; Zero Page
|
|
LAX $10,Y ; Zero Page,Y
|
|
LAX $1000 ; Absolute
|
|
LAX $1000,Y ; Absolute,Y
|
|
LAX ($10,X) ; Indirect,X
|
|
LAX ($10),Y ; Indirect,Y
|
|
|
|
; LAS (unofficial) - LDA/TSX with stack pointer
|
|
las_tests:
|
|
LAS $1000,Y ; Absolute,Y
|
|
|
|
; LDA - Load Accumulator
|
|
lda_tests:
|
|
LDA #$10 ; Immediate
|
|
LDA $10 ; Zero Page
|
|
LDA $10,X ; Zero Page,X
|
|
LDA $1000 ; Absolute
|
|
LDA $1000,X ; Absolute,X
|
|
LDA $1000,Y ; Absolute,Y
|
|
LDA ($10,X) ; Indirect,X
|
|
LDA ($10),Y ; Indirect,Y
|
|
|
|
; LDX - Load X Register
|
|
ldx_tests:
|
|
LDX #$10 ; Immediate
|
|
LDX $10 ; Zero Page
|
|
LDX $10,Y ; Zero Page,Y
|
|
LDX $1000 ; Absolute
|
|
LDX $1000,Y ; Absolute,Y
|
|
|
|
; LDY - Load Y Register
|
|
ldy_tests:
|
|
LDY #$10 ; Immediate
|
|
LDY $10 ; Zero Page
|
|
LDY $10,X ; Zero Page,X
|
|
LDY $1000
|
|
|
|
|
|
LDY $1000 ; Absolute
|
|
LDY $1000,X ; Absolute,X
|
|
|
|
; LSR - Logical Shift Right
|
|
lsr_tests:
|
|
LSR A ; Accumulator
|
|
LSR $10 ; Zero Page
|
|
LSR $10,X ; Zero Page,X
|
|
LSR $1000 ; Absolute
|
|
LSR $1000,X ; Absolute,X
|
|
|
|
; NOP - No Operation
|
|
nop_tests:
|
|
NOP ; Implicit
|
|
NOP #$10 ; Immediate (unofficial)
|
|
NOP $10 ; Zero Page (unofficial)
|
|
NOP $10,X ; Zero Page,X (unofficial)
|
|
NOP $1000 ; Absolute (unofficial)
|
|
NOP $1000,X ; Absolute,X (unofficial)
|
|
|
|
; ORA - Logical Inclusive OR
|
|
ora_tests:
|
|
ORA #$10 ; Immediate
|
|
ORA $10 ; Zero Page
|
|
ORA $10,X ; Zero Page,X
|
|
ORA $1000 ; Absolute
|
|
ORA $1000,X ; Absolute,X
|
|
ORA $1000,Y ; Absolute,Y
|
|
ORA ($10,X) ; Indirect,X
|
|
ORA ($10),Y ; Indirect,Y
|
|
|
|
; Stack Operations
|
|
stack_tests:
|
|
PHA ; Push Accumulator - Implicit
|
|
PHP ; Push Processor Status - Implicit
|
|
PLA ; Pull Accumulator - Implicit
|
|
PLP ; Pull Processor Status - Implicit
|
|
|
|
; RLA (unofficial) - ROL + AND
|
|
rla_tests:
|
|
RLA $10 ; Zero Page
|
|
RLA $10,X ; Zero Page,X
|
|
RLA $1000 ; Absolute
|
|
RLA $1000,X ; Absolute,X
|
|
RLA $1000,Y ; Absolute,Y
|
|
RLA ($10,X) ; Indirect,X
|
|
RLA ($10),Y ; Indirect,Y
|
|
|
|
; ROL - Rotate Left
|
|
rol_tests:
|
|
ROL A ; Accumulator
|
|
ROL $10 ; Zero Page
|
|
ROL $10,X ; Zero Page,X
|
|
ROL $1000 ; Absolute
|
|
ROL $1000,X ; Absolute,X
|
|
|
|
; ROR - Rotate Right
|
|
ror_tests:
|
|
ROR A ; Accumulator
|
|
ROR $10 ; Zero Page
|
|
ROR $10,X ; Zero Page,X
|
|
ROR $1000 ; Absolute
|
|
ROR $1000,X ; Absolute,X
|
|
|
|
; RRA (unofficial) - ROR + ADC
|
|
rra_tests:
|
|
RRA $10 ; Zero Page
|
|
RRA $10,X ; Zero Page,X
|
|
RRA $1000 ; Absolute
|
|
RRA $1000,X ; Absolute,X
|
|
RRA $1000,Y ; Absolute,Y
|
|
RRA ($10,X) ; Indirect,X
|
|
RRA ($10),Y ; Indirect,Y
|
|
|
|
; RTI - Return from Interrupt
|
|
rti_tests:
|
|
RTI ; Implicit
|
|
|
|
; RTS - Return from Subroutine
|
|
rts_tests:
|
|
RTS ; Implicit
|
|
|
|
; SAX (unofficial) - Store A&X
|
|
sax_tests:
|
|
SAX $10 ; Zero Page
|
|
SAX $10,Y ; Zero Page,Y
|
|
SAX $1000 ; Absolute
|
|
SAX ($10,X) ; Indirect,X
|
|
|
|
; SBC - Subtract with Carry
|
|
sbc_tests:
|
|
SBC #$10 ; Immediate
|
|
SBC $10 ; Zero Page
|
|
SBC $10,X ; Zero Page,X
|
|
SBC $1000 ; Absolute
|
|
SBC $1000,X ; Absolute,X
|
|
SBC $1000,Y ; Absolute,Y
|
|
SBC ($10,X) ; Indirect,X
|
|
SBC ($10),Y ; Indirect,Y
|
|
|
|
; SEC/SED/SEI - Set Flags
|
|
set_tests:
|
|
SEC ; Implicit
|
|
|
|
|
|
|
|
SEC ; Implicit
|
|
SED ; Implicit
|
|
SEI ; Implicit
|
|
|
|
; SHX (unofficial) - Store X&H
|
|
shx_tests:
|
|
SHX $1000,Y ; Absolute,Y
|
|
|
|
; SHY (unofficial) - Store Y&H
|
|
shy_tests:
|
|
SHY $1000,X ; Absolute,X
|
|
|
|
; SLO (unofficial) - ASL + ORA
|
|
slo_tests:
|
|
SLO $10 ; Zero Page
|
|
SLO $10,X ; Zero Page,X
|
|
SLO $1000 ; Absolute
|
|
SLO $1000,X ; Absolute,X
|
|
SLO $1000,Y ; Absolute,Y
|
|
SLO ($10,X) ; Indirect,X
|
|
SLO ($10),Y ; Indirect,Y
|
|
|
|
; SRE (unofficial) - LSR + EOR
|
|
sre_tests:
|
|
SRE $10 ; Zero Page
|
|
SRE $10,X ; Zero Page,X
|
|
SRE $1000 ; Absolute
|
|
SRE $1000,X ; Absolute,X
|
|
SRE $1000,Y ; Absolute,Y
|
|
SRE ($10,X) ; Indirect,X
|
|
SRE ($10),Y ; Indirect,Y
|
|
|
|
; STA - Store Accumulator
|
|
sta_tests:
|
|
STA $10 ; Zero Page
|
|
STA $10,X ; Zero Page,X
|
|
STA $1000 ; Absolute
|
|
STA $1000,X ; Absolute,X
|
|
STA $1000,Y ; Absolute,Y
|
|
STA ($10,X) ; Indirect,X
|
|
STA ($10),Y ; Indirect,Y
|
|
|
|
; STX - Store X Register
|
|
stx_tests:
|
|
STX $10 ; Zero Page
|
|
STX $10,Y ; Zero Page,Y
|
|
STX $1000 ; Absolute
|
|
|
|
; STY - Store Y Register
|
|
sty_tests:
|
|
STY $10 ; Zero Page
|
|
STY $10,X ; Zero Page,X
|
|
STY $1000 ; Absolute
|
|
|
|
; TAS (unofficial) - Store A&X into SP and A&X&H into memory
|
|
tas_tests:
|
|
TAS $1000,Y ; Absolute,Y
|
|
|
|
; Register Transfers
|
|
transfer_tests:
|
|
TAX ; Implicit
|
|
TAY ; Implicit
|
|
TSX ; Implicit
|
|
TXA ; Implicit
|
|
TXS ; Implicit
|
|
TYA ; Implicit
|
|
|
|
; XAA (unofficial) - Complex behavior with A,X,# (unstable)
|
|
;; xaa_tests:
|
|
;; XAA #$10 ; Immediate
|
|
|
|
; Additional unused opcodes/variants for complete coverage
|
|
additional_tests:
|
|
; Some assemblers might not recognize all unofficial opcodes by name
|
|
; So here's a section with .byte directives for any missed opcodes
|
|
|
|
; Additional NOPs (different variants)
|
|
.byte $1A ; NOP implicit (unofficial)
|
|
.byte $3A ; NOP implicit (unofficial)
|
|
.byte $5A ; NOP implicit (unofficial)
|
|
.byte $7A ; NOP implicit (unofficial)
|
|
.byte $DA ; NOP implicit (unofficial)
|
|
.byte $FA ; NOP implicit (unofficial)
|
|
|
|
; JAM/KIL/HLT variants (these halt the CPU)
|
|
.byte $02 ; KIL/JAM (unofficial)
|
|
.byte $12 ; KIL/JAM (unofficial)
|
|
.byte $22 ; KIL/JAM (unofficial)
|
|
.byte $32 ; KIL/JAM (unofficial)
|
|
.byte $42 ; KIL/JAM (unofficial)
|
|
.byte $52 ; KIL/JAM (unofficial)
|
|
.byte $62 ; KIL/JAM (unofficial)
|
|
.byte $72 ; KIL/JAM (unofficial)
|
|
.byte $92 ; KIL/JAM (unofficial)
|
|
.byte $B2 ; KIL/JAM (
|
|
|
|
|
|
.byte $B2 ; KIL/JAM (unofficial)
|
|
.byte $D2 ; KIL/JAM (unofficial)
|
|
.byte $F2 ; KIL/JAM (unofficial)
|
|
|
|
; LAX variants
|
|
.byte $AB ; LAX immediate (unofficial) - might not be recognized as LAX #$
|
|
|
|
; SAX variants
|
|
.byte $87 ; SAX zero page (unofficial)
|
|
.byte $97 ; SAX zero page,Y (unofficial)
|
|
.byte $8F ; SAX absolute (unofficial)
|
|
.byte $83 ; SAX (indirect,X) (unofficial)
|
|
|
|
; ANE/XAA (highly unstable)
|
|
.byte $8B ; XAA/ANE immediate (unofficial)
|
|
|
|
; SHY variants
|
|
.byte $9C ; SHY absolute,X (unofficial)
|
|
|
|
; SHX variants
|
|
.byte $9E ; SHX absolute,Y (unofficial)
|
|
|
|
; TAS/SHS variants
|
|
.byte $9B ; TAS/SHS absolute,Y (unofficial)
|
|
|
|
; LAS/LAR variants
|
|
.byte $BB ; LAS/LAR absolute,Y (unofficial)
|
|
|
|
; Additional addressing mode testing for all instructions
|
|
|
|
; Test boundary conditions
|
|
LDA $FF ; Zero page boundary
|
|
LDA $FF,X ; Zero page wrap-around
|
|
LDA $FFFF ; Absolute address boundary
|
|
LDA $FFFF,X ; Absolute,X wrap-around
|
|
LDA $FFFF,Y ; Absolute,Y wrap-around
|
|
;; JMP ($FFFF) ; Indirect JMP boundary
|
|
|
|
; Test with specific values that might be edge cases
|
|
LDA #$00 ; Immediate with 0
|
|
LDA #$FF ; Immediate with max value
|
|
LDA #$80 ; Immediate with sign bit
|
|
|
|
; Exhaustive branch testing
|
|
label_forward:
|
|
BEQ label_forward_target
|
|
BNE label_forward_target
|
|
BCS label_forward_target
|
|
BCC label_forward_target
|
|
BMI label_forward_target
|
|
BPL label_forward_target
|
|
BVS label_forward_target
|
|
BVC label_forward_target
|
|
label_forward_target:
|
|
|
|
; Backward branches
|
|
BEQ label_backward
|
|
BNE label_backward
|
|
BCS label_backward
|
|
BCC label_backward
|
|
BMI label_backward
|
|
BPL label_backward
|
|
BVS label_backward
|
|
BVC label_backward
|
|
label_backward:
|
|
|
|
; Exercise all unofficial instructions with all addressing modes
|
|
; Some of these combinations might not exist on real hardware
|
|
|
|
; DCP (DEC + CMP) all modes
|
|
DCP $20 ; Zero Page
|
|
DCP $20,X ; Zero Page,X
|
|
DCP $2000 ; Absolute
|
|
DCP $2000,X ; Absolute,X
|
|
DCP $2000,Y ; Absolute,Y
|
|
DCP ($20,X) ; Indirect,X
|
|
DCP ($20),Y ; Indirect,Y
|
|
|
|
; ISC/ISB (INC + SBC) all modes
|
|
ISC $20 ; Zero Page
|
|
ISC $20,X ; Zero Page,X
|
|
ISC $2000 ; Absolute
|
|
ISC $2000,X ; Absolute,X
|
|
ISC $2000,Y ; Absolute,Y
|
|
ISC ($20,X) ; Indirect,X
|
|
ISC ($20),Y ; Indirect,Y
|
|
|
|
; SLO (ASL + ORA) all modes
|
|
SLO $20 ; Zero Page
|
|
SLO $20,X ; Zero Page,X
|
|
SLO $2000 ; Absolute
|
|
|
|
|
|
SLO $2000 ; Absolute
|
|
SLO $2000,X ; Absolute,X
|
|
SLO $2000,Y ; Absolute,Y
|
|
SLO ($20,X) ; Indirect,X
|
|
SLO ($20),Y ; Indirect,Y
|
|
|
|
; RLA (ROL + AND) all modes
|
|
RLA $20 ; Zero Page
|
|
RLA $20,X ; Zero Page,X
|
|
RLA $2000 ; Absolute
|
|
RLA $2000,X ; Absolute,X
|
|
RLA $2000,Y ; Absolute,Y
|
|
RLA ($20,X) ; Indirect,X
|
|
RLA ($20),Y ; Indirect,Y
|
|
|
|
; SRE (LSR + EOR) all modes
|
|
SRE $20 ; Zero Page
|
|
SRE $20,X ; Zero Page,X
|
|
SRE $2000 ; Absolute
|
|
SRE $2000,X ; Absolute,X
|
|
SRE $2000,Y ; Absolute,Y
|
|
SRE ($20,X) ; Indirect,X
|
|
SRE ($20),Y ; Indirect,Y
|
|
|
|
; RRA (ROR + ADC) all modes
|
|
RRA $20 ; Zero Page
|
|
RRA $20,X ; Zero Page,X
|
|
RRA $2000 ; Absolute
|
|
RRA $2000,X ; Absolute,X
|
|
RRA $2000,Y ; Absolute,Y
|
|
RRA ($20,X) ; Indirect,X
|
|
RRA ($20),Y ; Indirect,Y
|
|
|
|
; LAX (LDA + LDX) all documented modes
|
|
LAX $20 ; Zero Page
|
|
LAX $20,Y ; Zero Page,Y
|
|
LAX $2000 ; Absolute
|
|
LAX $2000,Y ; Absolute,Y
|
|
LAX ($20,X) ; Indirect,X
|
|
LAX ($20),Y ; Indirect,Y
|
|
LAX #$20 ; Immediate (unstable)
|
|
|
|
; SAX (A&X store) all modes
|
|
SAX $20 ; Zero Page
|
|
SAX $20,Y ; Zero Page,Y
|
|
SAX $2000 ; Absolute
|
|
SAX ($20,X) ; Indirect,X
|
|
|
|
; Data regions to test loading and storing
|
|
.byte $AA, $55, $00, $FF, $01, $80, $7F, $81
|
|
|
|
; Test multiple data byte formats
|
|
data_section:
|
|
.byte $01, $02, $03, $04
|
|
.word $1234, $5678
|
|
.dword $12345678 ; Some assemblers support this
|
|
.byte %01010101 ; Binary format
|
|
.byte 'A', 'B', 'C' ; Character format
|
|
|
|
; Test self-modifying code scenarios
|
|
LDA #$EA ; Load NOP opcode
|
|
STA modify_target ; Modify the instruction below
|
|
modify_target:
|
|
BRK ; This will be modified to NOP
|
|
|
|
; Additional instruction combinations to ensure all opcodes are covered
|
|
|
|
; NOP variants (unofficial)
|
|
.byte $04 ; NOP zero page
|
|
.byte $44 ; NOP zero page
|
|
.byte $64 ; NOP zero page
|
|
.byte $0C ; NOP absolute
|
|
.byte $1C ; NOP absolute,X
|
|
.byte $3C ; NOP absolute,X
|
|
.byte $5C ; NOP absolute,X
|
|
.byte $7C ; NOP absolute,X
|
|
.byte $DC ; NOP absolute,X
|
|
.byte $FC ; NOP absolute,X
|
|
.byte $14 ; NOP zero page,X
|
|
.byte $34 ; NOP zero page,X
|
|
.byte $54 ; NOP zero page,X
|
|
.byte $74 ; NOP zero page,X
|
|
.byte $D4 ; NOP zero page,X
|
|
.byte $F4 ; NOP zero page,X
|
|
|
|
; ANC variants
|
|
.byte $0B ; ANC immediate
|
|
.byte $2B ; ANC immediate (another variant)
|
|
|
|
; ALR/ASR variant
|
|
.byte $4B ; ALR immediate
|
|
|
|
; ARR variant
|
|
.byte $6B ; ARR immediate
|
|
|
|
; AXS/SBX variant
|
|
.byte $CB ; AXS immediate
|
|
|
|
; Test decimal mode instructions
|
|
SED ; Set decimal mode
|
|
ADC #$09 ; Add in decimal mode
|
|
SBC #$05 ; Subtract in decimal mode
|
|
CLD ; Clear decimal mode
|
|
|
|
; Complex addressing modes with concrete values
|
|
LDA $1234,X ; Absolute,X
|
|
LDA $1234,Y ; Absolute,Y
|
|
LDA ($12,X) ; Indirect,X
|
|
LDA ($34),Y ; Indirect,Y
|
|
JMP ($5678) ; Indirect
|
|
|
|
; Specific tests for page boundary crossing
|
|
; Set X and Y to values that will cause page crosses
|
|
LDX #$FF
|
|
LDY #$FF
|
|
|
|
; These will cross page boundaries with the above X/Y values
|
|
LDA $1001,X ; Cross to $1100
|
|
LDA $1001,Y ; Cross to $1100
|
|
LDA ($01),Y ; Indirect cross
|
|
|
|
; Specific tests for zero page wrap-around
|
|
LDX #$FF
|
|
LDA $01,X ; Should wrap to $0000
|
|
|
|
; Complete set of stack operations
|
|
LDX #$FF
|
|
TXS ; Set stack pointer to $FF
|
|
PHA ; Push A
|
|
PHP ; Push processor status
|
|
PLA ; Pull A
|
|
PLP ; Pull processor status
|
|
|
|
; Test every possible branch
|
|
LDA #$80 ; Set N flag
|
|
BPL no_branch1 ; Should not branch
|
|
LDA #$00 ; Clear N flag
|
|
BMI no_branch2 ; Should not branch
|
|
no_branch1:
|
|
no_branch2:
|
|
|
|
LDA #$00
|
|
BEQ branch1 ; Should branch
|
|
LDA #$01 ; This should be skipped
|
|
branch1:
|
|
LDA #$01
|
|
BNE branch2 ; Should branch
|
|
LDA #$02 ; This should be skipped
|
|
branch2:
|
|
|
|
CLC ; Clear carry
|
|
BCS no_branch3 ; Should not branch
|
|
SEC ; Set carry
|
|
BCC no_branch4 ; Should not branch
|
|
no_branch3:
|
|
no_branch4:
|
|
|
|
CLV ; Clear overflow
|
|
BVS no_branch5 ; Should not branch
|
|
; Need to set overflow - more complex
|
|
; For test purposes we'll use a .byte directive
|
|
.byte $B8 ; CLV
|
|
.byte $70, $FE ; BVS -2 (back to the CLV)
|
|
no_branch5:
|
|
|
|
; Exhaustive testing of BIT instruction
|
|
LDA #$C0 ; Set bits 7 and 6
|
|
STA $30 ; Store in zero page
|
|
BIT $30 ; Test BIT with N and V set
|
|
|
|
LDA #$00 ; Clear all bits
|
|
STA $31 ; Store in zero page
|
|
BIT $31 ; Test BIT with all flags cleared
|
|
|
|
; Test all compare instructions
|
|
LDA #$50
|
|
CMP #$30 ; Compare with smaller (carry set)
|
|
CMP #$50 ; Compare with equal (carry set, zero set)
|
|
CMP #$70 ; Compare with larger (carry clear)
|
|
|
|
LDX #$40
|
|
CPX #$20 ; Compare X with smaller
|
|
CPX #$40 ; Compare X with equal
|
|
CPX #$60 ; Compare X with larger
|
|
|
|
|
|
LDY #$60
|
|
CPY #$40 ; Compare Y with smaller
|
|
CPY #$60 ; Compare Y with equal
|
|
CPY #$80 ; Compare Y with larger
|
|
|
|
; Test shifts and rotates with various values
|
|
LDA #$01 ; Test shift left with 1
|
|
ASL A ; Should become 2
|
|
|
|
LDA #$80 ; Test shift left with sign bit
|
|
ASL A ; Should set carry, clear result
|
|
|
|
LDA #$01 ; Test rotate left with 1
|
|
CLC ; Clear carry
|
|
ROL A ; Should become 2
|
|
|
|
LDA #$80 ; Test rotate left with sign bit
|
|
CLC ; Clear carry
|
|
ROL A ; Should set carry, clear result
|
|
|
|
LDA #$80 ; Test shift right with sign bit
|
|
LSR A ; Should become 0x40, clear carry
|
|
|
|
LDA #$01 ; Test shift right with 1
|
|
LSR A ; Should become 0, set carry
|
|
|
|
LDA #$01 ; Test rotate right with 1
|
|
CLC ; Clear carry
|
|
ROR A ; Should become 0
|
|
|
|
LDA #$01 ; Test rotate right with 1
|
|
SEC ; Set carry
|
|
ROR A ; Should become 0x80 + carry
|
|
|
|
; Exhaustive increment/decrement tests
|
|
LDA #$FF
|
|
STA $40 ; Store FF in memory
|
|
INC $40 ; Should wrap to 0
|
|
|
|
LDA #$01
|
|
STA $41 ; Store 01 in memory
|
|
DEC $41 ; Should become 0
|
|
|
|
LDX #$FF ; X = FF
|
|
INX ; Should wrap to 0
|
|
|
|
LDX #$01 ; X = 01
|
|
DEX ; Should become 0
|
|
|
|
LDY #$FF ; Y = FF
|
|
INY ; Should wrap to 0
|
|
|
|
LDY #$01 ; Y = 01
|
|
DEY ; Should become 0
|
|
|
|
; Test conditional behavior after operations
|
|
LDA #$00
|
|
BEQ is_zero1 ; Should branch
|
|
BRK ; Should be skipped
|
|
is_zero1:
|
|
|
|
LDA #$40
|
|
BNE not_zero1 ; Should branch
|
|
BRK ; Should be skipped
|
|
not_zero1:
|
|
|
|
LDA #$80
|
|
BMI is_negative1 ; Should branch
|
|
BRK ; Should be skipped
|
|
is_negative1:
|
|
|
|
LDA #$7F
|
|
BPL is_positive1 ; Should branch
|
|
BRK ; Should be skipped
|
|
is_positive1:
|
|
|
|
; Test unofficial instructions with various values
|
|
|
|
; SLO (ASL memory, then ORA with A)
|
|
LDA #$01
|
|
STA $50
|
|
LDA #$02
|
|
SLO $50 ; $50 becomes $02, A becomes $02|$02 = $02
|
|
|
|
; RLA (ROL memory, then AND with A)
|
|
LDA #$03
|
|
STA $51
|
|
LDA #$01
|
|
SEC ; Set carry
|
|
RLA $51 ; $51 becomes $07, A becomes $01&$07 = $01
|
|
|
|
; SRE (LSR memory, then EOR with A)
|
|
LDA #$01
|
|
STA $52
|
|
LDA #$03
|
|
SRE $52 ; $52 becomes $00 with carry, A becomes $03^$00 = $03
|
|
|
|
; RRA (ROR memory, then ADC with A)
|
|
LDA #$80
|
|
STA $53
|
|
LDA #$01
|
|
CLC ; Clear carry
|
|
RRA $53 ; $53 becomes $40, A becomes $01+$40 = $41
|
|
|
|
; Test memory wrapping behavior
|
|
LDX #$FF
|
|
LDA $00,X ; Zero page wrap from $FF to $00
|
|
|
|
; Test processor flags after arithmetical operations
|
|
CLC
|
|
LDA #$7F
|
|
ADC #$01 ; Should set overflow and negative (0x7F + 0x01 = 0x80)
|
|
|
|
SEC
|
|
LDA #$80
|
|
SBC #$01 ; Should set overflow and clear negative (0x80 - 0x01 = 0x7F)
|
|
|
|
; More page boundary crossings
|
|
LDX #$FF
|
|
LDA $1000,X ; Read from $10FF
|
|
|
|
LDY #$FF
|
|
LDA $1000,Y ; Read from $10FF
|
|
|
|
LDY #$FF
|
|
LDA ($80),Y ; If $80/$81 contains $1000, reads from $10FF
|
|
|
|
; Comprehensive unofficial opcodes testing
|
|
; ANC (AND immediate then copy bit 7 to carry)
|
|
LDA #$80
|
|
ANC #$FF ; Should set carry
|
|
|
|
LDA #$7F
|
|
ANC #$FF ; Should clear carry
|
|
|
|
; ALR/ASR (AND immediate then LSR)
|
|
LDA #$FF
|
|
ALR #$55 ; A becomes $55, then $2A with carry set
|
|
|
|
; ARR (AND immediate then ROR)
|
|
LDA #$FF
|
|
SEC
|
|
ARR #$55 ; A becomes $55
|