Z80 Microprocessor Undocumented Instructions ============================================ File: DOCS.Comp.Z80.UnDocOps - Update: 0.12 Author: J.G.Harston - Date: 15-10-1997 The Z80 processor is quite straightforward, and contains no major bugs or quirks. However, it has some undocumented features. Some of these are quite useful, and some are not, but many programs use the useful ones, and a few programs use the weird ones. Most Z80 opcodes are one byte long, not counting a possible byte or word operand. The four opcodes CB, DD, ED and FD are 'shift' opcodes: they change the meaning of the opcode following them. CB Block Instructions --------------------- There are 248 different CB opcodes. The block CB 30 to CB 37 is missing from the official list. These instructions, usually denoted by the mnemonic SLS, Shift Left and Set, shift left the operand and make bit 0 always one, bit 7 falling out into the carry. These instructions are quite commonly used. Index Instructions ------------------ The DD and FD opcodes precede instructions using the IX and IY registers. If you look at the instructions carefully, you see how they work: 2A nn LD HL,(nn) DD 2A nn LD IX,(nn) 7E LD A,(HL) DD 7E d LD A,(IX+d) A DD/FD opcode simply changes the meaning of HL in the next instruction. If a memory byte is addressed indirectly via HL, as in the second example, a displacement byte is added. Otherwise the instruction simply acts on IX/IY instead of HL. (A notational awkwardness, that will only bother assembler and disassembler writers: JP (HL) is not indirect; think of it as JP (x) where x is HL rather than JP x where x is (HL).) If a DD/FD opcode precedes an instruction that doesn't use the HL register pair at all, the instruction is executed as usual. However, if the instruction uses the H or L register, it will now use the high or low halves of the IX/IY register! Example: 44 LD B,H FD 44 LD B,IYH These types of unofficial instructions are used in many programs. By the way, many DD or FD opcodes after each other will effectively be NOPs, doing nothing except repeatedly setting the flag 'treat HL as IX' (or IY) and taking up 4 T states. Note that the FD or DD 'opcode' is treated as part of an instruction, so that the Z80 cannot be interrupted during execution of such a block. When (parts of) HL are used both as source and target, the instruction always uses the offset index instead of (HL), ie: 66 LD H,(HL) DD 66 LD H,(IX+nn) Two instructions do not obey the DD/FD rule. They are EX DE,HL and EXX. These instructions operate by toggling a flag that changes the reference to the registers; no data is actually being moved, which explains why they cannot operate on IX or IY. Indexed ED Instructions ----------------------- If a DD or FD precedes an ED instruction, it is ignored. ED instructions never operate on the IX or IY register. Indexed CB Instructions ----------------------- If a DD or FD precedes a CB instructions that uses (HL), it is modified to use (IX+nn) or (IY+nn), as with the following: CB CE SET 0,(HL) DD CB nn CE SET 0,(IX+nn) If the CB instruction does not use (HL) the result is more interesting. The indexed byte is always operated on, but then the result is copied to the unindexed register. For example: CB C0 SET 0,B DD CB nn C0 SET 0,(IX+nn) ; then copy result to B CB 05 RLC L DD CB nn 05 RLC (IX+nn) ; then copy result to L ED Block Instructions --------------------- There are a number of unofficial ED instructions, but none of them are very useful. The ED opcodes in the range 00-3F and 80-FF (except for the block instructions of course) do nothing at all but taking up 8 T states and incrementing the R register by 2. Most of the unlisted opcodes in the range 40-7F do have an effect, however, due to the opcode not being fully decoded. These are the extra instructions: ED 4C NEG ED 70 IN F,(C) ED 4E IM 0 ED 71 OUT (C),0 ED 74 NEG ED 54 NEG ED 75 RET ; RETI ED 55 RET ; RETI ED 76 IM 1 ED 5C NEG ED 77 NOP ED 5D RETN ED 7C NEG ED 7D RETN ED 64 NEG ED 7E IM 2 ED 65 RET ; RETI ED 7F NOP ED 66 IM 0 ED 6C NEG ED 6D RETN ED 6E IM 0 The ED 70 instruction reads from port (C), just like the other instructions, but the data doesn't get stored anywhere. It does change the flags in the same way as the other IN instructions, however. The ED 71 instruction OUTs a zero byte to port (C). These instructions 'should', by regularity of the instruction set, use (HL) as operand, but since from the processor's point of view accessing memory or accessing I/O devices is the same thing except for activation of the /IORQ line instead of the /MREQ line, and since the Z80 does not access memory twice in one instruction (disregarding instruction fetch of course) it can't fetch or store the data byte. The ED 4E instruction is a mirror of the ED 46 IM 0 instruction. All the IM instructons in ED 4x are mirrored in ED 6x The RETI instruction is functionally exactly equivalent to the RET instruction. It is used only to signify the end of an interrupt routine to an external hardware device, the Z80 PIO and SIO recognise the instruction bytes being executed. The reflections of RETI therefore are just RETs as hardware will not recognise them as RETIs. The RETN however is different from RET in that it resets IFF1 to the current value of IFF2. IFF1 and IFF2 are usually equal (and become equal after DI and EI and after a maskable interrupt has been accepted). They're different only if an NMI occurs when interrupts are enabled; then IFF1 is off, and IFF2, holding the previous state of the interrupt flip flop, is on, signifying that interrupts were enabled before the non-maskable interrupt. The state of IFF2 can be read by using LD A,R and LD A,I. R Register ---------- This is not really an undocumented feature, although precise explanations are hard to find. The R register is a counter that is updated every instruction, where DD, FD, ED and CB are to be regarded as separate instructions. So shifted instructions will increase R by two. There's an exception: doubly-shifted opcodes, the DDCB and FDCB ones, increase R by two also. The highest bit of R is never changed other than by LD R,A. This means that R either increments from 0 to 127 and back or 128 to 255 and back. This is because in the old days everyone used 16 Kbit chips. Inside the chip the bits were arranged in a 128x128 matrix, and needed a 7 bit refresh cycle. Probably for this reason Zilog decided to count only the lowest 7 bits. The sequence LD R,A then LD A,R results in A being incremented by 2. Block Instructions ------------------ When repeating block instructions are executed the opcode is executed, BC or B is decremented and if it is not zero, PC is decremented by 2 and the instruction refetched. This means that the repeating instructions increment R by 2 times BC or 2 times B. This also means that if you do a block copy that overwrites the instruction, it will terminate prematurely. Take as an example: ORG 32768 L1 LD HL,L1 LD DE,L1+1 LD BC,65535 LD (HL),0 LDIR This segment of code only executes the LDIR 11 times, at which point the ED part of the LDIR instruction is overwritten. The instructions there are now 00 B0 - NOP and OR B. Undocumented Flags ------------------ Bit 3 and 5 of the F register are not used. They can contain information, as you can readily figure out by using PUSH AF and POP AF. Furthermore, sometimes their values change. The values of bits 7, 5 and 3 follow the values of the corresponding bits of the last 8-bit result of an operation that changed the flags. Bit 7 is the sign flag and so fits correctly. If the instruction operates on a 16 bit word, the 8 bits used are the highest 8 bits of the 16 bit result - that is to be expected since the S flag is extracted from bit 15. For instance, after an ADD A,B bits 7, 5 and 3 bits will be identical to those bits of the A register. With the CP x instruction, the bits are taken from the argument. This means that odd things like the following are possible: BIT 6,(IX+nn) JP P,ArgumentLess128 JP Z,ArgumentLess192 JP NZ,Argument192to255 An amazing piece of code! Some programs even hold return addresses in the AF register for a while! Instructions on Emulators ------------------------- There are various Z80 emulators available and many of them add some extra opcodes in order to communicate with the host they are running on. The following is a brief list I have been able to find out about. J.G.Harston's !Z80Tube Z80 Emulator ----------------------------------- Extra opcodes: ED00 to ED0F ED 00 ED_QUIT - Leaves the emulator ED 01 ED_CLI - Passes string at HL to command line interpreter ED 02 ED_BYTE - Does Osbyte A,L,H ED 03 ED_WORD - Does OSWORD A with parameters as HL ED 04 ED_WRCH - Writes character in A to current output ED 05 ED_RDCH - Wait for a character from current input to A ED 06 ED_FILE - Do an operation on a whole file ED 07 ED_ARGS - Read or write info about an open file ED 08 ED_BGET - Get a byte from an open file ED 09 ED_BPUT - Put a byte to an open file ED 0A ED_GBPB - Read or write multiple bytes ED 0B ED_FIND - Open or close a file ED 0C ED_SYS - Pass a SWI to the host ED 0D ED_MISC - Various miscellaneous functions ED 0E ED_WRITE - Write emulator info ED 0F ED_READ - Read emulator info G.A.Gunter's 'Z80' Spectrum Emulator ------------------------------------ Extra opcodes: EDF8 to EDFF, of which: ED FB ED_Load - Loads a block of code into memory at address HL ED FF ED_Quit - Returns you to DOS immediately. Full Opcode List ---------------- See document DOCS.Comp.Z80.OpList for a full list of all opcodes.