Changes
Z80
,The Z80/Z80A was a very popular microprocessor, used in a wide range of applications, from gaming consoles like the [[ColecoVision]], the [[Sega Master System]] and [[Sega GameGear]] to personal computers like the [[ZX81]], [[ZX Spectrum]] and [[MSX]].
The best-selling devices to feature a Zilog Z80 are the [[Sega MegaDrive]] with 40 million units sold [https://segaretro.org/Sega_Mega_Drive#:~:text=The%20Mega%20Drive%20is%20Sega%27s,and%203%20million%20in%20Brazil. Source], and the TI graphing calculators with 90 million units sold [https://drive.google.com/file/d/1PshC6_lvHiBqry2ASsZ5D0AonmW01nxQ/view Source].
The Z80 microprocessor is an 8-bit [[CPU]] with a 4-bit ALU and a 16-bit address bus capable of direct access to 64KB of memory space. The Z80 is a little-endian CPU, meaning it stores 16-bit values with the least significant byte first, followed by the most significant byte.
The Z80 has about 8500 transistors. To put it into perspective, 64KB of DRAM contains 524288 transistors, as 1 bit of DRAM needs 1 transistor. Fun fact: an Amstrad CPC equipped with a 4MB RAM expansion has 32 million transistors dedicated to RAM while the Z80 CPU still has only 8500 transistors.
* P = parity (only for the parity flag)
* V = overflow (only for the parity flag)
==== Registers ====
! Instruction !! Opcode !! Hexcode !! NOPs !! Cycles !! M-Cycle Sequence !! S !! Z !! 5 !! H !! 3 !! P !! N !! C !! Effect !! Description
|-
| ld r,r̃ || 01rrrr̃r̃r̃ || 40-45/47-4D/4F-55/57-5D/5F-65/67-6D/6F/78-7F || 1 || 4 (4) || M1 || rowspan=15|- || rowspan=15|- || rowspan=15|- || rowspan=15|- || rowspan=15|- || rowspan=15|- || rowspan=15|- || rowspan=15|- || r := r̃ ||rowspan=15|8-bit Load
|-
| ld (hl),r || 01110rrr || 70/71/72/73/74/75/77 || 2 || 7 (4,3) || M1, MW || (hl) := r
| ld r,(hl) || 01rrr110 || 46/4E/56/5E/66/6E/7E || 2 || 7 (4,3) || M1, MR || r := (hl)
|-
| ld s,s̃ || 01ssss̃s̃s̃ || DD/FD 40-6F/78-7F || 2 || 8 (4,4) || M1, M1 || s := s̃
|-
| ld (ixy+d),r || 01110rrr || DD/FD 70/71/72/73/74/75/77 dd || 5 || 19 (4,4,3,5,3) || M1, M1, MRd, INT(5), MW || (ixy+d) := r
|| Decimal Adjust Accumulator
|-
| rrd || 01100111 || ED 67 || 5 || 18 (4,4,3,4,3) || M1, M1, MR, INT(4), MW || + || + || + || 0 || + || P || 0 || - || tmp := (hl), (hl) := [tmp >> 4] + [[a and 0x0f] << 4],<br> a := [a and 0xf0] + [tmp and 0x0f] => flags
|| Rotate Right Decimal
|-
| rld || 01101111 || ED 6F || 5 || 18 (4,4,3,4,3) || M1, M1, MR, INT(4), MW || + || + || + || 0 || + || P || 0 || - || tmp := [(hl) << 4] + [a and 0x0f], (hl) := tmp,<br> a := [a and 0xf0] + [tmp >> 8] => flags
|| Rotate Left Decimal
|}
! Instruction !! Opcode !! Hexcode !! NOPs !! Cycles !! M-Cycle Sequence !! S !! Z !! 5 !! H !! 3 !! P !! N !! C !! Effect !! Description
|-
| bit b,r || 01bbbrrr || CB 40-45/47-4D/4F-55/57-5D/5F-65/67-6D/6F-75/77-7D/7F || 2 || 8 (4,4) || M1, M1 || + || + || + || 1 || + || P || 0 || - || tmp := r and [1 << b] ||rowspan=3|Test Bit
|-
| bit b,(hl) || 01bbb110 || CB 46/4E/56/5E/66/6E/76/7E || 3 || 12 (4,4,4) || M1, M1, MR, INT(1) || + || + || X || 1 || X || P || 0 || - || tmp := (hl) and [1 << b], <br> f5 := wz.13, f3 := wz.11
| bit b,(ixy+d) || 01bbb110 || DD/FD CB dd 46/4E/56/5E/66/6E/76/7E || 6 || 20 (4,4,3,5,4) || M1, M1, MRd, MRo, INT(2), MR, INT(1) || + || + || X || 1 || X || P || 0 || - || tmp := (ixy+d) and [1 << b], <br> f5 := [ixy+d].13, f3 := [ixy+d].11
|-
| res b,r || 10bbbrrr || CB 80-85/87-8D/8F-95/97-9D/9F-A5/A7-AD/AF-B5/B7-BD/BF || 2 || 8 (4,4) || M1, M1 || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || r := r and ~[1 << b] ||rowspan=4|Reset Bit
|-
| res b,(ixy+d)->r || 10bbbrrr || DD/FD CB dd 80-85/87-8D/8F-95/97-9D/9F-A5/A7-AD/AF-B5/B7-BD/BF || 7 || 23 (4,4,3,5,4,3) || M1, M1, MRd, MRo, INT(2), MR, INT(1), MW || (ixy+d) := r := (ixy+d) and ~[1 << b]
|-
| res b,(hl) || 10bbb110 || CB 86/8E/96/9E/A6/AE/B6/BE || 4 || 15 (4,4,4,3) || M1, M1, MR, INT(1), MW || (hl) := (hl) and ~[1 << b]
| res b,(ixy+d) || 10bbb110 || DD/FD CB dd 86/8E/96/9E/A6/AE/B6/BE || 7 || 23 (4,4,3,5,4,3) || M1, M1, MRd, MRo, INT(2), MR, INT(1), MW || (ixy+d) := (ixy+d) and ~[1 << b]
|-
| set b,r || 11bbbrrr || CB C0-C5/C7-CD/CF-D5/D7-DD/DF-E5/E7-ED/EF-F5/F7-FD/7F FF || 2 || 8 (4,4) || M1, M1 || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || r := r or [1 << b] ||rowspan=4|Set Bit
|-
| set b,(ixy+d)->r || 11bbbrrr || DD/FD CB dd C0-C5/C7-CD/CF-D5/D7-DD/DF-E5/E7-ED/EF-F5/F7-FD/7F FF || 7 || 23 (4,4,3,5,4,3) || M1, M1, MRd, MRo, INT(2), MR, INT(1), MW || (ixy+d) := r := (ixy+d) or [1 << b]
|-
| set b,(hl) || 11bbb110 || CB C6/CE/D6/DE/E6/EE/F6/FE || 4 || 15 (4,4,4,3) || M1, M1, MR, INT(1), MW || (hl) := (hl) or [1 << b]
! Instruction !! Opcode !! Hexcode !! NOPs !! Cycles !! M-Cycle Sequence !! S !! Z !! 5 !! H !! 3 !! P !! N !! C !! Effect !! Description
|-
| ldi || 10100000 || ED A0 || 5 || 16 (4,4,3,5) || M1, M1, MR, MW, INT(2) || rowspan=4|- || rowspan=4|- || rowspan=4|X || rowspan=4|0 || rowspan=4|X || rowspan=4|C X || rowspan=4|0 || rowspan=4|- || tmp := (hl), (de) := tmp, de += 1, hl += 1, <br> bc -= 1, pf := bc!=0, f5 := [tmp + a].1, f3 := [tmp + a].3 || rowspan=4|Block Load
|-
| ldd || 10101000 || ED A8 || 5 || 16 (4,4,3,5) || M1, M1, MR, MW, INT(2) || tmp := (hl), (de) := tmp, de -= 1, hl -= 1, <br> bc -= 1, pf := bc!=0, f5 := [tmp + a].1, f3 := [tmp + a].3
|-
| ldir || 10110000 || ED B0 || 6/5 || 21/16 (4,4,3,5,5)/(4,4,3,5) || M1, M1, MR, MW, INT(2)(, INT(5)) || ldi, if bc != 0 then pc -= 2
| lddr || 10111000 || ED B8 || 6/5 || 21/16 (4,4,3,5,5)/(4,4,3,5) || M1, M1, MR, MW, INT(2)(, INT(5)) || ldd, if bc != 0 then pc -= 2
|-
| cpi || 10100001 || ED A1 || 4 || 16 (4,4,3,5) || M1, M1, MR, INT(5) || rowspan=4|+ || rowspan=4|+ || rowspan=4|X || rowspan=4|+ || rowspan=4|X || rowspan=4|C X || rowspan=4|1 || rowspan=4|- || tmp := a - (hl) => flags, bc -= 1, hl += 1, <br> bc -= 1, pf := bc!=0, f5 := [tmp - hf].1, f3 = [tmp - hf].3 || rowspan=4|Block Compare
|-
| cpd || 10101001 || ED A9 || 4 || 16 (4,4,3,5) || M1, M1, MR, INT(5) || tmp := a - (hl) => flags, bc -= 1, hl -= 1, <br> bc -= 1, pf := bc!=0, f5 := [tmp - hf].1, f3 = [tmp - hf].3
|-
| cpir || 10110001 || ED B1 || 6/4 || 21/16 (4,4,3,5,5)/(4,4,3,5) || M1, M1, MR, INT(5)(, INT(5)) || cpi, if bc != 0 and nz then pc -= 2
| cpdr || 10111001 || ED B9 || 6/4 || 21/16 (4,4,3,5,5)/(4,4,3,5) || M1, M1, MR, INT(5)(, INT(5)) || cpd, if bc != 0 and nz then pc -= 2
|-
| ini || 10100010 || ED A2 || 5 || 16 (4,5,4,3) || M1, M1, INT(1), IOR, MW || rowspan=4|+ || rowspan=4|+ || rowspan=4|+ || rowspan=4|X || rowspan=4|+ || rowspan=4|X || rowspan=4|X 1 || rowspan=4|X || tmp := ((c)), (hl) := tmp, hl += 1, <br> b -= 1 => flags, nf := tmp.7, <br> tmp2 := tmp + [[c + 1] and 0xff], <br> pf := parity of [[tmp2 and 0x07] xor b], <br> hf := cf := tmp2 > 255 || rowspan=4|Block I/O Input
|-
| ind || 10101010 || ED AA || 5 || 16 (4,5,4,3) || M1, M1, INT(1), IOR, MW || tmp := ((c)), (hl) := tmp, hl -= 1, <br> b -= 1 => flags, nf := tmp.7, <br> tmp2 = tmp + [[c - 1] and 0xff], <br> pf := parity of [[tmp2 and 0x07] xor b], <br> hf := cf := tmp2 > 255
|-
| inir || 10110010 || ED B2 || 6/5 || 21/16 (4,5,4,3,5)/(4,5,4,3) || M1, M1, INT(1), IOR, MW(, INT(5)) || ini, if b != 0 then pc -= 2
| indr || 10111010 || ED BA || 6/5 || 21/16 (4,5,4,3,5)/(4,5,4,3) || M1, M1, INT(1), IOR, MW(, INT(5)) || ind, if b != 0 then pc -= 2
|-
| outi || 10100011 || ED A3 || 5 || 16 (4,5,3,4) || M1, M1, INT(1), MR, IOW || rowspan=4|+ || rowspan=4|+ || rowspan=4|+ || rowspan=4|X || rowspan=4|+ || rowspan=4|X || rowspan=4|X 1 || rowspan=4|X || tmp := (hl), ((c)) := tmp, hl += 1, <br> b -= 1 => flags, nf := tmp.7, tmp2 = tmp + l, <br> pf := parity of [[tmp2 and 0x07] xor b], <br> hf := cf := tmp2 > 255 || rowspan=4|Block I/O Output
|-
| outd || 10101011 || ED AB || 5 || 16 (4,5,3,4) || M1, M1, INT(1), MR, IOW || tmp := (hl), ((c)) := tmp, hl -= 1, <br> b -= 1 => flags, nf := tmp.7, tmp2 = tmp + l, <br> pf := parity of [[tmp2 and 0x07] xor b], <br> hf := cf := tmp2 > 255
|-
| otir || 10110011 || ED B3 || 6/5 || 21/16 (4,5,3,4,5)/(4,5,3,4) || M1, M1, INT(1), MR, IOW(, INT(5)) || outi, if b != 0 then pc -= 2
| call cc,nn || 11ccc100 || C4/CC/D4/DC/E4/EC/F4/FC lo hi || 5/3 || 17/10 (4,3,4,3,3)/(4,3,3) || M1, MRl, MRh(, INT(1), MW, MW) || if cc then sp -= 2, (sp) := pc, pc := nn || Conditional call <br> ccc: 000=NZ, 001=Z, 010=NC, 011=C, 100=PO, 101=PE, 110=P, 111=M
|-
| jp nn (hl) || 11000011 11101001 || C3 lo hi E9 || 3 1 || 10 4 (4,3,3) || M1, MRl, MRh || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || pc := nn hl ||rowspan=3|Jump|-| jp (hl) || 11101001 || E9 || 1 || 4 (4) || M1 || pc := hl
|-
| jp (ixy) || 11101001 || DD/FD E9 || 2 || 8 (4,4) || M1, M1 || pc := ixy
|-
| jp nn || 11000011 || C3 lo hi || 3 || 10 (4,3,3) || M1, MRl, MRh || pc := nn
|-
| jp cc,nn || 11ccc010 || C2/CA/D2/DA/E2/EA/F2/FA lo hi || 3 || 10 (4,3,3) || M1, MRl, MRh || if cc then pc := nn || Conditional jump <br> ccc: 000=NZ, 001=Z, 010=NC, 011=C, 100=PO, 101=PE, 110=P, 111=M
| jr cc,e || 001cc000 || 20/28/30/38 ee || 3/2 || 12/7 (4,3,5)/(4,3) || M1, MRe(, INT(5)) || if cc then pc += e || Conditional relative jump <br> cc: 00=NZ, 01=Z, 10=NC, 11=C
|-
| djnz e || 00010000 || 10 ee || 4/3 || 13/8 (5,3,5)/(5,3) || M1, INT(1), MRe(, INT(5)) || b -= 1, if b <> != 0 then pc += e || Decrement, Jump Non-Zero
|-
| ret || 11001001 || C9 || 3 || 10 (4,3,3) || M1, MR, MR || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || rowspan=4|- || pc := (sp), sp += 2 || Return
| nop || 00000000 || 00 || 1 || 4 (4) || M1 || - || - || - || - || - || - || - || - || nothing ||No Operation
|-
| scf || 00110111 || 37 || 1 || 4 (4) || M1 || - || - || A X || 0 || A X || - || 0 || 1 || nothing else f5 := f5 or a.5, f3 := f3 or a.3 || Set Carry Flag
|-
| ccf || 00111111 || 3F || 1 || 4 (4) || M1 || - || - || A X || X || A X || - || 0 || X || hf := cf, cf := ~cf , f5 := f5 or a.5, f3 := f3 or a.3 || Complement Carry Flag
|-
| exx || 11011001 || D9 || 1 || 4 (4) || M1 || - || - || - || - || - || - || - || - || bc, de, hl <=> bc', de', hl' ||rowspan=5|Exchange
|-
| ex af,af' || 00001000 || 08 || 1 || 4 (4) || M1 || X || X || X || X || X || X || X || X || af <=> af'
|}
<br>
=== Interrupt Acknowledge ===
{| class="wikitable" style="white-space: nowrap;"
|-
! Type !! Cycles !! M-Cycle Sequence !! Effect !! Description
|-
| Non-Maskable Interrupt || 11 (5, 3, 3) || M1, Int(1), MW (Push PCH), MW (Push PCL) || iff2 := iff1, iff1 := 0, sp -= 2, (sp) := pc, pc := 0066h || Highest priority interrupt. Cannot be disabled by `DI`. Fixed vector address. Saves previous IFF1 state.
|-
| Interrupt in Mode 0 || 13+ (Typically 13 for RST) || M1 (IntAck + 2wait), Int(1), plus cycles for fetched instruction (e.g., MW, MW for RST) || Fetches instruction from Data Bus during acknowledge cycle; Executes fetched instruction (usually `RST nn`) || 8080 compatible mode. Relies on interrupting peripheral to supply an instruction byte (typically `RST`). Cycle count depends on the instruction supplied (13T is for a 1-byte `RST`).
|-
| Interrupt in Mode 1 || 13 (7, 3, 3) || M1 (IntAck + 2wait), Int(1), MW (Push PCH), MW (Push PCL) || iff1 := 0, sp -= 2, (sp) := pc, pc := 0038h || Simple mode, always jumps to fixed address `0038h`. No data needed from peripheral during acknowledge.
|-
| Interrupt in Mode 2 || 19 (7, 3, 3, 3, 3) || M1 (IntAck + 2wait), Int(1), MW (Push PCH), MW (Push PCL), MR (Read Vector Low), MR (Read Vector High) || iff1 := 0, sp -= 2, (sp) := pc, pc := '''('''(I << 8) + V''')''' || Most flexible mode. Forms pointer `(I * 256) + V` where `V` is vector byte from peripheral (LSB ignored). Reads 16-bit target address from pointer address. `I` register must be set up beforehand.
|}
* At the end of an NMI service routine, the earliest moment a maskable interrupt will be triggered is at the end of the instruction following RETN. [https://spectrumcomputing.co.uk/forums/viewtopic.php?t=7086 Source]
* RST instructions are just a CALL instruction to a fixed address baked in the instruction itself.
* JP cc,nn instruction consistently takes 10 T-states, no matter if the jump is taken or not.
* Unlike the conditional JP, CALL, RET instructions which have access to all conditions, JR is limited to NZ, Z, NC, C conditions.
* Despite what the syntax of the instructions JP (HL/IX/IY) suggests, PC will be loaded with the contents of the register itself, not the indexed value. Those instructions should be understood as JP HL/IX/IY.