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