Document Title: [Z80undoc.txt (text file)]
_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 <documented, as above>
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 <documented: RES 0,(IX+jj)>
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) <documented>
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 <rotate right decimal (HL)>
ED 6F RLD <rotate left decimal (HL)>
In addition, the following instructions cannot be
converted even though they are one-byters:
D9 EXX <exchange all registers>
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
}