source: trunk/src/binutils/opcodes/ns32k-dis.c@ 578

Last change on this file since 578 was 10, checked in by bird, 22 years ago

Initial revision

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