rusted-nes/full.asm

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