6502 Instruction Set

HILO-NIBBLE
‐0‐1‐2‐3‐4‐5‐6‐7‐8‐9‐A‐B‐C‐D‐E‐F
0‐BRK implORA X,ind---------ORA zpgASL zpg---PHP implORA #ASL A------ORA absASL abs---
1‐BPL relORA ind,Y---------ORA zpg,XASL zpg,X---CLC implORA abs,Y---------ORA abs,XASL abs,X---
2‐JSR absAND X,ind------BIT zpgAND zpgROL zpg---PLP implAND #ROL A---BIT absAND absROL abs---
3‐BMI relAND ind,Y---------AND zpg,XROL zpg,X---SEC implAND abs,Y---------AND abs,XROL abs,X---
4‐RTI implEOR X,ind---------EOR zpgLSR zpg---PHA implEOR #LSR A---JMP absEOR absLSR abs---
5‐BVC relEOR ind,Y---------EOR zpg,XLSR zpg,X---CLI implEOR abs,Y---------EOR abs,XLSR abs,X---
6‐RTS implADC X,ind---------ADC zpgROR zpg---PLA implADC #ROR A---JMP indADC absROR abs---
7‐BVS relADC ind,Y---------ADC zpg,XROR zpg,X---SEI implADC abs,Y---------ADC abs,XROR abs,X---
8‐---STA X,ind------STY zpgSTA zpgSTX zpg---DEY impl---TXA impl---STY absSTA absSTX abs---
9‐BCC relSTA ind,Y------STY zpg,XSTA zpg,XSTX zpg,Y---TYA implSTA abs,YTXS impl------STA abs,X------
A‐LDY #LDA X,indLDX #---LDY zpgLDA zpgLDX zpg---TAY implLDA #TAX impl---LDY absLDA absLDX abs---
B‐BCS relLDA ind,Y------LDY zpg,XLDA zpg,XLDX zpg,Y---CLV implLDA abs,YTSX impl---LDY abs,XLDA abs,XLDX abs,Y---
C‐CPY #CMP X,ind------CPY zpgCMP zpgDEC zpg---INY implCMP #DEX impl---CPY absCMP absDEC abs---
D‐BNE relCMP ind,Y---------CMP zpg,XDEC zpg,X---CLD implCMP abs,Y---------CMP abs,XDEC abs,X---
E‐CPX #SBC X,ind------CPX zpgSBC zpgINC zpg---INX implSBC #NOP impl---CPX absSBC absINC abs---
F‐BEQ relSBC ind,Y---------SBC zpg,XINC zpg,X---SED implSBC abs,Y---------SBC abs,XINC abs,X---

Description

Address Modes

AAccumulatorOPC Aoperand is AC (implied single byte instruction)
absabsoluteOPC $LLHHoperand is address $HHLL *
abs,Xabsolute, X-indexedOPC $LLHH,Xoperand is address; effective address is address incremented by X with carry **
abs,Yabsolute, Y-indexedOPC $LLHH,Yoperand is address; effective address is address incremented by Y with carry **
#immediateOPC #$BBoperand is byte BB
implimpliedOPCoperand implied
indindirectOPC ($LLHH)operand is address; effective address is contents of word at address: C.w($HHLL)
X,indX-indexed, indirectOPC ($LL,X)operand is zeropage address; effective address is word in (LL + X, LL + X + 1), inc. without carry: C.w($00LL + X)
ind,Yindirect, Y-indexedOPC ($LL),Yoperand is zeropage address; effective address is word in (LL, LL + 1) incremented by Y with carry: C.w($00LL) + Y
relrelativeOPC $BBbranch target is PC + signed offset BB ***
zpgzeropageOPC $LLoperand is zeropage address (hi-byte is zero, address = $00LL)
zpg,Xzeropage, X-indexedOPC $LL,Xoperand is zeropage address; effective address is address incremented by X without carry **
zpg,Yzeropage, Y-indexedOPC $LL,Yoperand is zeropage address; effective address is address incremented by Y without carry **
*
16-bit address words are little endian, lo(w)-byte first, followed by the hi(gh)-byte.
(An assembler will use a human readable, big-endian notation as in $HHLL.)
**
The available 16-bit address space is conceived as consisting of pages of 256 bytes each, with
address hi-bytes represententing the page index. An increment with carry may affect the hi-byte
and may thus result in a crossing of page boundaries, adding an extra cycle to the execution.
Increments without carry do not affect the hi-byte of an address and no page transitions do occur.
Generally, increments of 16-bit addresses include a carry, increments of zeropage addresses don't.
Notably this is not related in any way to the state of the carry bit of the accumulator.
***
Branch offsets are signed 8-bit values, -128 ... +127, negative offsets in two's complement.
Page transitions may occur and add an extra cycle to the exucution.

Instructions by Name

ADC
add with carry
AND
and (with accumulator)
ASL
arithmetic shift left
BCC
branch on carry clear
BCS
branch on carry set
BEQ
branch on equal (zero set)
BIT
bit test
BMI
branch on minus (negative set)
BNE
branch on not equal (zero clear)
BPL
branch on plus (negative clear)
BRK
break / interrupt
BVC
branch on overflow clear
BVS
branch on overflow set
CLC
clear carry
CLD
clear decimal
CLI
clear interrupt disable
CLV
clear overflow
CMP
compare (with accumulator)
CPX
compare with X
CPY
compare with Y
DEC
decrement
DEX
decrement X
DEY
decrement Y
EOR
exclusive or (with accumulator)
INC
increment
INX
increment X
INY
increment Y
JMP
jump
JSR
jump subroutine
LDA
load accumulator
LDX
load X
LDY
load Y
LSR
logical shift right
NOP
no operation
ORA
or with accumulator
PHA
push accumulator
PHP
push processor status (SR)
PLA
pull accumulator
PLP
pull processor status (SR)
ROL
rotate left
ROR
rotate right
RTI
return from interrupt
RTS
return from subroutine
SBC
subtract with carry
SEC
set carry
SED
set decimal
SEI
set interrupt disable
STA
store accumulator
STX
store X
STY
store Y
TAX
transfer accumulator to X
TAY
transfer accumulator to Y
TSX
transfer stack pointer to X
TXA
transfer X to accumulator
TXS
transfer X to stack pointer
TYA
transfer Y to accumulator

Registers

PCprogram counter(16 bit)
ACaccumulator(8 bit)
XX register(8 bit)
YY register(8 bit)
SRstatus register [NV-BDIZC](8 bit)
SPstack pointer(8 bit)

Note: The status register (SR) is also known as the P register.

SR Flags (bit 7 to bit 0)

NNegative
VOverflow
-ignored
BBreak
DDecimal (use BCD for arithmetics)
IInterrupt (IRQ disable)
ZZero
CCarry

Note: The break flag is not an actual flag implemented in a register, and rather
appears only, when the status register is pushed onto or pulled from the stack.
When pushed, it will be 1 when transfered by a BRK or PHP instruction, and
zero otherwise (i.e., when pushed by a hardware interrupt).
When pulled into the status register (by PLP or on RTI), it will be ignored.

In other words, the break flag will be inserted, whenever the status register
is transferred to the stack by software (BRK or PHP), and will be zero, when
transferred by hardware. Since there is no actual slot for the break flag, it
will be always ignored, when retrieved (PLP or RTI).
The break flag is not accessed by the CPU at anytime and there is no internal
representation. Its purpose is more for patching, to discern an interrupt caused
by a BRK instruction from a normal interrupt initiated by hardware.

Processor Stack

LIFO, top down, 8 bit range, 0x0100 - 0x01FF

Bytes, Words, Addressing

8 bit bytes, 16 bit words in lobyte-hibyte representation (Little-Endian).
16 bit address range, operands follow instruction codes.

Signed values are two's complement, sign in bit 7 (most significant bit).
(%11111111 = $FF = -1, %10000000 = $80 = -128, %01111111 = $7F = +127)

Vendor

MOS Technology, 1975

MOS Techology 6502 MPU

Image: Wikimedia Commons.

6502 Instructions in Detail

ADC

Add Memory to Accumulator with Carry

A + M + C -> A, C

NZCIDV
+++--+
addressingassembleropcbytescycles
immediateADC #oper6922
zeropageADC oper6523
zeropage,XADC oper,X7524
absoluteADC oper6D34
absolute,XADC oper,X7D34*
absolute,YADC oper,Y7934*
(indirect,X)ADC (oper,X)6126
(indirect),YADC (oper),Y7125*
AND

