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 
32 static 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 
37 static long
read_memory_integer(unsigned char * addr,int nr)38 read_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 
56 struct 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 
73 static int
fetch_data(struct disassemble_info * info,bfd_byte * addr)74 fetch_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 
100 struct 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 
108 static 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 
121 static 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 
134 static 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 
143 static 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 
151 static 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 
159 static 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 
177 static 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 
189 static 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 
201 static 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 
219 static void
optlist(int options,const struct ns32k_option * optionP,char * result)220 optlist (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 
248 static void
list_search(int reg_value,const struct ns32k_option * optionP,char * result)249 list_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 
264 static int
bit_extract(bfd_byte * buffer,int offset,int count)265 bit_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 
291 static int
bit_extract_simple(bfd_byte * buffer,int offset,int count)292 bit_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 
315 static void
bit_copy(bfd_byte * buffer,int offset,int count,char * to)316 bit_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 
323 static int
sign_extend(int value,int bits)324 sign_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 
332 static void
flip_bytes(char * ptr,int count)333 flip_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 
366 static int
get_displacement(bfd_byte * buffer,int * aoffsetp)367 get_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.  */
397 static int
invalid_float(bfd_byte * p,int len)398 invalid_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.  */
417 typedef 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 
425 static int
invalid_float(float_type_u * p,int len)426 invalid_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 
452 static int
print_insn_arg(int d,int ioffset,int * aoffsetp,bfd_byte * buffer,bfd_vma addr,char * result,int index_offset)453 print_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 
733 int
print_insn_ns32k(bfd_vma memaddr,disassemble_info * info)734 print_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