1 /* Print National Semiconductor 32000 instructions.
2 Copyright 1986, 1988, 1991, 1992, 1994, 1998
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. */
25 #if !defined(const) && !defined(__STDC__)
28 #include "opcode/ns32k.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));
43 static long read_memory_integer(addr
, nr
)
49 for (val
= 0, i
= nr
- 1; i
>= 0; i
--) {
51 val
|= (0xff & *(addr
+ i
));
56 /* 32000 instructions are never longer than this. */
64 /* Points to first byte not fetched. */
65 bfd_byte
*max_fetched
;
66 bfd_byte the_buffer
[MAXLEN
];
72 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
73 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
75 #define FETCH_DATA(info, addr) \
76 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
77 ? 1 : fetch_data ((info), (addr)))
80 fetch_data (info
, addr
)
81 struct disassemble_info
*info
;
85 struct private *priv
= (struct private *)info
->private_data
;
86 bfd_vma start
= priv
->insn_start
+ (priv
->max_fetched
- priv
->the_buffer
);
88 status
= (*info
->read_memory_func
) (start
,
90 addr
- priv
->max_fetched
,
94 (*info
->memory_error_func
) (status
, start
, info
);
95 longjmp (priv
->bailout
, 1);
98 priv
->max_fetched
= addr
;
101 /* Number of elements in the opcode table. */
102 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
104 #define NEXT_IS_ADDR '|'
107 struct ns32k_option
{
108 char *pattern
; /* the option itself */
109 unsigned long value
; /* binary value of the option */
110 unsigned long match
; /* these bits must match */
114 static const struct ns32k_option opt_u
[]= /* restore, exit */
116 { "r0", 0x80, 0x80 },
117 { "r1", 0x40, 0x40 },
118 { "r2", 0x20, 0x20 },
119 { "r3", 0x10, 0x10 },
120 { "r4", 0x08, 0x08 },
121 { "r5", 0x04, 0x04 },
122 { "r6", 0x02, 0x02 },
123 { "r7", 0x01, 0x01 },
127 static const struct ns32k_option opt_U
[]= /* save, enter */
129 { "r0", 0x01, 0x01 },
130 { "r1", 0x02, 0x02 },
131 { "r2", 0x04, 0x04 },
132 { "r3", 0x08, 0x08 },
133 { "r4", 0x10, 0x10 },
134 { "r5", 0x20, 0x20 },
135 { "r6", 0x40, 0x40 },
136 { "r7", 0x80, 0x80 },
140 static const struct ns32k_option opt_O
[]= /* setcfg */
149 static const struct ns32k_option opt_C
[]= /* cinv */
157 static const struct ns32k_option opt_S
[]= /* string inst */
165 static const struct ns32k_option list_P532
[]= /* lpr spr */
178 { "intbase", 0xe, 0xf },
183 static const struct ns32k_option list_M532
[]= /* lmr smr */
187 { "tear", 0xb, 0xf },
188 { "ptb0", 0xc, 0xf },
189 { "ptb1", 0xd, 0xf },
190 { "ivar0", 0xe, 0xf },
191 { "ivar1", 0xf, 0xf },
195 static const struct ns32k_option list_P032
[]= /* lpr spr */
197 { "upsr", 0x0, 0xf },
202 { "intbase", 0xe, 0xf },
207 static const struct ns32k_option list_M032
[]= /* lmr smr */
209 { "bpr0", 0x0, 0xf },
210 { "bpr1", 0x1, 0xf },
215 { "bcnt", 0xb, 0xf },
216 { "ptb0", 0xc, 0xf },
217 { "ptb1", 0xd, 0xf },
224 * figure out which options are present
227 optlist(options
, optionP
, result
)
229 const struct ns32k_option
*optionP
;
233 sprintf(result
, "[]");
236 sprintf(result
, "[");
238 for (; (options
!= 0) && optionP
->pattern
; optionP
++) {
239 if ((options
& optionP
->match
) == optionP
->value
) {
240 /* we found a match, update result and options */
241 strcat(result
, optionP
->pattern
);
242 options
&= ~optionP
->value
;
243 if (options
!= 0) /* more options to come */
248 strcat(result
, "undefined");
254 list_search (reg_value
, optionP
, result
)
256 const struct ns32k_option
*optionP
;
259 for (; optionP
->pattern
; optionP
++) {
260 if ((reg_value
& optionP
->match
) == optionP
->value
) {
261 sprintf(result
, "%s", optionP
->pattern
);
265 sprintf(result
, "undefined");
269 * extract "count" bits starting "offset" bits
274 bit_extract (buffer
, offset
, count
)
282 buffer
+= offset
>> 3;
288 FETCH_DATA(dis_info
, buffer
+ 1);
289 if ((*buffer
& (1 << offset
)))
301 /* Like bit extract but the buffer is valid and doen't need to be
305 bit_extract_simple (buffer
, offset
, count
)
314 buffer
+= offset
>> 3;
320 if ((*buffer
& (1 << offset
)))
333 bit_copy (buffer
, offset
, count
, to
)
339 for(; count
> 8; count
-= 8, to
++, offset
+= 8)
340 *to
= bit_extract (buffer
, offset
, 8);
341 *to
= bit_extract (buffer
, offset
, count
);
346 sign_extend (value
, bits
)
349 value
= value
& ((1 << bits
) - 1);
350 return (value
& (1 << (bits
-1))
351 ? value
| (~((1 << bits
) - 1))
356 flip_bytes (ptr
, count
)
365 ptr
[0] = ptr
[count
-1];
372 /* Given a character C, does it represent a general addressing mode? */
374 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
375 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
377 /* Adressing modes. */
378 #define Adrmod_index_byte 0x1c
379 #define Adrmod_index_word 0x1d
380 #define Adrmod_index_doubleword 0x1e
381 #define Adrmod_index_quadword 0x1f
383 /* Is MODE an indexed addressing mode? */
384 #define Adrmod_is_index(mode) \
385 (mode == Adrmod_index_byte \
386 || mode == Adrmod_index_word \
387 || mode == Adrmod_index_doubleword \
388 || mode == Adrmod_index_quadword)
391 /* Print the 32000 instruction at address MEMADDR in debugged memory,
392 on STREAM. Returns length of the instruction, in bytes. */
395 print_insn_ns32k (memaddr
, info
)
397 disassemble_info
*info
;
399 register unsigned int i
;
401 unsigned short first_word
;
402 int ioffset
; /* bits into instruction */
403 int aoffset
; /* bits into arguments */
404 char arg_bufs
[MAX_ARGS
+1][ARG_LEN
];
408 bfd_byte
*buffer
= priv
.the_buffer
;
411 info
->private_data
= (PTR
) &priv
;
412 priv
.max_fetched
= priv
.the_buffer
;
413 priv
.insn_start
= memaddr
;
414 if (setjmp (priv
.bailout
) != 0)
418 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
419 * us over the end of accessible data unnecessarilly
421 FETCH_DATA(info
, buffer
+ 1);
422 for (i
= 0; i
< NOPCODES
; i
++)
423 if (ns32k_opcodes
[i
].opcode_id_size
<= 8
425 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
426 == ns32k_opcodes
[i
].opcode_seed
))
429 /* Maybe it is 9 to 16 bits big */
430 FETCH_DATA(info
, buffer
+ 2);
431 first_word
= read_memory_integer(buffer
, 2);
433 for (i
= 0; i
< NOPCODES
; i
++)
435 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
436 == ns32k_opcodes
[i
].opcode_seed
)
439 /* Handle undefined instructions. */
442 (*dis_info
->fprintf_func
)(dis_info
->stream
, "0%o", buffer
[0]);
447 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%s", ns32k_opcodes
[i
].name
);
449 ioffset
= ns32k_opcodes
[i
].opcode_size
;
450 aoffset
= ns32k_opcodes
[i
].opcode_size
;
451 d
= ns32k_opcodes
[i
].operands
;
455 /* Offset in bits of the first thing beyond each index byte.
456 Element 0 is for operand A and element 1 is for operand B.
457 The rest are irrelevant, but we put them here so we don't
458 index outside the array. */
459 int index_offset
[MAX_ARGS
];
461 /* 0 for operand A, 1 for operand B, greater for other args. */
464 (*dis_info
->fprintf_func
)(dis_info
->stream
, "\t");
468 /* First we have to find and keep track of the index bytes,
469 if we are using scaled indexed addressing mode, since the index
470 bytes occur right after the basic instruction, not as part
471 of the addressing extension. */
474 int addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
476 if (Adrmod_is_index (addr_mode
))
479 index_offset
[0] = aoffset
;
482 if (d
[2] && Is_gen(d
[3]))
484 int addr_mode
= bit_extract (buffer
, ioffset
- 10, 5);
486 if (Adrmod_is_index (addr_mode
))
489 index_offset
[1] = aoffset
;
497 if (argnum
> maxarg
&& argnum
< MAX_ARGS
)
499 ioffset
= print_insn_arg (*d
, ioffset
, &aoffset
, buffer
,
500 memaddr
, arg_bufs
[argnum
],
501 index_offset
[whicharg
]);
505 for (argnum
= 0; argnum
<= maxarg
; argnum
++)
509 for (ch
= arg_bufs
[argnum
]; *ch
;)
511 if (*ch
== NEXT_IS_ADDR
)
514 addr
= bfd_scan_vma (ch
, NULL
, 16);
515 (*dis_info
->print_address_func
) (addr
, dis_info
);
516 while (*ch
&& *ch
!= NEXT_IS_ADDR
)
522 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%c", *ch
++);
525 (*dis_info
->fprintf_func
)(dis_info
->stream
, ", ");
531 /* Print an instruction operand of category given by d. IOFFSET is
532 the bit position below which small (<1 byte) parts of the operand can
533 be found (usually in the basic instruction, but for indexed
534 addressing it can be in the index byte). AOFFSETP is a pointer to the
535 bit position of the addressing extension. BUFFER contains the
536 instruction. ADDR is where BUFFER was read from. Put the disassembled
537 version of the operand in RESULT. INDEX_OFFSET is the bit position
538 of the index byte (it contains garbage if this operand is not a
539 general operand using scaled indexed addressing mode). */
542 print_insn_arg (d
, ioffset
, aoffsetp
, buffer
, addr
, result
, index_offset
)
544 int ioffset
, *aoffsetp
;
561 /* a "gen" operand but 5 bits from the end of instruction */
571 addr_mode
= bit_extract (buffer
, ioffset
-5, 5);
575 case 0x0: case 0x1: case 0x2: case 0x3:
576 case 0x4: case 0x5: case 0x6: case 0x7:
577 /* register mode R0 -- R7 */
583 sprintf (result
, "f%d", addr_mode
);
586 sprintf (result
, "r%d", addr_mode
);
589 case 0x8: case 0x9: case 0xa: case 0xb:
590 case 0xc: case 0xd: case 0xe: case 0xf:
591 /* Register relative disp(R0 -- R7) */
592 disp1
= get_displacement (buffer
, aoffsetp
);
593 sprintf (result
, "%d(r%d)", disp1
, addr_mode
& 7);
598 /* Memory relative disp2(disp1(FP, SP, SB)) */
599 disp1
= get_displacement (buffer
, aoffsetp
);
600 disp2
= get_displacement (buffer
, aoffsetp
);
601 sprintf (result
, "%d(%d(%s))", disp2
, disp1
,
602 addr_mode
==0x10?"fp":addr_mode
==0x11?"sp":"sb");
606 sprintf (result
, "reserved");
612 case 'I': case 'Z': case 'A':
613 /* I and Z are output operands and can`t be immediate
614 * A is an address and we can`t have the address of
615 * an immediate either. We don't know how much to increase
616 * aoffsetp by since whatever generated this is broken
619 sprintf (result
, _("$<undefined>"));
622 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
623 Ivalue
= sign_extend (Ivalue
, 8);
625 sprintf (result
, "$%d", Ivalue
);
628 Ivalue
= bit_extract (buffer
, *aoffsetp
, 16);
629 flip_bytes (&Ivalue
, 2);
631 Ivalue
= sign_extend (Ivalue
, 16);
632 sprintf (result
, "$%d", Ivalue
);
635 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
636 flip_bytes (&Ivalue
, 4);
638 sprintf (result
, "$%d", Ivalue
);
641 bit_copy (buffer
, *aoffsetp
, 32, (char *) &Fvalue
);
642 flip_bytes (&Fvalue
, 4);
644 if (INVALID_FLOAT (&Fvalue
, 4))
645 sprintf (result
, "<<invalid float 0x%.8x>>", *(int *) &Fvalue
);
646 else /* assume host has ieee float */
647 sprintf (result
, "$%g", Fvalue
);
650 bit_copy (buffer
, *aoffsetp
, 64, (char *) &Lvalue
);
651 flip_bytes (&Lvalue
, 8);
653 if (INVALID_FLOAT (&Lvalue
, 8))
654 sprintf (result
, "<<invalid long 0x%.8x%.8x>>",
655 *(((int *) &Lvalue
) + 1), *(int *) &Lvalue
);
656 else /* assume host has ieee float */
657 sprintf (result
, "$%g", Lvalue
);
663 disp1
= get_displacement (buffer
, aoffsetp
);
664 sprintf (result
, "@|%d|", disp1
);
667 /* External EXT(disp1) + disp2 (Mod table stuff) */
668 disp1
= get_displacement (buffer
, aoffsetp
);
669 disp2
= get_displacement (buffer
, aoffsetp
);
670 sprintf (result
, "EXT(%d) + %d", disp1
, disp2
);
673 /* Top of stack tos */
674 sprintf (result
, "tos");
677 /* Memory space disp(FP) */
678 disp1
= get_displacement (buffer
, aoffsetp
);
679 sprintf (result
, "%d(fp)", disp1
);
682 /* Memory space disp(SP) */
683 disp1
= get_displacement (buffer
, aoffsetp
);
684 sprintf (result
, "%d(sp)", disp1
);
687 /* Memory space disp(SB) */
688 disp1
= get_displacement (buffer
, aoffsetp
);
689 sprintf (result
, "%d(sb)", disp1
);
692 /* Memory space disp(PC) */
693 disp1
= get_displacement (buffer
, aoffsetp
);
694 *result
++ = NEXT_IS_ADDR
;
695 sprintf_vma (result
, addr
+ disp1
);
696 result
+= strlen (result
);
697 *result
++ = NEXT_IS_ADDR
;
704 /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
705 index
= bit_extract (buffer
, index_offset
- 8, 3);
706 print_insn_arg (d
, index_offset
, aoffsetp
, buffer
, addr
,
709 static const char *ind
= "bwdq";
712 off
= result
+ strlen (result
);
713 sprintf (off
, "[r%d:%c]", index
,
721 Ivalue
= bit_extract (buffer
, ioffset
-4, 4);
722 Ivalue
= sign_extend (Ivalue
, 4);
723 sprintf (result
, "%d", Ivalue
);
727 Ivalue
= bit_extract (buffer
, ioffset
-3, 3);
728 sprintf (result
, "r%d", Ivalue
&7);
732 sprintf (result
, "%d", get_displacement (buffer
, aoffsetp
));
735 Ivalue
= get_displacement (buffer
, aoffsetp
);
737 * Warning!! HACK ALERT!
738 * Operand type 'b' is only used by the cmp{b,w,d} and
739 * movm{b,w,d} instructions; we need to know whether
740 * it's a `b' or `w' or `d' instruction; and for both
741 * cmpm and movm it's stored at the same place so we
742 * just grab two bits of the opcode and look at it...
745 size
= bit_extract(buffer
, ioffset
-6, 2);
746 if (size
== 0) /* 00 => b */
748 else if (size
== 1) /* 01 => w */
751 size
= 4; /* 11 => d */
753 sprintf (result
, "%d", (Ivalue
/ size
) + 1);
756 *result
++ = NEXT_IS_ADDR
;
757 sprintf_vma (result
, addr
+ get_displacement (buffer
, aoffsetp
));
758 result
+= strlen (result
);
759 *result
++ = NEXT_IS_ADDR
;
763 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
765 sprintf (result
, "0x%x", Ivalue
);
768 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
769 optlist(Ivalue
, opt_u
, result
);
773 Ivalue
= bit_extract(buffer
, *aoffsetp
, 8);
774 optlist(Ivalue
, opt_U
, result
);
778 Ivalue
= bit_extract(buffer
, ioffset
-9, 9);
779 optlist(Ivalue
, opt_O
, result
);
783 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
784 optlist(Ivalue
, opt_C
, result
);
788 Ivalue
= bit_extract(buffer
, ioffset
- 8, 8);
789 optlist(Ivalue
, opt_S
, result
);
793 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
794 list_search(Ivalue
, 0 ? list_M032
: list_M532
, result
);
798 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
799 list_search(Ivalue
, 0 ? list_P032
: list_P532
, result
);
803 Ivalue
= bit_extract(buffer
, *aoffsetp
, 3);
804 sprintf(result
, "%d", Ivalue
);
808 Ivalue
= bit_extract(buffer
, *aoffsetp
, 5);
809 sprintf(result
, "%d", Ivalue
+ 1);
817 get_displacement (buffer
, aoffsetp
)
824 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
825 switch (Ivalue
& 0xc0)
829 Ivalue
= sign_extend (Ivalue
, 7);
833 Ivalue2
= bit_extract (buffer
, *aoffsetp
, 16);
834 flip_bytes (&Ivalue2
, 2);
835 Ivalue
= sign_extend (Ivalue2
, 14);
839 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
840 flip_bytes (&Ivalue
, 4);
841 Ivalue
= sign_extend (Ivalue
, 30);
849 #if 1 /* a version that should work on ns32k f's&d's on any machine */
851 invalid_float (p
, len
)
858 val
= (bit_extract_simple(p
, 23, 8)/*exponent*/ == 0xff
859 || (bit_extract_simple(p
, 23, 8)/*exponent*/ == 0 &&
860 bit_extract_simple(p
, 0, 23)/*mantisa*/ != 0));
862 val
= (bit_extract_simple(p
, 52, 11)/*exponent*/ == 0x7ff
863 || (bit_extract_simple(p
, 52, 11)/*exponent*/ == 0
864 && (bit_extract_simple(p
, 0, 32)/*low mantisa*/ != 0
865 || bit_extract_simple(p
, 32, 20)/*high mantisa*/ != 0)));
872 /* assumes the bytes have been swapped to local order */
873 typedef union { double d
;
875 struct { unsigned m
:23, e
:8, :1;} sf
;
876 struct { unsigned lm
; unsigned m
:20, e
:11, :1;} sd
;
880 invalid_float (p
, len
)
881 register float_type_u
*p
;
885 if ( len
== sizeof (float) )
886 val
= (p
->sf
.e
== 0xff
887 || (p
->sf
.e
== 0 && p
->sf
.m
!= 0));
888 else if ( len
== sizeof (double) )
889 val
= (p
->sd
.e
== 0x7ff
890 || (p
->sd
.e
== 0 && (p
->sd
.m
!= 0 || p
->sd
.lm
!= 0)));