AND Memory with Accumulator

A AND M -> A

NZCIDV
++----
addressingassembleropcbytescycles
immediateAND #oper2922
zeropageAND oper2523
zeropage,XAND oper,X3524
absoluteAND oper2D34
absolute,XAND oper,X3D34*
absolute,YAND oper,Y3934*
(indirect,X)AND (oper,X)2126
(indirect),YAND (oper),Y3125*
ASL

Shift Left One Bit (Memory or Accumulator)

C <- [76543210] <- 0

NZCIDV
+++---
addressingassembleropcbytescycles
accumulatorASL A0A12
zeropageASL oper0625
zeropage,XASL oper,X1626
absoluteASL oper0E36
absolute,XASL oper,X1E37
BCC

Branch on Carry Clear

branch on C = 0

NZCIDV
------
addressingassembleropcbytescycles
relativeBCC oper9022**
BCS

Branch on Carry Set

branch on C = 1

NZCIDV
------
addressingassembleropcbytescycles
relativeBCS operB022**
BEQ

Branch on Result Zero

branch on Z = 1

NZCIDV
------
addressingassembleropcbytescycles
relativeBEQ operF022**
BIT

Test Bits in Memory with Accumulator

bits 7 and 6 of operand are transfered to bit 7 and 6 of SR (N,V);
the zero-flag is set to the result of operand AND accumulator.

A AND M, M7 -> N, M6 -> V

NZCIDV
M7+---M6
addressingassembleropcbytescycles
zeropageBIT oper2423
absoluteBIT oper2C34
BMI

Branch on Result Minus

branch on N = 1

NZCIDV
------
addressingassembleropcbytescycles
relativeBMI oper3022**
BNE

Branch on Result not Zero

branch on Z = 0

NZCIDV
------
addressingassembleropcbytescycles
relativeBNE operD022**
BPL

Branch on Result Plus

branch on N = 0

NZCIDV
------
addressingassembleropcbytescycles
relativeBPL oper1022**
BRK

Force Break

BRK initiates a software interrupt similar to a hardware
interrupt (IRQ). The return address pushed to the stack is
PC+2, providing an extra byte of spacing for a break mark
(identifying a reason for the break.)
The status register will be pushed to the stack with the break
flag set to 1. However, when retrieved during RTI or by a PLP
instruction, the break flag will be ignored.
The interrupt disable flag is not set automatically.

interrupt,
push PC+2, push SR

NZCIDV
---1--
addressingassembleropcbytescycles
impliedBRK0017
BVC

Branch on Overflow Clear

branch on V = 0

NZCIDV
------
addressingassembleropcbytescycles
relativeBVC oper5022**
BVS

Branch on Overflow Set

branch on V = 1

NZCIDV
------
addressingassembleropcbytescycles
relativeBVS oper7022**
CLC

Clear Carry Flag

0 -> C

NZCIDV
--0---
addressingassembleropcbytescycles
impliedCLC1812
CLD

Clear Decimal Mode

0 -> D

NZCIDV
----0-
addressingassembleropcbytescycles
impliedCLDD812
CLI

Clear Interrupt Disable Bit

0 -> I

NZCIDV
---0--
addressingassembleropcbytescycles
impliedCLI5812
CLV

Clear Overflow Flag

0 -> V

NZCIDV
-----0
addressingassembleropcbytescycles
impliedCLVB812
CMP

Compare Memory with Accumulator

A - M

NZCIDV
+++---
addressingassembleropcbytescycles
immediateCMP #operC922
zeropageCMP operC523
zeropage,XCMP oper,XD524
absoluteCMP operCD34
absolute,XCMP oper,XDD34*
absolute,YCMP oper,YD934*
(indirect,X)CMP (oper,X)C126
(indirect),YCMP (oper),YD125*
CPX

Compare Memory and Index X

X - M

NZCIDV
+++---
addressingassembleropcbytescycles
immediateCPX #operE022
zeropageCPX operE423
absoluteCPX operEC34
CPY

Compare Memory and Index Y

Y - M

NZCIDV
+++---
addressingassembleropcbytescycles
immediateCPY #operC022
zeropageCPY operC423
absoluteCPY operCC34
DEC

Decrement Memory by One

M - 1 -> M

NZCIDV
++----
addressingassembleropcbytescycles
zeropageDEC operC625
zeropage,XDEC oper,XD626
absoluteDEC operCE36
absolute,XDEC oper,XDE37
DEX

Decrement Index X by One

X - 1 -> X

NZCIDV
++----
addressingassembleropcbytescycles
impliedDEXCA12
DEY

Decrement Index Y by One

Y - 1 -> Y

NZCIDV
++----
addressingassembleropcbytescycles
impliedDEY8812
EOR

Exclusive-OR Memory with Accumulator

A EOR M -> A

NZCIDV
++----
addressingassembleropcbytescycles
immediateEOR #oper4922
zeropageEOR oper4523
zeropage,XEOR oper,X5524
absoluteEOR oper4D34
absolute,XEOR oper,X5D34*
absolute,YEOR oper,Y5934*
(indirect,X)EOR (oper,X)4126
(indirect),YEOR (oper),Y5125*
INC

Increment Memory by One

M + 1 -> M

NZCIDV
++----
addressingassembleropcbytescycles
zeropageINC operE625
zeropage,XINC oper,XF626
absoluteINC operEE36
absolute,XINC oper,XFE37
INX

Increment Index X by One

X + 1 -> X

NZCIDV
++----
addressingassembleropcbytescycles
impliedINXE812
INY

Increment Index Y by One

Y + 1 -> Y

NZCIDV
++----
addressingassembleropcbytescycles
impliedINYC812
JMP

Jump to New Location

(PC+1) -> PCL
(PC+2) -> PCH

NZCIDV
------
addressingassembleropcbytescycles
absoluteJMP oper4C33
indirectJMP (oper)6C35
JSR

Jump to New Location Saving Return Address

push (PC+2),
(PC+1) -> PCL
(PC+2) -> PCH

NZCIDV
------
addressingassembleropcbytescycles
absoluteJSR oper2036
LDA

Load Accumulator with Memory

M -> A

NZCIDV
++----
addressingassembleropcbytescycles
immediateLDA #operA922
zeropageLDA operA523
zeropage,XLDA oper,XB524
absoluteLDA operAD34
absolute,XLDA oper,XBD34*
absolute,YLDA oper,YB934*
(indirect,X)LDA (oper,X)A126
(indirect),YLDA (oper),YB125*
LDX

Load Index X with Memory

M -> X

NZCIDV
++----
addressingassembleropcbytescycles
immediateLDX #operA222
zeropageLDX operA623
zeropage,YLDX oper,YB624
absoluteLDX operAE34
absolute,YLDX oper,YBE34*
LDY

Load Index Y with Memory

M -> Y

NZCIDV
++----
addressingassembleropcbytescycles
immediateLDY #operA022
zeropageLDY operA423
zeropage,XLDY oper,XB424
absoluteLDY operAC34
absolute,XLDY oper,XBC34*
LSR

Shift One Bit Right (Memory or Accumulator)

0 -> [76543210] -> C

NZCIDV
0++---
addressingassembleropcbytescycles
accumulatorLSR A4A12
zeropageLSR oper4625
zeropage,XLSR oper,X5626
absoluteLSR oper4E36
absolute,XLSR oper,X5E37
NOP

No Operation

---

NZCIDV
------
addressingassembleropcbytescycles
impliedNOPEA12
ORA

OR Memory with Accumulator

A OR M -> A

NZCIDV
++----
addressingassembleropcbytescycles
immediateORA #oper0922
zeropageORA oper0523
zeropage,XORA oper,X1524
absoluteORA oper0D34
absolute,XORA oper,X1D34*
absolute,YORA oper,Y1934*
(indirect,X)ORA (oper,X)0126
(indirect),YORA (oper),Y1125*
PHA

Push Accumulator on Stack

push A

NZCIDV
------
addressingassembleropcbytescycles
impliedPHA4813
PHP

Push Processor Status on Stack

The status register will be pushed with the break
flag and bit 5 set to 1.

push SR

NZCIDV
------
addressingassembleropcbytescycles
impliedPHP0813
PLA

Pull Accumulator from Stack

pull A

NZCIDV
++----
addressingassembleropcbytescycles
impliedPLA6814
PLP

