struct / union in initializer, RFE #901.
[sdcc.git] / sdcc-extra / emu / rrz80 / disasm.cc
blob3e0e334a845a6b3dd8d7ae33563a5ce7974e64ea
1 /*
2 * mon_z80.cpp - Z80 disassembler
4 * cxmon (C) 1997-2000 Christian Bauer, Marc Hellwig
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* Hacked by Michael Hope <michaelh@juju.net.nz> into rrgb. */
22 //#include "sysdeps.h"
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "types.h"
29 extern "C" uint8 mon_read_byte(uint32 addr);
31 //#include "mon.h"
32 //#include "mon_disass.h"
35 // Addressing modes
36 enum {
37 A_IMPL,
38 A_IMM8, // xx
39 A_IMM16, // xxxx
40 A_ABS8, // (xx)
41 A_ABS16, // (xxxx)
42 A_REL, // relative
43 A_A, // a
44 A_HL, // hl or ix or iy
45 A_SP, // sp
46 A_REG1, // 8-bit register (bits 0..2 of opcode) or (hl)/(ix+d)/(iy+d)
47 A_REG1X, // 8-bit register (bits 0..2 of opcode) or (hl)/(ix+d)/(iy+d), don't substitute h or l on prefixes
48 A_REG2, // 8-bit register (bits 3..5 of opcode) or (hl)/(ix+d)/(iy+d)
49 A_REG2X, // 8-bit register (bits 3..5 of opcode) or (hl)/(ix+d)/(iy+d), don't substitute h or l on prefixes
50 A_REG3, // 16-bit register (bits 4..5 of opcode) bc/de/hl/sp
51 A_REG4, // 16-bit register (bits 4..5 of opcode) bc/de/hl/af
52 A_COND, // condition code (bits 3..5 of opcode)
53 A_COND2, // condition code (bits 3..4 of opcode)
54 A_BIT, // bit number (bits 3..5 of opcode)
55 A_RST, // restart
56 A_BC_IND, // (bc)
57 A_DE_IND, // (de)
58 A_HL_IND, // (hl) or (ix) or (iy)
59 A_SP_IND, // (sp)
60 A_DE_HL, // de,hl
61 A_AF_AF // af,af'
64 // Mnemonics
65 enum {
66 M_ADC, M_ADD, M_AND, M_BIT, M_CALL, M_CCF, M_CP, M_CPD, M_CPDR, M_CPI,
67 M_CPIR, M_CPL, M_DAA, M_DEC, M_DI, M_DJNZ, M_EI, M_EX, M_EXX, M_HALT,
68 M_IM0, M_IM1, M_IM2, M_IN, M_INC, M_IND, M_INDR, M_INI, M_INIR, M_JP,
69 M_JR, M_LD, M_LDD, M_LDDR, M_LDI, M_LDIR, M_NEG, M_NOP, M_OR, M_OTDR,
70 M_OTIR, M_OUT, M_OUTD, M_OUTI, M_POP, M_PUSH, M_RES, M_RET, M_RETI,
71 M_RETN, M_RL, M_RLA, M_RLC, M_RLCA, M_RLD, M_RR, M_RRA, M_RRC, M_RRCA,
72 M_RRD, M_RST, M_SBC, M_SCF, M_SET, M_SL1, M_SLA, M_SRA, M_SRL, M_SUB,
73 M_XOR,
74 M_ILLEGAL,
76 M_MAXIMUM
79 // Chars for each mnemonic
80 static const char mnem_1[] = "aaabccccccccddddeeehiiiiiiiiijjlllllnnoooooopprrrrrrrrrrrrrrrssssssssx?";
81 static const char mnem_2[] = "ddniacppppppaeijixxammmnnnnnnprdddddeorttuuuoueeeelllllrrrrrsbcellrruo ";
82 static const char mnem_3[] = "cddtlf ddiilac n xl cddii ddiigp ditttpssttt accd accdtcft1aalbr ";
83 static const char mnem_4[] = " l r r z t012 r r r r rr di h in a a ";
85 // Mnemonic for each opcode
86 static const char mnemonic[256] = {
87 M_NOP , M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_RLCA, // 00
88 M_EX , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_RRCA,
89 M_DJNZ, M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_RLA , // 10
90 M_JR , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_RRA ,
91 M_JR , M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_DAA , // 20
92 M_JR , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_CPL ,
93 M_JR , M_LD , M_LD , M_INC , M_INC , M_DEC , M_LD , M_SCF , // 30
94 M_JR , M_ADD, M_LD , M_DEC , M_INC , M_DEC , M_LD , M_CCF ,
95 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , // 40
96 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD ,
97 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , // 50
98 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD ,
99 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , // 60
100 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD ,
101 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_HALT, M_LD , // 70
102 M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD , M_LD ,
103 M_ADD , M_ADD, M_ADD, M_ADD , M_ADD , M_ADD , M_ADD , M_ADD , // 80
104 M_ADC , M_ADC, M_ADC, M_ADC , M_ADC , M_ADC , M_ADC , M_ADC ,
105 M_SUB , M_SUB, M_SUB, M_SUB , M_SUB , M_SUB , M_SUB , M_SUB , // 90
106 M_SBC , M_SBC, M_SBC, M_SBC , M_SBC , M_SBC , M_SBC , M_SBC ,
107 M_AND , M_AND, M_AND, M_AND , M_AND , M_AND , M_AND , M_AND , // a0
108 M_XOR , M_XOR, M_XOR, M_XOR , M_XOR , M_XOR , M_XOR , M_XOR ,
109 M_OR , M_OR , M_OR , M_OR , M_OR , M_OR , M_OR , M_OR , // b0
110 M_CP , M_CP , M_CP , M_CP , M_CP , M_CP , M_CP , M_CP ,
111 M_RET , M_POP, M_JP , M_JP , M_CALL, M_PUSH , M_ADD , M_RST , // c0
112 M_RET , M_RET, M_JP , M_ILLEGAL, M_CALL, M_CALL , M_ADC , M_RST ,
113 M_RET , M_POP, M_JP , M_OUT , M_CALL, M_PUSH , M_SUB , M_RST , // d0
114 M_RET , M_EXX, M_JP , M_IN , M_CALL, M_ILLEGAL, M_SBC , M_RST ,
115 M_RET , M_POP, M_JP , M_EX , M_CALL, M_PUSH , M_AND , M_RST , // e0
116 M_RET , M_JP , M_JP , M_EX , M_CALL, M_ILLEGAL, M_XOR , M_RST ,
117 M_RET , M_POP, M_JP , M_DI , M_CALL, M_PUSH , M_OR , M_RST , // f0
118 M_RET , M_LD , M_JP , M_EI , M_CALL, M_ILLEGAL, M_CP , M_RST
121 // Source/destination addressing modes for each opcode
122 #define A(d,s) (((A_ ## d) << 8) | (A_ ## s))
124 static const short adr_mode[256] = {
125 A(IMPL,IMPL) , A(REG3,IMM16) , A(BC_IND,A) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 00
126 A(AF_AF,IMPL) , A(HL,REG3) , A(A,BC_IND) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) ,
127 A(REL,IMPL) , A(REG3,IMM16) , A(DE_IND,A) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 10
128 A(REL,IMPL) , A(HL,REG3) , A(A,DE_IND) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) ,
129 A(COND2,REL) , A(REG3,IMM16) , A(ABS16,HL) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 20
130 A(COND2,REL) , A(HL,REG3) , A(HL,ABS16) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) ,
131 A(COND2,REL) , A(REG3,IMM16) , A(ABS16,A) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) , // 30
132 A(COND2,REL) , A(HL,REG3) , A(A,ABS16) , A(REG3,IMPL) , A(REG2,IMPL) , A(REG2,IMPL) , A(REG2,IMM8) , A(IMPL,IMPL) ,
133 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , // 40
134 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) ,
135 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , // 50
136 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) ,
137 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) , // 60
138 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) ,
139 A(REG2,REG1X) , A(REG2,REG1X) , A(REG2,REG1X), A(REG2,REG1X), A(REG2,REG1X), A(REG2,REG1X), A(IMPL,IMPL) , A(REG2,REG1X), // 70
140 A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2,REG1) , A(REG2X,REG1), A(REG2,REG1) ,
141 A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , // 80
142 A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) ,
143 A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , // 90
144 A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) , A(A,REG1) ,
145 A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , // a0
146 A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) ,
147 A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , // b0
148 A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) , A(REG1,IMPL) ,
149 A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(IMM16,IMPL), A(COND,IMM16), A(REG4,IMPL) , A(A,IMM8) , A(RST,IMPL) , // c0
150 A(COND,IMPL) , A(IMPL,IMPL) , A(COND,IMM16), A(IMPL,IMPL) , A(COND,IMM16), A(IMM16,IMPL), A(A,IMM8) , A(RST,IMPL) ,
151 A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(ABS8,A) , A(COND,IMM16), A(REG4,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , // d0
152 A(COND,IMPL) , A(IMPL,IMPL) , A(COND,IMM16), A(A,ABS8) , A(COND,IMM16), A(IMPL,IMPL) , A(A,IMM8) , A(RST,IMPL) ,
153 A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(SP_IND,HL) , A(COND,IMM16), A(REG4,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , // e0
154 A(COND,IMPL) , A(HL_IND,IMPL), A(COND,IMM16), A(DE_HL,IMPL), A(COND,IMM16), A(IMPL,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) ,
155 A(COND,IMPL) , A(REG4,IMPL) , A(COND,IMM16), A(IMPL,IMPL) , A(COND,IMM16), A(REG4,IMPL) , A(IMM8,IMPL) , A(RST,IMPL) , // f0
156 A(COND,IMPL) , A(SP,HL) , A(COND,IMM16), A(IMPL,IMPL) , A(COND,IMM16), A(IMPL,IMPL) , A(IMM8,IMPL) , A(RST,IMPL)
161 * sprintf into a "stream"
164 struct SFILE {
165 char *buffer;
166 char *current;
169 static int mon_sprintf(SFILE *f, const char *format, ...)
171 int n;
172 va_list args;
173 va_start(args, format);
174 vsprintf(f->current, format, args);
175 f->current += n = strlen(f->current);
176 va_end(args);
177 return n;
182 * Disassemble one instruction, return number of bytes
185 static const char *reg_name[] = {"b", "c", "d", "e", "h", "l", "*", "a"};
186 static const char *reg_name_ix[] = {"b", "c", "d", "e", "hx", "lx", "*", "a"}; // undoc
187 static const char *reg_name_iy[] = {"b", "c", "d", "e", "hy", "ly", "*", "a"}; // undoc
188 static const char *reg_name_16[] = {"bc", "de", "hl", "sp"};
189 static const char *reg_name_16_2[] = {"bc", "de", "hl", "af"};
190 static const char *cond_name[] = {"nz", "z", "nc", "c", "po", "pe", "p", "m"};
192 static void operand(SFILE *f, char mode, uint32 &adr, uint8 op, bool ix, bool iy)
194 switch (mode) {
195 case A_IMPL:
196 break;
198 case A_IMM8:
199 mon_sprintf(f, "$%02x", mon_read_byte(adr)); adr++;
200 break;
202 case A_IMM16:
203 mon_sprintf(f, "$%04x", (mon_read_byte(adr + 1) << 8) | mon_read_byte(adr)); adr += 2;
204 break;
206 case A_ABS8:
207 mon_sprintf(f, "($%02x)", mon_read_byte(adr)); adr++;
208 break;
210 case A_ABS16:
211 mon_sprintf(f, "($%04x)", (mon_read_byte(adr + 1) << 8) | mon_read_byte(adr)); adr += 2;
212 break;
214 case A_REL:
215 mon_sprintf(f, "$%04x", (adr + 2 + (int8)mon_read_byte(adr)) & 0xffff); adr++;
216 break;
218 case A_A:
219 mon_sprintf(f, "a");
220 break;
222 case A_HL:
223 mon_sprintf(f, ix ? "ix" : (iy ? "iy" : "hl"));
224 break;
226 case A_SP:
227 mon_sprintf(f, "sp");
228 break;
230 case A_REG1:
231 case A_REG1X: {
232 int reg = op & 7;
233 if (reg == 6) {
234 if (ix || iy) {
235 mon_sprintf(f, "(%s+$%02x)", ix ? "ix" : "iy", mon_read_byte(adr)); adr++;
236 } else
237 mon_sprintf(f, "(hl)");
238 } else if (mode == A_REG1)
239 mon_sprintf(f, "%s", ix ? reg_name_ix[reg] : (iy ? reg_name_iy[reg] : reg_name[reg]));
240 else
241 mon_sprintf(f, "%s", reg_name[reg]);
242 break;
245 case A_REG2:
246 case A_REG2X: {
247 int reg = (op >> 3) & 7;
248 if (reg == 6) {
249 if (ix || iy) {
250 mon_sprintf(f, "(%s+$%02x)", ix ? "ix" : "iy", mon_read_byte(adr)); adr++;
251 } else
252 mon_sprintf(f, "(hl)");
253 } else if (mode == A_REG2)
254 mon_sprintf(f, "%s", ix ? reg_name_ix[reg] : (iy ? reg_name_iy[reg] : reg_name[reg]));
255 else
256 mon_sprintf(f, "%s", reg_name[reg]);
257 break;
260 case A_REG3:
261 mon_sprintf(f, reg_name_16[(op >> 4) & 3]);
262 break;
264 case A_REG4:
265 mon_sprintf(f, reg_name_16_2[(op >> 4) & 3]);
266 break;
268 case A_COND:
269 mon_sprintf(f, cond_name[(op >> 3) & 7]);
270 break;
272 case A_COND2:
273 mon_sprintf(f, cond_name[(op >> 3) & 3]);
274 break;
276 case A_BIT:
277 mon_sprintf(f, "%d", (op >> 3) & 7);
278 break;
280 case A_RST:
281 mon_sprintf(f, "$%02x", op & 0x38);
282 break;
284 case A_BC_IND:
285 mon_sprintf(f, "(bc)");
286 break;
288 case A_DE_IND:
289 mon_sprintf(f, "(de)");
290 break;
292 case A_HL_IND:
293 mon_sprintf(f, ix ? "(ix)" : (iy ? "(iy)" : "(hl)"));
294 break;
296 case A_SP_IND:
297 mon_sprintf(f, "(sp)");
298 break;
300 case A_DE_HL:
301 mon_sprintf(f, "de,hl");
302 break;
304 case A_AF_AF:
305 mon_sprintf(f, "af,af'");
306 break;
310 static int print_instr(SFILE *f, int mnem, char dst_mode, char src_mode, uint32 adr, uint8 op, bool ix, bool iy)
312 uint32 orig_adr = adr;
314 // Print mnemonic
315 mon_sprintf(f, "%c%c%c%c ", mnem_1[mnem], mnem_2[mnem], mnem_3[mnem], mnem_4[mnem]);
317 // Print destination operand
318 operand(f, dst_mode, adr, op, ix, iy);
320 // Print source operand
321 if (src_mode != A_IMPL)
322 mon_sprintf(f, ",");
323 operand(f, src_mode, adr, op, ix, iy);
325 return adr - orig_adr;
328 static int disass_cb(SFILE *f, uint32 adr, bool ix, bool iy)
330 int num;
332 // Fetch opcode
333 uint8 op;
334 if (ix || iy) {
335 op = mon_read_byte(adr + 1);
336 num = 2;
337 } else {
338 op = mon_read_byte(adr);
339 num = 1;
342 // Decode mnemonic and addressing modes
343 char mnem = 0, dst_mode = A_IMPL, src_mode = A_IMPL;
344 switch (op & 0xc0) {
345 case 0x00:
346 dst_mode = A_REG1;
347 switch ((op >> 3) & 7) {
348 case 0: mnem = M_RLC; break;
349 case 1: mnem = M_RRC; break;
350 case 2: mnem = M_RL; break;
351 case 3: mnem = M_RR; break;
352 case 4: mnem = M_SLA; break;
353 case 5: mnem = M_SRA; break;
354 case 6: mnem = M_SL1; break;
355 case 7: mnem = M_SRL; break;
357 break;
358 case 0x40:
359 mnem = M_BIT; dst_mode = A_BIT; src_mode = A_REG1;
360 break;
361 case 0x80:
362 mnem = M_RES; dst_mode = A_BIT; src_mode = A_REG1;
363 break;
364 case 0xc0:
365 mnem = M_SET; dst_mode = A_BIT; src_mode = A_REG1;
366 break;
369 // Print instruction
370 print_instr(f, mnem, dst_mode, src_mode, adr, op, ix, iy);
371 return num;
374 static int disass_ed(SFILE *f, uint32 adr)
376 // Fetch opcode
377 uint8 op = mon_read_byte(adr);
379 // Decode mnemonic and addressing modes
380 char mnem, dst_mode = A_IMPL, src_mode = A_IMPL;
381 switch (op) {
382 case 0x40:
383 case 0x48:
384 case 0x50:
385 case 0x58:
386 case 0x60:
387 case 0x68:
388 case 0x78:
389 mon_sprintf(f, "in\t%s,(c)", reg_name[(op >> 3) & 7]);
390 return 1;
391 case 0x70:
392 mon_sprintf(f, "in\t(c)");
393 return 1;
395 case 0x41:
396 case 0x49:
397 case 0x51:
398 case 0x59:
399 case 0x61:
400 case 0x69:
401 case 0x79:
402 mon_sprintf(f, "out\t(c),%s", reg_name[(op >> 3) & 7]);
403 return 1;
404 case 0x71: // undoc
405 mon_sprintf(f, "out\t(c),0");
406 return 1;
408 case 0x42:
409 case 0x52:
410 case 0x62:
411 case 0x72:
412 mnem = M_SBC; dst_mode = A_HL; src_mode = A_REG3;
413 break;
415 case 0x43:
416 case 0x53:
417 case 0x63:
418 case 0x73:
419 mnem = M_LD; dst_mode = A_ABS16; src_mode = A_REG3;
420 break;
422 case 0x4a:
423 case 0x5a:
424 case 0x6a:
425 case 0x7a:
426 mnem = M_ADC; dst_mode = A_HL; src_mode = A_REG3;
427 break;
429 case 0x4b:
430 case 0x5b:
431 case 0x6b:
432 case 0x7b:
433 mnem = M_LD; dst_mode = A_REG3; src_mode = A_ABS16;
434 break;
436 case 0x44:
437 case 0x4c: // undoc
438 case 0x54: // undoc
439 case 0x5c: // undoc
440 case 0x64: // undoc
441 case 0x6c: // undoc
442 case 0x74: // undoc
443 case 0x7c: // undoc
444 mnem = M_NEG;
445 break;
447 case 0x45:
448 case 0x55: // undoc
449 case 0x5d: // undoc
450 case 0x65: // undoc
451 case 0x6d: // undoc
452 case 0x75: // undoc
453 case 0x7d: // undoc
454 mnem = M_RETN;
455 break;
456 case 0x4d: mnem = M_RETI; break;
458 case 0x46:
459 case 0x4e: // undoc
460 case 0x66: // undoc
461 case 0x6e: // undoc
462 mnem = M_IM0;
463 break;
464 case 0x56:
465 case 0x76: // undoc
466 mnem = M_IM1;
467 break;
468 case 0x5e:
469 case 0x7e: // undoc
470 mnem = M_IM2;
471 break;
473 case 0x47:
474 mon_sprintf(f, "ld\ti,a");
475 return 1;
476 case 0x4f:
477 mon_sprintf(f, "ld\tr,a");
478 return 1;
479 case 0x57:
480 mon_sprintf(f, "ld\ta,i");
481 return 1;
482 case 0x5f:
483 mon_sprintf(f, "ld\ta,r");
484 return 1;
486 case 0x67: mnem = M_RRD; break;
487 case 0x6f: mnem = M_RLD; break;
489 case 0xa0: mnem = M_LDI; break;
490 case 0xa1: mnem = M_CPI; break;
491 case 0xa2: mnem = M_INI; break;
492 case 0xa3: mnem = M_OUTI; break;
493 case 0xa8: mnem = M_LDD; break;
494 case 0xa9: mnem = M_CPD; break;
495 case 0xaa: mnem = M_IND; break;
496 case 0xab: mnem = M_OUTD; break;
497 case 0xb0: mnem = M_LDIR; break;
498 case 0xb1: mnem = M_CPIR; break;
499 case 0xb2: mnem = M_INIR; break;
500 case 0xb3: mnem = M_OTIR; break;
501 case 0xb8: mnem = M_LDDR; break;
502 case 0xb9: mnem = M_CPDR; break;
503 case 0xba: mnem = M_INDR; break;
504 case 0xbb: mnem = M_OTDR; break;
506 default:
507 mnem = M_ILLEGAL;
508 break;
511 // Print instruction
512 return print_instr(f, mnem, dst_mode, src_mode, adr + 1, op, false, false) + 1;
515 static int disass(SFILE *f, uint32 adr, bool ix, bool iy)
517 uint8 op = mon_read_byte(adr);
518 if (op == 0xcb)
519 return disass_cb(f, adr + 1, ix, iy) + 1;
520 else
521 return print_instr(f, mnemonic[op], adr_mode[op] >> 8, adr_mode[op] & 0xff, adr + 1, op, ix, iy) + 1;
524 extern "C" int disass_z80(FILE *f, uint32 adr)
526 int num;
527 char buf[64];
528 SFILE sfile = {buf, buf};
530 switch (mon_read_byte(adr)) {
531 case 0xdd: // ix prefix
532 num = disass(&sfile, adr + 1, true, false) + 1;
533 break;
534 case 0xed:
535 num = disass_ed(&sfile, adr + 1) + 1;
536 break;
537 case 0xfd: // iy prefix
538 num = disass(&sfile, adr + 1, false, true) + 1;
539 break;
540 default:
541 num = disass(&sfile, adr, false, false);
542 break;
545 for (int i=0; i<4; i++) {
546 if (num > i)
547 fprintf(f, "%02x ", mon_read_byte(adr + i));
548 else
549 fprintf(f, " ");
552 fprintf(f, "\t%s", buf);
553 return num;