This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / opcodes / ns32k-dis.c
1 /* Print National Semiconductor 32000 instructions.
2    Copyright 1986, 1988, 1991, 1992, 1994 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., 675 Mass Ave, Cambridge, MA 02139, 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
29 static disassemble_info *dis_info;
30
31 /*
32  * Hacks to get it to compile <= READ THESE AS FIXES NEEDED
33  */
34 #define CORE_ADDR unsigned long
35 #define INVALID_FLOAT(val, size) invalid_float((char *)val, size)
36
37 static long read_memory_integer(addr, nr)
38      unsigned char *addr;
39      int nr;
40 {
41   long val;
42   int i;
43   for (val = 0, i = nr - 1; i >= 0; i--) {
44     val =  (val << 8);
45     val |= (0xff & *(addr + i));
46   }
47   return val;
48 }
49
50 /* 32000 instructions are never longer than this.  */
51 #define MAXLEN 62
52
53
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
74 fetch_data (info, addr)
75      struct disassemble_info *info;
76      bfd_byte *addr;
77 {
78   int status;
79   struct private *priv = (struct private *)info->private_data;
80   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
81
82   status = (*info->read_memory_func) (start,
83                                       priv->max_fetched,
84                                       addr - priv->max_fetched,
85                                       info);
86   if (status != 0)
87     {
88       (*info->memory_error_func) (status, start, info);
89       longjmp (priv->bailout, 1);
90     }
91   else
92     priv->max_fetched = addr;
93   return 1;
94 }
95 /* Number of elements in the opcode table.  */
96 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
97
98 #define NEXT_IS_ADDR    '|'
99
100 \f
101 struct option {
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 \f
108 static struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 /*
218  * figure out which options are present
219  */
220 static void
221 optlist(options, optionP, result)
222     int options;
223     struct option *optionP;
224     char *result;
225 {
226     if (options == 0) {
227         sprintf(result, "[]");
228         return;
229     }
230     sprintf(result, "[");
231
232     for (; (options != 0) && optionP->pattern; optionP++) {
233         if ((options & optionP->match) == optionP->value) {
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     if (options != 0)
242         strcat(result, "undefined");
243
244     strcat(result, "]");
245 }
246
247 static list_search(reg_value, optionP, result)
248     int reg_value;
249     struct option *optionP;
250     char *result;
251 {
252     for (; optionP->pattern; optionP++) {
253         if ((reg_value & optionP->match) == optionP->value) {
254             sprintf(result, "%s", optionP->pattern);
255             return;
256         }
257     }
258     sprintf(result, "undefined");
259 }
260 \f
261 /*
262  * extract "count" bits starting "offset" bits
263  * into buffer
264  */
265
266 static int
267 bit_extract (buffer, offset, count)
268      bfd_byte *buffer;
269      int offset;
270      int count;
271 {
272   int result;
273   int mask;
274   int bit;
275
276   buffer += offset >> 3;
277   offset &= 7;
278   bit = 1;
279   result = 0;
280   while (count--)
281     {
282       FETCH_DATA(dis_info, buffer + 1);
283       if ((*buffer & (1 << offset)))
284         result |= bit;
285       if (++offset == 8)
286         {
287           offset = 0;
288           buffer++;
289         }
290       bit <<= 1;
291     }
292   return result;
293 }
294
295 static void
296 bit_copy (buffer, offset, count, to)
297      char *buffer;
298      int offset;
299      int count;
300      char *to;
301 {
302   for(; count > 8; count -= 8, to++, offset += 8)
303     *to = bit_extract (buffer, offset, 8);
304   *to = bit_extract (buffer, offset, count);
305 }
306
307
308 static sign_extend (value, bits)
309      int value, bits;
310 {
311   value = value & ((1 << bits) - 1);
312   return (value & (1 << (bits-1))
313           ? value | (~((1 << bits) - 1))
314           : value);
315 }
316
317 static flip_bytes (ptr, count)
318      char *ptr;
319      int count;
320 {
321   char tmp;
322
323   while (count > 0)
324     {
325       tmp = ptr[0];
326       ptr[0] = ptr[count-1];
327       ptr[count-1] = tmp;
328       ptr++;
329       count -= 2;
330     }
331 }
332 \f
333 /* Given a character C, does it represent a general addressing mode?  */
334 #define Is_gen(c) \
335   ((c) == 'F' || (c) == 'L' || (c) == 'B' \
336    || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
337
338 /* Adressing modes.  */
339 #define Adrmod_index_byte 0x1c
340 #define Adrmod_index_word 0x1d
341 #define Adrmod_index_doubleword 0x1e
342 #define Adrmod_index_quadword 0x1f
343
344 /* Is MODE an indexed addressing mode?  */
345 #define Adrmod_is_index(mode) \
346   (mode == Adrmod_index_byte \
347    || mode == Adrmod_index_word \
348    || mode == Adrmod_index_doubleword \
349    || mode == Adrmod_index_quadword)
350
351 \f
352 /* Print the 32000 instruction at address MEMADDR in debugged memory,
353    on STREAM.  Returns length of the instruction, in bytes.  */
354
355 int
356 print_insn_ns32k (memaddr, info)
357      bfd_vma memaddr;
358      disassemble_info *info;
359 {
360   register int i;
361   register unsigned char *p;
362   register char *d;
363   unsigned short first_word;
364   int gen, disp;
365   int ioffset;          /* bits into instruction */
366   int aoffset;          /* bits into arguments */
367   char arg_bufs[MAX_ARGS+1][ARG_LEN];
368   int argnum;
369   int maxarg;
370   struct private priv;
371   bfd_byte *buffer = priv.the_buffer;
372   dis_info = info;
373
374   info->private_data = (PTR) &priv;
375   priv.max_fetched = priv.the_buffer;
376   priv.insn_start = memaddr;
377   if (setjmp (priv.bailout) != 0)
378     /* Error return.  */
379     return -1;
380
381   /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
382    * us over the end of accessible data unnecessarilly
383    */
384   FETCH_DATA(info, buffer + 1);
385   for (i = 0; i < NOPCODES; i++)
386     if (ns32k_opcodes[i].opcode_id_size <= 8
387         && ((buffer[0] & ((1 << ns32k_opcodes[i].opcode_id_size) - 1))
388             == ns32k_opcodes[i].opcode_seed))
389       break;
390   if (i == NOPCODES) {
391     /* Maybe it is 9 to 16 bits big */
392     FETCH_DATA(info, buffer + 2);
393     first_word = read_memory_integer(buffer, 2);
394
395     for (i = 0; i < NOPCODES; i++)
396       if ((first_word & ((1 << ns32k_opcodes[i].opcode_id_size) - 1))
397           == ns32k_opcodes[i].opcode_seed)
398         break;
399
400     /* Handle undefined instructions.  */
401     if (i == NOPCODES)
402       {
403         (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
404         return 1;
405       }
406   }
407
408   (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
409
410   ioffset = ns32k_opcodes[i].opcode_size;
411   aoffset = ns32k_opcodes[i].opcode_size;
412   d = ns32k_opcodes[i].operands;
413
414   if (*d)
415     {
416       /* Offset in bits of the first thing beyond each index byte.
417          Element 0 is for operand A and element 1 is for operand B.
418          The rest are irrelevant, but we put them here so we don't
419          index outside the array.  */
420       int index_offset[MAX_ARGS];
421
422       /* 0 for operand A, 1 for operand B, greater for other args.  */
423       int whicharg = 0;
424       
425       (*dis_info->fprintf_func)(dis_info->stream, "\t");
426
427       maxarg = 0;
428
429       /* First we have to find and keep track of the index bytes,
430          if we are using scaled indexed addressing mode, since the index
431          bytes occur right after the basic instruction, not as part
432          of the addressing extension.  */
433       if (Is_gen(d[1]))
434         {
435           int addr_mode = bit_extract (buffer, ioffset - 5, 5);
436
437           if (Adrmod_is_index (addr_mode))
438             {
439               aoffset += 8;
440               index_offset[0] = aoffset;
441             }
442         }
443       if (d[2] && Is_gen(d[3]))
444         {
445           int addr_mode = bit_extract (buffer, ioffset - 10, 5);
446
447           if (Adrmod_is_index (addr_mode))
448             {
449               aoffset += 8;
450               index_offset[1] = aoffset;
451             }
452         }
453
454       while (*d)
455         {
456           argnum = *d - '1';
457           d++;
458           if (argnum > maxarg && argnum < MAX_ARGS)
459             maxarg = argnum;
460           ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
461                                     memaddr, arg_bufs[argnum],
462                                     index_offset[whicharg]);
463           d++;
464           whicharg++;
465         }
466       for (argnum = 0; argnum <= maxarg; argnum++)
467         {
468           CORE_ADDR addr;
469           char *ch;
470           for (ch = arg_bufs[argnum]; *ch;)
471             {
472               if (*ch == NEXT_IS_ADDR)
473                 {
474                   ++ch;
475                   addr = atoi (ch);
476                   (*dis_info->print_address_func) (addr, dis_info);
477                   while (*ch && *ch != NEXT_IS_ADDR)
478                     ++ch;
479                   if (*ch)
480                     ++ch;
481                 }
482               else
483                 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
484             }
485           if (argnum < maxarg)
486             (*dis_info->fprintf_func)(dis_info->stream, ", ");
487         }
488     }
489   return aoffset / 8;
490 }
491
492 /* Print an instruction operand of category given by d.  IOFFSET is
493    the bit position below which small (<1 byte) parts of the operand can
494    be found (usually in the basic instruction, but for indexed
495    addressing it can be in the index byte).  AOFFSETP is a pointer to the
496    bit position of the addressing extension.  BUFFER contains the
497    instruction.  ADDR is where BUFFER was read from.  Put the disassembled
498    version of the operand in RESULT.  INDEX_OFFSET is the bit position
499    of the index byte (it contains garbage if this operand is not a
500    general operand using scaled indexed addressing mode).  */
501
502 print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
503      char d;
504      int ioffset, *aoffsetp;
505      char *buffer;
506      CORE_ADDR addr;
507      char *result;
508      int index_offset;
509 {
510   int addr_mode;
511   float Fvalue;
512   double Lvalue;
513   int Ivalue;
514   int disp1, disp2;
515   int index;
516   int size;
517
518   switch (d)
519     {
520     case 'f':
521       /* a "gen" operand but 5 bits from the end of instruction */
522       ioffset -= 5;
523     case 'Z':
524     case 'F':
525     case 'L':
526     case 'I':
527     case 'B':
528     case 'W':
529     case 'D':
530     case 'A':
531       addr_mode = bit_extract (buffer, ioffset-5, 5);
532       ioffset -= 5;
533       switch (addr_mode)
534         {
535         case 0x0: case 0x1: case 0x2: case 0x3:
536         case 0x4: case 0x5: case 0x6: case 0x7:
537           /* register mode R0 -- R7 */
538           switch (d)
539             {
540             case 'F':
541             case 'L':
542             case 'Z':
543               sprintf (result, "f%d", addr_mode);
544               break;
545             default:
546               sprintf (result, "r%d", addr_mode);
547             }
548           break;
549         case 0x8: case 0x9: case 0xa: case 0xb:
550         case 0xc: case 0xd: case 0xe: case 0xf:
551           /* Register relative disp(R0 -- R7) */
552           disp1 = get_displacement (buffer, aoffsetp);
553           sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
554           break;
555         case 0x10:
556         case 0x11:
557         case 0x12:
558           /* Memory relative disp2(disp1(FP, SP, SB)) */
559           disp1 = get_displacement (buffer, aoffsetp);
560           disp2 = get_displacement (buffer, aoffsetp);
561           sprintf (result, "%d(%d(%s))", disp2, disp1,
562                    addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
563           break;
564         case 0x13:
565           /* reserved */
566           sprintf (result, "reserved");
567           break;
568         case 0x14:
569           /* Immediate */
570           switch (d)
571             {
572             case 'I': case 'Z': case 'A':
573               /* I and Z are output operands and can`t be immediate
574                * A is an address and we can`t have the address of
575                * an immediate either. We don't know how much to increase
576                * aoffsetp by since whatever generated this is broken
577                * anyway!
578                */
579               sprintf (result, "$<undefined>");
580               break;
581             case 'B':
582               Ivalue = bit_extract (buffer, *aoffsetp, 8);
583               Ivalue = sign_extend (Ivalue, 8);
584               *aoffsetp += 8;
585               sprintf (result, "$%d", Ivalue);
586               break;
587             case 'W':
588               Ivalue = bit_extract (buffer, *aoffsetp, 16);
589               flip_bytes (&Ivalue, 2);
590               *aoffsetp += 16;
591               Ivalue = sign_extend (Ivalue, 16);
592               sprintf (result, "$%d", Ivalue);
593               break;
594             case 'D':
595               Ivalue = bit_extract (buffer, *aoffsetp, 32);
596               flip_bytes (&Ivalue, 4);
597               *aoffsetp += 32;
598               sprintf (result, "$%d", Ivalue);
599               break;
600             case 'F':
601               bit_copy (buffer, *aoffsetp, 32, (char *) &Fvalue);
602               flip_bytes (&Fvalue, 4);
603               *aoffsetp += 32;
604               if (INVALID_FLOAT (&Fvalue, 4))
605                 sprintf (result, "<<invalid float 0x%.8x>>", *(int *) &Fvalue);
606               else /* assume host has ieee float */
607                 sprintf (result, "$%g", Fvalue);
608               break;
609             case 'L':
610               bit_copy (buffer, *aoffsetp, 64, (char *) &Lvalue);
611               flip_bytes (&Lvalue, 8);
612               *aoffsetp += 64;
613               if (INVALID_FLOAT (&Lvalue, 8))
614                 sprintf (result, "<<invalid long 0x%.8x%.8x>>",
615                          *(((int *) &Lvalue) + 1), *(int *) &Lvalue);
616               else /* assume host has ieee float */
617                 sprintf (result, "$%g", Lvalue);
618               break;
619             }
620           break;
621         case 0x15:
622           /* Absolute @disp */
623           disp1 = get_displacement (buffer, aoffsetp);
624           sprintf (result, "@|%d|", disp1);
625           break;
626         case 0x16:
627           /* External EXT(disp1) + disp2 (Mod table stuff) */
628           disp1 = get_displacement (buffer, aoffsetp);
629           disp2 = get_displacement (buffer, aoffsetp);
630           sprintf (result, "EXT(%d) + %d", disp1, disp2);
631           break;
632         case 0x17:
633           /* Top of stack tos */
634           sprintf (result, "tos");
635           break;
636         case 0x18:
637           /* Memory space disp(FP) */
638           disp1 = get_displacement (buffer, aoffsetp);
639           sprintf (result, "%d(fp)", disp1);
640           break;
641         case 0x19:
642           /* Memory space disp(SP) */
643           disp1 = get_displacement (buffer, aoffsetp);
644           sprintf (result, "%d(sp)", disp1);
645           break;
646         case 0x1a:
647           /* Memory space disp(SB) */
648           disp1 = get_displacement (buffer, aoffsetp);
649           sprintf (result, "%d(sb)", disp1);
650           break;
651         case 0x1b:
652           /* Memory space disp(PC) */
653           disp1 = get_displacement (buffer, aoffsetp);
654           sprintf (result, "|%d|", addr + disp1);
655           break;
656         case 0x1c:
657         case 0x1d:
658         case 0x1e:
659         case 0x1f:
660           /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
661           index = bit_extract (buffer, index_offset - 8, 3);
662           print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
663                           result, 0);
664           {
665             static char *ind[] = {"b", "w", "d", "q"};
666             char *off;
667
668             off = result + strlen (result);
669             sprintf (off, "[r%d:%s]", index,
670                      ind[addr_mode & 3]);
671           }
672           break;
673         }
674       break;
675     case 'H':
676     case 'q':
677       Ivalue = bit_extract (buffer, ioffset-4, 4);
678       Ivalue = sign_extend (Ivalue, 4);
679       sprintf (result, "%d", Ivalue);
680       ioffset -= 4;
681       break;
682     case 'r':
683       Ivalue = bit_extract (buffer, ioffset-3, 3);
684       sprintf (result, "r%d", Ivalue&7);
685       ioffset -= 3;
686       break;
687     case 'd':
688       sprintf (result, "%d", get_displacement (buffer, aoffsetp));
689       break;
690     case 'b':
691       Ivalue = get_displacement (buffer, aoffsetp);
692       /*
693        * Warning!!  HACK ALERT!
694        * Operand type 'b' is only used by the cmp{b,w,d} and
695        * movm{b,w,d} instructions; we need to know whether
696        * it's a `b' or `w' or `d' instruction; and for both
697        * cmpm and movm it's stored at the same place so we
698        * just grab two bits of the opcode and look at it...
699        * 
700        */
701       size = bit_extract(buffer, ioffset-6, 2);
702       if (size == 0)            /* 00 => b */
703         size = 1;
704       else if (size == 1)       /* 01 => w */
705         size = 2;
706       else
707         size = 4;               /* 11 => d */
708
709       sprintf (result, "%d", (Ivalue / size) + 1);
710       break;
711     case 'p':
712       sprintf (result, "%c%d%c", NEXT_IS_ADDR,
713                addr + get_displacement (buffer, aoffsetp),
714                NEXT_IS_ADDR);
715       break;
716     case 'i':
717       Ivalue = bit_extract (buffer, *aoffsetp, 8);
718       *aoffsetp += 8;
719       sprintf (result, "0x%x", Ivalue);
720       break;
721     case 'u':
722       Ivalue = bit_extract (buffer, *aoffsetp, 8);
723       optlist(Ivalue, opt_u, result);
724       *aoffsetp += 8;
725       break;
726     case 'U':
727       Ivalue = bit_extract(buffer, *aoffsetp, 8);
728       optlist(Ivalue, opt_U, result);
729       *aoffsetp += 8;
730       break;
731     case 'O':
732       Ivalue = bit_extract(buffer, ioffset-9, 9);
733       optlist(Ivalue, opt_O, result);
734       ioffset -= 9;
735       break;
736     case 'C':
737       Ivalue = bit_extract(buffer, ioffset-4, 4);
738       optlist(Ivalue, opt_C, result);
739       ioffset -= 4;
740       break;
741     case 'S':
742       Ivalue = bit_extract(buffer, ioffset - 8, 8);
743       optlist(Ivalue, opt_S, result);
744       ioffset -= 8;
745       break;
746     case 'M':
747       Ivalue = bit_extract(buffer, ioffset-4, 4);
748       list_search(Ivalue, 0 ? list_M032 : list_M532, result);
749       ioffset -= 4;
750       break;
751     case 'P':
752       Ivalue = bit_extract(buffer, ioffset-4, 4);
753       list_search(Ivalue, 0 ? list_P032 : list_P532, result);
754       ioffset -= 4;
755       break;
756     case 'g':
757       Ivalue = bit_extract(buffer, *aoffsetp, 3);
758       sprintf(result, "%d", Ivalue);
759       *aoffsetp += 3;
760       break;
761     case 'G':
762       Ivalue = bit_extract(buffer, *aoffsetp, 5);
763       sprintf(result, "%d", Ivalue + 1);
764       *aoffsetp += 5;
765       break;
766     }
767   return ioffset;
768 }
769
770 get_displacement (buffer, aoffsetp)
771      char *buffer;
772      int *aoffsetp;
773 {
774   int Ivalue;
775   short Ivalue2;
776
777   Ivalue = bit_extract (buffer, *aoffsetp, 8);
778   switch (Ivalue & 0xc0)
779     {
780     case 0x00:
781     case 0x40:
782       Ivalue = sign_extend (Ivalue, 7);
783       *aoffsetp += 8;
784       break;
785     case 0x80:
786       Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
787       flip_bytes (&Ivalue2, 2);
788       Ivalue = sign_extend (Ivalue2, 14);
789       *aoffsetp += 16;
790       break;
791     case 0xc0:
792       Ivalue = bit_extract (buffer, *aoffsetp, 32);
793       flip_bytes (&Ivalue, 4);
794       Ivalue = sign_extend (Ivalue, 30);
795       *aoffsetp += 32;
796       break;
797     }
798   return Ivalue;
799 }
800 \f
801
802 #if 1 /* a version that should work on ns32k f's&d's on any machine */
803 int invalid_float(p, len)
804      register char *p;
805      register int len;
806 {
807   register val;
808
809   if ( len == 4 )
810     val = (bit_extract(p, 23, 8)/*exponent*/ == 0xff
811            || (bit_extract(p, 23, 8)/*exponent*/ == 0 &&
812                bit_extract(p, 0, 23)/*mantisa*/ != 0));
813   else if ( len == 8 )
814     val = (bit_extract(p, 52, 11)/*exponent*/ == 0x7ff
815            || (bit_extract(p, 52, 11)/*exponent*/ == 0
816                && (bit_extract(p, 0, 32)/*low mantisa*/ != 0
817                    || bit_extract(p, 32, 20)/*high mantisa*/ != 0)));
818   else
819     val = 1;
820   return (val);
821 }
822 #else
823
824 /* assumes the bytes have been swapped to local order */
825 typedef union { double d;
826                 float f;
827                 struct { unsigned m:23, e:8, :1;} sf;
828                 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
829               } float_type_u;
830
831 int invalid_float(p, len)
832      register float_type_u *p;
833      register int len;
834 {
835   register int val;
836   if ( len == sizeof (float) )
837     val = (p->sf.e == 0xff
838            || (p->sf.e == 0 && p->sf.m != 0));
839   else if ( len == sizeof (double) )
840     val = (p->sd.e == 0x7ff
841            || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
842   else
843     val = 1;
844   return (val);
845 }
846 #endif