Pull Processor Status from Stack

The status register will be pulled with the break
flag and bit 5 ignored.

pull SR

NZCIDV
from stack
addressingassembleropcbytescycles
impliedPLP2814
ROL

Rotate One Bit Left (Memory or Accumulator)

C <- [76543210] <- C

NZCIDV
+++---
addressingassembleropcbytescycles
accumulatorROL A2A12
zeropageROL oper2625
zeropage,XROL oper,X3626
absoluteROL oper2E36
absolute,XROL oper,X3E37
ROR

Rotate One Bit Right (Memory or Accumulator)

C -> [76543210] -> C

NZCIDV
+++---
addressingassembleropcbytescycles
accumulatorROR A6A12
zeropageROR oper6625
zeropage,XROR oper,X7626
absoluteROR oper6E36
absolute,XROR oper,X7E37
RTI

Return from Interrupt

The status register is pulled with the break flag
and bit 5 ignored. Then PC is pulled from the stack.

pull SR, pull PC

NZCIDV
from stack
addressingassembleropcbytescycles
impliedRTI4016
RTS

Return from Subroutine

pull PC, PC+1 -> PC

NZCIDV
------
addressingassembleropcbytescycles
impliedRTS6016
SBC

Subtract Memory from Accumulator with Borrow

A - M - C -> A

NZCIDV
+++--+
addressingassembleropcbytescycles
immediateSBC #operE922
zeropageSBC operE523
zeropage,XSBC oper,XF524
absoluteSBC operED34
absolute,XSBC oper,XFD34*
absolute,YSBC oper,YF934*
(indirect,X)SBC (oper,X)E126
(indirect),YSBC (oper),YF125*
SEC

Set Carry Flag

1 -> C

NZCIDV
--1---
addressingassembleropcbytescycles
impliedSEC3812
SED

Set Decimal Flag

1 -> D

NZCIDV
----1-
addressingassembleropcbytescycles
impliedSEDF812
SEI

Set Interrupt Disable Status

1 -> I

NZCIDV
---1--
addressingassembleropcbytescycles
impliedSEI7812
STA

Store Accumulator in Memory

A -> M

NZCIDV
------
addressingassembleropcbytescycles
zeropageSTA oper8523
zeropage,XSTA oper,X9524
absoluteSTA oper8D34
absolute,XSTA oper,X9D35
absolute,YSTA oper,Y9935
(indirect,X)STA (oper,X)8126
(indirect),YSTA (oper),Y9126
STX

Store Index X in Memory

X -> M

NZCIDV
------
addressingassembleropcbytescycles
zeropageSTX oper8623
zeropage,YSTX oper,Y9624
absoluteSTX oper8E34
STY

Sore Index Y in Memory

Y -> M

NZCIDV
------
addressingassembleropcbytescycles
zeropageSTY oper8423
zeropage,XSTY oper,X9424
absoluteSTY oper8C34
TAX

Transfer Accumulator to Index X

A -> X

NZCIDV
++----
addressingassembleropcbytescycles
impliedTAXAA12
TAY

Transfer Accumulator to Index Y

A -> Y

NZCIDV
++----
addressingassembleropcbytescycles
impliedTAYA812
TSX

Transfer Stack Pointer to Index X

SP -> X

NZCIDV
++----
addressingassembleropcbytescycles
impliedTSXBA12
TXA

Transfer Index X to Accumulator

X -> A

NZCIDV
++----
addressingassembleropcbytescycles
impliedTXA8A12
TXS

Transfer Index X to Stack Register

X -> SP

NZCIDV
------
addressingassembleropcbytescycles
impliedTXS9A12
TYA

Transfer Index Y to Accumulator

Y -> A

NZCIDV
++----
addressingassembleropcbytescycles
impliedTYA9812
*
add 1 to cycles if page boundary is crossed
**
add 1 to cycles if branch occurs on same page
add 2 to cycles if branch occurs to different page

Legend to Flags:

+
modified
-
not modified
1
set
0
cleared
M6
memory bit 6
M7
memory bit 7

Note on assembler syntax:
Some assemblers employ "OPC *oper" or a ".b" extension
to the mneomonic for forced zeropage addressing.

"Illegal" Opcodes and Undocumented Instructions

The following instructions are undocumented are not guaranteed to work.
Some are highly unstable, some may even start two asynchronous threads competing in race condition with the winner determined by such miniscule factors as temperature or minor differences in the production series, at other times, the outcome depends on the exact values involved and the chip series.

Use with care and at your own risk.

There are several mnemonics for various opcodes. Here, they are (mostly) the same as those used by the ACME and DASM assemblers with known synonyms provided in parentheses:

"Illegal" Opcodes in Details

Legend to markers used in the instruction details:

*
add 1 to cycles if page boundary is crossed
unstable
††
highly unstable
ALR (ASR)

AND oper + LSR

A AND oper, 0 -> [76543210] -> C

NZCIDV
+++---
addressingassembleropcbytescycles
immediateALR #oper4B22
ANC

AND oper + set C as ASL

A AND oper, bit(7) -> C

NZCIDV
+++---
addressingassembleropcbytescycles
immediateANC #oper0B22
ANC (ANC2)

AND oper + set C as ROL

effectively the same as instr. 0B

A AND oper, bit(7) -> C

NZCIDV
+++---
addressingassembleropcbytescycles
immediateANC #oper2B22
ANE (XAA)

* AND X + AND oper

Highly unstable, do not use.

A base value in A is determined based on the contets of A and a constant, which may be typically $00, $ff, $ee, etc. The value of this constant depends on temerature, the chip series, and maybe other factors, as well.
In order to eliminate these uncertaincies from the equation, use either 0 as the operand or a value of $FF in the accumulator.

(A OR CONST) AND X AND oper -> A

NZCIDV
++----
addressingassembleropcbytescycles
immediateANE #oper8B22 ††
ARR

AND oper + ROR

This operation involves the adder:
V-flag is set according to (A AND oper) + oper
The carry is not set, but bit 7 (sign) is exchanged with the carry

A AND oper, C -> [76543210] -> C

NZCIDV
+++--+
addressingassembleropcbytescycles
immediateARR #oper6B22
DCP (DCM)

DEC oper + CMP oper

M - 1 -> M, A - M

NZCIDV
+++---
addressingassembleropcbytescycles
zeropageDCP operC725
zeropage,XDCP oper,XD726
absoluteDCP operCF36
absolut,XDCP oper,XDF37
absolut,YDCP oper,YDB37
(indirect,X)DCP (oper,X)C328
(indirect),YDCP (oper),YD328
ISC (ISB, INS)

INC oper + SBC oper

M + 1 -> M, A - M - C -> A

NZCIDV
+++--+
addressingassembleropcbytescycles
zeropageISC operE725
zeropage,XISC oper,XF726
absoluteISC operEF36
absolut,XISC oper,XFF37
absolut,YISC oper,YFB37
(indirect,X)ISC (oper,X)E328
(indirect),YISC (oper),YF324
LAS (LAR)

LDA/TSX oper

M AND SP -> A, X, SP

NZCIDV
++----
addressingassembleropcbytescycles
absolut,YLAS oper,YBB34*
LAX

LDA oper + LDX oper

M -> A -> X

NZCIDV
++----
addressingassembleropcbytescycles
zeropageLAX operA723
zeropage,YLAX oper,YB724
absoluteLAX operAF34
absolut,YLAX oper,YBF34*
(indirect,X)LAX (oper,X)A326
(indirect),YLAX (oper),YB325*
LXA (LAX immediate)

Store * AND oper in A and X

Highly unstable, involves a 'magic' constant, see ANE

(A OR CONST) AND oper -> A -> X

NZCIDV
++----
addressingassembleropcbytescycles
immediateLXA #operAB22 ††
RLA

ROL oper + AND oper

M = C <- [76543210] <- C, A AND M -> A

NZCIDV
+++---
addressingassembleropcbytescycles
zeropageRLA oper2725
zeropage,XRLA oper,X3726
absoluteRLA oper2F36
absolut,XRLA oper,X3F37
absolut,YRLA oper,Y3B37
(indirect,X)RLA (oper,X)2328
(indirect),YRLA (oper),Y3328
RRA

ROR oper + ADC oper

M = C -> [76543210] -> C, A + M + C -> A, C

