8080/Z80 Processor Data by: Mark Ormston (aka Zolaerla or MeMSO) of NeueTECH Software memso@memso.net Version: 0.1 Date Created: 2006-12-30 Last Modified: 2007-03-07 Please leave this notice in any version of this text file! This document was made for readability in any general ASCII system, with 100 or more characters per line and 2 spaces per tab. I shall endeavor to convert all tabs to spaces before releasing a version of this document, but if I forget, this at least tells you how to correct it. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTICE! Though I attempt to be as accurate as possible, I am limited to what other sources state. Often times these sources disagree with one another and I end up having to pick and choose what sounds "right", even if it may not necessarily be so. I can give no guarantee of any sort that this information is 100% accurate. I just would like to think it is! If there is any information that would make this more complete, please email me above and let me know! Please put "For MeMSO" (capitalize it properly please) in the subject so I know it's not spam (I get up to 200 of those a day!). !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This document describes in full detail exactly how the 8080 and Z80 processors work. This information was gathered so I could program the CPU cores into my emulator. Anybody that knows much of anything about emulators knows that they need to be very exact to properly emulate the systems they are designed for, and it is this exactness I sought when creating this document. Many sources were used, and I have listed as many as I could in an appendix. A .xls file should come with this file. It contains charts of the opcodes/mnemonics in Opcode and Mnemonic sort order, for reference purposes. I have used this chart extensively myself. This document currently covers the following processors: 8080 8085 Z80 What this document *IS*: o Quite Unabridged o A gathering of information from many, many different sources to consolodate information in just a couple files o Useful for details on the inner workings of these CPUs o A place to find psuedo-code for EVERY opcode (often times not optimized for clarity's sake) o Will give all information necessary to both program and to emulate these processors o System independent. The code and descriptions of the CPUs ignore any hardware they are designed for as much as is humanly possible. What this document *IS NOT*: o A teaching guide for using/programming these processors o A guide for creating computers/systems using these processors (unless you just want the CPU details) o System dependent Hexidecimal values on the 8080 processors is done with an H at the end of the value. 10H is 10 hex (16 decimal), for example. Because these processors use this convention, I am using it throughout the documentation. I personally would prefer to use 0xABCD like C/C++ does, but any other 8080/Z80 documentation will also use the ABCDH notation. Throughout this document, I may add an indented section with "* Opinion" to show when I am stating my opinion on something. These may be ignored completely but may point out something that you may not otherwise think about. [x] - I use this to denote sources. For example, if I mention something from "Z80 CPU User Manual", I will simply call it [1]. See Sources at the end of the file for a list of sources. ??? - I put this anywhere where I am making a guess but do not know for certain. These are very frustrating for everyone, to be sure. KERBLUH - This is what I use to tell me that more information is needed. *************************************************************************************************** TABLE OF CONTENTS 1 Description of the 8080 line of processors 1.1 8080 Family 1.2 Z80 Family 2 List of processor registers 2.1 A: Accumulator 2.2 F or PSW: Flags or Program Status Word 2.3 B, C, D, E, H, L: General Purpose Registers 2.4 PC: Program Counter 2.5 SP: Stack Pointer 2.6 IR, ALU, ACT, TMP, W and Z: Temporary Registers 2.7 INTE F/F or IFF1: Interrupt Enable Flip-Flop 2.8 IM: Interrupt Mask (8085 only) 2.9 A', B', C', D', E', F', H', L': Alternate General Registers 2.10 IFF2: Alternate Interrupt Enable Flip-Flip 2.11 IX and IY: Index Registers (Z80 Family only) 2.12 I: Interrupt Page Address Register (Z80 Family only) 2.13 R: Memory Refresh Register (Z80 Family only) 2.14 IM: Interrupt Mode (Z80 Family only) 2.15 OPF: Opcode Flags (Z80 Family only) 2.16 FID: Full Interrupt Disable flag (Z80 Family only) 3 Addressing Modes 3.1 Immediate 3.2 Immediate Extended 3.3 Register 3.4 Implied 3.5 Relative 3.6 Extended 3.7 Register Indirect 3.8 Port 3.9 Restart Vector 3.10 Indexed (Z80 Family only) 3.11 Bit (Z80 Family only) 4 Opcodes/Mnemonics 4.1 How Opcodes are Built 4.2 Invalid Instructions 4.3 Mnemonic Listing Format 4.4 Alphabetic Mnemonic Listing and Full Descriptions 5 Interrupts 6 Pins 7 Quirks and Nuances 7.1 Nuances (Intentional Processor Behavior) 7.2 Quirks/Bugs ___________________________________________________________________________________________________ A1 Miscellaneous Notes and Issues A2 List of computers/game systems that used these processors Probably forever incomplete, but I can try A3 TO DO List A4 Updates List A5 8080 to Z80 mnemonic translations ___________________________________________________________________________________________________ Sources Information Sources ___________________________________________________________________________________________________ In the Spreadsheet: Sheet1 List of all opcodes, sorted by Prefix then Opcode (as best as possible) Sheet2 List of all opcodes, sorted by Mnemonic, then Prefix, then Opcode (as best as possible) Sheet3 Reference values used by Sheet1 and Sheet2 Sheet4 Cycle Exact Operations Status for the 8080 (Taken Verbatum from [6]) *************************************************************************************************** 1 Description of the 8080 line of processors Specifications for this line of processors: Native Depth: 8bit Endianness: Little (LSB first, 0x1234 is stored as 34 12) Addressing: 16bit (64KB) 64KB is directly addressable from the processor Hardware Via: Ports, 256 to 65536 total There are ways to access 65536 ports on the Z80 family, but the connected hardware would have to support it. Interrupts: RESET, Maskable Interrupt, HOLD; some also have NMI 8080: Does not have NMI 8085: Three special levels of interrupts are supported. KERBLUH - more info? Z80 Family: Multiple maskable interrupts are allowed through a daisy chain. Lower priority devices are disabled when a higher priority device's interrupt is being handled. A special RETI mnemonic is provided to remove this limitation and return to the previous priority. Also, three methods of maskable interrupts existed. NMI support exists as well. # of gen regs: 7 A, B, C, D, E, H and L # of spcl regs:8080 Family: 6, Z80 Family: 18 The 8080 family has six special, internal use registers: IR, ALU, ACT, TMP, W and Z. The Z80 family adds a few special purpose registers: IX, IY, I and R, as well as alternates of the seven general registers and the processor flags register. IX and IY are used for indexing purposes. I is used for one of the interrupt methods to control what page (256 byte region) of RAM the interrupt to. R is used for memory refresh. A', B', C', D', E', F', H' and L' effectively double the number of general registers except that they can never be directly used, only swapped with the existing general registers. Stack: Anywhere in memory and as large as memory permits, Pre-decremented The stack pointer is decremented BEFORE pushing and incremented AFTER popping. The current stack pointer is pointing to the next value to be popped. Segmentation: None All directly addressable memory can be access with a single register. Bitwise: 8080 Family: Very Limited, Z80 Family: Fair The 8080 family only had single bit rotation mnemonics and bit testing was done through the AND opcode. See RLA, RLCA, RRA, RRCA and AND opcodes The Z80 family added bit shifting, bit testing and bit setting/resetting opcodes See RL, RLC, RR, RRC, BIT, SET, and RES opcodes Relocatable: None to Minimal 8080 Family had no relocatable support Z80 Family supports simple relocatable code by supporting relative jumps and indexed memory with IX+d and IY+d addressing Note that subroutines are NOT relocatable See JR opcode and IX, IY registers Conditions: Poor Branching if: equal, not equal, above or equal, below, greater or equal, less, positive, negative (BEQ, BNE, BCC, BCS, BVC, BVS, BPL, BMI) Compare and branch if not equal (CBNE) Branch if a bit is set or clear (BBCx, BBSx) Loop Opcodes: None to Minimal 8080 Family: No loop opcodes Decrement and jump if not zero opcode: DJNZ Mult/Div: Minimal A 16bit to 8bit divide (DIV) and a two 8bit to 16bit multiply (MUL) Block Opcodes: None to Decent 8080 Family: No block opcodes The Z80 added support for many block manipulation instructions. These allow: Block Compare (forwards and backwards, testing for Equal only): CPD, CPDR, CPI, CPIR Block port input or output (forwards and backwards): IND, INDR, INI, INIR, OUTD, OTDR, OUTI, OTIR Memory copying (forwards and backwards): LDD, LDDR, LDI, LDIR Floating Point:None BCD Math: BCD adjust instructions The DAA allows BCD adjust after addition. There is no way to do a BCD adjustment for subtraction on the 8080 Family. A special n flag (0 - Addition, 1 - Subtraction) was added to the Z80 so that DAA can subtract instead of add to modify the value if a subtraction was used last. Priviledges: None Pipelining: None Multitasking: No hardware support Mult Proc Supp:None SIMD Support: None NOTE: Something confusing about the documentation of the 8080 and Z80 is it uses the word "cycle" to mean a full internal operation (such as loading a value from memory, doing arithmetic, etc.) and these are called M (machine cycle) whereas a "clock" is a tick in the CPU for an amount of actual time and these are called T (time clock). Other documentation uses the word "state" in place of "clock". Until I find a reason to include M cycles, they will be completely omitted from this documentation. Here is how [6] describes this: "each clock period marks a state; three to five states constitute a machine cycle; and one to five machine cycles comprise an instruction cycle. A full instruction cycle requires anywhere from four to eighteen states for its completion, depending on the kind of instruction involved." ___________________________________________________________________________________________________ 1.1 8080 Family 8080 8080A ??? 8080B ??? 8085 An upgraded 8080 by Intel Added RIM and SIM instructions 8085A ??? ___________________________________________________________________________________________________ 1.2 Z80 Family The Zxxx series of processors were created based on the 8080 processor by Zilog. The Z80 was way more powerful than the 8080 (and Intel's later 8085), and was more popular. The Z180 added true 16bit support and the Z380 added 32bit support. The Z80 redid the mnemonics, almost completely from scratch, for it's processors. Since the Z80s method of mnemonics are more similar to modern processors and because there are so many more mnemonics for the Z80 than the 8080, we are using it's versions of the mnemonics. The Z80 added ??? more instructions, KERBLUH - List of new instructions. The Z80 also added many new addressing methods for existing functions, in particular versions of opcodes that circumvent use of the accumulator. Z80 2.5MHz Z80A 4MHz Z80B 6MHz Z80H 8MHz Z80L Z800 ??? Z8000 ??? Z80000 ??? Z180 (Z80180) Z280 Z380 (Z80380 or Z80382/Z80380C) *************************************************************************************************** 2 List of processor registers ___________________________________________________________________________________________________ 2.1 A: Accumulator 8bit. The accumulator is used for basic arithmetic and logic functions. ___________________________________________________________________________________________________ 2.2 F or PSW: Flags or Program Status Word 8bit. The Flags register holds the current status flags of the processor. These are formatted as: 76543210 sz-h-p-c 8080 Family szyhxpnc Z80 Family Everywhere that the n, y and x flags are referenced, they only apply to the Z80 family of processors. BITS 0 - 01 - c: Carry flag (some documentation calls this CY including the 8080 Family documentation) This bit is mostly used for carrying a bit from one operation to the next. This is especially useful for multi-byte operations. 1 - 02 - 8080 Family: Unused??? Z80 Family: n: Add/Subtract flag The DAA instruction uses this flag to distinguish between ADD and SUB instructions. If n is clear, then it is for an ADD. If it is set, it is for a SUB. 2 - 04 - p/v: Parity/Overflow flag For arithmetic operations this is an overflow flag, designating when the result is greater or less than the maximum or minimum signed value permitted. For logical and rotate instructions, this indicates if parity is odd (p/v = 0) or even (p/v = 1). In search and transfer instructions, p/v is 0 if the counter reaches 0, 1 if it has not. With LD A, I and LD A, R instructions, p/v is set to the value of IFF2. When inputting a device with IN r, (C), p/v is set to the data parity This is just called p in the 8080 Family and is only used for parity. 3 - 08 - 8080 Family: Unused??? Z80 Family: x: Undocumented A copy of bit 3 of the result in some operations. 4 - 10 - h: Half Carry flag (called AC for Auxiliary Carry for the 8080 Family) Set or cleared based on the carry/borrow status between bits 3 and 4 of an 8bit arithmetic operation. This is used by DAA to correct the result of a packed BCD add or subtract. h = 1 if a carry/borrow occurs between bits 3 and 4; h = 0 if a carry/borrow does not occur 5 - 20 - 8080 Family: Unused??? Z80 Family: y: Undocumented A copy of bit 5 of the result in some operations 6 - 40 - z: Zero flag This bit is set when a resulting value is zero or two values are equal. When testing a bit, z is set if the bit is clear, or clear if the bit is set. 7 - 80 - s: Sign flag This bit is set if the most significant bit of a value is set (meaning it's negative) ___________________________________________________________________________________________________ 2.3 B, C, D, E, H, L: General Purpose Registers 8bit. These are the general purpose registers used for most operations on the processor. B and C, D and E, or H and L may be used together to form 16bit values. The BC combination is sometimes called Byte Counter and is sometimes used as a count for loop or repeat instructions. DE is sometimes used as a destination (think DE for DEstination) pointer in loop or repeat instructions. HL is sometimes used as a source pointer in loop or repeat instructions, and often used as an indirect pointer to a value in memory. (HL) is the only register pair that can be used as a direct pointer in memory, though (IX+d) and (IY+d) exist for indexed pointers in the Z80 Family. ___________________________________________________________________________________________________ 2.4 PC: Program Counter 16bit. This register points to the location the program is currently executing at. ___________________________________________________________________________________________________ 2.5 SP: Stack Pointer 16bit. This register points to the top of the stack which may be located anywhere in memory. Values are pushed onto the stack with the PUSH instruction, and removed with the POP instruction. ___________________________________________________________________________________________________ 2.6 IR, ALU, ACT, TMP, W, Z: Temporary Registers 8bit, except ALU which is 9bit. Internally, there are six temporary registers used for data storage, calculating effective addresses, etc. [6] calls these IR (Instruction Register), ALU (Arithmetic Logic Unit data, which is actually 9bit to handle carry/borrow), ACT (ACcumulator Temp), TMP (TeMP), W and Z. IR is used to hold the current opcode or instruction. ALU, ACT and TMP are used for used for temporary place holders while operating on the actual ALU. W and Z are be used for a 16bit value WZ (with W as the high byte). As far as I can tell, ACT/TMP is used when 8bit data needs to be stored temporarily, ALU when a result is calculated but not immediately stored (such as the INC r and DEC r on the 8080), and WZ is used when a whole 16bit value is needed (such as for immediate addressing). In the Excel spread sheet, there is a sheet that shows exactly how each cycle and machine cycle is spent on the 8080 and illustrates how the processor uses these temporary registers. On the 8080, WZ is only used in three cases: To temporarily hold a 16bit value loaded from memory (EX (SP), HL), to temporarily hold a new PC value (from JP, CALL, RET, RST), or to hold a 16bit address read from memory (LD A, (nn), LD (nn), A, LD HL, (nn), LD (nn), HL, IN A, (n), OUT (n), A). Note that the listed opcodes are the ONLY cases where the 8080 uses WZ. WZ is not used when a 16bit address is held in HL or SP. LD A, (HL) for example since HL already holds our address. !!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!! This next part is purely guesswork as nobody has yet been able to fully understand how this functions! I merely took the information from [4] combined with what we know about WZ from [6] and tried to make logical sense out of what happens, but I could be wrong. On the Z80, WZ is used the same way as it was on the 8080. Extending the "hold a 16bit address" idea used on the 8080, WZ is also used in the (IX+d) and (IY+d) operations to hold the resulting 16bit address. However, it also is used in places that the 8080 did not use it, such as for 16bit arithmetic as a temporary value holder. [4] mentions that it seems to have been used by ADD HL, nn even though the 8080 documentation clearly shows that it is not used here. In this case, WZ holds the value of HL BEFORE the add, since ALU at this point could directly store the results into HL. I personally find this a little odd, but if it's true, maybe all 16bit arithmetic does the same thing. ___________________________________________________________________________________________________ 2.7 INTE F/F or IFF1: Interrupt Enable Flip-Flop 1bit. If this value is clear, normal interrupts are not accepted. If it is set, then normal interrupts are accepted. It is set with the EI instruction and cleared with DI. ___________________________________________________________________________________________________ 2.8 IM: Interrupt Mask 8085 Only 3bit. This special "mask" value is used to mask the there special RST lines on the 8085: 5.5, 6.5 and 7.5. It can be set with the SIM instruction and read with the RIM instruction. KERBLUH - More information is necessary ___________________________________________________________________________________________________ 2.9 A', B', C', D', E', F', H', L': Alternate General Registers Z80 Family Only These are all secondary versions of the registers with the same name, sans '. They are usable only by special exchange instructions. EX AF, AF' command switches A and F with A' and F'. EXX switches B, C, D, E, H and L with their respective alternate versions. ___________________________________________________________________________________________________ 2.10 IFF2: Interrupt Enable Flip-Flop Z80 Family Only This secondary IFF is used to store the original value of IFF1 for an NMI. When an NMI occurs, IFF1 becomes 0. When a subsequent RETN instruction occurs (Return from NMI), IFF1 becomes IFF2 returning the processor's interrupt status back to what it was before the NMI. Aside from an NMI, IFF2 will always have the same value as IFF1. EI and DI set/clear both IFF1 and IFF2 simultaneously. ___________________________________________________________________________________________________ 2.11 IX and IY: Index Registers Z80 Family Only 16bit. These registers are used in indexed addressing modes. * Undocumented feature: When specifically accessing the high or low bytes of these registers, an h or an l is appended to the name, giving us IXh, IXl, IYh and IYl. Some documentation instead calls these HX, LX, HY, and LY, but these are less meaningful so I will use the IX* and IY* versions. ___________________________________________________________________________________________________ 2.12 I: Interrupt Page Address Register Z80 Family Only 8bit. Holds the upper eight bits of the indirect address to use for indirect calls to memory when a device throws an interrupt and interrupt mode 2 (IM = 2) is in use. ___________________________________________________________________________________________________ 2.13 R: Memory Refresh Register Z80 Family Only 8bit. This register is used to send pulses to the dynamic memory with changing values to help with memory refresh. Bits 0 - 6 of this value are constantly changed, bit 7 is static unless changed with the LD R, A opcode. This value may be read from or written to using LD R, A or LD A, R. How bits 0 - 6 are affected: Every instruction without a prefix increases it by 1 Instructions with a prefix (CB, DD, ED, FD, DD CB or FD CB) increate it by 2. Superfluous DD or FF prefixes increase it by 1. INT or NMI (interrupts) increase it by 1. ___________________________________________________________________________________________________ 2.14 IM: Interrupt Mode Z80 Family Only 2bit. This controls which of the three interrupt modes is currently in use. This may be 0 to 2. ___________________________________________________________________________________________________ 2.15 OPF: Opcode Flags Z80 Family Only This is not described in ANY other documentation, it is my stab at making a logical explanation of some hidden flags on the Z80. Opcode Flags: 3bit. These flags control what KIND of opcode gets executed next. Using prefixes on the Z80, there are 7 distinct opcode sets, though there really are only 3 and then two optional flags that affect two of those sets (3 + 2 * 2 = 7). The normal, ED and CB opcodes are all fully unique opcode sets that have nothing to do with each other. With 3bits, we have 8 values, so one value is unused. To make this as meaningful as possible, I am going to explain how I imagine all three bits working (meaning I have NO CLUE if I'm anywhere near correct here): OPF BITS 0 - 1 - If this bit is SET, we are using IX register overrides where possible. This is described below. If this bit is CLEAR, we are using normal registers. 1 - 2 - If this bit is SET, we are using IY register overrides where possible. This is described below. If this bit is CLEAR, we are using normal registers. Both this bit and bit 0 cannot be set at the same time. If they are, it has a new meaning. 2 - 4 - If this bit is SET, we are in a new opcode data set. At this point, no more prefixes are accepted because they all map to new opcodes. If this bit is CLEAR, we are using the normal opcode set and new prefixes may be used. Using this, we get the following values: 000 - No prefix: Normal opcode, normal registers 001 - DD prefix: Normal opcode, IX-override registers 010 - FD prefix: Normal opcode, IY-override registers 011 - NOT USED 100 - CB prefix: CB opcodes, normal registers 101 - DD CB prefix: 8bit displacement, DD CB opcodes 110 - FD CB prefix: 8bit displacement, FD CB opcodes 111 - ED prefix: ED opcodes, normal registers After a DD prefix, bits 0-1 are set to 01 After a FD prefix, bits 0-1 are set to 10 After a ED prefix, bits 0-2 become 111 After a CB prefix, bit 2 is set After any other opcode, these flags are cleared (set to 000). ___________________________________________________________________________________________________ 2.16 FID: Full Interrupt Disable flag Z80 Family Only This is not described in ANY other documentation, it is my stab at making a logical explanation of some hidden flags on the Z80. 1bit. This flag is only set by a prefix, it is cleared by all other opcodes. It denies ALL (even NMI???) interrupts on the processor while set. This is to guarantee that an interrupt does not occur between the prefix and the opcode it is affecting. *************************************************************************************************** 3 Addressing Modes ___________________________________________________________________________________________________ 3.1 Immediate eg, LD A, 12H ; Load A with the value of 12H An immediate 8bit value is the value used. ___________________________________________________________________________________________________ 3.2 Immediate Extended eg, LD HL, 1234H ; Load HL with the value of 1234H An immediate 16bit value is the value used. ___________________________________________________________________________________________________ 3.3 Register eg, LD A, B ; Load A from B The opcode is encoded with a register value (or two register values) to use. ___________________________________________________________________________________________________ 3.4 Implied eg, DI ; Disable interrupts The opcode implies what is used without it being specified directly. ___________________________________________________________________________________________________ 3.5 Relative eg, JR 34H ; Jump relative to a location 34H bytes from the next instruction Uses one byte of signed data, giving a range of -128 to 127, which is added to the PC value of the next instruction. ___________________________________________________________________________________________________ 3.6 Extended eg, LD A, (1234H) ; Load A with the value at 1234H Uses a 16bit value which is where an operand is located. ___________________________________________________________________________________________________ 3.7 Register Indirect eg, LD (HL), 12H ; Load the byte at HL in memory with 12H Uses a 16bit CPU register pair (such as HL) as a pointer to a location in memory. ___________________________________________________________________________________________________ 3.8 Port eg, IN A, (12H) ; Inputs a byte from port 12H The (12H) is not a memory address, but instead references one of the 256 hardware ports. ___________________________________________________________________________________________________ 3.9 Restart Vector eg, RST 0 A special CALL instruction, RST (Restart), uses this addressing mode. It can call one of eight different addresses in the beginning of memory where commonly called subroutines are located or jumped to. These addresses are at 00H, 08H, 10H, 18H, 20H, 28H, 30H and 38H. ___________________________________________________________________________________________________ 3.10 Indexed eg, LD (IY+12H), A ; Load the byte at IY+12H with the value in A Z80 Family Only A signed 8bit immediate value (-128 to 127) is used and added to one of the index registers to form a pointer to memory. An overflow wraps around in memory. ___________________________________________________________________________________________________ 3.11 Bit Z80 Family Only While not exactly it's own addressing mode in some regards (it uses Register, Register Indirect or Indexed addressing), it narrows down the actual value addressed to a single bit instead of a full byte value. *************************************************************************************************** 4 Opcodes ___________________________________________________________________________________________________ 4.1 How Opcodes are Built 16bit and higher data is stored Little Endian in memory, like the x86 or 65xx processors but unlike the 68K processors. This means that the value of 1234H is stored in memory as 34 12. On the 8080 Family, each opcode has: Opcode (1 byte) Optional immediate/address (only if there is no two byte prefix) [1 or 2 bytes] + ---------+----------+ | Opcode | Immed. | | |(Optional)| +----------+----------+ 1 byte 1 or 2 bytes (if used) On the Z80, each opcode has: Optional prefixes (CB, DD, ED, FD, DD CB or FD CB) [1 or 2 bytes] Optional displacement (always used if a DD CB or FD CB prefix is used) [1 byte] Opcode [1 byte] Optional displacement (never used by DD CB or FD CB prefix opcodes) [1 byte] Optional immediate/address (only if there is no two byte prefix) [1 or 2 bytes] +----------+----------+ ---------+----------+----------+ | Prefixes | Disp. | Opcode | Disp. | Immed. | |(Optional)|(Optional)| |(Optional)|(Optional)| +----------+----------+----------+----------+----------+ 1 or 2 1 byte 1 byte 1 byte 1 or 2 bytes (if used) (if used) bytes (if used) (if used) --------------------------------------------------------------------------------------------------- 4.1.1 Prefixes There are six prefixes available: CB, DD, ED, FD, DD CB and FD CB. No interrupts can occur between a prefix and the opcode they modify. This INCLUDES any superfluous prefixes (like having DD twice). Superfluous prefixes cost 4 cycles each. Specific prefixes cost different amounts depending on the instruction they modify, what it becomes, etc. See specific instructions for details. CB and ED: These prefixes give the opcode completely new meaning. The CB instructions are all bit-level operations (shifting, rotating, testing, setting). The ED instructions include RETN, RETI, setting Interrupt Modes, special load instructions and port I/O instructions. DD: This prefix is used to replace (HL) with (IX+d), HL with IX, H with the high byte of IX (IXh), and L with the low byte of IX (IXl). Opcodes that do not use H, L, HL or (HL) are the same as if the prefix did not exist. EXX (opcode D8), EX DE, HL (opcode EB), and opcodes that are prefixed with ED are unaffected by the prefix. Note that some documentation notate JP HL (opcode E9) as JP (HL) which is incorrect. When prefixing E9 with DD, you get JP IX *NOT* JP (IX+d). eg, LD H, L will become LD IXh, IXl Note that in opcodes where (HL) (register indirect with HL) is used, (IX+d) will be used with a signed 8bit displacement and any H or L also used in that opcode will not be changed. eg, LD H, (HL) will become LD H, (IX+d) *NOT* LD IXh, (IX+d) If the DD is followed by another DD, or an ED or FD, the first DD is ignored and the second prefix is used instead. This takes four cycles and interrupts cannot occur between the prefixes. If the DD is followed by a CB, then treat this as a DD CB prefix. FD: This prefix is the same as DD, except it uses IY instead of IX. Note that there is no way to use IX and IY in the same instruction. DD CB: When DD is used on a CB instruction, an 8bit displacement ALWAYS follows the prefix, followed by the opcode. If the CB instruction was a BIT instruction, then the BIT instruction responds the same as they would without the DD before it (the displacement is ignored) except for BIT x, (HL), which becomes BIT x, (IX+d). For other instructions, if the original instruction was xxx (HL), it becomes xxx (IX+d) (eg, RES 2, (HL) becomes RES 2, (IX+d)). However, if the original instruction was anything else (not BIT and not using (HL)), then an unusual double-operation occurs. The expected operation occurs on (IX+d) as if it was an (HL) instruction in the first place, BUT the result is then stored in the register specified by the CB instruction. The store in the register occurs even if the memory location at (IX+d) is not writable. For example, RES 2, A becomes LD A, RES 2, (IX+d), which resets bit 2 at (IX+d) then loads that value into A. FD CB: This prefix is the same as DD CB, except it uses IY instead of IX. --------------------------------------------------------------------------------------------------- 4.1.2 Opcode Construction Most opcodes are formed by a common format encoding in the byte itself. Specific sets of bits are separated into different categories for this purpose: Opcode Bits 7 6 5 4 3 2 1 0 | x | y | z | | p |q| | a | | b | x - These two bits (bits 6 and 7) are used to determine the type of operation for the opcode. y - These three bits (bits 3 - 5) are usually used to determine the destination register. When they holds a register, they use the rrr chart below. This can also hold a condition (see the cnd chart), an arithmetic mode (see the alu chart), a rotation/shift operation (see the rot chart), an interrupt mode (see the irm chart), or a bit value z - These three bits (bits 0 - 2) are usually used to determine the source register. When they hold a register value, they use the rrr chart below. p - This is used to determine a special transfer mode, or for a pair of registers (see dd chart) q - a - Used for 2 bit conditions (cc Chart) and for the Block Instructions (bbaa Block Chart) b - Used for Block Instructions (bbaa Block Chart) rrr, rrx and rry Chart (or RRR, RRX or RRY when two of the same set are in use) This occurs for normal 8bit register access. Where rrx and rry are applicable, only 100, 101 and 110 are worthwhile, all other values are duplicates of the rrr version and since rrx and rry require an extra byte (and 4 more clocks) to execute, it is a much less efficient method to access those registers. Val rrr rrx rry 000 B B B 001 C C C 010 D D D 011 E E E 100 H IXh~ IYh~ 101 L IXl~ IYl~ 110* (HL) (IX+d) (IY+d) 111 A A A * 110 [(HL), (IX+d) or (IY+d)] is a special case. It does not always apply (for example, if LD (HL), (HL) were to occur, the result is actually HALT), and it costs more cycles than the register modes. Because of this differing behavior, all opcode listings will show the 110 results separately. ~ These values are only applicable if there is not an (IX+d) or (IY+d) already in the opcode. If (IX+d) or (IY+d) exists elsewhere in the opcode, then these are the same as the normal rrr values (H or L). These values are considered "undocumented" and will be listed individually. bbb Chart This is used for bit manipulation opcodes such as BIT and SET Val Bit Used 000 0 001 1 010 2 011 3 100 4 101 5 110 6 111 7 dd, df, dx, dy Chart This occurs for 16bit double register access. much less efficient method to access those registers. The first register shown is the high byte, the second is the low byte. Val dd df dx dy 00 BC BC BC BC 01 DE DE DE DE 10 HL HL IX IY 11 SP AF SP SP cnd Chart (3bits Conditional) This is used for conditions Val cnd Test 000 NZ !z 001 Z z 010 NC !c 011 C c 100 PO !p 101 PE p 110 P !s 111 M s cc Chart (2bits Conditional) This is used for the JR conditional jumps Val cc Test 00 NZ !z 01 Z z 10 NC !c 11 C c alu Chart This is used to determine specific arithmetic operations Val alu 000 ADD A 001 ADC A 010 SUB A 011 SBC A 100 AND A 101 XOR A 110 OR A 111 CP A rot Chart This is used to determine specific bit rotation/shifting operations Val rot 000 RLC 001 RRC 010 RL 011 RR 100 SLA 101 SRA 110 SL1 111 SRL rst Chart This is used by the RST instruction and determines the address in the zero page where to reset to Val Address 000 00H 001 08H 010 10H 011 18H 100 20H 101 28H 110 30H 111 38H bbaa Block Chart a controls the method: 00=I, 01=D, 10=IR, 11=DR b controls the operation: 00=LD, 01=CP, 10=IN, 11=OUT/OT Index[a,b] b=00 b=01 b=10 b=11 a=00 LDI CPI INI OUTI a=01 LDD CPD IND OUTD a=10 LDIR CPIR INIR OTIR a=11 LDDR CPDR INDR OTDR ___________________________________________________________________________________________________ 4.2 Invalid Instructions According to [2], invalid opcodes take 4 cycles and act just like NOP. Note that if there are any prefixes before the "NOP" that 4 cycles are used per prefix just like normal. VERY IMPORTANT: If an operand or register value is used, it is assumed that it has the same bit depth as the value would on the real CPU being emulated. This means that a 4bit value that is 0x0F, when incremented will become 0x00 NOT 0x10 which is impossible for a 4bit value! ___________________________________________________________________________________________________ 4.3 Mnemonic Listing Format Each opcode has a C-style psuedo code snip, and a textual description of the opcodes. VERY IMPORTANT: If an operand or register value is used, it is assumed that it has the same bit depth as the value would on the real CPU being emulated. This means that a 4bit value that is 0x0F, when incremented will become 0x00 NOT 0x10 which is impossible for a 4bit value! Unless a code section says "Code: [Full Version]", we are assuming that: Before starting the code: The effective address(es) are already calculated PC incremented as necessary If there is an operand read in, it will be in the operand variable If two operands are read in, the first (destination) will be operand1 and the second (source) will be operand2 After the code: If any data is written out (eg, operand1), it will be output/stored/etc. Value/Variable Definitions: A Accumulator AF Accumulator and the Flags as a 16bit value. A is the high byte, F is the low byte. AFalt The AF' alternate of AF. B B register BC B and C registers as a 16bit value. B is the high byte, C is the low byte. BCalt The BC' alternate of BC. C C register c Carry flag D D register DE D and E registers as a 16bit value. D is the high byte, E is the low byte. DEalt The DE' alternate of DE. E E register F Flags h Half-Carry flag H H register HL H and L registers as a 16bit value. H is the high byte, L is the low byte. HLalt The HL' alternate of HL. IX X Index register IXh High byte of the X Index register IXl Low byte of the X Index register IY Y Index register IYh High byte of the Y Index register IYl Low byte of the Y Index register L L register n Last math operation flag p Parry/Overflow flag s Sign flag W W temporary register x Undocumented x flag y Undocumented y flag z Zero flag Z Z temporary register All flag values, if set in the code, become 1 if the value was true or non-zero, 0 if it was false or zero. When used as a value, they only contain 1 (if set) or 0 (if clear). Specials: address The effective address for the opcode CPU The CPU type. This will be one of the CPU types above For example, if we're on a Z80, CPU will hold Z80. We can test for it with (CPU == Z80) This is to show differences in how different CPUs handle opcodes highbit Holds the value of the highest bit of the register's current size operand Holds the current operand. If operand is modified, the opcode updates it in memory (or the register it applies to, if applicable) operand1 The first operand when multiple operands exist in an opcode operand2 The second operand when multiple operands exist in an opcode result The result before it is stored anywhere, U32 or higher temp A temporary value, U32 or higher value May hold the value from the operand when we may want to modify the operand without storing it back where it came from. This is also used to hold an immediate value ___________________________________________________________________________________________________ 4.4 Alphabetic Mnemonic Listing and Full Descriptions --------------------------------------------------------------------------------------------------- ADC ADD with Carry Description: .......................................................................... Adds the second operand and carry to the first operand. [1] states that R is set if carry out of bit 11. However, I believe they meant H (Half-Carry). Also according to [1], ADC sets most of the flags whereas ADD does not. I don't know if this is correct or not. Flags: ................................................................................ // 8bit ADC: szyhxpnc ******0* s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 of the result set? h - Was there carry from bit 3? (lower 4 bits of operand1 + lower 4 bits of (operand2 + c) >= 0x10)? x - Was bit 3 of the result set? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there carry (result > 0xFF)? szyhxpnc ******0* s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 of the high byte (bit 13) set? h - Was there carry from bit 11? (lower 12 bits of operand1 + lower 12 bits of (operand2 + c) >= 0x1000)? x - Was bit 3 of the high byte (bit 11) set? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there carry (result > 0xFFFF)? Code: ................................................................................. // 8bit ADC: result = operand1 + operand2 + c; h = ((operand1 & 0x0F) + ((operand2 + c) & 0x0F) >= 0x10; p = (~(operand1 ^ operand2) & (operand1 ^ result)) & 0x80; c = result > 0xFF; operand1 = (U8) result; s = operand1 & 0x80; y = operand1 & 0x20; x = operand1 & 0x08; z = !operand1; n = 0; // 16bit ADC: result = operand1 + operand2 + c; h = ((operand1 & 0x0FFF) + ((operand2 + c) & 0x0FFF) >= 0x1000; p = (~(operand1 ^ operand2) & (operand1 ^ result)) & 0x8000; c = result > 0xFFFF; operand1 = (U16) result; s = operand1 & 0x8000; y = operand1 & 0x2000; x = operand1 & 0x0800; z = !operand1; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- ADD ADD Description: .......................................................................... Adds the second operand to the first operand. Flags: ................................................................................ // 8bit ADD: szyhxpnc ******0* s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 of the result set? h - Was there carry from bit 3 (lower 4 bits of operand1 + lower 4 bits of operand2 >= 0x10)? x - Was bit 3 of the result set? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there carry (result > 0xFF)? // 16bit ADD: szyhxpnc ---*--0* h - Was there carry from bit 11? (lower 12 bits of operand1 + lower 12 bits of operand2 >= 0x1000)? c - Was there carry (result > 0xFFFF)? Code: ................................................................................. // 8bit ADD: result = operand1 + operand2; h = ((operand1 & 0x0F) + (operand2 & 0x0F)) >= 0x10; p = (~(operand1 ^ operand2) & (operand1 ^ result)) & 0x80; c = result > 0xFF; operand1 = (U8) result; s = operand1 & 0x80; y = operand1 & 0x20; x = operand1 & 0x08; z = !operand1; n = 0; // 16bit ADD: result = operand1 + operand2; h = ((operand1 & 0x0FFF) + (operand2 & 0x0FFF)) >= 0x1000; c = result > 0xFFFF; n = 0; operand1 = (U16) result; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- AND bitwise AND Description: .......................................................................... Performs a bitwise AND on A with the operand, storing the result in A. Flags: ................................................................................ szyhxpnc ***1**00 s - Was the highbit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even for A? [1] states: "P/V is reset if overflow, reset otherwise" This is obviously a typo, but I wonder what overflow means on a bitwise AND operation??? Since [1] states that p is set if parity is even for XOR, I am assuming this is also. Code: ................................................................................. A &= operand; s = A & 0x80; y = A & 0x20; x = A & 0x08; z = !A; p = IsParityEven(A); n = 0; c = 0; h = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- BIT BIT test Z80 Family Only Description: .......................................................................... Tests if the specified bit (bits 3-5 in the opcode are the specified bit, with values from 0 to 7) is set in the operand. The zero flag is set if the bit is NOT set, otherwise it is cleared. Flags: ................................................................................ szyhxpnc ***1**0- s - Set if the bit to test was 7 and it was set z - Was the bit tested NOT set? y - Set if the bit to test was 5 and it was set x - Set if the bit to test was 3 and it was set p - Set if the specified value was NOT set (same as z) According to [4], these specific instructions cause the x and y flags to be set differently. I am taking what [4] has stated (they made no mention of WZ) and, using our 8080 knowledge of WZ, adding in extra information pertaining to WZ for these instructions: BIT n, (IX+d) BIT n, (IY+d) BIT n, (HL) y - Set if bit 5 of the high byte of W is set x - Set if bit 3 of the high byte of W is set Please see the section on W, Z in the registers area for a description of how WZ is used. Note that BIT n, (IX+d) and BIT n, (IY+d) set WZ, so the address generated can be assumed to be where these bits are set from. Code: ................................................................................. // This code example does NOT take the strange behavior of BIT n, (HL) style instructions into // consideration for x and y // bittotest is the bit we need to test temp = operand & (1 << bittotest); p = z = !temp; s = temp & 0x80; y = temp & 0x20; x = temp & 0x08; h = 1; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CALL CALL subroutine Description: .......................................................................... Pushes the PC value after the opcode, then jumps to the specified subroutine. If this is a conditional call, then push and the jump only occur if the condition is true. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Opcode CD, 1100 1101b: PushWord(PC); PC = value; // Conditional opcodes: if (condition_true) { PushWord(PC); PC = value; } Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CCF Complement Carry Flag Description: .......................................................................... Complements (switches) the carry flag. Flags: ................................................................................ szyhxpnc ---*--0* h - Was c set before the operation? c - The opposite of c previously Code: ................................................................................. h = c; c ^= 1; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CP ComPare Description: .......................................................................... Compares the operand with A by subtracting the operand from A. The result is discarded, only the flags are changed. Flags: ................................................................................ szyhxpnc ******1* s - Was the high bit set on the result? z - Was the result zero (ie, the values were equal)? y - Was bit 5 set on the result? h - Was there borrow from bit 4 (lower 4bits of A are less than the lower 4bits of the operand)? x - Was bit 3 set on the result? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there borrow (A < operand)? Code: ................................................................................. result = (U8) (A - operand); s = result & 0x80; y = result & 0x20; x = result & 0x08; z = !result; h = (A & 0x0F) < (operand & 0x0F); p = ((A ^ operand) & (A ^ result)) & 0x80; c = A < operand; n = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CPD ComPare then Decrement Z80 Family Only Description: .......................................................................... Compares the byte at (HL) with A then decrements HL and decrements BC. Flags: ................................................................................ szyhxpnc ******1- s - Was the high bit set on the result? z - Was the result zero (ie, the values were equal)? y - Was bit 1 of A - value - (h after setting) set? h - Was there borrow from bit 4 (lower 4bits of A are less than the lower 4 bits of (HL))? x - Was bit 3 of A - value - (h after setting) set? p - Was BC non-zero? Code: ................................................................................. temp = GetByte(HL); HL--; BC--; result = (U8) (A - temp); s = result & 0x80; y = result & 0x20; x = result & 0x08; z = !result; h = (A & 0x0F) < (temp & 0x0F); p = BC; n = 1; result -= h; y = result & 0x01; x = result & 0x08; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CPDR ComPare then Decrement and Repeat Z80 Family Only Description: .......................................................................... Compares the byte at (HL) with A then decrements HL and decrements BC. If, after decrementing, BC is non-zero and A was not equal to (HL), then this instruction is repeated. In effect, this causes the instruction to loop BC times. If BC is set to 0, then 0x10000 (65536) loops occur. Flags: ................................................................................ szyhxpnc ******1- s - Was the high bit set on the result? z - Was the result zero (ie, the values were equal)? y - Was bit 1 of A - value - (h after setting) set? h - Was there borrow from bit 4 (lower 4bits of A are less than the lower 4 bits of (HL))? x - Was bit 3 of A - value - (h after setting) set? p - Was BC non-zero? Code: ................................................................................. temp = GetByte(HL); HL--; BC--; result = (U8) (A - temp); s = result & 0x80; y = result & 0x20; x = result & 0x08; z = !result; h = (A & 0x0F) < (temp & 0x0F); p = BC; n = 1; result -= h; y = result & 0x01; x = result & 0x08; if (BC && !z) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CPI ComPare then Increment Z80 Family Only Description: .......................................................................... Compares the byte at (HL) with A then increments HL and decrements BC. Flags: ................................................................................ szyhxpnc ******1- s - Was the high bit set on the result? z - Was the result zero (ie, the values were equal)? y - Was bit 1 of A - value - (h after setting) set? h - Was there borrow from bit 4 (lower 4bits of A are less than the lower 4 bits of (HL))? x - Was bit 3 of A - value - (h after setting) set? p - Was BC non-zero? Code: ................................................................................. temp = GetByte(HL); HL++; BC--; result = (U8) (A - temp); s = result & 0x80; z = !result; h = (A & 0x0F) < (temp & 0x0F); p = BC; n = 1; result -= h; y = result & 0x01; x = result & 0x08; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CPIR ComPare then Increment and Repeat Z80 Family Only Description: .......................................................................... Compares the byte at (HL) with A then increments HL and decrements BC. If, after decrementing, BC is non-zero and A was not equal to (HL), then this instruction is repeated. In effect, this causes the instruction to loop BC times. If BC is set to 0, then 0x10000 (65536) loops occur. Flags: ................................................................................ szyhxpnc ******1- s - Was the high bit set on the result? z - Was the result zero (ie, the values were equal)? y - Was bit 1 of A - value - (h after setting) set? h - Was there borrow from bit 4 (lower 4bits of A are less than the lower 4 bits of (HL))? x - Was bit 3 of A - value - (h after setting) set? p - Was BC non-zero? Code: ................................................................................. temp = GetByte(HL); HL++; BC--; result = (U8) (A - temp); s = result & 0x80; y = result & 0x20; x = result & 0x08; z = !result; h = (A & 0x0F) < (temp & 0x0F); p = BC; n = 1; result -= h; y = result & 0x01; x = result & 0x08; if (BC && !z) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- CPL ComPLement Description: .......................................................................... Sets A to the one's complement of itself (switches all bits). Flags: ................................................................................ szyhxpnc ---1--1- Code: ................................................................................. A ^= 0xFF; h = 1; n = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- DAA Decimal Adjust after Arithmetic Description: .......................................................................... Adjusts the accumulator for BCD addition or subtraction operations. Depending on the n flag, the "delta" in this table is either added (n = 0) or subtracted (n = 1) from the accumulator (all values in hex, taken from [4]): c | High | h | low |delta |nibble| |nibble| --+------+---+------+----- 0 | 0-8 | * | A-F | 06 0 | 9-F | * | A-F | 66 1 | * | * | A-F | 66 0 | 0-9 | 1 | 0-9 | 06 0 | A-F | 1 | 0-9 | 66 1 | * | 1 | 0-9 | 66 0 | 0-9 | 0 | 0-9 | 00 0 | A-F | 0 | 0-9 | 60 1 | * | 0 | 0-9 | 60 (see my code below for a "code" version of this chart) Flags: ................................................................................ szyhxpnc ******-* s - Was the high bit of the result set? z - Was the result 0? y - Was bit 5 set in the result? h - Was there carry from bit 3 for add, borrow from bit 4 for subtract? x - Was bit 3 set in the result? p - Did the result have even parity? c - Was there carry/borrow (was 60 added/subtracted)? Code: ................................................................................. // Place holders for carry and half-carry old_c = c; old_h = h; // This is our "work-in-progress" for the result result = A; // Assume half-carry and carry are 0 h = c = 0; // Do the subtraction version // This is based on the chart from [4] if (n) { // Was the lower nibble 0x0A or higher? if ((A & 0x0F) >= 0x0A) { result -= 0x06; // If the upper nibble is 9 or higher or we have carry, subtract 0x60 if (old_c || (A & 0xF0) >= 0x90) { c = 1; result -= 0x60; } // Otherwise, the lower nibble is 0x09 or lower } else { // Do we subtract 0x60 because of carry or the high nibble being too high? if (old_c || (A & 0xF0) >= 0xA0) { c = 1; result -= 0x60; } // Do we subtract 0x06 because of half-carry? if (old_h) { // Set half-carry if we borrowed if ((A & 0x0F) < 0x06) h = 1; result -= 0x06; } } // Do the addition version } else { // Is the lower nibble 0x0A or higher? if ((A & 0x0F) >= 0x0A) { // Half-carry occurred h = 1; result += 0x06; // If carry or the upper nibble is 0x90 or higher if (old_c || (A & 0xF0) >= 0x90) { c = 1; result += 0x60; } // Otherwise the lower nibble is 0x09 or lower } else { // If carry or the upper nibble is 0xA0 or higher if (old_c || (A & 0xF0) >= 0xA0) { c = 1; result += 0x60; } // Do we add 0x06 because of half-carry? if (old_h) { if ((A & 0x0F) < 0x06) h = 1; result += 0x06; } } } s = result & 0x80; y = result & 0x20; x = result & 0x08; p = IsParityEven(result); A = result; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- DEC DECrement Description: .......................................................................... Decrements the operand by 1. Flags: ................................................................................ // 8bit version: szyhxpnc ******1- s - Was the high bit set on the result? z - Was the result zero? y - Was bit 5 set in the result? h - Was there borrow from bit 4 (are the bottom 4 bits of the result = 0x0F)? x - Was bit 3 set in the result? p - Was there overflow (was the result 0x7F)? // 16bit version: szyhxpnc -------- Code: ................................................................................. // 8bit version: operand--; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; h = operand == 0x0F; p = operand == 0x7F; n = 1; // 16bit version: operand--; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- DI Disable Interrupts Description: .......................................................................... Sets the interrupt flip flop to 0, effectively disabling the maskable interrupts. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. IFF1 = 0; IFF2 = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- DJNZ Decrement and Jump if Not Zero Z80 Family Only Description: .......................................................................... Decrements B and jumps to a location within a signed byte (-128 to 127) of the first byte of the next instruction if B is not zero. This is useful for loops. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // In this case, operand is the 8bit immediate value if (--B) PC += (S16) ((S8) operand); Example: .............................................................................. ; This routine moves a line from an input buffer (Inbuf) to an output buffer (Outbuf). It moves ; the bytes until it finds a CR, or until it has moved 80 bytes, whichever occurs first. LD B, 80 ; 7 Set up counter LD HL, Inbuf ; 10 Set up pointers LD DE, Outbuf ; 10 LOOP: LD A, (HL) ; 7 Get next byte from input buffer LD (DE), A ; 7 Store in output buffer CP 0DH ; 7 Is it a CR? JR Z, DONE ; 7/12 Yes finished INC HL ; 6 Increment pointers INC DE ; 6 DJNZ LOOP ; 8/13 Loop back if 80 bytes have not been moved DONE: Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- EI Enable Interrupts Description: .......................................................................... Sets the interrupt flip flop to 1, enabling the maskable interrupts. Interrupts are not actually accepted until after the instruction after this instruction, which allows an EI, RETI combination to occur before a pending interrupt can occur and prevents stack overflows. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // This is difficult to show in a code snippet // Essentially, a flag should be sent to the emulator to tell it that not until after the next // instruction are interrupts permitted, even though IFF1 will be 1. // If an NMI is received subsequentally, that flag should be ignored (and IFF1 will be 0 at // that point anyways) IFF1 = 1; IFF2 = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- EX EXchange values Description: .......................................................................... Exchanges or switches the two specified values. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. temp = operand1; operand1 = operand2; operand2 = temp; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- EXX EXchange general register set [no clue where the second X goes... eXtended maybe?] Z80 Family Only Description: .......................................................................... Exchanges the six general registers with their alternate register sets. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. temp = BC; BC = BCalt; BCalt = temp; temp = DE; DE = DEalt; DEalt = temp; temp = HL; HL = HLalt; HLalt = temp; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- HALT HALT Description: .......................................................................... Halts the CPU until an interrupt or reset is received. This instruction basically continuously runs itself until an interrupt has occurred. This instruction replaces the opcode that would be LD (HL), (HL) Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Repeat this instruction if an interrupt has not occurred if (!An_Interrupt_Has_Occurred) PC--; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- IM set Interrupt Mode Z80 Family Only Description: .......................................................................... Sets the interrupt mode. There are only three interrupt modes; 0 to 2. Three separate opcodes exist to set these different values. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. IM = NewMode; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- IN INput from hardware port Description: .......................................................................... Inputs a byte from a hardware port. The value is read from a hardware port specified by operand2 and written to operand1. 16bit ports: In actuality, a 16bit port address is set. Opcode DB uses A*256 + the value, whereas the (C) versions use BC instead of just C. Flags: ................................................................................ Opcode DB: szyhxpnc -------- Other opcodes: szyhxpnc ***0**0- s - Was the high bit set from the value? z - Was the value zero? y - Was bit 5 set in the value? x - Was bit 3 set in the value? p - Was parity even for the value? Code: ................................................................................. // Opcode DB: A = GetPortByte((A<<8) + value); // IN F, (C): temp = GetPortByte(BC); s = temp & 0x80; z = !temp; y = temp & 0x20; x = temp & 0x08; p = IsParityEven(temp); // Other opcodes: operand = GetPortByte(BC); s = operand & 0x80; z = !operand; y = operand & 0x20; x = operand & 0x08; p = IsParityEven(operand); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- INC INCrement Description: .......................................................................... Increments the operand by 1. Flags: ................................................................................ // 8bit version: szyhxpnc ******0- s - Was the high bit set on the result? z - Was the result zero? y - Was bit 5 set in the result? h - Was there carry from bit 3 (are the bottom 4 bits of the result 0)? x - Was bit 3 set in the result? p - Was there overflow (was the result 0x80)? // 16bit version: szyhxpnc -------- Code: ................................................................................. // 8bit version: operand++; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; h = !(operand & 0x0F); p = operand == 0x80; n = 0; // 16bit version: operand++; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- IND INput from hardware port and Decrement Z80 Family Only Description: .......................................................................... B is decremented. Then a byte is inputted from the hardware port specified by C into the byte pointed to by HL. HL is then decremented. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from AFTER the decrement. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B is AFTER decrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value read + ((C - 1) & 0xFF) > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + C - 1) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. B--; value = GetPortByte(BC); PutByte(HL, value); HL--; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + ((C - 1) & 0xFF) > 0xFF; p = IsParityEven(((value + C - 1) & 0x07) ^ B); z = !B; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- INDR INput from hardware port, Decrement and Repeat Z80 Family Only Description: .......................................................................... B is decremented. Then a byte is inputted from the hardware port specified by C into the byte pointed to by HL. HL is then decremented. If B is not zero, then this instruction is repeated. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from AFTER the decrement. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B is AFTER decrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value read + ((C - 1) & 0xFF) > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + C - 1) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. B--; value = GetPortByte(BC); PutByte(HL, value); HL--; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + ((C - 1) & 0xFF) > 0xFF; p = IsParityEven(((value + C - 1) & 0x07) ^ B); z = !B; // We're using z since it gets set as soon as B is zero if (!z) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- INI INput from hardware port and Increment Z80 Family Only Description: .......................................................................... B is decremented. Then a byte is inputted from the hardware port specified by C into the byte pointed to by HL. HL is then incremented. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from AFTER the decrement. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B is AFTER decrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value read + ((C + 1) & 0xFF) > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + C + 1) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. B--; value = GetPortByte(BC); PutByte(HL, value); HL++; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + ((C + 1) & 0xFF) > 0xFF; p = IsParityEven(((value + C + 1) & 0x07) ^ B); z = !B; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- INIR INput from hardware port, Increment and Repeat Z80 Family Only Description: .......................................................................... B is decremented. Then a byte is inputted from the hardware port specified by C into the byte pointed to by HL. HL is then incremented. If B is not zero, then the instruction is repeated. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from AFTER the decrement. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B is AFTER decrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value read + ((C + 1) & 0xFF) > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + C + 1) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. B--; value = GetPortByte(BC); PutByte(HL, value); HL++; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + ((C + 1) & 0xFF) > 0xFF; p = IsParityEven(((value + C + 1) & 0x07) ^ B); z = !B; // We're using z since it gets set as soon as B is zero if (!z) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- JP JumP absolute Description: .......................................................................... Jumps to the specified address by setting the program counter to the operand. If this is a jump with a condition, then the jump only occurs if the condition is true. Note that in the case of JP (HL) (opcode E9), JP (IX) (DD E9), JP (IY) (FD E9), the program counter actually becomes the register pair not a value from memory. Because of this, I omit the parenthesis on these opcodes. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Condition based opcodes: if (condition_true) PC = operand; // Other opcodes: PC = operand; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- JR Jump Relative Z80 Family Only Description: .......................................................................... Jumps to a location within a signed byte (-128 to 127) of the first byte of the next instruction. If this is a jump with a condition, then the jump only occurs if the condition is true. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // In this case, value is the 8bit immediate value // Opcode 18 or 0001 1000b: PC += (S16) ((S8) value); // Condition based opcodes: if (condition_true) PC += (S16) ((S8) value); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- LD LoaD value Description: .......................................................................... Loads the contents of one value into another. Flags are set when using LD A, I or LD A, R. Flags: ................................................................................ 8080: sz-h-p-c -------- Z80: szyhxpnc -------- LD A, I and LD A, R set the flags accordingly: szyhxpnc ***0**0- s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 set in the result? x - Was bit 3 set in the result? p - Contains IFF2 Code: ................................................................................. operand1 = operand2; // Additional for LD A, I and LD A, R: s = operand1 & 0x80; y = operand1 & 0x20; x = operand1 & 0x08; z = !operand1; p = IFF2; h = 0; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- LDD LoaD then Decrement Z80 Family Only Description: .......................................................................... Transfers a byte from (HL) to (DE), then decrements both register pairs and decrements the BC register pair. Flags: ................................................................................ szyhxpnc --*0**0- y - Was bit 1 of A + value loaded set? x - Was bit 3 of A + value loaded set? p - Was BC non-zero? Code: ................................................................................. value = GetByte(HL); PutByte(DE, value); HL--; DE--; BC--; p = BC; h = 0; n = 0; temp = A + value; y = temp & 0x01; x = temp & 0x08; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- LDDR LoaD then Decrement and Repeat Z80 Family Only Description: .......................................................................... Transfers a byte from (HL) to (DE), then decrements both register pairs and decrements the BC register pair. If, after decrementing, BC is non-zero, then this instruction is repeated. In effect, this causes the instruction to loop BC times. If BC is set to 0, then 0x10000 (65536) loops occur. Flags: ................................................................................ szyhxpnc --*0*00- y - Was bit 1 of A + value loaded set? x - Was bit 3 of A + value loaded set? Code: ................................................................................. value = GetByte(HL); PutByte(DE, value); HL--; DE--; BC--; h = 0; n = 0; p = 0; temp = A + value; y = temp & 0x01; x = temp & 0x08; // Redo the instruction if we're not done if (BC) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- LDI LoaD then Increment Z80 Family Only Description: .......................................................................... Transfers a byte from (HL) to (DE), then increments both register pairs and decrements the BC register pair. Flags: ................................................................................ szyhxpnc --*0**0- y - Was bit 1 of A + value loaded set? x - Was bit 3 of A + value loaded set? p - Was BC non-zero? Code: ................................................................................. value = GetByte(HL); PutByte(DE, value); HL++; DE++; BC--; p = BC; h = 0; n = 0; temp = A + value; y = temp & 0x01; x = temp & 0x08; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- LDIR LoaD then Increment and Repeat Z80 Family Only Description: .......................................................................... Transfers a byte from (HL) to (DE), then increments both register pairs and decrements the BC register pair. If, after decrementing, BC is non-zero, then this instruction is repeated. In effect, this causes the instruction to loop BC times. If BC is set to 0, then 0x10000 (65536) loops occur. Flags: ................................................................................ szyhxpnc --*0*00- y - Was bit 1 of A + value loaded set? x - Was bit 3 of A + value loaded set? Code: ................................................................................. value = GetByte(HL); PutByte(DE, value); HL++; DE++; BC--; h = 0; n = 0; p = 0; temp = A + value; y = temp & 0x01; x = temp & 0x08; // Redo the instruction if we're not done if (BC) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- NEG NEGative Z80 Family Only Description: .......................................................................... Sets the accumulator to the negative of the accumulator (two's complement). This is the same as subtracting A from 0. Flags: ................................................................................ szyhxpnc ******1* s - Was the highbit of the result set? z - Was the result 0? y - Was bit 5 of the result set? h - Was there borrow from bit 4? x - Was bit 3 of the result set? p - Was the result 0x80? c - Was the result 0? Code: ................................................................................. h = A & 0x0F; A = 0 - A; s = A & 0x80; y = A & 0x20; x = A & 0x08; z = !A; p = A == 0x80; c = !A; n = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- NOP No OPeration Description: .......................................................................... Nothing happens, essentially this is just a place holder. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Does nothing Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- OR bitwise OR Description: .......................................................................... Performs a bitwise OR on A with the operand, storing the result in A. Flags: ................................................................................ szyhxpnc ***0**00 s - Was the highbit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set p - Was parity even? [1] states: "P/V is set if overflow, reset otherwise" I wonder what overflow means on a bitwise OR operation??? Since [1] states that p is set if parity is even for XOR, I am assuming this is also. Code: ................................................................................. A |= operand; s = A & 0x80; y = A & 0x20; x = A & 0x08; z = !A; p = IsParityEven(A); h = 0; n = 0; c = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- OUT OUTput to hardware port Description: .......................................................................... Outputs a byte to a hardware port. The value from operand2 is written to the port specified by operand1. 16bit ports: In actuality, a 16bit port address is set. Opcode D3 uses A*256 + the value, whereas the (C) versions use BC instead of just C. Flags: ................................................................................ Opcode D3: szyhxpnc -------- Other opcodes: szyhxpnc ***0**0- s - Was the high bit set from the value? z - Was the value zero? y - Was bit 5 set in the value? x - Was bit 3 set in the value? p - Was parity even for the value? Code: ................................................................................. // Opcode D3: PutPortByte((A<<8) + value, A); // Other opcodes: PutPortByte(BC, operand); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- OUTD OUTput to hardware port and Decrement Z80 Family Only Description: .......................................................................... Outputs a byte from the hardware port specified by C from the byte pointed to by HL. B is then decremented and HL is decremented. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from BEFORE decrementing B. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B and L are AFTER decrementing/incrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value written + L > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + L) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. value = GetByte(HL); PutPortByte(BC, value); B--; HL--; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + L > 0xFF; p = IsParityEven(((value + L) & 0x07) ^ B); z = !B; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- OTDR OuTput to hardware port, Decrement and Repeat Z80 Family Only Description: .......................................................................... Outputs a byte from the hardware port specified by C from the byte pointed to by HL. B is then decremented and HL is decremented. If B is not zero, the instruction is repeated. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from BEFORE decrementing B. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B and L are AFTER decrementing/incrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value written + L > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + L) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. value = GetByte(HL); PutPortByte(BC, value); B--; HL--; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + L > 0xFF; p = IsParityEven(((value + L) & 0x07) ^ B); z = !B; // We're using z since it gets set as soon as B is zero if (!z) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- OUTI OUTput to hardware port and Increment Z80 Family Only Description: .......................................................................... Outputs a byte from the hardware port specified by C from the byte pointed to by HL. B is then decremented and HL is incremented. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from BEFORE decrementing B. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B and L are AFTER decrementing/incrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value written + L > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + L) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. value = GetByte(HL); PutPortByte(BC, value); B--; HL++; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + L > 0xFF; p = IsParityEven(((value + L) & 0x07) ^ B); z = !B; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- OTIR OuTput to hardware port, Increment and Repeat Z80 Family Only Description: .......................................................................... Outputs a byte from the hardware port specified by C from the byte pointed to by HL. B is then decremented and HL is incremented. If B is not zero, the instruction is repeated. 16bit ports: In actuality, a 16bit port address is used, BC instead of just C. The value of B used is from BEFORE decrementing B. The flags are taken from [4] which differ a LOT from what [1] says. Since the flag data from [4] is based on extensive testing, I will trust it over [1]. Flags: ................................................................................ For flags, the value of B and L are AFTER decrementing/incrementing. szyhxpnc ******** s - Was the high bit of B set? z - Was B zero? y - Was bit 5 of B set? h - Was the value written + L > 0xFF? x - Was bit 3 of B set? p - Was the parity even for ((value read + L) & 0x07) ^ B n - Was the high bit set on the value read? c - Same as h Code: ................................................................................. value = GetByte(HL); PutPortByte(BC, value); B--; HL++; s = B & 0x80; y = B & 0x20; x = B & 0x08; n = value & 0x80; c = h = value + L > 0xFF; p = IsParityEven(((value + L) & 0x07) ^ B); z = !B; // We're using z since it gets set as soon as B is zero if (!z) PC -= 2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- POP POP a value from the stack Description: .......................................................................... Pops a value from the stack. The low byte is read from (SP), then SP is incremented. Then the high byte is read from (SP) and SP is again incremented. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. operand = GetByte(SP); SP++; operand += (GetByte(SP) << 8); SP++; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- PUSH PUSH a value onto the stack Description: .......................................................................... Pushes a value onto the stack. SP is decremented, then the high byte is stored at (SP). Then SP is decremented again, and the low byte is stored at (SP). Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Short version: PushWord(operand); // Fully detailed version: SP--; PutByte(SP, operand >> 8); SP--; PutByte(SP, operand); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RES RESet a bit Z80 Family Only Description: .......................................................................... Loads the value from the memory address or register specified into either TMP (all documented instructions), or to the register specified in operand3 (undocumented instructions). Then, clears the specified bit (bits 3-5 in the opcode are the specified bit, with values from 0 to 7). The result is then stored back to the memory address (or not if it's a memory location in ROM) or register specified. If there is a second operand, the value is first loaded from the first operand into the second operand, the bit is then cleared in that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Bit and One Operand: // bittotest is the bit we need to test operand &= ~(1 << bittotest); // Bit and Two Operands: operand2 = operand1; operand2 &= ~(1 << bittotest); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RET RETurn from subroutine Description: .......................................................................... Pops PC off of the stack. This essentially returns us from a subroutine. If this is a conditional RET, then PC is only popped off of the stack if the condition is met. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Opcode C9, 1100 1001b: PC = PopWord(); // Conditional opcodes: if (condition_true) PC = PopWord(); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RETI RETurn from Interrupt Z80 Family Only Description: .......................................................................... Pops PC off of the stack and signalling to hardware that an interrupt has just been handled. Since only higher priority hardware can interrupt lower priority hardware, the hardware that receives the signal is the last device that caused the interrupt. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. PC = PopWord(); SendInterruptCompleteSignal(); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RETN RETurn from Non-maskable interrupt Z80 Family Only Description: .......................................................................... Pops PC off of the stack and sets IFF1 to IFF2. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. PC = PopWord(); IFF1 = IFF2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RL Rotate Left with carry Z80 Family Only Description: .......................................................................... Rotates the operand to the left by one bit, moving the high bit to the carry flag and the carry flag into bit 0 of the operand. If there is a second operand, the value is first loaded from the first operand into the second operand, the rotate is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit set on the result? z - Was the result 0? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the high bit set before rotating? Code: ................................................................................. // One operand: old_c = c; c = operand & 0x80; operand <<= 1; operand += old_c; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: old_c = c; operand2 = operand1; c = operand2 & 0x80; operand2 <<= 1; operand2 += old_c; s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RLA Rotate Left Accumulator with carry Description: .......................................................................... Rotates the accumulator to the left by one bit, moving the high bit to the carry flag and the carry flag into bit 0 of the accumulator. Flags: ................................................................................ szyhxpnc ---0--0* c - Was the highbit set on A before the rotate? Code: ................................................................................. old_c = c; c = A & 0x80; A <<= 1; A += old_c; h = 0; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RLC Rotate Left and to Carry Z80 Family Only Description: .......................................................................... Rotates the register's to the left by one bit, moving the high bit to the carry flag and to bit 0 of the operand. If there is a second operand, the value is first loaded from the first operand into the second operand, the rotate is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit set on the result? z - Was the result 0? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the high bit set before rotating? Code: ................................................................................. // One operand: c = operand & 0x80; operand <<= 1; operand += c; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; c = operand2 & 0x80; operand2 <<= 1; operand2 += c; s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RLCA Rotate Left to Carry and Accumulator Description: .......................................................................... Rotates the accumulator to the left by one bit, moving the high bit to bit 0 and also storing it in the carry flag. Flags: ................................................................................ szyhxpnc ---0--0* c - Was the highbit set on A before the rotate? Code: ................................................................................. c = A & 0x80; A <<= 1; A += c; // remember that c is 1 if (A & 0x80) is true h = 0; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RLD Rotate Left 12bit Data Z80 Family Only Description: .......................................................................... The operands for this opcode are A and (HL), both are affected. The lower 4bits of A are used as the top 4bits in a 12bit value, with (HL) as the lower 8bits, and this value is rotated to the left by 4 bits. The top 4bits of A are unaffected. eg, if A is $1F and (HL) is $37, RLD causes A to become $13, the 3 was the upper 4bits of (HL), and (HL) to become $7F, the 7 was the lower 4bits of (HL) and the F was the lower 4bits of A Flags: ................................................................................ szyhxpnc ***0**0- s - Was the high bit set on A? z - Was A zero? y - Was bit 5 of A set? x - Was bit 3 of A set? p - Was parity even on A? Code: ................................................................................. // operand is (HL) // A is A of course temp = (operand >> 4) + (A & 0xF0); operand = (operand << 4) + (A & 0x0F); A = temp; s = A & 0x80; y = A & 0x20; x = A & 0x08; z = !A; p = IsParityEven(A); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RR Rotate Right with carry Z80 Family Only Description: .......................................................................... Rotates the operand to the right by one bit, moving the low bit to the carry flag and the carry flag into the high bit of the operand. If there is a second operand, the value is first loaded from the first operand into the second operand, the rotate is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit set on the result? z - Was the result 0? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the low bit set before rotating? Code: ................................................................................. // One operand: old_c = c; c = operand & 0x01; operand >>= 1; operand += old_c << 7; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; old_c = c; c = operand2 & 0x01; operand2 >>= 1; operand2 += old_c << 7; s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RRA Rotate Right Accumulator with carry Description: .......................................................................... Rotates the accumulator to the right by one bit, moving the kiw bit to the carry flag and the carry flag into bit 7 of the accumulator. Flags: ................................................................................ szyhxpnc ---0--0* c - Was bit 0 set on A before the rotate? Code: ................................................................................. old_c = c; c = A & 0x01; A >>= 1; if (old_c) A += 0x80; h = 0; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RRC Rotate Right and to Carry Z80 Family Only Description: .......................................................................... Rotates the register's to the right by one bit, moving the low bit to the carry flag and to the high bit. If there is a second operand, the value is first loaded from the first operand into the second operand, the rotate is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit set on the result? z - Was the result 0? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the low bit set before rotating? Code: ................................................................................. // One operand: c = operand & 0x01; operand >>= 1; operand += c << 7; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; c = operand2 & 0x01; operand2 >>= 1; operand2 += c << 7; s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RRCA Rotate Right to Carry and Accumulator Description: .......................................................................... Rotates the accumulator to the right by one bit, moving the low bit to bit 7 and also storing it in the carry flag. Flags: ................................................................................ szyhxpnc ---0--0* c - Was bit 0 set on A before the rotate? Code: ................................................................................. c = A & 0x01; A >>= 1; if (c) A += 0x80; h = 0; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RRD Rotate Right 12bit Data Z80 Family Only Description: .......................................................................... The operands for this opcode are A and (HL), both are affected. The lower 4bits of A are used as the top 4bits in a 12bit value, with (HL) as the lower 8bits, and this value is rotated to the right by 4 bits. The top 4bits of A are unaffected. eg, if A is $1F and (HL) is $37, RRD causes A to become $17, the 7 was the lower 4bits of (HL), and (HL) to become $F3, the F was the lower 4bits of A and the 3 was the upper 4bits of (HL) Flags: ................................................................................ szyhxpnc ***0**0- s - Was the high bit set on A? z - Was A zero? y - Was bit 5 of A set? x - Was bit 3 of A set? p - Was parity even on A? Code: ................................................................................. // operand is (HL) // A is A of course temp = (operand & 0x0F) + (A & 0xF0); operand = (operand >> 4) + ((A & 0x0F) << 4); A = temp; s = A & 0x80; y = A & 0x20; x = A & 0x08; z = !A; p = IsParityEven(A); Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- RST ReSeT (or ReSTart) Description: .......................................................................... Not to be confused with a system reset or reboot, this simply calls a predefined location in memory. The value locations in memory are 00H, 08H, 10H, 18H, 20H, 28H, 30H and 38H, which matches bits 3-5 of the opcode (the value, not the bits). PC is pushed before this location is called. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. PushWord(PC); PC = opcode & 0x38; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SBC SuBtract with Carry Description: .......................................................................... Subtracts the second operand and carry from the first operand. Flags: ................................................................................ // 8bit SBC szyhxpnc ******1* s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 of the result set? h - Was there borrow from bit 4 (lower 4 bits of operand1 < lower 4 bits of operand2 + c)? x - Was bit 3 of the result set? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there borrow (operand1 < operand2 + c)? // 16bit SBC szyhxpnc ******1* s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 of the high byte set? h - Was there borrow from bit 12 (lower 12 bits of operand1 < lower 12 bits of (operand2 + c))? x - Was bit 3 of the high byte set? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there borrow (operand1 < operand2 + c)? Code: ................................................................................. // 8bit SBC: temp = operand2 + c; result = operand1 - temp; h = (operand1 & 0x0F) < ((operand2 + c) & 0x0F); p = ((operand1 ^ temp) & (operand1 ^ result)) & 0x80; c = operand1 < temp; s = result & 0x80; y = result & 0x20; x = result & 0x08; operand1 = (U8) result; z = !operand1; n = 1; // 16bit SBC: temp = operand2 + c; result = operand1 - temp; h = (operand1 & 0x0FFF) < ((operand2 + c) & 0x0FFF); p = ((operand1 ^ temp) & (operand1 ^ result)) & 0x8000; c = operand1 < temp; s = result & 0x8000; y = result & 0x2000; x = result & 0x0800; operand1 = (U16) result; z = !operand1; n = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SCF Set Carry Flag Description: .......................................................................... Sets the carry flag. Flags: ................................................................................ szyhxpnc ---0--01 Code: ................................................................................. c = 1; h = 0; n = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SET SET a bit Z80 Family Only Description: .......................................................................... Sets the specified bit (bits 3-5 in the opcode are the specified bit, with values from 0 to 7) in the operand. If there is a second operand, the value is first loaded from the first operand into the second operand, the bit is then set in that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. // Bit and One Operand: // bittotest is the bit we need to test operand |= (1 << bittotest); // Bit and Two Operands: operand2 = operand1; operand2 |= (1 << bittotest); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SL1* Shift Left with 1 aka SLL* Shift Left Logical [UNDOCUMENTED] Z80 Family Only Description: .......................................................................... Shifts the operand to the left by one bit, placing a 1 in bit 0. NOTE: Some documentation calls this instruction Shift Left Logical, but this is not a correct representation of the opcode. A logical shift left would place a 0 in bit 0 (just like SLA). If there is a second operand, the value is first loaded from the first operand into the second operand, the shift is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the high bit set before the shift? Code: ................................................................................. // One operand: c = operand & 0x80; operand <<= 1; operand++; // set bit 0 to 1 s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; c = operand2 & 0x80; operand2 <<= 1; operand2++; // set bit 0 to 1 s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SLA Shift Left Arithmetic Z80 Family Only Description: .......................................................................... Shifts the operand to the left by one bit. If there is a second operand, the value is first loaded from the first operand into the second operand, the shift is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the high bit set before the shift? Code: ................................................................................. // One operand: c = operand & 0x80; operand <<= 1; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; c = operand2 & 0x80; operand2 <<= 1; s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SLL* Shift Left Logical see SL1* Shift Left with 1 [UNDOCUMENTED] Z80 Family Only --------------------------------------------------------------------------------------------------- SRA Shift Right Arithmetic Z80 Family Only Description: .......................................................................... Shifts the operand to the right by one bit, preserving the high bit. This is useful when using bit shifting to divide a signed value. If there is a second operand, the value is first loaded from the first operand into the second operand, the shift is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the low bit set before the shift? Code: ................................................................................. // One operand: s = operand & 0x80; c = operand & 0x01; operand >>= 1; operand |= s << 7; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; s = operand2 & 0x80; c = operand2 & 0x01; operand2 >>= 1; operand2 |= s << 7; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SRL Shift Right Logical Z80 Family Only Description: .......................................................................... Shifts the operand to the right by one bit. This is useful when using bit shifting to divide an unsigned value. If there is a second operand, the value is first loaded from the first operand into the second operand, the shift is done on that operand, then stored back into the first operand. The second operand will always be one of the general registers. Flags: ................................................................................ szyhxpnc ***0**0* s - Was the high bit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even on the result? c - Was the low bit set before the shift? Code: ................................................................................. // One operand: c = operand & 0x01; operand >>= 1; s = operand & 0x80; y = operand & 0x20; x = operand & 0x08; z = !operand; p = IsParityEven(operand); // Two operands: operand2 = operand1; c = operand2 & 0x01; operand2 >>= 1; s = operand2 & 0x80; y = operand2 & 0x20; x = operand2 & 0x08; z = !operand2; p = IsParityEven(operand2); operand1 = operand2; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- SUB SUBtract Description: .......................................................................... Subtracts the second operand from the first operand. NOTE: In a most confusing way, the SUB instruction in the Z80 documents does NOT have A as the first operand when SBC, ADD and ADC which all act about the same do! I am NOT leaving things this way since I find it rather stupid. Flags: ................................................................................ szyhxpnc ******1* s - Was the high bit set in the result? z - Was the result zero? y - Was bit 5 of the result set? h - Was there borrow from bit 4 (lower 4 bits of operand1 < lower 4 bits of operand2)? x - Was bit 3 of the result set? p - Was there signed overflow? p is set only if one of the following is true: If both operand1 and operand2 are negative and the result is positive If both operand1 and operand2 are positive and the result is negative c - Was there borrow (operand1 < operand2)? Code: ................................................................................. result = operand1 - operand2; h = (operand1 & 0x0F) < (operand2 & 0x0F); p = ((operand1 ^ operand2) & (operand1 ^ result)) & 0x80; c = operand1 < operand2; s = result & 0x80; y = result & 0x20; x = result & 0x08; operand1 = (U8) result; z = !operand1; n = 1; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- XOR bitwise eXclusive OR Description: .......................................................................... Performs a bitwise eXclusive OR on A with the operand, storing the result in A. * NOTE: [1] has an "oversight" issue here in that they list the opcode values of XOR as the same as the OR. I'm assuming a copy and paste occured and someone didn't fix their problem. Flags: ................................................................................ szyhxpnc ***0**00 s - Was the highbit of the result set? z - Was the result zero? y - Was bit 5 of the result set? x - Was bit 3 of the result set? p - Was parity even? Code: ................................................................................. A ^= operand; s = A & 0x80; y = A & 0x20; x = A & 0x08; z = !A; p = IsParityEven(A); h = 0; n = 0; c = 0; Opcodes: .............................................................................. --------------------------------------------------------------------------------------------------- xxx MNEmonic Description: .......................................................................... Flags: ................................................................................ szyhxpnc -------- Code: ................................................................................. Opcodes: .............................................................................. *************************************************************************************************** 5 Interrupts KERBLUH - Add 8080 and 8085 details NMI 8080 The 8080 does not have NMI support Z80 Family Costs 11 cycles [1] states that IFF2 = IFF1 before IFF1 is set to 0, but [4] did thorough testing and states that it does NOT get copied over and IFF1 is simply set to 0. IFF1 = 0 Push PC PC = 0066H INT - Maskable Interrupt 8080 Allows a device to execute any instruction on the CPU. This takes two clocks more than that instruction would normally cost. Immediately after the instruction is executed, normal control is returned to the program that was interrupted. This mode is normally used for sending an RST instruction. Assuming this sends an RST instruction, this costs 13 cycles KERBLUH - Is the 8085 the same? Z80 Family On the Z80 Family, there are three interrupt response modes, set by IM x (where x is the mode to use). These all respond rather differently, though all of them set IFF1 and IFF2 to 0. Because of this, before returning from a maskable interrupt, an EI instruction should be used to reenabled interrupts. IFF1 = 0 IFF2 = 0 Mode 0 Identical to the 8080-style interrupt described above Mode 1 This mode is similar to NMI except a different location in memory is called, the equivalent of an RST 38H Costs 2 clocks more than a normal restart instruction (13 cycles) Push PC PC = 0038H Mode 2 In this mode, an address is generated using I as the high byte and eight bits passed by the interrupting device to be used as the low byte. At the address specified, a 16bit value is loaded into PC. This allows I to index up to 128 interrupt routines. This takes a total of 19 clocks to complete (7 to fetch the lower 8bits from the device, 6 to push PC and 6 to jump to the new location). [1] states that the low by must always be 0 so the addresses align to a 2byte boundary. However, [4] states they have tested IM2 and could use FFH for an address, meaning that the low bit is INDEED read. Since [4] is based on years of use and testing, I will trust it's results. Push PC PC = *((I << 8) + value); RESET 8080: The program counter is cleared to 0. All other registers are not changed when reset occurs, so their state is unknown, INCLUDING the interrupt enable flip-flop. PC = 0 Z80 Family: Reset the interrupt enable flip-flop Sets the interrupt status to Mode 0. During reset time, the address and data bus go to a high-impedance state, and all control output signals go to the inactive state. Notice that RESET must be active for a minimum of three full clock clocks before the reset operation is complete. According to [4], the best "guess" for how the registers are is: IX = IY = SP = BC = HL = DE = AF = FFFFH PC = I = IM = R = IFF1 = IFF2 = 0 *************************************************************************************************** 6 Pins ___________________________________________________________________________________________________ 6.1 8080 40 pins total: ----v---- A10 [| 1 40|] A11 GND [| 2 39|] A14 D4 [| 3 38|] A13 D5 [| 4 37|] A12 D6 [| 5 36|] A15 D7 [| 6 35|] A9 D3 [| 7 34|] A8 D2 [| 8 33|] A7 D1 [| 9 32|] A6 D0 [|10 31|] A5 -5V [|11 30|] A4 -> RESET [|12 29|] A3 -> HOLD [|13 28|] +12V -> INT [|14 27|] A2 *2 [|15 26|] A1 <- INTE [|16 25|] A0 <- DBIN [|17 24|] WAIT -> <- WR [|18 23|] READY <- <- SYNC [|19 22|] *1 +5V [|20 21|] HLDA -> --------- *1 and *2 are clock inputs, and the *s should really be the crossed out o (phi). In: ......................................................................... HOLD External devices can intercept time from the processor by sending this signal. The processor will relinquish it's address and data lines and idle while it is "on hold", as well as responding by setting it's HLDA pin. The hold occurs on the processor on T3 (the third cycle) of any given machine cycle. If this occurs before the current machine cycle has completed, the CPU will complete the machine cycle before actually going on hold. INT If an external device sets this high, it request an interrupt from the processor. READY Pulling this line low tells the processor that memory access is occurring and will cause the processor to idle until it is released. If the processor expends cycles waiting for the READY signal, it then sends the WAIT signal RESET Setting this signal high for at least three cycles will cause the CPU to reset. See the description of RESET above in the interrupts section for full details. Out: ........................................................................ DBIN Generated when the CPU needs to input data, to syncronice external transfers HLDA This pin is set high when the CPU is "on hold" from a request through the HOLD pin INTE This pin is high when interrupts are enabled so that external devices know whether or not their interrupts will be processed SYNC This is pulsed every machine cycle (not clocks) WAIT This signal goes high when one or more cycles/states are "waiting" for the READY signal to be released. WR Generated when the CPU needs to output data, to syncronize external transfers ___________________________________________________________________________________________________ 6.2 8085 KERBLUH - yeah, I need pin information for the 8085... ___________________________________________________________________________________________________ 6.3 Z80 These pin details are mostly verbatim from [1]. 40 pins total: ----v---- A11 [| 1 40|] A10 A12 [| 2 39|] A9 A13 [| 3 38|] A8 A14 [| 4 37|] A7 A15 [| 5 36|] A6 -> CLK [| 6 35|] A5 D4 [| 7 34|] A4 D3 [| 8 33|] A3 D5 [| 9 Z 32|] A2 D6 [|10 8 31|] A1 +5V [|11 0 30|] A0 D2 [|12 29|] GND D7 [|13 28|] RFSH -> D0 [|14 27|] M1 -> D1 [|15 26|] RESET <- -> INT [|16 25|] BUSREQ <- -> NMI [|17 24|] WAIT <- <- HALT [|18 23|] BUSACK -> <- MREQ [|19 22|] WR -> <- IORQ [|20 21|] RD -> --------- In: ......................................................................... WAIT WAIT (active low). WAIT communicates to the CPU that the addressed memory or I/O devices are not ready for a data transfer. The CPU continues to enter a WAIT state as long as this signal is active. Extended WAIT periods can prevent the CPU from properly refreshing dynamic memory. INT Interrupt Request (active low). The CPU receives the interrupt request if the interrupt enable flip-flop (IFF) is enabled. NMI Non-Maskable Interrupt (negative edge-triggered). NMI has a higher priority than INT. NMI is always recognized at the end of the current instruction, independent of the status of the interrupt enable flip-flop, and automatically forces the CPU to restart at location 0066H. RESET Reset (active low). RESET initializes the CPU as follows: it resets the interrupt enable flip-flop, clears the PC and registers I and R, and sets the interrupt status to Mode 0. During reset time, the address and data bus go to a high-impedance state, and all control output signals go to the inactive state. Notice that RESET must be active for a minimum of three full clocks before the reset operation is complete. BUSREQ Bus Request (active low). From [1]: Bus Request has a higher priority than NMI and is always recognized at the end of the current machine cycle. BUSREQ forces the CPU address bus, data bus, and control signals MREQ IORQ, RD, and WR to go to a high- impedance state so that other devices can control these lines. BUSREQ is normally wired-OR and requires an external pull-up for these applications. Extended BUSREQ periods due to extensive DMA operations can prevent the CPU from properly refreshing dynamic RAMS. CLK Clock. Single-phase MOS-level clock. Out: ........................................................................ M1 Machine Cycle One (active low). M1, together with MREQ, indicates that the current machine cycle is the opcode fetch cycle of an instruction execution. M1 together with IORQ, indicates an interrupt acknowledge cycle. MREQ Memory Request (active low, tristate). MREQ indicates that the address bus holds a valid address for a memory read or memory write operation. IORQ Input/Output Request (active low, tristate). Indicates that the lower half of the address bus holds a valid I/O address for an I/O read or write operation. IORQ is also generated concurrently with M1 during an interrupt acknowledge cycle to indicate that an interrupt response vector can be placed on the data bus. RD Read (active low, tristate). RD indicates that the CPU wants to read data from memory or an I/O device. The addressed I/O device or memory should use this signal to gate data onto the CPU data bus. WR Write (active low, tristate). WR indicates that the CPU data bus holds valid data to be stored at the addressed memory or I/O location. RFSH Refresh (active low). RFSH, together with MREQ indicates that the lower seven bits of the system’s address bus can be used as a refresh address to the system’s dynamic memories. HALT HALT State (active low). Indicates that the processor has executed a HALT instruction and is waiting for a non-maskable interrupt (or a maskable one if the mask is enabled) to start up again. The CPU constantly executes NOPs to maintain the memory refresh. BUSACK Bus Acknowledge (active low). Indicates to the requesting device that the CPU address bus, data bus and control signals MREQ, IORQ, RD and WR have entered their high-impedance states. The external circuitry can now control these lines. *************************************************************************************************** 7 Quirks and Nuances ___________________________________________________________________________________________________ 7.1 Nuances (Intentional Processor Behavior) BCD is not directly supported by arithmetic functions, but rather by BCD modification routines, such as DAA. To supplement this is an h (Half Carry) flag which stores if there was carry/borrow on the low nibble. DAA did not function properly on the 8080 and 8085. To correct this a special bit was added to the Z80, n (Add/Subtract flag), which is set by subtract operations and cleared by add operations. For subtract instructions, c (Carry) and h (Half Carry) are set to 1 for borrow and 0 for no borrow. When listing two operands in Z80 assembly, the first operand is the destination operand and the second operand is the source, similar to the x86s but opposite of the 68Ks. Something confusing about the documentation of the Z80 is it uses the word "cycle" to mean a full internal operation (such as loading a value from memory, doing arithmetic, etc.) and these are called M (machine cycle) whereas a "clock" is a tick in the CPU for an amount of actual time and these are called T (time clock). Other documentation uses the word "state" in place of "clock". As far as this document goes, a clock and a cycle are the same thing, 1 cycle of the Hz rating of the CPU (a 4MHz computer has 4 million cycles per second). Since most "fast" opcodes take four cycles each, a 4MHz Z80 will run at 1MIPS (Million Instructions Per Second). ___________________________________________________________________________________________________ 7.2 Quirks/Bugs An anonymous note on the Z80: "Hey another thing you may wish to consider mentioning are the bugs in the NMOS version of the CPU. One of them is with regard to the buggy IFF2->parity flag performance in the LD A,I and LD A,R instructions. An error can occur when an INTACK runs near these instructions: the parity flag will be showing 0 when it should have been 1. A Zilog app. note is around somewhere talking about this. It's a rather nasty bug for embeddedaapps... There are I think a few others." KERBLUH - mention what happens with the undocumented opcodes Z80s *************************************************************************************************** A1 Miscellaneous Notes and Issues Z80 assemblers support $+ or $- for relative jumps, such as JR $+4 to jump ahead four bytes. However, the assembler will use the position of the opcode for the relative amount whereas the processor itself uses the position of the FOLLOWING opcode. JR $+2 tells the assembler to jump 2 bytes relative to the beginning of the opcode itself. This essentially places PC just after the opcode (since it's a 2 byte opcode) because what really is passed to the processor is an offset of zero. The documentation states that the offset is -126 to +129 bytes from the beginning of the opcode, BUT it's stored as if it was -128 to +127 bytes from the beginning of the next opcode. In my documentation, whether or not the processor truly subtracts 2 from the value before adding to PC or if it actually does add to PC after the opcode is beside the point, I'm going to assume the processor isn't stupid and is simply adding a sign-extended byte to PC AFTER the opcode. Opcode E9, JP HL, is normally listed as JP (HL) in the documentation I've come across, but it does not actually access the memory at HL. Instead, it sets PC to HL. Therefore, I believe that JP HL is a correct representation, and from seeing other documentation by Z80 assemblers, I'm not alone in this belief. The same is true for DD E9 (JP IX) and FD E9 (JP IY). In general documentation, SUB is without A (it's implied), however ADD, ADC and SBC all list A as the first operand. Because this makes no sense to me, SUB is always listed with A as the first operand even if it is redundant. I honestly would like to do this with all math/logic/bitwise mnemonics that have A implied... *************************************************************************************************** A2 List of computers/game systems that used these processors 8080: MITS Altair 8800 8085: Z80: Colecovision Commodore 128 (for running CP/M programs) SEGA Master System SEGA Game Gear SEGA Genesis (sound chip) SNK Neo Geo (sound chip) TI graphic calculators (??? need a list) TRS-80 (Tandy Radio Shack) Sinclair ZX series Z80 (modified): Nintendo Gameboy Nintendo Gameboy Color *************************************************************************************************** A3 TO DO List o Finish documenting the illegal opcodes o Get better information on the 8080 and 8085. . I have the opcodes and mnemonics, as well as timing and descriptions, but no information on the interrupt model of the 8085 and if the RIM and SIM instructions are any indication, it's a bit unique. . Need to know what happens on interrupt for the 8085. . Need to document the RIM and SIM instructions for the 8085 . Also need to get PIN information on the 8085 o Get information for the Z180, Z280, Z380 and any other Z80 Family processors *************************************************************************************************** A4 Updates List v0.1 2006-12-30 to ??? Original Version *************************************************************************************************** A5 8080 to Z80 mnemonic translations NOTE: I use SUB A, r whereas most other Z80 documentation will use just SUB r. I think this is a mistake since SBC, ADD and ADC all use the A even when it's implied. The RIM and SIM instructions of the 8085 are described above in the Mnemonics listing. 8080 Z80 Equivalent 8080 Mnemonic Meaning ACI imm8 ADC A, imm8 Add with Carry and Immediate ADC r ADC A, r ADd register with Carry ADC M ADC A, (HL) ADd memory with Carry ADD r ADD A, r ADD register ADD M ADD A, (HL) ADD memory ADI imm8 ADD A, imm8 ADd Immediate ANA r AND r ANd Accumulator with register ANA M AND (HL) ANd Accumulator with memory ANI imm8 AND imm8 ANd accumulator with Immediate CALL add16 CALL addr16 CALL subroutine (No Change) Ccond addr16 CALL cond, addr16 Call on condition CMA CPL CoMplement Accumulator CMC CCF CoMplement Carry CMP r CP r CoMPare accumulator with register CMP M CP (HL) CoMPare accumulator with memory CPI imm8 CP imm8 ComPare accumulator with Immediate DAA DAA Decimal Adjust Accumulator (No Change) DAD dd ADD HL, dd Double byte ADd DCR r DEC r DEcRement register DCR M DEC (HL) DEcRement memory DCX dd DEC dd DeCrement eXtended DI DI Disable Interrupts (No Change) EI EI Enable Interrupts (No Change) HLT HALT HaLT IN port8 IN A, (port8) INput from hardware INR r INC r INcRement register INR M INC (HL) INcRement memory INX dd INC dd INcrement eXtended Jcond addr16 JP cond, addr16 Jump on condition JMP addr16 JP addr16 JuMP LDA addr16 LD A, (nn) LoaD Accumulator LDAX B LD A, (BC) LoaD Accumulator (no clue what the X means, eXtended address??) LDAX D LD A, (DE) LoaD Accumulator (no clue what the X means, eXtended address??) LHLD addr16 LD HL, (nn) Load H and L Direct LXI dd, imm16 LD dd, imm16 Load eXtended Immediate MOV r1, r2 LD r1, r2 MOVe register MOV r, M LD r, (HL) MOVe from memory MOV M, r LD (HL), r MOVe to memory MVI r, imm8 LD r, imm8 MoVe Immediate MVI M, imm8 LD (HL), imm8 MoVe Immediate NOP NOP No OPeration (No Change) ORA r OR r OR Accumulator with register ORA M OR (HL) OR Accumulator with memory ORI imm8 OR imm8 OR accumulator with Immediate OUT port8 OUT (port8), A OUTput to hardware PCHL JP HL load PC from HL POP df POP df POP value from stach (No Change) POP PSW POP AF POP program status word PUSH df PUSH df PUSH value onto stack (No Change) PUSH PSW PUSH AF PUSH processor status word RAL RLA Rotate Accumulator Left through carry RLC RLCA Rotate accumulator Left and into Carry RAR RRA Rotate Accumulator Right through carry RET RET RETurn from subroutine (No Change) Rcond RET cond Return from subroutine on condition RRC RRCA Rotate accumulator Right and into Carry RST n RST n ReSTart (No Change) SBB r SBC A, r SuBtract register with Borrow SBB M SBC A, (HL) SuBtract memory with Borrow SBI imm8 SBI A, imm8 Subtract with Borrow and Immediate SHLD addr16 LD (nn), HL Store H and L Direct SPHL LD SP, HL load SP with HL STA addr16 LD (nn), A STore Accumulator STAX B LD (BC), A STore Accumulator (no clue what the X means, eXtended address??) STAX D LD (DE), A STore Accumulator (no clue what the X means, eXtended address??) STC SCF SeT Carry SUB r SUB A, r SUBtract register SUB M SUB A, (HL) SUBtract memory SUI imm8 SUB A, imm8 SUbtract Immediate XCHG EX DE, HL eXCHanGe XRA r XOR r eXclusive oR Accumulator with register XRA M XOR (HL) eXclusive oR Accumulator with memory XRI imm8 XOR imm8 eXclusive oR accumulator with Immediate XTHL EX (SP), HL eXchange stack Top with HL *************************************************************************************************** Sources Information Sources [1] Z80 CPU User Manual http://www.zilog.com/ (c) March 2005, ZiLOG Inc * Used to gather processor details and information. The ZiLOG manuals are the only ones I could find that actually explained what anything meant on the Z80 processors. [2] Decoding Z80 Opcodes, Revision 2 (c) ???, Cristian Dinu * Used to determine how the Z80 instructions are constructed. [3] Clock Cycles for Z80 Opcodes (c) March 24, 1996, Oscar Lindberg * The charts in this file were very useful to help me see how opcodes were organized and to cross-compare with other documents in sections where there were discrepencies. [4] The Undocumented Z80 Documented, v0.91 http://www.myquest.nl/z80undocumented/ (c) September 18, 2005, Sean Young and Jan Wilmans * Provided TONS of useful information that the ZiLOG documentation did not, such as the existence of the x and y flags and how they function. Everything dealing with the x and y flags comes from this document, though the information was cross-compared with other documents. Also used for most of the undocumented features. [5] 8080A/8085A Instruction Set Chapter 5 of an 8080A/8085A document. Original document's name is unknown (c) 1976, Intel Corporation * Provided full information about the 8080/8085 processors. Used to get pretty much all the information for registers and instructions to compare with the Z80 data. [6] Intel 8080 Data Sheet (c) ???, Intel Corporation * Used to get detailed pin and timing information as well as breakdowns on what the processor does with every opcode and information on the temporary registers.