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