source: vendor/binutils/current/opcodes/z8k-dis.c

Last change on this file was 609, checked in by bird, 22 years ago

binutils v2.14 - offical sources.

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