1/* Print National Semiconductor 32000 instructions.
2   Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007,
3   2009  Free Software Foundation, Inc.
4
5   This file is part of the GNU opcodes library.
6
7   This library is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3, or (at your option)
10   any later version.
11
12   It is distributed in the hope that it will be useful, but WITHOUT
13   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15   License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20   MA 02110-1301, USA.  */
21
22#include "sysdep.h"
23#include "bfd.h"
24#include "dis-asm.h"
25#if !defined(const) && !defined(__STDC__)
26#define const
27#endif
28#include "opcode/ns32k.h"
29#include "opintl.h"
30
31static disassemble_info *dis_info;
32
33/* Hacks to get it to compile <= READ THESE AS FIXES NEEDED.  */
34#define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
35
36static long
37read_memory_integer (unsigned char * addr, int nr)
38{
39  long val;
40  int i;
41
42  for (val = 0, i = nr - 1; i >= 0; i--)
43    {
44      val =  (val << 8);
45      val |= (0xff & *(addr + i));
46    }
47  return val;
48}
49
50/* 32000 instructions are never longer than this.  */
51#define MAXLEN 62
52
53#include <setjmp.h>
54
55struct private
56{
57  /* Points to first byte not fetched.  */
58  bfd_byte *max_fetched;
59  bfd_byte the_buffer[MAXLEN];
60  bfd_vma insn_start;
61  jmp_buf bailout;
62};
63
64
65/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
66   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
67   on error.  */
68#define FETCH_DATA(info, addr) \
69  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
70   ? 1 : fetch_data ((info), (addr)))
71
72static int
73fetch_data (struct disassemble_info *info, bfd_byte *addr)
74{
75  int status;
76  struct private *priv = (struct private *) info->private_data;
77  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
78
79  status = (*info->read_memory_func) (start,
80				      priv->max_fetched,
81				      addr - priv->max_fetched,
82				      info);
83  if (status != 0)
84    {
85      (*info->memory_error_func) (status, start, info);
86      longjmp (priv->bailout, 1);
87    }
88  else
89    priv->max_fetched = addr;
90  return 1;
91}
92
93/* Number of elements in the opcode table.  */
94#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
95
96#define NEXT_IS_ADDR	'|'
97
98
99struct 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
107static const struct ns32k_option opt_u[]= /* Restore, exit.  */
108{
109  { "r0",	0x80,	0x80	},
110  { "r1",	0x40,	0x40	},
111  { "r2",	0x20,	0x20	},
112  { "r3",	0x10,	0x10	},
113  { "r4",	0x08,	0x08	},
114  { "r5",	0x04,	0x04	},
115  { "r6",	0x02,	0x02	},
116  { "r7",	0x01,	0x01	},
117  {  0 ,	0x00,	0x00	}
118};
119
120static const struct ns32k_option opt_U[]= /* Save, enter.  */
121{
122  { "r0",	0x01,	0x01	},
123  { "r1",	0x02,	0x02	},
124  { "r2",	0x04,	0x04	},
125  { "r3",	0x08,	0x08	},
126  { "r4",	0x10,	0x10	},
127  { "r5",	0x20,	0x20	},
128  { "r6",	0x40,	0x40	},
129  { "r7",	0x80,	0x80	},
130  {  0 ,	0x00,	0x00	}
131};
132
133static const struct ns32k_option opt_O[]= /* Setcfg.  */
134{
135  { "c",	0x8,	0x8	},
136  { "m",	0x4,	0x4	},
137  { "f",	0x2,	0x2	},
138  { "i",	0x1,	0x1	},
139  {  0 ,	0x0,	0x0	}
140};
141
142static const struct ns32k_option opt_C[]= /* Cinv.  */
143{
144  { "a",	0x4,	0x4	},
145  { "i",	0x2,	0x2	},
146  { "d",	0x1,	0x1	},
147  {  0 ,	0x0,	0x0	}
148};
149
150static const struct ns32k_option opt_S[]= /* String inst.  */
151{
152  { "b",	0x1,	0x1	},
153  { "u",	0x6,	0x6	},
154  { "w",	0x2,	0x2	},
155  {  0 ,	0x0,	0x0	}
156};
157
158static const struct ns32k_option list_P532[]= /* Lpr spr.  */
159{
160  { "us",	0x0,	0xf	},
161  { "dcr",	0x1,	0xf	},
162  { "bpc",	0x2,	0xf	},
163  { "dsr",	0x3,	0xf	},
164  { "car",	0x4,	0xf	},
165  { "fp",	0x8,	0xf	},
166  { "sp",	0x9,	0xf	},
167  { "sb",	0xa,	0xf	},
168  { "usp",	0xb,	0xf	},
169  { "cfg",	0xc,	0xf	},
170  { "psr",	0xd,	0xf	},
171  { "intbase",	0xe,	0xf	},
172  { "mod",	0xf,	0xf	},
173  {  0 ,	0x00,	0xf	}
174};
175
176static const struct ns32k_option list_M532[]= /* Lmr smr.  */
177{
178  { "mcr",	0x9,	0xf	},
179  { "msr",	0xa,	0xf	},
180  { "tear",	0xb,	0xf	},
181  { "ptb0",	0xc,	0xf	},
182  { "ptb1",	0xd,	0xf	},
183  { "ivar0",	0xe,	0xf	},
184  { "ivar1",	0xf,	0xf	},
185  {  0 ,	0x0,	0xf	}
186};
187
188static const struct ns32k_option list_P032[]= /* Lpr spr.  */
189{
190  { "upsr",	0x0,	0xf	},
191  { "fp",	0x8,	0xf	},
192  { "sp",	0x9,	0xf	},
193  { "sb",	0xa,	0xf	},
194  { "psr",	0xb,	0xf	},
195  { "intbase",	0xe,	0xf	},
196  { "mod",	0xf,	0xf	},
197  {  0 ,	0x0,	0xf	}
198};
199
200static const struct ns32k_option list_M032[]= /* Lmr smr.  */
201{
202  { "bpr0",	0x0,	0xf	},
203  { "bpr1",	0x1,	0xf	},
204  { "pf0",	0x4,	0xf	},
205  { "pf1",	0x5,	0xf	},
206  { "sc",	0x8,	0xf	},
207  { "msr",	0xa,	0xf	},
208  { "bcnt",	0xb,	0xf	},
209  { "ptb0",	0xc,	0xf	},
210  { "ptb1",	0xd,	0xf	},
211  { "eia",	0xf,	0xf	},
212  {  0 ,	0x0,	0xf	}
213};
214
215
216/* Figure out which options are present.   */
217
218static void
219optlist (int options, const struct ns32k_option * optionP, char * result)
220{
221  if (options == 0)
222    {
223      sprintf (result, "[]");
224      return;
225    }
226
227  sprintf (result, "[");
228
229  for (; (options != 0) && optionP->pattern; optionP++)
230    {
231      if ((options & optionP->match) == optionP->value)
232	{
233	  /* We found a match, update result and options.  */
234	  strcat (result, optionP->pattern);
235	  options &= ~optionP->value;
236	  if (options != 0)	/* More options to come.  */
237	    strcat (result, ",");
238	}
239    }
240
241  if (options != 0)
242    strcat (result, "undefined");
243
244  strcat (result, "]");
245}
246
247static void
248list_search (int reg_value, const struct ns32k_option *optionP, char *result)
249{
250  for (; optionP->pattern; optionP++)
251    {
252      if ((reg_value & optionP->match) == optionP->value)
253	{
254	  sprintf (result, "%s", optionP->pattern);
255	  return;
256	}
257    }
258  sprintf (result, "undefined");
259}
260
261/* Extract "count" bits starting "offset" bits into buffer.  */
262
263static int
264bit_extract (bfd_byte *buffer, int offset, int count)
265{
266  int result;
267  int bit;
268
269  buffer += offset >> 3;
270  offset &= 7;
271  bit = 1;
272  result = 0;
273  while (count--)
274    {
275      FETCH_DATA (dis_info, buffer + 1);
276      if ((*buffer & (1 << offset)))
277	result |= bit;
278      if (++offset == 8)
279	{
280	  offset = 0;
281	  buffer++;
282	}
283      bit <<= 1;
284    }
285  return result;
286}
287
288/* Like bit extract but the buffer is valid and doen't need to be fetched.  */
289
290static int
291bit_extract_simple (bfd_byte *buffer, int offset, int count)
292{
293  int result;
294  int bit;
295
296  buffer += offset >> 3;
297  offset &= 7;
298  bit = 1;
299  result = 0;
300  while (count--)
301    {
302      if ((*buffer & (1 << offset)))
303	result |= bit;
304      if (++offset == 8)
305	{
306	  offset = 0;
307	  buffer++;
308	}
309      bit <<= 1;
310    }
311  return result;
312}
313
314static void
315bit_copy (bfd_byte *buffer, int offset, int count, char *to)
316{
317  for (; count > 8; count -= 8, to++, offset += 8)
318    *to = bit_extract (buffer, offset, 8);
319  *to = bit_extract (buffer, offset, count);
320}
321
322static int
323sign_extend (int value, int bits)
324{
325  value = value & ((1 << bits) - 1);
326  return (value & (1 << (bits - 1))
327	  ? value | (~((1 << bits) - 1))
328	  : value);
329}
330
331static void
332flip_bytes (char *ptr, int count)
333{
334  char tmp;
335
336  while (count > 0)
337    {
338      tmp = ptr[0];
339      ptr[0] = ptr[count - 1];
340      ptr[count - 1] = tmp;
341      ptr++;
342      count -= 2;
343    }
344}
345
346/* Given a character C, does it represent a general addressing mode?  */
347#define Is_gen(c) \
348  ((c) == 'F' || (c) == 'L' || (c) == 'B' \
349   || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
350
351/* Adressing modes.  */
352#define Adrmod_index_byte        0x1c
353#define Adrmod_index_word        0x1d
354#define Adrmod_index_doubleword  0x1e
355#define Adrmod_index_quadword    0x1f
356
357/* Is MODE an indexed addressing mode?  */
358#define Adrmod_is_index(mode) \
359  (   mode == Adrmod_index_byte \
360   || mode == Adrmod_index_word \
361   || mode == Adrmod_index_doubleword \
362   || mode == Adrmod_index_quadword)
363
364
365static int
366get_displacement (bfd_byte *buffer, int *aoffsetp)
367{
368  int Ivalue;
369  short Ivalue2;
370
371  Ivalue = bit_extract (buffer, *aoffsetp, 8);
372  switch (Ivalue & 0xc0)
373    {
374    case 0x00:
375    case 0x40:
376      Ivalue = sign_extend (Ivalue, 7);
377      *aoffsetp += 8;
378      break;
379    case 0x80:
380      Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
381      flip_bytes ((char *) & Ivalue2, 2);
382      Ivalue = sign_extend (Ivalue2, 14);
383      *aoffsetp += 16;
384      break;
385    case 0xc0:
386      Ivalue = bit_extract (buffer, *aoffsetp, 32);
387      flip_bytes ((char *) & Ivalue, 4);
388      Ivalue = sign_extend (Ivalue, 30);
389      *aoffsetp += 32;
390      break;
391    }
392  return Ivalue;
393}
394
395#if 1 /* A version that should work on ns32k f's&d's on any machine.  */
396static int
397invalid_float (bfd_byte *p, int len)
398{
399  int val;
400
401  if (len == 4)
402    val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
403	   || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
404	       && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
405  else if (len == 8)
406    val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
407	   || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
408	       && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
409		   || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
410  else
411    val = 1;
412  return (val);
413}
414#else
415/* Assumes the bytes have been swapped to local order.  */
416typedef union
417{
418  double d;
419  float f;
420  struct { unsigned m:23, e:8, :1;} sf;
421  struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
422} float_type_u;
423
424static int
425invalid_float (float_type_u *p, int len)
426{
427  int val;
428
429  if (len == sizeof (float))
430    val = (p->sf.e == 0xff
431	   || (p->sf.e == 0 && p->sf.m != 0));
432  else if (len == sizeof (double))
433    val = (p->sd.e == 0x7ff
434	   || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
435  else
436    val = 1;
437  return val;
438}
439#endif
440
441/* Print an instruction operand of category given by d.  IOFFSET is
442   the bit position below which small (<1 byte) parts of the operand can
443   be found (usually in the basic instruction, but for indexed
444   addressing it can be in the index byte).  AOFFSETP is a pointer to the
445   bit position of the addressing extension.  BUFFER contains the
446   instruction.  ADDR is where BUFFER was read from.  Put the disassembled
447   version of the operand in RESULT.  INDEX_OFFSET is the bit position
448   of the index byte (it contains garbage if this operand is not a
449   general operand using scaled indexed addressing mode).  */
450
451static int
452print_insn_arg (int d,
453		int ioffset,
454		int *aoffsetp,
455		bfd_byte *buffer,
456		bfd_vma addr,
457		char *result,
458		int index_offset)
459{
460  union
461  {
462    float f;
463    double d;
464    int i[2];
465  } value;
466  int Ivalue;
467  int addr_mode;
468  int disp1, disp2;
469  int size;
470
471  switch (d)
472    {
473    case 'f':
474      /* A "gen" operand but 5 bits from the end of instruction.  */
475      ioffset -= 5;
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 (setjmp (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