1/* Print National Semiconductor 32000 instructions.
2   Copyright (C) 1986-2020 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
30static 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
35static long
36read_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
54struct 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
71static int
72fetch_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
98struct 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
106static 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
119static 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
132static 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
141static 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
149static 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
157static 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
175static 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
187static 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
199static 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
217static void
218optlist (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
246static void
247list_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
262static int
263bit_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
291static int
292bit_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
317static void
318bit_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
327static int
328sign_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
334static void
335flip_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
366static int
367get_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.  */
397static int
398invalid_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.  */
417typedef 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
425static int
426invalid_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
452static int
453print_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	    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	  {
621	    int bit_index;
622	    static const char *ind = "bwdq";
623	    char *off;
624
625	    /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
626	    bit_index = bit_extract (buffer, index_offset - 8, 3);
627	    print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
628			    result, 0);
629	    off = result + strlen (result);
630	    sprintf (off, "[r%d:%c]", bit_index, 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
730/* Print the 32000 instruction at address MEMADDR in debugged memory,
731   on STREAM.  Returns length of the instruction, in bytes.  */
732
733int
734print_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 (OPCODES_SIGSETJMP (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 bitoff = d[1] == 'f' ? 10 : 5;
812	  int addr_mode = bit_extract (buffer, ioffset - bitoff, 5);
813
814	  if (Adrmod_is_index (addr_mode))
815	    {
816	      aoffset += 8;
817	      index_offset[0] = aoffset;
818	    }
819	}
820
821      if (d[2] && Is_gen (d[3]))
822	{
823	  int addr_mode = bit_extract (buffer, ioffset - 10, 5);
824
825	  if (Adrmod_is_index (addr_mode))
826	    {
827	      aoffset += 8;
828	      index_offset[1] = aoffset;
829	    }
830	}
831
832      while (*d)
833	{
834	  argnum = *d - '1';
835	  d++;
836	  if (argnum > maxarg && argnum < MAX_ARGS)
837	    maxarg = argnum;
838	  ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
839				    memaddr, arg_bufs[argnum],
840				    index_offset[whicharg]);
841	  d++;
842	  if (whicharg++ >= 1)
843	    break;
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