53367abdea0ea5d97c859470b5c6d6c8b688db6e
[platform/upstream/binutils.git] / opcodes / ns32k-dis.c
1 /* Print National Semiconductor 32000 instructions.
2    Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001
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., 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
31 static 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
38 static int print_insn_arg
39   PARAMS ((int, int, int *, char *, bfd_vma, char *, int));
40 static int get_displacement PARAMS ((char *, int *));
41 static int invalid_float PARAMS ((char *, int));
42 static long int read_memory_integer PARAMS ((unsigned char *, int));
43 static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
44 struct ns32k_option;
45 static void optlist PARAMS ((int, const struct ns32k_option *, char *));
46 static void list_search PARAMS ((int, const struct ns32k_option *, char *));
47 static int bit_extract PARAMS ((bfd_byte *, int, int));
48 static int bit_extract_simple PARAMS ((bfd_byte *, int, int));
49 static void bit_copy PARAMS ((char *, int, int, char *));
50 static int sign_extend PARAMS ((int, int));
51 static void flip_bytes PARAMS ((char *, int));
52
53 static 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
72 struct 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
89 static int
90 fetch_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 \f
117 struct 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 \f
124 static 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
137 static 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
150 static 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
159 static 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
167 static 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
175 static 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
193 static 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
205 static 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
217 static 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  */
236 static void
237 optlist(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
263 static void
264 list_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 \f
278 /*
279  * extract "count" bits starting "offset" bits
280  * into buffer
281  */
282
283 static int
284 bit_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  */
314 static int
315 bit_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
341 static void
342 bit_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
354 static int
355 sign_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
364 static void
365 flip_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 \f
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 \f
400 /* Print the 32000 instruction at address MEMADDR in debugged memory,
401    on STREAM.  Returns length of the instruction, in bytes.  */
402
403 int
404 print_insn_ns32k (memaddr, info)
405      bfd_vma memaddr;
406      disassemble_info *info;
407 {
408   register unsigned int i;
409   register 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
550 static int
551 print_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   int addr_mode;
560   float Fvalue;
561   double Lvalue;
562   int Ivalue;
563   int disp1, disp2;
564   int index;
565   int size;
566
567   switch (d)
568     {
569     case 'f':
570       /* a "gen" operand but 5 bits from the end of instruction */
571       ioffset -= 5;
572     case 'Z':
573     case 'F':
574     case 'L':
575     case 'I':
576     case 'B':
577     case 'W':
578     case 'D':
579     case 'A':
580       addr_mode = bit_extract (buffer, ioffset-5, 5);
581       ioffset -= 5;
582       switch (addr_mode)
583         {
584         case 0x0: case 0x1: case 0x2: case 0x3:
585         case 0x4: case 0x5: case 0x6: case 0x7:
586           /* register mode R0 -- R7 */
587           switch (d)
588             {
589             case 'F':
590             case 'L':
591             case 'Z':
592               sprintf (result, "f%d", addr_mode);
593               break;
594             default:
595               sprintf (result, "r%d", addr_mode);
596             }
597           break;
598         case 0x8: case 0x9: case 0xa: case 0xb:
599         case 0xc: case 0xd: case 0xe: case 0xf:
600           /* Register relative disp(R0 -- R7) */
601           disp1 = get_displacement (buffer, aoffsetp);
602           sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
603           break;
604         case 0x10:
605         case 0x11:
606         case 0x12:
607           /* Memory relative disp2(disp1(FP, SP, SB)) */
608           disp1 = get_displacement (buffer, aoffsetp);
609           disp2 = get_displacement (buffer, aoffsetp);
610           sprintf (result, "%d(%d(%s))", disp2, disp1,
611                    addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
612           break;
613         case 0x13:
614           /* reserved */
615           sprintf (result, "reserved");
616           break;
617         case 0x14:
618           /* Immediate */
619           switch (d)
620             {
621             case 'I': case 'Z': case 'A':
622               /* I and Z are output operands and can`t be immediate
623                * A is an address and we can`t have the address of
624                * an immediate either. We don't know how much to increase
625                * aoffsetp by since whatever generated this is broken
626                * anyway!
627                */
628               sprintf (result, _("$<undefined>"));
629               break;
630             case 'B':
631               Ivalue = bit_extract (buffer, *aoffsetp, 8);
632               Ivalue = sign_extend (Ivalue, 8);
633               *aoffsetp += 8;
634               sprintf (result, "$%d", Ivalue);
635               break;
636             case 'W':
637               Ivalue = bit_extract (buffer, *aoffsetp, 16);
638               flip_bytes (&Ivalue, 2);
639               *aoffsetp += 16;
640               Ivalue = sign_extend (Ivalue, 16);
641               sprintf (result, "$%d", Ivalue);
642               break;
643             case 'D':
644               Ivalue = bit_extract (buffer, *aoffsetp, 32);
645               flip_bytes (&Ivalue, 4);
646               *aoffsetp += 32;
647               sprintf (result, "$%d", Ivalue);
648               break;
649             case 'F':
650               bit_copy (buffer, *aoffsetp, 32, (char *) &Fvalue);
651               flip_bytes (&Fvalue, 4);
652               *aoffsetp += 32;
653               if (INVALID_FLOAT (&Fvalue, 4))
654                 sprintf (result, "<<invalid float 0x%.8x>>", *(int *) &Fvalue);
655               else /* assume host has ieee float */
656                 sprintf (result, "$%g", Fvalue);
657               break;
658             case 'L':
659               bit_copy (buffer, *aoffsetp, 64, (char *) &Lvalue);
660               flip_bytes (&Lvalue, 8);
661               *aoffsetp += 64;
662               if (INVALID_FLOAT (&Lvalue, 8))
663                 sprintf (result, "<<invalid long 0x%.8x%.8x>>",
664                          *(((int *) &Lvalue) + 1), *(int *) &Lvalue);
665               else /* assume host has ieee float */
666                 sprintf (result, "$%g", Lvalue);
667               break;
668             }
669           break;
670         case 0x15:
671           /* Absolute @disp */
672           disp1 = get_displacement (buffer, aoffsetp);
673           sprintf (result, "@|%d|", disp1);
674           break;
675         case 0x16:
676           /* External EXT(disp1) + disp2 (Mod table stuff) */
677           disp1 = get_displacement (buffer, aoffsetp);
678           disp2 = get_displacement (buffer, aoffsetp);
679           sprintf (result, "EXT(%d) + %d", disp1, disp2);
680           break;
681         case 0x17:
682           /* Top of stack tos */
683           sprintf (result, "tos");
684           break;
685         case 0x18:
686           /* Memory space disp(FP) */
687           disp1 = get_displacement (buffer, aoffsetp);
688           sprintf (result, "%d(fp)", disp1);
689           break;
690         case 0x19:
691           /* Memory space disp(SP) */
692           disp1 = get_displacement (buffer, aoffsetp);
693           sprintf (result, "%d(sp)", disp1);
694           break;
695         case 0x1a:
696           /* Memory space disp(SB) */
697           disp1 = get_displacement (buffer, aoffsetp);
698           sprintf (result, "%d(sb)", disp1);
699           break;
700         case 0x1b:
701           /* Memory space disp(PC) */
702           disp1 = get_displacement (buffer, aoffsetp);
703           *result++ = NEXT_IS_ADDR;
704           sprintf_vma (result, addr + disp1);
705           result += strlen (result);
706           *result++ = NEXT_IS_ADDR;
707           *result = '\0';
708           break;
709         case 0x1c:
710         case 0x1d:
711         case 0x1e:
712         case 0x1f:
713           /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
714           index = bit_extract (buffer, index_offset - 8, 3);
715           print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
716                           result, 0);
717           {
718             static const char *ind = "bwdq";
719             char *off;
720
721             off = result + strlen (result);
722             sprintf (off, "[r%d:%c]", index,
723                      ind[addr_mode & 3]);
724           }
725           break;
726         }
727       break;
728     case 'H':
729     case 'q':
730       Ivalue = bit_extract (buffer, ioffset-4, 4);
731       Ivalue = sign_extend (Ivalue, 4);
732       sprintf (result, "%d", Ivalue);
733       ioffset -= 4;
734       break;
735     case 'r':
736       Ivalue = bit_extract (buffer, ioffset-3, 3);
737       sprintf (result, "r%d", Ivalue&7);
738       ioffset -= 3;
739       break;
740     case 'd':
741       sprintf (result, "%d", get_displacement (buffer, aoffsetp));
742       break;
743     case 'b':
744       Ivalue = get_displacement (buffer, aoffsetp);
745       /*
746        * Warning!!  HACK ALERT!
747        * Operand type 'b' is only used by the cmp{b,w,d} and
748        * movm{b,w,d} instructions; we need to know whether
749        * it's a `b' or `w' or `d' instruction; and for both
750        * cmpm and movm it's stored at the same place so we
751        * just grab two bits of the opcode and look at it...
752        * 
753        */
754       size = bit_extract(buffer, ioffset-6, 2);
755       if (size == 0)            /* 00 => b */
756         size = 1;
757       else if (size == 1)       /* 01 => w */
758         size = 2;
759       else
760         size = 4;               /* 11 => d */
761
762       sprintf (result, "%d", (Ivalue / size) + 1);
763       break;
764     case 'p':
765       *result++ = NEXT_IS_ADDR;
766       sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
767       result += strlen (result);
768       *result++ = NEXT_IS_ADDR;
769       *result = '\0';
770       break;
771     case 'i':
772       Ivalue = bit_extract (buffer, *aoffsetp, 8);
773       *aoffsetp += 8;
774       sprintf (result, "0x%x", Ivalue);
775       break;
776     case 'u':
777       Ivalue = bit_extract (buffer, *aoffsetp, 8);
778       optlist(Ivalue, opt_u, result);
779       *aoffsetp += 8;
780       break;
781     case 'U':
782       Ivalue = bit_extract(buffer, *aoffsetp, 8);
783       optlist(Ivalue, opt_U, result);
784       *aoffsetp += 8;
785       break;
786     case 'O':
787       Ivalue = bit_extract(buffer, ioffset-9, 9);
788       optlist(Ivalue, opt_O, result);
789       ioffset -= 9;
790       break;
791     case 'C':
792       Ivalue = bit_extract(buffer, ioffset-4, 4);
793       optlist(Ivalue, opt_C, result);
794       ioffset -= 4;
795       break;
796     case 'S':
797       Ivalue = bit_extract(buffer, ioffset - 8, 8);
798       optlist(Ivalue, opt_S, result);
799       ioffset -= 8;
800       break;
801     case 'M':
802       Ivalue = bit_extract(buffer, ioffset-4, 4);
803       list_search(Ivalue, 0 ? list_M032 : list_M532, result);
804       ioffset -= 4;
805       break;
806     case 'P':
807       Ivalue = bit_extract(buffer, ioffset-4, 4);
808       list_search(Ivalue, 0 ? list_P032 : list_P532, result);
809       ioffset -= 4;
810       break;
811     case 'g':
812       Ivalue = bit_extract(buffer, *aoffsetp, 3);
813       sprintf(result, "%d", Ivalue);
814       *aoffsetp += 3;
815       break;
816     case 'G':
817       Ivalue = bit_extract(buffer, *aoffsetp, 5);
818       sprintf(result, "%d", Ivalue + 1);
819       *aoffsetp += 5;
820       break;
821     }
822   return ioffset;
823 }
824
825 static int
826 get_displacement (buffer, aoffsetp)
827      char *buffer;
828      int *aoffsetp;
829 {
830   int Ivalue;
831   short Ivalue2;
832
833   Ivalue = bit_extract (buffer, *aoffsetp, 8);
834   switch (Ivalue & 0xc0)
835     {
836     case 0x00:
837     case 0x40:
838       Ivalue = sign_extend (Ivalue, 7);
839       *aoffsetp += 8;
840       break;
841     case 0x80:
842       Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
843       flip_bytes (&Ivalue2, 2);
844       Ivalue = sign_extend (Ivalue2, 14);
845       *aoffsetp += 16;
846       break;
847     case 0xc0:
848       Ivalue = bit_extract (buffer, *aoffsetp, 32);
849       flip_bytes (&Ivalue, 4);
850       Ivalue = sign_extend (Ivalue, 30);
851       *aoffsetp += 32;
852       break;
853     }
854   return Ivalue;
855 }
856 \f
857
858 #if 1 /* a version that should work on ns32k f's&d's on any machine */
859 static int
860 invalid_float (p, len)
861      register char *p;
862      register int len;
863 {
864   register int val;
865
866   if ( len == 4 )
867     val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff
868            || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 &&
869                bit_extract_simple(p, 0, 23)/*mantisa*/ != 0));
870   else if ( len == 8 )
871     val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff
872            || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0
873                && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0
874                    || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0)));
875   else
876     val = 1;
877   return (val);
878 }
879 #else
880
881 /* assumes the bytes have been swapped to local order */
882 typedef union { double d;
883                 float f;
884                 struct { unsigned m:23, e:8, :1;} sf;
885                 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
886               } float_type_u;
887
888 static int
889 invalid_float (p, len)
890      register float_type_u *p;
891      register int len;
892 {
893   register int val;
894   if ( len == sizeof (float) )
895     val = (p->sf.e == 0xff
896            || (p->sf.e == 0 && p->sf.m != 0));
897   else if ( len == sizeof (double) )
898     val = (p->sd.e == 0x7ff
899            || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
900   else
901     val = 1;
902   return (val);
903 }
904 #endif