1/* Print National Semiconductor 32000 instructions.
2   Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005
3   Free Software Foundation, Inc.
4
5   This file is part of opcodes library.
6
7   This program 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 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public 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
23#include "bfd.h"
24#include "sysdep.h"
25#include "dis-asm.h"
26#if !defined(const) && !defined(__STDC__)
27#define const
28#endif
29#include "opcode/ns32k.h"
30#include "opintl.h"
31
32static disassemble_info *dis_info;
33
34/* Hacks to get it to compile <= READ THESE AS FIXES NEEDED.  */
35#define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
36
37static long
38read_memory_integer (unsigned char * addr, int nr)
39{
40  long val;
41  int i;
42
43  for (val = 0, i = nr - 1; i >= 0; i--)
44    {
45      val =  (val << 8);
46      val |= (0xff & *(addr + i));
47    }
48  return val;
49}
50
51/* 32000 instructions are never longer than this.  */
52#define MAXLEN 62
53
54#include <setjmp.h>
55
56struct private
57{
58  /* Points to first byte not fetched.  */
59  bfd_byte *max_fetched;
60  bfd_byte the_buffer[MAXLEN];
61  bfd_vma insn_start;
62  jmp_buf bailout;
63};
64
65
66/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
67   to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
68   on error.  */
69#define FETCH_DATA(info, addr) \
70  ((addr) <= ((struct private *)(info->private_data))->max_fetched \
71   ? 1 : fetch_data ((info), (addr)))
72
73static int
74fetch_data (struct disassemble_info *info, bfd_byte *addr)
75{
76  int status;
77  struct private *priv = (struct private *) info->private_data;
78  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
79
80  status = (*info->read_memory_func) (start,
81				      priv->max_fetched,
82				      addr - priv->max_fetched,
83				      info);
84  if (status != 0)
85    {
86      (*info->memory_error_func) (status, start, info);
87      longjmp (priv->bailout, 1);
88    }
89  else
90    priv->max_fetched = addr;
91  return 1;
92}
93
94/* Number of elements in the opcode table.  */
95#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
96
97#define NEXT_IS_ADDR	'|'
98
99
100struct ns32k_option
101{
102  char *pattern;		/* The option itself.  */
103  unsigned long value;		/* Binary value of the option.  */
104  unsigned long match;		/* These bits must match.  */
105};
106
107
108static const struct ns32k_option opt_u[]= /* Restore, exit.  */
109{
110  { "r0",	0x80,	0x80	},
111  { "r1",	0x40,	0x40	},
112  { "r2",	0x20,	0x20	},
113  { "r3",	0x10,	0x10	},
114  { "r4",	0x08,	0x08	},
115  { "r5",	0x04,	0x04	},
116  { "r6",	0x02,	0x02	},
117  { "r7",	0x01,	0x01	},
118  {  0 ,	0x00,	0x00	}
119};
120
121static const struct ns32k_option opt_U[]= /* Save, enter.  */
122{
123  { "r0",	0x01,	0x01	},
124  { "r1",	0x02,	0x02	},
125  { "r2",	0x04,	0x04	},
126  { "r3",	0x08,	0x08	},
127  { "r4",	0x10,	0x10	},
128  { "r5",	0x20,	0x20	},
129  { "r6",	0x40,	0x40	},
130  { "r7",	0x80,	0x80	},
131  {  0 ,	0x00,	0x00	}
132};
133
134static const struct ns32k_option opt_O[]= /* Setcfg.  */
135{
136  { "c",	0x8,	0x8	},
137  { "m",	0x4,	0x4	},
138  { "f",	0x2,	0x2	},
139  { "i",	0x1,	0x1	},
140  {  0 ,	0x0,	0x0	}
141};
142
143static const struct ns32k_option opt_C[]= /* Cinv.  */
144{
145  { "a",	0x4,	0x4	},
146  { "i",	0x2,	0x2	},
147  { "d",	0x1,	0x1	},
148  {  0 ,	0x0,	0x0	}
149};
150
151static const struct ns32k_option opt_S[]= /* String inst.  */
152{
153  { "b",	0x1,	0x1	},
154  { "u",	0x6,	0x6	},
155  { "w",	0x2,	0x2	},
156  {  0 ,	0x0,	0x0	}
157};
158
159static const struct ns32k_option list_P532[]= /* Lpr spr.  */
160{
161  { "us",	0x0,	0xf	},
162  { "dcr",	0x1,	0xf	},
163  { "bpc",	0x2,	0xf	},
164  { "dsr",	0x3,	0xf	},
165  { "car",	0x4,	0xf	},
166  { "fp",	0x8,	0xf	},
167  { "sp",	0x9,	0xf	},
168  { "sb",	0xa,	0xf	},
169  { "usp",	0xb,	0xf	},
170  { "cfg",	0xc,	0xf	},
171  { "psr",	0xd,	0xf	},
172  { "intbase",	0xe,	0xf	},
173  { "mod",	0xf,	0xf	},
174  {  0 ,	0x00,	0xf	}
175};
176
177static const struct ns32k_option list_M532[]= /* Lmr smr.  */
178{
179  { "mcr",	0x9,	0xf	},
180  { "msr",	0xa,	0xf	},
181  { "tear",	0xb,	0xf	},
182  { "ptb0",	0xc,	0xf	},
183  { "ptb1",	0xd,	0xf	},
184  { "ivar0",	0xe,	0xf	},
185  { "ivar1",	0xf,	0xf	},
186  {  0 ,	0x0,	0xf	}
187};
188
189static const struct ns32k_option list_P032[]= /* Lpr spr.  */
190{
191  { "upsr",	0x0,	0xf	},
192  { "fp",	0x8,	0xf	},
193  { "sp",	0x9,	0xf	},
194  { "sb",	0xa,	0xf	},
195  { "psr",	0xb,	0xf	},
196  { "intbase",	0xe,	0xf	},
197  { "mod",	0xf,	0xf	},
198  {  0 ,	0x0,	0xf	}
199};
200
201static const struct ns32k_option list_M032[]= /* Lmr smr.  */
202{
203  { "bpr0",	0x0,	0xf	},
204  { "bpr1",	0x1,	0xf	},
205  { "pf0",	0x4,	0xf	},
206  { "pf1",	0x5,	0xf	},
207  { "sc",	0x8,	0xf	},
208  { "msr",	0xa,	0xf	},
209  { "bcnt",	0xb,	0xf	},
210  { "ptb0",	0xc,	0xf	},
211  { "ptb1",	0xd,	0xf	},
212  { "eia",	0xf,	0xf	},
213  {  0 ,	0x0,	0xf	}
214};
215
216
217/* Figure out which options are present.   */
218
219static void
220optlist (int options, const struct ns32k_option * optionP, char * result)
221{
222  if (options == 0)
223    {
224      sprintf (result, "[]");
225      return;
226    }
227
228  sprintf (result, "[");
229
230  for (; (options != 0) && optionP->pattern; optionP++)
231    {
232      if ((options & optionP->match) == optionP->value)
233	{
234	  /* We found a match, update result and options.  */
235	  strcat (result, optionP->pattern);
236	  options &= ~optionP->value;
237	  if (options != 0)	/* More options to come.  */
238	    strcat (result, ",");
239	}
240    }
241
242  if (options != 0)
243    strcat (result, "undefined");
244
245  strcat (result, "]");
246}
247
248static void
249list_search (int reg_value, const struct ns32k_option *optionP, char *result)
250{
251  for (; optionP->pattern; optionP++)
252    {
253      if ((reg_value & optionP->match) == optionP->value)
254	{
255	  sprintf (result, "%s", optionP->pattern);
256	  return;
257	}
258    }
259  sprintf (result, "undefined");
260}
261
262/* Extract "count" bits starting "offset" bits into buffer.  */
263
264static int
265bit_extract (bfd_byte *buffer, int offset, int count)
266{
267  int result;
268  int bit;
269
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  int result;
295  int bit;
296
297  buffer += offset >> 3;
298  offset &= 7;
299  bit = 1;
300  result = 0;
301  while (count--)
302    {
303      if ((*buffer & (1 << offset)))
304	result |= bit;
305      if (++offset == 8)
306	{
307	  offset = 0;
308	  buffer++;
309	}
310      bit <<= 1;
311    }
312  return result;
313}
314
315static void
316bit_copy (bfd_byte *buffer, int offset, int count, char *to)
317{
318  for (; count > 8; count -= 8, to++, offset += 8)
319    *to = bit_extract (buffer, offset, 8);
320  *to = bit_extract (buffer, offset, count);
321}
322
323static int
324sign_extend (int value, int bits)
325{
326  value = value & ((1 << bits) - 1);
327  return (value & (1 << (bits - 1))
328	  ? value | (~((1 << bits) - 1))
329	  : value);
330}
331
332static void
333flip_bytes (char *ptr, int count)
334{
335  char tmp;
336
337  while (count > 0)
338    {
339      tmp = ptr[0];
340      ptr[0] = ptr[count - 1];
341      ptr[count - 1] = tmp;
342      ptr++;
343      count -= 2;
344    }
345}
346
347/* Given a character C, does it represent a general addressing mode?  */
348#define Is_gen(c) \
349  ((c) == 'F' || (c) == 'L' || (c) == 'B' \
350   || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
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 index;
471  int size;
472
473  switch (d)
474    {
475    case 'f':
476      /* A "gen" operand but 5 bits from the end of instruction.  */
477      ioffset -= 5;
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	  /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
621	  index = bit_extract (buffer, index_offset - 8, 3);
622	  print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
623			  result, 0);
624	  {
625	    static const char *ind = "bwdq";
626	    char *off;
627
628	    off = result + strlen (result);
629	    sprintf (off, "[r%d:%c]", index,
630		     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 (setjmp (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 addr_mode = bit_extract (buffer, ioffset - 5, 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	  d++;
835	  if (argnum > maxarg && argnum < MAX_ARGS)
836	    maxarg = argnum;
837	  ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
838				    memaddr, arg_bufs[argnum],
839				    index_offset[whicharg]);
840	  d++;
841	  whicharg++;
842	}
843      for (argnum = 0; argnum <= maxarg; argnum++)
844	{
845	  bfd_vma addr;
846	  char *ch;
847
848	  for (ch = arg_bufs[argnum]; *ch;)
849	    {
850	      if (*ch == NEXT_IS_ADDR)
851		{
852		  ++ch;
853		  addr = bfd_scan_vma (ch, NULL, 16);
854		  (*dis_info->print_address_func) (addr, dis_info);
855		  while (*ch && *ch != NEXT_IS_ADDR)
856		    ++ch;
857		  if (*ch)
858		    ++ch;
859		}
860	      else
861		(*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
862	    }
863	  if (argnum < maxarg)
864	    (*dis_info->fprintf_func)(dis_info->stream, ", ");
865	}
866    }
867  return aoffset / 8;
868}
869