xref: /netbsd-src/external/gpl3/gdb.old/dist/opcodes/ns32k-dis.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Print National Semiconductor 32000 instructions.
2    Copyright (C) 1986-2022 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
99 {
100   char *pattern;		/* The option itself.  */
101   unsigned long value;		/* Binary value of the option.  */
102   unsigned long match;		/* These bits must match.  */
103 };
104 
105 
106 static const struct ns32k_option opt_u[]= /* Restore, exit.  */
107 {
108   { "r0",	0x80,	0x80	},
109   { "r1",	0x40,	0x40	},
110   { "r2",	0x20,	0x20	},
111   { "r3",	0x10,	0x10	},
112   { "r4",	0x08,	0x08	},
113   { "r5",	0x04,	0x04	},
114   { "r6",	0x02,	0x02	},
115   { "r7",	0x01,	0x01	},
116   {  0 ,	0x00,	0x00	}
117 };
118 
119 static const struct ns32k_option opt_U[]= /* Save, enter.  */
120 {
121   { "r0",	0x01,	0x01	},
122   { "r1",	0x02,	0x02	},
123   { "r2",	0x04,	0x04	},
124   { "r3",	0x08,	0x08	},
125   { "r4",	0x10,	0x10	},
126   { "r5",	0x20,	0x20	},
127   { "r6",	0x40,	0x40	},
128   { "r7",	0x80,	0x80	},
129   {  0 ,	0x00,	0x00	}
130 };
131 
132 static const struct ns32k_option opt_O[]= /* Setcfg.  */
133 {
134   { "c",	0x8,	0x8	},
135   { "m",	0x4,	0x4	},
136   { "f",	0x2,	0x2	},
137   { "i",	0x1,	0x1	},
138   {  0 ,	0x0,	0x0	}
139 };
140 
141 static const struct ns32k_option opt_C[]= /* Cinv.  */
142 {
143   { "a",	0x4,	0x4	},
144   { "i",	0x2,	0x2	},
145   { "d",	0x1,	0x1	},
146   {  0 ,	0x0,	0x0	}
147 };
148 
149 static const struct ns32k_option opt_S[]= /* String inst.  */
150 {
151   { "b",	0x1,	0x1	},
152   { "u",	0x6,	0x6	},
153   { "w",	0x2,	0x2	},
154   {  0 ,	0x0,	0x0	}
155 };
156 
157 static const struct ns32k_option list_P532[]= /* Lpr spr.  */
158 {
159   { "us",	0x0,	0xf	},
160   { "dcr",	0x1,	0xf	},
161   { "bpc",	0x2,	0xf	},
162   { "dsr",	0x3,	0xf	},
163   { "car",	0x4,	0xf	},
164   { "fp",	0x8,	0xf	},
165   { "sp",	0x9,	0xf	},
166   { "sb",	0xa,	0xf	},
167   { "usp",	0xb,	0xf	},
168   { "cfg",	0xc,	0xf	},
169   { "psr",	0xd,	0xf	},
170   { "intbase",	0xe,	0xf	},
171   { "mod",	0xf,	0xf	},
172   {  0 ,	0x00,	0xf	}
173 };
174 
175 static const struct ns32k_option list_M532[]= /* Lmr smr.  */
176 {
177   { "mcr",	0x9,	0xf	},
178   { "msr",	0xa,	0xf	},
179   { "tear",	0xb,	0xf	},
180   { "ptb0",	0xc,	0xf	},
181   { "ptb1",	0xd,	0xf	},
182   { "ivar0",	0xe,	0xf	},
183   { "ivar1",	0xf,	0xf	},
184   {  0 ,	0x0,	0xf	}
185 };
186 
187 static const struct ns32k_option list_P032[]= /* Lpr spr.  */
188 {
189   { "upsr",	0x0,	0xf	},
190   { "fp",	0x8,	0xf	},
191   { "sp",	0x9,	0xf	},
192   { "sb",	0xa,	0xf	},
193   { "psr",	0xb,	0xf	},
194   { "intbase",	0xe,	0xf	},
195   { "mod",	0xf,	0xf	},
196   {  0 ,	0x0,	0xf	}
197 };
198 
199 static const struct ns32k_option list_M032[]= /* Lmr smr.  */
200 {
201   { "bpr0",	0x0,	0xf	},
202   { "bpr1",	0x1,	0xf	},
203   { "pf0",	0x4,	0xf	},
204   { "pf1",	0x5,	0xf	},
205   { "sc",	0x8,	0xf	},
206   { "msr",	0xa,	0xf	},
207   { "bcnt",	0xb,	0xf	},
208   { "ptb0",	0xc,	0xf	},
209   { "ptb1",	0xd,	0xf	},
210   { "eia",	0xf,	0xf	},
211   {  0 ,	0x0,	0xf	}
212 };
213 
214 
215 /* Figure out which options are present.   */
216 
217 static void
218 optlist (int options, const struct ns32k_option * optionP, char * result)
219 {
220   if (options == 0)
221     {
222       sprintf (result, "[]");
223       return;
224     }
225 
226   sprintf (result, "[");
227 
228   for (; (options != 0) && optionP->pattern; optionP++)
229     {
230       if ((options & optionP->match) == optionP->value)
231 	{
232 	  /* We found a match, update result and options.  */
233 	  strcat (result, optionP->pattern);
234 	  options &= ~optionP->value;
235 	  if (options != 0)	/* More options to come.  */
236 	    strcat (result, ",");
237 	}
238     }
239 
240   if (options != 0)
241     strcat (result, "undefined");
242 
243   strcat (result, "]");
244 }
245 
246 static void
247 list_search (int reg_value, const struct ns32k_option *optionP, char *result)
248 {
249   for (; optionP->pattern; optionP++)
250     {
251       if ((reg_value & optionP->match) == optionP->value)
252 	{
253 	  sprintf (result, "%s", optionP->pattern);
254 	  return;
255 	}
256     }
257   sprintf (result, "undefined");
258 }
259 
260 /* Extract "count" bits starting "offset" bits into buffer.  */
261 
262 static int
263 bit_extract (bfd_byte *buffer, int offset, int count)
264 {
265   unsigned int result;
266   unsigned int bit;
267 
268   if (offset < 0 || count < 0)
269     return 0;
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   unsigned int result;
295   unsigned int bit;
296 
297   if (offset < 0 || count < 0)
298     return 0;
299   buffer += offset >> 3;
300   offset &= 7;
301   bit = 1;
302   result = 0;
303   while (count--)
304     {
305       if ((*buffer & (1 << offset)))
306 	result |= bit;
307       if (++offset == 8)
308 	{
309 	  offset = 0;
310 	  buffer++;
311 	}
312       bit <<= 1;
313     }
314   return result;
315 }
316 
317 static void
318 bit_copy (bfd_byte *buffer, int offset, int count, char *to)
319 {
320   if (offset < 0 || count < 0)
321     return;
322   for (; count > 8; count -= 8, to++, offset += 8)
323     *to = bit_extract (buffer, offset, 8);
324   *to = bit_extract (buffer, offset, count);
325 }
326 
327 static int
328 sign_extend (unsigned int value, unsigned int bits)
329 {
330   unsigned int sign = 1u << (bits - 1);
331   return ((value & (sign + sign - 1)) ^ sign) - sign;
332 }
333 
334 static void
335 flip_bytes (char *ptr, int count)
336 {
337   char tmp;
338 
339   while (count > 0)
340     {
341       tmp = ptr[0];
342       ptr[0] = ptr[count - 1];
343       ptr[count - 1] = tmp;
344       ptr++;
345       count -= 2;
346     }
347 }
348 
349 /* Given a character C, does it represent a general addressing mode?  */
350 #define Is_gen(c) (strchr ("FLBWDAIZf", (c)) != NULL)
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 
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 -1 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 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       /* Fall through.  */
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 	    default:
528 	      /* I and Z are output operands and can`t be immediate
529 	         A is an address and we can`t have the address of
530 	         an immediate either. We don't know how much to increase
531 	         aoffsetp by since whatever generated this is broken
532 	         anyway!  */
533 	      sprintf (result, _("$<undefined>"));
534 	      break;
535 	    case 'B':
536 	      Ivalue = bit_extract (buffer, *aoffsetp, 8);
537 	      Ivalue = sign_extend (Ivalue, 8);
538 	      *aoffsetp += 8;
539 	      sprintf (result, "$%d", Ivalue);
540 	      break;
541 	    case 'W':
542 	      Ivalue = bit_extract (buffer, *aoffsetp, 16);
543 	      flip_bytes ((char *) & Ivalue, 2);
544 	      *aoffsetp += 16;
545 	      Ivalue = sign_extend (Ivalue, 16);
546 	      sprintf (result, "$%d", Ivalue);
547 	      break;
548 	    case 'D':
549 	      Ivalue = bit_extract (buffer, *aoffsetp, 32);
550 	      flip_bytes ((char *) & Ivalue, 4);
551 	      *aoffsetp += 32;
552 	      sprintf (result, "$%d", Ivalue);
553 	      break;
554 	    case 'F':
555 	      bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
556 	      flip_bytes ((char *) &value.f, 4);
557 	      *aoffsetp += 32;
558 	      if (INVALID_FLOAT (&value.f, 4))
559 		sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
560 	      else /* Assume host has ieee float.  */
561 		sprintf (result, "$%g", value.f);
562 	      break;
563 	    case 'L':
564 	      bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
565 	      flip_bytes ((char *) &value.d, 8);
566 	      *aoffsetp += 64;
567 	      if (INVALID_FLOAT (&value.d, 8))
568 		sprintf (result, "<<invalid double 0x%.8x%.8x>>",
569 			 value.i[1], value.i[0]);
570 	      else /* Assume host has ieee float.  */
571 		sprintf (result, "$%g", value.d);
572 	      break;
573 	    }
574 	  break;
575 	case 0x15:
576 	  /* Absolute @disp.  */
577 	  disp1 = get_displacement (buffer, aoffsetp);
578 	  sprintf (result, "@|%d|", disp1);
579 	  break;
580 	case 0x16:
581 	  /* External EXT(disp1) + disp2 (Mod table stuff).  */
582 	  disp1 = get_displacement (buffer, aoffsetp);
583 	  disp2 = get_displacement (buffer, aoffsetp);
584 	  sprintf (result, "EXT(%d) + %d", disp1, disp2);
585 	  break;
586 	case 0x17:
587 	  /* Top of stack tos.  */
588 	  sprintf (result, "tos");
589 	  break;
590 	case 0x18:
591 	  /* Memory space disp(FP).  */
592 	  disp1 = get_displacement (buffer, aoffsetp);
593 	  sprintf (result, "%d(fp)", disp1);
594 	  break;
595 	case 0x19:
596 	  /* Memory space disp(SP).  */
597 	  disp1 = get_displacement (buffer, aoffsetp);
598 	  sprintf (result, "%d(sp)", disp1);
599 	  break;
600 	case 0x1a:
601 	  /* Memory space disp(SB).  */
602 	  disp1 = get_displacement (buffer, aoffsetp);
603 	  sprintf (result, "%d(sb)", disp1);
604 	  break;
605 	case 0x1b:
606 	  /* Memory space disp(PC).  */
607 	  disp1 = get_displacement (buffer, aoffsetp);
608 	  *result++ = NEXT_IS_ADDR;
609 	  sprintf (result, "%" PRIx64, (uint64_t) (addr + disp1));
610 	  result += strlen (result);
611 	  *result++ = NEXT_IS_ADDR;
612 	  *result = '\0';
613 	  break;
614 	case 0x1c:
615 	case 0x1d:
616 	case 0x1e:
617 	case 0x1f:
618 	  {
619 	    int bit_index;
620 	    static const char *ind = "bwdq";
621 	    char *off;
622 
623 	    /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
624 	    bit_index = bit_extract (buffer, index_offset - 8, 3);
625 	    print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
626 			    result, 0);
627 	    off = result + strlen (result);
628 	    sprintf (off, "[r%d:%c]", bit_index, ind[addr_mode & 3]);
629 	  }
630 	  break;
631 	}
632       break;
633     case 'H':
634     case 'q':
635       Ivalue = bit_extract (buffer, ioffset-4, 4);
636       Ivalue = sign_extend (Ivalue, 4);
637       sprintf (result, "%d", Ivalue);
638       ioffset -= 4;
639       break;
640     case 'r':
641       Ivalue = bit_extract (buffer, ioffset-3, 3);
642       sprintf (result, "r%d", Ivalue&7);
643       ioffset -= 3;
644       break;
645     case 'd':
646       sprintf (result, "%d", get_displacement (buffer, aoffsetp));
647       break;
648     case 'b':
649       Ivalue = get_displacement (buffer, aoffsetp);
650       /* Warning!!  HACK ALERT!
651          Operand type 'b' is only used by the cmp{b,w,d} and
652          movm{b,w,d} instructions; we need to know whether
653          it's a `b' or `w' or `d' instruction; and for both
654          cmpm and movm it's stored at the same place so we
655          just grab two bits of the opcode and look at it...  */
656       size = bit_extract(buffer, ioffset-6, 2);
657       if (size == 0)		/* 00 => b.  */
658 	size = 1;
659       else if (size == 1)	/* 01 => w.  */
660 	size = 2;
661       else
662 	size = 4;		/* 11 => d.  */
663 
664       sprintf (result, "%d", (Ivalue / size) + 1);
665       break;
666     case 'p':
667       *result++ = NEXT_IS_ADDR;
668       sprintf (result, "%" PRIx64,
669 	       (uint64_t) (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 
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 (OPCODES_SIGSETJMP (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       int index_offset[2];
794 
795       /* 0 for operand A, 1 for operand B, greater for other args.  */
796       int whicharg = 0;
797 
798       (*dis_info->fprintf_func)(dis_info->stream, "\t");
799 
800       maxarg = 0;
801 
802       /* First we have to find and keep track of the index bytes,
803 	 if we are using scaled indexed addressing mode, since the index
804 	 bytes occur right after the basic instruction, not as part
805 	 of the addressing extension.  */
806       index_offset[0] = -1;
807       index_offset[1] = -1;
808       if (Is_gen (d[1]))
809 	{
810 	  int bitoff = d[1] == 'f' ? 10 : 5;
811 	  int addr_mode = bit_extract (buffer, ioffset - bitoff, 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 	  if (argnum >= MAX_ARGS)
835 	    abort ();
836 	  d++;
837 	  if (argnum > maxarg)
838 	    maxarg = argnum;
839 	  ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
840 				    memaddr, arg_bufs[argnum],
841 				    whicharg > 1 ? -1 : index_offset[whicharg]);
842 	  d++;
843 	  whicharg++;
844 	}
845 
846       for (argnum = 0; argnum <= maxarg; argnum++)
847 	{
848 	  bfd_vma addr;
849 	  char *ch;
850 
851 	  for (ch = arg_bufs[argnum]; *ch;)
852 	    {
853 	      if (*ch == NEXT_IS_ADDR)
854 		{
855 		  ++ch;
856 		  addr = bfd_scan_vma (ch, NULL, 16);
857 		  (*dis_info->print_address_func) (addr, dis_info);
858 		  while (*ch && *ch != NEXT_IS_ADDR)
859 		    ++ch;
860 		  if (*ch)
861 		    ++ch;
862 		}
863 	      else
864 		(*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
865 	    }
866 	  if (argnum < maxarg)
867 	    (*dis_info->fprintf_func)(dis_info->stream, ", ");
868 	}
869     }
870   return aoffset / 8;
871 }
872