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