NZCIDV
+++--+
addressingassembleropcbytescycles
zeropageRRA oper6725
zeropage,XRRA oper,X7726
absoluteRRA oper6F36
absolut,XRRA oper,X7F37
absolut,YRRA oper,Y7B37
(indirect,X)RRA (oper,X)6328
(indirect),YRRA (oper),Y7328
SAX (AXS, AAX)

A and X are put on the bus at the same time (resulting effectively in an AND operation) and stored in M

A AND X -> M

NZCIDV
------
addressingassembleropcbytescycles
zeropageSAX oper8723
zeropage,YSAX oper,Y9724
absoluteSAX oper8F34
(indirect,X)SAX (oper,X)8326
SBX (AXS, SAX)

CMP and DEX at once, sets flags like CMP

(A AND X) - oper -> X

NZCIDV
+++---
addressingassembleropcbytescycles
immediateSBX #operCB22
SHA (AHX, AXA)

Stores A AND X AND (high-byte of addr. + 1) at addr.

unstable: sometimes 'AND (H+1)' is dropped, page boundary crossings may not work (with the high-byte of the value used as the high-byte of the address)

A AND X AND (H+1) -> M

NZCIDV
------
addressingassembleropcbytescycles
absolut,YSHA oper,Y9F35
(indirect),YSHA (oper),Y9326
SHX (A11, SXA, XAS)

Stores X AND (high-byte of addr. + 1) at addr.

unstable: sometimes 'AND (H+1)' is dropped, page boundary crossings may not work (with the high-byte of the value used as the high-byte of the address)

X AND (H+1) -> M

NZCIDV
------
addressingassembleropcbytescycles
absolut,YSHX oper,Y9E35
SHY (A11, SYA, SAY)

Stores Y AND (high-byte of addr. + 1) at addr.

unstable: sometimes 'AND (H+1)' is dropped, page boundary crossings may not work (with the high-byte of the value used as the high-byte of the address)

Y AND (H+1) -> M

NZCIDV
------
addressingassembleropcbytescycles
absolut,XSHY oper,X9C35
SLO (ASO)

ASL oper + ORA oper

M = C <- [76543210] <- 0, A OR M -> A

NZCIDV
+++---
addressingassembleropcbytescycles
zeropageSLO oper0725
zeropage,XSLO oper,X1726
absoluteSLO oper0F36
absolut,XSLO oper,X1F37
absolut,YSLO oper,Y1B37
(indirect,X)SLO (oper,X)0328
(indirect),YSLO (oper),Y1328
SRE (LSE)

LSR oper + EOR oper

M = 0 -> [76543210] -> C, A EOR M -> A

NZCIDV
+++---
addressingassembleropcbytescycles
zeropageSRE oper4725
zeropage,XSRE oper,X5726
absoluteSRE oper4F36
absolut,XSRE oper,X5F37
absolut,YSRE oper,Y5B37
(indirect,X)SRE (oper,X)4328
(indirect),YSRE (oper),Y5328
TAS (XAS, SHS)

Puts A AND X in SP and stores A AND X AND (high-byte of addr. + 1) at addr.

unstable: sometimes 'AND (H+1)' is dropped, page boundary crossings may not work (with the high-byte of the value used as the high-byte of the address)

A AND X -> SP, A AND X AND (H+1) -> M

NZCIDV
------
addressingassembleropcbytescycles
absolut,YTAS oper,Y9B35
USBC (SBC)

SBC oper + NOP

effectively same as normal SBC immediate, instr. E9.

A - M - C -> A

NZCIDV
+++--+
addressingassembleropcbytescycles
immediateUSBC #operEB22
NOPs (including DOP, TOP)

Instructions effecting in 'no operations' in various address modes. Operands are ignored.

NZCIDV
------
opcaddressingbytescycles
1Aimplied12
3Aimplied12
5Aimplied12
7Aimplied12
DAimplied12
FAimplied12
80immediate22
82immediate22
89immediate22
C2immediate22
E2immediate22
04zeropage23
44zeropage23
64zeropage23
14zeropage,X24
34zeropage,X24
54zeropage,X24
74zeropage,X24
D4zeropage,X24
F4zeropage,X24
0Cabsolute34
1Cabsolut,X34*
3Cabsolut,X34*
5Cabsolut,X34*
7Cabsolut,X34*
DCabsolut,X34*
FCabsolut,X34*
JAM (KIL, HLT)

These instructions freeze the CPU.

The processor will be trapped infinitely in T1 phase with $FF on the data bus. — Reset required.

Instruction codes: 02, 12, 22, 32, 42, 52, 62, 72, 92, B2, D2, F2

Have a look at this table of the instruction layout in order to see how most of these
"illegal" instructions are a result of executing both instructions at c=1 and c=2 in
a given slot (same column, rows immediately above) at once.
Where c is the lowest two bits of the instruction code. E.g., "SAX abs", instruction
code $8F, binary 10001111, is "STA abs", 10001101 ($8D) and "STX abs", 10001110 ($8E).

Compare Instructions

The 6502 MPU features three basic compare instructions in various address modes:

InstructionComparison
CMPAccumulator and operand
CPXX register and operand
CPYY register and operand

The various compare instructions subtract the operand from the respective register
without setting the result and adjust the N, Z, and C flags accordingly.
Flags will be set as follows:

RelationNZC
register < operands00
register = operand011
register > operands01

s: N-flag is sign (bit 7) of 'register − operand'.

Mind that the negative flag is not significant, but all conditions may be evaluated
by checking the carry and/or zero flag(s).

6502 Jump Vectors and Stack Operations

The 256 bytes processor stack of the 6502 is located at $0100 ... $01FF in
memory, growing down from top to bottom.

There are three 2-byte address locations at the very top end of the 64K address
space serving as jump vectors for reset/startup and interrupt operations:

$FFFA, $FFFB ... NMI (Non-Maskable Interrupt) vector
$FFFC, $FFFD ... RES (Reset) vector
$FFFE, $FFFF ... IRQ (Interrupt Request) vector

At the occurrence of interrupt, the value of the program counter (PC) is put in
high-low order onto the stack, followed by the value currently in the status
register and control will be transferred to the address location found in the
respective interrupt vector. These are recovered from the stack at the end of
an interrupt routine by the RTI instruction.

6502 Interrupt Operations
(Image: MCS6502 Instruction Set Summary, MOS Technology, Inc.)

Similarly, as a JSR instruction is encountered, PC is dumped onto the stack
and recovered by the JSR instruction:

6502 Subroutine Operations
(Image: MCS6502 Instruction Set Summary, MOS Technology, Inc.)

The Break Flag and the Stack

Interrupts and stack operations involving the status register (or P register)
are the only instances, the break flag appears (namely on the stack).
It has no representation in the CPU and can't be accessed by any instruction.

Therefore, it's somewhat difficult to inspect the break flag in order to
discern a software interrupt (BRK) from a hardware interrupt (NMI or IRQ) and
the mechanism is seldom used. Accessing a break mark put in the extra byte
following a BRK instruction is even more cumbersome and probably involves
indexed zeropage operations.

Bit 5 (unused) of the status register will be set to 1, whenever the
register is pushed to the stack. Bits 5 and 4 will always be ignored, when
transferred to the status register.

E.g.,

1)

SR: N V - B D I Z C 0 0 - - 0 0 1 1 PHP -> 0 0 1 1 0 0 1 1 = $33 PLP <- 0 0 - - 0 0 1 1 = $03 but: PLA <- 0 0 1 1 0 0 1 1 = $33

2)

LDA #$32 ;00110010 PHA -> 0 0 1 1 0 0 1 0 = $32 PLP <- 0 0 - - 0 0 1 0 = $02

3)

LDA #$C0 PHA -> 1 1 0 0 0 0 0 0 = $C0 LDA #$08 PHA -> 0 0 0 0 1 0 0 0 = $08 LDA #$12 PHA -> 0 0 0 1 0 0 1 0 = $12 RTI SR: 0 0 - - 0 0 1 0 = $02 PC: $C008

Mind that most emulators are displaying the status register (SR or P) in the
state as it would be currently pushed to the stack, with bits 4 and 5 on, adding
a bias of $30 to the register value. Here, we chose to rather omit this virtual
presence of these bits, since there isn't really a slot for them in the hardware.

6502 Instruction Layout

The 6502 instruction table is laid out according to a pattern a-b-c, where
a and b are an octal number each, followed by a group of two binary digits c,
as in the bit-vector "aaabbbcc".

aaabbbcc
bit76543210
(0…7)(0…7)(0…3)

