DECODING Z80 OPCODES
- of use to disassembler and emulator writers -
Document by Cristian Dinu, based on various sources of information (see the acknowledgements section)
For any suggestions, 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, not JP
(HL).
In the expression of an instruction, everything in bold should be taken ad literam, everything italic should be evaluated.
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 |
Registers pairs (table name: rp) |
---|
Index | 0 | 1 | 2 | 3 |
Value | BC | DE | HL | SP |
Registers 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 two NOPs.
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: Retrieve/store register pair from/to immediate address
q=0 | LD (nn), rp[p] | |
| |
q=1 | LD rp[p], (nn) | |
| |
z=3: 16-bit add/subtract with carry
q=0 | SBC HL, rp[p] | |
| |
q=1 | ADC HL, rp[p] | |
| |
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 two NOPs.
FOR x=3
Invalid instruction, equivalent to two NOPs.
DD-PREFIXED OPCODES
If the next byte is a DD, ED or FD prefix, this DD prefix is ignored (equiv. to a NOP) and processing continues with the next byte.
If the next byte is a CB prefix, the instruction will be read as follows:
DD CB d op (a total of 4 bytes)
CB and op will form a CB-instruction which can be decoded as stated earlier. However, the instruction will now also act on (IX+d). For instance, RLC B becomes RLC B, (IX+d). If the instruction acted on (HL) or if the mnemonic was BIT, the instruction will only act on (IX+d).
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 opcodes are unaffected.
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.
- EOF -