Z80 instruction set
The Zilog Z80 is an 8-bit microprocessor introduced in 1976. The instruction set was designed to be upward binary compatible with the Intel 8080. Intel 8080 instructions are one to three bytes long whereas the Z80 requires up to four bytes per instruction.
Zilog continued to expand the instruction set of the Z80 with several successors including the Z180, Z280, and Z380. The latest iteration, the eZ80, was introduced in 2001 and was available for purchase as of 2025[update]. The instruction set also appears on non-Zilog CPUs such as the Hitachi HD64180,[1] Mitsui R800, and the Eastern Bloc U880.[2]
Instruction set
[edit]
The Z80 uses 252 out of the available 256 codes as single byte opcodes (the "root instructions"), most of which are inherited from the 8080. The four remaining codes are used extensively as opcode prefixes:[3] CB and ED enable extra instructions, and DD or FD select IX or IY respectively in place of HL. This scheme gives the Z80 a large number of permutations of instructions and registers. Zilog categorizes these into 158 different "instruction types", 78 of which are the same as those of the Intel 8080.[3] This allows operation of all 8080 programs on a Z80. The Zilog documentation[4] further groups instructions into categories. Most are from the 8080, others are entirely new like the block and bit instructions, and other 8080 instructions with more versatile addressing modes, like the 16-bit loads, I/O, rotates/shifts, and relative jumps. The categories are:
- Load and exchange
- Block transfer and search
- Arithmetic and logical
- Rotate and shift
- Bit manipulation (set, reset, test)
- Jump, call, and return
- Input/output
- CPU control
Encoding order
[edit]To expand on the 8080 instruction set, Z80 instructions may require a IX/IY override, an opcode prefix, or both. Any one instruction may contain up to four components. The components of the instruction are assembled in the following order:
IX/IY override |
CB or ED prefix |
(IX/IY + n) offset if CB |
Opcode |
(IX/IY + n) offset if no CB |
data or address |
Root instructions
[edit]The root opcodes include all the 8080 opcodes. The Z80 adds eight new one-byte instructions, two opcode prefixes, and the IX and IY overrides.[5] Colored rows indicate new Z80 instructions.
Opcode | Operands | Mnemonic | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | b2 | b3 | ||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | — | — | NOP | No operation |
0 | 0 | RP | 0 | 0 | 0 | 1 | datlo | dathi | LD rp,data | RP ← data | |
0 | 0 | RP | 0 | 0 | 1 | 0 | — | — | LD (rp),A | (RP) ← A [BC or DE only] | |
0 | 0 | RP | 0 | 0 | 1 | 1 | — | — | INC rp | RP ← RP + 1 | |
0 | 0 | DDD | 1 | 0 | 0 | — | — | INC ddd | DDD ← DDD + 1 | ||
0 | 0 | DDD | 1 | 0 | 1 | — | — | DEC ddd | DDD ← DDD - 1 | ||
0 | 0 | DDD | 1 | 1 | 0 | data | — | LD ddd,data | DDD ← data | ||
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | — | — | RLCA | A1-7 ← A0-6; A0 ← Cy ← A7 |
0 | 0 | RP | 1 | 0 | 0 | 1 | — | — | ADD rp | HL ← HL + RP | |
0 | 0 | RP | 1 | 0 | 1 | 0 | — | — | LD A,(rp) | A ← (RP) [BC or DE only] | |
0 | 0 | RP | 1 | 0 | 1 | 1 | — | — | DEC rp | RP ← RP - 1 | |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | — | — | EX AF,AF' | AF ↔ AF' |
0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | — | — | RRCA | A0-6 ← A1-7; A7 ← Cy ← A0 |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | offset | — | DJNZ offset | B = B - 1; if B ≠ 0 then PC ← PC + offset |
0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | — | — | RLA | A1-7 ← A0-6; Cy ← A7; A0 ← Cy |
0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | offset | — | JR offset | PC ← PC + offset |
0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | — | — | RRA | A0-6 ← A1-7; Cy ← A0; A7 ← Cy |
0 | 0 | 1 | CC | 0 | 0 | 0 | offset | — | JR cc,offset | If CC0-1 true, PC ← PC + offset (Only 2 lower bits of CC used: NZ, Z, NC, C) | |
0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | addlo | addhi | LD add,HL | (add) ← HL |
0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | — | — | DAA | In N flag = 0 {If A0-3 > 9 OR AC = 1 then A ← A + 6;
then if A4-7 > 9 OR Cy = 1 then A ← A + 0x60} else {do post-subtract DAA} |
0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | addlo | addhi | LD HL,add | HL ← (add) |
0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | — | — | CPL | A ← ¬A |
0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | addlo | addhi | LD add,A | (add) ← A |
0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | — | — | SCF | Cy ← 1 |
0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | addlo | addhi | LD A,add | A ← (add) |
0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | — | — | CCF | Cy ← ¬Cy |
0 | 1 | DDD | SSS | — | — | LD ddd,sss | DDD ← SSS | ||||
0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | — | — | HALT | Halt |
1 | 0 | ALU | SSS | — | — | ADD ADC SUB SBC AND XOR OR CP sss | A ← A [ALU operation] SSS | ||||
1 | 1 | CC | 0 | 0 | 0 | — | — | RET cc | If cc true, PC ← (SP), SP ← SP + 2 | ||
1 | 1 | RP | 0 | 0 | 0 | 1 | — | — | POP rp | RP ← (SP), SP ← SP + 2 | |
1 | 1 | CC | 0 | 1 | 0 | addlo | addhi | JP cc,add | If cc true, PC ← add | ||
1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | addlo | addhi | JP add | PC ← add |
1 | 1 | CC | 1 | 0 | 0 | addlo | addhi | CALL cc,add | If cc true, SP ← SP - 2, (SP) ← PC, PC ← add | ||
1 | 1 | RP | 0 | 1 | 0 | 1 | — | — | PUSH rp | SP ← SP - 2, (SP) ← RP | |
1 | 1 | ALU | 1 | 1 | 0 | data | — | ADD ADC SUB SBC AND XOR OR CP data | A ← A [ALU operation] data | ||
1 | 1 | N | 1 | 1 | 1 | — | — | RST n | SP ← SP - 2, (SP) ← PC, PC ← N | ||
1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | — | — | RET | PC ← (SP), SP ← SP + 2 |
1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | — | — | CB prefix | See CB prefix table |
1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | addlo | addhi | CALL add | SP ← SP - 2, (SP) ← PC, PC ← add |
1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | port | — | OUT port,A | Port(A:port) ← A † |
1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | — | — | EXX | (BC) ↔ (BC′), (DE) ↔ (DE'), (HL) ↔ (HL′) |
1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | port | — | IN A,port | A ← Port(A:port) † |
1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | — | — | IX override | HL becomes IX; (HL) becomes (IX + offset) |
1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | — | — | EX (SP),HL | (SP) ↔ HL |
1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | — | — | JP (HL) | PC ← HL |
1 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | — | — | EX DE,HL | HL ↔ DE |
1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | — | — | ED prefix | See ED prefix table |
1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | — | — | DI | IFF1 ← IFF2 ← 0; Disable interrupts |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | — | — | LD SP,HL | SP ← HL |
1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | — | — | EI | IFF1 ← IFF2 ← 1; Enable interrupts |
1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | — | — | IY override | HL becomes IY; (HL) becomes (IY + offset) |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | b2 | b3 | Mnemonic | Description |
SSS DDD | 2 | 1 | 0 | CC | ALU | RP | |||||
B | 0 | 0 | 0 | NZ | ADD (A ← A + arg) | BC | |||||
C | 0 | 0 | 1 | Z | ADC (A ← A + arg + Cy) | DE | |||||
D | 0 | 1 | 0 | NC | SUB (A ← A - arg) | HL | |||||
E | 0 | 1 | 1 | C | SBC (A ← A - arg - Cy) | SP or AF | |||||
H | 1 | 0 | 0 | PO | AND (A ← A ∧ arg) | ||||||
L | 1 | 0 | 1 | PE | XOR (A ← A ⊻ arg) | ||||||
(HL) | 1 | 1 | 0 | P | OR (A ← A ∨ arg) | ||||||
A | 1 | 1 | 1 | N | CP (A - arg) | ||||||
SSS DDD | 2 | 1 | 0 | CC | ALU |
† OUT port,A and IN A,port instructions generate a 16-bit port address with the 8-bit immediate port number forming the lower part of the address and the A register forming the upper part. Typically, devices will only decode the lower part. In contrast, the 8080 duplicates the immediate port number on both the upper and lower address bus.
Instructions prefixed with ED
[edit]The ED-prefixed opcodes are a catch-all of new Z80 instructions that could not be encoded in one byte. This group encompasses only 56 of 256 available opcodes.[5]
Opcode | Operands | Mnemonic | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | b2 | b3 | ||
0 | 1 | DDD | 0 | 0 | 0 | — | — | IN r,(C) | DDD ← port(BC) (Port number is 16 bits) | ||
0 | 1 | SSS | 0 | 0 | 1 | — | — | OUT (C),r | port(BC) ← SSS (Port number is 16 bits) | ||
0 | 1 | RP | 0 | 0 | 1 | 0 | — | — | SBC HL,ss | HL ← HL – ss – CY | |
0 | 1 | RP | 0 | 0 | 1 | 1 | addlo | addhi | LD (add), ss | (add) ← RP | |
0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | — | — | NEG | A ← 0 - A |
0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | — | — | RETN | PC ← (SP); SP ← SP + 2; IFF1 ← IFF2 |
0 | 1 | 0 | NN | 1 | 1 | 0 | — | — | IM n | Interrupt mode 0, 1, 2 (encoded 0, 2, 3) | |
0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | — | — | LD I,A | interrupt control vector ← A |
0 | 1 | RP | 1 | 0 | 1 | 0 | — | — | ADC HL,ss | HL ← HL + ss + CY | |
0 | 1 | RP | 1 | 0 | 1 | 1 | addlo | addhi | LD dd, (add) | RP ← (add) | |
0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | — | — | RETI | PC ← (SP); SP ← SP + 2; end interrupt |
0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | — | — | LD R,A | refresh ← A |
0 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | — | — | LD A,I | A ← interrupt control vector ‡ |
0 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | — | — | LD A,R | A ← refresh ‡ |
0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | — | — | RRD | A0-3 ← (HL)0-3; (HL)7-4 ← A0-3; (HL)0-3 ← (HL)7-4 |
0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | — | — | RLD | A0-3 ← (HL)7-4; (HL)0-3 ← A0-3; (HL)7-4 ← (HL)0-3 |
1 | 0 | 1 | R | D | 0 | 0 | 0 | — | — | LDI LDIR LDD LDDR | (DE) ← (HL); HL = HL ± 1; DE = DE ± 1; BC = BC - 1 † |
1 | 0 | 1 | R | D | 0 | 0 | 1 | — | — | CPI CPIR CPD CPDR | A - (HL); HL ← HL ± 1; BC ← BC - 1 † |
1 | 0 | 1 | R | D | 0 | 1 | 0 | — | — | INI INIR IND INDR | (HL) ← port(BC); HL ← HL ± 1; B ← B – 1 † |
1 | 0 | 1 | R | D | 0 | 1 | 1 | — | — | OTI OTIR OTD OTDR | port(BC) ← (HL); HL ← HL ± 1; B ← B – 1 † |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | b2 | b3 | Mnemonic | Description |
† When D = 1, pointers HL and DE decrement. When R = 1, operation repeats until BC or B = 0. CPIR/CPDR may terminate early if A = (HL). All block IO instructions output BC, not just C, as the port address. Block memory operations such as LDI or CPI set P/V if BC – 1 ≠ 0.
‡ LD A,I and LD A,R are the only two LD instructions that set flags. Additionally, IFF2 is loaded into the P/V flag. C unaffected.
Instructions prefixed with CB
[edit]The CB-prefixed opcodes cover shifts and rotates plus the bit test, clear, and set instructions. All of these instructions can be used with any register or memory. This group encompasses 248 of 256 available opcodes.[5]
Opcode | Mnemonic | Description | |||||||
---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
0 | 0 | 0 | 0 | 0 | SSS | RLC r | R1-7 ← R0-6; R0 ← Cy ← R7 | ||
0 | 0 | 0 | 0 | 1 | SSS | RRC r | R0-6 ← R1-7; R7 ← Cy ← R0 | ||
0 | 0 | 0 | 1 | 0 | SSS | RL r | R1-7 ← R0-6; Cy ← R7; R0 ← Cy | ||
0 | 0 | 0 | 1 | 1 | SSS | RR r | R0-6 ← R1-7; Cy ← R0; R7 ← Cy | ||
0 | 0 | 1 | 0 | 0 | SSS | SLA r | Cy ← R7; R1-7 ← R0-6; R0 ← 0 | ||
0 | 0 | 1 | 0 | 1 | SSS | SRA r | Cy ← R0; R0-6 ← R1-7 | ||
0 | 0 | 1 | 1 | 1 | SSS | SRL r | Cy ← R0; R0-6 ← R1-7; R7 ← 0 | ||
0 | 1 | bit | SSS | BIT b,r | R ∧ (1 << b) | ||||
1 | 0 | bit | SSS | RES b,r | R ← R ∧ ¬(1 << b) | ||||
1 | 1 | bit | SSS | SET b,r | R ← R ∨ (1 << b) | ||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Mnemonic | Description |
IX and IY overrides
[edit]Two opcode prefixes expand the number of Z80 addressing modes to access the new IX and IY index registers:
- Prefix DD changes HL to IX or (HL) to (IX+displacement)
- Prefix FD changes HL to IY or (HL) to (IY+displacement)
The index registers, IX and IY, were intended as flexible 16-bit pointers, enhancing the ability to manipulate memory, stack frames, and data structures. Officially, they were treated as 16-bit only. In reality, they were implemented as a pair of 8-bit registers[6] in the same fashion as the HL register, which is accessible either as 16 bits or separately as the high and low registers. The binary opcodes were identical, but preceded by a new opcode prefix.[7] Zilog published the opcodes and related mnemonics for the intended functions, but did not document the fact that every opcode that allowed manipulation of the HL register was equally valid for the 8-bit portions of the IX and IY registers. For example, the opcode 26h followed by an immediate byte value forms the instruction LD H,n
. It will load the n immediate value into the H register. Preceding this two-byte instruction with the IX register's opcode prefix, DD, would instead result in the most significant 8 bits of the IX register being loaded with that same value. A notable exception to this would be instructions similar to LD H,(IX+d)
which make use of both the HL and IX or IY registers in the same instruction.[7] In this case the DD prefix is only applied to the (IX+d) portion of the instruction. The halves of the IX and IY registers could also hold operands for 8-bit arithmetic, logical, and compare instructions, sparing the regular 8-bit registers for other use.
References
[edit]- ^ Cohen, Charles L. (4 March 1985). "Sun Rises on New Designs". ElectronicsWeek. pp. 18–21. Retrieved 2 June 2024.
- ^ "UD 880 und UD 855" [UD 880 and UD 855]. Radio Fernsehen Elektronik (in German). 35 (2). VEB Verlag Technik: 70. 1986. ISSN 0033-7900.
- ^ a b "Z80 CPU Introduction". Zilog. 1995. Archived from the original on December 20, 2023.
It has a language of 252 root instructions and with the reserved 4 bytes as prefixes, accesses an additional 308 instructions.
- ^ "Z80-CPU Instruction Set" (PDF). Zilog. 1976. p. 19. Archived from the original on November 5, 2023. Retrieved July 20, 2021.
- ^ a b c Z80 CPU User Manual (PDF) (11 ed.). Zilog. August 2016. Retrieved 15 August 2025.
- ^ Froehlich, Robert A. (1984). The free software catalog and directory. Crown Publishers. p. 133. ISBN 978-0-517-55448-7.
Undocumented Z80 codes allow 8-bit operations with IX and IY registers.
- ^ a b Bot, Jacco J. T. "Z80 Undocumented Instructions". Home of the Z80 CPU. Archived from the original on December 23, 2023.
If an opcode works with the registers HL, H or L then if that opcode is preceded by #DD (or #FD) it works on IX, IXH or IXL (or IY, IYH, IYL), with some exceptions. The exceptions are instructions like LD H,IXH and LD L,IYH.