65816 Opcodes

65816 Opcode matrix:

imm = #$00
sr = $00,S
dp = $00
dpx = $00,X
dpy = $00,Y
idp = ($00)
idx = ($00,X)
idy = ($00),Y
idl = [$00]
idly = [$00],Y
isy = ($00,S),Y
abs = $0000
abx = $0000,X
aby = $0000,Y
abl = $000000
alx = $000000,X
ind = ($0000)
iax = ($0000,X)
ial = [$000000]
rel = $0000 (8 bits PC-relative)
rell = $0000 (16 bits PC-relative)
bm = $00,$00

| x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF
0x | BRK 7 | ORA idx 6 | COP imm 7 | ORA sr 4 | TSB dp 5 | ORA dp 3 | ASL dp 5 | ORA idl 6 | PHP 3 | ORA imm 2 | ASL 2 | PHD 4 | TSB abs 6 | ORA abs 4 | ASL abs 6 | ORA abl 5
1x | BPL rel 2* | ORA idy 5* | ORA idp 5 | ORA isy 7 | TRB dp 5 | ORA dpx 4 | ASL dpx 6 | ORA idly 6 | CLC 2 | ORA aby 4* | INC 2 | TCS 2 | TRB abs 6 | ORA abx 4* | ASL abx 7 | ORA alx 4
2x | JSR abs 6 | AND idx 6 | JSR abl 8 | AND sr 4 | BIT dp 3 | AND dp 3 | ROL dp 5 | AND idl 6 | PLP 4 | AND imm 2 | ROL 2 | PLD 5 | BIT abs 4 | AND abs 4 | ROL abs 6 | AND abl 5
3x | BMI rel 2* | AND idy 5* | AND idp 5 | AND isy 7 | BIT dpx 4 | AND dpx 4 | ROL dpx 6 | AND idly 6 | SEC 2 | AND aby 4* | DEC 2 | TSC 2 | BIT abx 4* | AND abx 4* | ROL abx 7 | AND alx 5
4x | RTI 6 | EOR idx 6 | WDM n/a | EOR sr 4 | MVP bm 1# | EOR dp 3 | LSR dp 5 | EOR idl 6 | PHA 3 | EOR imm 2 | LSR 2 | PHK 3 | JMP abs 3 | EOR abs 4 | LSR abs 6 | EOR abl 5
5x | BVC rel 2* | EOR idy 5* | EOR idp 5 | EOR isy 6 | MVN bm 1# | EOR dpx 4 | LSR dpx 6 | EOR idly 6 | CLI 2 | EOR aby 4* | PHY 3 | TCD 2 | JMP abl 4 | EOR abx 4* | LSR abx 7 | EOR alx 5
6x | RTS 6 | ADC idx 6 | PER rell 6 | ADC sr 4 | STZ dp 3 | ADC dp 3 | ROR zp 5 | ADC idl 6 | PLA 4 | ADC imm 2 | ROR 2 | RTL 6 | JMP ind 5 | ADC abs 4 | ROR abs 6 | ADC abl 5
7x | BVS rel 2* | ADC idy 5* | ADC idp 5 | ADC isy 7 | STZ dpx 4 | ADC dpx 4 | ROR zpx 6 | ADC idly 6 | SEI 2 | ADC aby 4* | PLY 4 | TDC 2 | JMP ial 6 | ADC abx 4* | ROR abx 7 | ADC alx 5
8x | BRA rel 3* | STA idx 6 | BRL rell 4 | STA sr 4 | STY dp 3 | STA dp 3 | STX dp 3 | STA idl 6 | DEY 2 | BIT imm 2 | TXA 2 | PHB 3 | STY abs 4 | STA abs 4 | STX abs 4 | STA abl 5
9x | BCC rel 2* | STA idy 6 | STA idp 5 | STA isy 7 | STY dpx 4 | STA dpx 4 | STX dpy 4 | STA idly 6 | TYA 2 | STA aby 5 | TXS 2 | TXY 2 | STZ abs 4 | STA abx 5 | STZ abx 5 | STA alx 5
Ax | LDY imm 2 | LDA idx 6 | LDX imm 2 | LDA sr 4 | LDY dp 3 | LDA dp 3 | LDX dp 3 | LDA idl 6 | TAY 2 | LDA imm 2 | TAX 2 | PLB 4 | LDY abs 4 | LDA abs 4 | LDX abs 4 | LDA abl 5
Bx | BCS rel 2* | LDA idy 5* | LDA idp 5 | LDA isy 7 | LDY dpx 4 | LDA dpx 4 | LDX dpy 4 | LDA idly 6 | CLV 2 | LDA aby 4* | TSX 2 | TYX 2 | LDY abx 4* | LDA abx 4* | LDX aby 4* | LDA alx 5
Cx | CPY imm 2 | CMP idx 6 | REP imm 3 | CMP sr 4 | CPY dp 3 | CMP dp 3 | DEC dp 5 | CMP idl 6 | INY 2 | CMP imm 2 | DEX 2 | WAI 3 | CPY abs 4 | CMP abs 4 | DEC abs 6 | CMP abl 5
Dx | BNE rel 2* | CMP idy 5* | CMP idp 5 | CMP isy 7 | PEI idp 6 | CMP dpx 4 | DEC dpx 6 | CMP idly 6 | CLD 2 | CMP aby 4* | PHX 3 | STP 3 | JMP iax 6 | CMP abx 4* | DEC abx 7 | CMP alx 5
Ex | CPX imm 2 | SBC idx 6 | SEP imm 3 | SBC sr 4 | CPX dp 3 | SBC dp 3 | INC dp 5 | SBC idl 6 | INX 2 | SBC imm 2 | NOP 2 | XBA 3 | CPX abs 4 | SBC abs 4 | INC abs 6 | SBC abl 5
Fx | BEQ rel 2* | SBC idy 5* | SBC idp 5 | SBC isy 7 | PEA abs 5 | SBC dpx 4 | INC dpx 6 | SBC idly 6 | SED 2 | SBC aby 4* | PLX 4 | XCE 2 | JSR iax 8 | SBC abx 4* | INC abx 7 | SBC alx 5

