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