Introduction
Loads and stores work on the accumulator (width by M) or an index register (width by X). The 65816 adds STZ (store zero) to the 6502’s set, 16-bit stack pushes and pulls, three more places to push an address, transfers to and from the stack pointer and the direct page register, and two block moves.
Loads and stores
Each form is written mode opcode, bytes, cycles, then the cycle tags. Bytes “2 or 3” is the immediate form, which is 3 when the flag that follows is clear.
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
lda | imm A9, 2 or 3, 2 +Mdp A5, 2, 3 +M +DLdp,X B5, 2, 4 +M +DLabs AD, 3, 4 +Mabs,X BD, 3, 4 +M +Pabs,Y B9, 3, 4 +M +Plong AF, 4, 5 +Mlong,X BF, 4, 5 +M(dp) B2, 2, 5 +M +DL(dp,X) A1, 2, 6 +M +DL(dp),Y B1, 2, 5 +M +DL +P[dp] A7, 2, 6 +M +DL[dp],Y B7, 2, 6 +M +DLsr,S A3, 2, 4 +M(sr,S),Y B3, 2, 7 +M | A = memory (8 or 16 bits). | N Z |
ldx | imm A2, 2 or 3, 2 +Xdp A6, 2, 3 +X +DLdp,Y B6, 2, 4 +X +DLabs AE, 3, 4 +Xabs,Y BE, 3, 4 +X +P | X = memory. | N Z |
ldy | imm A0, 2 or 3, 2 +Xdp A4, 2, 3 +X +DLdp,X B4, 2, 4 +X +DLabs AC, 3, 4 +Xabs,X BC, 3, 4 +X +P | Y = memory. | N Z |
sta | dp 85, 2, 3 +M +DLdp,X 95, 2, 4 +M +DLabs 8D, 3, 4 +Mabs,X 9D, 3, 5 +Mabs,Y 99, 3, 5 +Mlong 8F, 4, 5 +Mlong,X 9F, 4, 5 +M(dp) 92, 2, 5 +M +DL(dp,X) 81, 2, 6 +M +DL(dp),Y 91, 2, 6 +M +DL[dp] 87, 2, 6 +M +DL[dp],Y 97, 2, 6 +M +DLsr,S 83, 2, 4 +M(sr,S),Y 93, 2, 7 +M | Memory = A. There is no immediate form: opcode 89 is BIT. | – |
stx | dp 86, 2, 3 +X +DLdp,Y 96, 2, 4 +X +DLabs 8E, 3, 4 +X | Memory = X. | – |
sty | dp 84, 2, 3 +X +DLdp,X 94, 2, 4 +X +DLabs 8C, 3, 4 +X | Memory = Y. | – |
stz | dp 64, 2, 3 +M +DLdp,X 74, 2, 4 +M +DLabs 9C, 3, 4 +Mabs,X 9E, 3, 5 +M | Memory = 0 (8 or 16 bits, by M). | – |
Register transfers
All are one byte and two cycles (XBA three). A transfer to a register of a smaller width copies only the low byte; to a larger one, the register’s high byte is zero. TCD, TDC, TCS and TSC always use the full 16-bit accumulator.
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
tax | imp AA, 1, 2 | X = A (the width of X). | N Z |
tay | imp A8, 1, 2 | Y = A (the width of Y). | N Z |
txa | imp 8A, 1, 2 | A = X (the width of A). | N Z |
tya | imp 98, 1, 2 | A = Y (the width of A). | N Z |
txy | imp 9B, 1, 2 | Y = X. | N Z |
tyx | imp BB, 1, 2 | X = Y. | N Z |
tsx | imp BA, 1, 2 | X = the stack pointer (the width of X). | N Z |
txs | imp 9A, 1, 2 | The stack pointer = X. In emulation mode only the low byte is set; in native mode the full 16 bits. | – |
tcd | imp 5B, 1, 2 | The direct page register = the 16-bit accumulator. | N Z |
tdc | imp 7B, 1, 2 | The 16-bit accumulator = the direct page register. | N Z |
tcs | imp 1B, 1, 2 | The stack pointer = the 16-bit accumulator (low byte only in emulation mode). Also written TAS. | – |
tsc | imp 3B, 1, 2 | The 16-bit accumulator = the stack pointer. Also written TSA. | N Z |
xba | imp EB, 1, 3 | Exchange the two bytes of the 16-bit accumulator. N and Z reflect the new low byte, whatever M is. Also written SWA. | N Z |
The stack
The stack grows downward from S. A push stores at S and then decrements it; a pull increments S and reads. Pushes and pulls of the accumulator and index registers are 16 bits when the flag that follows them is clear.
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
pha | imp 48, 1, 3 +M | Push A (1 or 2 bytes). | – |
php | imp 08, 1, 3 | Push the status register. In emulation mode the pushed copy has the B flag (bit 4) set. | – |
phx | imp DA, 1, 3 +X | Push X (1 or 2 bytes). | – |
phy | imp 5A, 1, 3 +X | Push Y (1 or 2 bytes). | – |
phb | imp 8B, 1, 3 | Push the data bank register. | – |
phd | imp 0B, 1, 4 | Push the direct page register (2 bytes). | – |
phk | imp 4B, 1, 3 | Push the program bank register. | – |
pla | imp 68, 1, 4 +M | Pull A (1 or 2 bytes). | N Z |
plp | imp 28, 1, 4 | Pull the status register. In native mode this sets M and X from the stack, which a disassembler cannot know; setting X clears the high bytes of X and Y. | N V M X D I Z C |
plx | imp FA, 1, 4 +X | Pull X (1 or 2 bytes). | N Z |
ply | imp 7A, 1, 4 +X | Pull Y (1 or 2 bytes). | N Z |
plb | imp AB, 1, 4 | Pull the data bank register. The usual way to set it: phk then plb. | N Z |
pld | imp 2B, 1, 5 | Pull the direct page register (2 bytes). | N Z |
pea | abs F4, 3, 5 | Push the 16-bit operand itself (not what it addresses). | – |
pei | (dp) D4, 2, 6 +DL | Push the 16-bit word at the direct page address. | – |
per | rel long 62, 3, 6 | Push the address of the instruction after it plus the signed 16-bit operand: a position-independent address. | – |
Block moves
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
mvn | block 54, 3, 7 per byte | Copies C + 1 bytes (C is the 16-bit accumulator whatever M is) from the source bank at X to the destination bank at Y, ascending: X and Y each increase, C decreases, and DB is set to the destination bank. The instruction repeats itself until C is $FFFF. Written mvn src,dst; the bytes are the destination bank, then the source. With 8-bit index registers X and Y wrap at the end of the page. | – |
mvp | block 44, 3, 7 per byte | The same, descending: X and Y decrease, so X and Y start at the last byte. Use it when the destination overlaps the source and is above it. | – |
Not described
Known, not yet covered
- Reference: the detail of interrupts during a block move (it can be interrupted between bytes and resumes) and the wrap rules of the stack in emulation mode for PEA, PEI and PER.
Links
Reference
- 65816 reference – the Super Famicom Development Wiki’s instruction table
- W65C816S data sheet – Western Design Center