1/* Print National Semiconductor 32000 instructions.
2   Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007
3   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 index;
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    case 'Z':
478    case 'F':
479    case 'L':
480    case 'I':
481    case 'B':
482    case 'W':
483    case 'D':
484    case 'A':
485      addr_mode = bit_extract (buffer, ioffset - 5, 5);
486      ioffset -= 5;
487      switch (addr_mode)
488	{
489	case 0x0: case 0x1: case 0x2: case 0x3:
490	case 0x4: case 0x5: case 0x6: case 0x7:
491	  /* Register mode R0 -- R7.  */
492	  switch (d)
493	    {
494	    case 'F':
495	    case 'L':
496	    case 'Z':
497	      sprintf (result, "f%d", addr_mode);
498	      break;
499	    default:
500	      sprintf (result, "r%d", addr_mode);
501	    }
502	  break;
503	case 0x8: case 0x9: case 0xa: case 0xb:
504	case 0xc: case 0xd: case 0xe: case 0xf:
505	  /* Register relative disp(R0 -- R7).  */
506	  disp1 = get_displacement (buffer, aoffsetp);
507	  sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
508	  break;
509	case 0x10:
510	case 0x11:
511	case 0x12:
512	  /* Memory relative disp2(disp1(FP, SP, SB)).  */
513	  disp1 = get_displacement (buffer, aoffsetp);
514	  disp2 = get_displacement (buffer, aoffsetp);
515	  sprintf (result, "%d(%d(%s))", disp2, disp1,
516		   addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
517	  break;
518	case 0x13:
519	  /* Reserved.  */
520	  sprintf (result, "reserved");
521	  break;
522	case 0x14:
523	  /* Immediate.  */
524	  switch (d)
525	    {
526	    case 'I':
527	    case 'Z':
528	    case 'A':
529	      /* I and Z are output operands and can`t be immediate
530	         A is an address and we can`t have the address of
531	         an immediate either. We don't know how much to increase
532	         aoffsetp by since whatever generated this is broken
533	         anyway!  */
534	      sprintf (result, _("$<undefined>"));
535	      break;
536	    case 'B':
537	      Ivalue = bit_extract (buffer, *aoffsetp, 8);
538	      Ivalue = sign_extend (Ivalue, 8);
539	      *aoffsetp += 8;
540	      sprintf (result, "$%d", Ivalue);
541	      break;
542	    case 'W':
543	      Ivalue = bit_extract (buffer, *aoffsetp, 16);
544	      flip_bytes ((char *) & Ivalue, 2);
545	      *aoffsetp += 16;
546	      Ivalue = sign_extend (Ivalue, 16);
547	      sprintf (result, "$%d", Ivalue);
548	      break;
549	    case 'D':
550	      Ivalue = bit_extract (buffer, *aoffsetp, 32);
551	      flip_bytes ((char *) & Ivalue, 4);
552	      *aoffsetp += 32;
553	      sprintf (result, "$%d", Ivalue);
554	      break;
555	    case 'F':
556	      bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
557	      flip_bytes ((char *) &value.f, 4);
558	      *aoffsetp += 32;
559	      if (INVALID_FLOAT (&value.f, 4))
560		sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
561	      else /* Assume host has ieee float.  */
562		sprintf (result, "$%g", value.f);
563	      break;
564	    case 'L':
565	      bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
566	      flip_bytes ((char *) &value.d, 8);
567	      *aoffsetp += 64;
568	      if (INVALID_FLOAT (&value.d, 8))
569		sprintf (result, "<<invalid double 0x%.8x%.8x>>",
570			 value.i[1], value.i[0]);
571	      else /* Assume host has ieee float.  */
572		sprintf (result, "$%g", value.d);
573	      break;
574	    }
575	  break;
576	case 0x15:
577	  /* Absolute @disp.  */
578	  disp1 = get_displacement (buffer, aoffsetp);
579	  sprintf (result, "@|%d|", disp1);
580	  break;
581	case 0x16:
582	  /* External EXT(disp1) + disp2 (Mod table stuff).  */
583	  disp1 = get_displacement (buffer, aoffsetp);
584	  disp2 = get_displacement (buffer, aoffsetp);
585	  sprintf (result, "EXT(%d) + %d", disp1, disp2);
586	  break;
587	case 0x17:
588	  /* Top of stack tos.  */
589	  sprintf (result, "tos");
590	  break;
591	case 0x18:
592	  /* Memory space disp(FP).  */
593	  disp1 = get_displacement (buffer, aoffsetp);
594	  sprintf (result, "%d(fp)", disp1);
595	  break;
596	case 0x19:
597	  /* Memory space disp(SP).  */
598	  disp1 = get_displacement (buffer, aoffsetp);
599	  sprintf (result, "%d(sp)", disp1);
600	  break;
601	case 0x1a:
602	  /* Memory space disp(SB).  */
603	  disp1 = get_displacement (buffer, aoffsetp);
604	  sprintf (result, "%d(sb)", disp1);
605	  break;
606	case 0x1b:
607	  /* Memory space disp(PC).  */
608	  disp1 = get_displacement (buffer, aoffsetp);
609	  *result++ = NEXT_IS_ADDR;
610	  sprintf_vma (result, addr + disp1);
611	  result += strlen (result);
612	  *result++ = NEXT_IS_ADDR;
613	  *result = '\0';
614	  break;
615	case 0x1c:
616	case 0x1d:
617	case 0x1e:
618	case 0x1f:
619	  /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
620	  index = bit_extract (buffer, index_offset - 8, 3);
621	  print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
622			  result, 0);
623	  {
624	    static const char *ind = "bwdq";
625	    char *off;
626
627	    off = result + strlen (result);
628	    sprintf (off, "[r%d:%c]", index,
629		     ind[addr_mode & 3]);
630	  }
631	  break;
632	}
633      break;
634    case 'H':
635    case 'q':
636      Ivalue = bit_extract (buffer, ioffset-4, 4);
637      Ivalue = sign_extend (Ivalue, 4);
638      sprintf (result, "%d", Ivalue);
639      ioffset -= 4;
640      break;
641    case 'r':
642      Ivalue = bit_extract (buffer, ioffset-3, 3);
643      sprintf (result, "r%d", Ivalue&7);
644      ioffset -= 3;
645      break;
646    case 'd':
647      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
648      break;
649    case 'b':
650      Ivalue = get_displacement (buffer, aoffsetp);
651      /* Warning!!  HACK ALERT!
652         Operand type 'b' is only used by the cmp{b,w,d} and
653         movm{b,w,d} instructions; we need to know whether
654         it's a `b' or `w' or `d' instruction; and for both
655         cmpm and movm it's stored at the same place so we
656         just grab two bits of the opcode and look at it...  */
657      size = bit_extract(buffer, ioffset-6, 2);
658      if (size == 0)		/* 00 => b.  */
659	size = 1;
660      else if (size == 1)	/* 01 => w.  */
661	size = 2;
662      else
663	size = 4;		/* 11 => d.  */
664
665      sprintf (result, "%d", (Ivalue / size) + 1);
666      break;
667    case 'p':
668      *result++ = NEXT_IS_ADDR;
669      sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
670      result += strlen (result);
671      *result++ = NEXT_IS_ADDR;
672      *result = '\0';
673      break;
674    case 'i':
675      Ivalue = bit_extract (buffer, *aoffsetp, 8);
676      *aoffsetp += 8;
677      sprintf (result, "0x%x", Ivalue);
678      break;
679    case 'u':
680      Ivalue = bit_extract (buffer, *aoffsetp, 8);
681      optlist (Ivalue, opt_u, result);
682      *aoffsetp += 8;
683      break;
684    case 'U':
685      Ivalue = bit_extract (buffer, *aoffsetp, 8);
686      optlist (Ivalue, opt_U, result);
687      *aoffsetp += 8;
688      break;
689    case 'O':
690      Ivalue = bit_extract (buffer, ioffset - 9, 9);
691      optlist (Ivalue, opt_O, result);
692      ioffset -= 9;
693      break;
694    case 'C':
695      Ivalue = bit_extract (buffer, ioffset - 4, 4);
696      optlist (Ivalue, opt_C, result);
697      ioffset -= 4;
698      break;
699    case 'S':
700      Ivalue = bit_extract (buffer, ioffset - 8, 8);
701      optlist (Ivalue, opt_S, result);
702      ioffset -= 8;
703      break;
704    case 'M':
705      Ivalue = bit_extract (buffer, ioffset - 4, 4);
706      list_search (Ivalue, 0 ? list_M032 : list_M532, result);
707      ioffset -= 4;
708      break;
709    case 'P':
710      Ivalue = bit_extract (buffer, ioffset - 4, 4);
711      list_search (Ivalue, 0 ? list_P032 : list_P532, result);
712      ioffset -= 4;
713      break;
714    case 'g':
715      Ivalue = bit_extract (buffer, *aoffsetp, 3);
716      sprintf (result, "%d", Ivalue);
717      *aoffsetp += 3;
718      break;
719    case 'G':
720      Ivalue = bit_extract(buffer, *aoffsetp, 5);
721      sprintf (result, "%d", Ivalue + 1);
722      *aoffsetp += 5;
723      break;
724    }
725  return ioffset;
726}
727
728
729/* Print the 32000 instruction at address MEMADDR in debugged memory,
730   on STREAM.  Returns length of the instruction, in bytes.  */
731
732int
733print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)
734{
735  unsigned int i;
736  const char *d;
737  unsigned short first_word;
738  int ioffset;		/* Bits into instruction.  */
739  int aoffset;		/* Bits into arguments.  */
740  char arg_bufs[MAX_ARGS+1][ARG_LEN];
741  int argnum;
742  int maxarg;
743  struct private priv;
744  bfd_byte *buffer = priv.the_buffer;
745  dis_info = info;
746
747  info->private_data = & priv;
748  priv.max_fetched = priv.the_buffer;
749  priv.insn_start = memaddr;
750  if (setjmp (priv.bailout) != 0)
751    /* Error return.  */
752    return -1;
753
754  /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
755     us over the end of accessible data unnecessarilly.  */
756  FETCH_DATA (info, buffer + 1);
757  for (i = 0; i < NOPCODES; i++)
758    if (ns32k_opcodes[i].opcode_id_size <= 8
759	&& ((buffer[0]
760	     & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
761	    == ns32k_opcodes[i].opcode_seed))
762      break;
763  if (i == NOPCODES)
764    {
765      /* Maybe it is 9 to 16 bits big.  */
766      FETCH_DATA (info, buffer + 2);
767      first_word = read_memory_integer(buffer, 2);
768
769      for (i = 0; i < NOPCODES; i++)
770	if ((first_word
771	     & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
772	    == ns32k_opcodes[i].opcode_seed)
773	  break;
774
775      /* Handle undefined instructions.  */
776      if (i == NOPCODES)
777	{
778	  (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
779	  return 1;
780	}
781    }
782
783  (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
784
785  ioffset = ns32k_opcodes[i].opcode_size;
786  aoffset = ns32k_opcodes[i].opcode_size;
787  d = ns32k_opcodes[i].operands;
788
789  if (*d)
790    {
791      /* Offset in bits of the first thing beyond each index byte.
792	 Element 0 is for operand A and element 1 is for operand B.
793	 The rest are irrelevant, but we put them here so we don't
794	 index outside the array.  */
795      int index_offset[MAX_ARGS];
796
797      /* 0 for operand A, 1 for operand B, greater for other args.  */
798      int whicharg = 0;
799
800      (*dis_info->fprintf_func)(dis_info->stream, "\t");
801
802      maxarg = 0;
803
804      /* First we have to find and keep track of the index bytes,
805	 if we are using scaled indexed addressing mode, since the index
806	 bytes occur right after the basic instruction, not as part
807	 of the addressing extension.  */
808      if (Is_gen(d[1]))
809	{
810	  int addr_mode = bit_extract (buffer, ioffset - 5, 5);
811
812	  if (Adrmod_is_index (addr_mode))
813	    {
814	      aoffset += 8;
815	      index_offset[0] = aoffset;
816	    }
817	}
818
819      if (d[2] && Is_gen(d[3]))
820	{
821	  int addr_mode = bit_extract (buffer, ioffset - 10, 5);
822
823	  if (Adrmod_is_index (addr_mode))
824	    {
825	      aoffset += 8;
826	      index_offset[1] = aoffset;
827	    }
828	}
829
830      while (*d)
831	{
832	  argnum = *d - '1';
833	  d++;
834	  if (argnum > maxarg && argnum < MAX_ARGS)
835	    maxarg = argnum;
836	  ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
837				    memaddr, arg_bufs[argnum],
838				    index_offset[whicharg]);
839	  d++;
840	  whicharg++;
841	}
842      for (argnum = 0; argnum <= maxarg; argnum++)
843	{
844	  bfd_vma addr;
845	  char *ch;
846
847	  for (ch = arg_bufs[argnum]; *ch;)
848	    {
849	      if (*ch == NEXT_IS_ADDR)
850		{
851		  ++ch;
852		  addr = bfd_scan_vma (ch, NULL, 16);
853		  (*dis_info->print_address_func) (addr, dis_info);
854		  while (*ch && *ch != NEXT_IS_ADDR)
855		    ++ch;
856		  if (*ch)
857		    ++ch;
858		}
859	      else
860		(*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
861	    }
862	  if (argnum < maxarg)
863	    (*dis_info->fprintf_func)(dis_info->stream, ", ");
864	}
865    }
866  return aoffset / 8;
867}
868