; 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