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. */
24 #if !defined(const) && !defined(__STDC__)
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
)
43 for (val
= 0, i
= nr
- 1; i
>= 0; i
--) {
45 val
|= (0xff & *(addr
+ i
));
50 /* 32000 instructions are never longer than this. */
58 /* Points to first byte not fetched. */
59 bfd_byte
*max_fetched
;
60 bfd_byte the_buffer
[MAXLEN
];
66 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
67 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
69 #define FETCH_DATA(info, addr) \
70 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
71 ? 1 : fetch_data ((info), (addr)))
74 fetch_data (info
, addr
)
75 struct disassemble_info
*info
;
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
,
84 addr
- priv
->max_fetched
,
88 (*info
->memory_error_func
) (status
, start
, info
);
89 longjmp (priv
->bailout
, 1);
92 priv
->max_fetched
= addr
;
95 /* Number of elements in the opcode table. */
96 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
98 #define NEXT_IS_ADDR '|'
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 },
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 },
134 static struct option opt_O
[]= /* setcfg */
143 static struct option opt_C
[]= /* cinv */
151 static struct option opt_S
[]= /* string inst */
159 static struct option list_P532
[]= /* lpr spr */
172 { "intbase", 0xe, 0xf },
177 static struct option list_M532
[]= /* lmr smr */
181 { "tear", 0xb, 0xf },
182 { "ptb0", 0xc, 0xf },
183 { "ptb1", 0xd, 0xf },
184 { "ivar0", 0xe, 0xf },
185 { "ivar1", 0xf, 0xf },
189 static struct option list_P032
[]= /* lpr spr */
191 { "upsr", 0x0, 0xf },
196 { "intbase", 0xe, 0xf },
201 static struct option list_M032
[]= /* lmr smr */
203 { "bpr0", 0x0, 0xf },
204 { "bpr1", 0x1, 0xf },
209 { "bcnt", 0xb, 0xf },
210 { "ptb0", 0xc, 0xf },
211 { "ptb1", 0xd, 0xf },
218 * figure out which options are present
221 optlist(options
, optionP
, result
)
223 struct option
*optionP
;
227 sprintf(result
, "[]");
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 */
242 strcat(result
, "undefined");
247 static list_search(reg_value
, optionP
, result
)
249 struct option
*optionP
;
252 for (; optionP
->pattern
; optionP
++) {
253 if ((reg_value
& optionP
->match
) == optionP
->value
) {
254 sprintf(result
, "%s", optionP
->pattern
);
258 sprintf(result
, "undefined");
262 * extract "count" bits starting "offset" bits
267 bit_extract (buffer
, offset
, count
)
276 buffer
+= offset
>> 3;
282 FETCH_DATA(dis_info
, buffer
+ 1);
283 if ((*buffer
& (1 << offset
)))
296 bit_copy (buffer
, offset
, count
, 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
)
311 value
= value
& ((1 << bits
) - 1);
312 return (value
& (1 << (bits
-1))
313 ? value
| (~((1 << bits
) - 1))
317 static flip_bytes (ptr
, count
)
326 ptr
[0] = ptr
[count
-1];
333 /* Given a character C, does it represent a general addressing mode? */
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
)
358 disassemble_info
*info
;
361 register unsigned char *p
;
363 unsigned short first_word
;
365 int ioffset
; /* bits into instruction */
366 int aoffset
; /* bits into arguments */
367 char arg_bufs
[MAX_ARGS
+1][ARG_LEN
];
371 bfd_byte
*buffer
= priv
.the_buffer
;
374 info
->private_data
= (PTR
) &priv
;
375 priv
.max_fetched
= priv
.the_buffer
;
376 priv
.insn_start
= memaddr
;
377 if (setjmp (priv
.bailout
) != 0)
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
))
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
)
400 /* Handle undefined instructions. */
403 (*dis_info
->fprintf_func
)(dis_info
->stream
, "0%o", buffer
[0]);
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
;
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. */
425 (*dis_info
->fprintf_func
)(dis_info
->stream
, "\t");
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. */
435 int addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
437 if (Adrmod_is_index (addr_mode
))
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
))
450 index_offset
[1] = aoffset
;
458 if (argnum
> maxarg
&& argnum
< MAX_ARGS
)
460 ioffset
= print_insn_arg (*d
, ioffset
, &aoffset
, buffer
,
461 memaddr
, arg_bufs
[argnum
],
462 index_offset
[whicharg
]);
466 for (argnum
= 0; argnum
<= maxarg
; argnum
++)
470 for (ch
= arg_bufs
[argnum
]; *ch
;)
472 if (*ch
== NEXT_IS_ADDR
)
476 (*dis_info
->print_address_func
) (addr
, dis_info
);
477 while (*ch
&& *ch
!= NEXT_IS_ADDR
)
483 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%c", *ch
++);
486 (*dis_info
->fprintf_func
)(dis_info
->stream
, ", ");
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
)
504 int ioffset
, *aoffsetp
;
521 /* a "gen" operand but 5 bits from the end of instruction */
531 addr_mode
= bit_extract (buffer
, ioffset
-5, 5);
535 case 0x0: case 0x1: case 0x2: case 0x3:
536 case 0x4: case 0x5: case 0x6: case 0x7:
537 /* register mode R0 -- R7 */
543 sprintf (result
, "f%d", addr_mode
);
546 sprintf (result
, "r%d", addr_mode
);
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);
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");
566 sprintf (result
, "reserved");
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
579 sprintf (result
, "$<undefined>");
582 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
583 Ivalue
= sign_extend (Ivalue
, 8);
585 sprintf (result
, "$%d", Ivalue
);
588 Ivalue
= bit_extract (buffer
, *aoffsetp
, 16);
589 flip_bytes (&Ivalue
, 2);
591 Ivalue
= sign_extend (Ivalue
, 16);
592 sprintf (result
, "$%d", Ivalue
);
595 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
596 flip_bytes (&Ivalue
, 4);
598 sprintf (result
, "$%d", Ivalue
);
601 bit_copy (buffer
, *aoffsetp
, 32, (char *) &Fvalue
);
602 flip_bytes (&Fvalue
, 4);
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
);
610 bit_copy (buffer
, *aoffsetp
, 64, (char *) &Lvalue
);
611 flip_bytes (&Lvalue
, 8);
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
);
623 disp1
= get_displacement (buffer
, aoffsetp
);
624 sprintf (result
, "@|%d|", disp1
);
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
);
633 /* Top of stack tos */
634 sprintf (result
, "tos");
637 /* Memory space disp(FP) */
638 disp1
= get_displacement (buffer
, aoffsetp
);
639 sprintf (result
, "%d(fp)", disp1
);
642 /* Memory space disp(SP) */
643 disp1
= get_displacement (buffer
, aoffsetp
);
644 sprintf (result
, "%d(sp)", disp1
);
647 /* Memory space disp(SB) */
648 disp1
= get_displacement (buffer
, aoffsetp
);
649 sprintf (result
, "%d(sb)", disp1
);
652 /* Memory space disp(PC) */
653 disp1
= get_displacement (buffer
, aoffsetp
);
654 sprintf (result
, "|%d|", addr
+ disp1
);
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
,
665 static char *ind
[] = {"b", "w", "d", "q"};
668 off
= result
+ strlen (result
);
669 sprintf (off
, "[r%d:%s]", index
,
677 Ivalue
= bit_extract (buffer
, ioffset
-4, 4);
678 Ivalue
= sign_extend (Ivalue
, 4);
679 sprintf (result
, "%d", Ivalue
);
683 Ivalue
= bit_extract (buffer
, ioffset
-3, 3);
684 sprintf (result
, "r%d", Ivalue
&7);
688 sprintf (result
, "%d", get_displacement (buffer
, aoffsetp
));
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 */
704 else if (size
== 1) /* 01 => w */
707 size
= 4; /* 11 => d */
709 sprintf (result
, "%d", (Ivalue
/ size
) + 1);
712 sprintf (result
, "%c%d%c", NEXT_IS_ADDR
,
713 addr
+ get_displacement (buffer
, aoffsetp
),
717 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
719 sprintf (result
, "0x%x", Ivalue
);
722 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
723 optlist(Ivalue
, opt_u
, result
);
727 Ivalue
= bit_extract(buffer
, *aoffsetp
, 8);
728 optlist(Ivalue
, opt_U
, result
);
732 Ivalue
= bit_extract(buffer
, ioffset
-9, 9);
733 optlist(Ivalue
, opt_O
, result
);
737 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
738 optlist(Ivalue
, opt_C
, result
);
742 Ivalue
= bit_extract(buffer
, ioffset
- 8, 8);
743 optlist(Ivalue
, opt_S
, result
);
747 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
748 list_search(Ivalue
, 0 ? list_M032
: list_M532
, result
);
752 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
753 list_search(Ivalue
, 0 ? list_P032
: list_P532
, result
);
757 Ivalue
= bit_extract(buffer
, *aoffsetp
, 3);
758 sprintf(result
, "%d", Ivalue
);
762 Ivalue
= bit_extract(buffer
, *aoffsetp
, 5);
763 sprintf(result
, "%d", Ivalue
+ 1);
770 get_displacement (buffer
, aoffsetp
)
777 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
778 switch (Ivalue
& 0xc0)
782 Ivalue
= sign_extend (Ivalue
, 7);
786 Ivalue2
= bit_extract (buffer
, *aoffsetp
, 16);
787 flip_bytes (&Ivalue2
, 2);
788 Ivalue
= sign_extend (Ivalue2
, 14);
792 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
793 flip_bytes (&Ivalue
, 4);
794 Ivalue
= sign_extend (Ivalue
, 30);
802 #if 1 /* a version that should work on ns32k f's&d's on any machine */
803 int invalid_float(p
, len
)
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));
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)));
824 /* assumes the bytes have been swapped to local order */
825 typedef union { double d
;
827 struct { unsigned m
:23, e
:8, :1;} sf
;
828 struct { unsigned lm
; unsigned m
:20, e
:11, :1;} sd
;
831 int invalid_float(p
, len
)
832 register float_type_u
*p
;
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)));
This page took 0.047159 seconds and 4 git commands to generate.