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