"*" : add 1 cycle if page boundary is crossed.
"#" : add 7 cycles for every byte moved and 1 cycle if page boundary is crossed.
add 1 cycle if m=0: ADC, AND, BIT, CMP, EOR, LDA, ORA, PHA, PLA, SBC, STA, STZ
add 2 cycles if m=0 (NOT the implied ones): ASL, DEC, INC, LSR, ROL, ROR, TRB, TSB
add 1 cycle if x=0: CPX, CPY, LDX, LDY, STX, STY, PLX, PLY, PHX, PHY
add 1 cycle if e=0: BRK, RTI
add 1 cycle if direct page register is non zero on direct page adressing modes.
add 1 cycle on conditional branches if taken.
native 65816 only: branches do not take one additional cycle when page boundary is crossed.
`A = Akkumulator
B = Akkumulator, upper 8 bits
C = Akkumulator (but always 16 bit not depending on M)
X = X-Register
Y = Y-Register
S = Stack-Pointer
P = Status-Register
+(S) = Stack-Pointer relative with pre-increment
(S)- = Stack-Pointer relative with post-decrement
DBR = Data Bank Register (all data movements with 16 bit adresses will refer to this bank)
DPR = Direct Page Register (all direct page accesses will use this as adress base)
PBR = Program Bank Register (the bank the actual code is executed)`
Please note that 3 new flags have been added to the P: E, M and X.
While E=1 the 65816 is in 6502 emulation mode and will act like a 6502 in all legal matters.
DBR, DPR and PBR are still active! Take care: irq's will force PBR=0 without saving the PBR!
While E=0 the 65816 is in native mode.
While M=1 the Akku is 8 bits wide.
While M=0 the Akku is 16 bits wide.
While X=1 the X and Y registers are 8 bits wide.
While X=0 the X and Y registers are 16 bits wide.
Also note that the P has virtually lost the B flag in some matters.
65816 opcodes:

Opcode | Function | E | N | V | M | X | D | I | Z | C
BRA | branch always |  |  |  |  |  |  |  |  |
BRL | branch always (long) |  |  |  |  |  |  |  |  |
COP | coprocessor enable |  |  |  |  |  | * | * |  |
MVN | move block backward |  |  |  |  |  |  |  |  |
MVP | move block forward |  |  |  |  |  |  |  |  |
PEA | (S)-:=adr |  |  |  |  |  |  |  |  |
PEI | (S)-:=adr |  |  |  |  |  |  |  |  |
PER | (S)-:=adr |  |  |  |  |  |  |  |  |
PHB | (S)-:=DBR |  |  |  |  |  |  |  |  |
PHD | (S)-:=DPR |  |  |  |  |  |  |  |  |
PHK | (S)-:=PBR |  |  |  |  |  |  |  |  |
PHX | (S)-:=X |  |  |  |  |  |  |  |  |
PHY | (S)-:=Y |  |  |  |  |  |  |  |  |
PLB | DBR:=+(S) |  | * |  |  |  |  |  | * |
PLD | DPR:=+(S) |  | * |  |  |  |  |  | * |
PLX | X:=+(S) |  | * |  |  |  |  |  | * |
PLY | Y:=+(S) |  | * |  |  |  |  |  | * |
REP | P:=P nand #{imm} |  | ? | ? | ? | ? | ? | ? | ? | ?
SEP | P:=P or #{imm} |  | ? | ? | ? | ? | ? | ? | ? | ?
RTL | PC:=+(S) (long) |  |  |  |  |  |  |  |  |
STP | stop CPU |  |  |  |  |  |  |  |  |
WAI | wait for IRQ |  |  |  |  |  |  |  |  |
STZ | {adr}:=0 |  |  |  |  |  |  |  |  |
TCD | DPR:=C |  |  |  |  |  |  |  |  |
TDC | C:=DPR |  | * |  |  |  |  |  | * |
TCS | S:=C |  |  |  |  |  |  |  |  |
TSC | C:=S |  | * |  |  |  |  |  | * |
TXY | Y:=X |  | * |  |  |  |  |  | * |
TYX | X:=Y |  | * |  |  |  |  |  | * |
XBA | exchange B with A |  | * |  |  |  |  |  | * |
XCE | exchange C with E | * |  |  |  |  |  |  |  | *
TRB | {adr}:={adr} nand A |  |  |  |  |  |  |  | * |
TSB | {adr}:={adr} or A |  |  |  |  |  |  |  | * |
WDM | n/a |  |  |  |  |  |  |  |  |

note to STP, WAI: these opcodes need 3 cycles to shut down the CPU.
© 2009-2012 Graham. Last change on 01.09.2012.
back