ns32k-dis.c revision 1.1.1.9 1 /* Print National Semiconductor 32000 instructions.
2 Copyright (C) 1986-2025 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 unsigned int result;
269 unsigned int bit;
270
271 if (offset < 0 || count < 0)
272 return 0;
273 buffer += offset >> 3;
274 offset &= 7;
275 bit = 1;
276 result = 0;
277 while (count--)
278 {
279 FETCH_DATA (dis_info, buffer + 1);
280 if ((*buffer & (1 << offset)))
281 result |= bit;
282 if (++offset == 8)
283 {
284 offset = 0;
285 buffer++;
286 }
287 bit <<= 1;
288 }
289 return result;
290 }
291
292 /* Like bit extract but the buffer is valid and doen't need to be fetched. */
293
294 static int
295 bit_extract_simple (bfd_byte *buffer, int offset, int count)
296 {
297 unsigned int result;
298 unsigned int bit;
299
300 if (offset < 0 || count < 0)
301 return 0;
302 buffer += offset >> 3;
303 offset &= 7;
304 bit = 1;
305 result = 0;
306 while (count--)
307 {
308 if ((*buffer & (1 << offset)))
309 result |= bit;
310 if (++offset == 8)
311 {
312 offset = 0;
313 buffer++;
314 }
315 bit <<= 1;
316 }
317 return result;
318 }
319
320 static void
321 bit_copy (bfd_byte *buffer, int offset, int count, char *to)
322 {
323 if (offset < 0 || count < 0)
324 return;
325 for (; count > 8; count -= 8, to++, offset += 8)
326 *to = bit_extract (buffer, offset, 8);
327 *to = bit_extract (buffer, offset, count);
328 }
329
330 static int
331 sign_extend (unsigned int value, unsigned int bits)
332 {
333 unsigned int sign = 1u << (bits - 1);
334 return ((value & (sign + sign - 1)) ^ sign) - sign;
335 }
336
337 static void
338 flip_bytes (char *ptr, int count)
339 {
340 char tmp;
341
342 while (count > 0)
343 {
344 tmp = ptr[0];
345 ptr[0] = ptr[count - 1];
346 ptr[count - 1] = tmp;
347 ptr++;
348 count -= 2;
349 }
350 }
351
352 /* Given a character C, does it represent a general addressing mode? */
354 #define Is_gen(c) (strchr ("FLBWDAIZf", (c)) != NULL)
355
356 /* Adressing modes. */
357 #define Adrmod_index_byte 0x1c
358 #define Adrmod_index_word 0x1d
359 #define Adrmod_index_doubleword 0x1e
360 #define Adrmod_index_quadword 0x1f
361
362 /* Is MODE an indexed addressing mode? */
363 #define Adrmod_is_index(mode) \
364 ( mode == Adrmod_index_byte \
365 || mode == Adrmod_index_word \
366 || mode == Adrmod_index_doubleword \
367 || mode == Adrmod_index_quadword)
368
369
370 static int
372 get_displacement (bfd_byte *buffer, int *aoffsetp)
373 {
374 int Ivalue;
375 short Ivalue2;
376
377 Ivalue = bit_extract (buffer, *aoffsetp, 8);
378 switch (Ivalue & 0xc0)
379 {
380 case 0x00:
381 case 0x40:
382 Ivalue = sign_extend (Ivalue, 7);
383 *aoffsetp += 8;
384 break;
385 case 0x80:
386 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
387 flip_bytes ((char *) & Ivalue2, 2);
388 Ivalue = sign_extend (Ivalue2, 14);
389 *aoffsetp += 16;
390 break;
391 case 0xc0:
392 Ivalue = bit_extract (buffer, *aoffsetp, 32);
393 flip_bytes ((char *) & Ivalue, 4);
394 Ivalue = sign_extend (Ivalue, 30);
395 *aoffsetp += 32;
396 break;
397 }
398 return Ivalue;
399 }
400
401 #if 1 /* A version that should work on ns32k f's&d's on any machine. */
402 static int
403 invalid_float (bfd_byte *p, int len)
404 {
405 int val;
406
407 if (len == 4)
408 val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
409 || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
410 && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
411 else if (len == 8)
412 val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
413 || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
414 && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
415 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
416 else
417 val = 1;
418 return (val);
419 }
420 #else
421 /* Assumes the bytes have been swapped to local order. */
422 typedef union
423 {
424 double d;
425 float f;
426 struct { unsigned m:23, e:8, :1;} sf;
427 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
428 } float_type_u;
429
430 static int
431 invalid_float (float_type_u *p, int len)
432 {
433 int val;
434
435 if (len == sizeof (float))
436 val = (p->sf.e == 0xff
437 || (p->sf.e == 0 && p->sf.m != 0));
438 else if (len == sizeof (double))
439 val = (p->sd.e == 0x7ff
440 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
441 else
442 val = 1;
443 return val;
444 }
445 #endif
446
447 /* Print an instruction operand of category given by d. IOFFSET is
448 the bit position below which small (<1 byte) parts of the operand can
449 be found (usually in the basic instruction, but for indexed
450 addressing it can be in the index byte). AOFFSETP is a pointer to the
451 bit position of the addressing extension. BUFFER contains the
452 instruction. ADDR is where BUFFER was read from. Put the disassembled
453 version of the operand in RESULT. INDEX_OFFSET is the bit position
454 of the index byte (it contains -1 if this operand is not a
455 general operand using scaled indexed addressing mode). */
456
457 static int
458 print_insn_arg (int d,
459 int ioffset,
460 int *aoffsetp,
461 bfd_byte *buffer,
462 bfd_vma addr,
463 char *result,
464 int index_offset)
465 {
466 union
467 {
468 float f;
469 double d;
470 int i[2];
471 } value;
472 int Ivalue;
473 int addr_mode;
474 int disp1, disp2;
475 int size;
476
477 switch (d)
478 {
479 case 'f':
480 /* A "gen" operand but 5 bits from the end of instruction. */
481 ioffset -= 5;
482 /* Fall through. */
483 case 'Z':
484 case 'F':
485 case 'L':
486 case 'I':
487 case 'B':
488 case 'W':
489 case 'D':
490 case 'A':
491 addr_mode = bit_extract (buffer, ioffset - 5, 5);
492 ioffset -= 5;
493 switch (addr_mode)
494 {
495 case 0x0: case 0x1: case 0x2: case 0x3:
496 case 0x4: case 0x5: case 0x6: case 0x7:
497 /* Register mode R0 -- R7. */
498 switch (d)
499 {
500 case 'F':
501 case 'L':
502 case 'Z':
503 sprintf (result, "f%d", addr_mode);
504 break;
505 default:
506 sprintf (result, "r%d", addr_mode);
507 }
508 break;
509 case 0x8: case 0x9: case 0xa: case 0xb:
510 case 0xc: case 0xd: case 0xe: case 0xf:
511 /* Register relative disp(R0 -- R7). */
512 disp1 = get_displacement (buffer, aoffsetp);
513 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
514 break;
515 case 0x10:
516 case 0x11:
517 case 0x12:
518 /* Memory relative disp2(disp1(FP, SP, SB)). */
519 disp1 = get_displacement (buffer, aoffsetp);
520 disp2 = get_displacement (buffer, aoffsetp);
521 sprintf (result, "%d(%d(%s))", disp2, disp1,
522 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
523 break;
524 case 0x13:
525 /* Reserved. */
526 sprintf (result, "reserved");
527 break;
528 case 0x14:
529 /* Immediate. */
530 switch (d)
531 {
532 default:
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 (result, "%" PRIx64, (uint64_t) (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 (result, "%" PRIx64,
674 (uint64_t) (addr + get_displacement (buffer, aoffsetp)));
675 result += strlen (result);
676 *result++ = NEXT_IS_ADDR;
677 *result = '\0';
678 break;
679 case 'i':
680 Ivalue = bit_extract (buffer, *aoffsetp, 8);
681 *aoffsetp += 8;
682 sprintf (result, "0x%x", Ivalue);
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 'U':
690 Ivalue = bit_extract (buffer, *aoffsetp, 8);
691 optlist (Ivalue, opt_U, result);
692 *aoffsetp += 8;
693 break;
694 case 'O':
695 Ivalue = bit_extract (buffer, ioffset - 9, 9);
696 optlist (Ivalue, opt_O, result);
697 ioffset -= 9;
698 break;
699 case 'C':
700 Ivalue = bit_extract (buffer, ioffset - 4, 4);
701 optlist (Ivalue, opt_C, result);
702 ioffset -= 4;
703 break;
704 case 'S':
705 Ivalue = bit_extract (buffer, ioffset - 8, 8);
706 optlist (Ivalue, opt_S, result);
707 ioffset -= 8;
708 break;
709 case 'M':
710 Ivalue = bit_extract (buffer, ioffset - 4, 4);
711 list_search (Ivalue, 0 ? list_M032 : list_M532, result);
712 ioffset -= 4;
713 break;
714 case 'P':
715 Ivalue = bit_extract (buffer, ioffset - 4, 4);
716 list_search (Ivalue, 0 ? list_P032 : list_P532, result);
717 ioffset -= 4;
718 break;
719 case 'g':
720 Ivalue = bit_extract (buffer, *aoffsetp, 3);
721 sprintf (result, "%d", Ivalue);
722 *aoffsetp += 3;
723 break;
724 case 'G':
725 Ivalue = bit_extract(buffer, *aoffsetp, 5);
726 sprintf (result, "%d", Ivalue + 1);
727 *aoffsetp += 5;
728 break;
729 }
730 return ioffset;
731 }
732
733
734 /* Print the 32000 instruction at address MEMADDR in debugged memory,
736 on STREAM. Returns length of the instruction, in bytes. */
737
738 int
739 print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
740 {
741 unsigned int i;
742 const char *d;
743 unsigned short first_word;
744 int ioffset; /* Bits into instruction. */
745 int aoffset; /* Bits into arguments. */
746 char arg_bufs[MAX_ARGS+1][ARG_LEN];
747 int argnum;
748 int maxarg;
749 struct private priv;
750 bfd_byte *buffer = priv.the_buffer;
751 dis_info = info;
752
753 info->private_data = & priv;
754 priv.max_fetched = priv.the_buffer;
755 priv.insn_start = memaddr;
756 if (OPCODES_SIGSETJMP (priv.bailout) != 0)
757 /* Error return. */
758 return -1;
759
760 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
761 us over the end of accessible data unnecessarilly. */
762 FETCH_DATA (info, buffer + 1);
763 for (i = 0; i < NOPCODES; i++)
764 if (ns32k_opcodes[i].opcode_id_size <= 8
765 && ((buffer[0]
766 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
767 == ns32k_opcodes[i].opcode_seed))
768 break;
769 if (i == NOPCODES)
770 {
771 /* Maybe it is 9 to 16 bits big. */
772 FETCH_DATA (info, buffer + 2);
773 first_word = read_memory_integer(buffer, 2);
774
775 for (i = 0; i < NOPCODES; i++)
776 if ((first_word
777 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
778 == ns32k_opcodes[i].opcode_seed)
779 break;
780
781 /* Handle undefined instructions. */
782 if (i == NOPCODES)
783 {
784 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
785 return 1;
786 }
787 }
788
789 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
790
791 ioffset = ns32k_opcodes[i].opcode_size;
792 aoffset = ns32k_opcodes[i].opcode_size;
793 d = ns32k_opcodes[i].operands;
794
795 if (*d)
796 {
797 /* Offset in bits of the first thing beyond each index byte.
798 Element 0 is for operand A and element 1 is for operand B. */
799 int index_offset[2];
800
801 /* 0 for operand A, 1 for operand B, greater for other args. */
802 int whicharg = 0;
803
804 (*dis_info->fprintf_func)(dis_info->stream, "\t");
805
806 maxarg = 0;
807
808 /* First we have to find and keep track of the index bytes,
809 if we are using scaled indexed addressing mode, since the index
810 bytes occur right after the basic instruction, not as part
811 of the addressing extension. */
812 index_offset[0] = -1;
813 index_offset[1] = -1;
814 if (Is_gen (d[1]))
815 {
816 int bitoff = d[1] == 'f' ? 10 : 5;
817 int addr_mode = bit_extract (buffer, ioffset - bitoff, 5);
818
819 if (Adrmod_is_index (addr_mode))
820 {
821 aoffset += 8;
822 index_offset[0] = aoffset;
823 }
824 }
825
826 if (d[2] && Is_gen (d[3]))
827 {
828 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
829
830 if (Adrmod_is_index (addr_mode))
831 {
832 aoffset += 8;
833 index_offset[1] = aoffset;
834 }
835 }
836
837 while (*d)
838 {
839 argnum = *d - '1';
840 if (argnum >= MAX_ARGS)
841 abort ();
842 d++;
843 if (argnum > maxarg)
844 maxarg = argnum;
845 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
846 memaddr, arg_bufs[argnum],
847 whicharg > 1 ? -1 : index_offset[whicharg]);
848 d++;
849 whicharg++;
850 }
851
852 for (argnum = 0; argnum <= maxarg; argnum++)
853 {
854 bfd_vma addr;
855 char *ch;
856
857 for (ch = arg_bufs[argnum]; *ch;)
858 {
859 if (*ch == NEXT_IS_ADDR)
860 {
861 ++ch;
862 addr = bfd_scan_vma (ch, NULL, 16);
863 (*dis_info->print_address_func) (addr, dis_info);
864 while (*ch && *ch != NEXT_IS_ADDR)
865 ++ch;
866 if (*ch)
867 ++ch;
868 }
869 else
870 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
871 }
872 if (argnum < maxarg)
873 (*dis_info->fprintf_func)(dis_info->stream, ", ");
874 }
875 }
876 return aoffset / 8;
877 }
878