* readelf.c (display_debug_frames): Don't crash for mismatched
[deliverable/binutils-gdb.git] / opcodes / ns32k-dis.c
CommitLineData
252b5132 1/* Print National Semiconductor 32000 instructions.
6a51a8a8 2 Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002
060d22b0 3 Free Software Foundation, Inc.
252b5132
RH
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));
d83c6548
AJ
42static long int read_memory_integer PARAMS ((unsigned char *, int));
43static int fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
44struct ns32k_option;
45static void optlist PARAMS ((int, const struct ns32k_option *, char *));
46static void list_search PARAMS ((int, const struct ns32k_option *, char *));
47static int bit_extract PARAMS ((bfd_byte *, int, int));
48static int bit_extract_simple PARAMS ((bfd_byte *, int, int));
49static void bit_copy PARAMS ((char *, int, int, char *));
50static int sign_extend PARAMS ((int, int));
51static void flip_bytes PARAMS ((char *, int));
252b5132
RH
52
53static long read_memory_integer(addr, nr)
54 unsigned char *addr;
55 int nr;
56{
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));
62 }
63 return val;
64}
65
66/* 32000 instructions are never longer than this. */
67#define MAXLEN 62
68
69
70#include <setjmp.h>
71
72struct private
73{
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;
79};
80
81
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)))
88
89static int
90fetch_data (info, addr)
91 struct disassemble_info *info;
92 bfd_byte *addr;
93{
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);
97
98 status = (*info->read_memory_func) (start,
99 priv->max_fetched,
100 addr - priv->max_fetched,
101 info);
102 if (status != 0)
103 {
104 (*info->memory_error_func) (status, start, info);
105 longjmp (priv->bailout, 1);
106 }
107 else
108 priv->max_fetched = addr;
109 return 1;
110}
111/* Number of elements in the opcode table. */
112#define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
113
114#define NEXT_IS_ADDR '|'
115
116\f
117struct 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 */
121};
122
123\f
124static const struct ns32k_option opt_u[]= /* restore, exit */
125{
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 }
135};
136
137static const struct ns32k_option opt_U[]= /* save, enter */
138{
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 }
148};
149
150static const struct ns32k_option opt_O[]= /* setcfg */
151{
152 { "c", 0x8, 0x8 },
153 { "m", 0x4, 0x4 },
154 { "f", 0x2, 0x2 },
155 { "i", 0x1, 0x1 },
156 { 0 , 0x0, 0x0 }
157};
158
159static const struct ns32k_option opt_C[]= /* cinv */
160{
161 { "a", 0x4, 0x4 },
162 { "i", 0x2, 0x2 },
163 { "d", 0x1, 0x1 },
164 { 0 , 0x0, 0x0 }
165};
166
167static const struct ns32k_option opt_S[]= /* string inst */
168{
169 { "b", 0x1, 0x1 },
170 { "u", 0x6, 0x6 },
171 { "w", 0x2, 0x2 },
172 { 0 , 0x0, 0x0 }
173};
174
175static const struct ns32k_option list_P532[]= /* lpr spr */
176{
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 }
191};
192
193static const struct ns32k_option list_M532[]= /* lmr smr */
194{
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 }
203};
204
205static const struct ns32k_option list_P032[]= /* lpr spr */
206{
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 }
215};
216
217static const struct ns32k_option list_M032[]= /* lmr smr */
218{
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 }
230};
231
232
233/*
234 * figure out which options are present
235 */
236static void
237optlist(options, optionP, result)
238 int options;
239 const struct ns32k_option *optionP;
240 char *result;
241{
242 if (options == 0) {
243 sprintf(result, "[]");
244 return;
245 }
246 sprintf(result, "[");
247
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, ",");
255 }
256 }
257 if (options != 0)
258 strcat(result, "undefined");
259
260 strcat(result, "]");
261}
262
263static void
264list_search (reg_value, optionP, result)
265 int reg_value;
266 const struct ns32k_option *optionP;
267 char *result;
268{
269 for (; optionP->pattern; optionP++) {
270 if ((reg_value & optionP->match) == optionP->value) {
271 sprintf(result, "%s", optionP->pattern);
272 return;
273 }
274 }
275 sprintf(result, "undefined");
276}
277\f
278/*
279 * extract "count" bits starting "offset" bits
280 * into buffer
281 */
282
283static int
284bit_extract (buffer, offset, count)
285 bfd_byte *buffer;
286 int offset;
287 int count;
288{
289 int result;
290 int bit;
291
292 buffer += offset >> 3;
293 offset &= 7;
294 bit = 1;
295 result = 0;
296 while (count--)
297 {
298 FETCH_DATA(dis_info, buffer + 1);
299 if ((*buffer & (1 << offset)))
300 result |= bit;
301 if (++offset == 8)
302 {
303 offset = 0;
304 buffer++;
305 }
306 bit <<= 1;
307 }
308 return result;
309}
310
311/* Like bit extract but the buffer is valid and doen't need to be
312 * fetched
313 */
314static int
315bit_extract_simple (buffer, offset, count)
316 bfd_byte *buffer;
317 int offset;
318 int count;
319{
320 int result;
252b5132
RH
321 int bit;
322
323 buffer += offset >> 3;
324 offset &= 7;
325 bit = 1;
326 result = 0;
327 while (count--)
328 {
329 if ((*buffer & (1 << offset)))
330 result |= bit;
331 if (++offset == 8)
332 {
333 offset = 0;
334 buffer++;
335 }
336 bit <<= 1;
337 }
338 return result;
339}
340
341static void
342bit_copy (buffer, offset, count, to)
343 char *buffer;
344 int offset;
345 int count;
346 char *to;
347{
348 for(; count > 8; count -= 8, to++, offset += 8)
349 *to = bit_extract (buffer, offset, 8);
350 *to = bit_extract (buffer, offset, count);
351}
352
353
354static int
355sign_extend (value, bits)
356 int value, bits;
357{
358 value = value & ((1 << bits) - 1);
359 return (value & (1 << (bits-1))
360 ? value | (~((1 << bits) - 1))
361 : value);
362}
363
364static void
365flip_bytes (ptr, count)
366 char *ptr;
367 int count;
368{
369 char tmp;
370
371 while (count > 0)
372 {
373 tmp = ptr[0];
374 ptr[0] = ptr[count-1];
375 ptr[count-1] = tmp;
376 ptr++;
377 count -= 2;
378 }
379}
380\f
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')
385
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
391
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)
398
399\f
400/* Print the 32000 instruction at address MEMADDR in debugged memory,
401 on STREAM. Returns length of the instruction, in bytes. */
402
403int
404print_insn_ns32k (memaddr, info)
405 bfd_vma memaddr;
406 disassemble_info *info;
407{
e3c99126
AM
408 unsigned int i;
409 const char *d;
252b5132
RH
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;
419
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;
426
427 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
428 * us over the end of accessible data unnecessarilly
429 */
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);
441
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;
447
448 /* Handle undefined instructions. */
449 if (i == NOPCODES)
450 {
451 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
452 return 1;
453 }
454 }
455
456 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);
457
458 ioffset = ns32k_opcodes[i].opcode_size;
459 aoffset = ns32k_opcodes[i].opcode_size;
460 d = ns32k_opcodes[i].operands;
461
462 if (*d)
463 {
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];
469
470 /* 0 for operand A, 1 for operand B, greater for other args. */
471 int whicharg = 0;
472
473 (*dis_info->fprintf_func)(dis_info->stream, "\t");
474
475 maxarg = 0;
476
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]))
482 {
483 int addr_mode = bit_extract (buffer, ioffset - 5, 5);
484
485 if (Adrmod_is_index (addr_mode))
486 {
487 aoffset += 8;
488 index_offset[0] = aoffset;
489 }
490 }
491 if (d[2] && Is_gen(d[3]))
492 {
493 int addr_mode = bit_extract (buffer, ioffset - 10, 5);
494
495 if (Adrmod_is_index (addr_mode))
496 {
497 aoffset += 8;
498 index_offset[1] = aoffset;
499 }
500 }
501
502 while (*d)
503 {
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++;
513 }
514 for (argnum = 0; argnum <= maxarg; argnum++)
515 {
516 bfd_vma addr;
517 char *ch;
518 for (ch = arg_bufs[argnum]; *ch;)
519 {
520 if (*ch == NEXT_IS_ADDR)
521 {
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;
529 }
530 else
531 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
532 }
533 if (argnum < maxarg)
534 (*dis_info->fprintf_func)(dis_info->stream, ", ");
535 }
536 }
537 return aoffset / 8;
538}
539
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). */
549
550static int
551print_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;
558{
6a51a8a8
AM
559 union {
560 float f;
561 double d;
562 int i[2];
563 } value;
252b5132 564 int Ivalue;
6a51a8a8 565 int addr_mode;
252b5132
RH
566 int disp1, disp2;
567 int index;
568 int size;
569
570 switch (d)
571 {
572 case 'f':
573 /* a "gen" operand but 5 bits from the end of instruction */
574 ioffset -= 5;
575 case 'Z':
576 case 'F':
577 case 'L':
578 case 'I':
579 case 'B':
580 case 'W':
581 case 'D':
582 case 'A':
583 addr_mode = bit_extract (buffer, ioffset-5, 5);
584 ioffset -= 5;
585 switch (addr_mode)
586 {
587 case 0x0: case 0x1: case 0x2: case 0x3:
588 case 0x4: case 0x5: case 0x6: case 0x7:
589 /* register mode R0 -- R7 */
590 switch (d)
591 {
592 case 'F':
593 case 'L':
594 case 'Z':
595 sprintf (result, "f%d", addr_mode);
596 break;
597 default:
598 sprintf (result, "r%d", addr_mode);
599 }
600 break;
601 case 0x8: case 0x9: case 0xa: case 0xb:
602 case 0xc: case 0xd: case 0xe: case 0xf:
603 /* Register relative disp(R0 -- R7) */
604 disp1 = get_displacement (buffer, aoffsetp);
605 sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
606 break;
607 case 0x10:
608 case 0x11:
609 case 0x12:
610 /* Memory relative disp2(disp1(FP, SP, SB)) */
611 disp1 = get_displacement (buffer, aoffsetp);
612 disp2 = get_displacement (buffer, aoffsetp);
613 sprintf (result, "%d(%d(%s))", disp2, disp1,
614 addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
615 break;
616 case 0x13:
617 /* reserved */
618 sprintf (result, "reserved");
619 break;
620 case 0x14:
621 /* Immediate */
622 switch (d)
623 {
624 case 'I': case 'Z': case 'A':
625 /* I and Z are output operands and can`t be immediate
626 * A is an address and we can`t have the address of
627 * an immediate either. We don't know how much to increase
628 * aoffsetp by since whatever generated this is broken
629 * anyway!
630 */
631 sprintf (result, _("$<undefined>"));
632 break;
633 case 'B':
634 Ivalue = bit_extract (buffer, *aoffsetp, 8);
635 Ivalue = sign_extend (Ivalue, 8);
636 *aoffsetp += 8;
637 sprintf (result, "$%d", Ivalue);
638 break;
639 case 'W':
640 Ivalue = bit_extract (buffer, *aoffsetp, 16);
fc05c67f 641 flip_bytes ((char *) & Ivalue, 2);
252b5132
RH
642 *aoffsetp += 16;
643 Ivalue = sign_extend (Ivalue, 16);
644 sprintf (result, "$%d", Ivalue);
645 break;
646 case 'D':
647 Ivalue = bit_extract (buffer, *aoffsetp, 32);
fc05c67f 648 flip_bytes ((char *) & Ivalue, 4);
252b5132
RH
649 *aoffsetp += 32;
650 sprintf (result, "$%d", Ivalue);
651 break;
652 case 'F':
6a51a8a8
AM
653 bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
654 flip_bytes ((char *) &value.f, 4);
252b5132 655 *aoffsetp += 32;
6a51a8a8
AM
656 if (INVALID_FLOAT (&value.f, 4))
657 sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
252b5132 658 else /* assume host has ieee float */
6a51a8a8 659 sprintf (result, "$%g", value.f);
252b5132
RH
660 break;
661 case 'L':
6a51a8a8
AM
662 bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
663 flip_bytes ((char *) &value.d, 8);
252b5132 664 *aoffsetp += 64;
6a51a8a8
AM
665 if (INVALID_FLOAT (&value.d, 8))
666 sprintf (result, "<<invalid double 0x%.8x%.8x>>",
667 value.i[1], value.i[0]);
252b5132 668 else /* assume host has ieee float */
6a51a8a8 669 sprintf (result, "$%g", value.d);
252b5132
RH
670 break;
671 }
672 break;
673 case 0x15:
674 /* Absolute @disp */
675 disp1 = get_displacement (buffer, aoffsetp);
676 sprintf (result, "@|%d|", disp1);
677 break;
678 case 0x16:
679 /* External EXT(disp1) + disp2 (Mod table stuff) */
680 disp1 = get_displacement (buffer, aoffsetp);
681 disp2 = get_displacement (buffer, aoffsetp);
682 sprintf (result, "EXT(%d) + %d", disp1, disp2);
683 break;
684 case 0x17:
685 /* Top of stack tos */
686 sprintf (result, "tos");
687 break;
688 case 0x18:
689 /* Memory space disp(FP) */
690 disp1 = get_displacement (buffer, aoffsetp);
691 sprintf (result, "%d(fp)", disp1);
692 break;
693 case 0x19:
694 /* Memory space disp(SP) */
695 disp1 = get_displacement (buffer, aoffsetp);
696 sprintf (result, "%d(sp)", disp1);
697 break;
698 case 0x1a:
699 /* Memory space disp(SB) */
700 disp1 = get_displacement (buffer, aoffsetp);
701 sprintf (result, "%d(sb)", disp1);
702 break;
703 case 0x1b:
704 /* Memory space disp(PC) */
705 disp1 = get_displacement (buffer, aoffsetp);
706 *result++ = NEXT_IS_ADDR;
707 sprintf_vma (result, addr + disp1);
708 result += strlen (result);
709 *result++ = NEXT_IS_ADDR;
710 *result = '\0';
711 break;
712 case 0x1c:
713 case 0x1d:
714 case 0x1e:
715 case 0x1f:
716 /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
717 index = bit_extract (buffer, index_offset - 8, 3);
718 print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
719 result, 0);
720 {
721 static const char *ind = "bwdq";
722 char *off;
723
724 off = result + strlen (result);
725 sprintf (off, "[r%d:%c]", index,
726 ind[addr_mode & 3]);
727 }
728 break;
729 }
730 break;
731 case 'H':
732 case 'q':
733 Ivalue = bit_extract (buffer, ioffset-4, 4);
734 Ivalue = sign_extend (Ivalue, 4);
735 sprintf (result, "%d", Ivalue);
736 ioffset -= 4;
737 break;
738 case 'r':
739 Ivalue = bit_extract (buffer, ioffset-3, 3);
740 sprintf (result, "r%d", Ivalue&7);
741 ioffset -= 3;
742 break;
743 case 'd':
744 sprintf (result, "%d", get_displacement (buffer, aoffsetp));
745 break;
746 case 'b':
747 Ivalue = get_displacement (buffer, aoffsetp);
748 /*
749 * Warning!! HACK ALERT!
750 * Operand type 'b' is only used by the cmp{b,w,d} and
751 * movm{b,w,d} instructions; we need to know whether
752 * it's a `b' or `w' or `d' instruction; and for both
753 * cmpm and movm it's stored at the same place so we
754 * just grab two bits of the opcode and look at it...
755 *
756 */
757 size = bit_extract(buffer, ioffset-6, 2);
758 if (size == 0) /* 00 => b */
759 size = 1;
760 else if (size == 1) /* 01 => w */
761 size = 2;
762 else
763 size = 4; /* 11 => d */
764
765 sprintf (result, "%d", (Ivalue / size) + 1);
766 break;
767 case 'p':
768 *result++ = NEXT_IS_ADDR;
769 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
770 result += strlen (result);
771 *result++ = NEXT_IS_ADDR;
772 *result = '\0';
773 break;
774 case 'i':
775 Ivalue = bit_extract (buffer, *aoffsetp, 8);
776 *aoffsetp += 8;
777 sprintf (result, "0x%x", Ivalue);
778 break;
779 case 'u':
780 Ivalue = bit_extract (buffer, *aoffsetp, 8);
781 optlist(Ivalue, opt_u, result);
782 *aoffsetp += 8;
783 break;
784 case 'U':
785 Ivalue = bit_extract(buffer, *aoffsetp, 8);
786 optlist(Ivalue, opt_U, result);
787 *aoffsetp += 8;
788 break;
789 case 'O':
790 Ivalue = bit_extract(buffer, ioffset-9, 9);
791 optlist(Ivalue, opt_O, result);
792 ioffset -= 9;
793 break;
794 case 'C':
795 Ivalue = bit_extract(buffer, ioffset-4, 4);
796 optlist(Ivalue, opt_C, result);
797 ioffset -= 4;
798 break;
799 case 'S':
800 Ivalue = bit_extract(buffer, ioffset - 8, 8);
801 optlist(Ivalue, opt_S, result);
802 ioffset -= 8;
803 break;
804 case 'M':
805 Ivalue = bit_extract(buffer, ioffset-4, 4);
806 list_search(Ivalue, 0 ? list_M032 : list_M532, result);
807 ioffset -= 4;
808 break;
809 case 'P':
810 Ivalue = bit_extract(buffer, ioffset-4, 4);
811 list_search(Ivalue, 0 ? list_P032 : list_P532, result);
812 ioffset -= 4;
813 break;
814 case 'g':
815 Ivalue = bit_extract(buffer, *aoffsetp, 3);
816 sprintf(result, "%d", Ivalue);
817 *aoffsetp += 3;
818 break;
819 case 'G':
820 Ivalue = bit_extract(buffer, *aoffsetp, 5);
821 sprintf(result, "%d", Ivalue + 1);
822 *aoffsetp += 5;
823 break;
824 }
825 return ioffset;
826}
827
828static int
829get_displacement (buffer, aoffsetp)
830 char *buffer;
831 int *aoffsetp;
832{
833 int Ivalue;
834 short Ivalue2;
835
836 Ivalue = bit_extract (buffer, *aoffsetp, 8);
837 switch (Ivalue & 0xc0)
838 {
839 case 0x00:
840 case 0x40:
841 Ivalue = sign_extend (Ivalue, 7);
842 *aoffsetp += 8;
843 break;
844 case 0x80:
845 Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
fc05c67f 846 flip_bytes ((char *) & Ivalue2, 2);
252b5132
RH
847 Ivalue = sign_extend (Ivalue2, 14);
848 *aoffsetp += 16;
849 break;
850 case 0xc0:
851 Ivalue = bit_extract (buffer, *aoffsetp, 32);
fc05c67f 852 flip_bytes ((char *) & Ivalue, 4);
252b5132
RH
853 Ivalue = sign_extend (Ivalue, 30);
854 *aoffsetp += 32;
855 break;
856 }
857 return Ivalue;
858}
859\f
860
861#if 1 /* a version that should work on ns32k f's&d's on any machine */
862static int
863invalid_float (p, len)
864 register char *p;
865 register int len;
866{
867 register int val;
868
869 if ( len == 4 )
870 val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff
871 || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 &&
872 bit_extract_simple(p, 0, 23)/*mantisa*/ != 0));
873 else if ( len == 8 )
874 val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff
875 || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0
876 && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0
877 || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0)));
878 else
879 val = 1;
880 return (val);
881}
882#else
883
884/* assumes the bytes have been swapped to local order */
885typedef union { double d;
886 float f;
887 struct { unsigned m:23, e:8, :1;} sf;
888 struct { unsigned lm; unsigned m:20, e:11, :1;} sd;
889 } float_type_u;
890
891static int
892invalid_float (p, len)
893 register float_type_u *p;
894 register int len;
895{
896 register int val;
897 if ( len == sizeof (float) )
898 val = (p->sf.e == 0xff
899 || (p->sf.e == 0 && p->sf.m != 0));
900 else if ( len == sizeof (double) )
901 val = (p->sd.e == 0x7ff
902 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0)));
903 else
904 val = 1;
905 return (val);
906}
907#endif
This page took 0.251431 seconds and 4 git commands to generate.