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)
Index01234567
ValueBCDEHL(HL)A

Register pairs (table name: rp)
Index0123
ValueBCDEHLSP

Register pairs with AF instead of SP (table name: rp2)
Index0123
ValueBCDEHLAF

Conditions (table name: cc)
Index01234567
ValueNZZNCCPOPEPM

Artithmetic/logic operations (table name: alu)
Index01234567
ValueADD A,ADC A,SUBSBC A,ANDXORORCP

Rotation/shift operations (table name: rot)
Index01234567
ValueRLCRRCRLRRSLASRASLLSRL

Interrupt modes (table name: im)
Index01234567
Value00/11200/112

Block instructions (table name: bli)
z0123
y=4LDICPIINIOUTI
y=5LDDCPDINDOUTD
y=6LDIRCPIRINIROTIR
y=7LDDRCPDRINDROTDR


UNPREFIXED OPCODES

FOR x=0

z=0: Relative jumps and assorted ops

y=0NOP y=3JR d
y=1EX AF, AF' y=4..7JR cc[y-4], d
y=2DJNZ d

z=1: 16-bit load immediate/add

q=0LD rp[p], nn
q=1ADD HL, rp[p]

z=2: Indirect loading

y=0LD (BC), A y=4LD (nn), HL
y=1LD A, (BC) y=5LD HL, (nn)
y=2LD (DE), A y=6LD (nn), A
y=3LD A, (DE) y=7LD A, (nn)

z=3: 16-bit INC/DEC

q=0INC rp[p]
q=1DEC rp[p]

z=4: 8-bit INC

INC r[y]

z=5: 8-bit DEC

DEC r[y]

z=6: 8-bit load immediate

LD r[y], n

z=7: Assorted operations on accumulator/flags

y=0RLCA y=4DAA
y=1RRCA y=5CPL
y=2RLA y=6SCF
y=3RRA y=7CCF


FOR x=1

8-bit loading

LD r[y], r[z]

Exception: if y=6 and z=6, the instruction is HALT.


FOR x=2

Operate on accumulator and register/memory location

alu[y] r[z]


FOR x=3

z=0: Conditional return

RET cc[y]

z=1: POP & various ops

q=0POP rp2[p]
q=1p=0RET p=2JP HL
p=1EXX p=3LD SP, HL

z=2: Conditional jump

JP cc[y], nn

z=3: Assorted operations

y=0JP nn y=4EX (SP), HL
y=1(CB prefix) y=5EX DE, HL
y=2OUT (n), A y=6DI
y=3IN A, (n) y=7EI

z=4: Conditional call

CALL cc[y], nn

z=5: PUSH & various ops

q=0PUSH rp2[p]
q=1p=0CALL nn p=2(ED prefix)
p=1(DD prefix) p=3(FD prefix)

z=6: Operate on accumulator and immediate operand

alu[y] n

z=7: Restart

RST y*8 (in hex)


CB-PREFIXED OPCODES

x=0: Roll/shift register or memory location

rot[y] r[z]

x=1: Test bit

BIT y, r[z]

x=2: Reset bit

RES y, r[z]

x=3: Set bit

SET y, r[z]


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<>6IN r[y], (C)
y=6IN (C)

z=1: Output to 16-bit port

y<>6OUT (C), r[y]
y=6OUT (C), 0

z=2: 16-bit add/subtract with carry

q=0SBC HL, rp[p]
q=1ADC HL, rp[p]

z=3: Retrieve/store register pair from/to immediate address

q=0LD (nn), rp[p]
q=1LD rp[p], (nn)

z=4: Negate accumulator

NEG

z=5: Return from interrupt

y<>1RETN
y=1RETI

z=6: Set interrupt mode

IM im[y]

z=7: Assorted ops

y=0LD I, A y=4RRD
y=1LD R, A y=5RLD
y=2LD A, I y=6NOP
y=3LD I, A y=7NOP


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<>6LD r[z], rot[y] (IX+d)
z=6rot[y] (IX+d)

x=1: Test bit at memory location

BIT y, (IX+d)

x=2: Reset bit and copy result to register

z<>6LD r[z], RES y, (IX+d)
z=6RES y, (IX+d)

x=3: Set bit and copy result to register

z<>6LD r[z], SET y, (IX+d)
z=6SET 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 -