Introduction
The HuC6280 has every instruction of the WDC 65C02 except WAI and STP, with the Rockwell bit instructions (RMB, SMB, BBR, BBS). Each form is written mode opcode, bytes, cycles; the cycle notes say what a taken branch, decimal mode and the T flag add. The cycle counts differ from the 65C02’s: most are higher, and a memory access takes 4 or 5 cycles instead of 3 or 4. Zero page operands are at $2000 + n. ADC, AND, EOR and ORA change meaning when the T flag is set. BRK is one byte, followed by a byte the processor skips; it returns to the address two bytes after the BRK and jumps through the vector at $FFF6. Where a flag differs from the 65C02 the entry says so.
Loads, stores, transfers and the stack
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
lda | imm A9, 2, 2zp A5, 2, 4zp,X B5, 2, 4abs AD, 3, 5abs,X BD, 3, 5abs,Y B9, 3, 5(zp) B2, 2, 7(zp,X) A1, 2, 7(zp),Y B1, 2, 7 | Load A. | N Z |
ldx | imm A2, 2, 2zp A6, 2, 4zp,Y B6, 2, 4abs AE, 3, 5abs,Y BE, 3, 5 | Load X. | N Z |
ldy | imm A0, 2, 2zp A4, 2, 4zp,X B4, 2, 4abs AC, 3, 5abs,X BC, 3, 5 | Load Y. | N Z |
sta | zp 85, 2, 4zp,X 95, 2, 4abs 8D, 3, 5abs,X 9D, 3, 5abs,Y 99, 3, 5(zp) 92, 2, 7(zp,X) 81, 2, 7(zp),Y 91, 2, 7 | Store A. | none |
stx | zp 86, 2, 4zp,Y 96, 2, 4abs 8E, 3, 5 | Store X. | none |
sty | zp 84, 2, 4zp,X 94, 2, 4abs 8C, 3, 5 | Store Y. | none |
stz | zp 64, 2, 4zp,X 74, 2, 4abs 9C, 3, 5abs,X 9E, 3, 5 | Store zero. | none |
tax | imp AA, 1, 2 | X = A. | N Z |
tay | imp A8, 1, 2 | Y = A. | N Z |
txa | imp 8A, 1, 2 | A = X. | N Z |
tya | imp 98, 1, 2 | A = Y. | N Z |
tsx | imp BA, 1, 2 | X = S. | N Z |
txs | imp 9A, 1, 2 | S = X. | none |
pha | imp 48, 1, 3 | Push A. | none |
php | imp 08, 1, 3 | Push P. | none |
phx | imp DA, 1, 3 | Push X. | none |
phy | imp 5A, 1, 3 | Push Y. | none |
pla | imp 68, 1, 4 | Pull A. | N Z |
plp | imp 28, 1, 4 | Pull P, including the T flag. | all |
plx | imp FA, 1, 4 | Pull X. | N Z |
ply | imp 7A, 1, 4 | Pull Y. | N Z |
Arithmetic, logic, shifts and bit tests
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
adc | imm 69, 2, 2zp 65, 2, 4zp,X 75, 2, 4abs 6D, 3, 5abs,X 7D, 3, 5abs,Y 79, 3, 5(zp) 72, 2, 7(zp,X) 61, 2, 7(zp),Y 71, 2, 7 | A = A + memory + C; in decimal mode on packed digits (+1 cycle). With T set it adds to memory at zero page X instead (+3 cycles): the T flag. | N V Z C |
sbc | imm E9, 2, 2zp E5, 2, 4zp,X F5, 2, 4abs ED, 3, 5abs,X FD, 3, 5abs,Y F9, 3, 5(zp) F2, 2, 7(zp,X) E1, 2, 7(zp),Y F1, 2, 7 | A = A − memory − (1 − C); decimal mode +1 cycle. Not affected by the T flag. | N V Z C |
and | imm 29, 2, 2zp 25, 2, 4zp,X 35, 2, 4abs 2D, 3, 5abs,X 3D, 3, 5abs,Y 39, 3, 5(zp) 32, 2, 7(zp,X) 21, 2, 7(zp),Y 31, 2, 7 | A = A AND memory. With T set it works on memory at zero page X (+3 cycles). | N Z |
ora | imm 09, 2, 2zp 05, 2, 4zp,X 15, 2, 4abs 0D, 3, 5abs,X 1D, 3, 5abs,Y 19, 3, 5(zp) 12, 2, 7(zp,X) 01, 2, 7(zp),Y 11, 2, 7 | A = A OR memory. With T set it works on memory at zero page X (+3 cycles). | N Z |
eor | imm 49, 2, 2zp 45, 2, 4zp,X 55, 2, 4abs 4D, 3, 5abs,X 5D, 3, 5abs,Y 59, 3, 5(zp) 52, 2, 7(zp,X) 41, 2, 7(zp),Y 51, 2, 7 | A = A XOR memory. With T set it works on memory at zero page X (+3 cycles). | N Z |
cmp | imm C9, 2, 2zp C5, 2, 4zp,X D5, 2, 4abs CD, 3, 5abs,X DD, 3, 5abs,Y D9, 3, 5(zp) D2, 2, 7(zp,X) C1, 2, 7(zp),Y D1, 2, 7 | Compare A with memory (A − memory, result discarded). | N Z C |
cpx | imm E0, 2, 2zp E4, 2, 4abs EC, 3, 5 | Compare X with memory. | N Z C |
cpy | imm C0, 2, 2zp C4, 2, 4abs CC, 3, 5 | Compare Y with memory. | N Z C |
bit | imm 89, 2, 2zp 24, 2, 4zp,X 34, 2, 4abs 2C, 3, 5abs,X 3C, 3, 5 | Z from A AND memory; N and V copy bits 7 and 6 of the memory byte. The immediate form sets N and V too on the one core read (the 65C02 changes only Z). | N V Z |
asl | acc 0A, 1, 2zp 06, 2, 6zp,X 16, 2, 6abs 0E, 3, 7abs,X 1E, 3, 7 | Shift left; bit 7 goes to C. | N Z C |
lsr | acc 4A, 1, 2zp 46, 2, 6zp,X 56, 2, 6abs 4E, 3, 7abs,X 5E, 3, 7 | Shift right; bit 0 goes to C. | N Z C |
rol | acc 2A, 1, 2zp 26, 2, 6zp,X 36, 2, 6abs 2E, 3, 7abs,X 3E, 3, 7 | Rotate left through C. | N Z C |
ror | acc 6A, 1, 2zp 66, 2, 6zp,X 76, 2, 6abs 6E, 3, 7abs,X 7E, 3, 7 | Rotate right through C. | N Z C |
inc | acc 1A, 1, 2zp E6, 2, 6zp,X F6, 2, 6abs EE, 3, 7abs,X FE, 3, 7 | Add one to A or memory. | N Z |
dec | acc 3A, 1, 2zp C6, 2, 6zp,X D6, 2, 6abs CE, 3, 7abs,X DE, 3, 7 | Subtract one from A or memory. | N Z |
inx | imp E8, 1, 2 | X = X + 1. | N Z |
iny | imp C8, 1, 2 | Y = Y + 1. | N Z |
dex | imp CA, 1, 2 | X = X − 1. | N Z |
dey | imp 88, 1, 2 | Y = Y − 1. | N Z |
trb | zp 14, 2, 6abs 1C, 3, 7 | Clear in memory the bits that are set in A; Z from A AND memory. The HuC6280 also copies bits 7 and 6 of memory to N and V (the core read; the 65C02 changes only Z). | N V Z |
tsb | zp 04, 2, 6abs 0C, 3, 7 | Set in memory the bits that are set in A; flags as TRB. | N V Z |
Jumps, branches, calls, flags and the bit instructions
| Instruction | Forms | What it does | Flags |
|---|---|---|---|
jmp | abs 4C, 3, 4(abs) 6C, 3, 7(abs,X) 7C, 3, 7 | Jump. The two indirect forms read the target from memory, low byte first. | none |
jsr | abs 20, 3, 7 | Call: push the address of the last byte of the instruction, jump. | none |
rts | imp 60, 1, 7 | Return: pull the address and add one. | none |
rti | imp 40, 1, 7 | Return from an interrupt: pull P (with T), then the address. | all |
brk | imp 00, 1, 8 | Software interrupt: push the address two bytes on and P with B set, clear D and T, set I, jump through the vector at $FFF6. | D I T |
nop | imp EA, 1, 2 | No operation. | none |
bpl | rel 10, 2, 2 | Branch if N is clear. +2 cycles if taken (all conditional branches). | none |
bmi | rel 30, 2, 2 | Branch if N is set. | none |
bvc | rel 50, 2, 2 | Branch if V is clear. | none |
bvs | rel 70, 2, 2 | Branch if V is set. | none |
bcc | rel 90, 2, 2 | Branch if C is clear. | none |
bcs | rel B0, 2, 2 | Branch if C is set. | none |
bne | rel D0, 2, 2 | Branch if Z is clear. | none |
beq | rel F0, 2, 2 | Branch if Z is set. | none |
bra | rel 80, 2, 4 | Branch always. | none |
clc | imp 18, 1, 2 | Clear C. | C |
cld | imp D8, 1, 2 | Clear D. | D |
cli | imp 58, 1, 2 | Clear I: enable interrupts. | I |
clv | imp B8, 1, 2 | Clear V. | V |
sec | imp 38, 1, 2 | Set C. | C |
sed | imp F8, 1, 2 | Set D: decimal mode. | D |
sei | imp 78, 1, 2 | Set I: disable interrupts. | I |
rmb0 … rmb7 | zp 07 17 27 37 47 57 67 77, 2, 7 | Clear bit n of a zero page byte (n = 0 to 7 in the order of the opcodes). | none |
smb0 … smb7 | zp 87 97 A7 B7 C7 D7 E7 F7, 2, 7 | Set bit n of a zero page byte. | none |
bbr0 … bbr7 | zp,rel 0F 1F 2F 3F 4F 5F 6F 7F, 3, 6 | Branch if bit n of a zero page byte is clear. +2 cycles if taken. | none |
bbs0 … bbs7 | zp,rel 8F 9F AF BF CF DF EF FF, 3, 6 | Branch if bit n of a zero page byte is set. +2 cycles if taken. | none |
Not described
Known, not yet covered
- Reference: the exact bus accesses of each instruction (the 65C02’s read-modify-write double read, for example).
Unknown
- Reference: the cycle counts here come from the jspce core and the Hudson table as remembered, not from a data sheet read for this work; PLA, PLP, PLX and PLY (4 here, 3 in the core) are the instructions where they differ.
- Reference: whether PLP and RTI really load the T flag, and whether BIT #immediate and TSB, TRB set N and V on real chips (cores only).