User Tools

Site Tools

“TestCode = FFFF”


Alphabetical Listing

ADC Add (with carry) memory to accumulator
AND Bitwise AND accumulator with memory
ASL (Arithmetic) shift left accumulator / memory
BCC Branch if carry clear
BCS Branch if carry set
BEQ Branch if equal (zero set)
BIT Bit test accumulator with memory
BNE Branch if not equal (zero clear)
BPL Branch if plus (negative clear)
BMI Branch if minus (negative set)
BRA Branch (unconditional)
BRK Breakpoint interrupt
BRL Branch long (unconditional)
BVC Branch if overflow clear
BVS Branch if overflow set
CLC Clear carry flag
CLD Clear decimal mode flag
CLI Clear interrupt-disable flag
CLV Clear overflow flag
CMP Compare accumulator with memory
COP Coprocessor interrupt
CPX Compare index register X with memory
CPY Compare index register Y with memory
DEC Decrement accumulator / memory
DEX Decrement index register X
DEY Decrement index register Y
EOR Bitwise XOR accumulator with memory
INC Increment accumulator / memory
INX Increment index register X
INY Increment index register Y
JML Jump long (can change banks)
JMP Jump (within current bank)
JSL Jump to subroutine long (can change banks)
JSR Jump to subroutine (within current bank)
LDA Load to accumulator from memory
LDX Load to index register X from memory
LDY Load to index register Y from memory
LSR Logical shift right accumulator / memory
MVN Move memory in the negative direction
MVP Move memory in the positive direction
NOP No operation
ORA Bitwise OR accumulator with memory
PEA Push effective absolute
PEI Push effective indirect
PER Push effective relative
PHA Push accumulator
PHB Push data bank register
PHD Push direct page register
PHK Push program bank register
PHP Push processor status register
PHX Push index register X
PHY Push index register Y
PLA Pull to accumulator
PLB Pull to data bank register
PLD Pull to direct page register
PLP Pull to status flags
PLX Pull to index register X
PLY Pull to index register Y
REP Reset processor status register bits
ROL Rotate accumulator / memory left (with carry)
ROR Rotate accumulator / memory right (with carry)
RTI Return from interrupt
RTL Return from subroutine long (from JSL)
RTS Return from subroutine (from JSR)
SBC Subtract (with carry) memory from accumulator
SEC Set carry flag
SED Set decimal mode flag
SEI Set interrupt-disable flag
SEP Set processor status register bits
STA Store accumulator to memory
STX Store index register X to memory
STY Store index register Y to memory
STZ Store zero to memory
TAX Transfer accumulator to index register X
TAY Transfer accumulator to index register Y
TCD Transfer accumulator to direct page register
TCS Transfer accumulator to stack pointer
TDC Transfer direct page register to accumulator
TRB Test and reset memory bits against accumulator
TSB Test and set memory bits with accumulator
TSC Transfer stack pointer to accumulator
TSX Transfer stack pointer to index register X
TXA Transfer index register X to accumulator
TXS Transfer index register X to stack pointer
TXY Transfer index register X to Y
TYA Transfer index register Y to accumulator
TYX Transfer index register Y to X
WAI Wait for interrupt
WDM William David Mensch Jr., 65816 designer (reserved, no operation)
XBA Exchange bytes of the accumulator
XCE Exchange carry and emulation bits

Functional Grouping


ADC Add with carry to A
SBC Subtract with borrow from carry from A
ASL Shift left by one bit, aka multiply by 2
LSR Shift right by one bit, aka divide by 2
INC/INX/INY Increment, adds 1
DEC/DEX/DEY Decrement, subtracts 1

