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