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