]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/z80-dis.c
Add support for the GBZ80 and Z80N variants of the Z80 architecture, and add DWARF...
[thirdparty/binutils-gdb.git] / opcodes / z80-dis.c
CommitLineData
6655dba2 1/* Print Z80, Z180, EZ80 and R800 instructions
b3adc24a 2 Copyright (C) 2005-2020 Free Software Foundation, Inc.
3c9b82ba
NC
3 Contributed by Arnold Metselaar <arnold_m@operamail.com>
4
9b201bb5
NC
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
3c9b82ba 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
3c9b82ba 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
3c9b82ba
NC
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
22#include "sysdep.h"
88c1242d 23#include "disassemble.h"
3c9b82ba
NC
24#include <stdio.h>
25
26struct buffer
27{
28 bfd_vma base;
29 int n_fetch;
30 int n_used;
6655dba2
SB
31 signed char data[6];
32 long inss; /* instruction set bit mask, taken from bfd_mach */
33 int nn_len; /* address length: 2 - Z80 mode, 3 - ADL mode*/
3c9b82ba
NC
34} ;
35
6655dba2 36typedef int (*func)(struct buffer *, disassemble_info *, const char *);
3c9b82ba
NC
37
38struct tab_elt
39{
40 unsigned char val;
41 unsigned char mask;
42 func fp;
6655dba2
SB
43 const char * text;
44 unsigned inss; /* bit mask of supported bfd_mach_* or 0 for all mach */
3c9b82ba
NC
45} ;
46
6655dba2
SB
47#define INSS_ALL 0
48#define INSS_Z80 ((1 << bfd_mach_z80) | (1 << bfd_mach_z80strict) | (1 << bfd_mach_z80full))
49#define INSS_R800 (1 << bfd_mach_r800)
50#define INSS_GBZ80 (1 << bfd_mach_gbz80)
51#define INSS_Z180 (1 << bfd_mach_z180)
52#define INSS_EZ80_Z80 (1 << bfd_mach_ez80_z80)
53#define INSS_EZ80_ADL (1 << bfd_mach_ez80_adl)
54#define INSS_EZ80 (INSS_EZ80_ADL | INSS_EZ80_Z80)
9fc0b501 55#define INSS_Z80N (1 << bfd_mach_z80n)
6655dba2 56
9e919b5f 57#define TXTSIZ 24
3c9b82ba 58/* Names of 16-bit registers. */
6655dba2 59static const char * rr_str[] = { "bc", "de", "hl", "sp" };
3c9b82ba 60/* Names of 8-bit registers. */
6655dba2 61static const char * r_str[] = { "b", "c", "d", "e", "h", "l", "(hl)", "a" };
3c9b82ba 62/* Texts for condition codes. */
6655dba2 63static const char * cc_str[] = { "nz", "z", "nc", "c", "po", "pe", "p", "m" };
3c9b82ba 64/* Instruction names for 8-bit arithmetic, operand "a" is often implicit */
6655dba2 65static const char * arit_str[] =
3c9b82ba
NC
66{
67 "add a,", "adc a,", "sub ", "sbc a,", "and ", "xor ", "or ", "cp "
68} ;
9fc0b501
SB
69static const char * arit_str_gbz80[] =
70{
71 "add a,", "adc a,", "sub a,", "sbc a,", "and ", "xor ", "or ", "cp "
72} ;
6655dba2
SB
73static const char * arit_str_ez80[] =
74{
75 "add a,", "adc a,", "sub a,", "sbc a,", "and a,", "xor a,", "or a,", "cp a,"
76} ;
77
3c9b82ba 78\f
6655dba2 79static int
9fc0b501 80mach_inst (struct buffer *buf, const struct tab_elt *p)
6655dba2
SB
81{
82 return !p->inss || (p->inss & buf->inss);
83}
84
3c9b82ba
NC
85static int
86fetch_data (struct buffer *buf, disassemble_info * info, int n)
87{
88 int r;
89
40c75bc8 90 if (buf->n_fetch + n > (int)sizeof (buf->data))
3c9b82ba
NC
91 abort ();
92
93 r = info->read_memory_func (buf->base + buf->n_fetch,
9e919b5f 94 (unsigned char*) buf->data + buf->n_fetch,
3c9b82ba
NC
95 n, info);
96 if (r == 0)
97 buf->n_fetch += n;
98 return !r;
99}
100
101static int
6655dba2 102prt (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
103{
104 info->fprintf_func (info->stream, "%s", txt);
105 buf->n_used = buf->n_fetch;
106 return 1;
107}
108
109static int
6655dba2 110prt_e (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
111{
112 char e;
113 int target_addr;
114
115 if (fetch_data (buf, info, 1))
116 {
117 e = buf->data[1];
118 target_addr = (buf->base + 2 + e) & 0xffff;
119 buf->n_used = buf->n_fetch;
120 info->fprintf_func (info->stream, "%s0x%04x", txt, target_addr);
121 }
122 else
123 buf->n_used = -1;
124
125 return buf->n_used;
126}
127
128static int
6655dba2 129jr_cc (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
130{
131 char mytxt[TXTSIZ];
132
133 snprintf (mytxt, TXTSIZ, txt, cc_str[(buf->data[0] >> 3) & 3]);
134 return prt_e (buf, info, mytxt);
135}
136
137static int
6655dba2 138prt_nn (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
139{
140 int nn;
141 unsigned char *p;
6655dba2 142 int i;
3c9b82ba
NC
143
144 p = (unsigned char*) buf->data + buf->n_fetch;
6655dba2 145 if (fetch_data (buf, info, buf->nn_len))
3c9b82ba 146 {
6655dba2
SB
147 nn = 0;
148 i = buf->nn_len;
149 while (i--)
150 nn = nn * 0x100 + p[i];
3c9b82ba
NC
151 info->fprintf_func (info->stream, txt, nn);
152 buf->n_used = buf->n_fetch;
153 }
154 else
155 buf->n_used = -1;
156 return buf->n_used;
157}
158
159static int
6655dba2 160prt_rr_nn (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
161{
162 char mytxt[TXTSIZ];
d0411736 163 int rr;
3c9b82ba 164
43e65147 165 rr = (buf->data[buf->n_fetch - 1] >> 4) & 3;
d0411736 166 snprintf (mytxt, TXTSIZ, txt, rr_str[rr]);
3c9b82ba
NC
167 return prt_nn (buf, info, mytxt);
168}
169
170static int
6655dba2 171prt_rr (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
172{
173 info->fprintf_func (info->stream, "%s%s", txt,
174 rr_str[(buf->data[buf->n_fetch - 1] >> 4) & 3]);
175 buf->n_used = buf->n_fetch;
176 return buf->n_used;
177}
178
179static int
6655dba2 180prt_n (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
181{
182 int n;
183 unsigned char *p;
184
185 p = (unsigned char*) buf->data + buf->n_fetch;
186
187 if (fetch_data (buf, info, 1))
188 {
189 n = p[0];
190 info->fprintf_func (info->stream, txt, n);
191 buf->n_used = buf->n_fetch;
192 }
193 else
194 buf->n_used = -1;
195
196 return buf->n_used;
197}
198
9fc0b501
SB
199static int
200prt_n_n (struct buffer *buf, disassemble_info * info, const char *txt)
201{
202 char mytxt[TXTSIZ];
203 int n;
204 unsigned char *p;
205
206 p = (unsigned char*) buf->data + buf->n_fetch;
207
208 if (fetch_data (buf, info, 1))
209 {
210 n = p[0];
211 snprintf (mytxt, TXTSIZ, txt, n);
212 buf->n_used = buf->n_fetch;
213 }
214 else
215 buf->n_used = -1;
216
217 return prt_n (buf, info, mytxt);
218}
219
3c9b82ba 220static int
6655dba2
SB
221prt_r_n (struct buffer *buf, disassemble_info * info, const char *txt)
222{
223 char mytxt[TXTSIZ];
224 int r;
225
226 r = (buf->data[buf->n_fetch - 1] >> 3) & 7;
227 snprintf (mytxt, TXTSIZ, txt, r_str[r]);
228 return prt_n (buf, info, mytxt);
229}
230
231static int
232ld_r_n (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
233{
234 char mytxt[TXTSIZ];
235
6655dba2 236 snprintf (mytxt, TXTSIZ, txt, r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7]);
3c9b82ba
NC
237 return prt_n (buf, info, mytxt);
238}
239
240static int
6655dba2 241prt_r (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
242{
243 info->fprintf_func (info->stream, txt,
244 r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7]);
245 buf->n_used = buf->n_fetch;
246 return buf->n_used;
247}
248
249static int
6655dba2 250ld_r_r (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
251{
252 info->fprintf_func (info->stream, txt,
253 r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
254 r_str[buf->data[buf->n_fetch - 1] & 7]);
255 buf->n_used = buf->n_fetch;
256 return buf->n_used;
257}
258
259static int
6655dba2 260prt_d (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba 261{
6655dba2
SB
262 int d;
263 signed char *p;
264
265 p = buf->data + buf->n_fetch;
266
267 if (fetch_data (buf, info, 1))
268 {
269 d = p[0];
270 info->fprintf_func (info->stream, txt, d);
271 buf->n_used = buf->n_fetch;
272 }
273 else
274 buf->n_used = -1;
275
276 return buf->n_used;
277}
278
279static int
280prt_rr_d (struct buffer *buf, disassemble_info * info, const char *txt)
281{
282 char mytxt[TXTSIZ];
283 int rr;
284
285 rr = (buf->data[buf->n_fetch - 1] >> 4) & 3;
286 if (rr == 3) /* SP is not supported */
287 return 0;
288
289 snprintf (mytxt, TXTSIZ, txt, rr_str[rr]);
290 return prt_d (buf, info, mytxt);
291}
292
293static int
294arit_r (struct buffer *buf, disassemble_info * info, const char *txt)
295{
296 const char * const *arit;
9fc0b501
SB
297
298 if (buf->inss & INSS_EZ80)
299 arit = arit_str_ez80;
300 else if (buf->inss & INSS_GBZ80)
301 arit = arit_str_gbz80;
302 else
303 arit = arit_str;
304
3c9b82ba 305 info->fprintf_func (info->stream, txt,
6655dba2
SB
306 arit[(buf->data[buf->n_fetch - 1] >> 3) & 7],
307 r_str[buf->data[buf->n_fetch - 1] & 7]);
3c9b82ba
NC
308 buf->n_used = buf->n_fetch;
309 return buf->n_used;
310}
311
312static int
6655dba2 313prt_cc (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
314{
315 info->fprintf_func (info->stream, "%s%s", txt,
316 cc_str[(buf->data[0] >> 3) & 7]);
317 buf->n_used = buf->n_fetch;
318 return buf->n_used;
319}
320
321static int
6655dba2 322pop_rr (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
323{
324 static char *rr_stack[] = { "bc","de","hl","af"};
325
326 info->fprintf_func (info->stream, "%s %s", txt,
327 rr_stack[(buf->data[0] >> 4) & 3]);
328 buf->n_used = buf->n_fetch;
329 return buf->n_used;
330}
331
332
333static int
6655dba2 334jp_cc_nn (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
335{
336 char mytxt[TXTSIZ];
337
338 snprintf (mytxt,TXTSIZ,
339 "%s%s,0x%%04x", txt, cc_str[(buf->data[0] >> 3) & 7]);
340 return prt_nn (buf, info, mytxt);
341}
342
343static int
6655dba2 344arit_n (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
345{
346 char mytxt[TXTSIZ];
6655dba2 347 const char * const *arit;
3c9b82ba 348
9fc0b501
SB
349 if (buf->inss & INSS_EZ80)
350 arit = arit_str_ez80;
351 else if (buf->inss & INSS_GBZ80)
352 arit = arit_str_gbz80;
353 else
354 arit = arit_str;
355
6655dba2 356 snprintf (mytxt,TXTSIZ, txt, arit[(buf->data[0] >> 3) & 7]);
3c9b82ba
NC
357 return prt_n (buf, info, mytxt);
358}
359
360static int
6655dba2 361rst (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
362{
363 info->fprintf_func (info->stream, txt, buf->data[0] & 0x38);
364 buf->n_used = buf->n_fetch;
365 return buf->n_used;
366}
367
9fc0b501 368
3c9b82ba 369static int
6655dba2 370cis (struct buffer *buf, disassemble_info * info, const char *txt ATTRIBUTE_UNUSED)
3c9b82ba
NC
371{
372 static char * opar[] = { "ld", "cp", "in", "out" };
373 char * op;
374 char c;
375
376 c = buf->data[1];
377 op = ((0x13 & c) == 0x13) ? "ot" : (opar[c & 3]);
378 info->fprintf_func (info->stream,
379 "%s%c%s", op,
380 (c & 0x08) ? 'd' : 'i',
381 (c & 0x10) ? "r" : "");
382 buf->n_used = 2;
383 return buf->n_used;
384}
385
386static int
6655dba2
SB
387cism (struct buffer *buf, disassemble_info * info, const char *txt ATTRIBUTE_UNUSED)
388{
389 static char * opar[] = { "in%cm%s", "ot%cm%s" };
390 char * op;
391 char c;
392
393 c = buf->data[1];
394 op = opar[c & 1];
395 info->fprintf_func (info->stream,
396 op,
397 (c & 0x08) ? 'd' : 'i',
398 (c & 0x10) ? "r" : "");
399 buf->n_used = 2;
400 return buf->n_used;
401}
402
403static int
404cis2 (struct buffer *buf, disassemble_info * info, const char *txt ATTRIBUTE_UNUSED)
405{
406 static char * opar[] = { "in", "out" };
407 char * op;
408 char c;
409
410 c = buf->data[1];
411 op = ((0x14 & c) == 0x14) ? "ot" : (opar[c & 1]);
412 info->fprintf_func (info->stream,
413 "%s%c2%s",
414 op,
415 (c & 0x08) ? 'd' : 'i',
416 (c & 0x10) ? "r" : "");
417 buf->n_used = 2;
418 return buf->n_used;
419}
420
421static int
422dump (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
423{
424 int i;
425
426 info->fprintf_func (info->stream, "defb ");
427 for (i = 0; txt[i]; ++i)
428 info->fprintf_func (info->stream, i ? ", 0x%02x" : "0x%02x",
429 (unsigned char) buf->data[i]);
430 buf->n_used = i;
431 return buf->n_used;
432}
9fc0b501 433
3c9b82ba
NC
434/* Table to disassemble machine codes with prefix 0xED. */
435struct tab_elt opc_ed[] =
436{
9fc0b501
SB
437 { 0x30, 0xFF, prt, "mul d,e", INSS_Z80N },
438 { 0x31, 0xFF, prt, "add hl,a", INSS_Z80N },
439 { 0x30, 0xFE, dump, "xx", INSS_ALL }, /* do not move this line */
6655dba2
SB
440 { 0x00, 0xC7, prt_r_n, "in0 %s,(0x%%02x)", INSS_Z180|INSS_EZ80 },
441 { 0x01, 0xC7, prt_r_n, "out0 (0x%%02x),%s", INSS_Z180|INSS_EZ80 },
442 { 0x32, 0xFF, prt_d, "lea ix,ix%+d", INSS_EZ80 },
443 { 0x33, 0xFF, prt_d, "lea iy,iy%+d", INSS_EZ80 },
444 { 0x02, 0xCF, prt_rr_d, "lea %s,ix%%+d", INSS_EZ80 },
445 { 0x03, 0xCF, prt_rr_d, "lea %s,iy%%+d", INSS_EZ80 },
446 { 0x04, 0xC7, prt_r, "tst %s", INSS_Z180},
447 { 0x04, 0xC7, prt_r, "tst a,%s", INSS_EZ80 },
448 { 0x07, 0xFF, prt, "ld bc,(hl)", INSS_EZ80 },
449 { 0x0F, 0xCF, prt_rr, "ld (hl),", INSS_EZ80 },
450 { 0x17, 0xFF, prt, "ld de,(hl)", INSS_EZ80 },
9fc0b501
SB
451 { 0x23, 0xFF, prt, "swapnib", INSS_Z80N },
452 { 0x24, 0xFF, prt, "mirror", INSS_Z80N },
6655dba2 453 { 0x27, 0xFF, prt, "ld hl,(hl)", INSS_EZ80 },
9fc0b501
SB
454 { 0x27, 0xFF, prt_n, "test 0x%02x", INSS_Z80N },
455 { 0x28, 0xFF, prt, "bsla de,b", INSS_Z80N },
456 { 0x29, 0xFF, prt, "bsra de,b", INSS_Z80N },
457 { 0x2A, 0xFF, prt, "bsrl de,b", INSS_Z80N },
458 { 0x2B, 0xFF, prt, "bsrf de,b", INSS_Z80N },
459 { 0x2C, 0xFF, prt, "bslc de,b", INSS_Z80N },
460 { 0x32, 0xFF, prt, "add de,a", INSS_Z80N },
461 { 0x33, 0xFF, prt, "add bc,a", INSS_Z80N },
462 { 0x34, 0xFF, prt_nn, "add hl,0x%04x", INSS_Z80N },
463 { 0x35, 0xFF, prt_nn, "add de,0x%04x", INSS_Z80N },
464 { 0x36, 0xFF, prt_nn, "add bc,0x%04x", INSS_Z80N },
6655dba2
SB
465 { 0x36, 0xFF, prt, "ld iy,(hl)", INSS_EZ80 },
466 { 0x37, 0xFF, prt, "ld ix,(hl)", INSS_EZ80 },
467 { 0x3E, 0xFF, prt, "ld (hl),iy", INSS_EZ80 },
468 { 0x3F, 0xFF, prt, "ld (hl),ix", INSS_EZ80 },
9fc0b501 469 { 0x70, 0xFF, prt, "in f,(c)", INSS_Z80 | INSS_R800 | INSS_Z80N },
6655dba2
SB
470 { 0x70, 0xFF, dump, "xx", INSS_ALL },
471 { 0x40, 0xC7, prt_r, "in %s,(bc)", INSS_EZ80 },
472 { 0x40, 0xC7, prt_r, "in %s,(c)", INSS_ALL },
9fc0b501
SB
473 { 0x71, 0xFF, prt, "out (c),0", INSS_Z80 | INSS_Z80N },
474 { 0x71, 0xFF, dump, "xx", INSS_ALL },
6655dba2
SB
475 { 0x41, 0xC7, prt_r, "out (bc),%s", INSS_EZ80 },
476 { 0x41, 0xC7, prt_r, "out (c),%s", INSS_ALL },
477 { 0x42, 0xCF, prt_rr, "sbc hl,", INSS_ALL },
478 { 0x43, 0xCF, prt_rr_nn, "ld (0x%%04x),%s", INSS_ALL },
479 { 0x44, 0xFF, prt, "neg", INSS_ALL },
480 { 0x45, 0xFF, prt, "retn", INSS_ALL },
481 { 0x46, 0xFF, prt, "im 0", INSS_ALL },
482 { 0x47, 0xFF, prt, "ld i,a", INSS_ALL },
483 { 0x4A, 0xCF, prt_rr, "adc hl,", INSS_ALL },
484 { 0x4B, 0xCF, prt_rr_nn, "ld %s,(0x%%04x)", INSS_ALL },
485 { 0x4C, 0xCF, prt_rr, "mlt ", INSS_Z180|INSS_EZ80 },
486 { 0x4D, 0xFF, prt, "reti", INSS_ALL },
487 { 0x4F, 0xFF, prt, "ld r,a", INSS_ALL },
488 { 0x54, 0xFF, prt_d, "lea ix,iy%+d", INSS_EZ80 },
489 { 0x55, 0xFF, prt_d, "lea iy,ix%+d", INSS_EZ80 },
490 { 0x56, 0xFF, prt, "im 1", INSS_ALL },
491 { 0x57, 0xFF, prt, "ld a,i", INSS_ALL },
492 { 0x5E, 0xFF, prt, "im 2", INSS_ALL },
493 { 0x5F, 0xFF, prt, "ld a,r", INSS_ALL },
494 { 0x64, 0xFF, prt_n, "tst 0x%02x", INSS_Z180 },
495 { 0x64, 0xFF, prt_n, "tst a,0x%02x", INSS_EZ80 },
496 { 0x65, 0xFF, prt_d, "pea ix%+d", INSS_EZ80 },
497 { 0x66, 0xFF, prt_d, "pea iy%+d", INSS_EZ80 },
498 { 0x67, 0xFF, prt, "rrd", INSS_ALL },
9fc0b501
SB
499 { 0x6D, 0xFF, prt, "ld mb,a", INSS_EZ80 },
500 { 0x6E, 0xFF, prt, "ld a,mb", INSS_EZ80 },
6655dba2
SB
501 { 0x6F, 0xFF, prt, "rld", INSS_ALL },
502 { 0x74, 0xFF, prt_n, "tstio 0x%02x", INSS_Z180|INSS_EZ80 },
503 { 0x76, 0xFF, prt, "slp", INSS_Z180|INSS_EZ80 },
9fc0b501
SB
504 { 0x7D, 0xFF, prt, "stmix", INSS_EZ80 },
505 { 0x7E, 0xFF, prt, "rsmix", INSS_EZ80 },
6655dba2
SB
506 { 0x82, 0xE6, cism, "", INSS_Z180|INSS_EZ80 },
507 { 0x84, 0xC7, cis2, "", INSS_EZ80 },
9fc0b501
SB
508 { 0x8A, 0xFF, prt_n_n, "push 0x%02x%%02x", INSS_Z80N },
509 { 0x90, 0xFF, prt, "outinb", INSS_Z80N },
510 { 0x91, 0xFF, prt_n_n, "nextreg 0x%02x,0x%%02x", INSS_Z80N },
511 { 0x92, 0xFF, prt_n, "nextreg 0x%02x,a", INSS_Z80N },
512 { 0x93, 0xFF, prt, "pixeldn", INSS_Z80N },
513 { 0x94, 0xFF, prt, "pixelad", INSS_Z80N },
514 { 0x95, 0xFF, prt, "setae", INSS_Z80N },
515 { 0x98, 0xFF, prt, "jp (c)", INSS_Z80N },
6655dba2 516 { 0xA0, 0xE4, cis, "", INSS_ALL },
9fc0b501
SB
517 { 0xA4, 0xFF, prt, "ldix", INSS_Z80N },
518 { 0xAC, 0xFF, prt, "lddx", INSS_Z80N },
519 { 0xA5, 0xFF, prt, "ldws", INSS_Z80N },
520 { 0xB4, 0xFF, prt, "ldirx", INSS_Z80N },
521 { 0xB7, 0xFF, prt, "ldpirx", INSS_Z80N },
522 { 0xBC, 0xFF, prt, "lddrx", INSS_Z80N },
6655dba2
SB
523 { 0xC2, 0xFF, prt, "inirx", INSS_EZ80 },
524 { 0xC3, 0xFF, prt, "otirx", INSS_EZ80 },
9fc0b501 525 { 0xC7, 0xFF, prt, "ld i,hl", INSS_EZ80 },
6655dba2
SB
526 { 0xCA, 0xFF, prt, "indrx", INSS_EZ80 },
527 { 0xCB, 0xFF, prt, "otdrx", INSS_EZ80 },
528 { 0xC3, 0xFF, prt, "muluw hl,bc", INSS_R800 },
529 { 0xC5, 0xE7, prt_r, "mulub a,%s", INSS_R800 },
9fc0b501 530 { 0xD7, 0xFF, prt, "ld hl,i", INSS_EZ80 },
6655dba2
SB
531 { 0xF3, 0xFF, prt, "muluw hl,sp", INSS_R800 },
532 { 0x00, 0x00, dump, "xx", INSS_ALL }
3c9b82ba
NC
533};
534
535static int
6655dba2
SB
536pref_ed (struct buffer *buf, disassemble_info *info,
537 const char *txt ATTRIBUTE_UNUSED)
3c9b82ba
NC
538{
539 struct tab_elt *p;
540
40c75bc8 541 if (fetch_data (buf, info, 1))
3c9b82ba 542 {
40c75bc8 543 for (p = opc_ed; p->val != (buf->data[1] & p->mask) || !mach_inst (buf, p); ++p)
6655dba2 544 ;
3c9b82ba
NC
545 p->fp (buf, info, p->text);
546 }
547 else
548 buf->n_used = -1;
549
550 return buf->n_used;
551}
552\f
553/* Instruction names for the instructions addressing single bits. */
554static char *cb1_str[] = { "", "bit", "res", "set"};
555/* Instruction names for shifts and rotates. */
556static char *cb2_str[] =
557{
558 "rlc", "rrc", "rl", "rr", "sla", "sra", "sli", "srl"
559};
560
561static int
6655dba2
SB
562pref_cb (struct buffer *buf, disassemble_info *info,
563 const char *txt ATTRIBUTE_UNUSED)
3c9b82ba 564{
6655dba2
SB
565 const char *op_txt;
566 int idx;
3c9b82ba
NC
567 if (fetch_data (buf, info, 1))
568 {
569 buf->n_used = 2;
570 if ((buf->data[1] & 0xc0) == 0)
6655dba2
SB
571 {
572 idx = (buf->data[1] >> 3) & 7;
573 if ((buf->inss & INSS_GBZ80) && (idx == 6))
574 op_txt = "swap";
575 else
576 op_txt = cb2_str[idx];
577 info->fprintf_func (info->stream, "%s %s",
578 op_txt,
579 r_str[buf->data[1] & 7]);
580 }
3c9b82ba
NC
581 else
582 info->fprintf_func (info->stream, "%s %d,%s",
583 cb1_str[(buf->data[1] >> 6) & 3],
584 (buf->data[1] >> 3) & 7,
585 r_str[buf->data[1] & 7]);
586 }
587 else
588 buf->n_used = -1;
589
590 return buf->n_used;
591}
9fc0b501 592
3c9b82ba 593static int
6655dba2 594addvv (struct buffer * buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
595{
596 info->fprintf_func (info->stream, "add %s,%s", txt, txt);
597
598 return buf->n_used = buf->n_fetch;
599}
600
601static int
6655dba2 602ld_v_v (struct buffer * buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
603{
604 char mytxt[TXTSIZ];
605
606 snprintf (mytxt, TXTSIZ, "ld %s%%s,%s%%s", txt, txt);
607 return ld_r_r (buf, info, mytxt);
608}
609
610static int
6655dba2 611prt_d_n (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba 612{
6655dba2 613 char mytxt[TXTSIZ];
3c9b82ba 614 int d;
9e919b5f 615 signed char *p;
3c9b82ba 616
c9021189 617 p = buf->data + buf->n_fetch;
3c9b82ba
NC
618
619 if (fetch_data (buf, info, 1))
620 {
621 d = p[0];
6655dba2
SB
622 snprintf (mytxt, TXTSIZ, txt, d);
623 return prt_n (buf, info, mytxt);
3c9b82ba
NC
624 }
625 else
626 buf->n_used = -1;
627
628 return buf->n_used;
629}
630
631static int
6655dba2 632arit_d (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
633{
634 char mytxt[TXTSIZ];
6655dba2
SB
635 signed char c;
636 const char * const *arit;
3c9b82ba 637
6655dba2
SB
638 arit = (buf->inss & INSS_EZ80) ? arit_str_ez80 : arit_str;
639 c = buf->data[buf->n_fetch - 1];
640 snprintf (mytxt, TXTSIZ, txt, arit[(c >> 3) & 7]);
641 return prt_d (buf, info, mytxt);
3c9b82ba
NC
642}
643
644static int
6655dba2 645ld_r_d (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
646{
647 char mytxt[TXTSIZ];
9e919b5f 648 signed char c;
3c9b82ba
NC
649
650 c = buf->data[buf->n_fetch - 1];
6655dba2 651 snprintf (mytxt, TXTSIZ, txt, r_str[(c >> 3) & 7]);
3c9b82ba
NC
652 return prt_d (buf, info, mytxt);
653}
654
655static int
40c75bc8 656ld_d_r (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
657{
658 char mytxt[TXTSIZ];
9e919b5f 659 signed char c;
3c9b82ba
NC
660
661 c = buf->data[buf->n_fetch - 1];
6655dba2 662 snprintf (mytxt, TXTSIZ, txt, r_str[c & 7]);
3c9b82ba
NC
663 return prt_d (buf, info, mytxt);
664}
665
666static int
40c75bc8 667ld_ii_ii (struct buffer *buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
668{
669 char mytxt[TXTSIZ];
9e919b5f 670 signed char c;
6655dba2
SB
671 int p;
672 static const char *ii[2] = { "ix", "iy" };
3c9b82ba 673
bce58db4 674 p = (buf->data[buf->n_fetch - 2] == (signed char) 0xdd) ? 0 : 1;
3c9b82ba 675 c = buf->data[buf->n_fetch - 1];
6655dba2
SB
676 if ((c & 0x07) != 0x07)
677 p = 1 - p; /* 0 -> 1, 1 -> 0 */
678 snprintf (mytxt, TXTSIZ, txt, ii[p]);
3c9b82ba
NC
679 return prt_d (buf, info, mytxt);
680}
681
682static int
6655dba2 683pref_xd_cb (struct buffer * buf, disassemble_info * info, const char *txt)
3c9b82ba
NC
684{
685 if (fetch_data (buf, info, 2))
686 {
687 int d;
688 char arg[TXTSIZ];
9e919b5f 689 signed char *p;
3c9b82ba
NC
690
691 buf->n_used = 4;
692 p = buf->data;
693 d = p[2];
694
695 if (((p[3] & 0xC0) == 0x40) || ((p[3] & 7) == 0x06))
9e919b5f 696 snprintf (arg, TXTSIZ, "(%s%+d)", txt, d);
3c9b82ba 697 else
9e919b5f 698 snprintf (arg, TXTSIZ, "(%s%+d),%s", txt, d, r_str[p[3] & 7]);
3c9b82ba
NC
699
700 if ((p[3] & 0xc0) == 0)
701 info->fprintf_func (info->stream, "%s %s",
702 cb2_str[(buf->data[3] >> 3) & 7],
703 arg);
704 else
705 info->fprintf_func (info->stream, "%s %d,%s",
706 cb1_str[(buf->data[3] >> 6) & 3],
707 (buf->data[3] >> 3) & 7,
708 arg);
709 }
710 else
711 buf->n_used = -1;
712
713 return buf->n_used;
714}
715\f
716/* Table to disassemble machine codes with prefix 0xDD or 0xFD. */
717static struct tab_elt opc_ind[] =
718{
6655dba2
SB
719 { 0x07, 0xFF, prt_d, "ld bc,(%s%%+d)", INSS_EZ80 },
720 { 0x0F, 0xFF, prt_d, "ld (%s%%+d),bc", INSS_EZ80 },
721 { 0x17, 0xFF, prt_d, "ld de,(%s%%+d)", INSS_EZ80 },
722 { 0x1F, 0xFF, prt_d, "ld (%s%%+d),de", INSS_EZ80 },
723 { 0x24, 0xF7, prt_r, "inc %s%%s", INSS_ALL },
724 { 0x25, 0xF7, prt_r, "dec %s%%s", INSS_ALL },
725 { 0x26, 0xF7, ld_r_n, "ld %s%%s,0x%%%%02x", INSS_ALL },
726 { 0x27, 0xFF, prt_d, "ld hl,(%s%%+d)", INSS_EZ80 },
727 { 0x2F, 0xFF, prt_d, "ld (%s%%+d),hl", INSS_EZ80 },
728 { 0x21, 0xFF, prt_nn, "ld %s,0x%%04x", INSS_ALL },
729 { 0x22, 0xFF, prt_nn, "ld (0x%%04x),%s", INSS_ALL },
730 { 0x2A, 0xFF, prt_nn, "ld %s,(0x%%04x)", INSS_ALL },
731 { 0x23, 0xFF, prt, "inc %s", INSS_ALL },
732 { 0x2B, 0xFF, prt, "dec %s", INSS_ALL },
733 { 0x29, 0xFF, addvv, "%s", INSS_ALL },
734 { 0x31, 0xFF, ld_ii_ii, "ld %%s,(%s%%%%+d)", INSS_EZ80 },
735 { 0x37, 0xFF, ld_ii_ii, "ld %%s,(%s%%%%+d)", INSS_EZ80 },
736 { 0x3E, 0xFE, ld_ii_ii, "ld (%s%%%%+d),%%s", INSS_EZ80 },
737 { 0x09, 0xCF, prt_rr, "add %s,", INSS_ALL },
738 { 0x34, 0xFF, prt_d, "inc (%s%%+d)", INSS_ALL },
739 { 0x35, 0xFF, prt_d, "dec (%s%%+d)", INSS_ALL },
740 { 0x36, 0xFF, prt_d_n, "ld (%s%%+d),0x%%%%02x", INSS_ALL },
741
742 { 0x76, 0xFF, dump, "h", INSS_ALL },
743 { 0x46, 0xC7, ld_r_d, "ld %%s,(%s%%%%+d)", INSS_ALL },
744 { 0x70, 0xF8, ld_d_r, "ld (%s%%%%+d),%%s", INSS_ALL },
745 { 0x64, 0xF6, ld_v_v, "%s", INSS_ALL },
746 { 0x60, 0xF0, ld_r_r, "ld %s%%s,%%s", INSS_ALL },
747 { 0x44, 0xC6, ld_r_r, "ld %%s,%s%%s", INSS_ALL },
748
749 { 0x86, 0xC7, arit_d, "%%s(%s%%%%+d)", INSS_ALL },
750 { 0x84, 0xC6, arit_r, "%%s%s%%s", INSS_ALL },
751
752 { 0xE1, 0xFF, prt, "pop %s", INSS_ALL },
753 { 0xE5, 0xFF, prt, "push %s", INSS_ALL },
754 { 0xCB, 0xFF, pref_xd_cb, "%s", INSS_ALL },
755 { 0xE3, 0xFF, prt, "ex (sp),%s", INSS_ALL },
756 { 0xE9, 0xFF, prt, "jp (%s)", INSS_ALL },
757 { 0xF9, 0xFF, prt, "ld sp,%s", INSS_ALL },
758 { 0x00, 0x00, dump, "?", INSS_ALL },
3c9b82ba
NC
759} ;
760
761static int
6655dba2 762pref_ind (struct buffer *buf, disassemble_info *info, const char *txt)
3c9b82ba
NC
763{
764 if (fetch_data (buf, info, 1))
765 {
766 char mytxt[TXTSIZ];
767 struct tab_elt *p;
768
6655dba2
SB
769 for (p = opc_ind; p->val != (buf->data[1] & p->mask) || !mach_inst (buf, p); ++p)
770 ;
3c9b82ba
NC
771 snprintf (mytxt, TXTSIZ, p->text, txt);
772 p->fp (buf, info, mytxt);
773 }
774 else
775 buf->n_used = -1;
776
777 return buf->n_used;
778}
779
6655dba2
SB
780static int
781print_insn_z80_buf (struct buffer *buf, disassemble_info *info);
782
783static int
660e62b1 784suffix (struct buffer *buf, disassemble_info *info, const char *txt)
6655dba2 785{
6655dba2
SB
786 char mybuf[TXTSIZ*4];
787 fprintf_ftype old_fprintf;
788 void *old_stream;
789 char *p;
790
6655dba2
SB
791 switch (txt[2])
792 {
793 case 'l': /* SIL or LIL */
660e62b1 794 buf->nn_len = 3;
6655dba2
SB
795 break;
796 case 's': /* SIS or LIS */
660e62b1 797 buf->nn_len = 2;
6655dba2
SB
798 break;
799 default:
660e62b1
AM
800 abort ();
801 }
802 if (!fetch_data (buf, info, 1)
803 || buf->data[1] == 0x40
804 || buf->data[1] == 0x49
805 || buf->data[1] == 0x52
806 || buf->data[1] == 0x5b)
807 {
808 /* Double prefix, or end of data. */
7a6bf3be 809 info->fprintf_func (info->stream, ".db 0x%02x ; %s", (unsigned)buf->data[0], txt);
660e62b1
AM
810 buf->n_used = 1;
811 return buf->n_used;
6655dba2 812 }
660e62b1 813
6655dba2
SB
814 old_fprintf = info->fprintf_func;
815 old_stream = info->stream;
660e62b1 816 info->fprintf_func = (fprintf_ftype) &sprintf;
6655dba2 817 info->stream = mybuf;
660e62b1
AM
818 buf->base++;
819 if (print_insn_z80_buf (buf, info) >= 0)
820 buf->n_used++;
6655dba2
SB
821 info->fprintf_func = old_fprintf;
822 info->stream = old_stream;
823
660e62b1
AM
824 for (p = mybuf; *p; ++p)
825 if (*p == ' ')
826 break;
827 if (*p)
6655dba2 828 {
660e62b1
AM
829 *p++ = '\0';
830 info->fprintf_func (info->stream, "%s.%s %s", mybuf, txt, p);
6655dba2 831 }
660e62b1
AM
832 else
833 info->fprintf_func (info->stream, "%s.%s", mybuf, txt);
834 return buf->n_used;
6655dba2
SB
835}
836
3c9b82ba 837/* Table to disassemble machine codes without prefix. */
9fc0b501
SB
838static const struct tab_elt
839opc_main[] =
3c9b82ba 840{
6655dba2
SB
841 { 0x00, 0xFF, prt, "nop", INSS_ALL },
842 { 0x01, 0xCF, prt_rr_nn, "ld %s,0x%%04x", INSS_ALL },
843 { 0x02, 0xFF, prt, "ld (bc),a", INSS_ALL },
844 { 0x03, 0xCF, prt_rr, "inc ", INSS_ALL },
845 { 0x04, 0xC7, prt_r, "inc %s", INSS_ALL },
846 { 0x05, 0xC7, prt_r, "dec %s", INSS_ALL },
847 { 0x06, 0xC7, ld_r_n, "ld %s,0x%%02x", INSS_ALL },
848 { 0x07, 0xFF, prt, "rlca", INSS_ALL },
849 { 0x08, 0xFF, prt, "ex af,af'", ~INSS_GBZ80 },
850 { 0x09, 0xCF, prt_rr, "add hl,", INSS_ALL },
851 { 0x0A, 0xFF, prt, "ld a,(bc)", INSS_ALL },
852 { 0x0B, 0xCF, prt_rr, "dec ", INSS_ALL },
853 { 0x0F, 0xFF, prt, "rrca", INSS_ALL },
854 { 0x10, 0xFF, prt_e, "djnz ", ~INSS_GBZ80 },
855 { 0x12, 0xFF, prt, "ld (de),a", INSS_ALL },
856 { 0x17, 0xFF, prt, "rla", INSS_ALL },
857 { 0x18, 0xFF, prt_e, "jr ", INSS_ALL },
858 { 0x1A, 0xFF, prt, "ld a,(de)", INSS_ALL },
859 { 0x1F, 0xFF, prt, "rra", INSS_ALL },
860 { 0x20, 0xE7, jr_cc, "jr %s,", INSS_ALL },
861 { 0x22, 0xFF, prt_nn, "ld (0x%04x),hl", ~INSS_GBZ80 },
862 { 0x27, 0xFF, prt, "daa", INSS_ALL },
863 { 0x2A, 0xFF, prt_nn, "ld hl,(0x%04x)", ~INSS_GBZ80 },
864 { 0x2F, 0xFF, prt, "cpl", INSS_ALL },
865 { 0x32, 0xFF, prt_nn, "ld (0x%04x),a", INSS_ALL },
866 { 0x37, 0xFF, prt, "scf", INSS_ALL },
867 { 0x3A, 0xFF, prt_nn, "ld a,(0x%04x)", INSS_ALL },
868 { 0x3F, 0xFF, prt, "ccf", INSS_ALL },
869
870 { 0x76, 0xFF, prt, "halt", INSS_ALL },
871
872 { 0x40, 0xFF, suffix, "sis", INSS_EZ80 },
873 { 0x49, 0xFF, suffix, "lis", INSS_EZ80 },
874 { 0x52, 0xFF, suffix, "sil", INSS_EZ80 },
875 { 0x5B, 0xFF, suffix, "lil", INSS_EZ80 },
876
877 { 0x40, 0xC0, ld_r_r, "ld %s,%s", INSS_ALL},
878
879 { 0x80, 0xC0, arit_r, "%s%s", INSS_ALL },
880
881 { 0xC0, 0xC7, prt_cc, "ret ", INSS_ALL },
882 { 0xC1, 0xCF, pop_rr, "pop", INSS_ALL },
883 { 0xC2, 0xC7, jp_cc_nn, "jp ", INSS_ALL },
884 { 0xC3, 0xFF, prt_nn, "jp 0x%04x", INSS_ALL },
885 { 0xC4, 0xC7, jp_cc_nn, "call ", INSS_ALL },
886 { 0xC5, 0xCF, pop_rr, "push", INSS_ALL },
887 { 0xC6, 0xC7, arit_n, "%s0x%%02x", INSS_ALL },
888 { 0xC7, 0xC7, rst, "rst 0x%02x", INSS_ALL },
889 { 0xC9, 0xFF, prt, "ret", INSS_ALL },
890 { 0xCB, 0xFF, pref_cb, "", INSS_ALL },
891 { 0xCD, 0xFF, prt_nn, "call 0x%04x", INSS_ALL },
892 { 0xD3, 0xFF, prt_n, "out (0x%02x),a", ~INSS_GBZ80 },
893 { 0xD9, 0xFF, prt, "exx", ~INSS_GBZ80 },
894 { 0xDB, 0xFF, prt_n, "in a,(0x%02x)", ~INSS_GBZ80 },
895 { 0xDD, 0xFF, pref_ind, "ix", ~INSS_GBZ80 },
896 { 0xE3, 0xFF, prt, "ex (sp),hl", ~INSS_GBZ80 },
897 { 0xE9, 0xFF, prt, "jp (hl)", INSS_ALL },
898 { 0xEB, 0xFF, prt, "ex de,hl", ~INSS_GBZ80 },
899 { 0xED, 0xFF, pref_ed, "", ~INSS_GBZ80 },
900 { 0xF3, 0xFF, prt, "di", INSS_ALL },
9fc0b501 901 { 0xF9, 0xFF, prt, "ld sp,hl", INSS_ALL },
6655dba2
SB
902 { 0xFB, 0xFF, prt, "ei", INSS_ALL },
903 { 0xFD, 0xFF, pref_ind, "iy", ~INSS_GBZ80 },
904 { 0x00, 0x00, prt, "????", INSS_ALL },
3c9b82ba
NC
905} ;
906
9fc0b501
SB
907/* Separate GBZ80 main opcode table due to many differences */
908static const struct tab_elt
909opc_main_gbz80[] =
910{
911 { 0x00, 0xFF, prt,"nop", INSS_ALL },
912 { 0x01, 0xCF, prt_rr_nn, "ld %s,0x%%04x", INSS_ALL },
913 { 0x02, 0xFF, prt, "ld (bc),a", INSS_ALL },
914 { 0x03, 0xCF, prt_rr, "inc ", INSS_ALL },
915 { 0x04, 0xC7, prt_r, "inc %s", INSS_ALL },
916 { 0x05, 0xC7, prt_r, "dec %s", INSS_ALL },
917 { 0x06, 0xC7, ld_r_n, "ld %s,0x%%02x", INSS_ALL },
918 { 0x07, 0xFF, prt, "rlca", INSS_ALL },
919 { 0x08, 0xFF, prt_nn, "ld (0x%04x),sp", INSS_GBZ80 },
920 { 0x09, 0xCF, prt_rr, "add hl,", INSS_ALL },
921 { 0x0A, 0xFF, prt, "ld a,(bc)", INSS_ALL },
922 { 0x0B, 0xCF, prt_rr, "dec ", INSS_ALL },
923 { 0x0F, 0xFF, prt, "rrca", INSS_ALL },
924 { 0x10, 0xFF, prt, "stop", INSS_GBZ80 },
925 { 0x12, 0xFF, prt, "ld (de),a", INSS_ALL },
926 { 0x17, 0xFF, prt, "rla", INSS_ALL },
927 { 0x18, 0xFF, prt_e, "jr ", INSS_ALL },
928 { 0x1A, 0xFF, prt, "ld a,(de)", INSS_ALL },
929 { 0x1F, 0xFF, prt, "rra", INSS_ALL },
930 { 0x20, 0xE7, jr_cc, "jr %s,", INSS_ALL },
931 { 0x22, 0xFF, prt, "ld (hl+),a", INSS_GBZ80 },
932 { 0x27, 0xFF, prt, "daa", INSS_ALL },
933 { 0x2A, 0xFF, prt, "ld a,(hl+)", INSS_GBZ80 },
934 { 0x2F, 0xFF, prt, "cpl", INSS_ALL },
935 { 0x32, 0xFF, prt, "ld (hl-),a", INSS_GBZ80 },
936 { 0x37, 0xFF, prt, "scf", INSS_ALL },
937 { 0x3A, 0xFF, prt, "ld a,(hl-)", INSS_GBZ80 },
938 { 0x3F, 0xFF, prt, "ccf", INSS_ALL },
939 { 0x76, 0xFF, prt, "halt", INSS_ALL },
940 { 0x40, 0xC0, ld_r_r, "ld %s,%s", INSS_ALL},
941 { 0x80, 0xC0, arit_r, "%s%s", INSS_ALL },
942 { 0xC0, 0xE7, prt_cc, "ret ", INSS_ALL },
943 { 0xC1, 0xCF, pop_rr, "pop", INSS_ALL },
944 { 0xC2, 0xE7, jp_cc_nn, "jp ", INSS_ALL },
945 { 0xC3, 0xFF, prt_nn, "jp 0x%04x", INSS_ALL },
946 { 0xC4, 0xE7, jp_cc_nn, "call ", INSS_ALL },
947 { 0xC5, 0xCF, pop_rr, "push", INSS_ALL },
948 { 0xC6, 0xC7, arit_n, "%s0x%%02x", INSS_ALL },
949 { 0xC7, 0xC7, rst, "rst 0x%02x", INSS_ALL },
950 { 0xC9, 0xFF, prt, "ret", INSS_ALL },
951 { 0xCB, 0xFF, pref_cb, "", INSS_ALL },
952 { 0xCD, 0xFF, prt_nn, "call 0x%04x", INSS_ALL },
953 { 0xD9, 0xFF, prt, "reti", INSS_GBZ80 },
954 { 0xE0, 0xFF, prt_n, "ldh (0x%02x),a", INSS_GBZ80 },
955 { 0xE2, 0xFF, prt, "ldh (c),a", INSS_GBZ80 },
956 { 0xE8, 0xFF, prt_d, "add sp,%d", INSS_GBZ80 },
957 { 0xE9, 0xFF, prt, "jp (hl)", INSS_ALL },
958 { 0xEA, 0xFF, prt_nn, "ld (0x%04x),a", INSS_GBZ80 },
959 { 0xF0, 0xFF, prt_n, "ldh a,(0x%02x)", INSS_GBZ80 },
960 { 0xF2, 0xFF, prt, "ldh a,(c)", INSS_GBZ80 },
961 { 0xF3, 0xFF, prt, "di", INSS_ALL },
962 { 0xF8, 0xFF, prt_d, "ldhl sp,%d", INSS_GBZ80 },
963 { 0xF9, 0xFF, prt, "ld sp,hl", INSS_ALL },
964 { 0xFA, 0xFF, prt_nn, "ld a,(0x%04x)", INSS_GBZ80 },
965 { 0xFB, 0xFF, prt, "ei", INSS_ALL },
966 { 0x00, 0x00, dump, "?", INSS_ALL },
967} ;
968
3c9b82ba
NC
969int
970print_insn_z80 (bfd_vma addr, disassemble_info * info)
971{
972 struct buffer buf;
3c9b82ba
NC
973
974 buf.base = addr;
6655dba2
SB
975 buf.inss = 1 << info->mach;
976 buf.nn_len = info->mach == bfd_mach_ez80_adl ? 3 : 2;
977 info->bytes_per_line = (buf.inss & INSS_EZ80) ? 6 : 4; /* <ss pp oo nn mm MM> OR <pp oo nn mm> */
3c9b82ba 978
6655dba2
SB
979 return print_insn_z80_buf (&buf, info);
980}
981
982static int
983print_insn_z80_buf (struct buffer *buf, disassemble_info *info)
984{
9fc0b501 985 const struct tab_elt *p;
6655dba2 986
660e62b1
AM
987 buf->n_fetch = 0;
988 buf->n_used = 0;
6655dba2 989 if (! fetch_data (buf, info, 1))
3c9b82ba
NC
990 return -1;
991
9fc0b501
SB
992 p = (buf->inss & INSS_GBZ80) ? opc_main_gbz80 : opc_main;
993
994 for (; p->val != (buf->data[0] & p->mask) || !mach_inst (buf, p); ++p)
3c9b82ba 995 ;
6655dba2 996 p->fp (buf, info, p->text);
3c9b82ba 997
6655dba2 998 return buf->n_used;
3c9b82ba 999}