Introduction
The address bus is 24 bits: a bank byte and a 16-bit offset. Most modes give only the 16-bit
offset and take the bank from a register: the data bank register DB for data,
the program bank register PB for jumps and branches, and bank 0 for the direct
page, the stack and the vectors. The long modes carry the bank in the instruction. When an
offset plus an index passes $FFFF it carries into the bank, except in program-counter
arithmetic, which wraps inside the bank.
The modes
“Bytes” is the length of an instruction that uses the mode, native mode with M and X set. A 16-bit memory operand (M or X clear) is read from the address and the next one, low byte first.
| Mode | Syntax | Bytes | The address |
|---|---|---|---|
| Implied | clc | 1 | The operand is a register or flag the opcode names. |
| Accumulator | asl a | 1 | The accumulator is the operand. |
| Immediate | lda #$12 | 2, or 3 | The operand is in the instruction. The length is 3 for LDA, ADC, SBC, AND, ORA, EOR, CMP, BIT when M is clear and for LDX, LDY, CPX, CPY when X is clear; REP, SEP, COP, BRK and WDM always have one byte. |
| Direct page | lda $12 | 2 | Bank 0, address D + the operand byte. |
| Direct page indexed with X | lda $12,x | 2 | Bank 0, D + operand + X. |
| Direct page indexed with Y | ldx $12,y | 2 | Bank 0, D + operand + Y (LDX and STX only). |
| Direct page indirect | lda ($12) | 2 | The 16-bit pointer at bank 0, D + operand, in the data bank. |
| Direct page indexed indirect | lda ($12,x) | 2 | The pointer at bank 0, D + operand + X, in the data bank. |
| Direct page indirect indexed | lda ($12),y | 2 | The pointer at bank 0, D + operand, in the data bank, plus Y. |
| Direct page indirect long | lda [$12] | 2 | A 24-bit pointer at bank 0, D + operand: the bank comes from the third byte. |
| Direct page indirect long indexed | lda [$12],y | 2 | The 24-bit pointer plus Y. |
| Absolute | lda $1234 | 3 | The data bank, the 16-bit operand. For JMP and JSR the program bank. |
| Absolute indexed with X | lda $1234,x | 3 | DB:operand + X. |
| Absolute indexed with Y | lda $1234,y | 3 | DB:operand + Y. |
| Absolute long | lda $123456 | 4 | The 24-bit operand. |
| Absolute long indexed with X | lda $123456,x | 4 | The 24-bit operand + X. |
| Absolute indirect | jmp ($1234) | 3 | JMP only: the 16-bit pointer at bank 0, offset operand; the jump stays in the program bank. |
| Absolute indexed indirect | jmp ($1234,x) | 3 | JMP and JSR: the pointer at PB:operand + X, in the program bank. |
| Absolute indirect long | jml [$1234] | 3 | JML only: a 24-bit pointer at bank 0, offset operand. |
| Stack relative | lda $03,s | 2 | Bank 0, S + the operand byte: a local variable on the stack. |
| Stack relative indirect indexed | lda ($03,s),y | 2 | The pointer at S + operand, in the data bank, plus Y. |
| Relative | bne $8010 | 2 | PC after the instruction + the signed operand byte, wrapping inside the program bank. |
| Relative long | brl $8010 | 3 | PC after the instruction + the signed 16-bit operand (BRL and PER). |
| Block move | mvn $7e,$7f | 3 | Two bank bytes: the instruction’s second byte is the destination bank, the third the source bank; the assembler writes the source first. |
pea $1234 (absolute) and pei ($12) (direct page indirect) use these modes’ syntax, but push the address itself (PEA) or the 16-bit word the direct page holds (PEI) and read no data from it; see PEA.
Cycle tags
On the instruction pages each form is mode opcode, bytes, cycles. The cycles are the data sheet’s base count; a tag after it names an extra cost that depends on the state:
| Tag | Adds | When |
|---|---|---|
+M | 1 cycle | M is clear: a 16-bit accumulator or memory operand (also PHA and PLA). |
+2M | 2 cycles | M is clear, for a read-modify-write instruction on memory: it reads and writes the extra byte. |
+X | 1 cycle | X is clear: a 16-bit index register operand (LDX, LDY, STX, STY, CPX, CPY, PHX, PHY, PLX, PLY). |
+DL | 1 cycle | The low byte of the direct page register is not zero (every direct page mode, and PEI). |
+P | 1 cycle | The index crosses a page boundary, or X is clear (16-bit index). A store always takes this cycle, so its base count already includes it. |
+T | 1 cycle | A conditional branch is taken. |
+E | 1 cycle | In emulation mode only: a taken branch (BRA always) crosses a page boundary. |
BRK and COP take one cycle fewer in emulation mode (7, not 8), and RTI (6, not 7). A block move takes 7 cycles for each byte it moves, and runs until C reaches $FFFF after the byte, so it moves C + 1 bytes. REP and SEP take 3 cycles, XBA 3, WAI and STP 3 to start, other register instructions 2.
Not described
Known, not yet covered
- Reference: how each mode wraps at the end of the bank or the direct page (a direct page pointer at $FF, a stack pointer at $0000), which the data sheet describes in its notes on address wrapping. The explorer does not model memory.
Links
Reference
- 65816 reference – the Super Famicom Development Wiki: addressing modes and the cycle footnotes
- W65C816S data sheet – Western Design Center: the addressing mode table