DECODING Z80 OPCODES
- of use to disassembler and emulator writers -
Revision 2
Document by Cristian Dinu, compiled using various sources of information (see the acknowledgements section). You need a browser that supports Cascading Style Sheets (CSS) to view this file.
For any comments, suggestions, typo/factual error reports, please visit the World Of Spectrum forum and post a message there for GOC.
CONTENTS
General info
Unprefixed opcodes
CB-prefixed opcodes
ED-prefixed opcodes
DD-prefixed opcodes
FD-prefixed opcodes
Acknowledgements
GENERAL INFO
Notations
x = the number formed from bits 6 and 7 of the opcode (0 is the least significant)
y = the number formed from bits 3, 4 and 5 of the opcode
z = the number formed from bits 0, 1 and 2 of the opcode
p = the number formed from bits 4 and 5 of the opcode (i.e. y divided by 2)
q = the value of bit 3 of the opcode (i.e. y mod 2)
n = 8-bit immediate unsigned operand (number)
d = 8-bit immediate signed displacement
nn = 16-bit immediate operand (number)
tab[x] = whatever is contained in the table named tab at index x (analogous for y and z and other table names)
All instructions with d, n or nn in their expression are generally immediately followed by the displacement/operand (a byte or a word, respectively).
Although relative jump instructions are often shown with a 16-bit address following them, here they will take the form JR/DJNZ d, where d is the signed 8-bit displacement that follows. The jump's final address is obtained by adding the displacement to the instruction's address plus 2.
In this document, the 'jump to HL' instruction is written in its correct form JP HL, as opposed to JP
(HL).
In the expression of an instruction, everything in bold should be taken ad literam, everything italic should be evaluated.
This document makes use of an imaginary instruction with the mnemonic NONI (No Operation No Interrupts). Its interpretation is 'perform a no-operation (wait 4 T-states) and do not allow interrupts to occur immediately after this instruction'. Depending on the context, the Z80 may actually do more than just a simple NOP, but the effects are irrelevant assuming normal operation of the processor.
Tables
8-bit registers (table name: r) |
---|
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | B | C | D | E | H | L | (HL) | A |
Register pairs (table name: rp) |
---|
Index | 0 | 1 | 2 | 3 |
Value | BC | DE | HL | SP |
Register pairs with AF instead of SP (table name: rp2) |
---|
Index | 0 | 1 | 2 | 3 |
Value | BC | DE | HL | AF |
Conditions (table name: cc) |
---|
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | NZ | Z | NC | C | PO | PE | P | M |
Artithmetic/logic operations (table name: alu) |
---|
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | ADD A, | ADC A, | SUB | SBC A, | AND | XOR | OR | CP |
Rotation/shift operations (table name: rot) |
---|
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | RLC | RRC | RL | RR | SLA | SRA | SLL | SRL |
Interrupt modes (table name: im) |
---|
Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Value | 0 | 0/1 | 1 | 2 | 0 | 0/1 | 1 | 2 |
Block instructions (table name: bli) |
---|
z | 0 | 1 | 2 | 3 |
y=4 | LDI | CPI | INI | OUTI |
y=5 | LDD | CPD | IND | OUTD |
y=6 | LDIR | CPIR | INIR | OTIR |
y=7 | LDDR | CPDR | INDR | OTDR |
UNPREFIXED OPCODES
FOR x=0
z=0: Relative jumps and assorted ops
y=0 | NOP | |
y=3 | JR d |
y=1 | EX AF, AF' | |
y=4..7 | JR cc[y-4], d |
y=2 | DJNZ d | |
| |
z=1: 16-bit load immediate/add
q=0 | LD rp[p], nn | |
| |
q=1 | ADD HL, rp[p] | |
| |
z=2: Indirect loading
y=0 | LD (BC), A | |
y=4 | LD (nn), HL |
y=1 | LD A, (BC) | |
y=5 | LD HL, (nn) |
y=2 | LD (DE), A | |
y=6 | LD (nn), A |
y=3 | LD A, (DE) | |
y=7 | LD A, (nn) |
z=3: 16-bit INC/DEC
q=0 | INC rp[p] | |
| |
q=1 | DEC rp[p] | |
| |
z=4: 8-bit INC
z=5: 8-bit DEC
z=6: 8-bit load immediate
z=7: Assorted operations on accumulator/flags
y=0 | RLCA | |
y=4 | DAA |
y=1 | RRCA | |
y=5 | CPL |
y=2 | RLA | |
y=6 | SCF |
y=3 | RRA | |
y=7 | CCF |
FOR x=1
8-bit loading
Exception: if y=6 and z=6, the instruction is HALT.
FOR x=2
Operate on accumulator and register/memory location
FOR x=3
z=0: Conditional return
z=1: POP & various ops
q=0 | POP rp2[p] | |
| |
q=1 | p=0 | RET | |
p=2 | JP HL |
| p=1 | EXX | |
p=3 | LD SP, HL |
z=2: Conditional jump
z=3: Assorted operations
y=0 | JP nn | |
y=4 | EX (SP), HL |
y=1 | (CB prefix) | |
y=5 | EX DE, HL |
y=2 | OUT (n), A | |
y=6 | DI |
y=3 | IN A, (n) | |
y=7 | EI |
z=4: Conditional call
z=5: PUSH & various ops
q=0 | PUSH rp2[p] | |
| |
q=1 | p=0 | CALL nn | |
p=2 | (ED prefix) |
| p=1 | (DD prefix) | |
p=3 | (FD prefix) |
z=6: Operate on accumulator and immediate operand
z=7: Restart
CB-PREFIXED OPCODES
x=0: Roll/shift register or memory location
x=1: Test bit
x=2: Reset bit
x=3: Set bit
ED-PREFIXED OPCODES
FOR x=0
Invalid instruction, equivalent to NONI followed by NOP.
FOR x=1
z=0: Input from 16-bit port
y<>6 | IN r[y], (C) | |
| |
y=6 | IN (C) | |
| |
z=1: Output to 16-bit port
y<>6 | OUT (C), r[y] | |
| |
y=6 | OUT (C), 0 | |
| |
z=2: 16-bit add/subtract with carry
q=0 | SBC HL, rp[p] | |
| |
q=1 | ADC HL, rp[p] | |
| |
z=3: Retrieve/store register pair from/to immediate address
q=0 | LD (nn), rp[p] | |
| |
q=1 | LD rp[p], (nn) | |
| |
z=4: Negate accumulator
z=5: Return from interrupt
z=6: Set interrupt mode
z=7: Assorted ops
y=0 | LD I, A | |
y=4 | RRD |
y=1 | LD R, A | |
y=5 | RLD |
y=2 | LD A, I | |
y=6 | NOP |
y=3 | LD I, A | |
y=7 | NOP |
FOR x=2
For y=4..7 and z=0..3, the instruction is bli[y,z].
Otherwise, invalid instruction, equivalent to NONI followed by NOP.
FOR x=3
Invalid instruction, equivalent to NONI followed by NOP.
DD-PREFIXED OPCODES
If the next byte is a DD, ED or FD prefix, this DD prefix is ignored (it's equivalent to a NONI) and processing continues with the next byte.
If the next byte is a CB prefix, the instruction will be decoded as stated in the following section, "DDCB-prefixed opcodes".
Otherwise:
If the next opcode makes use of HL, H, L, but not (HL), any occurence of these will be replaced by IX, IXH, IXL respectively. An exception of this is EX DE, HL which is unaffected.
If the next opcode makes use of (HL), it will be replaced by (IX+d), where d is a signed 8-bit displacement immediately following the opcode (any immediate data such as n or nn will follow the displacement byte). Other instances of H and L are unaffected.
All other instructions are unaffected.
DDCB-PREFIXED OPCODES
These instructions have the following format:
DD CB d op (a total of 4 bytes)
CB and op will form instructions similar to those in the "CB-prefixed opcodes" section above. However, these will operate on (IX+d) and, if the instruction isn't BIT, copy the result to the register they would have initially acted upon, unless it was (HL).
x=0: Roll/shift memory location and copy result to register
z<>6 | LD r[z], rot[y] (IX+d) |
| |
z=6 | rot[y] (IX+d) |
| |
x=1: Test bit at memory location
x=2: Reset bit and copy result to register
z<>6 | LD r[z], RES y, (IX+d) |
|
z=6 | RES y, (IX+d) |
| |
x=3: Set bit and copy result to register
z<>6 | LD r[z], SET y, (IX+d) |
|
z=6 | SET y, (IX+d) |
| |
An instruction such as LD r, RES b, (IX+d) should be interpreted as "attempt to reset bit b of the byte at IX+d, and copy the result to register r, even if you cannot write the new byte at the said address (i.e. when it points to a ROM location).
Such an instruction is sometimes also represented in this form: RES r, (IX+d), r.
FD-PREFIXED OPCODES
The FD prefix acts exactly like the DD prefix, but it brings in the IY register instead of IX.
ACKNOWLEDGEMENTS
The 'algorithm' described herein was constructed by studying an "instruction/flags affected/binary form/effect" list in a Romanian book called "Ghidul Programatorului ZX Spectrum" ("The ZX Spectrum Programmer's Guide").
The exact effects and quirks of the CB/DD/ED/FD prefixes, as well as the undoccumented ED and CB instructions, were learnt from "The Undocumented Z80 Documented" by Sean Young.
My thanks to Ven Reddy, who suggested the use of a better representation for the DDCB instructions, and to Dr Phillip Kendall, who pointed out several subtle errors in the representation of invalid instructions.
- EOF -
|