Example:
All ROR instructions share a = 3 and c = 2 (3b2) with the address mode in b.
At the same time, all instructions addressing the zero-page share b = 1 (a1c).
abc = 312  =>  ( 3 << 5 | 1 << 2 | 2 )  =  %011.001.10  =  $66  "ROR zpg".

Notably, there are no legal opcodes defined where c = 3, accounting for the
empty columns in the usual, hexadecimal view of the instruction table.
(For compactness empty rows where c = 3 are omitted from the tables below.)

The following table lists the instruction set, rows sorted by c, then a.

Generally, instructions of a kind are typically found in rows as a combination
of a and c, and address modes are in columns b.
However, there are a few exception to this rule, namely, where bits 0 of both
c and b are low (c = 0, 2; b = 0, 2, 4, 6) and combinations of c and b select
a group of related operations. (E.g., c=0 ∧ b=4: branch, c=0 ∧ b=6: set flag)

cab
01234567
00$00BRK impl$08PHP impl$10BPL rel$18CLC impl
1$20JSR abs$24BIT zpg$28PLP impl$2CBIT abs$30BMI rel$38SEC impl
2$40RTI impl$48PHA impl$4CJMP abs$50BVC rel$58CLI impl
3$60RTS impl$68PLA impl$6CJMP ind$70BVS rel$78SEI impl
4$84STY zpg$88DEY impl$8CSTY abs$90BCC rel$94STY zpg,X$98TYA impl
5$A0LDY #$A4LDY zpg$A8TAY impl$ACLDY abs$B0BCS rel$B4LDY zpg,X$B8CLV impl$BCLDY abs,X
6$C0CPY #$C4CPY zpg$C8INY impl$CCCPY abs$D0BNE rel$D8CLD impl
7$E0CPX #$E4CPX zpg$E8INX impl$ECCPX abs$F0BEQ rel$F8SED impl
10$01ORA X,ind$05ORA zpg$09ORA #$0DORA abs$11ORA ind,Y$15ORA zpg,X$19ORA abs,Y$1DORA abs,X
1$21AND X,ind$25AND zpg$29AND #$2DAND abs$31AND ind,Y$35AND zpg,X$39AND abs,Y$3DAND abs,X
2$41EOR X,ind$45EOR zpg$49EOR #$4DEOR abs$51EOR ind,Y$55EOR zpg,X$59EOR abs,Y$5DEOR abs,X
3$61ADC X,ind$65ADC zpg$69ADC #$6DADC abs$71ADC ind,Y$75ADC zpg,X$79ADC abs,Y$7DADC abs,X
4$81STA X,ind$85STA zpg$8DSTA abs$91STA ind,Y$95STA zpg,X$99STA abs,Y$9DSTA abs,X
5$A1LDA X,ind$A5LDA zpg$A9LDA #$ADLDA abs$B1LDA ind,Y$B5LDA zpg,X$B9LDA abs,Y$BDLDA abs,X
6$C1CMP X,ind$C5CMP zpg$C9CMP #$CDCMP abs$D1CMP ind,Y$D5CMP zpg,X$D9CMP abs,Y$DDCMP abs,X
7$E1SBC X,ind$E5SBC zpg$E9SBC #$EDSBC abs$F1SBC ind,Y$F5SBC zpg,X$F9SBC abs,Y$FDSBC abs,X
20$06ASL zpg$0AASL A$0EASL abs$16ASL zpg,X$1EASL abs,X
1$26ROL zpg$2AROL A$2EROL abs$36ROL zpg,X$3EROL abs,X
2$46LSR zpg$4ALSR A$4ELSR abs$56LSR zpg,X$5ELSR abs,X
3$66ROR zpg$6AROR A$6EROR abs$76ROR zpg,X$7EROR abs,X
4$86STX zpg$8ATXA impl$8ESTX abs$96STX zpg,Y$9ATXS impl
5$A2LDX #$A6LDX zpg$AATAX impl$AELDX abs$B6LDX zpg,Y$BATSX impl$BELDX abs,Y
6$C6DEC zpg$CADEX impl$CEDEC abs$D6DEC zpg,X$DEDEC abs,X
7$E6INC zpg$EANOP impl$EEINC abs$F6INC zpg,X$FEINC abs,X

Note: The operand of instructions like "ASL A" is often depicted as implied, as well.
Mind that, for any practical reasons, the two notations are interchangeable for any
instructions involving the accumulator. — However, there are subtle differences.

A rotated view, rows as combinations of c and b, and columns as a:

cba
01234567
00$00BRK impl$20JSR abs$40RTI impl$60RTS impl$A0LDY #$C0CPY #$E0CPX #
1$24BIT zpg$84STY zpg$A4LDY zpg$C4CPY zpg$E4CPX zpg
2$08PHP impl$28PLP impl$48PHA impl$68PLA impl$88DEY impl$A8TAY impl$C8INY impl$E8INX impl
3$2CBIT abs$4CJMP abs$6CJMP ind$8CSTY abs$ACLDY abs$CCCPY abs$ECCPX abs
4$10BPL rel$30BMI rel$50BVC rel$70BVS rel$90BCC rel$B0BCS rel$D0BNE rel$F0BEQ rel
5$94STY zpg,X$B4LDY zpg,X
6$18CLC impl$38SEC impl$58CLI impl$78SEI impl$98TYA impl$B8CLV impl$D8CLD impl$F8SED impl
7$BCLDY abs,X
10$01ORA X,ind$21AND X,ind$41EOR X,ind$61ADC X,ind$81STA X,ind$A1LDA X,ind$C1CMP X,ind$E1SBC X,ind
1$05ORA zpg$25AND zpg$45EOR zpg$65ADC zpg$85STA zpg$A5LDA zpg$C5CMP zpg$E5SBC zpg
2$09ORA #$29AND #$49EOR #$69ADC #$A9LDA #$C9CMP #$E9SBC #
3$0DORA abs$2DAND abs$4DEOR abs$6DADC abs$8DSTA abs$ADLDA abs$CDCMP abs$EDSBC abs
4$11ORA ind,Y$31AND ind,Y$51EOR ind,Y$71ADC ind,Y$91STA ind,Y$B1LDA ind,Y$D1CMP ind,Y$F1SBC ind,Y
5$15ORA zpg,X$35AND zpg,X$55EOR zpg,X$75ADC zpg,X$95STA zpg,X$B5LDA zpg,X$D5CMP zpg,X$F5SBC zpg,X
6$19ORA abs,Y$39AND abs,Y$59EOR abs,Y$79ADC abs,Y$99STA abs,Y$B9LDA abs,Y$D9CMP abs,Y$F9SBC abs,Y
7$1DORA abs,X$3DAND abs,X$5DEOR abs,X$7DADC abs,X$9DSTA abs,X$BDLDA abs,X$DDCMP abs,X$FDSBC abs,X
20$A2LDX #
1$06ASL zpg$26ROL zpg$46LSR zpg$66ROR zpg$86STX zpg$A6LDX zpg$C6DEC zpg$E6INC zpg
2$0AASL A$2AROL A$4ALSR A$6AROR A$8ATXA impl$AATAX impl$CADEX impl$EANOP impl
3$0EASL abs$2EROL abs$4ELSR abs$6EROR abs$8ESTX abs$AELDX abs$CEDEC abs$EEINC abs
4
5$16ASL zpg,X$36ROL zpg,X$56LSR zpg,X$76ROR zpg,X$96STX zpg,Y$B6LDX zpg,Y$D6DEC zpg,X$F6INC zpg,X
6$9ATXS impl$BATSX impl
7$1EASL abs,X$3EROL abs,X$5ELSR abs,X$7EROR abs,X$BELDX abs,Y$DEDEC abs,X$FEINC abs,X

Finally, a more complex view, the instruction set listed by rows as
combinations of a and c, and b in columns:

Address modes are either a property of b (even columns) or combinations
of b and c (odd columns with aspecific row-index modulus 3; i.e., every
third row in a given column). In those latter columns, first and third
rows (c = 0 and c = 2) refer to the same kind of general operation.

Load, store and transfer instructions as well as comparisons are typically
found in the lower half of the table, while most of the arithmetical and
logical operations as well as stack and jump instructions are found in the
upper half. (However, mind the exception of SBC as a "mirror" of ADC.)

