Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / opcodes / ns32k-dis.c
1 /* Print National Semiconductor 32000 instructions.
2 Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007
3 Free Software Foundation, Inc.
4
5 This file is part of the GNU opcodes library.
6
7 This library 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 3, or (at your option)
10 any later version.
11
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.
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 "bfd.h"
24 #include "dis-asm.h"
25 #if !defined(const) && !defined(__STDC__)
26 #define const
27 #endif
28 #include "opcode/ns32k.h"
29 #include "opintl.h"
30
31 static disassemble_info *dis_info;
32
33 /* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
34 #define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
35
36 static long
37 read_memory_integer (unsigned char * addr, int nr)
38 {
39 long val;
40 int i;
41
42 for (val = 0, i = nr - 1; i >= 0; i--)
43 {
44 val = (val << 8);
45 val |= (0xff & *(addr + i));
46 }
47 return val;
48 }
49
50 /* 32000 instructions are never longer than this. */
51 #define MAXLEN 62
52
53 #include <setjmp.h>
54
55 struct private
56 {
57 /* Points to first byte not fetched. */
58 bfd_byte *max_fetched;
59 bfd_byte the_buffer[MAXLEN];
60 bfd_vma insn_start;
61 jmp_buf bailout;
62 };
63
64
65 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
66 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
67 on error. */
68 #define FETCH_DATA(info, addr) \
69 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
70 ? 1 : fetch_data ((info), (addr)))
71
72 static int
73 fetch_data (struct disassemble_info *info, bfd_byte *addr)
74 {
75 int status;
76 struct private *priv = (struct private *) info->private_data;
77 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
78
79 status = (*info->read_memory_func) (start,
80 priv->max_fetched,
81 addr - priv->max_fetched,
82 info);
83 if (status != 0)
84 {
85 (*info->memory_error_func) (status, start, info);
86 longjmp (priv->bailout, 1);
87 }
88 else
89 priv->max_fetched = addr;
90 return 1;
91 }
92
93 /* Number of elements in the opcode table. */
94 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
95
96 #define NEXT_IS_ADDR '|'
97
98 \f
99 struct ns32k_option
100 {
101 char *pattern; /* The option itself. */
102 unsigned long value; /* Binary value of the option. */
103 unsigned long match; /* These bits must match. */
104 };
105
106 \f
107 static const struct ns32k_option opt_u[]= /* Restore, exit. */
108 {
109 { "r0", 0x80, 0x80 },
110 { "r1", 0x40, 0x40 },
111 { "r2", 0x20, 0x20 },
112 { "r3", 0x10, 0x10 },
113 { "r4", 0x08, 0x08 },
114 { "r5", 0x04, 0x04 },
115 { "r6", 0x02, 0x02 },
116 { "r7", 0x01, 0x01 },
117 { 0 , 0x00, 0x00 }
118 };
119
120 static const struct ns32k_option opt_U[]= /* Save, enter. */
121 {
122 { "r0", 0x01, 0x01 },
123 { "r1", 0x02, 0x02 },
124 { "r2", 0x04, 0x04 },
125 { "r3", 0x08, 0x08 },
126 { "r4", 0x10, 0x10 },
127 { "r5", 0x20, 0x20 },
128 { "r6", 0x40, 0x40 },
129 { "r7", 0x80, 0x80 },
130 { 0 , 0x00, 0x00 }
131 };
132
133 static const struct ns32k_option opt_O[]= /* Setcfg. */
134 {
135 { "c", 0x8, 0x8 },
136 { "m", 0x4, 0x4 },
137 { "f", 0x2, 0x2 },
138 { "i", 0x1, 0x1 },
139 { 0 , 0x0, 0x0 }
140 };
141
142 static const struct ns32k_option opt_C[]= /* Cinv. */
143 {
144 { "a", 0x4, 0x4 },
145 { "i", 0x2, 0x2 },
146 { "d", 0x1, 0x1 },
147 { 0 , 0x0, 0x0 }
148 };
149
150 static const struct ns32k_option opt_S[]= /* String inst. */
151 {
152 { "b", 0x1, 0x1 },
153 { "u", 0x6, 0x6 },
154 { "w", 0x2, 0x2 },
155 { 0 , 0x0, 0x0 }
156 };
157
158 static const struct ns32k_option list_P532[]= /* Lpr spr. */
159 {
160 { "us", 0x0, 0xf },
161 { "dcr", 0x1, 0xf },
162 { "bpc", 0x2, 0xf },
163 { "dsr", 0x3, 0xf },
164 { "car", 0x4, 0xf },
165 { "fp", 0x8, 0xf },
166 { "sp", 0x9, 0xf },
167 { "sb", 0xa, 0xf },
168 { "usp", 0xb, 0xf },
169 { "cfg", 0xc, 0xf },
170 { "psr", 0xd, 0xf },
171 { "intbase", 0xe, 0xf },
172 { "mod", 0xf, 0xf },
173 { 0 , 0x00, 0xf }
174 };
175
176 static const struct ns32k_option list_M532[]= /* Lmr smr. */
177 {
178 { "mcr", 0x9, 0xf },
179 { "msr", 0xa, 0xf },
180 { "tear", 0xb, 0xf },
181 { "ptb0", 0xc, 0xf },
182 { "ptb1", 0xd, 0xf },
183 { "ivar0", 0xe, 0xf },
184 { "ivar1", 0xf, 0xf },
185 { 0 , 0x0, 0xf }
186 };
187
188 static const struct ns32k_option list_P032[]= /* Lpr spr. */
189 {
190 { "upsr", 0x0, 0xf },
191 { "fp", 0x8, 0xf },
192 { "sp", 0x9, 0xf },
193 { "sb", 0xa, 0xf },
194 { "psr", 0xb, 0xf },
195 { "intbase", 0xe, 0xf },
196 { "mod", 0xf, 0xf },
197 { 0 , 0x0, 0xf }
198 };
199
200 static const struct ns32k_option list_M032[]= /* Lmr smr. */
201 {
202 { "bpr0", 0x0, 0xf },
203 { "bpr1", 0x1, 0xf },
204 { "pf0", 0x4, 0xf },
205 { "pf1", 0x5, 0xf },
206 { "sc", 0x8, 0xf },
207 { "msr", 0xa, 0xf },
208 { "bcnt", 0xb, 0xf },
209 { "ptb0", 0xc, 0xf },
210 { "ptb1", 0xd, 0xf },
211 { "eia", 0xf, 0xf },
212 { 0 , 0x0, 0xf }
213 };
214
215
216 /* Figure out which options are present. */
217
218 static void
219 optlist (int options, const struct ns32k_option * optionP, char * result)
220 {
221 if (options == 0)
222 {
223 sprintf (result, "[]");
224 return;
225 }
226
227 sprintf (result, "[");
228
229 for (; (options != 0) && optionP->pattern; optionP++)
230 {
231 if ((options & optionP->match) == optionP->value)
232 {
233 /* We found a match, update result and options. */
234 strcat (result, optionP->pattern);
235 options &= ~optionP->value;
236 if (options != 0) /* More options to come. */
237 strcat (result, ",");
238 }
239 }
240
241 if (options != 0)
242 strcat (result, "undefined");
243
244 strcat (result, "]");
245 }
246
247 static void
248 list_search (int reg_value, const struct ns32k_option *optionP, char *result)
249 {
250 for (; optionP->pattern; optionP++)
251 {
252 if ((reg_value & optionP->match) == optionP->value)
253 {
254 sprintf (result, "%s", optionP->pattern);
255 return;
256 }
257 }
258 sprintf (result, "undefined");
259 }
260 \f
261 /* Extract "count" bits starting "offset" bits into buffer. */
262
263 static int
264 bit_extract (bfd_byte *buffer, int offset, int count)
265 {
266 int result;
267 int bit;
268
269 buffer += offset >> 3;
270 offset &= 7;
271 bit = 1;
272 result = 0;
273 while (count--)
274 {
275 FETCH_DATA (dis_info, buffer + 1);
276 if ((*buffer & (1 << offset)))
277 result |= bit;
278 if (++offset == 8)
279 {
280 offset = 0;
281 buffer++;
282 }
283 bit <<= 1;
284 }
285 return result;
286 }
287
288 /* Like bit extract but the buffer is valid and doen't need to be fetched. */
289
290 static int
291 bit_extract_simple (bfd_byte *buffer, int offset, int count)
292 {
293 int result;
294 int bit;
295
296 buffer += offset >> 3;
297 offset &= 7;
298 bit = 1;
299 result = 0;
300 while (count--)
301 {
302 if ((*buffer & (1 << offset)))
303 result |= bit;
304 if (++offset == 8)
305 {
306 offset = 0;
307 buffer++;
308 }
309 bit <<= 1;
310 }
311 return result;
312 }
313
314 static void
315 bit_copy (bfd_byte *buffer, int offset, int count, char *to)
316 {
317 for (; count > 8; count -= 8, to++, offset += 8)
318 *to = bit_extract (buffer, offset, 8);
319 *to = bit_extract (buffer, offset, count);
320 }
321
322 static int
323 sign_extend (int value, int bits)
324 {
325 value = value & ((1 << bits) - 1);
326 return (value & (1 << (bits - 1))
327 ? value | (~((1 << bits) - 1))
328 : value);
329 }
330
331 static void
332 flip_bytes (char *ptr, int count)
333 {
334 char tmp;
335
336 while (count > 0)
337 {
338 tmp = ptr[0];
339 ptr[0] = ptr[count - 1];
340 ptr[count - 1] = tmp;
341 ptr++;
342 count -= 2;
343 }
344 }
345 \f
346 /* Given a character C, does it represent a general addressing mode? */
347 #define Is_gen(c) \
348 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
349 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
350
351 /* Adressing modes. */
352 #define Adrmod_index_byte 0x1c
353 #define Adrmod_index_word 0x1d
354 #define Adrmod_index_doubleword 0x1e
355 #define Adrmod_index_quadword 0x1f
356
357 /* Is MODE an indexed addressing mode? */
358 #define Adrmod_is_index(mode) \
359 ( mode == Adrmod_index_byte \
360 || mode == Adrmod_index_word \
361 || mode == Adrmod_index_doubleword \
362 || mode == Adrmod_index_quadword)
363
364 \f
365 static int
366 get_displacement (bfd_byte *buffer, int *aoffsetp)
367 {
368 int Ivalue;
369 short Ivalue2;
370
371 Ivalue = bit_extract (buffer, *aoffsetp, 8);
372 switch (Ivalue & 0xc0)
373 {
374 case 0x00:
375 case 0x40:
376 Ivalue = sign_extend (Ivalue, 7);
377 *aoffsetp += 8;
378 break;
379 case 0x80:
380 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
381 flip_bytes ((char *) & Ivalue2, 2);
382 Ivalue = sign_extend (Ivalue2, 14);
383 *aoffsetp += 16;
384 break;
385 case 0xc0:
386 Ivalue = bit_extract (buffer, *aoffsetp, 32);
387 flip_bytes ((char *) & Ivalue, 4);
388 Ivalue = sign_extend (Ivalue, 30);
389 *aoffsetp += 32;
390 break;
391 }
392 return Ivalue;
393 }
394
395 #if 1 /* A version that should work on ns32k f's&d's on any machine. */
396 static int
397 invalid_float (bfd_byte *p, int len)
398 {
399 int val;
400
401 if (len == 4)
402 val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
403 || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
404 && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
405 else if (len == 8)
406 val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
407 || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
408 && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
409 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
410 else
411 val = 1;
412 return (val);
413 }
414 #else
415 /* Assumes the bytes have been swapped to local order. */
416 typedef union
417 {
418 double d;
419 float f;
420 struct { unsigned m:23, e:8, :1;} sf;
421 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
422 } float_type_u;
423
424 static int
425 invalid_float (float_type_u *p, int len)
426 {
427 int val;
428
429 if (len == sizeof (float))
430 val = (p->sf.e == 0xff
431 || (p->sf.e == 0 && p->sf.m != 0));
432 else if (len == sizeof (double))
433 val = (p->sd.e == 0x7ff
434 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
435 else
436 val = 1;
437 return val;
438 }
439 #endif
440
441 /* Print an instruction operand of category given by d. IOFFSET is
442 the bit position below which small (<1 byte) parts of the operand can
443 be found (usually in the basic instruction, but for indexed
444 addressing it can be in the index byte). AOFFSETP is a pointer to the
445 bit position of the addressing extension. BUFFER contains the
446 instruction. ADDR is where BUFFER was read from. Put the disassembled
447 version of the operand in RESULT. INDEX_OFFSET is the bit position
448 of the index byte (it contains garbage if this operand is not a
449 general operand using scaled indexed addressing mode). */
450
451 static int
452 print_insn_arg (int d,
453 int ioffset,
454 int *aoffsetp,
455 bfd_byte *buffer,
456 bfd_vma addr,
457 char *result,
458 int index_offset)
459 {
460 union
461 {
462 float f;
463 double d;
464 int i[2];
465 } value;
466 int Ivalue;
467 int addr_mode;
468 int disp1, disp2;
469 int index;
470 int size;
471
472 switch (d)
473 {
474 case 'f':
475 /* A "gen" operand but 5 bits from the end of instruction. */
476 ioffset -= 5;
477 case 'Z':
478 case 'F':
479 case 'L':
480 case 'I':
481 case 'B':
482 case 'W':
483 case 'D':
484 case 'A':
485 addr_mode = bit_extract (buffer, ioffset - 5, 5);
486 ioffset -= 5;
487 switch (addr_mode)
488 {
489 case 0x0: case 0x1: case 0x2: case 0x3:
490 case 0x4: case 0x5: case 0x6: case 0x7:
491 /* Register mode R0 -- R7. */
492 switch (d)
493 {
494 case 'F':
495 case 'L':
496 case 'Z':
497 sprintf (result, "f%d", addr_mode);
498 break;
499 default:
500 sprintf (result, "r%d", addr_mode);
501 }
502 break;
503 case 0x8: case 0x9: case 0xa: case 0xb:
504 case 0xc: case 0xd: case 0xe: case 0xf:
505 /* Register relative disp(R0 -- R7). */
506 disp1 = get_displacement (buffer, aoffsetp);
507 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
508 break;
509 case 0x10:
510 case 0x11:
511 case 0x12:
512 /* Memory relative disp2(disp1(FP, SP, SB)). */
513 disp1 = get_displacement (buffer, aoffsetp);
514 disp2 = get_displacement (buffer, aoffsetp);
515 sprintf (result, "%d(%d(%s))", disp2, disp1,
516 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
517 break;
518 case 0x13:
519 /* Reserved. */
520 sprintf (result, "reserved");
521 break;
522 case 0x14:
523 /* Immediate. */
524 switch (d)
525 {
526 case 'I':
527 case 'Z':
528 case 'A':
529 /* I and Z are output operands and can`t be immediate
530 A is an address and we can`t have the address of
531 an immediate either. We don't know how much to increase
532 aoffsetp by since whatever generated this is broken
533 anyway! */
534 sprintf (result, _("$<undefined>"));
535 break;
536 case 'B':
537 Ivalue = bit_extract (buffer, *aoffsetp, 8);
538 Ivalue = sign_extend (Ivalue, 8);
539 *aoffsetp += 8;
540 sprintf (result, "$%d", Ivalue);
541 break;
542 case 'W':
543 Ivalue = bit_extract (buffer, *aoffsetp, 16);
544 flip_bytes ((char *) & Ivalue, 2);
545 *aoffsetp += 16;
546 Ivalue = sign_extend (Ivalue, 16);
547 sprintf (result, "$%d", Ivalue);
548 break;
549 case 'D':
550 Ivalue = bit_extract (buffer, *aoffsetp, 32);
551 flip_bytes ((char *) & Ivalue, 4);
552 *aoffsetp += 32;
553 sprintf (result, "$%d", Ivalue);
554 break;
555 case 'F':
556 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
557 flip_bytes ((char *) &value.f, 4);
558 *aoffsetp += 32;
559 if (INVALID_FLOAT (&value.f, 4))
560 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
561 else /* Assume host has ieee float. */
562 sprintf (result, "$%g", value.f);
563 break;
564 case 'L':
565 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
566 flip_bytes ((char *) &value.d, 8);
567 *aoffsetp += 64;
568 if (INVALID_FLOAT (&value.d, 8))
569 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
570 value.i[1], value.i[0]);
571 else /* Assume host has ieee float. */
572 sprintf (result, "$%g", value.d);
573 break;
574 }
575 break;
576 case 0x15:
577 /* Absolute @disp. */
578 disp1 = get_displacement (buffer, aoffsetp);
579 sprintf (result, "@|%d|", disp1);
580 break;
581 case 0x16:
582 /* External EXT(disp1) + disp2 (Mod table stuff). */
583 disp1 = get_displacement (buffer, aoffsetp);
584 disp2 = get_displacement (buffer, aoffsetp);
585 sprintf (result, "EXT(%d) + %d", disp1, disp2);
586 break;
587 case 0x17:
588 /* Top of stack tos. */
589 sprintf (result, "tos");
590 break;
591 case 0x18:
592 /* Memory space disp(FP). */
593 disp1 = get_displacement (buffer, aoffsetp);
594 sprintf (result, "%d(fp)", disp1);
595 break;
596 case 0x19:
597 /* Memory space disp(SP). */
598 disp1 = get_displacement (buffer, aoffsetp);
599 sprintf (result, "%d(sp)", disp1);
600 break;
601 case 0x1a:
602 /* Memory space disp(SB). */
603 disp1 = get_displacement (buffer, aoffsetp);
604 sprintf (result, "%d(sb)", disp1);
605 break;
606 case 0x1b:
607 /* Memory space disp(PC). */
608 disp1 = get_displacement (buffer, aoffsetp);
609 *result++ = NEXT_IS_ADDR;
610 sprintf_vma (result, addr + disp1);
611 result += strlen (result);
612 *result++ = NEXT_IS_ADDR;
613 *result = '\0';
614 break;
615 case 0x1c:
616 case 0x1d:
617 case 0x1e:
618 case 0x1f:
619 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
620 index = bit_extract (buffer, index_offset - 8, 3);
621 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
622 result, 0);
623 {
624 static const char *ind = "bwdq";
625 char *off;
626
627 off = result + strlen (result);
628 sprintf (off, "[r%d:%c]", index,
629 ind[addr_mode & 3]);
630 }
631 break;
632 }
633 break;
634 case 'H':
635 case 'q':
636 Ivalue = bit_extract (buffer, ioffset-4, 4);
637 Ivalue = sign_extend (Ivalue, 4);
638 sprintf (result, "%d", Ivalue);
639 ioffset -= 4;
640 break;
641 case 'r':
642 Ivalue = bit_extract (buffer, ioffset-3, 3);
643 sprintf (result, "r%d", Ivalue&7);
644 ioffset -= 3;
645 break;
646 case 'd':
647 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
648 break;
649 case 'b':
650 Ivalue = get_displacement (buffer, aoffsetp);
651 /* Warning!! HACK ALERT!
652 Operand type 'b' is only used by the cmp{b,w,d} and
653 movm{b,w,d} instructions; we need to know whether
654 it's a `b' or `w' or `d' instruction; and for both
655 cmpm and movm it's stored at the same place so we
656 just grab two bits of the opcode and look at it... */
657 size = bit_extract(buffer, ioffset-6, 2);
658 if (size == 0) /* 00 => b. */
659 size = 1;
660 else if (size == 1) /* 01 => w. */
661 size = 2;
662 else
663 size = 4; /* 11 => d. */
664
665 sprintf (result, "%d", (Ivalue / size) + 1);
666 break;
667 case 'p':
668 *result++ = NEXT_IS_ADDR;
669 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
670 result += strlen (result);
671 *result++ = NEXT_IS_ADDR;
672 *result = '\0';
673 break;
674 case 'i':
675 Ivalue = bit_extract (buffer, *aoffsetp, 8);
676 *aoffsetp += 8;
677 sprintf (result, "0x%x", Ivalue);
678 break;
679 case 'u':
680 Ivalue = bit_extract (buffer, *aoffsetp, 8);
681 optlist (Ivalue, opt_u, result);
682 *aoffsetp += 8;
683 break;
684 case 'U':
685 Ivalue = bit_extract (buffer, *aoffsetp, 8);
686 optlist (Ivalue, opt_U, result);
687 *aoffsetp += 8;
688 break;
689 case 'O':
690 Ivalue = bit_extract (buffer, ioffset - 9, 9);
691 optlist (Ivalue, opt_O, result);
692 ioffset -= 9;
693 break;
694 case 'C':
695 Ivalue = bit_extract (buffer, ioffset - 4, 4);
696 optlist (Ivalue, opt_C, result);
697 ioffset -= 4;
698 break;
699 case 'S':
700 Ivalue = bit_extract (buffer, ioffset - 8, 8);
701 optlist (Ivalue, opt_S, result);
702 ioffset -= 8;
703 break;
704 case 'M':
705 Ivalue = bit_extract (buffer, ioffset - 4, 4);
706 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
707 ioffset -= 4;
708 break;
709 case 'P':
710 Ivalue = bit_extract (buffer, ioffset - 4, 4);
711 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
712 ioffset -= 4;
713 break;
714 case 'g':
715 Ivalue = bit_extract (buffer, *aoffsetp, 3);
716 sprintf (result, "%d", Ivalue);
717 *aoffsetp += 3;
718 break;
719 case 'G':
720 Ivalue = bit_extract(buffer, *aoffsetp, 5);
721 sprintf (result, "%d", Ivalue + 1);
722 *aoffsetp += 5;
723 break;
724 }
725 return ioffset;
726 }
727
728 \f
729 /* Print the 32000 instruction at address MEMADDR in debugged memory,
730 on STREAM. Returns length of the instruction, in bytes. */
731
732 int
733 print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
734 {
735 unsigned int i;
736 const char *d;
737 unsigned short first_word;
738 int ioffset; /* Bits into instruction. */
739 int aoffset; /* Bits into arguments. */
740 char arg_bufs[MAX_ARGS+1][ARG_LEN];
741 int argnum;
742 int maxarg;
743 struct private priv;
744 bfd_byte *buffer = priv.the_buffer;
745 dis_info = info;
746
747 info->private_data = & priv;
748 priv.max_fetched = priv.the_buffer;
749 priv.insn_start = memaddr;
750 if (setjmp (priv.bailout) != 0)
751 /* Error return. */
752 return -1;
753
754 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
755 us over the end of accessible data unnecessarilly. */
756 FETCH_DATA (info, buffer + 1);
757 for (i = 0; i < NOPCODES; i++)
758 if (ns32k_opcodes[i].opcode_id_size <= 8
759 && ((buffer[0]
760 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
761 == ns32k_opcodes[i].opcode_seed))
762 break;
763 if (i == NOPCODES)
764 {
765 /* Maybe it is 9 to 16 bits big. */
766 FETCH_DATA (info, buffer + 2);
767 first_word = read_memory_integer(buffer, 2);
768
769 for (i = 0; i < NOPCODES; i++)
770 if ((first_word
771 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
772 == ns32k_opcodes[i].opcode_seed)
773 break;
774
775 /* Handle undefined instructions. */
776 if (i == NOPCODES)
777 {
778 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
779 return 1;
780 }
781 }
782
783 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
784
785 ioffset = ns32k_opcodes[i].opcode_size;
786 aoffset = ns32k_opcodes[i].opcode_size;
787 d = ns32k_opcodes[i].operands;
788
789 if (*d)
790 {
791 /* Offset in bits of the first thing beyond each index byte.
792 Element 0 is for operand A and element 1 is for operand B.
793 The rest are irrelevant, but we put them here so we don't
794 index outside the array. */
795 int index_offset[MAX_ARGS];
796
797 /* 0 for operand A, 1 for operand B, greater for other args. */
798 int whicharg = 0;
799
800 (*dis_info->fprintf_func)(dis_info->stream, "\t");
801
802 maxarg = 0;
803
804 /* First we have to find and keep track of the index bytes,
805 if we are using scaled indexed addressing mode, since the index
806 bytes occur right after the basic instruction, not as part
807 of the addressing extension. */
808 if (Is_gen(d[1]))
809 {
810 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
811
812 if (Adrmod_is_index (addr_mode))
813 {
814 aoffset += 8;
815 index_offset[0] = aoffset;
816 }
817 }
818
819 if (d[2] && Is_gen(d[3]))
820 {
821 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
822
823 if (Adrmod_is_index (addr_mode))
824 {
825 aoffset += 8;
826 index_offset[1] = aoffset;
827 }
828 }
829
830 while (*d)
831 {
832 argnum = *d - '1';
833 d++;
834 if (argnum > maxarg && argnum < MAX_ARGS)
835 maxarg = argnum;
836 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
837 memaddr, arg_bufs[argnum],
838 index_offset[whicharg]);
839 d++;
840 whicharg++;
841 }
842 for (argnum = 0; argnum <= maxarg; argnum++)
843 {
844 bfd_vma addr;
845 char *ch;
846
847 for (ch = arg_bufs[argnum]; *ch;)
848 {
849 if (*ch == NEXT_IS_ADDR)
850 {
851 ++ch;
852 addr = bfd_scan_vma (ch, NULL, 16);
853 (*dis_info->print_address_func) (addr, dis_info);
854 while (*ch && *ch != NEXT_IS_ADDR)
855 ++ch;
856 if (*ch)
857 ++ch;
858 }
859 else
860 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
861 }
862 if (argnum < maxarg)
863 (*dis_info->fprintf_func)(dis_info->stream, ", ");
864 }
865 }
866 return aoffset / 8;
867 }
This page took 0.05532 seconds and 4 git commands to generate.