Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Zilog Z80
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Design == {{More citations needed section|date=February 2025}} === Programming model and register set === [[File:Z80 arch.svg|thumb|upright=1.95|An approximate block diagram of the Z80: There is no dedicated adder for offsets or separate incrementer for R, and no need for more than a single 16-bit temporary register WZ (although the incrementer latches are also used as a 16-bit temporary register, in other contexts). It is the PC and IR registers that are placed in a separate group, with a detachable bus segment, to allow updates of these registers in parallel with the main register bank.<ref>{{Cite web |last=Shiriff |first=Ken |title=Down to the silicon: how the Z80's registers are implemented |url=https://www.righto.com/2014/10/how-z80s-registers-are-implemented-down.html |url-status=live |archive-url=https://web.archive.org/web/20231105135940/http://www.righto.com/2014/10/how-z80s-registers-are-implemented-down.html |archive-date=November 5, 2023}}</ref>]] The programming model and register set of the Z80 are fairly conventional, ultimately based on the register structure of the [[Datapoint 2200]]. The Z80 was designed as an extension of the Intel 8080, created by the same engineers, which in turn was an extension of the [[Intel 8008|8008]]. The 8008 was basically a [[PMOS logic|PMOS]] implementation of the TTL-based CPU of the Datapoint 2200.{{efn|The related [[Intel 8086|8086]] family also inherited this register design.}} The 2200 design allowed 8-bit registers H and L (High and Low) to be paired into a 16-bit address register HL.{{efn|This variable HL pointer was actually the only way to access memory (for data) in the Datapoint 2200, and hence also in the Intel 8008. No direct addresses could be used to access data.}} In the 8080, this pairing was added to the BC and DE pairs as well, while HL was generalized to allow use as a 16-bit accumulator, not just an address register. The 8080 also introduced immediate 16-bit data for BC, DE, HL, and SP loads. Furthermore, direct 16-bit copying between HL and memory was now possible, using a direct address. The Z80 [[Orthogonal instruction set|orthogonalized]] this further by making all 16-bit register pairs, including IX and IY, more general purpose, as well as allowing 16-bit copying directly to and from memory for all of these pairs. The 16-bit IX and IY registers in the Z80 are primarily intended as base address-registers, where a particular instruction supplies a constant offset that is added to the previous values, but they are also usable as 16-bit accumulators, among other things. A limitation is that all operand references involving IX or IY require an extra instruction prefix byte, adding at least four clock cycles over the timing of an instruction using HL instead; this sometimes makes using IX or IY less efficient than a method using only the 8080-model registers. The Z80 also introduced a new signed [[overflow flag]] and complemented the fairly simple 16-bit arithmetics of the 8080 with dedicated instructions for ''signed'' 16-bit arithmetics.[[File:Z80 pinout.svg|thumb|upright=1.5|The Z80's original [[dual in-line package|DIP40]] chip package pinout]]The 8080-compatible registers AF, BC, DE, HL are duplicated as a separate register file in the Z80,<ref>{{Cite book |title=Kilobaud |date=1977 |publisher=1001001 |page=22}}</ref> where the processor can quickly (in four t-states, the least possible execution time for any Z80 instruction) switch from one bank to the other;<ref>{{Cite book |last=Zaks |first=Rodnay |url=https://archive.org/details/Programming_The_Z80_Third_Edition_Rodnay_Zaks/ |title=Programming the Z80 |date=1982 |publisher=SYBEX |isbn=978-0-89588-069-7 |edition=3rd |page=62}}</ref> a feature useful for speeding up responses to single-level, high-priority interrupts. The dual register-set is useful in the embedded role, as it improves interrupt handling performance, but found widespread use in the personal computer role as an additional set of general registers for complex code like [[floating-point arithmetic]] or home computer games. The duplicate register file is often referred to as the "alternate register set" (by some, the "primed" register file since the apostrophe character is used to denote them in assembler source code and the Zilog documentation). This emphasizes that only one set is addressable at any time. However, the 8-bit accumulator A with its flag register F is bifurcated from the "general purpose" register pairs HL, DE and BC. This is accomplished with two separate instructions used to swap their accessibilities: <code>EX AF,AF'</code> exchanges only register pair AF with AF', while the <code>EXX</code> instruction exchanges the three general purpose register pairs HL, DE and BC with their alternates HL', DE' and BC'. Thus the accumulator A can interact independently with any of the general purpose 8-bit registers in the alternate (or primed) register file, or, if HL' contains a pointer to memory, some byte there (DE' and BC' can also transfer 8-bit data between memory and accumulator A). This can become confusing for programmers because after executing <code>EX AF,AF'</code> or <code>EXX</code>, the contents of the alternate (primed) registers are now in the main registers, and vice versa. The only way for the programmer to understand and track this swapped condition is to trace through the code flow, noting each occurrence of a register swap instruction. Obviously if jump and call instructions are made within these code segments it can quickly become difficult to tell which register file is in context unless carefully commented. Thus it is advisable that exchange instructions be used directly and in short discrete code segments. The Zilog Z280 instruction set includes <code>JAF</code> and <code>JAR</code> instructions which jump to a destination address if the alternate registers are in context (thus officially recognizing this programming complication). ==== Registers ==== {| class="floatright" style="font-size:88%; border: 1px solid #a2a9b1;" |+ '''Zilog Z80 registers''' |- | {| style="font-size:88%;" |- | style="width:10px; text-align:center;"| <sup>1</sup><sub>5</sub> | style="width:10px; text-align:center;"| <sup>1</sup><sub>4</sub> | style="width:10px; text-align:center;"| <sup>1</sup><sub>3</sub> | style="width:10px; text-align:center;"| <sup>1</sup><sub>2</sub> | style="width:10px; text-align:center;"| <sup>1</sup><sub>1</sub> | style="width:10px; text-align:center;"| <sup>1</sup><sub>0</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>9</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>8</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>7</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>6</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>5</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>4</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>3</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>2</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>1</sub> | style="width:10px; text-align:center;"| <sup>0</sup><sub>0</sub> | style="width:auto;" | ''(bit position)'' |- |colspan="17" | '''Main registers''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| Accumulator (A) | style="text-align:center;background:#DDD" colspan="8"| Flags (F) | style="background:white; color:black;"| '''AF''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| B | style="text-align:center;" colspan="8"| C | style="background:white; color:black;"| '''BC''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| D | style="text-align:center;" colspan="8"| E | style="background:white; color:black;"| '''DE''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| H | style="text-align:center;" colspan="8"| L | style="background:white; color:black;"| '''HL''' |- |colspan="17" | '''Alternate (shadow) registers''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| Accumulator' (A') | style="text-align:center;background:#DDD" colspan="8"| Flags' (F') | style="background:white; color:black;"| '''AF{{'}}''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| B' | style="text-align:center;" colspan="8"| C' | style="background:white; color:black;"| '''BC{{'}}''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| D' | style="text-align:center;" colspan="8"| E' | style="background:white; color:black;"| '''DE{{'}}''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| H' | style="text-align:center;" colspan="8"| L' | style="background:white; color:black;"| '''HL{{'}}''' |- |colspan="17" | '''Index registers''' |- style="background:silver;color:black" | style="text-align:center;" colspan="16"| Index X | style="background:white; color:black;"| '''IX''' |- style="background:silver;color:black" | style="text-align:center;" colspan="16"| Index Y | style="background:white; color:black;"| '''IY''' |- style="background:silver;color:black" | style="text-align:center;" colspan="16"| Stack Pointer | style="background:white; color:black;"| '''SP''' |- |colspan="17" | '''Other registers''' |- style="background:silver;color:black" | style="text-align:center;" colspan="8"| Interrupt vector | style="text-align:center;" colspan="8"| Refresh counter | style="background:white; color:black;"| '''I/R''' |- |colspan="17" | '''Program counter''' |- style="background:silver;color:black" | style="text-align:center;" colspan="16"| Program Counter | style="background:white; color:black;"| '''PC''' |- |colspan="17" | '''Status register''' |- style="background:silver;color:black" | style="background:white; color:black;" colspan="8"| <!--NEED TO ADD INTERRUPT STATUS/MODE BITS--> | style="text-align:center;"| [[Sign flag|S]] | style="text-align:center;"| [[Zero flag|Z]] | style="text-align:center;"| - | style="text-align:center;"| [[Adjust flag|H]] | style="text-align:center;"| - | style="text-align:center;"| [[Parity flag|P]]/[[Overflow flag|V]] | style="text-align:center;"| N | style="text-align:center;"| [[Carry flag|C]] | style="background:white; color:black" | '''F'''lags |} |} As on the 8080, 8-bit registers are typically paired to provide 16-bit versions. The 8080 compatible registers<ref name="Heath 2003">{{Cite book |last=Heath |first=Steve |url=https://archive.org/details/embeddedsystemsd0000heat |title=Embedded systems design |date=2003 |publisher=Newnes |isbn=978-0-7506-5546-0 |location=Oxford |page=21 |url-access=registration}}</ref> are: * <code>AF</code>: 8-bit [[Accumulator (computing)|accumulator]] (A) and flag bits (F) carry, zero, minus, parity/overflow, half-carry (used for [[Binary-coded decimal|BCD]]), and an Add/Subtract flag (usually called N) also for BCD * <code>BC</code>: 16-bit data/address register or two 8-bit registers * <code>DE</code>: 16-bit data/address register or two 8-bit registers * <code>HL</code>: 16-bit accumulator/address register or two 8-bit registers * <code>SP</code>: [[stack pointer]], 16 bits * <code>PC</code>: program counter, 16 bits The new registers introduced with the Z80 are: * <code>IX</code>: 16-bit index or base register for 8-bit immediate offsets * <code>IY</code>: 16-bit index or base register for 8-bit immediate offsets * <code>I</code>: interrupt vector base register, 8 bits * <code>R</code>: DRAM refresh counter, 8 bits ([[Most significant bit|msb]] does not count) * <code>AF'</code>: alternate (or shadow) accumulator and flags (''toggled in and out with EX AF,AF' '') * <code>BC'</code>, <code>DE'</code> and <code>HL'</code>: alternate (or shadow) registers (''toggled in and out with EXX'') * Four bits of interrupt status and interrupt mode status The ''refresh register'', <code>R</code>, increments each time the CPU fetches an opcode (or an opcode prefix, which internally executes like a 1-byte instruction) and has no simple relationship with program execution. This has sometimes been used to generate [[pseudorandom]] numbers in games, and also in software protection schemes.{{Citation needed|date=February 2012}} It has also been employed as a "hardware" counter in some designs; an example of this is the [[ZX81]], which lets it keep track of character positions on the TV screen by triggering an interrupt at [[integer overflow|wrap around]] (by connecting INT to A6). The ''interrupt vector register'', <code>I</code>, is used for the Z80 specific mode 2 interrupts (selected by the <code>IM 2</code> instruction). It supplies the high byte of the base address for a 128-entry table of [[interrupt service routine|service routine]] addresses which are selected via an index sent to the CPU during an [[interrupt]] acknowledge cycle; this index is simply the low byte part of the pointer to the tabulated indirect address pointing to the service routine.<ref name="Wai-Kai 2002" /> The pointer identifies a particular peripheral chip or peripheral function or event, where the chips are normally connected in a so-called [[Daisy chain (electrical engineering)|daisy chain]] for priority resolution. Like the refresh register, this register has also sometimes been used creatively; in interrupt modes 0 and 1 (or in a system not using interrupts) it can be used as simply another 8-bit data register. The instructions <code>LD A,R</code> and <code>LD A,I</code> affect the Z80 flags register, unlike all the other <code>LD</code> (load) instructions. The Sign (bit 7) and Zero (bit 6) flags are set according to the data loaded from the Refresh or Interrupt source registers. For both instructions, the Parity/Overflow flag (bit 2) is set according to the current state of the IFF2 flip-flop.<ref>{{Cite web |last=Rison |first=Mark |editor-last=Young |editor-first=Sean |title=Z80 Flag Affection |url=http://www.z80.info/z80sflag.htm |url-status=live |archive-url=https://web.archive.org/web/20231223185036/http://z80.info/z80sflag.htm |archive-date=December 23, 2023 |access-date=June 14, 2016 |website=z80.info |publisher=Thomas Scherrer}}</ref> ==== Microarchitecture ==== Although the Z80 is generally considered an eight-bit CPU, it has a four-bit [[Arithmetic logic unit|ALU]], so calculations are done in two steps.<ref>{{Cite web |last=Shirriff |first=Ken |title=The Z-80 has a 4-bit ALU. Here's how it works. |url=http://www.righto.com/2013/09/the-z-80-has-4-bit-alu-heres-how-it.html |archive-url=https://web.archive.org/web/20130909224112/http://www.righto.com/2013/09/the-z-80-has-4-bit-alu-heres-how-it.html |archive-date=September 9, 2013 |access-date=November 16, 2021}}</ref> === Z80 assembly language === ==== Datapoint 2200 and Intel 8008 ==== The first Intel 8008 [[assembly language]] was based on a simple (but systematic) syntax inherited from the Datapoint 2200 design. This original syntax was later transformed into a new, somewhat more traditional, assembly language form for this same original 8008 chip. At about the same time, the new assembly language was also extended to accommodate the additional addressing modes in the more advanced Intel 8080 chip (the 8008 and 8080 shared a language subset without being [[binary-code compatibility|binary compatible]]; however, the 8008 was binary compatible with the Datapoint 2200). In this process, the mnemonic <code>L</code>, for ''LOAD'', was replaced by various abbreviations of the words ''LOAD'', ''STORE'' and ''MOVE'', intermixed with other symbolic letters. The mnemonic letter <code>M</code>, for ''memory'' (referenced by HL), was lifted out from within the instruction mnemonic to become a syntactically freestanding ''operand'', while registers and combinations of registers became inconsistently denoted; either by abbreviated operands (MVI D, LXI H and so on), within the instruction mnemonic itself (LDA, LHLD and so on), or both at the same time (LDAX B, STAX D and so on). {| class="wikitable" |- ! Intel 8008<br />Datapoint 2200 ! Intel 8080<br />Intel 8085 ! Zilog Z80 ! Intel 8086/<br />Intel 8088 |- ! <small>before ca. 1973</small> ! <small>ca. 1974</small> ! <small>1976</small> ! <small>1978</small> |- | <syntaxhighlight lang="nasm" inline>LBC</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV B,C</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD B,C</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV CH,CL</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LDAX B</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD A,(BC)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>LAM</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV A,M</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD A,(HL)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV AL,[BX]</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>LBM</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV B,M</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD B,(HL)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV CH,[BX]</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>STAX D</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (DE),A</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>LMA</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV M,A</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (HL),A</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV [BX],AL</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>LMC</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV M,C</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (HL),C</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV [BX],CL</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>LDI 56</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MVI D,56</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD D,56</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV DL,56</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>LMI 56</syntaxhighlight>{{efn|Load memory immediate not available on Datapoint 2200.}} | <syntaxhighlight lang="nasm" inline>MVI M,56</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (HL),56</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV byte ptr [BX],56</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LDA 1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD A,(1234)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV AL,[1234]</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>STA 1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (1234),A</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV [1234],AL</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD B,(IX+56)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV CH,[SI+56]</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (IX+56),C</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV [SI+56],CL</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (IY+56),78</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV byte ptr [DI+56],78</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LXI B,1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD BC,1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV CX,1234</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LXI H,1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD HL,1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV BX,1234</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>SHLD 1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD (1234),HL</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV [1234],BX</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LHLD 1234</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD HL,(1234)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV BX,[1234]</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD BC,(1234)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV CX,[1234]</syntaxhighlight> |- | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>--</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>LD IX,(1234)</syntaxhighlight> | <syntaxhighlight lang="nasm" inline>MOV SI,[1234]</syntaxhighlight> |}''Illustration of four syntaxes, using samples of equivalent, or (for 8086) very similar, load and store instructions.<ref name="Durda 2012">{{Cite web |last=Durda IV |first=Frank |date=2012 |title=8080/Z80 Instruction Set |url=http://nemesis.lonestar.org/computers/tandy/software/apps/m4/qd/opcodes.html |url-status=dead |archive-url=https://web.archive.org/web/20160211094642/http://nemesis.lonestar.org/computers/tandy/software/apps/m4/qd/opcodes.html |archive-date=February 11, 2016 |access-date=July 22, 2009}}</ref> The Z80 syntax uses parentheses around an expression to indicate that the value should be used as a memory address (as mentioned below), while the 8086 syntax uses brackets instead of ordinary parentheses for this purpose. Both Z80 and 8086 use the + sign to indicate that a constant is added to a base register to form an address. Note that the 8086 is not a complete superset of the Z80. BX is the only 8086 register pair that can be used as a pointer.'' ==== New syntax ==== Because Intel claimed a copyright on their assembly mnemonics,<ref>{{Cite book |title=Intel Component Data Catalog 1978 |date=1978 |publisher=Intel Corporation |location=Santa Clara, CA |pages=11–17 |chapter=8080A/ 8-Bit N-Channel Microprocessor |quote=All mnemonics copyright Intel Corporation 1977}}</ref> a new assembly syntax had to be developed for the Z80. This time a more systematic approach was used: * All registers and register pairs are explicitly denoted by their full names * Parentheses are consistently used to indicate "memory contents at" (constant address or variable pointer dereferencing) with the exception the jump instructions <code>JP (HL)</code>, <code>JP (IX)</code>, and <code>JP (IY)</code>. These load the new PC address from the respective register directly, without indirecting through memory.{{efn|Jump (<code>JP</code>) instructions, which load the program counter with a new instruction address, do not themselves access memory. Absolute and relative forms of the jump reflect this by omitting the round brackets from their operands. Register based jump instructions such as "<code>JP (HL)</code>" include round brackets in an apparent deviation from this convention.<ref>{{Cite web |title=Z80 Relocating Macro Assembler User's Guide |url=http://z80cpu.eu/mirrors/oldcomputers.dyndns.org/manuals/z80asm.pdf |url-status=dead |archive-url=https://web.archive.org/web/20110720173724/http://z80cpu.eu/mirrors/oldcomputers.dyndns.org/manuals/z80asm.pdf |archive-date=July 20, 2011 |access-date=June 4, 2009 |page=B–2}}</ref>}} * All load and store instructions use the same mnemonic name, LD, for LOAD (a return to the simplistic Datapoint 2200 vocabulary); other common instructions, such as ADD and INC, use the same mnemonic regardless of addressing mode or operand size. This is possible because the operands themselves carry enough information. These principles made it straightforward to find names and forms for all new Z80 instructions, as well as [[Orthogonality (programming)|orthogonalizations]] of old ones, such as <code>LD BC,1234</code>. Apart from naming differences, and despite a certain discrepancy in basic register structure, the Z80 and [[Intel 8086|8086]] syntax are virtually [[isomorphic]] for a large portion of instructions. Only quite superficial similarities (such as the word MOV, or the letter X, for extended register) exist between the 8080 and 8086 assembly languages, although 8080 programs can be translated to 8086 assembly language by [[Assembly language translator|translator programs]].<ref name="Scanlon 1988" /><ref name="Nelson 1989" /> === Instruction set and encoding === The Z80 uses 252 out of the available 256 codes as single byte opcodes ("root instruction" most of which are inherited from the 8080); the four remaining codes are used extensively as [[opcode prefix]]es:<ref name="Zilog 1995">{{Cite web |year=1995 |title=Z80 CPU Introduction |url=http://www.z80.info/z80brief.htm |url-status=live |archive-url=https://web.archive.org/web/20231220144519/http://www.z80.info/z80brief.htm |archive-date=December 20, 2023 |publisher=[[Zilog]] |quote=It has a language of 252 root instructions and with the reserved 4 bytes as prefixes, accesses an additional 308 instructions.}}</ref> CB and ED enable extra instructions, and DD or FD select IX+d or IY+d respectively (in some cases without displacement d) 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<ref name="Zilog 1995" /> (allowing operation of all 8080 programs on a Z80). The Zilog documentation<ref>{{Cite web |year=1976 |title=Z80-CPU Instruction Set |url=https://usermanual.wiki/Document/ZilogZ80CPUTechnicalManual.2406416115/view#23 |url-status=live |archive-url=https://web.archive.org/web/20231105184525/https://usermanual.wiki/Document/ZilogZ80CPUTechnicalManual.2406416115/view#23 |archive-date=November 5, 2023 |access-date=July 20, 2021 |publisher=[[Zilog]] |page=19 |type=PDF}}</ref> further groups instructions into the following categories (most from the 8080, others entirely new like the block and bit instructions, and others 8080 instructions with more versatile addressing modes, like the 16-bit loads, I/O, rotates/shifts and relative jumps): * Load and exchange * Block transfer and search * Arithmetic and logical * Rotate and shift * Bit manipulation (set, reset, test) * Jump, call and return * Input/output * Basic CPU control No explicit multiply instructions are available in the original Z80,<ref>{{Cite book |last1=Sanchez |first1=Julio |title=Software Solutions for Engineers And Scientists |last2=Canton |first2=Maria P. |date=2008 |publisher=Taylor & Francis |isbn=978-1-4200-4302-0 |page=65 |quote=The 8-bit microprocessors that preceded the 80x86 family (such as the Intel 8080, the Zilog Z80, and the Motorola) did not include multiplication.}}</ref> though registers A and HL can be multiplied by powers of two with ADD A,A and ADD HL,HL instructions (similarly IX and IY also). Shift instructions can also multiply or divide by powers of two. Different sizes and variants of additions, shifts, and rotates have somewhat differing effects on flags because most of the flag-changing properties of the 8080 were copied. However, the parity flag bit P of the 8080 (bit 2) is called P/V (parity/overflow) in the Z80 as it serves the additional purpose of a twos complement overflow indicator, a feature lacking in the 8080. Arithmetic instructions on the Z80 set it to indicate overflow rather than parity, while bitwise instructions still use it as a parity flag. (This introduces a subtle incompatibility of the Z80 with code written for the 8080, as the Z80 sometimes indicates signed overflow where the 8080 would indicate parity, possibly causing the logic of some practical 8080 software to fail on the Z80.{{efn|For example, on the 8080, a programmer might test the parity of a byte by {{code|ADD}}ing zero to it, by {{code|SUB}}tracting zero from it, or by {{code|OR}}ing or {{code|XOR}}ing it with zero; all of these are single-instruction operations of the same speed and size, on both the 8080 and the Z80. If the programmer happened to choose to test parity by {{code|OR}}ing or {{code|XOR}}ing with zero, then the Z80 will execute the program correctly, but if the programmer chose to test parity by {{code|ADD}}ing or {{code|SUB}}tracting zero, then the Z80 will always reset the P/V flag to zero (since adding or subtracting zero never causes an overflow or underflow) instead of assigning P to correctly indicate the parity of the byte (as the 8080—or 8085—would), and the program may fail. Nothing in the Intel programming manuals or other documentation for the 8080 discouraged use of arithmetic instructions, or prescribed using logical instructions, to test parity, so there is no reason that an 8080 programmer exercising recommended good programming practice should be expected to have chosen one of the ways that will work on the Z80 over one of the ways that will not work.}}) This new overflow flag is used for all new Z80-specific 16-bit operations ({{code|ADC}}, {{code|SBC}}) as well as for 8-bit arithmetic operations, while the 16-bit operations inherited from the 8080 ({{code|ADD}}, {{code|INC}}, {{code|DEC}}) do not affect it. Also, bit 1 of the flags register (a spare bit on the 8080) is used as a flag N that indicates whether the last arithmetic instruction executed was a subtraction or addition. The Z80 version of the {{code|DAA}} instruction (decimal adjust accumulator for BCD arithmetic) checks the N flag and behaves accordingly, so a (hypothetical) subtraction followed later by {{code|DAA}} will yield a different result on an old 8080 than on the Z80. However, this would likely be erroneous code on the 8080, as {{code|DAA}} was defined for addition only on that processor. The Z80 has six new {{code|LD}} instructions that can load the DE, BC, and SP register pairs from memory, and load memory from these three register pairs—unlike the 8080.<ref name="Durda 2012" /> As on the 8080, load instructions do not affect the flags (except for the special-purpose I and R register loads). A result of a regular encoding (common with the 8080) is that each of the 8-bit registers can be loaded from themselves (e.g. {{code|LD A,A}}). This is effectively a {{code|NOP}}. New block transfer instructions can move up to 64 kilobytes from memory to memory or between memory and I/O peripheral ports. Block instructions {{code|LDIR}} and {{code|LDDR}} ('''l'''oa'''d''', '''i'''ncrement/'''d'''ecrement, '''r'''epeat) use HL to point to the source address, DE to the destination address, and BC as a byte counter. Bytes are copied from source to destination, the pointers are incremented or decremented, and the byte counter is decremented until BC reaches zero. Non-repeating versions {{code|LDI}} and {{code|LDD}} move a single byte and bump the pointers and byte counter, which if it becomes zero resets the P/V flag. Corresponding memory-to-I/O instructions {{code|INIR}}, {{code|INDR}}, {{code|OTIR}}, {{code|OTDR}}, {{code|INI}}, {{code|IND}}, {{code|OUTI}} and {{code|OUTD}} operate similarly, except that B, not BC, is used as the byte counter.{{sfnp|Ciarcia|1981|p=86}}<ref>{{Cite book |last=HAYES |first=JOHN P. |title=Computer Architecture and Organization |year=1978 |isbn=0-07-027363-4 |page=423}}</ref> The Z80 can input and output any register to an I/O port using register C to designate the port. (The 8080 only performs I/O through the accumulator A, using a direct port address specified in the instruction; a self-modifying code technique is required to use a variable 8080 port address.) The last group of block instructions perform a {{code|CP}} compare operation between the byte at (HL) and the accumulator A. Register pair DE is not used. The repeating versions {{code|CPIR}} and {{code|CPDR}} only terminate if BC goes to zero or a match is found. HL is left pointing to the byte after ({{code|CPIR}}) or before ({{code|CPDR}}) the matching byte. If no match is found, the Z flag is reset. There are non-repeating versions {{code|CPI}} and {{code|CPD}}. Unlike the 8080, the Z80 can jump to a relative address ({{code|JR}} instead of {{code|JP}}) using a shorter instruction with a signed 8-bit displacement. There are unconditional and conditional forms of this instruction. Only the zero and carry conditions can be tested. (All 8080 jumps and calls, conditional or not, are three-byte instructions.) If jump is taken, the two-byte {{code|JR}} instructions are slower than the 8080-style three-byte {{code|JP}} instructions; if not taken, {{code|JR}} instructions are quicker. A two-byte instruction specialized for program looping is also new to the Z80: {{code|DJNZ}} ('''d'''ecrement '''j'''ump if '''n'''on-'''z'''ero) takes a signed 8-bit displacement as an operand. The B register is decremented, and if the result is nonzero, then program execution jumps relative to PC; the flags remain unaltered. To perform an equivalent loop on an 8080 requires separate {{code|DEC}} and conditional jump (to a two-byte absolute address) instructions (totalling four bytes), and the {{code|DEC}} alters the flag register. The index register (IX/IY, often abbreviated XY) instructions can be useful for accessing data organised in fixed heterogenous structures (such as [[record (computer science)|records]]) or at fixed offsets relative a variable base address (as in [[recursive]] [[stack frame]]s) and can also reduce code size by removing the need for multiple short instructions using non-indexed registers. However, although they may save speed in some contexts when compared to long/complex "equivalent" sequences of simpler operations, they incur a lot of additional CPU time (e.g., 19 T-states to access one indexed memory location vs. as little as 11 to access the same memory using HL and {{code|INC}} to point to the next). Thus, for simple or linear accesses of data, use of IX and IY tend to be slower and occupy more memory. Still, they may be useful in cases where the "main" registers are all occupied, by removing the need to save/restore registers. Their officially undocumented 8-bit halves (see below) can be especially useful in this context, for they incur less slowdown than their 16-bit parents. Similarly, instructions for 16-bit additions are not particularly fast (11 clocks) in the original Z80 (being 1 clock slower than in the 8080/8085); nonetheless, they are about twice as fast as performing the same calculations using 8-bit operations, and equally important, they reduce register usage. It was not uncommon for programmers to "poke" different offset displacement bytes (which were typically calculated dynamically) into indexed instructions; this is an example of [[self-modifying code]], which was regular practice on nearly all early 8-bit processors with non-[[Instruction pipelining#Special situations|pipelined]] execution units. The index registers have a parallel instruction to {{code|JP (HL)}}, which is {{code|JP (XY)}}. This is often seen in stack-oriented languages like [[Forth (programming language)|Forth]], which at the end of every Forth word (atomic subroutines comprising the language) must jump unconditionally back to their thread interpreter routines. Typically this jump instruction appears hundreds of times in an application, and using {{code|JP (XY)}} rather than {{code|JP THREAD}} saves a byte and two T-states for each occurrence. This naturally makes the index register unavailable for any other use, or else the need to constantly reload it would negate its efficiency. The 10-year-newer microcoded [[Z180]] design could initially afford more "chip area", permitting a slightly more efficient implementation (using a wider [[Arithmetic logic unit|ALU]], among other things); similar things can be said for the [[Zilog Z800|Z800]], [[Z280]], and [[Z380]]. However, it was not until the fully pipelined [[Zilog eZ80|eZ80]] was launched in 2001 that those instructions finally became approximately as cycle-efficient as it is technically possible to make them, i.e. given the Z80 encodings combined with the capability to do an 8-bit read or write every clock cycle.{{Citation needed|date=July 2011}} ==== Undocumented instructions ==== 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,<ref>{{Cite book |last=Froehlich |first=Robert A. |url=https://archive.org/details/freesoftwarecata0000froe/ |title=The free software catalog and directory |date=1984 |publisher=Crown Publishers |isbn=978-0-517-55448-7 |page=133 |quote=Undocumented Z80 codes allow 8 bit operations with IX and IY registers. |url-access=registration}}</ref> in the same fashion as the HL register, which is accessible either as 16 bits or separately as the ''H''igh and ''L''ow registers. The binary opcodes (machine language) were identical, but preceded by a new opcode prefix.<ref name="undocz80">{{Cite web |last=Bot |first=Jacco J. T. |title=Z80 Undocumented Instructions |url=http://www.z80.info/z80undoc.htm |url-status=live |archive-url=https://web.archive.org/web/20231223185034/http://z80.info/z80undoc.htm |archive-date=December 23, 2023 |website=Home of the Z80 CPU |quote=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.}}</ref> 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 H and L registers 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 {{code|(LD H,n)}} will load that 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 {{code|LD H,(IX+d)}} which make use of both the HL and IX or IY registers in the same instruction;<ref name="undocz80" /> in this case the DD prefix is only applied to the (IX+d) portion of the instruction. The halves of the XY registers could also hold operands for 8-bit arithmetic, logical and compare instructions, sparing the regular 8-bit registers for other use. The undocumented ability to increment and decrement the upper half of an index register made it easy to expand the range of the normal indexed instructions, without having to resort to the documented {{code|ADD/SBC XY,DE}} or {{code|ADD/SBC XY,BC}}. There are several other undocumented instructions as well.<ref>Robin Nixon ''The Amstrad Notepad Advanced User Guide'', Robin Nixon, 1993, {{ISBN|1-85058-515-6}}, pages 219–223.</ref> Undocumented or [[illegal opcode]]s are not detected by the Z80 and have various effects, some of which are useful. However, as they are not part of the formal definition of the instruction set, different implementations of the Z80 are not guaranteed (or especially likely) to work the same way for every undocumented opcode. ==== Bugs ==== The {{code|OTDR}} instruction does not conform to the Z80 documentation. Both the {{code|OTDR}} and {{code|OTIR}} instructions are supposed to leave the carry (C) flag unmodified. The {{code|OTIR}} instruction operates correctly; however, during the execution of the {{code|OTDR}} instruction, the carry flag takes the results of a spurious compare between the accumulator (A) and the last output of the {{code|OTDR}} instruction.<ref name="Young 1998" /> === Example code === The following Z80 assembly source code is for a subroutine named <code>memcpy</code> that copies a block of data bytes of a given size from one location to another. Important: the example code does not handle the case where the destination block overlaps the source; a serious limitation, but one that is irrelevant for some applications—such as, especially, when the source is in ROM and the destination in RAM, so they can never overlap. The data block is copied one byte at a time, and the data movement and looping logic utilizes 16-bit operations. It demonstrates a variety of instructions but in practice it would not be coded this way as the Z80 has a single instruction that will replace this entire subroutine: <code>LDIR</code>. The sample code will move one byte every 46 T-states. Substituting the <code>LDIR</code> instruction will move each byte in only 21 T-states. Note that the assembled code is binary-compatible with the Intel 8080 and 8085 CPUs. {| |-valign="top" |<syntaxhighlight lang="text" highlight="16"> 1000 1000 1000 F5 1001 7E 1002 12 1003 23 1004 13 1005 0B 1006 78 1007 B1 1008 C2 01 10 100B F1 100C C9 100D </syntaxhighlight> |<syntaxhighlight lang="tasm" highlight="16"> ; memcpy -- ; Copy a block of memory from one location to another. ; This routine is the equivalent of LDIR ; ; Entry registers ; HL - Address of source data block ; DE - Address of destination data block ; BC - Number of bytes to copy ; ; Return registers ; HL - First byte after source data block ; DE - First byte after destination data block ; BC - Zero ; (LDIR does not fully save AF. H, P/V, and N are reset.) org 1000h ; Origin at 1000h memcpy public push af ; Save AF like LDIR loop ld a,(hl) ; Copy 1 source byte ld (de),a ; to its destination inc hl ; Bump source pointer inc de ; Bump dest pointer dec bc ; Count the copied byte ld a,b ; Test BC for zero or c ; If BC != 0, jp nz,loop ; repeat the loop pop af ; Restore AF ret ; Return end </syntaxhighlight> |} === Instruction execution === Each instruction is executed in steps that are usually termed [[machine cycle]]s (M-cycles), each of which can take between three and six clock periods (T-states).<ref>{{Cite book |url=https://www.zilog.com/docs/z80/um0080.pdf#G5.1130345 |title=Z80 Family CPU User Manual |publisher=[[Zilog]] |year=2016 |page=7 |chapter=Timing |id=UM008011-0816 |access-date=January 5, 2024 |archive-url=https://web.archive.org/web/20231226131929/http://www.zilog.com/docs/z80/um0080.pdf#G5.1130345 |archive-date=December 26, 2023 |url-status=live}}</ref> Each M-cycle corresponds roughly to one memory access or internal operation. Multiple instructions actually end during the M1 of the ''next'' instruction which is known as a ''fetch/execute overlap''. {| class="wikitable" |+ Examples of typical instructions (R=read, W=write) ! Total M-cycles ! T-states ! instruction ! M1 ! M2 ! M3 ! M4 ! M5 ! M6 |- | 1{{sfnp|Ciarcia|1981|p=65}} | 4<ref name="Zilog 2005" /> | <syntaxhighlight lang="nasm" inline>INC B</syntaxhighlight> | opcode | || | || || |- | 2<ref>{{Cite book |last=Zaks |first=Rodnay |url=https://archive.org/details/Programming_The_Z80_Third_Edition_Rodnay_Zaks/ |title=Programming the Z80 |date=1989 |publisher=Sybex |isbn=978-0-89588-069-7 |page=200 |quote=ADD A, n Add accumulator with immediate data n. MEMORY Timing: 2 M cycles; 7 T states. |issue=69}}</ref> | 7 | <syntaxhighlight lang="nasm" inline>ADD A,n</syntaxhighlight> | opcode | n | || | || |- | 3{{sfnp|Ciarcia|1981|p=63}} | 11 | <syntaxhighlight lang="nasm" inline>ADD HL,DE</syntaxhighlight> | opcode | internal | internal | || || |- | 4{{sfnp|Ciarcia|1981|p=77}} | 15 | <syntaxhighlight lang="nasm" inline>SET b,(HL)</syntaxhighlight> | prefix | opcode | R(HL), set | W(HL) | || |- | 5{{sfnp|Ciarcia|1981|p=36}} | 19 | <syntaxhighlight lang="nasm" inline>LD (IX+d),n</syntaxhighlight> | prefix | opcode | d | n,add | W(IX+d) || |- | 6{{sfnp|Ciarcia|1981|p=58}} | 23 | <syntaxhighlight lang="nasm" inline>INC (IY+d)</syntaxhighlight> | prefix | opcode | d | add |R(IY+d),inc | W(IY+d) |} The Z80 machine cycles are sequenced by an internal [[state machine]] which builds each M-cycle out of 3, 4, 5 or 6 T-states depending on context. This avoids cumbersome asynchronous logic and makes the control signals behave consistently at a wide range of clock frequencies. It also means that a higher frequency crystal must be used than without this subdivision of machine cycles (approximately 2–3 times higher). It does not imply tighter requirements on [[memory access time]]s, since a high resolution clock allows more precise control of memory timings and so memory can be active in parallel with the CPU to a greater extent, allowing more efficient use of available memory bandwidth.{{citation needed|date=December 2012}} One central example of this is that, for [[opcode fetch]], the Z80 combines two full clock cycles into a memory access period (the M1-signal). In the Z80 this signal lasts for a relatively larger part of the typical instruction execution time than in a design such as the [[Motorola 6800|6800]], [[MOS Technology 6502|6502]], or similar, where this period would typically last typically 30-40% of a clock cycle.{{citation needed|date=November 2012}} With memory chip affordability (i.e. access times around 450-250 ns in the 1980s{{citation needed|date=November 2012}}) typically determining the fastest possible access time, this meant that such designs were locked to a significantly longer clock cycle (i.e. lower internal clock speed) than the Z80. Memory was generally slow compared to the state machine sub-cycles (clock cycles) used in contemporary microprocessors. The shortest machine cycle that could safely be used in embedded designs has therefore often been limited by memory access times, not by the maximum CPU frequency (especially so during the home computer era). However, this relation has slowly changed during the last decades, particularly regarding [[Static random access memory|SRAM]]; cacheless, single-cycle designs such as the eZ80 have therefore become much more meaningful recently. The content of the refresh register R is sent out on the lower half of the address bus along with a refresh control signal while the CPU is decoding and executing the fetched instruction. During refresh the contents of the Interrupt register I are sent out on the upper half of the address bus.<ref>{{Cite book |url=https://www.zilog.com/docs/z80/um0080.pdf#G5.1012169 |title=Z80 Family CPU User Manual |publisher=[[Zilog]] |year=2016 |page=3 |chapter=Special-Purpose Registers |id=UM008011-0816 |access-date=January 5, 2024 |archive-url=https://web.archive.org/web/20231226131929/http://www.zilog.com/docs/z80/um0080.pdf#G5.1012169 |archive-date=December 26, 2023 |url-status=live}}</ref> === Compatible peripherals === Zilog introduced a number of peripheral parts for the Z80, which all support the Z80's interrupt handling system and I/O address space. These include the counter/timer channel (CTC),<ref>{{Cite web |last=<!--Staff writer(s); no by-line.--> |date=2001 |title=Z80 Family CPU Peripherals User Manual |url=http://datasheet.eeworld.com.cn/pdf/ZILOG/68012_Z80.pdf |url-status=dead |archive-url=https://web.archive.org/web/20140502033449/http://datasheet.eeworld.com.cn/pdf/ZILOG/68012_Z80.pdf |archive-date=May 2, 2014 |access-date=April 30, 2014 |website=EEWORLD Datasheet |publisher=ZiLOG}}</ref> the SIO (serial input/output), the DMA (direct memory access), the PIO (parallel input/output) and the DART (dual asynchronous receiver–transmitter). As the product line developed, low-power, high-speed and [[CMOS]] versions of these chips were introduced. <gallery mode="packed"> File:Basic Measuring Instruments - Math Processor 83002190 - Zilog Z80 PIO Z84C2008PEC-3919.jpg|PIO Z84C2008 File:Basic Measuring Instruments - Math Processor 83002190 - Zilog Z80 CTC Z84C3008PEC-3918.jpg|CTC Z84C3008 File:Basic Measuring Instruments - Math Processor 83002190 - Zilog Z80 SIO Z84C4008PEC-3920.jpg|SIO Z84C4008 </gallery> Like the 8080, 8085 and 8086 processors, but unlike processors such as the Motorola 6800 and MOS Technology 6502, the Z80 and 8080 has a separate control line and address space for I/O instructions. While some Z80-based computers such as the [[Osborne 1]] used "Motorola-style" [[Memory-mapped I/O|memory mapped input/output]] devices, usually the I/O space was used to address one of the Zilog peripheral chips compatible with the Z80. During the timing for an I/O read or an I/O write operation, a single wait cycle is automatically inserted by the Z80.<ref>{{Cite web |title=Sharp 1986 Semiconductor Data Book |url=http://www.bitsavers.org/components/sharp/_dataBooks/1986_Sharp_MOS_Semiconductor_Data_Book.pdf#page=225 |access-date=January 1, 2024 |page=218 |archive-date=January 1, 2024 |archive-url=https://web.archive.org/web/20240101005825/http://www.bitsavers.org/components/sharp/_dataBooks/1986_Sharp_MOS_Semiconductor_Data_Book.pdf#page=225 |url-status=live }}</ref> Zilog I/O chips supported the Z80's new mode 2 interrupts which simplified interrupt handling for large numbers of peripherals. The Z80 was officially described as supporting 16-bit (64 KB) memory addressing, and 8-bit (256 ports) I/O-addressing. All I/O instructions actually assert the entire 16-bit address bus. OUT (C),reg and IN reg,(C) places the contents of the entire 16-bit BC register on the address bus;<ref name="Young 1998">{{Cite web |last=Young |first=Sean |date=October 1998 |title=Z80 Undocumented Features (in software behaviour) |url=http://z80.info/z80undoc3.txt |url-status=live |archive-url=https://web.archive.org/web/20231225235537/http://z80.info/z80undoc3.txt |archive-date=December 25, 2023 |quote=The I/O instructions use the whole of the address bus, not just the lower 8 bits. So in fact, you can have 65536 I/O ports in a Z80 system (the Spectrum uses this). IN r,(C), OUT (C),r and all the I/O block instructions put the whole of BC on the address bus. IN A,(n) and OUT (n),A put A*256+n on the address bus.}}</ref> OUT (n),A and IN A,(n) places the contents of the A register on b8–b15 of the address bus and n on b0–b7 of the address bus. A designer could choose to decode the entire 16-bit address bus on I/O operations in order to take advantage of this feature, or use the high half of the address bus to select subfeatures of the I/O device. This feature has also been used to minimise decoding hardware requirements, such as in the [[Amstrad CPC]]/[[Amstrad PCW|PCW]] and [[ZX81]].
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)