acb
01234567
00$00BRK impl$08PHP impl$10BPL rel$18CLC impl
1$01ORA X,ind$05ORA zpg$09ORA #$0DORA abs$11ORA ind,Y$15ORA zpg,X$19ORA abs,Y$1DORA abs,X
2$06ASL zpg$0AASL A$0EASL abs$16ASL zpg,X$1EASL abs,X
10$20JSR abs$24BIT zpg$28PLP impl$2CBIT abs$30BMI rel$38SEC impl
1$21AND X,ind$25AND zpg$29AND #$2DAND abs$31AND ind,Y$35AND zpg,X$39AND abs,Y$3DAND abs,X
2$26ROL zpg$2AROL A$2EROL abs$36ROL zpg,X$3EROL abs,X
20$40RTI impl$48PHA impl$4CJMP abs$50BVC rel$58CLI impl
1$41EOR X,ind$45EOR zpg$49EOR #$4DEOR abs$51EOR ind,Y$55EOR zpg,X$59EOR abs,Y$5DEOR abs,X
2$46LSR zpg$4ALSR A$4ELSR abs$56LSR zpg,X$5ELSR abs,X
30$60RTS impl$68PLA impl$6CJMP ind$70BVS rel$78SEI impl
1$61ADC X,ind$65ADC zpg$69ADC #$6DADC abs$71ADC ind,Y$75ADC zpg,X$79ADC abs,Y$7DADC abs,X
2$66ROR zpg$6AROR A$6EROR abs$76ROR zpg,X$7EROR abs,X
40$84STY zpg$88DEY impl$8CSTY abs$90BCC rel$94STY zpg,X$98TYA impl
1$81STA X,ind$85STA zpg$8DSTA abs$91STA ind,Y$95STA zpg,X$99STA abs,Y$9DSTA abs,X
2$86STX zpg$8ATXA impl$8ESTX abs$96STX zpg,Y$9ATXS impl
50$A0LDY #$A4LDY zpg$A8TAY impl$ACLDY abs$B0BCS rel$B4LDY zpg,X$B8CLV impl$BCLDY abs,X
1$A1LDA X,ind$A5LDA zpg$A9LDA #$ADLDA abs$B1LDA ind,Y$B5LDA zpg,X$B9LDA abs,Y$BDLDA abs,X
2$A2LDX #$A6LDX zpg$AATAX impl$AELDX abs$B6LDX zpg,Y$BATSX impl$BELDX abs,Y
60$C0CPY #$C4CPY zpg$C8INY impl$CCCPY abs$D0BNE rel$D8CLD impl
1$C1CMP X,ind$C5CMP zpg$C9CMP #$CDCMP abs$D1CMP ind,Y$D5CMP zpg,X$D9CMP abs,Y$DDCMP abs,X
2$C6DEC zpg$CADEX impl$CEDEC abs$D6DEC zpg,X$DEDEC abs,X
70$E0CPX #$E4CPX zpg$E8INX impl$ECCPX abs$F0BEQ rel$F8SED impl
1$E1SBC X,ind$E5SBC zpg$E9SBC #$EDSBC abs$F1SBC ind,Y$F5SBC zpg,X$F9SBC abs,Y$FDSBC abs,X
2$E6INC zpg$EANOP impl$EEINC abs$F6INC zpg,X$FEINC abs,X

"Illegal" Opcodes Revisited

So, how do the "illegal" opcodes fit into this decoding scheme?
Let's have a look — "illegals" are shown on grey background.

The first view — rows by c and a and columns as b — reveals a strict relation
beetween address modes and columns:

cab
01234567
00$00BRK impl$04NOP zpg$08PHP impl$0CNOP abs$10BPL rel$14NOP zpg,X$18CLC impl$1CNOP abs,X
1$20JSR abs$24BIT zpg$28PLP impl$2CBIT abs$30BMI rel$34NOP zpg,X$38SEC impl$3CNOP abs,X
2$40RTI impl$44NOP zpg$48PHA impl$4CJMP abs$50BVC rel$54NOP zpg,X$58CLI impl$5CNOP abs,X
3$60RTS impl$64NOP zpg$68PLA impl$6CJMP ind$70BVS rel$74NOP zpg,X$78SEI impl$7CNOP abs,X
4$80NOP #$84STY zpg$88DEY impl$8CSTY abs$90BCC rel$94STY zpg,X$98TYA impl$9CSHY abs,X
5$A0LDY #$A4LDY zpg$A8TAY impl$ACLDY abs$B0BCS rel$B4LDY zpg,X$B8CLV impl$BCLDY abs,X
6$C0CPY #$C4CPY zpg$C8INY impl$CCCPY abs$D0BNE rel$D4NOP zpg,X$D8CLD impl$DCNOP abs,X
7$E0CPX #$E4CPX zpg$E8INX impl$ECCPX abs$F0BEQ rel$F4NOP zpg,X$F8SED impl$FCNOP abs,X
10$01ORA X,ind$05ORA zpg$09ORA #$0DORA abs$11ORA ind,Y$15ORA zpg,X$19ORA abs,Y$1DORA abs,X
1$21AND X,ind$25AND zpg$29AND #$2DAND abs$31AND ind,Y$35AND zpg,X$39AND abs,Y$3DAND abs,X
2$41EOR X,ind$45EOR zpg$49EOR #$4DEOR abs$51EOR ind,Y$55EOR zpg,X$59EOR abs,Y$5DEOR abs,X
3$61ADC X,ind$65ADC zpg$69ADC #$6DADC abs$71ADC ind,Y$75ADC zpg,X$79ADC abs,Y$7DADC abs,X
4$81STA X,ind$85STA zpg$89NOP #$8DSTA abs$91STA ind,Y$95STA zpg,X$99STA abs,Y$9DSTA abs,X
5$A1LDA X,ind$A5LDA zpg$A9LDA #$ADLDA abs$B1LDA ind,Y$B5LDA zpg,X$B9LDA abs,Y$BDLDA abs,X
6$C1CMP X,ind$C5CMP zpg$C9CMP #$CDCMP abs$D1CMP ind,Y$D5CMP zpg,X$D9CMP abs,Y$DDCMP abs,X
7$E1SBC X,ind$E5SBC zpg$E9SBC #$EDSBC abs$F1SBC ind,Y$F5SBC zpg,X$F9SBC abs,Y$FDSBC abs,X
20$02JAM $06ASL zpg$0AASL A$0EASL abs$12JAM $16ASL zpg,X$1ANOP impl$1EASL abs,X
1$22JAM $26ROL zpg$2AROL A$2EROL abs$32JAM $36ROL zpg,X$3ANOP impl$3EROL abs,X
2$42JAM $46LSR zpg$4ALSR A$4ELSR abs$52JAM $56LSR zpg,X$5ANOP impl$5ELSR abs,X
3$62JAM $66ROR zpg$6AROR A$6EROR abs$72JAM $76ROR zpg,X$7ANOP impl$7EROR abs,X
4$82NOP #$86STX zpg$8ATXA impl$8ESTX abs$92JAM $96STX zpg,Y$9ATXS impl$9ESHX abs,Y
5$A2LDX #$A6LDX zpg$AATAX impl$AELDX abs$B2JAM $B6LDX zpg,Y$BATSX impl$BELDX abs,Y
6$C2NOP #$C6DEC zpg$CADEX impl$CEDEC abs$D2JAM $D6DEC zpg,X$DANOP impl$DEDEC abs,X
7$E2NOP #$E6INC zpg$EANOP impl$EEINC abs$F2JAM $F6INC zpg,X$FANOP impl$FEINC abs,X
30$03SLO X,ind$07SLO zpg$0BANC #$0FSLO abs$13SLO ind,Y$17SLO zpg,X$1BSLO abs,Y$1FSLO abs,X
1$23RLA X,ind$27RLA zpg$2BANC #$2FRLA abs$33RLA ind,Y$37RLA zpg,X$3BRLA abs,Y$3FRLA abs,X
2$43SRE X,ind$47SRE zpg$4BALR #$4FSRE abs$53SRE ind,Y$57SRE zpg,X$5BSRE abs,Y$5FSRE abs,X
3$63RRA X,ind$67RRA zpg$6BARR #$6FRRA abs$73RRA ind,Y$77RRA zpg,X$7BRRA abs,Y$7FRRA abs,X
4$83SAX X,ind$87SAX zpg$8BANE #$8FSAX abs$93SHA ind,Y$97SAX zpg,Y$9BTAS abs,Y$9FSHA abs,Y
5$A3LAX X,ind$A7LAX zpg$ABLXA #$AFLAX abs$B3LAX ind,Y$B7LAX zpg,Y$BBLAS abs,Y$BFLAX abs,Y
6$C3DCP X,ind$C7DCP zpg$CBSBX #$CFDCP abs$D3DCP ind,Y$D7DCP zpg,X$DBDCP abs,Y$DFDCP abs,X
7$E3ISC X,ind$E7ISC zpg$EBUSBC #$EFISC abs$F3ISC ind,Y$F7ISC zpg,X$FBISC abs,Y$FFISC abs,X

