xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/ns32k-dis.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* Print National Semiconductor 32000 instructions.
2    Copyright (c) 1986, 88, 91, 92, 94, 95, 1998 Free Software Foundation, Inc.
3 
4 This file is part of opcodes library.
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 
20 
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "dis-asm.h"
24 #if !defined(const) && !defined(__STDC__)
25 #define const
26 #endif
27 #include "opcode/ns32k.h"
28 #include "opintl.h"
29 
30 static disassemble_info *dis_info;
31 
32 /*
33  * Hacks to get it to compile <= READ THESE AS FIXES NEEDED
34  */
35 #define INVALID_FLOAT(val, size) invalid_float((char *)val, size)
36 
37 static int print_insn_arg
38   PARAMS ((int, int, int *, char *, bfd_vma, char *, int));
39 static int get_displacement PARAMS ((char *, int *));
40 static int invalid_float PARAMS ((char *, int));
41 
42 static long read_memory_integer(addr, nr)
43      unsigned char *addr;
44      int nr;
45 {
46   long val;
47   int i;
48   for (val = 0, i = nr - 1; i >= 0; i--) {
49     val =  (val << 8);
50     val |= (0xff & *(addr + i));
51   }
52   return val;
53 }
54 
55 /* 32000 instructions are never longer than this.  */
56 #define MAXLEN 62
57 
58 
59 #include <setjmp.h>
60 
61 struct private
62 {
63   /* Points to first byte not fetched.  */
64   bfd_byte *max_fetched;
65   bfd_byte the_buffer[MAXLEN];
66   bfd_vma insn_start;
67   jmp_buf bailout;
68 };
69 
70 
71 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
72    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
73    on error.  */
74 #define FETCH_DATA(info, addr) \
75   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
76    ? 1 : fetch_data ((info), (addr)))
77 
78 static int
79 fetch_data (info, addr)
80      struct disassemble_info *info;
81      bfd_byte *addr;
82 {
83   int status;
84   struct private *priv = (struct private *)info->private_data;
85   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
86 
87   status = (*info->read_memory_func) (start,
88 				      priv->max_fetched,
89 				      addr - priv->max_fetched,
90 				      info);
91   if (status != 0)
92     {
93       (*info->memory_error_func) (status, start, info);
94       longjmp (priv->bailout, 1);
95     }
96   else
97     priv->max_fetched = addr;
98   return 1;
99 }
100 /* Number of elements in the opcode table.  */
101 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
102 
103 #define NEXT_IS_ADDR	'|'
104 
105 
106 struct ns32k_option {
107   char *pattern;		/* the option itself */
108   unsigned long value;		/* binary value of the option */
109   unsigned long match;		/* these bits must match */
110 };
111 
112 
113 static const struct ns32k_option opt_u[]= /* restore, exit */
114 {
115   { "r0",	0x80,	0x80	},
116   { "r1",	0x40,	0x40	},
117   { "r2",	0x20,	0x20	},
118   { "r3",	0x10,	0x10	},
119   { "r4",	0x08,	0x08	},
120   { "r5",	0x04,	0x04	},
121   { "r6",	0x02,	0x02	},
122   { "r7",	0x01,	0x01	},
123   {  0 ,	0x00,	0x00	}
124 };
125 
126 static const struct ns32k_option opt_U[]= /* save, enter */
127 {
128   { "r0",	0x01,	0x01	},
129   { "r1",	0x02,	0x02	},
130   { "r2",	0x04,	0x04	},
131   { "r3",	0x08,	0x08	},
132   { "r4",	0x10,	0x10	},
133   { "r5",	0x20,	0x20	},
134   { "r6",	0x40,	0x40	},
135   { "r7",	0x80,	0x80	},
136   {  0 ,	0x00,	0x00	}
137 };
138 
139 static const struct ns32k_option opt_O[]= /* setcfg */
140 {
141   { "c",	0x8,	0x8	},
142   { "m",	0x4,	0x4	},
143   { "f",	0x2,	0x2	},
144   { "i",	0x1,	0x1	},
145   {  0 ,	0x0,	0x0	}
146 };
147 
148 static const struct ns32k_option opt_C[]= /* cinv */
149 {
150   { "a",	0x4,	0x4	},
151   { "i",	0x2,	0x2	},
152   { "d",	0x1,	0x1	},
153   {  0 ,	0x0,	0x0	}
154 };
155 
156 static const struct ns32k_option opt_S[]= /* string inst */
157 {
158   { "b",	0x1,	0x1	},
159   { "u",	0x6,	0x6	},
160   { "w",	0x2,	0x2	},
161   {  0 ,	0x0,	0x0	}
162 };
163 
164 static const struct ns32k_option list_P532[]= /* lpr spr */
165 {
166   { "us",	0x0,	0xf	},
167   { "dcr",	0x1,	0xf	},
168   { "bpc",	0x2,	0xf	},
169   { "dsr",	0x3,	0xf	},
170   { "car",	0x4,	0xf	},
171   { "fp",	0x8,	0xf	},
172   { "sp",	0x9,	0xf	},
173   { "sb",	0xa,	0xf	},
174   { "usp",	0xb,	0xf	},
175   { "cfg",	0xc,	0xf	},
176   { "psr",	0xd,	0xf	},
177   { "intbase",	0xe,	0xf	},
178   { "mod",	0xf,	0xf	},
179   {  0 ,	0x00,	0xf	}
180 };
181 
182 static const struct ns32k_option list_M532[]= /* lmr smr */
183 {
184   { "mcr",	0x9,	0xf	},
185   { "msr",	0xa,	0xf	},
186   { "tear",	0xb,	0xf	},
187   { "ptb0",	0xc,	0xf	},
188   { "ptb1",	0xd,	0xf	},
189   { "ivar0",	0xe,	0xf	},
190   { "ivar1",	0xf,	0xf	},
191   {  0 ,	0x0,	0xf	}
192 };
193 
194 static const struct ns32k_option list_P032[]= /* lpr spr */
195 {
196   { "upsr",	0x0,	0xf	},
197   { "fp",	0x8,	0xf	},
198   { "sp",	0x9,	0xf	},
199   { "sb",	0xa,	0xf	},
200   { "psr",	0xb,	0xf	},
201   { "intbase",	0xe,	0xf	},
202   { "mod",	0xf,	0xf	},
203   {  0 ,	0x0,	0xf	}
204 };
205 
206 static const struct ns32k_option list_M032[]= /* lmr smr */
207 {
208   { "bpr0",	0x0,	0xf	},
209   { "bpr1",	0x1,	0xf	},
210   { "pf0",	0x4,	0xf	},
211   { "pf1",	0x5,	0xf	},
212   { "sc",	0x8,	0xf	},
213   { "msr",	0xa,	0xf	},
214   { "bcnt",	0xb,	0xf	},
215   { "ptb0",	0xc,	0xf	},
216   { "ptb1",	0xd,	0xf	},
217   { "eia",	0xf,	0xf	},
218   {  0 ,	0x0,	0xf	}
219 };
220 
221 
222 /*
223  * figure out which options are present
224  */
225 static void
226 optlist(options, optionP, result)
227      int options;
228      const struct ns32k_option *optionP;
229      char *result;
230 {
231     if (options == 0) {
232 	sprintf(result, "[]");
233 	return;
234     }
235     sprintf(result, "[");
236 
237     for (; (options != 0) && optionP->pattern; optionP++) {
238 	if ((options & optionP->match) == optionP->value) {
239 	    /* we found a match, update result and options */
240 	    strcat(result, optionP->pattern);
241 	    options &= ~optionP->value;
242 	    if (options != 0)	/* more options to come */
243 		strcat(result, ",");
244 	}
245     }
246     if (options != 0)
247 	strcat(result, "undefined");
248 
249     strcat(result, "]");
250 }
251 
252 static void
253 list_search (reg_value, optionP, result)
254      int reg_value;
255      const struct ns32k_option *optionP;
256      char *result;
257 {
258     for (; optionP->pattern; optionP++) {
259 	if ((reg_value & optionP->match) == optionP->value) {
260 	    sprintf(result, "%s", optionP->pattern);
261 	    return;
262 	}
263     }
264     sprintf(result, "undefined");
265 }
266 
267 /*
268  * extract "count" bits starting "offset" bits
269  * into buffer
270  */
271 
272 static int
273 bit_extract (buffer, offset, count)
274      bfd_byte *buffer;
275      int offset;
276      int count;
277 {
278   int result;
279   int bit;
280 
281   buffer += offset >> 3;
282   offset &= 7;
283   bit = 1;
284   result = 0;
285   while (count--)
286     {
287       FETCH_DATA(dis_info, buffer + 1);
288       if ((*buffer & (1 << offset)))
289 	result |= bit;
290       if (++offset == 8)
291 	{
292 	  offset = 0;
293 	  buffer++;
294 	}
295       bit <<= 1;
296     }
297   return result;
298 }
299 
300 /* Like bit extract but the buffer is valid and doen't need to be
301  * fetched
302  */
303 static int
304 bit_extract_simple (buffer, offset, count)
305      bfd_byte *buffer;
306      int offset;
307      int count;
308 {
309   int result;
310   int mask;
311   int bit;
312 
313   buffer += offset >> 3;
314   offset &= 7;
315   bit = 1;
316   result = 0;
317   while (count--)
318     {
319       if ((*buffer & (1 << offset)))
320 	result |= bit;
321       if (++offset == 8)
322 	{
323 	  offset = 0;
324 	  buffer++;
325 	}
326       bit <<= 1;
327     }
328   return result;
329 }
330 
331 static void
332 bit_copy (buffer, offset, count, to)
333      char *buffer;
334      int offset;
335      int count;
336      char *to;
337 {
338   for(; count > 8; count -= 8, to++, offset += 8)
339     *to = bit_extract (buffer, offset, 8);
340   *to = bit_extract (buffer, offset, count);
341 }
342 
343 
344 static int
345 sign_extend (value, bits)
346      int value, bits;
347 {
348   value = value & ((1 << bits) - 1);
349   return (value & (1 << (bits-1))
350 	  ? value | (~((1 << bits) - 1))
351 	  : value);
352 }
353 
354 static void
355 flip_bytes (ptr, count)
356      char *ptr;
357      int count;
358 {
359   char tmp;
360 
361   while (count > 0)
362     {
363       tmp = ptr[0];
364       ptr[0] = ptr[count-1];
365       ptr[count-1] = tmp;
366       ptr++;
367       count -= 2;
368     }
369 }
370 
371 /* Given a character C, does it represent a general addressing mode?  */
372 #define Is_gen(c) \
373   ((c) == 'F' || (c) == 'L' || (c) == 'B' \
374    || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
375 
376 /* Adressing modes.  */
377 #define Adrmod_index_byte 0x1c
378 #define Adrmod_index_word 0x1d
379 #define Adrmod_index_doubleword 0x1e
380 #define Adrmod_index_quadword 0x1f
381 
382 /* Is MODE an indexed addressing mode?  */
383 #define Adrmod_is_index(mode) \
384   (mode == Adrmod_index_byte \
385    || mode == Adrmod_index_word \
386    || mode == Adrmod_index_doubleword \
387    || mode == Adrmod_index_quadword)
388 
389 
390 /* Print the 32000 instruction at address MEMADDR in debugged memory,
391    on STREAM.  Returns length of the instruction, in bytes.  */
392 
393 int
394 print_insn_ns32k (memaddr, info)
395      bfd_vma memaddr;
396      disassemble_info *info;
397 {
398   register unsigned int i;
399   register char *d;
400   unsigned short first_word;
401   int ioffset;		/* bits into instruction */
402   int aoffset;		/* bits into arguments */
403   char arg_bufs[MAX_ARGS+1][ARG_LEN];
404   int argnum;
405   int maxarg;
406   struct private priv;
407   bfd_byte *buffer = priv.the_buffer;
408   dis_info = info;
409 
410   info->private_data = (PTR) &priv;
411   priv.max_fetched = priv.the_buffer;
412   priv.insn_start = memaddr;
413   if (setjmp (priv.bailout) != 0)
414     /* Error return.  */
415     return -1;
416 
417   /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
418    * us over the end of accessible data unnecessarilly
419    */
420   FETCH_DATA(info, buffer + 1);
421   for (i = 0; i < NOPCODES; i++)
422     if (ns32k_opcodes[i].opcode_id_size <= 8
423 	&& ((buffer[0]
424 	     & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
425 	    == ns32k_opcodes[i].opcode_seed))
426       break;
427   if (i == NOPCODES) {
428     /* Maybe it is 9 to 16 bits big */
429     FETCH_DATA(info, buffer + 2);
430     first_word = read_memory_integer(buffer, 2);
431 
432     for (i = 0; i < NOPCODES; i++)
433       if ((first_word
434 	   & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
435 	  == ns32k_opcodes[i].opcode_seed)
436 	break;
437 
438     /* Handle undefined instructions.  */
439     if (i == NOPCODES)
440       {
441 	(*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
442 	return 1;
443       }
444   }
445 
446   (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
447 
448   ioffset = ns32k_opcodes[i].opcode_size;
449   aoffset = ns32k_opcodes[i].opcode_size;
450   d = ns32k_opcodes[i].operands;
451 
452   if (*d)
453     {
454       /* Offset in bits of the first thing beyond each index byte.
455 	 Element 0 is for operand A and element 1 is for operand B.
456 	 The rest are irrelevant, but we put them here so we don't
457 	 index outside the array.  */
458       int index_offset[MAX_ARGS];
459 
460       /* 0 for operand A, 1 for operand B, greater for other args.  */
461       int whicharg = 0;
462 
463       (*dis_info->fprintf_func)(dis_info->stream, "\t");
464 
465       maxarg = 0;
466 
467       /* First we have to find and keep track of the index bytes,
468 	 if we are using scaled indexed addressing mode, since the index
469 	 bytes occur right after the basic instruction, not as part
470 	 of the addressing extension.  */
471       if (Is_gen(d[1]))
472 	{
473 	  int addr_mode = bit_extract (buffer, ioffset - 5, 5);
474 
475 	  if (Adrmod_is_index (addr_mode))
476 	    {
477 	      aoffset += 8;
478 	      index_offset[0] = aoffset;
479 	    }
480 	}
481       if (d[2] && Is_gen(d[3]))
482 	{
483 	  int addr_mode = bit_extract (buffer, ioffset - 10, 5);
484 
485 	  if (Adrmod_is_index (addr_mode))
486 	    {
487 	      aoffset += 8;
488 	      index_offset[1] = aoffset;
489 	    }
490 	}
491 
492       while (*d)
493 	{
494 	  argnum = *d - '1';
495 	  d++;
496 	  if (argnum > maxarg && argnum < MAX_ARGS)
497 	    maxarg = argnum;
498 	  ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
499 				    memaddr, arg_bufs[argnum],
500 				    index_offset[whicharg]);
501 	  d++;
502 	  whicharg++;
503 	}
504       for (argnum = 0; argnum <= maxarg; argnum++)
505 	{
506 	  bfd_vma addr;
507 	  char *ch;
508 	  for (ch = arg_bufs[argnum]; *ch;)
509 	    {
510 	      if (*ch == NEXT_IS_ADDR)
511 		{
512 		  ++ch;
513 		  addr = bfd_scan_vma (ch, NULL, 16);
514 		  (*dis_info->print_address_func) (addr, dis_info);
515 		  while (*ch && *ch != NEXT_IS_ADDR)
516 		    ++ch;
517 		  if (*ch)
518 		    ++ch;
519 		}
520 	      else
521 		(*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
522 	    }
523 	  if (argnum < maxarg)
524 	    (*dis_info->fprintf_func)(dis_info->stream, ", ");
525 	}
526     }
527   return aoffset / 8;
528 }
529 
530 /* Print an instruction operand of category given by d.  IOFFSET is
531    the bit position below which small (<1 byte) parts of the operand can
532    be found (usually in the basic instruction, but for indexed
533    addressing it can be in the index byte).  AOFFSETP is a pointer to the
534    bit position of the addressing extension.  BUFFER contains the
535    instruction.  ADDR is where BUFFER was read from.  Put the disassembled
536    version of the operand in RESULT.  INDEX_OFFSET is the bit position
537    of the index byte (it contains garbage if this operand is not a
538    general operand using scaled indexed addressing mode).  */
539 
540 static int
541 print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
542      int d;
543      int ioffset, *aoffsetp;
544      char *buffer;
545      bfd_vma addr;
546      char *result;
547      int index_offset;
548 {
549   int addr_mode;
550   float Fvalue;
551   double Lvalue;
552   int Ivalue;
553   int disp1, disp2;
554   int index;
555   int size;
556 
557   switch (d)
558     {
559     case 'f':
560       /* a "gen" operand but 5 bits from the end of instruction */
561       ioffset -= 5;
562     case 'Z':
563     case 'F':
564     case 'L':
565     case 'I':
566     case 'B':
567     case 'W':
568     case 'D':
569     case 'A':
570       addr_mode = bit_extract (buffer, ioffset-5, 5);
571       ioffset -= 5;
572       switch (addr_mode)
573 	{
574 	case 0x0: case 0x1: case 0x2: case 0x3:
575 	case 0x4: case 0x5: case 0x6: case 0x7:
576 	  /* register mode R0 -- R7 */
577 	  switch (d)
578 	    {
579 	    case 'F':
580 	    case 'L':
581 	    case 'Z':
582 	      sprintf (result, "f%d", addr_mode);
583 	      break;
584 	    default:
585 	      sprintf (result, "r%d", addr_mode);
586 	    }
587 	  break;
588 	case 0x8: case 0x9: case 0xa: case 0xb:
589 	case 0xc: case 0xd: case 0xe: case 0xf:
590 	  /* Register relative disp(R0 -- R7) */
591 	  disp1 = get_displacement (buffer, aoffsetp);
592 	  sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
593 	  break;
594 	case 0x10:
595 	case 0x11:
596 	case 0x12:
597 	  /* Memory relative disp2(disp1(FP, SP, SB)) */
598 	  disp1 = get_displacement (buffer, aoffsetp);
599 	  disp2 = get_displacement (buffer, aoffsetp);
600 	  sprintf (result, "%d(%d(%s))", disp2, disp1,
601 		   addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
602 	  break;
603 	case 0x13:
604 	  /* reserved */
605 	  sprintf (result, "reserved");
606 	  break;
607 	case 0x14:
608 	  /* Immediate */
609 	  switch (d)
610 	    {
611 	    case 'I': case 'Z': case 'A':
612 	      /* I and Z are output operands and can`t be immediate
613 	       * A is an address and we can`t have the address of
614 	       * an immediate either. We don't know how much to increase
615 	       * aoffsetp by since whatever generated this is broken
616 	       * anyway!
617 	       */
618 	      sprintf (result, _("$<undefined>"));
619 	      break;
620 	    case 'B':
621 	      Ivalue = bit_extract (buffer, *aoffsetp, 8);
622 	      Ivalue = sign_extend (Ivalue, 8);
623 	      *aoffsetp += 8;
624 	      sprintf (result, "$%d", Ivalue);
625 	      break;
626 	    case 'W':
627 	      Ivalue = bit_extract (buffer, *aoffsetp, 16);
628 	      flip_bytes (&Ivalue, 2);
629 	      *aoffsetp += 16;
630 	      Ivalue = sign_extend (Ivalue, 16);
631 	      sprintf (result, "$%d", Ivalue);
632 	      break;
633 	    case 'D':
634 	      Ivalue = bit_extract (buffer, *aoffsetp, 32);
635 	      flip_bytes (&Ivalue, 4);
636 	      *aoffsetp += 32;
637 	      sprintf (result, "$%d", Ivalue);
638 	      break;
639 	    case 'F':
640 	      bit_copy (buffer, *aoffsetp, 32, (char *) &Fvalue);
641 	      flip_bytes (&Fvalue, 4);
642 	      *aoffsetp += 32;
643 	      if (INVALID_FLOAT (&Fvalue, 4))
644 		sprintf (result, "<<invalid float 0x%.8x>>", *(int *) &Fvalue);
645 	      else /* assume host has ieee float */
646 		sprintf (result, "$%g", Fvalue);
647 	      break;
648 	    case 'L':
649 	      bit_copy (buffer, *aoffsetp, 64, (char *) &Lvalue);
650 	      flip_bytes (&Lvalue, 8);
651 	      *aoffsetp += 64;
652 	      if (INVALID_FLOAT (&Lvalue, 8))
653 		sprintf (result, "<<invalid long 0x%.8x%.8x>>",
654 			 *(((int *) &Lvalue) + 1), *(int *) &Lvalue);
655 	      else /* assume host has ieee float */
656 		sprintf (result, "$%g", Lvalue);
657 	      break;
658 	    }
659 	  break;
660 	case 0x15:
661 	  /* Absolute @disp */
662 	  disp1 = get_displacement (buffer, aoffsetp);
663 	  sprintf (result, "@|%d|", disp1);
664 	  break;
665 	case 0x16:
666 	  /* External EXT(disp1) + disp2 (Mod table stuff) */
667 	  disp1 = get_displacement (buffer, aoffsetp);
668 	  disp2 = get_displacement (buffer, aoffsetp);
669 	  sprintf (result, "EXT(%d) + %d", disp1, disp2);
670 	  break;
671 	case 0x17:
672 	  /* Top of stack tos */
673 	  sprintf (result, "tos");
674 	  break;
675 	case 0x18:
676 	  /* Memory space disp(FP) */
677 	  disp1 = get_displacement (buffer, aoffsetp);
678 	  sprintf (result, "%d(fp)", disp1);
679 	  break;
680 	case 0x19:
681 	  /* Memory space disp(SP) */
682 	  disp1 = get_displacement (buffer, aoffsetp);
683 	  sprintf (result, "%d(sp)", disp1);
684 	  break;
685 	case 0x1a:
686 	  /* Memory space disp(SB) */
687 	  disp1 = get_displacement (buffer, aoffsetp);
688 	  sprintf (result, "%d(sb)", disp1);
689 	  break;
690 	case 0x1b:
691 	  /* Memory space disp(PC) */
692 	  disp1 = get_displacement (buffer, aoffsetp);
693 	  *result++ = NEXT_IS_ADDR;
694 	  sprintf_vma (result, addr + disp1);
695 	  result += strlen (result);
696 	  *result++ = NEXT_IS_ADDR;
697 	  *result = '\0';
698 	  break;
699 	case 0x1c:
700 	case 0x1d:
701 	case 0x1e:
702 	case 0x1f:
703 	  /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
704 	  index = bit_extract (buffer, index_offset - 8, 3);
705 	  print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
706 			  result, 0);
707 	  {
708 	    static const char *ind = "bwdq";
709 	    char *off;
710 
711 	    off = result + strlen (result);
712 	    sprintf (off, "[r%d:%c]", index,
713 		     ind[addr_mode & 3]);
714 	  }
715 	  break;
716 	}
717       break;
718     case 'H':
719     case 'q':
720       Ivalue = bit_extract (buffer, ioffset-4, 4);
721       Ivalue = sign_extend (Ivalue, 4);
722       sprintf (result, "%d", Ivalue);
723       ioffset -= 4;
724       break;
725     case 'r':
726       Ivalue = bit_extract (buffer, ioffset-3, 3);
727       sprintf (result, "r%d", Ivalue&7);
728       ioffset -= 3;
729       break;
730     case 'd':
731       sprintf (result, "%d", get_displacement (buffer, aoffsetp));
732       break;
733     case 'b':
734       Ivalue = get_displacement (buffer, aoffsetp);
735       /*
736        * Warning!!  HACK ALERT!
737        * Operand type 'b' is only used by the cmp{b,w,d} and
738        * movm{b,w,d} instructions; we need to know whether
739        * it's a `b' or `w' or `d' instruction; and for both
740        * cmpm and movm it's stored at the same place so we
741        * just grab two bits of the opcode and look at it...
742        *
743        */
744       size = bit_extract(buffer, ioffset-6, 2);
745       if (size == 0)		/* 00 => b */
746 	size = 1;
747       else if (size == 1)	/* 01 => w */
748 	size = 2;
749       else
750 	size = 4;		/* 11 => d */
751 
752       sprintf (result, "%d", (Ivalue / size) + 1);
753       break;
754     case 'p':
755       *result++ = NEXT_IS_ADDR;
756       sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
757       result += strlen (result);
758       *result++ = NEXT_IS_ADDR;
759       *result = '\0';
760       break;
761     case 'i':
762       Ivalue = bit_extract (buffer, *aoffsetp, 8);
763       *aoffsetp += 8;
764       sprintf (result, "0x%x", Ivalue);
765       break;
766     case 'u':
767       Ivalue = bit_extract (buffer, *aoffsetp, 8);
768       optlist(Ivalue, opt_u, result);
769       *aoffsetp += 8;
770       break;
771     case 'U':
772       Ivalue = bit_extract(buffer, *aoffsetp, 8);
773       optlist(Ivalue, opt_U, result);
774       *aoffsetp += 8;
775       break;
776     case 'O':
777       Ivalue = bit_extract(buffer, ioffset-9, 9);
778       optlist(Ivalue, opt_O, result);
779       ioffset -= 9;
780       break;
781     case 'C':
782       Ivalue = bit_extract(buffer, ioffset-4, 4);
783       optlist(Ivalue, opt_C, result);
784       ioffset -= 4;
785       break;
786     case 'S':
787       Ivalue = bit_extract(buffer, ioffset - 8, 8);
788       optlist(Ivalue, opt_S, result);
789       ioffset -= 8;
790       break;
791     case 'M':
792       Ivalue = bit_extract(buffer, ioffset-4, 4);
793       list_search(Ivalue, 0 ? list_M032 : list_M532, result);
794       ioffset -= 4;
795       break;
796     case 'P':
797       Ivalue = bit_extract(buffer, ioffset-4, 4);
798       list_search(Ivalue, 0 ? list_P032 : list_P532, result);
799       ioffset -= 4;
800       break;
801     case 'g':
802       Ivalue = bit_extract(buffer, *aoffsetp, 3);
803       sprintf(result, "%d", Ivalue);
804       *aoffsetp += 3;
805       break;
806     case 'G':
807       Ivalue = bit_extract(buffer, *aoffsetp, 5);
808       sprintf(result, "%d", Ivalue + 1);
809       *aoffsetp += 5;
810       break;
811     }
812   return ioffset;
813 }
814 
815 static int
816 get_displacement (buffer, aoffsetp)
817      char *buffer;
818      int *aoffsetp;
819 {
820   int Ivalue;
821   short Ivalue2;
822 
823   Ivalue = bit_extract (buffer, *aoffsetp, 8);
824   switch (Ivalue & 0xc0)
825     {
826     case 0x00:
827     case 0x40:
828       Ivalue = sign_extend (Ivalue, 7);
829       *aoffsetp += 8;
830       break;
831     case 0x80:
832       Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
833       flip_bytes (&Ivalue2, 2);
834       Ivalue = sign_extend (Ivalue2, 14);
835       *aoffsetp += 16;
836       break;
837     case 0xc0:
838       Ivalue = bit_extract (buffer, *aoffsetp, 32);
839       flip_bytes (&Ivalue, 4);
840       Ivalue = sign_extend (Ivalue, 30);
841       *aoffsetp += 32;
842       break;
843     }
844   return Ivalue;
845 }
846 
847 
848 #if 1 /* a version that should work on ns32k f's&d's on any machine */
849 static int
850 invalid_float (p, len)
851      register char *p;
852      register int len;
853 {
854   register int val;
855 
856   if ( len == 4 )
857     val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff
858 	   || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 &&
859 	       bit_extract_simple(p, 0, 23)/*mantisa*/ != 0));
860   else if ( len == 8 )
861     val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff
862 	   || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0
863 	       && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0
864 		   || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0)));
865   else
866     val = 1;
867   return (val);
868 }
869 #else
870 
871 /* assumes the bytes have been swapped to local order */
872 typedef union { double d;
873 		float f;
874 		struct { unsigned m:23, e:8, :1;} sf;
875 		struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
876 	      } float_type_u;
877 
878 static int
879 invalid_float (p, len)
880      register float_type_u *p;
881      register int len;
882 {
883   register int val;
884   if ( len == sizeof (float) )
885     val = (p->sf.e == 0xff
886 	   || (p->sf.e == 0 && p->sf.m != 0));
887   else if ( len == sizeof (double) )
888     val = (p->sd.e == 0x7ff
889 	   || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
890   else
891     val = 1;
892   return (val);
893 }
894 #endif
895