Skip to content

The instruction set

Grouped by what you are trying to do, rather than alphabetically, because that is how you look for one. Cycle counts are for the plain form of each instruction; add one for a page crossing on an indexed read, and one more for a taken branch.

Moving bytes about

LDA LDX LDYLoad a register. 2–5 cycles.
STA STX STYStore one. 3–6 cycles.
STZStore zero without loading anything first. 65C02.
TAX TAY TXA TYACopy between registers. 2 cycles.
TSX TXSThe stack pointer, in and out of X.

Arithmetic

ADCAdd with carry — CLC first.
SBCSubtract with borrow — SEC first.
INC DECAdd or subtract one, in memory or (65C02) in A.
INX INY DEX DEYThe same for the index registers.
CMP CPX CPYCompare. Sets the flags, keeps the register.

CMP is a subtraction that throws the answer away. After it: Z means equal, C means the register was greater or equal, and N is the sign of the difference — which is why bcs and bcc are the right branches after comparing unsigned numbers, and bmi/bpl are the wrong ones.

Bits

AND ORA EORThe three you expect.
ASL LSRShift left or right, dropping a bit into the carry.
ROL RORRotate through the carry — how you shift a 16-bit value.
BITTest bits without changing anything: Z from A AND memory, and N and V straight from bits 7 and 6 of the memory byte.
TRB TSBClear or set every bit in a mask, in one instruction. 65C02.

BIT reads two flags for free

Bits 7 and 6 of the byte land in N and V without touching A. Hardware status registers are often laid out with the two most urgent flags in exactly those positions, and this is why.

Deciding and going

BEQ BNEZero flag set / clear
BCS BCCCarry set / clear
BMI BPLNegative flag set / clear
BVS BVCOverflow set / clear
BRAAlways. 65C02.
JMPAnywhere — direct, indirect, or (65C02) through a table with (abs,X).
JSR RTSCall and return.

The stack

PHA PLAPush and pull A
PHX PHY PLX PLYThe same for X and Y. 65C02.
PHP PLPThe flags

The stack is 256 bytes at $0100, and it wraps rather than overflows: push 257 things and you are back where you started, quietly writing over your own return addresses. In practice this only ever bites recursive code.

Flags, interrupts, and stopping

CLC SECCarry
CLD SEDDecimal mode
CLI SEIInterrupts on / off
CLVClear overflow
BRKSoftware interrupt — on this machine, a breakpoint into the Monitor
RTIReturn from an interrupt
NOPNothing, for two cycles
WAI STPWait for an interrupt / stop until reset. W65C02S.
BRK is two bytes, not one

The processor pushes the address of BRK plus two, so a one-byte BRK would return into the middle of whatever followed it. Assemblers know this; what it means for you is that a BRK used as a breakpoint should have a spare byte after it. On this machine BRK lands in the Monitor with every register on display, which makes it the cheapest debugging tool there is — see Reaching the machine.

Decimal mode

SED makes ADC and SBC work in packed decimal: $09 + $01 gives $10 rather than $0A. It is genuinely useful for a score you intend to print digit by digit, and genuinely dangerous if you forget to CLD afterwards, because everything else — including any interrupt that arrives — is still doing arithmetic in the mode you left set.

The Kernal clears it at power-on and never sets it. If you use it, bracket it tightly.

The full tables

Cycle-exact matrices exist and are better than anything this page could reproduce:

Next: where everything lives.

Written for BIOS v1.5. Released under the MIT License.