And, again, as a rotated view, rows as combinations of c and b, and columns as a.
We may observe a close relationship between the legal and the undocumented
instructions in the vertical (quarter-)segements of each column.

cba
01234567
00$00BRK impl$20JSR abs$40RTI impl$60RTS impl$80NOP #$A0LDY #$C0CPY #$E0CPX #
1$04NOP zpg$24BIT zpg$44NOP zpg$64NOP zpg$84STY zpg$A4LDY zpg$C4CPY zpg$E4CPX zpg
2$08PHP impl$28PLP impl$48PHA impl$68PLA impl$88DEY impl$A8TAY impl$C8INY impl$E8INX impl
3$0CNOP abs$2CBIT abs$4CJMP abs$6CJMP ind$8CSTY abs$ACLDY abs$CCCPY abs$ECCPX abs
4$10BPL rel$30BMI rel$50BVC rel$70BVS rel$90BCC rel$B0BCS rel$D0BNE rel$F0BEQ rel
5$14NOP zpg,X$34NOP zpg,X$54NOP zpg,X$74NOP zpg,X$94STY zpg,X$B4LDY zpg,X$D4NOP zpg,X$F4NOP zpg,X
6$18CLC impl$38SEC impl$58CLI impl$78SEI impl$98TYA impl$B8CLV impl$D8CLD impl$F8SED impl
7$1CNOP abs,X$3CNOP abs,X$5CNOP abs,X$7CNOP abs,X$9CSHY abs,X$BCLDY abs,X$DCNOP abs,X$FCNOP abs,X
10$01ORA X,ind$21AND X,ind$41EOR X,ind$61ADC X,ind$81STA X,ind$A1LDA X,ind$C1CMP X,ind$E1SBC X,ind
1$05ORA zpg$25AND zpg$45EOR zpg$65ADC zpg$85STA zpg$A5LDA zpg$C5CMP zpg$E5SBC zpg
2$09ORA #$29AND #$49EOR #$69ADC #$89NOP #$A9LDA #$C9CMP #$E9SBC #
3$0DORA abs$2DAND abs$4DEOR abs$6DADC abs$8DSTA abs$ADLDA abs$CDCMP abs$EDSBC abs
4$11ORA ind,Y$31AND ind,Y$51EOR ind,Y$71ADC ind,Y$91STA ind,Y$B1LDA ind,Y$D1CMP ind,Y$F1SBC ind,Y
5$15ORA zpg,X$35AND zpg,X$55EOR zpg,X$75ADC zpg,X$95STA zpg,X$B5LDA zpg,X$D5CMP zpg,X$F5SBC zpg,X
6$19ORA abs,Y$39AND abs,Y$59EOR abs,Y$79ADC abs,Y$99STA abs,Y$B9LDA abs,Y$D9CMP abs,Y$F9SBC abs,Y
7$1DORA abs,X$3DAND abs,X$5DEOR abs,X$7DADC abs,X$9DSTA abs,X$BDLDA abs,X$DDCMP abs,X$FDSBC abs,X
20$02JAM $22JAM $42JAM $62JAM $82NOP #$A2LDX #$C2NOP #$E2NOP #
1$06ASL zpg$26ROL zpg$46LSR zpg$66ROR zpg$86STX zpg$A6LDX zpg$C6DEC zpg$E6INC zpg
2$0AASL A$2AROL A$4ALSR A$6AROR A$8ATXA impl$AATAX impl$CADEX impl$EANOP impl
3$0EASL abs$2EROL abs$4ELSR abs$6EROR abs$8ESTX abs$AELDX abs$CEDEC abs$EEINC abs
4$12JAM $32JAM $52JAM $72JAM $92JAM $B2JAM $D2JAM $F2JAM
5$16ASL zpg,X$36ROL zpg,X$56LSR zpg,X$76ROR zpg,X$96STX zpg,Y$B6LDX zpg,Y$D6DEC zpg,X$F6INC zpg,X
6$1ANOP impl$3ANOP impl$5ANOP impl$7ANOP impl$9ATXS impl$BATSX impl$DANOP impl$FANOP impl
7$1EASL abs,X$3EROL abs,X$5ELSR abs,X$7EROR abs,X$9ESHX abs,Y$BELDX abs,Y$DEDEC abs,X$FEINC abs,X
30$03SLO X,ind$23RLA X,ind$43SRE X,ind$63RRA X,ind$83SAX X,ind$A3LAX X,ind$C3DCP X,ind$E3ISC X,ind
1$07SLO zpg$27RLA zpg$47SRE zpg$67RRA zpg$87SAX zpg$A7LAX zpg$C7DCP zpg$E7ISC zpg
2$0BANC #$2BANC #$4BALR #$6BARR #$8BANE #$ABLXA #$CBSBX #$EBUSBC #
3$0FSLO abs$2FRLA abs$4FSRE abs$6FRRA abs$8FSAX abs$AFLAX abs$CFDCP abs$EFISC abs
4$13SLO ind,Y$33RLA ind,Y$53SRE ind,Y$73RRA ind,Y$93SHA ind,Y$B3LAX ind,Y$D3DCP ind,Y$F3ISC ind,Y
5$17SLO zpg,X$37RLA zpg,X$57SRE zpg,X$77RRA zpg,X$97SAX zpg,Y$B7LAX zpg,Y$D7DCP zpg,X$F7ISC zpg,X
6$1BSLO abs,Y$3BRLA abs,Y$5BSRE abs,Y$7BRRA abs,Y$9BTAS abs,Y$BBLAS abs,Y$DBDCP abs,Y$FBISC abs,Y
7$1FSLO abs,X$3FRLA abs,X$5FSRE abs,X$7FRRA abs,X$9FSHA abs,Y$BFLAX abs,Y$DFDCP abs,X$FFISC abs,X

And, finally, in a third view, we may observe how each of the rows of "illegal"
instructions at c = 3 inherits behavior from the two rows with c = 1 and c = 2
immediately above, combining the operations of these instructions with the
address mode of the respective instruction at c = 1.
(Mind that in binary 3 is the combination of 2 and 1, bits 0 and 1 both set.)

We may further observe that additional NOPs result from non-effective or non-
sensical combinations of operations and address modes, e.g., instr. $89, which
would be "STA #", storing the contents of the accumulator in the operand.
Some other instructions, typically combinations involving indirect indexed
addressing, fail over unresolved timing issues entirely, resulting in a "JAM".

(We me also observe that there is indeed a difference in accumulator mode
— as in "OPC A" — and immediate addressing. E.g., $6A, "ROR A", is a valid
instruction, while instruction $7A, "ROR implied", is a NOP.
We may also note how "ROR X,ind" at $62 and "ROR ind,Y" at $72 fail entirely
and result in a JAM.)

