ns32k-dis.c revision 1.1.1.5 1 /* Print National Semiconductor 32000 instructions.
2 Copyright (C) 1986-2018 Free Software Foundation, Inc.
3
4 This file is part of the GNU opcodes library.
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "sysdep.h"
22 #include "bfd.h"
23 #include "disassemble.h"
24 #if !defined(const) && !defined(__STDC__)
25 #define const
26 #endif
27 #include "opcode/ns32k.h"
28 #include "opintl.h"
29
30 static disassemble_info *dis_info;
31
32 /* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
33 #define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
34
35 static long
36 read_memory_integer (unsigned char * addr, int nr)
37 {
38 long val;
39 int i;
40
41 for (val = 0, i = nr - 1; i >= 0; i--)
42 {
43 val = (val << 8);
44 val |= (0xff & *(addr + i));
45 }
46 return val;
47 }
48
49 /* 32000 instructions are never longer than this. */
50 #define MAXLEN 62
51
52 #include <setjmp.h>
53
54 struct private
55 {
56 /* Points to first byte not fetched. */
57 bfd_byte *max_fetched;
58 bfd_byte the_buffer[MAXLEN];
59 bfd_vma insn_start;
60 OPCODES_SIGJMP_BUF bailout;
61 };
62
63
64 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
65 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
66 on error. */
67 #define FETCH_DATA(info, addr) \
68 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
69 ? 1 : fetch_data ((info), (addr)))
70
71 static int
72 fetch_data (struct disassemble_info *info, bfd_byte *addr)
73 {
74 int status;
75 struct private *priv = (struct private *) info->private_data;
76 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
77
78 status = (*info->read_memory_func) (start,
79 priv->max_fetched,
80 addr - priv->max_fetched,
81 info);
82 if (status != 0)
83 {
84 (*info->memory_error_func) (status, start, info);
85 OPCODES_SIGLONGJMP (priv->bailout, 1);
86 }
87 else
88 priv->max_fetched = addr;
89 return 1;
90 }
91
92 /* Number of elements in the opcode table. */
93 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
94
95 #define NEXT_IS_ADDR '|'
96
97
98 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
107 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
262 /* Extract "count" bits starting "offset" bits into buffer. */
264
265 static int
266 bit_extract (bfd_byte *buffer, int offset, int count)
267 {
268 int result;
269 int bit;
270
271 buffer += offset >> 3;
272 offset &= 7;
273 bit = 1;
274 result = 0;
275 while (count--)
276 {
277 FETCH_DATA (dis_info, buffer + 1);
278 if ((*buffer & (1 << offset)))
279 result |= bit;
280 if (++offset == 8)
281 {
282 offset = 0;
283 buffer++;
284 }
285 bit <<= 1;
286 }
287 return result;
288 }
289
290 /* Like bit extract but the buffer is valid and doen't need to be fetched. */
291
292 static int
293 bit_extract_simple (bfd_byte *buffer, int offset, int count)
294 {
295 int result;
296 int bit;
297
298 buffer += offset >> 3;
299 offset &= 7;
300 bit = 1;
301 result = 0;
302 while (count--)
303 {
304 if ((*buffer & (1 << offset)))
305 result |= bit;
306 if (++offset == 8)
307 {
308 offset = 0;
309 buffer++;
310 }
311 bit <<= 1;
312 }
313 return result;
314 }
315
316 static void
317 bit_copy (bfd_byte *buffer, int offset, int count, char *to)
318 {
319 for (; count > 8; count -= 8, to++, offset += 8)
320 *to = bit_extract (buffer, offset, 8);
321 *to = bit_extract (buffer, offset, count);
322 }
323
324 static int
325 sign_extend (int value, int bits)
326 {
327 value = value & ((1 << bits) - 1);
328 return (value & (1 << (bits - 1))
329 ? value | (~((1 << bits) - 1))
330 : value);
331 }
332
333 static void
334 flip_bytes (char *ptr, int count)
335 {
336 char tmp;
337
338 while (count > 0)
339 {
340 tmp = ptr[0];
341 ptr[0] = ptr[count - 1];
342 ptr[count - 1] = tmp;
343 ptr++;
344 count -= 2;
345 }
346 }
347
348 /* Given a character C, does it represent a general addressing mode? */
350 #define Is_gen(c) \
351 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
352 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
353
354 /* Adressing modes. */
355 #define Adrmod_index_byte 0x1c
356 #define Adrmod_index_word 0x1d
357 #define Adrmod_index_doubleword 0x1e
358 #define Adrmod_index_quadword 0x1f
359
360 /* Is MODE an indexed addressing mode? */
361 #define Adrmod_is_index(mode) \
362 ( mode == Adrmod_index_byte \
363 || mode == Adrmod_index_word \
364 || mode == Adrmod_index_doubleword \
365 || mode == Adrmod_index_quadword)
366
367
368 static int
370 get_displacement (bfd_byte *buffer, int *aoffsetp)
371 {
372 int Ivalue;
373 short Ivalue2;
374
375 Ivalue = bit_extract (buffer, *aoffsetp, 8);
376 switch (Ivalue & 0xc0)
377 {
378 case 0x00:
379 case 0x40:
380 Ivalue = sign_extend (Ivalue, 7);
381 *aoffsetp += 8;
382 break;
383 case 0x80:
384 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
385 flip_bytes ((char *) & Ivalue2, 2);
386 Ivalue = sign_extend (Ivalue2, 14);
387 *aoffsetp += 16;
388 break;
389 case 0xc0:
390 Ivalue = bit_extract (buffer, *aoffsetp, 32);
391 flip_bytes ((char *) & Ivalue, 4);
392 Ivalue = sign_extend (Ivalue, 30);
393 *aoffsetp += 32;
394 break;
395 }
396 return Ivalue;
397 }
398
399 #if 1 /* A version that should work on ns32k f's&d's on any machine. */
400 static int
401 invalid_float (bfd_byte *p, int len)
402 {
403 int val;
404
405 if (len == 4)
406 val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
407 || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
408 && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
409 else if (len == 8)
410 val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
411 || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
412 && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
413 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
414 else
415 val = 1;
416 return (val);
417 }
418 #else
419 /* Assumes the bytes have been swapped to local order. */
420 typedef union
421 {
422 double d;
423 float f;
424 struct { unsigned m:23, e:8, :1;} sf;
425 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
426 } float_type_u;
427
428 static int
429 invalid_float (float_type_u *p, int len)
430 {
431 int val;
432
433 if (len == sizeof (float))
434 val = (p->sf.e == 0xff
435 || (p->sf.e == 0 && p->sf.m != 0));
436 else if (len == sizeof (double))
437 val = (p->sd.e == 0x7ff
438 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
439 else
440 val = 1;
441 return val;
442 }
443 #endif
444
445 /* Print an instruction operand of category given by d. IOFFSET is
446 the bit position below which small (<1 byte) parts of the operand can
447 be found (usually in the basic instruction, but for indexed
448 addressing it can be in the index byte). AOFFSETP is a pointer to the
449 bit position of the addressing extension. BUFFER contains the
450 instruction. ADDR is where BUFFER was read from. Put the disassembled
451 version of the operand in RESULT. INDEX_OFFSET is the bit position
452 of the index byte (it contains garbage if this operand is not a
453 general operand using scaled indexed addressing mode). */
454
455 static int
456 print_insn_arg (int d,
457 int ioffset,
458 int *aoffsetp,
459 bfd_byte *buffer,
460 bfd_vma addr,
461 char *result,
462 int index_offset)
463 {
464 union
465 {
466 float f;
467 double d;
468 int i[2];
469 } value;
470 int Ivalue;
471 int addr_mode;
472 int disp1, disp2;
473 int size;
474
475 switch (d)
476 {
477 case 'f':
478 /* A "gen" operand but 5 bits from the end of instruction. */
479 ioffset -= 5;
480 /* Fall through. */
481 case 'Z':
482 case 'F':
483 case 'L':
484 case 'I':
485 case 'B':
486 case 'W':
487 case 'D':
488 case 'A':
489 addr_mode = bit_extract (buffer, ioffset - 5, 5);
490 ioffset -= 5;
491 switch (addr_mode)
492 {
493 case 0x0: case 0x1: case 0x2: case 0x3:
494 case 0x4: case 0x5: case 0x6: case 0x7:
495 /* Register mode R0 -- R7. */
496 switch (d)
497 {
498 case 'F':
499 case 'L':
500 case 'Z':
501 sprintf (result, "f%d", addr_mode);
502 break;
503 default:
504 sprintf (result, "r%d", addr_mode);
505 }
506 break;
507 case 0x8: case 0x9: case 0xa: case 0xb:
508 case 0xc: case 0xd: case 0xe: case 0xf:
509 /* Register relative disp(R0 -- R7). */
510 disp1 = get_displacement (buffer, aoffsetp);
511 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
512 break;
513 case 0x10:
514 case 0x11:
515 case 0x12:
516 /* Memory relative disp2(disp1(FP, SP, SB)). */
517 disp1 = get_displacement (buffer, aoffsetp);
518 disp2 = get_displacement (buffer, aoffsetp);
519 sprintf (result, "%d(%d(%s))", disp2, disp1,
520 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
521 break;
522 case 0x13:
523 /* Reserved. */
524 sprintf (result, "reserved");
525 break;
526 case 0x14:
527 /* Immediate. */
528 switch (d)
529 {
530 case 'I':
531 case 'Z':
532 case 'A':
533 /* I and Z are output operands and can`t be immediate
534 A is an address and we can`t have the address of
535 an immediate either. We don't know how much to increase
536 aoffsetp by since whatever generated this is broken
537 anyway! */
538 sprintf (result, _("$<undefined>"));
539 break;
540 case 'B':
541 Ivalue = bit_extract (buffer, *aoffsetp, 8);
542 Ivalue = sign_extend (Ivalue, 8);
543 *aoffsetp += 8;
544 sprintf (result, "$%d", Ivalue);
545 break;
546 case 'W':
547 Ivalue = bit_extract (buffer, *aoffsetp, 16);
548 flip_bytes ((char *) & Ivalue, 2);
549 *aoffsetp += 16;
550 Ivalue = sign_extend (Ivalue, 16);
551 sprintf (result, "$%d", Ivalue);
552 break;
553 case 'D':
554 Ivalue = bit_extract (buffer, *aoffsetp, 32);
555 flip_bytes ((char *) & Ivalue, 4);
556 *aoffsetp += 32;
557 sprintf (result, "$%d", Ivalue);
558 break;
559 case 'F':
560 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
561 flip_bytes ((char *) &value.f, 4);
562 *aoffsetp += 32;
563 if (INVALID_FLOAT (&value.f, 4))
564 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
565 else /* Assume host has ieee float. */
566 sprintf (result, "$%g", value.f);
567 break;
568 case 'L':
569 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
570 flip_bytes ((char *) &value.d, 8);
571 *aoffsetp += 64;
572 if (INVALID_FLOAT (&value.d, 8))
573 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
574 value.i[1], value.i[0]);
575 else /* Assume host has ieee float. */
576 sprintf (result, "$%g", value.d);
577 break;
578 }
579 break;
580 case 0x15:
581 /* Absolute @disp. */
582 disp1 = get_displacement (buffer, aoffsetp);
583 sprintf (result, "@|%d|", disp1);
584 break;
585 case 0x16:
586 /* External EXT(disp1) + disp2 (Mod table stuff). */
587 disp1 = get_displacement (buffer, aoffsetp);
588 disp2 = get_displacement (buffer, aoffsetp);
589 sprintf (result, "EXT(%d) + %d", disp1, disp2);
590 break;
591 case 0x17:
592 /* Top of stack tos. */
593 sprintf (result, "tos");
594 break;
595 case 0x18:
596 /* Memory space disp(FP). */
597 disp1 = get_displacement (buffer, aoffsetp);
598 sprintf (result, "%d(fp)", disp1);
599 break;
600 case 0x19:
601 /* Memory space disp(SP). */
602 disp1 = get_displacement (buffer, aoffsetp);
603 sprintf (result, "%d(sp)", disp1);
604 break;
605 case 0x1a:
606 /* Memory space disp(SB). */
607 disp1 = get_displacement (buffer, aoffsetp);
608 sprintf (result, "%d(sb)", disp1);
609 break;
610 case 0x1b:
611 /* Memory space disp(PC). */
612 disp1 = get_displacement (buffer, aoffsetp);
613 *result++ = NEXT_IS_ADDR;
614 sprintf_vma (result, addr + disp1);
615 result += strlen (result);
616 *result++ = NEXT_IS_ADDR;
617 *result = '\0';
618 break;
619 case 0x1c:
620 case 0x1d:
621 case 0x1e:
622 case 0x1f:
623 {
624 int bit_index;
625 static const char *ind = "bwdq";
626 char *off;
627
628 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
629 bit_index = bit_extract (buffer, index_offset - 8, 3);
630 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
631 result, 0);
632 off = result + strlen (result);
633 sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
634 }
635 break;
636 }
637 break;
638 case 'H':
639 case 'q':
640 Ivalue = bit_extract (buffer, ioffset-4, 4);
641 Ivalue = sign_extend (Ivalue, 4);
642 sprintf (result, "%d", Ivalue);
643 ioffset -= 4;
644 break;
645 case 'r':
646 Ivalue = bit_extract (buffer, ioffset-3, 3);
647 sprintf (result, "r%d", Ivalue&7);
648 ioffset -= 3;
649 break;
650 case 'd':
651 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
652 break;
653 case 'b':
654 Ivalue = get_displacement (buffer, aoffsetp);
655 /* Warning!! HACK ALERT!
656 Operand type 'b' is only used by the cmp{b,w,d} and
657 movm{b,w,d} instructions; we need to know whether
658 it's a `b' or `w' or `d' instruction; and for both
659 cmpm and movm it's stored at the same place so we
660 just grab two bits of the opcode and look at it... */
661 size = bit_extract(buffer, ioffset-6, 2);
662 if (size == 0) /* 00 => b. */
663 size = 1;
664 else if (size == 1) /* 01 => w. */
665 size = 2;
666 else
667 size = 4; /* 11 => d. */
668
669 sprintf (result, "%d", (Ivalue / size) + 1);
670 break;
671 case 'p':
672 *result++ = NEXT_IS_ADDR;
673 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
674 result += strlen (result);
675 *result++ = NEXT_IS_ADDR;
676 *result = '\0';
677 break;
678 case 'i':
679 Ivalue = bit_extract (buffer, *aoffsetp, 8);
680 *aoffsetp += 8;
681 sprintf (result, "0x%x", Ivalue);
682 break;
683 case 'u':
684 Ivalue = bit_extract (buffer, *aoffsetp, 8);
685 optlist (Ivalue, opt_u, result);
686 *aoffsetp += 8;
687 break;
688 case 'U':
689 Ivalue = bit_extract (buffer, *aoffsetp, 8);
690 optlist (Ivalue, opt_U, result);
691 *aoffsetp += 8;
692 break;
693 case 'O':
694 Ivalue = bit_extract (buffer, ioffset - 9, 9);
695 optlist (Ivalue, opt_O, result);
696 ioffset -= 9;
697 break;
698 case 'C':
699 Ivalue = bit_extract (buffer, ioffset - 4, 4);
700 optlist (Ivalue, opt_C, result);
701 ioffset -= 4;
702 break;
703 case 'S':
704 Ivalue = bit_extract (buffer, ioffset - 8, 8);
705 optlist (Ivalue, opt_S, result);
706 ioffset -= 8;
707 break;
708 case 'M':
709 Ivalue = bit_extract (buffer, ioffset - 4, 4);
710 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
711 ioffset -= 4;
712 break;
713 case 'P':
714 Ivalue = bit_extract (buffer, ioffset - 4, 4);
715 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
716 ioffset -= 4;
717 break;
718 case 'g':
719 Ivalue = bit_extract (buffer, *aoffsetp, 3);
720 sprintf (result, "%d", Ivalue);
721 *aoffsetp += 3;
722 break;
723 case 'G':
724 Ivalue = bit_extract(buffer, *aoffsetp, 5);
725 sprintf (result, "%d", Ivalue + 1);
726 *aoffsetp += 5;
727 break;
728 }
729 return ioffset;
730 }
731
732
733 /* Print the 32000 instruction at address MEMADDR in debugged memory,
735 on STREAM. Returns length of the instruction, in bytes. */
736
737 int
738 print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
739 {
740 unsigned int i;
741 const char *d;
742 unsigned short first_word;
743 int ioffset; /* Bits into instruction. */
744 int aoffset; /* Bits into arguments. */
745 char arg_bufs[MAX_ARGS+1][ARG_LEN];
746 int argnum;
747 int maxarg;
748 struct private priv;
749 bfd_byte *buffer = priv.the_buffer;
750 dis_info = info;
751
752 info->private_data = & priv;
753 priv.max_fetched = priv.the_buffer;
754 priv.insn_start = memaddr;
755 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
756 /* Error return. */
757 return -1;
758
759 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
760 us over the end of accessible data unnecessarilly. */
761 FETCH_DATA (info, buffer + 1);
762 for (i = 0; i < NOPCODES; i++)
763 if (ns32k_opcodes[i].opcode_id_size <= 8
764 && ((buffer[0]
765 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
766 == ns32k_opcodes[i].opcode_seed))
767 break;
768 if (i == NOPCODES)
769 {
770 /* Maybe it is 9 to 16 bits big. */
771 FETCH_DATA (info, buffer + 2);
772 first_word = read_memory_integer(buffer, 2);
773
774 for (i = 0; i < NOPCODES; i++)
775 if ((first_word
776 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
777 == ns32k_opcodes[i].opcode_seed)
778 break;
779
780 /* Handle undefined instructions. */
781 if (i == NOPCODES)
782 {
783 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
784 return 1;
785 }
786 }
787
788 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
789
790 ioffset = ns32k_opcodes[i].opcode_size;
791 aoffset = ns32k_opcodes[i].opcode_size;
792 d = ns32k_opcodes[i].operands;
793
794 if (*d)
795 {
796 /* Offset in bits of the first thing beyond each index byte.
797 Element 0 is for operand A and element 1 is for operand B.
798 The rest are irrelevant, but we put them here so we don't
799 index outside the array. */
800 int index_offset[MAX_ARGS];
801
802 /* 0 for operand A, 1 for operand B, greater for other args. */
803 int whicharg = 0;
804
805 (*dis_info->fprintf_func)(dis_info->stream, "\t");
806
807 maxarg = 0;
808
809 /* First we have to find and keep track of the index bytes,
810 if we are using scaled indexed addressing mode, since the index
811 bytes occur right after the basic instruction, not as part
812 of the addressing extension. */
813 if (Is_gen(d[1]))
814 {
815 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
816
817 if (Adrmod_is_index (addr_mode))
818 {
819 aoffset += 8;
820 index_offset[0] = aoffset;
821 }
822 }
823
824 if (d[2] && Is_gen(d[3]))
825 {
826 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
827
828 if (Adrmod_is_index (addr_mode))
829 {
830 aoffset += 8;
831 index_offset[1] = aoffset;
832 }
833 }
834
835 while (*d)
836 {
837 argnum = *d - '1';
838 d++;
839 if (argnum > maxarg && argnum < MAX_ARGS)
840 maxarg = argnum;
841 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
842 memaddr, arg_bufs[argnum],
843 index_offset[whicharg]);
844 d++;
845 whicharg++;
846 }
847 for (argnum = 0; argnum <= maxarg; argnum++)
848 {
849 bfd_vma addr;
850 char *ch;
851
852 for (ch = arg_bufs[argnum]; *ch;)
853 {
854 if (*ch == NEXT_IS_ADDR)
855 {
856 ++ch;
857 addr = bfd_scan_vma (ch, NULL, 16);
858 (*dis_info->print_address_func) (addr, dis_info);
859 while (*ch && *ch != NEXT_IS_ADDR)
860 ++ch;
861 if (*ch)
862 ++ch;
863 }
864 else
865 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
866 }
867 if (argnum < maxarg)
868 (*dis_info->fprintf_func)(dis_info->stream, ", ");
869 }
870 }
871 return aoffset / 8;
872 }
873