* readelf.c (do_archive_index): New.
[deliverable/binutils-gdb.git] / opcodes / z80-dis.c
CommitLineData
3c9b82ba 1/* Print Z80 and R800 instructions
9b201bb5 2 Copyright 2005, 2007 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"
23#include "dis-asm.h"
24#include <stdio.h>
25
26struct buffer
27{
28 bfd_vma base;
29 int n_fetch;
30 int n_used;
9e919b5f 31 signed char data[4];
3c9b82ba
NC
32} ;
33
34typedef int (*func)(struct buffer *, disassemble_info *, char *);
35
36struct tab_elt
37{
38 unsigned char val;
39 unsigned char mask;
40 func fp;
41 char * text;
42} ;
43
9e919b5f 44#define TXTSIZ 24
3c9b82ba
NC
45/* Names of 16-bit registers. */
46static char * rr_str[] = { "bc", "de", "hl", "sp" };
47/* Names of 8-bit registers. */
48static char * r_str[] = { "b", "c", "d", "e", "h", "l", "(hl)", "a" };
49/* Texts for condition codes. */
50static char * cc_str[] = { "nz", "z", "nc", "c", "po", "pe", "p", "m" };
51/* Instruction names for 8-bit arithmetic, operand "a" is often implicit */
52static char * arit_str[] =
53{
54 "add a,", "adc a,", "sub ", "sbc a,", "and ", "xor ", "or ", "cp "
55} ;
56\f
57static int
58fetch_data (struct buffer *buf, disassemble_info * info, int n)
59{
60 int r;
61
62 if (buf->n_fetch + n > 4)
63 abort ();
64
65 r = info->read_memory_func (buf->base + buf->n_fetch,
9e919b5f 66 (unsigned char*) buf->data + buf->n_fetch,
3c9b82ba
NC
67 n, info);
68 if (r == 0)
69 buf->n_fetch += n;
70 return !r;
71}
72
73static int
74prt (struct buffer *buf, disassemble_info * info, char *txt)
75{
76 info->fprintf_func (info->stream, "%s", txt);
77 buf->n_used = buf->n_fetch;
78 return 1;
79}
80
81static int
82prt_e (struct buffer *buf, disassemble_info * info, char *txt)
83{
84 char e;
85 int target_addr;
86
87 if (fetch_data (buf, info, 1))
88 {
89 e = buf->data[1];
90 target_addr = (buf->base + 2 + e) & 0xffff;
91 buf->n_used = buf->n_fetch;
92 info->fprintf_func (info->stream, "%s0x%04x", txt, target_addr);
93 }
94 else
95 buf->n_used = -1;
96
97 return buf->n_used;
98}
99
100static int
101jr_cc (struct buffer *buf, disassemble_info * info, char *txt)
102{
103 char mytxt[TXTSIZ];
104
105 snprintf (mytxt, TXTSIZ, txt, cc_str[(buf->data[0] >> 3) & 3]);
106 return prt_e (buf, info, mytxt);
107}
108
109static int
110prt_nn (struct buffer *buf, disassemble_info * info, char *txt)
111{
112 int nn;
113 unsigned char *p;
114
115 p = (unsigned char*) buf->data + buf->n_fetch;
116 if (fetch_data (buf, info, 2))
117 {
118 nn = p[0] + (p[1] << 8);
119 info->fprintf_func (info->stream, txt, nn);
120 buf->n_used = buf->n_fetch;
121 }
122 else
123 buf->n_used = -1;
124 return buf->n_used;
125}
126
127static int
128prt_rr_nn (struct buffer *buf, disassemble_info * info, char *txt)
129{
130 char mytxt[TXTSIZ];
131
132 snprintf (mytxt, TXTSIZ, txt, rr_str[(buf->data[0] >> 4) & 3]);
133 return prt_nn (buf, info, mytxt);
134}
135
136static int
137prt_rr (struct buffer *buf, disassemble_info * info, char *txt)
138{
139 info->fprintf_func (info->stream, "%s%s", txt,
140 rr_str[(buf->data[buf->n_fetch - 1] >> 4) & 3]);
141 buf->n_used = buf->n_fetch;
142 return buf->n_used;
143}
144
145static int
146prt_n (struct buffer *buf, disassemble_info * info, char *txt)
147{
148 int n;
149 unsigned char *p;
150
151 p = (unsigned char*) buf->data + buf->n_fetch;
152
153 if (fetch_data (buf, info, 1))
154 {
155 n = p[0];
156 info->fprintf_func (info->stream, txt, n);
157 buf->n_used = buf->n_fetch;
158 }
159 else
160 buf->n_used = -1;
161
162 return buf->n_used;
163}
164
165static int
166ld_r_n (struct buffer *buf, disassemble_info * info, char *txt)
167{
168 char mytxt[TXTSIZ];
169
170 snprintf (mytxt, TXTSIZ, txt, r_str[(buf->data[0] >> 3) & 7]);
171 return prt_n (buf, info, mytxt);
172}
173
174static int
175prt_r (struct buffer *buf, disassemble_info * info, char *txt)
176{
177 info->fprintf_func (info->stream, txt,
178 r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7]);
179 buf->n_used = buf->n_fetch;
180 return buf->n_used;
181}
182
183static int
184ld_r_r (struct buffer *buf, disassemble_info * info, char *txt)
185{
186 info->fprintf_func (info->stream, txt,
187 r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
188 r_str[buf->data[buf->n_fetch - 1] & 7]);
189 buf->n_used = buf->n_fetch;
190 return buf->n_used;
191}
192
193static int
194arit_r (struct buffer *buf, disassemble_info * info, char *txt)
195{
196 info->fprintf_func (info->stream, txt,
197 arit_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
198 r_str[buf->data[buf->n_fetch - 1] & 7]);
199 buf->n_used = buf->n_fetch;
200 return buf->n_used;
201}
202
203static int
204prt_cc (struct buffer *buf, disassemble_info * info, char *txt)
205{
206 info->fprintf_func (info->stream, "%s%s", txt,
207 cc_str[(buf->data[0] >> 3) & 7]);
208 buf->n_used = buf->n_fetch;
209 return buf->n_used;
210}
211
212static int
213pop_rr (struct buffer *buf, disassemble_info * info, char *txt)
214{
215 static char *rr_stack[] = { "bc","de","hl","af"};
216
217 info->fprintf_func (info->stream, "%s %s", txt,
218 rr_stack[(buf->data[0] >> 4) & 3]);
219 buf->n_used = buf->n_fetch;
220 return buf->n_used;
221}
222
223
224static int
225jp_cc_nn (struct buffer *buf, disassemble_info * info, char *txt)
226{
227 char mytxt[TXTSIZ];
228
229 snprintf (mytxt,TXTSIZ,
230 "%s%s,0x%%04x", txt, cc_str[(buf->data[0] >> 3) & 7]);
231 return prt_nn (buf, info, mytxt);
232}
233
234static int
235arit_n (struct buffer *buf, disassemble_info * info, char *txt)
236{
237 char mytxt[TXTSIZ];
238
239 snprintf (mytxt,TXTSIZ, txt, arit_str[(buf->data[0] >> 3) & 7]);
240 return prt_n (buf, info, mytxt);
241}
242
243static int
244rst (struct buffer *buf, disassemble_info * info, char *txt)
245{
246 info->fprintf_func (info->stream, txt, buf->data[0] & 0x38);
247 buf->n_used = buf->n_fetch;
248 return buf->n_used;
249}
250
251\f
252static int
253cis (struct buffer *buf, disassemble_info * info, char *txt ATTRIBUTE_UNUSED)
254{
255 static char * opar[] = { "ld", "cp", "in", "out" };
256 char * op;
257 char c;
258
259 c = buf->data[1];
260 op = ((0x13 & c) == 0x13) ? "ot" : (opar[c & 3]);
261 info->fprintf_func (info->stream,
262 "%s%c%s", op,
263 (c & 0x08) ? 'd' : 'i',
264 (c & 0x10) ? "r" : "");
265 buf->n_used = 2;
266 return buf->n_used;
267}
268
269static int
270dump (struct buffer *buf, disassemble_info * info, char *txt)
271{
272 int i;
273
274 info->fprintf_func (info->stream, "defb ");
275 for (i = 0; txt[i]; ++i)
276 info->fprintf_func (info->stream, i ? ", 0x%02x" : "0x%02x",
277 (unsigned char) buf->data[i]);
278 buf->n_used = i;
279 return buf->n_used;
280}
281\f
282/* Table to disassemble machine codes with prefix 0xED. */
283struct tab_elt opc_ed[] =
284{
285 { 0x70, 0xFF, prt, "in f,(c)" },
286 { 0x70, 0xFF, dump, "xx" },
287 { 0x40, 0xC7, prt_r, "in %s,(c)" },
288 { 0x71, 0xFF, prt, "out (c),0" },
289 { 0x70, 0xFF, dump, "xx" },
290 { 0x41, 0xC7, prt_r, "out (c),%s" },
291 { 0x42, 0xCF, prt_rr, "sbc hl," },
292 { 0x43, 0xCF, prt_rr_nn, "ld (0x%%04x),%s" },
293 { 0x44, 0xFF, prt, "neg" },
294 { 0x45, 0xFF, prt, "retn" },
295 { 0x46, 0xFF, prt, "im 0" },
296 { 0x47, 0xFF, prt, "ld i,a" },
297 { 0x4A, 0xCF, prt_rr, "adc hl," },
298 { 0x4B, 0xCF, prt_rr_nn, "ld %s,(0x%%04x)" },
299 { 0x4D, 0xFF, prt, "reti" },
300 { 0x56, 0xFF, prt, "im 1" },
301 { 0x57, 0xFF, prt, "ld a,i" },
302 { 0x5E, 0xFF, prt, "im 2" },
303 { 0x67, 0xFF, prt, "rrd" },
304 { 0x6F, 0xFF, prt, "rld" },
305 { 0xA0, 0xE4, cis, "" },
306 { 0xC3, 0xFF, prt, "muluw hl,bc" },
307 { 0xC5, 0xE7, prt_r, "mulub a,%s" },
308 { 0xF3, 0xFF, prt, "muluw hl,sp" },
309 { 0x00, 0x00, dump, "xx" }
310};
311
312static int
313pref_ed (struct buffer * buf, disassemble_info * info,
314 char* txt ATTRIBUTE_UNUSED)
315{
316 struct tab_elt *p;
317
318 if (fetch_data(buf, info, 1))
319 {
320 for (p = opc_ed; p->val != (buf->data[1] & p->mask); ++p)
321 ;
322 p->fp (buf, info, p->text);
323 }
324 else
325 buf->n_used = -1;
326
327 return buf->n_used;
328}
329\f
330/* Instruction names for the instructions addressing single bits. */
331static char *cb1_str[] = { "", "bit", "res", "set"};
332/* Instruction names for shifts and rotates. */
333static char *cb2_str[] =
334{
335 "rlc", "rrc", "rl", "rr", "sla", "sra", "sli", "srl"
336};
337
338static int
339pref_cb (struct buffer * buf, disassemble_info * info,
340 char* txt ATTRIBUTE_UNUSED)
341{
342 if (fetch_data (buf, info, 1))
343 {
344 buf->n_used = 2;
345 if ((buf->data[1] & 0xc0) == 0)
346 info->fprintf_func (info->stream, "%s %s",
347 cb2_str[(buf->data[1] >> 3) & 7],
348 r_str[buf->data[1] & 7]);
349 else
350 info->fprintf_func (info->stream, "%s %d,%s",
351 cb1_str[(buf->data[1] >> 6) & 3],
352 (buf->data[1] >> 3) & 7,
353 r_str[buf->data[1] & 7]);
354 }
355 else
356 buf->n_used = -1;
357
358 return buf->n_used;
359}
360\f
361static int
362addvv (struct buffer * buf, disassemble_info * info, char* txt)
363{
364 info->fprintf_func (info->stream, "add %s,%s", txt, txt);
365
366 return buf->n_used = buf->n_fetch;
367}
368
369static int
370ld_v_v (struct buffer * buf, disassemble_info * info, char* txt)
371{
372 char mytxt[TXTSIZ];
373
374 snprintf (mytxt, TXTSIZ, "ld %s%%s,%s%%s", txt, txt);
375 return ld_r_r (buf, info, mytxt);
376}
377
378static int
379prt_d (struct buffer *buf, disassemble_info * info, char *txt)
380{
381 int d;
9e919b5f 382 signed char *p;
3c9b82ba 383
c9021189 384 p = buf->data + buf->n_fetch;
3c9b82ba
NC
385
386 if (fetch_data (buf, info, 1))
387 {
388 d = p[0];
389 info->fprintf_func (info->stream, txt, d);
390 buf->n_used = buf->n_fetch;
391 }
392 else
393 buf->n_used = -1;
394
395 return buf->n_used;
396}
397
398static int
399prt_d_n (struct buffer *buf, disassemble_info * info, char *txt)
400{
401 char mytxt[TXTSIZ];
402 int d;
9e919b5f 403 signed char *p;
3c9b82ba 404
c9021189 405 p = buf->data + buf->n_fetch;
3c9b82ba
NC
406
407 if (fetch_data (buf, info, 1))
408 {
409 d = p[0];
410 snprintf (mytxt, TXTSIZ, txt, d);
411 return prt_n (buf, info, mytxt);
412 }
413 else
414 buf->n_used = -1;
415
416 return buf->n_used;
417}
418
419static int
420arit_d (struct buffer *buf, disassemble_info * info, char *txt)
421{
422 char mytxt[TXTSIZ];
9e919b5f 423 signed char c;
3c9b82ba
NC
424
425 c = buf->data[buf->n_fetch - 1];
426 snprintf (mytxt, TXTSIZ, txt, arit_str[(c >> 3) & 7]);
427 return prt_d (buf, info, mytxt);
428}
429
430static int
431ld_r_d (struct buffer *buf, disassemble_info * info, char *txt)
432{
433 char mytxt[TXTSIZ];
9e919b5f 434 signed char c;
3c9b82ba
NC
435
436 c = buf->data[buf->n_fetch - 1];
437 snprintf (mytxt, TXTSIZ, txt, r_str[(c >> 3) & 7]);
438 return prt_d (buf, info, mytxt);
439}
440
441static int
442ld_d_r(struct buffer *buf, disassemble_info * info, char *txt)
443{
444 char mytxt[TXTSIZ];
9e919b5f 445 signed char c;
3c9b82ba
NC
446
447 c = buf->data[buf->n_fetch - 1];
448 snprintf (mytxt, TXTSIZ, txt, r_str[c & 7]);
449 return prt_d (buf, info, mytxt);
450}
451
452static int
453pref_xd_cb (struct buffer * buf, disassemble_info * info, char* txt)
454{
455 if (fetch_data (buf, info, 2))
456 {
457 int d;
458 char arg[TXTSIZ];
9e919b5f 459 signed char *p;
3c9b82ba
NC
460
461 buf->n_used = 4;
462 p = buf->data;
463 d = p[2];
464
465 if (((p[3] & 0xC0) == 0x40) || ((p[3] & 7) == 0x06))
9e919b5f 466 snprintf (arg, TXTSIZ, "(%s%+d)", txt, d);
3c9b82ba 467 else
9e919b5f 468 snprintf (arg, TXTSIZ, "(%s%+d),%s", txt, d, r_str[p[3] & 7]);
3c9b82ba
NC
469
470 if ((p[3] & 0xc0) == 0)
471 info->fprintf_func (info->stream, "%s %s",
472 cb2_str[(buf->data[3] >> 3) & 7],
473 arg);
474 else
475 info->fprintf_func (info->stream, "%s %d,%s",
476 cb1_str[(buf->data[3] >> 6) & 3],
477 (buf->data[3] >> 3) & 7,
478 arg);
479 }
480 else
481 buf->n_used = -1;
482
483 return buf->n_used;
484}
485\f
486/* Table to disassemble machine codes with prefix 0xDD or 0xFD. */
487static struct tab_elt opc_ind[] =
488{
489 { 0x24, 0xF7, prt_r, "inc %s%%s" },
490 { 0x25, 0xF7, prt_r, "dec %s%%s" },
491 { 0x26, 0xF7, ld_r_n, "ld %s%%s,0x%%%%02x" },
492 { 0x21, 0xFF, prt_nn, "ld %s,0x%%04x" },
493 { 0x22, 0xFF, prt_nn, "ld (0x%%04x),%s" },
494 { 0x2A, 0xFF, prt_nn, "ld %s,(0x%%04x)" },
495 { 0x23, 0xFF, prt, "inc %s" },
496 { 0x2B, 0xFF, prt, "dec %s" },
497 { 0x29, 0xFF, addvv, "%s" },
498 { 0x09, 0xCF, prt_rr, "add %s," },
9e919b5f
AM
499 { 0x34, 0xFF, prt_d, "inc (%s%%+d)" },
500 { 0x35, 0xFF, prt_d, "dec (%s%%+d)" },
501 { 0x36, 0xFF, prt_d_n, "ld (%s%%+d),0x%%%%02x" },
3c9b82ba
NC
502
503 { 0x76, 0xFF, dump, "h" },
9e919b5f
AM
504 { 0x46, 0xC7, ld_r_d, "ld %%s,(%s%%%%+d)" },
505 { 0x70, 0xF8, ld_d_r, "ld (%s%%%%+d),%%s" },
3c9b82ba
NC
506 { 0x64, 0xF6, ld_v_v, "%s" },
507 { 0x60, 0xF0, ld_r_r, "ld %s%%s,%%s" },
508 { 0x44, 0xC6, ld_r_r, "ld %%s,%s%%s" },
509
9e919b5f 510 { 0x86, 0xC7, arit_d, "%%s(%s%%%%+d)" },
3c9b82ba
NC
511 { 0x84, 0xC6, arit_r, "%%s%s%%s" },
512
513 { 0xE1, 0xFF, prt, "pop %s" },
514 { 0xE5, 0xFF, prt, "push %s" },
515 { 0xCB, 0xFF, pref_xd_cb, "%s" },
516 { 0xE3, 0xFF, prt, "ex (sp),%s" },
517 { 0xE9, 0xFF, prt, "jp (%s)" },
518 { 0xF9, 0xFF, prt, "ld sp,%s" },
519 { 0x00, 0x00, dump, "?" },
520} ;
521
522static int
523pref_ind (struct buffer * buf, disassemble_info * info, char* txt)
524{
525 if (fetch_data (buf, info, 1))
526 {
527 char mytxt[TXTSIZ];
528 struct tab_elt *p;
529
530 for (p = opc_ind; p->val != (buf->data[1] & p->mask); ++p)
531 ;
532 snprintf (mytxt, TXTSIZ, p->text, txt);
533 p->fp (buf, info, mytxt);
534 }
535 else
536 buf->n_used = -1;
537
538 return buf->n_used;
539}
540
541/* Table to disassemble machine codes without prefix. */
542static struct tab_elt opc_main[] =
543{
544 { 0x00, 0xFF, prt, "nop" },
545 { 0x01, 0xCF, prt_rr_nn, "ld %s,0x%%04x" },
546 { 0x02, 0xFF, prt, "ld (bc),a" },
547 { 0x03, 0xCF, prt_rr, "inc " },
548 { 0x04, 0xC7, prt_r, "inc %s" },
549 { 0x05, 0xC7, prt_r, "dec %s" },
550 { 0x06, 0xC7, ld_r_n, "ld %s,0x%%02x" },
551 { 0x07, 0xFF, prt, "rlca" },
552 { 0x08, 0xFF, prt, "ex af,af'" },
553 { 0x09, 0xCF, prt_rr, "add hl," },
554 { 0x0A, 0xFF, prt, "ld a,(bc)" },
555 { 0x0B, 0xCF, prt_rr, "dec " },
556 { 0x0F, 0xFF, prt, "rrca" },
557 { 0x10, 0xFF, prt_e, "djnz " },
558 { 0x12, 0xFF, prt, "ld (de),a" },
559 { 0x17, 0xFF, prt, "rla" },
560 { 0x18, 0xFF, prt_e, "jr "},
561 { 0x1A, 0xFF, prt, "ld a,(de)" },
562 { 0x1F, 0xFF, prt, "rra" },
563 { 0x20, 0xE7, jr_cc, "jr %s,"},
564 { 0x22, 0xFF, prt_nn, "ld (0x%04x),hl" },
565 { 0x27, 0xFF, prt, "daa"},
566 { 0x2A, 0xFF, prt_nn, "ld hl,(0x%04x)" },
567 { 0x2F, 0xFF, prt, "cpl" },
568 { 0x32, 0xFF, prt_nn, "ld (0x%04x),a" },
569 { 0x37, 0xFF, prt, "scf" },
570 { 0x3A, 0xFF, prt_nn, "ld a,(0x%04x)" },
571 { 0x3F, 0xFF, prt, "ccf" },
572
573 { 0x76, 0xFF, prt, "halt" },
574 { 0x40, 0xC0, ld_r_r, "ld %s,%s"},
575
576 { 0x80, 0xC0, arit_r, "%s%s" },
577
578 { 0xC0, 0xC7, prt_cc, "ret " },
579 { 0xC1, 0xCF, pop_rr, "pop" },
580 { 0xC2, 0xC7, jp_cc_nn, "jp " },
581 { 0xC3, 0xFF, prt_nn, "jp 0x%04x" },
582 { 0xC4, 0xC7, jp_cc_nn, "call " },
583 { 0xC5, 0xCF, pop_rr, "push" },
584 { 0xC6, 0xC7, arit_n, "%s0x%%02x" },
585 { 0xC7, 0xC7, rst, "rst 0x%02x" },
586 { 0xC9, 0xFF, prt, "ret" },
587 { 0xCB, 0xFF, pref_cb, "" },
588 { 0xCD, 0xFF, prt_nn, "call 0x%04x" },
589 { 0xD3, 0xFF, prt_n, "out (0x%02x),a" },
590 { 0xD9, 0xFF, prt, "exx" },
591 { 0xDB, 0xFF, prt_n, "in a,(0x%02x)" },
592 { 0xDD, 0xFF, pref_ind, "ix" },
593 { 0xE3, 0xFF, prt, "ex (sp),hl" },
594 { 0xE9, 0xFF, prt, "jp (hl)" },
595 { 0xEB, 0xFF, prt, "ex de,hl" },
596 { 0xED, 0xFF, pref_ed, ""},
597 { 0xF3, 0xFF, prt, "di" },
598 { 0xF9, 0xFF, prt, "ld sp,hl" },
599 { 0xFB, 0xFF, prt, "ei" },
600 { 0xFD, 0xFF, pref_ind, "iy" },
601 { 0x00, 0x00, prt, "????" },
602} ;
603
604int
605print_insn_z80 (bfd_vma addr, disassemble_info * info)
606{
607 struct buffer buf;
608 struct tab_elt *p;
609
610 buf.base = addr;
611 buf.n_fetch = 0;
612 buf.n_used = 0;
613
614 if (! fetch_data (& buf, info, 1))
615 return -1;
616
617 for (p = opc_main; p->val != (buf.data[0] & p->mask); ++p)
618 ;
619 p->fp (& buf, info, p->text);
620
621 return buf.n_used;
622}
This page took 0.104791 seconds and 4 git commands to generate.