acb
01234567
00$00BRK impl$04NOP zpg$08PHP impl$0CNOP abs$10BPL rel$14NOP zpg,X$18CLC impl$1CNOP abs,X
1$01ORA X,ind$05ORA zpg$09ORA #$0DORA abs$11ORA ind,Y$15ORA zpg,X$19ORA abs,Y$1DORA abs,X
2$02JAM $06ASL zpg$0AASL A$0EASL abs$12JAM $16ASL zpg,X$1ANOP impl$1EASL abs,X
3$03SLO X,ind$07SLO zpg$0BANC #$0FSLO abs$13SLO ind,Y$17SLO zpg,X$1BSLO abs,Y$1FSLO abs,X
10$20JSR abs$24BIT zpg$28PLP impl$2CBIT abs$30BMI rel$34NOP zpg,X$38SEC impl$3CNOP abs,X
1$21AND X,ind$25AND zpg$29AND #$2DAND abs$31AND ind,Y$35AND zpg,X$39AND abs,Y$3DAND abs,X
2$22JAM $26ROL zpg$2AROL A$2EROL abs$32JAM $36ROL zpg,X$3ANOP impl$3EROL abs,X
3$23RLA X,ind$27RLA zpg$2BANC #$2FRLA abs$33RLA ind,Y$37RLA zpg,X$3BRLA abs,Y$3FRLA abs,X
20$40RTI impl$44NOP zpg$48PHA impl$4CJMP abs$50BVC rel$54NOP zpg,X$58CLI impl$5CNOP abs,X
1$41EOR X,ind$45EOR zpg$49EOR #$4DEOR abs$51EOR ind,Y$55EOR zpg,X$59EOR abs,Y$5DEOR abs,X
2$42JAM $46LSR zpg$4ALSR A$4ELSR abs$52JAM $56LSR zpg,X$5ANOP impl$5ELSR abs,X
3$43SRE X,ind$47SRE zpg$4BALR #$4FSRE abs$53SRE ind,Y$57SRE zpg,X$5BSRE abs,Y$5FSRE abs,X
30$60RTS impl$64NOP zpg$68PLA impl$6CJMP ind$70BVS rel$74NOP zpg,X$78SEI impl$7CNOP abs,X
1$61ADC X,ind$65ADC zpg$69ADC #$6DADC abs$71ADC ind,Y$75ADC zpg,X$79ADC abs,Y$7DADC abs,X
2$62JAM $66ROR zpg$6AROR A$6EROR abs$72JAM $76ROR zpg,X$7ANOP impl$7EROR abs,X
3$63RRA X,ind$67RRA zpg$6BARR #$6FRRA abs$73RRA ind,Y$77RRA zpg,X$7BRRA abs,Y$7FRRA abs,X
40$80NOP #$84STY zpg$88DEY impl$8CSTY abs$90BCC rel$94STY zpg,X$98TYA impl$9CSHY abs,X
1$81STA X,ind$85STA zpg$89NOP #$8DSTA abs$91STA ind,Y$95STA zpg,X$99STA abs,Y$9DSTA abs,X
2$82NOP #$86STX zpg$8ATXA impl$8ESTX abs$92JAM $96STX zpg,Y$9ATXS impl$9ESHX abs,Y
3$83SAX X,ind$87SAX zpg$8BANE #$8FSAX abs$93SHA ind,Y$97SAX zpg,Y$9BTAS abs,Y$9FSHA abs,Y
50$A0LDY #$A4LDY zpg$A8TAY impl$ACLDY abs$B0BCS rel$B4LDY zpg,X$B8CLV impl$BCLDY abs,X
1$A1LDA X,ind$A5LDA zpg$A9LDA #$ADLDA abs$B1LDA ind,Y$B5LDA zpg,X$B9LDA abs,Y$BDLDA abs,X
2$A2LDX #$A6LDX zpg$AATAX impl$AELDX abs$B2JAM $B6LDX zpg,Y$BATSX impl$BELDX abs,Y
3$A3LAX X,ind$A7LAX zpg$ABLXA #$AFLAX abs$B3LAX ind,Y$B7LAX zpg,Y$BBLAS abs,Y$BFLAX abs,Y
60$C0CPY #$C4CPY zpg$C8INY impl$CCCPY abs$D0BNE rel$D4NOP zpg,X$D8CLD impl$DCNOP abs,X
1$C1CMP X,ind$C5CMP zpg$C9CMP #$CDCMP abs$D1CMP ind,Y$D5CMP zpg,X$D9CMP abs,Y$DDCMP abs,X
2$C2NOP #$C6DEC zpg$CADEX impl$CEDEC abs$D2JAM $D6DEC zpg,X$DANOP impl$DEDEC abs,X
3$C3DCP X,ind$C7DCP zpg$CBSBX #$CFDCP abs$D3DCP ind,Y$D7DCP zpg,X$DBDCP abs,Y$DFDCP abs,X
70$E0CPX #$E4CPX zpg$E8INX impl$ECCPX abs$F0BEQ rel$F4NOP zpg,X$F8SED impl$FCNOP abs,X
1$E1SBC X,ind$E5SBC zpg$E9SBC #$EDSBC abs$F1SBC ind,Y$F5SBC zpg,X$F9SBC abs,Y$FDSBC abs,X
2$E2NOP #$E6INC zpg$EANOP impl$EEINC abs$F2JAM $F6INC zpg,X$FANOP impl$FEINC abs,X
3$E3ISC X,ind$E7ISC zpg$EBUSBC #$EFISC abs$F3ISC ind,Y$F7ISC zpg,X$FBISC abs,Y$FFISC abs,X

As a final observation, the two highly unstable instructions "ANE" (XAA) and
"LXA" (LAX immediate) involving a "magic constant" are both combinations of
an accumulator operation and an inter-register transfer between the
accumulator and the X register:

$8B (a=5, c=3, b=2): ANE # = STA # (NOP) + TXA
(A OR CONST) AND X AND oper -> A

$AB (a=4, c=3, b=2): LXA # = LDA # + TAX
(A OR CONST) AND oper -> A -> X

In the case of ANE, the contents of the accumulator is put on the internal
data lines at the same time as the contents of the X-register, while there's
also the operand read for the immediate operation, with the result
transferred to the accumulator.

In the case of LXA, the immediate operand and the contents of the accumulator
are competing for the imput lines, while the result will be transferred to
both the accumulator and the X register.

The outcome of these competing, noisy conditions depends on the production
series of the chip, and maybe even on environmental conditions. This effects
in an OR-ing of the accumulator with the "magic constant" combined with an
AND-ing of the competing inputs. The final transfer to the target register(s)
then seems to work as may be expected.

(This AND-ing of competing values susggests that the 6502 is working internally
in active negative logic, where all data lines are first set to high and then
cleared for any zero bits. This also suggests that the "magic constant" stands
merely for a partial transfer of the contents of the accumulator.)

Much of this also applies to "TAS" (XAS, SHS), $9B, but here the extra cycles
for indexed addressing seem to contribute to the conflict being resolved
without this "magic constant". However, TAS is still unstable.

Simlarly the peculiar group involving the high-byte of the provided address + 1
(as in "H+1") — SHA (AHX, AXA), SHX (A11, SXA, XAS), SHY (A11, SYA, SAY) —
involves a conflict of an attempt to store the accumulator and another register
being put on the data lines at the same time, and the operations required to
determine the target address for for indexed addressing. Again, the competing
values are AND-ed and the instructions are unstable.

We may also observe that SHY is really the unimplemented instruction "STY abs,X"
and SHX is "STX abs,Y" with SHA being the combination of "LDA abs,X" and SHX.

We may conclude that these "illegal opcodes" or "undocumented instructions" are
really a text-book example of undefined behavior for undefined input patterns.
Generally speaking, for any instructions xxxxxx11 (c=3) both instructions at
xxxxxx01 (c=1) and xxxxxx10 (c=2) are started in a thread, with competing ouput
values on the internal data lines AND-ed. For some combinations, this results
in a fragile race condition, while others are showing mostly stable behavior.
The addressing mode is generally determined by that of the instruction at c=1.

(It may be interesting that is doesn't matter, if any of the two threads jams,
as long as the timing for the other thread resolves. So there is no "JAM"
instruction at c=3.)

The 65xx-Family:

TypeFeatures, Comments
6502NMOS, 16 bit address bus, 8 bit data bus
6502Aaccelerated version of 6502
6502Caccelerated version of 6502, additional halt pin, CMOS
65C0216 bit version, additional instructions and address modes
6503, 6505, 650612 bit address bus [4 KiB]
650413 bit address bus [8 KiB]
650713 bit address bus [8 KiB], no interrupts
650920 bit address bus [1 MiB] by bankswitching
6510as 6502 with additional 6 bit I/O-port
6511integrated micro controler with I/O-port, serial interface, and RAM (Rockwell)
65F11as 6511, integrated FORTH interpreter
7501as 6502, HMOS
8500as 6510, CMOS
8502as 6510 with switchable 2 MHz option, 7 bit I/O-port
65816 (65C816)16 bit registers and ALU, 24 bit address bus [16 MiB], up to 24 MHz (Western Design Center)
65802 (65C802)as 65816, pin compatible to 6502, 64 KiB address bus, up to 16 MHz

Site Notes

Disclaimer

Errors excepted. The information is provided for free and AS IS, therefore without any warranty;
without even the implied warranty of merchantability or fitness for a particular purpose.

See also

External Links

Presented by virtual 6502, mass:werk.