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