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