_F_r_o_m _N_O_R_T_H_E_R_N _B_Y_T_E_S _- _V_o_l_u_m_e _3 _N_u_m_b_e_r _1_0 _(_O_c_t_. _'_8_2_) UNDOCUMENTED Z-80 OPCODES by Bill Smythe is reprinted from the CHICATRUG NEWS (Chicago TRS-80 Users' Group). NORTHERN BYTES editor's note: This is the most comprehensive article that I have seen to date covering this subject! If you are willing to set aside your Editor/Assembler for a while and take a direct look at the Z-80 opcodes, certain patterns will become apparent. For example, of the 256 possible opcodes (00 through FF) all but four are in use as one-byte instructions. Some of these stand alone; others are followed by one- or two-byte operands. For example: 13 INC DE (no operand) 3E nn LD A,nn (1-byte operand) 10 dd DJNZ dd (1-byte operand) 01 nn mm LD BC,mmnn (2-byte operand) The four missing opcodes are CB, DD, ED, and FD. These serve as "escape codes" to alert the Z-80 that a two-byte instruction is coming up. Examples: CB C0 SET 0,B DD 21 nn mm LD IX,mmnn ED 80 LDIR FD 2B DEC IY Like the one-byte instructions, some two-byters are used with operands, while others stand alone. One of the first observations made by any Z-80 hacker is the parallel among HL, IX, and IY instructions: 21 nn mm LD HL,mmnn DD 21 nn mm LD IX,mmnn FD 21 nn mm LD IY,mmnn 77 LD (HL),A DD 77 jj LD (IX+jj),A FD 77 jj LD (IY+jj),A Almost any instruction referring to HL can be changed to the corresponding instruction for IX or IY by prefixing DD or FD, respectively. When HL appears in parentheses, it becomes (IX+jj) or (IY+jj), where the index jj appears in the opcode as the second byte following the DD or FD. Meanwhile, the two-byte opcodes beginning with CB form an orderly set of shift, rotate, set, reset, and bit-test instructions, while the relatively disorganized ED set performs a variety of useful tasks. And then there are the combined prefixes DDCB and FDCB. Their relationship to the CB codes are pretty much what you would expect: CB 46 BIT 0,(HL) DD CB jj 46 BIT 0,(IX+jj) FD CB jj 46 BIT 0,(IY+jj) _T_h_e _F_u_n _B_e_g_i_n_s Everything said so far is pretty much common knowledge, well-documented by Zilog, the Z-80 manufacturer. But what happens when DD or FD is prefixed to an instruction not containing HL? 37 SCF C3 nn mm JP mmnn DD 37 ????? FD C3 nn mm ????? As far as I can determine, the prefixes in these cases have no effect. The two instructions shown here continue to function as SCF and JP mmnn, respectively. But what if the instruction deals with either H or L, but not HL? 24 INC H 2E nn LD L,nn Just as the register pair HL is made up of two registers, H and L, it appears that the 16-bit IX register consists of two 8-bit registers, which I shall call HX and LX. Similarly for IY. The above instructions become: DD 24 INC HX DD 2E nn LD LX,nn FD 24 INC HY FD 2E nn LD LY,nn The last instruction, for example, loads the low-order half of the IY register with the value nn while leaving the high-order half untouched. If, however, an instruction contains both H and (HL), or both L and (HL), then only the (HL) part is affected by the addition of DD or FD: 66 LD H,(HL) DD 66 jj LD H,(IX+jj) FD 66 jj LD H,(IY+jj) Adding a second DD or FD in front has no additional effect. Apparently, there are no such instructions as LD HX,(IX+jj) or LD HY,(IY+jj). _W_h_a_t_'_s _Y_o_u_r _C_B _H_a_n_d_l_e_? The CB instructions are divided into four groups: CB00 through CB3F: rotate and shift group CB40 through CB7F: BIT testing CB08 through CBBF: RESet group CBC0 through CBFF: SET group Of these four groups, all seem complete except for the first. The first group is divided into eight subgroups of eight instructions each: CB00-CB07: RLC (rotate left circular) CB08-CB0F: RRC (rotate right circular) CB10-CB17: RL (rotate left through carry) CB18-CB1F: RR (rotate right through carry) CB20-CB27: SLA (shift left arithmetic) CB28-CB2F: SRA (shift right arithmetic) CB30-CB37: ??????? CB38-CB3F: SRL (shift right logical) The missing CB30 group looks as though it ought to be a shift left logical, whatever that is. Trouble is, SLA (shift left arithmetic) is already pretty logical. So what's left for SLL to do? As might be expected, SLL shifts bits 0 through 6 leftward into bits 1 through 7, while bit 7 goes into the carry flag. But then comes the surprise -- bit 0 is set. Yes, Virginia, regardless of the previous status of any bit, or of any flag, bit 0 is turned on. Thus SLL, in effect, multiplies by 2 and adds 1. As with the other CB instructions, the affected register is B, C, D, E, H, L, (HL), or A depending on which instruction, CB30 through CB37, is used. _C_o_m_b_i_n_a_t_i_o_n_s _a_n_d _M_o_r_e _C_o_m_b_i_n_a_t_i_o_n_s Of the combined opcodes, DDCBjjxx and FDCBjjxx, only every eighth one is documented by Zilog: DD CB jj 06 RLC (IX+jj) DD CB jj 0E RRC (IX+jj) (etc.) One might not expect much from those not on the list, since the corresponding DD-less CB instructions have nothing to do with HL. Not so, however -- a lot of weird stuff is going on here: DD CB jj 00 RLC B,(IX+jj) DD CB jj 01 RLC C,(IX+jj) DD CB jj 02 RLC D,(IX+jj) DD CB jj 03 RLC E,(IX+jj) DD CB jj 04 RLC H,(IX+jj) DD CB jj 05 RLC L,(IX+jj) DD CB jj 06 DD CB jj 07 RLC A,(IX+jj) -- and similarly for RRC, RL, RR, SLA, SRA, SLL, and SRL. But what does that mean, "RLC B,(IX+jj)"? THat's just a name I chose for a peculiar phenomenon in which (IX+jj) is rotated left cirular, then copied into B. In other words, RLC B,(IX+jj) is like RLC (IX+jj) followed by LD B,(IX+jj). The SET and RESet instructions are even more curious: DD CB jj 80 RES B,0,(IX+jj) DD CB jj 81 RES C,0,(IX+jj) DD CB jj 82 RES D,0,(IX+jj) DD CB jj 83 RES E,0,(IX+jj) DD CB jj 84 RES H,0,(IX+jj) DD CB jj 85 RES L,0,(IX+jj) DD CB jj 86 DD CB jj 87 RES A,0,(IX+jj) I don't know how many Editor/Assemblers could handle 3 operands, even if they recognized undocumented opcodes. I couldn't think of any other way to express what happens -- (IX+jj) first has bit 0 reset, then is copied into the indicated register (e.g. B). The action is equivalent to RES 0,(IX+jj) followed by LD B,(IX+jj). Of course, the same can be done with bits 1 through 7, with SET as well as RESet, and with IY as well as IX. The BIT instructions are less interesting. Undocumented codes DDCBjj40 through DDCBjj47 turn out to be equivalent to the documented version. No copying into registers B, C, D, etc. is done: DD CB jj 40 BIT 0,(IX+jj) DD CB jj 41 BIT 0,(IX+jj) DD CB jj 42 BIT 0,(IX+jj) DD CB jj 43 BIT 0,(IX+jj) DD CB jj 44 BIT 0,(IX+jj) DD CB jj 45 BIT 0,(IX+jj) DD CB jj 46 BIT 0,(IX+jj) DD CB jj 47 BIT 0,(IX+jj) _L_o_t_s _o_f _R_o_o_m _f_o_r _M_o_r_e My investigations into the ED group yielded little of interest. There were some duplications; for example, the eight instructions ED44, ED4C, ED54, ED5C, ED64, ED6C, ED74, ED7C all turned out to be NEG, even though only the first is documented as such. I also found duplicates for RETN, RETI, IM 0, IM 1, and IM 2. There were also a couple of "expected" duplicates: ED 63 nn mm LD (mmnn),HL ED 6B nn mm LD HL,(mmnn) -- but these instructions already exist, and execute faster, in the non-ED set. The ED group did provide a couple of lone curiosities: ED 70 IN --,(C) ED 71 OUT (C),-- These appear where you would expect the "missing" IN (HL),(C) and OUT (C),(HL). Nothing happens with (HL), though. IN --,(C) appears to function like IN A,(C), IN B,(C), etc., except that the result does not go anywhere. The flags, however, are set as expected. OUT (C),-- seems to output a zero to the port. I could not detect any action for the first and fourth quarters of the ED set, ED00-ED3F and EDC0=EDFF. Three-fourths of the third quarter is also "missing", as are two instructions in the second quarter, ED77 and ED7F. This leaves room for 178 more instructions -- anyone for an upgrade? I'd like to see instructions like LD B,(DE) and CP (DE) and SUB (DE). _E_X_C_E_P_T_I_O_N_S I said that any HL instruction could be changed to IX or IY by simply prefixing DD or FD. That was a little white lie. The following instructions are not convertible because they begin with ED: ED 42 SBC HL,BC ED 4A ADC HL,BC ED 52 SBC HL,DE ED 5A ADC HL,DE ED 62 SBC HL,HL ED 6A ADC HL,HL ED 72 SBC HL,SP ED 7A ADC HL,SP ED 67 RRD ED 6F RLD In addition, the following instructions cannot be converted even though they are one-byters: D9 EXX EB EX DE,HL -- and the JP (HL) instruction becomes JP (IX) or JP (IY), not JP (IX+jj) or JP (IY+jj): E9 JP (HL) DD E9 JP (IX) FD E9 JP (IY) _O_n_e _a_t _a _t_i_m_e_, _P_l_e_a_s_e Except for DDCB and FDCB, there is no benefit in combining two or more of the four escape codes. There are three cases: (1) In the event of multiple DDs and/or FDs, all but the last will be ignored. (2) EDCB, EDDD, EDED, and EDFD will be ignored entirely since they lie in the inoperative fourth quarter of the ED set. (3) If either DD or FD precedes ED, the former will be ignored. _A _W_o_r_d _o_f _C_a_u_t_i_o_n To any machine-language programmers whose appetites may have been whetted: Most Z-80 Editor/Assemblers do not recognize undocumented opcodes, so you'll have to enter these codes as DEFBs. More important, it is conceivable that not all Z-80s will respond to these codes in the same way. If you plan to sell your programs, the best advice is not to use undocumented instructions. _S_u_m_m_a_r_y _o_f _U_s_e_f_u_l _U_n_d_o_c_u_m_e_n_t_e_d _Z_-_8_0 _O_p_c_o_d_e_s DD24 INC HX DD62 LD HX,D DD8C ADC A,HX DD25 DEC HX DD63 LD HX,E DD8D ADC A,LX DD26 nn LD HX,nn DD64 LD HX,HX DD94 SUB HX DD2C INC LX DD65 LD HX,LX DD95 SUB LX DD2D DEC LX DD67 LD HX,A DD9C SBC A,HX DD2E nn LD LX,nn DD68 LD LX,B DD9D SBC A,LX DD44 LD B,HX DD69 LD LX,C DDA4 AND HX DD45 LD B,LX DD6A LD LX,D DDA5 AND LX DD4C LD C,HX DD6B LD LX,E DDAC XOR HX DD4D LD C,LX DD6C LD LX,HX DDAD XOR LX DD54 LD D,HX DD6D LD LX,LX DDB4 OR HX DD55 LD D,LX DD6F LD LX,A DDB5 OR LX DD5C LD E,LX DD7C LD A,HX DDBC CP HX DD5D LD E,LX DD7D LD A,LX DDBD CP LX DD60 LD HX,B DD84 ADD A,HX DD61 LD HX,C DD85 ADD A,LX The corresponding instructions for HY and LY may be obtained by using FD in place of DD. CB30 SLL B CB34 SLL H CB31 SLL C CB35 SLL L CB32 SLL D CB36 SLL (HL) CB33 SLL E CB37 SLL A DDCBjj00-DDCBjj07 RLC r,(IX+jj) DDCBjj00-DDCBjj0F RRC r,(IX+jj) DDCBjj10-DDCBjj17 RL r,(IX+jj) DDCBjj18-DDCBJJ1F RR r,(IX+jj) DDCBjj20-DDCBjj27 SLA r,(IX+jj) DDCBjj28-DDCBjj2F SRL r,(IX+jj) DDCBjj30-DDCBjj37 SLL r,(IX+jj) DDCBjj38-DDCBjj3F SRL r,(IX+jj) DDCBjj80-DDCBjj87 RES r,0,(IX+jj) DDCBjj88-DDCBjj8F RES r,1,(IX+jj) DDCBjj90-DDCBjj97 RES r,2,(IX+jj) DDCBjj98-DDCBjj9F RES r,3,(IX+jj) DDCBjjA0-DDCBjjA7 RES r,4,(IX+jj) DDCBjjA8-DDCBjjAF RES r,5,(IX+jj) DDCBjjB0-DDCBjjB7 RES r,6,(IX+jj) DDCBjjB8-DDCBjjBF RES r,7,(IX+jj) DDCBjjC0-DDCBjjC7 SET r,0,(IX+jj) DDCBjjC8-DDCBjjCF SET r,1,(IX+jj) DDCBjjD0-DDCBjjD7 SET r,2,(IX+jj) DDCBjjD8-DDCBjjDF SET r,3,(IX+jj) DDCBjjE0-DDCBjjE7 SET r,4,(IX+jj) DDCBjjE8-DDCBjjEF SET r,5,(IX+jj) DDCBjjF0-DDCBjjF7 SET r,6,(IX+jj) DDCBjjF8-DDCBjjFF SET r,7,(IX+jj) In the last 3 tables, the corresponding instructions for (IY+jj) may be obtained by using FD in place of DD. The value of r is determined as follows: Last digit of opcode: register r: 0 or 8 B 1 or 9 C 2 or A D 3 or B E 4 or C H 5 or D L 6 or E (blank) 7 or F A