1999-09-12 Donn Terry <donn@interix.com>
[binutils.git] / opcodes / ns32k-dis.c
blob050266be849014bfb4aecfc7fdca647dba401653
1 /* Print National Semiconductor 32000 instructions.
2 Copyright (c) 1986, 88, 91, 92, 94, 95, 1998 Free Software Foundation, Inc.
4 This file is part of opcodes library.
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.
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.
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. */
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"
30 static disassemble_info *dis_info;
33 * Hacks to get it to compile <= READ THESE AS FIXES NEEDED
35 #define INVALID_FLOAT(val, size) invalid_float((char *)val, size)
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));
42 static long read_memory_integer(addr, nr)
43 unsigned char *addr;
44 int nr;
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));
52 return val;
55 /* 32000 instructions are never longer than this. */
56 #define MAXLEN 62
59 #include <setjmp.h>
61 struct private
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;
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)))
78 static int
79 fetch_data (info, addr)
80 struct disassemble_info *info;
81 bfd_byte *addr;
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);
87 status = (*info->read_memory_func) (start,
88 priv->max_fetched,
89 addr - priv->max_fetched,
90 info);
91 if (status != 0)
93 (*info->memory_error_func) (status, start, info);
94 longjmp (priv->bailout, 1);
96 else
97 priv->max_fetched = addr;
98 return 1;
100 /* Number of elements in the opcode table. */
101 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
103 #define NEXT_IS_ADDR '|'
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 */
113 static const struct ns32k_option opt_u[]= /* restore, exit */
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 }
126 static const struct ns32k_option opt_U[]= /* save, enter */
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 }
139 static const struct ns32k_option opt_O[]= /* setcfg */
141 { "c", 0x8, 0x8 },
142 { "m", 0x4, 0x4 },
143 { "f", 0x2, 0x2 },
144 { "i", 0x1, 0x1 },
145 { 0 , 0x0, 0x0 }
148 static const struct ns32k_option opt_C[]= /* cinv */
150 { "a", 0x4, 0x4 },
151 { "i", 0x2, 0x2 },
152 { "d", 0x1, 0x1 },
153 { 0 , 0x0, 0x0 }
156 static const struct ns32k_option opt_S[]= /* string inst */
158 { "b", 0x1, 0x1 },
159 { "u", 0x6, 0x6 },
160 { "w", 0x2, 0x2 },
161 { 0 , 0x0, 0x0 }
164 static const struct ns32k_option list_P532[]= /* lpr spr */
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 }
182 static const struct ns32k_option list_M532[]= /* lmr smr */
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 }
194 static const struct ns32k_option list_P032[]= /* lpr spr */
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 }
206 static const struct ns32k_option list_M032[]= /* lmr smr */
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 }
223 * figure out which options are present
225 static void
226 optlist(options, optionP, result)
227 int options;
228 const struct ns32k_option *optionP;
229 char *result;
231 if (options == 0) {
232 sprintf(result, "[]");
233 return;
235 sprintf(result, "[");
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, ",");
246 if (options != 0)
247 strcat(result, "undefined");
249 strcat(result, "]");
252 static void
253 list_search (reg_value, optionP, result)
254 int reg_value;
255 const struct ns32k_option *optionP;
256 char *result;
258 for (; optionP->pattern; optionP++) {
259 if ((reg_value & optionP->match) == optionP->value) {
260 sprintf(result, "%s", optionP->pattern);
261 return;
264 sprintf(result, "undefined");
268 * extract "count" bits starting "offset" bits
269 * into buffer
272 static int
273 bit_extract (buffer, offset, count)
274 bfd_byte *buffer;
275 int offset;
276 int count;
278 int result;
279 int bit;
281 buffer += offset >> 3;
282 offset &= 7;
283 bit = 1;
284 result = 0;
285 while (count--)
287 FETCH_DATA(dis_info, buffer + 1);
288 if ((*buffer & (1 << offset)))
289 result |= bit;
290 if (++offset == 8)
292 offset = 0;
293 buffer++;
295 bit <<= 1;
297 return result;
300 /* Like bit extract but the buffer is valid and doen't need to be
301 * fetched
303 static int
304 bit_extract_simple (buffer, offset, count)
305 bfd_byte *buffer;
306 int offset;
307 int count;
309 int result;
310 int mask;
311 int bit;
313 buffer += offset >> 3;
314 offset &= 7;
315 bit = 1;
316 result = 0;
317 while (count--)
319 if ((*buffer & (1 << offset)))
320 result |= bit;
321 if (++offset == 8)
323 offset = 0;
324 buffer++;
326 bit <<= 1;
328 return result;
331 static void
332 bit_copy (buffer, offset, count, to)
333 char *buffer;
334 int offset;
335 int count;
336 char *to;
338 for(; count > 8; count -= 8, to++, offset += 8)
339 *to = bit_extract (buffer, offset, 8);
340 *to = bit_extract (buffer, offset, count);
344 static int
345 sign_extend (value, bits)
346 int value, bits;
348 value = value & ((1 << bits) - 1);
349 return (value & (1 << (bits-1))
350 ? value | (~((1 << bits) - 1))
351 : value);
354 static void
355 flip_bytes (ptr, count)
356 char *ptr;
357 int count;
359 char tmp;
361 while (count > 0)
363 tmp = ptr[0];
364 ptr[0] = ptr[count-1];
365 ptr[count-1] = tmp;
366 ptr++;
367 count -= 2;
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')
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
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)
390 /* Print the 32000 instruction at address MEMADDR in debugged memory,
391 on STREAM. Returns length of the instruction, in bytes. */
394 print_insn_ns32k (memaddr, info)
395 bfd_vma memaddr;
396 disassemble_info *info;
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;
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;
417 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
418 * us over the end of accessible data unnecessarilly
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);
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;
438 /* Handle undefined instructions. */
439 if (i == NOPCODES)
441 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
442 return 1;
446 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
448 ioffset = ns32k_opcodes[i].opcode_size;
449 aoffset = ns32k_opcodes[i].opcode_size;
450 d = ns32k_opcodes[i].operands;
452 if (*d)
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];
460 /* 0 for operand A, 1 for operand B, greater for other args. */
461 int whicharg = 0;
463 (*dis_info->fprintf_func)(dis_info->stream, "\t");
465 maxarg = 0;
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]))
473 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
475 if (Adrmod_is_index (addr_mode))
477 aoffset += 8;
478 index_offset[0] = aoffset;
481 if (d[2] && Is_gen(d[3]))
483 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
485 if (Adrmod_is_index (addr_mode))
487 aoffset += 8;
488 index_offset[1] = aoffset;
492 while (*d)
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++;
504 for (argnum = 0; argnum <= maxarg; argnum++)
506 bfd_vma addr;
507 char *ch;
508 for (ch = arg_bufs[argnum]; *ch;)
510 if (*ch == NEXT_IS_ADDR)
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;
520 else
521 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
523 if (argnum < maxarg)
524 (*dis_info->fprintf_func)(dis_info->stream, ", ");
527 return aoffset / 8;
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). */
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;
549 int addr_mode;
550 float Fvalue;
551 double Lvalue;
552 int Ivalue;
553 int disp1, disp2;
554 int index;
555 int size;
557 switch (d)
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)
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)
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);
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)
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!
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;
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);
708 static const char *ind = "bwdq";
709 char *off;
711 off = result + strlen (result);
712 sprintf (off, "[r%d:%c]", index,
713 ind[addr_mode & 3]);
715 break;
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);
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...
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 */
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;
812 return ioffset;
815 static int
816 get_displacement (buffer, aoffsetp)
817 char *buffer;
818 int *aoffsetp;
820 int Ivalue;
821 short Ivalue2;
823 Ivalue = bit_extract (buffer, *aoffsetp, 8);
824 switch (Ivalue & 0xc0)
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;
844 return Ivalue;
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;
854 register int val;
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);
869 #else
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;
878 static int
879 invalid_float (p, len)
880 register float_type_u *p;
881 register int len;
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);
894 #endif