PR binutils/12523
[deliverable/binutils-gdb.git] / opcodes / z8k-dis.c
CommitLineData
252b5132 1/* Disassemble z8000 code.
aa820537 2 Copyright 1992, 1993, 1998, 2000, 2001, 2002, 2003, 2005, 2007
5c90f90d 3 Free Software Foundation, Inc.
252b5132 4
9b201bb5 5 This file is part of the GNU opcodes library.
252b5132 6
9b201bb5 7 This library is free software; you can redistribute it and/or modify
3c25c5f6 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.
252b5132 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.
252b5132 16
3c25c5f6 17 You should have received a copy of the GNU General Public License
9b201bb5
NC
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132 21
252b5132
RH
22#include "sysdep.h"
23#include "dis-asm.h"
24
25#define DEFINE_TABLE
26#include "z8k-opc.h"
c8fd013c 27
252b5132 28#include <setjmp.h>
a0bd404e 29
3c25c5f6
NC
30typedef struct
31{
252b5132
RH
32 /* These are all indexed by nibble number (i.e only every other entry
33 of bytes is used, and every 4th entry of words). */
34 unsigned char nibbles[24];
35 unsigned char bytes[24];
36 unsigned short words[24];
37
38 /* Nibble number of first word not yet fetched. */
39 int max_fetched;
40 bfd_vma insn_start;
41 jmp_buf bailout;
42
6ddfd88c 43 int tabl_index;
252b5132
RH
44 char instr_asmsrc[80];
45 unsigned long arg_reg[0x0f];
46 unsigned long immediate;
47 unsigned long displacement;
48 unsigned long address;
49 unsigned long cond_code;
50 unsigned long ctrl_code;
51 unsigned long flags;
52 unsigned long interrupts;
3c25c5f6
NC
53}
54instr_data_s;
252b5132
RH
55
56/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
57 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
58 on error. */
59#define FETCH_DATA(info, nibble) \
ec22bdda 60 ((nibble) < ((instr_data_s *) (info->private_data))->max_fetched \
252b5132
RH
61 ? 1 : fetch_data ((info), (nibble)))
62
63static int
c8fd013c 64fetch_data (struct disassemble_info *info, int nibble)
252b5132
RH
65{
66 unsigned char mybuf[20];
67 int status;
5c90f90d 68 instr_data_s *priv = (instr_data_s *) info->private_data;
252b5132
RH
69
70 if ((nibble % 4) != 0)
71 abort ();
72
73 status = (*info->read_memory_func) (priv->insn_start,
74 (bfd_byte *) mybuf,
75 nibble / 2,
76 info);
77 if (status != 0)
78 {
79 (*info->memory_error_func) (status, priv->insn_start, info);
80 longjmp (priv->bailout, 1);
81 }
82
83 {
84 int i;
5c90f90d
KH
85 unsigned char *p = mybuf;
86
252b5132
RH
87 for (i = 0; i < nibble;)
88 {
89 priv->words[i] = (p[0] << 8) | p[1];
5c90f90d 90
252b5132
RH
91 priv->bytes[i] = *p;
92 priv->nibbles[i++] = *p >> 4;
5c90f90d 93 priv->nibbles[i++] = *p & 0xf;
252b5132
RH
94
95 ++p;
96 priv->bytes[i] = *p;
97 priv->nibbles[i++] = *p >> 4;
98 priv->nibbles[i++] = *p & 0xf;
99
100 ++p;
101 }
102 }
103 priv->max_fetched = nibble;
104 return 1;
105}
106
3c25c5f6
NC
107static char *codes[16] =
108 {
109 "f",
110 "lt",
111 "le",
112 "ule",
113 "ov/pe",
114 "mi",
115 "eq",
116 "c/ult",
117 "t",
118 "ge",
119 "gt",
120 "ugt",
121 "nov/po",
122 "pl",
123 "ne",
124 "nc/uge"
125 };
126
127static char *ctrl_names[8] =
128 {
129 "<invld>",
130 "flags",
131 "fcw",
132 "refresh",
133 "psapseg",
134 "psapoff",
135 "nspseg",
136 "nspoff"
137 };
6840198f
NC
138
139static int seg_length;
c8fd013c
CG
140int z8k_lookup_instr (unsigned char *, disassemble_info *);
141static void output_instr (instr_data_s *, unsigned long, disassemble_info *);
142static void unpack_instr (instr_data_s *, int, disassemble_info *);
143static void unparse_instr (instr_data_s *, int);
252b5132
RH
144
145static int
c8fd013c 146print_insn_z8k (bfd_vma addr, disassemble_info *info, int is_segmented)
252b5132
RH
147{
148 instr_data_s instr_data;
149
150 info->private_data = (PTR) &instr_data;
151 instr_data.max_fetched = 0;
152 instr_data.insn_start = addr;
153 if (setjmp (instr_data.bailout) != 0)
154 /* Error return. */
155 return -1;
156
3c25c5f6
NC
157 info->bytes_per_chunk = 2;
158 info->bytes_per_line = 6;
159 info->display_endian = BFD_ENDIAN_BIG;
160
252b5132 161 instr_data.tabl_index = z8k_lookup_instr (instr_data.nibbles, info);
6ddfd88c 162 if (instr_data.tabl_index >= 0)
252b5132
RH
163 {
164 unpack_instr (&instr_data, is_segmented, info);
6840198f 165 unparse_instr (&instr_data, is_segmented);
252b5132 166 output_instr (&instr_data, addr, info);
6840198f 167 return z8k_table[instr_data.tabl_index].length + seg_length;
252b5132
RH
168 }
169 else
170 {
171 FETCH_DATA (info, 4);
172 (*info->fprintf_func) (info->stream, ".word %02x%02x",
173 instr_data.bytes[0], instr_data.bytes[2]);
174 return 2;
175 }
176}
177
178int
c8fd013c 179print_insn_z8001 (bfd_vma addr, disassemble_info *info)
252b5132
RH
180{
181 return print_insn_z8k (addr, info, 1);
182}
183
184int
c8fd013c 185print_insn_z8002 (bfd_vma addr, disassemble_info *info)
252b5132
RH
186{
187 return print_insn_z8k (addr, info, 0);
188}
189
190int
c8fd013c 191z8k_lookup_instr (unsigned char *nibbles, disassemble_info *info)
252b5132 192{
252b5132
RH
193 int nibl_index, tabl_index;
194 int nibl_matched;
7f31df7c 195 int need_fetch = 0;
252b5132
RH
196 unsigned short instr_nibl;
197 unsigned short tabl_datum, datum_class, datum_value;
198
199 nibl_matched = 0;
200 tabl_index = 0;
7f31df7c 201 FETCH_DATA (info, 4);
252b5132
RH
202 while (!nibl_matched && z8k_table[tabl_index].name)
203 {
204 nibl_matched = 1;
5c90f90d
KH
205 for (nibl_index = 0;
206 nibl_index < z8k_table[tabl_index].length * 2 && nibl_matched;
207 nibl_index++)
252b5132
RH
208 {
209 if ((nibl_index % 4) == 0)
7f31df7c
CG
210 {
211 /* Fetch data only if it isn't already there. */
212 if (nibl_index >= 4 || (nibl_index < 4 && need_fetch))
213 FETCH_DATA (info, nibl_index + 4); /* Fetch one word at a time. */
214 if (nibl_index < 4)
215 need_fetch = 0;
216 else
217 need_fetch = 1;
218 }
252b5132
RH
219 instr_nibl = nibbles[nibl_index];
220
221 tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
222 datum_class = tabl_datum & CLASS_MASK;
223 datum_value = ~CLASS_MASK & tabl_datum;
224
225 switch (datum_class)
226 {
227 case CLASS_BIT:
228 if (datum_value != instr_nibl)
229 nibl_matched = 0;
230 break;
3c25c5f6
NC
231 case CLASS_IGNORE:
232 break;
252b5132
RH
233 case CLASS_00II:
234 if (!((~instr_nibl) & 0x4))
235 nibl_matched = 0;
236 break;
237 case CLASS_01II:
238 if (!(instr_nibl & 0x4))
239 nibl_matched = 0;
240 break;
241 case CLASS_0CCC:
242 if (!((~instr_nibl) & 0x8))
243 nibl_matched = 0;
244 break;
245 case CLASS_1CCC:
246 if (!(instr_nibl & 0x8))
247 nibl_matched = 0;
248 break;
249 case CLASS_0DISP7:
250 if (!((~instr_nibl) & 0x8))
251 nibl_matched = 0;
252 nibl_index += 1;
253 break;
254 case CLASS_1DISP7:
255 if (!(instr_nibl & 0x8))
256 nibl_matched = 0;
257 nibl_index += 1;
258 break;
259 case CLASS_REGN0:
260 if (instr_nibl == 0)
261 nibl_matched = 0;
262 break;
263 case CLASS_BIT_1OR2:
264 if ((instr_nibl | 0x2) != (datum_value | 0x2))
265 nibl_matched = 0;
266 break;
267 default:
268 break;
269 }
270 }
3c25c5f6 271
252b5132 272 if (nibl_matched)
3c25c5f6 273 return tabl_index;
252b5132
RH
274
275 tabl_index++;
276 }
277 return -1;
252b5132
RH
278}
279
280static void
c8fd013c
CG
281output_instr (instr_data_s *instr_data,
282 unsigned long addr ATTRIBUTE_UNUSED,
283 disassemble_info *info)
252b5132 284{
3c25c5f6 285 int num_bytes;
252b5132
RH
286 char out_str[100];
287
3c25c5f6 288 out_str[0] = 0;
252b5132 289
3c25c5f6
NC
290 num_bytes = (z8k_table[instr_data->tabl_index].length + seg_length) * 2;
291 FETCH_DATA (info, num_bytes);
252b5132
RH
292
293 strcat (out_str, instr_data->instr_asmsrc);
294
295 (*info->fprintf_func) (info->stream, "%s", out_str);
296}
297
298static void
c8fd013c 299unpack_instr (instr_data_s *instr_data, int is_segmented, disassemble_info *info)
252b5132
RH
300{
301 int nibl_count, loop;
302 unsigned short instr_nibl, instr_byte, instr_word;
303 long instr_long;
6840198f
NC
304 unsigned int tabl_datum, datum_class;
305 unsigned short datum_value;
252b5132
RH
306
307 nibl_count = 0;
308 loop = 0;
6840198f 309 seg_length = 0;
3c25c5f6 310
252b5132
RH
311 while (z8k_table[instr_data->tabl_index].byte_info[loop] != 0)
312 {
313 FETCH_DATA (info, nibl_count + 4 - (nibl_count % 4));
314 instr_nibl = instr_data->nibbles[nibl_count];
ec22bdda
KH
315 instr_byte = instr_data->bytes[nibl_count & ~1];
316 instr_word = instr_data->words[nibl_count & ~3];
252b5132
RH
317
318 tabl_datum = z8k_table[instr_data->tabl_index].byte_info[loop];
319 datum_class = tabl_datum & CLASS_MASK;
320 datum_value = tabl_datum & ~CLASS_MASK;
321
322 switch (datum_class)
323 {
252b5132
RH
324 case CLASS_DISP:
325 switch (datum_value)
326 {
327 case ARG_DISP16:
7f6621cd
KH
328 instr_data->displacement = instr_data->insn_start + 4
329 + (signed short) (instr_word & 0xffff);
252b5132
RH
330 nibl_count += 3;
331 break;
332 case ARG_DISP12:
7f6621cd 333 if (instr_word & 0x800)
3c25c5f6
NC
334 /* Negative 12 bit displacement. */
335 instr_data->displacement = instr_data->insn_start + 2
336 - (signed short) ((instr_word & 0xfff) | 0xf000) * 2;
7f6621cd 337 else
3c25c5f6
NC
338 instr_data->displacement = instr_data->insn_start + 2
339 - (instr_word & 0x0fff) * 2;
340
252b5132
RH
341 nibl_count += 2;
342 break;
343 default:
344 break;
345 }
346 break;
347 case CLASS_IMM:
348 switch (datum_value)
349 {
350 case ARG_IMM4:
351 instr_data->immediate = instr_nibl;
352 break;
3c25c5f6
NC
353 case ARG_NIM4:
354 instr_data->immediate = (- instr_nibl) & 0xf;
355 break;
252b5132 356 case ARG_NIM8:
3c25c5f6 357 instr_data->immediate = (- instr_byte) & 0xff;
252b5132
RH
358 nibl_count += 1;
359 break;
360 case ARG_IMM8:
361 instr_data->immediate = instr_byte;
362 nibl_count += 1;
363 break;
364 case ARG_IMM16:
365 instr_data->immediate = instr_word;
366 nibl_count += 3;
367 break;
368 case ARG_IMM32:
369 FETCH_DATA (info, nibl_count + 8);
370 instr_long = (instr_data->words[nibl_count] << 16)
371 | (instr_data->words[nibl_count + 4]);
372 instr_data->immediate = instr_long;
373 nibl_count += 7;
374 break;
375 case ARG_IMMN:
376 instr_data->immediate = instr_nibl - 1;
377 break;
378 case ARG_IMM4M1:
379 instr_data->immediate = instr_nibl + 1;
380 break;
381 case ARG_IMM_1:
382 instr_data->immediate = 1;
383 break;
384 case ARG_IMM_2:
385 instr_data->immediate = 2;
386 break;
387 case ARG_IMM2:
388 instr_data->immediate = instr_nibl & 0x3;
389 break;
390 default:
391 break;
392 }
393 break;
394 case CLASS_CC:
395 instr_data->cond_code = instr_nibl;
396 break;
252b5132
RH
397 case CLASS_ADDRESS:
398 if (is_segmented)
399 {
400 if (instr_nibl & 0x8)
401 {
402 FETCH_DATA (info, nibl_count + 8);
403 instr_long = (instr_data->words[nibl_count] << 16)
404 | (instr_data->words[nibl_count + 4]);
7f31df7c 405 instr_data->address = ((instr_word & 0x7f00) << 16)
7f6621cd 406 + (instr_long & 0xffff);
252b5132 407 nibl_count += 7;
7f6621cd 408 seg_length = 2;
252b5132
RH
409 }
410 else
411 {
7f31df7c 412 instr_data->address = ((instr_word & 0x7f00) << 16)
7f6621cd 413 + (instr_word & 0x00ff);
252b5132
RH
414 nibl_count += 3;
415 }
416 }
417 else
418 {
419 instr_data->address = instr_word;
420 nibl_count += 3;
421 }
422 break;
423 case CLASS_0CCC:
252b5132 424 case CLASS_1CCC:
6840198f 425 instr_data->ctrl_code = instr_nibl & 0x7;
252b5132
RH
426 break;
427 case CLASS_0DISP7:
7f6621cd
KH
428 instr_data->displacement =
429 instr_data->insn_start + 2 - (instr_byte & 0x7f) * 2;
252b5132
RH
430 nibl_count += 1;
431 break;
432 case CLASS_1DISP7:
7f6621cd
KH
433 instr_data->displacement =
434 instr_data->insn_start + 2 - (instr_byte & 0x7f) * 2;
252b5132
RH
435 nibl_count += 1;
436 break;
437 case CLASS_01II:
438 instr_data->interrupts = instr_nibl & 0x3;
439 break;
440 case CLASS_00II:
441 instr_data->interrupts = instr_nibl & 0x3;
442 break;
3c25c5f6 443 case CLASS_IGNORE:
252b5132 444 case CLASS_BIT:
6840198f 445 instr_data->ctrl_code = instr_nibl & 0x7;
252b5132 446 break;
252b5132
RH
447 case CLASS_FLAGS:
448 instr_data->flags = instr_nibl;
449 break;
450 case CLASS_REG:
451 instr_data->arg_reg[datum_value] = instr_nibl;
452 break;
252b5132
RH
453 case CLASS_REGN0:
454 instr_data->arg_reg[datum_value] = instr_nibl;
455 break;
7f6621cd
KH
456 case CLASS_DISP8:
457 instr_data->displacement =
458 instr_data->insn_start + 2 + (signed char) instr_byte * 2;
6840198f 459 nibl_count += 1;
7f6621cd 460 break;
3c25c5f6
NC
461 case CLASS_BIT_1OR2:
462 instr_data->immediate = ((instr_nibl >> 1) & 0x1) + 1;
463 nibl_count += 1;
464 break;
252b5132 465 default:
7f6621cd 466 abort ();
252b5132
RH
467 break;
468 }
469
470 loop += 1;
471 nibl_count += 1;
472 }
473}
474
a0bd404e
CG
475static void
476print_intr(char *tmp_str, unsigned long interrupts)
477{
478 int comma = 0;
479
480 *tmp_str = 0;
481 if (! (interrupts & 2))
482 {
483 strcat (tmp_str, "vi");
484 comma = 1;
485 }
486 if (! (interrupts & 1))
487 {
488 if (comma) strcat (tmp_str, ",");
489 strcat (tmp_str, "nvi");
490 }
491}
492
493static void
494print_flags(char *tmp_str, unsigned long flags)
495{
496 int comma = 0;
497
498 *tmp_str = 0;
499 if (flags & 8)
500 {
501 strcat (tmp_str, "c");
502 comma = 1;
503 }
504 if (flags & 4)
505 {
506 if (comma) strcat (tmp_str, ",");
507 strcat (tmp_str, "z");
508 comma = 1;
509 }
510 if (flags & 2)
511 {
512 if (comma) strcat (tmp_str, ",");
513 strcat (tmp_str, "s");
514 comma = 1;
515 }
516 if (flags & 1)
517 {
518 if (comma) strcat (tmp_str, ",");
519 strcat (tmp_str, "p");
520 }
521}
7f31df7c 522
252b5132 523static void
c8fd013c 524unparse_instr (instr_data_s *instr_data, int is_segmented)
252b5132 525{
6840198f
NC
526 unsigned short datum_value;
527 unsigned int tabl_datum, datum_class;
252b5132
RH
528 int loop, loop_limit;
529 char out_str[80], tmp_str[25];
530
3c25c5f6 531 sprintf (out_str, "%s\t", z8k_table[instr_data->tabl_index].name);
252b5132
RH
532
533 loop_limit = z8k_table[instr_data->tabl_index].noperands;
534 for (loop = 0; loop < loop_limit; loop++)
535 {
536 if (loop)
537 strcat (out_str, ",");
538
539 tabl_datum = z8k_table[instr_data->tabl_index].arg_info[loop];
540 datum_class = tabl_datum & CLASS_MASK;
541 datum_value = tabl_datum & ~CLASS_MASK;
542
543 switch (datum_class)
544 {
545 case CLASS_X:
3c25c5f6
NC
546 sprintf (tmp_str, "0x%0lx(r%ld)", instr_data->address,
547 instr_data->arg_reg[datum_value]);
252b5132
RH
548 strcat (out_str, tmp_str);
549 break;
550 case CLASS_BA:
3c25c5f6 551 if (is_segmented)
14899840 552 sprintf (tmp_str, "rr%ld(#0x%lx)", instr_data->arg_reg[datum_value],
3c25c5f6
NC
553 instr_data->immediate);
554 else
14899840 555 sprintf (tmp_str, "r%ld(#0x%lx)", instr_data->arg_reg[datum_value],
3c25c5f6 556 instr_data->immediate);
252b5132
RH
557 strcat (out_str, tmp_str);
558 break;
559 case CLASS_BX:
3c25c5f6
NC
560 if (is_segmented)
561 sprintf (tmp_str, "rr%ld(r%ld)", instr_data->arg_reg[datum_value],
562 instr_data->arg_reg[ARG_RX]);
563 else
564 sprintf (tmp_str, "r%ld(r%ld)", instr_data->arg_reg[datum_value],
565 instr_data->arg_reg[ARG_RX]);
252b5132
RH
566 strcat (out_str, tmp_str);
567 break;
568 case CLASS_DISP:
6840198f 569 sprintf (tmp_str, "0x%0lx", instr_data->displacement);
252b5132
RH
570 strcat (out_str, tmp_str);
571 break;
572 case CLASS_IMM:
a0bd404e
CG
573 if (datum_value == ARG_IMM2) /* True with EI/DI instructions only. */
574 {
575 print_intr (tmp_str, instr_data->interrupts);
576 strcat (out_str, tmp_str);
577 break;
578 }
252b5132
RH
579 sprintf (tmp_str, "#0x%0lx", instr_data->immediate);
580 strcat (out_str, tmp_str);
581 break;
582 case CLASS_CC:
583 sprintf (tmp_str, "%s", codes[instr_data->cond_code]);
584 strcat (out_str, tmp_str);
585 break;
586 case CLASS_CTRL:
6840198f 587 sprintf (tmp_str, "%s", ctrl_names[instr_data->ctrl_code]);
252b5132
RH
588 strcat (out_str, tmp_str);
589 break;
590 case CLASS_DA:
591 case CLASS_ADDRESS:
6840198f 592 sprintf (tmp_str, "0x%0lx", instr_data->address);
252b5132
RH
593 strcat (out_str, tmp_str);
594 break;
595 case CLASS_IR:
a5d2034a
NC
596 if (is_segmented)
597 sprintf (tmp_str, "@rr%ld", instr_data->arg_reg[datum_value]);
598 else
599 sprintf (tmp_str, "@r%ld", instr_data->arg_reg[datum_value]);
252b5132
RH
600 strcat (out_str, tmp_str);
601 break;
6ddfd88c
CG
602 case CLASS_IRO:
603 sprintf (tmp_str, "@r%ld", instr_data->arg_reg[datum_value]);
604 strcat (out_str, tmp_str);
605 break;
252b5132 606 case CLASS_FLAGS:
a0bd404e 607 print_flags(tmp_str, instr_data->flags);
252b5132
RH
608 strcat (out_str, tmp_str);
609 break;
610 case CLASS_REG_BYTE:
611 if (instr_data->arg_reg[datum_value] >= 0x8)
a5d2034a
NC
612 sprintf (tmp_str, "rl%ld",
613 instr_data->arg_reg[datum_value] - 0x8);
252b5132 614 else
a5d2034a 615 sprintf (tmp_str, "rh%ld", instr_data->arg_reg[datum_value]);
252b5132
RH
616 strcat (out_str, tmp_str);
617 break;
618 case CLASS_REG_WORD:
619 sprintf (tmp_str, "r%ld", instr_data->arg_reg[datum_value]);
620 strcat (out_str, tmp_str);
621 break;
622 case CLASS_REG_QUAD:
623 sprintf (tmp_str, "rq%ld", instr_data->arg_reg[datum_value]);
624 strcat (out_str, tmp_str);
625 break;
626 case CLASS_REG_LONG:
627 sprintf (tmp_str, "rr%ld", instr_data->arg_reg[datum_value]);
628 strcat (out_str, tmp_str);
629 break;
6840198f 630 case CLASS_PR:
7f6621cd
KH
631 if (is_segmented)
632 sprintf (tmp_str, "rr%ld", instr_data->arg_reg[datum_value]);
633 else
634 sprintf (tmp_str, "r%ld", instr_data->arg_reg[datum_value]);
6840198f
NC
635 strcat (out_str, tmp_str);
636 break;
252b5132 637 default:
7f6621cd 638 abort ();
252b5132
RH
639 break;
640 }
641 }
642
643 strcpy (instr_data->instr_asmsrc, out_str);
644}
This page took 0.627293 seconds and 4 git commands to generate.