There are no general multiply/divide instructions on the CPU. Super Metroid has a routine at $80:82D6 that (inaccurately–it's missing a carry) multiplies two 16-bit values (from A and Y) and stores a result in $05F1-$05F4.

Bitwise Operations

AND AND value with A
BIT Test bits against A and set flags
EOR Exclusive-or (xor) value with A
ORA OR value with A
TRB NAND memory with A, but set Z flag as if it were BIT
TSB OR memory with A, but set Z flag as if it were BIT
ROL Rotate left, through carry
ROR Rotate right, through carry

The rotate operations can be used like shift operations, for data that's bigger than the size of a register.

TRB/TSB oddly affect memory and not the A register. BIT does not affect the value in A.


BRA Always branch
BCC / BCS Branch if carry clear or set
BVC / BVS Branch if overflow clear or set
BPL / BMI Branch if minus flag clear or set
BNE / BEQ Branch if zero clear or set
CMP/CPX/CPY Compare value with A/Y/X and set flags

I'm not sure if BRL (long branch) is useful, since it uses the same space as a JMP but can't always travel as far.

CMP does its work by subtracting the compared value from A, setting the flags, and throwing away the result. When the value and A were equal, the subtraction yields 0, and the Z flag is set. Which is why BEQ branches on Zero.

The Super Metroid engine occasionally returns single bits of information from subroutines via the carry flag. For example, whether a block should be treated as solid (SEC) or not (CLC) during touch/collision.


JSR - RTS Jump to subroutine in the same bank - return from it
JSL - RTL Jump to subroutine in any bank - return from it
JMP Go to address in the same bank
JML Go to address in any bank

JSL-RTL use one extra instruction byte and one additional byte on the stack, compared to JSR-RTS.

Moving Between Registers

What most other chips call “move,” the 65c816 calls “transfer.”

TAX Accumulator (A) to X
TXA X to Accumulator
TAY Accumulator to Y
TYA Y to Accumulator
TXY X to Y
TYX Y to X

Moving Between Memory

There are no memory/memory operations. Everything involving two values happens between memory and a register. Also, see the stack section for moving between registers and the stack.

LDA/LDX/LDY Load from memory to A/X/Y register
STA/STX/STY Store to memory from A/X/Y register
STZ Store zero to memory


All of the PH* instructions have a corresponding PL*, except for PHK. The only way to affect the code segment is through JSL or JML.

PHP Push processor flags (frequently before SEP/REP)
PHK Push code bank
PHB Push data bank
PHD Push direct page register
PHA/PHX/PHY Push A/X/Y register
PEA Push address (may have to write PEA.w in xkas)

Super Metroid occasionally does things like:

PHB : PHK : PLB : (a section of code) : PLB : RTL

This saves the data bank, then sets the data bank to the current code bank for the section of code. Finally, the original data bank is restored just before returning.

Another common sequence is:

PEA $8200 : PLB : PLB

This sets bank $82 as the data bank. PEA writes the stack so that it says $00 $82, making the first PLB set the data bank to $00, and the second one sets the intended $82.

Processor Flags

CLC/CLD/CLI/CLV Clear carry/decimal/interrupt/overflow
SEC/SED/SEI Set carry/decimal/interrupt
REP Clear (reset) status bits
SEP Set status bits

Interrupts are disabled when SEI is used, and allowed when CLI is used. NMIs, as usual, cannot be disabled.

Overflow can only be set by doing arithmetic that sets it, such as ADC, or using SEP.

Status Bits

80 Negative (BPL/BMI)
40 Overflow (BVC/BVS)
20 A register size: 0 for 16-bit, 1 for 8-bit
10 X/Y register size: 0 for 16-bit, 1 for 8-bit
08 Decimal mode, may not be emulated properly
04 IRQ Disable: 0 for enabled, 1 for disabled
02 Zero (BEQ/BNE)
01 Carry (BCC/BCS)

The most common bits changed with SEP and REP in Super Metroid are $10 and $20 (sometimes combined as $30.) SEP changes the flags to 1, and REP changes them to 0, so REP #$30 sets 16-bit mode for A and X/Y.

super/technical_information/asm_mnemonics.txt · Last modified: 2019/02/15 08:30 by p.jboy