1 /* Print National Semiconductor 32000 instructions.
2 Copyright (c) 1986, 88, 91, 92, 94, 95, 1998 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #if !defined(const) && !defined(__STDC__)
27 #include "opcode/ns32k.h"
30 static disassemble_info
*dis_info
;
33 * Hacks to get it to compile <= READ THESE AS FIXES NEEDED
35 #define INVALID_FLOAT(val, size) invalid_float((char *)val, size)
37 static int print_insn_arg
38 PARAMS ((int, int, int *, char *, bfd_vma
, char *, int));
39 static int get_displacement
PARAMS ((char *, int *));
40 static int invalid_float
PARAMS ((char *, int));
42 static long read_memory_integer(addr
, nr
)
48 for (val
= 0, i
= nr
- 1; i
>= 0; i
--) {
50 val
|= (0xff & *(addr
+ i
));
55 /* 32000 instructions are never longer than this. */
63 /* Points to first byte not fetched. */
64 bfd_byte
*max_fetched
;
65 bfd_byte the_buffer
[MAXLEN
];
71 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
72 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
74 #define FETCH_DATA(info, addr) \
75 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
76 ? 1 : fetch_data ((info), (addr)))
79 fetch_data (info
, addr
)
80 struct disassemble_info
*info
;
84 struct private *priv
= (struct private *)info
->private_data
;
85 bfd_vma start
= priv
->insn_start
+ (priv
->max_fetched
- priv
->the_buffer
);
87 status
= (*info
->read_memory_func
) (start
,
89 addr
- priv
->max_fetched
,
93 (*info
->memory_error_func
) (status
, start
, info
);
94 longjmp (priv
->bailout
, 1);
97 priv
->max_fetched
= addr
;
100 /* Number of elements in the opcode table. */
101 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
103 #define NEXT_IS_ADDR '|'
106 struct ns32k_option
{
107 char *pattern
; /* the option itself */
108 unsigned long value
; /* binary value of the option */
109 unsigned long match
; /* these bits must match */
113 static const struct ns32k_option opt_u
[]= /* restore, exit */
115 { "r0", 0x80, 0x80 },
116 { "r1", 0x40, 0x40 },
117 { "r2", 0x20, 0x20 },
118 { "r3", 0x10, 0x10 },
119 { "r4", 0x08, 0x08 },
120 { "r5", 0x04, 0x04 },
121 { "r6", 0x02, 0x02 },
122 { "r7", 0x01, 0x01 },
126 static const struct ns32k_option opt_U
[]= /* save, enter */
128 { "r0", 0x01, 0x01 },
129 { "r1", 0x02, 0x02 },
130 { "r2", 0x04, 0x04 },
131 { "r3", 0x08, 0x08 },
132 { "r4", 0x10, 0x10 },
133 { "r5", 0x20, 0x20 },
134 { "r6", 0x40, 0x40 },
135 { "r7", 0x80, 0x80 },
139 static const struct ns32k_option opt_O
[]= /* setcfg */
148 static const struct ns32k_option opt_C
[]= /* cinv */
156 static const struct ns32k_option opt_S
[]= /* string inst */
164 static const struct ns32k_option list_P532
[]= /* lpr spr */
177 { "intbase", 0xe, 0xf },
182 static const struct ns32k_option list_M532
[]= /* lmr smr */
186 { "tear", 0xb, 0xf },
187 { "ptb0", 0xc, 0xf },
188 { "ptb1", 0xd, 0xf },
189 { "ivar0", 0xe, 0xf },
190 { "ivar1", 0xf, 0xf },
194 static const struct ns32k_option list_P032
[]= /* lpr spr */
196 { "upsr", 0x0, 0xf },
201 { "intbase", 0xe, 0xf },
206 static const struct ns32k_option list_M032
[]= /* lmr smr */
208 { "bpr0", 0x0, 0xf },
209 { "bpr1", 0x1, 0xf },
214 { "bcnt", 0xb, 0xf },
215 { "ptb0", 0xc, 0xf },
216 { "ptb1", 0xd, 0xf },
223 * figure out which options are present
226 optlist(options
, optionP
, result
)
228 const struct ns32k_option
*optionP
;
232 sprintf(result
, "[]");
235 sprintf(result
, "[");
237 for (; (options
!= 0) && optionP
->pattern
; optionP
++) {
238 if ((options
& optionP
->match
) == optionP
->value
) {
239 /* we found a match, update result and options */
240 strcat(result
, optionP
->pattern
);
241 options
&= ~optionP
->value
;
242 if (options
!= 0) /* more options to come */
247 strcat(result
, "undefined");
253 list_search (reg_value
, optionP
, result
)
255 const struct ns32k_option
*optionP
;
258 for (; optionP
->pattern
; optionP
++) {
259 if ((reg_value
& optionP
->match
) == optionP
->value
) {
260 sprintf(result
, "%s", optionP
->pattern
);
264 sprintf(result
, "undefined");
268 * extract "count" bits starting "offset" bits
273 bit_extract (buffer
, offset
, count
)
281 buffer
+= offset
>> 3;
287 FETCH_DATA(dis_info
, buffer
+ 1);
288 if ((*buffer
& (1 << offset
)))
300 /* Like bit extract but the buffer is valid and doen't need to be
304 bit_extract_simple (buffer
, offset
, count
)
313 buffer
+= offset
>> 3;
319 if ((*buffer
& (1 << offset
)))
332 bit_copy (buffer
, offset
, count
, to
)
338 for(; count
> 8; count
-= 8, to
++, offset
+= 8)
339 *to
= bit_extract (buffer
, offset
, 8);
340 *to
= bit_extract (buffer
, offset
, count
);
345 sign_extend (value
, bits
)
348 value
= value
& ((1 << bits
) - 1);
349 return (value
& (1 << (bits
-1))
350 ? value
| (~((1 << bits
) - 1))
355 flip_bytes (ptr
, count
)
364 ptr
[0] = ptr
[count
-1];
371 /* Given a character C, does it represent a general addressing mode? */
373 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
374 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
376 /* Adressing modes. */
377 #define Adrmod_index_byte 0x1c
378 #define Adrmod_index_word 0x1d
379 #define Adrmod_index_doubleword 0x1e
380 #define Adrmod_index_quadword 0x1f
382 /* Is MODE an indexed addressing mode? */
383 #define Adrmod_is_index(mode) \
384 (mode == Adrmod_index_byte \
385 || mode == Adrmod_index_word \
386 || mode == Adrmod_index_doubleword \
387 || mode == Adrmod_index_quadword)
390 /* Print the 32000 instruction at address MEMADDR in debugged memory,
391 on STREAM. Returns length of the instruction, in bytes. */
394 print_insn_ns32k (memaddr
, info
)
396 disassemble_info
*info
;
398 register unsigned int i
;
400 unsigned short first_word
;
401 int ioffset
; /* bits into instruction */
402 int aoffset
; /* bits into arguments */
403 char arg_bufs
[MAX_ARGS
+1][ARG_LEN
];
407 bfd_byte
*buffer
= priv
.the_buffer
;
410 info
->private_data
= (PTR
) &priv
;
411 priv
.max_fetched
= priv
.the_buffer
;
412 priv
.insn_start
= memaddr
;
413 if (setjmp (priv
.bailout
) != 0)
417 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
418 * us over the end of accessible data unnecessarilly
420 FETCH_DATA(info
, buffer
+ 1);
421 for (i
= 0; i
< NOPCODES
; i
++)
422 if (ns32k_opcodes
[i
].opcode_id_size
<= 8
424 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
425 == ns32k_opcodes
[i
].opcode_seed
))
428 /* Maybe it is 9 to 16 bits big */
429 FETCH_DATA(info
, buffer
+ 2);
430 first_word
= read_memory_integer(buffer
, 2);
432 for (i
= 0; i
< NOPCODES
; i
++)
434 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
435 == ns32k_opcodes
[i
].opcode_seed
)
438 /* Handle undefined instructions. */
441 (*dis_info
->fprintf_func
)(dis_info
->stream
, "0%o", buffer
[0]);
446 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%s", ns32k_opcodes
[i
].name
);
448 ioffset
= ns32k_opcodes
[i
].opcode_size
;
449 aoffset
= ns32k_opcodes
[i
].opcode_size
;
450 d
= ns32k_opcodes
[i
].operands
;
454 /* Offset in bits of the first thing beyond each index byte.
455 Element 0 is for operand A and element 1 is for operand B.
456 The rest are irrelevant, but we put them here so we don't
457 index outside the array. */
458 int index_offset
[MAX_ARGS
];
460 /* 0 for operand A, 1 for operand B, greater for other args. */
463 (*dis_info
->fprintf_func
)(dis_info
->stream
, "\t");
467 /* First we have to find and keep track of the index bytes,
468 if we are using scaled indexed addressing mode, since the index
469 bytes occur right after the basic instruction, not as part
470 of the addressing extension. */
473 int addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
475 if (Adrmod_is_index (addr_mode
))
478 index_offset
[0] = aoffset
;
481 if (d
[2] && Is_gen(d
[3]))
483 int addr_mode
= bit_extract (buffer
, ioffset
- 10, 5);
485 if (Adrmod_is_index (addr_mode
))
488 index_offset
[1] = aoffset
;
496 if (argnum
> maxarg
&& argnum
< MAX_ARGS
)
498 ioffset
= print_insn_arg (*d
, ioffset
, &aoffset
, buffer
,
499 memaddr
, arg_bufs
[argnum
],
500 index_offset
[whicharg
]);
504 for (argnum
= 0; argnum
<= maxarg
; argnum
++)
508 for (ch
= arg_bufs
[argnum
]; *ch
;)
510 if (*ch
== NEXT_IS_ADDR
)
513 addr
= bfd_scan_vma (ch
, NULL
, 16);
514 (*dis_info
->print_address_func
) (addr
, dis_info
);
515 while (*ch
&& *ch
!= NEXT_IS_ADDR
)
521 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%c", *ch
++);
524 (*dis_info
->fprintf_func
)(dis_info
->stream
, ", ");
530 /* Print an instruction operand of category given by d. IOFFSET is
531 the bit position below which small (<1 byte) parts of the operand can
532 be found (usually in the basic instruction, but for indexed
533 addressing it can be in the index byte). AOFFSETP is a pointer to the
534 bit position of the addressing extension. BUFFER contains the
535 instruction. ADDR is where BUFFER was read from. Put the disassembled
536 version of the operand in RESULT. INDEX_OFFSET is the bit position
537 of the index byte (it contains garbage if this operand is not a
538 general operand using scaled indexed addressing mode). */
541 print_insn_arg (d
, ioffset
, aoffsetp
, buffer
, addr
, result
, index_offset
)
543 int ioffset
, *aoffsetp
;
560 /* a "gen" operand but 5 bits from the end of instruction */
570 addr_mode
= bit_extract (buffer
, ioffset
-5, 5);
574 case 0x0: case 0x1: case 0x2: case 0x3:
575 case 0x4: case 0x5: case 0x6: case 0x7:
576 /* register mode R0 -- R7 */
582 sprintf (result
, "f%d", addr_mode
);
585 sprintf (result
, "r%d", addr_mode
);
588 case 0x8: case 0x9: case 0xa: case 0xb:
589 case 0xc: case 0xd: case 0xe: case 0xf:
590 /* Register relative disp(R0 -- R7) */
591 disp1
= get_displacement (buffer
, aoffsetp
);
592 sprintf (result
, "%d(r%d)", disp1
, addr_mode
& 7);
597 /* Memory relative disp2(disp1(FP, SP, SB)) */
598 disp1
= get_displacement (buffer
, aoffsetp
);
599 disp2
= get_displacement (buffer
, aoffsetp
);
600 sprintf (result
, "%d(%d(%s))", disp2
, disp1
,
601 addr_mode
==0x10?"fp":addr_mode
==0x11?"sp":"sb");
605 sprintf (result
, "reserved");
611 case 'I': case 'Z': case 'A':
612 /* I and Z are output operands and can`t be immediate
613 * A is an address and we can`t have the address of
614 * an immediate either. We don't know how much to increase
615 * aoffsetp by since whatever generated this is broken
618 sprintf (result
, _("$<undefined>"));
621 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
622 Ivalue
= sign_extend (Ivalue
, 8);
624 sprintf (result
, "$%d", Ivalue
);
627 Ivalue
= bit_extract (buffer
, *aoffsetp
, 16);
628 flip_bytes (&Ivalue
, 2);
630 Ivalue
= sign_extend (Ivalue
, 16);
631 sprintf (result
, "$%d", Ivalue
);
634 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
635 flip_bytes (&Ivalue
, 4);
637 sprintf (result
, "$%d", Ivalue
);
640 bit_copy (buffer
, *aoffsetp
, 32, (char *) &Fvalue
);
641 flip_bytes (&Fvalue
, 4);
643 if (INVALID_FLOAT (&Fvalue
, 4))
644 sprintf (result
, "<<invalid float 0x%.8x>>", *(int *) &Fvalue
);
645 else /* assume host has ieee float */
646 sprintf (result
, "$%g", Fvalue
);
649 bit_copy (buffer
, *aoffsetp
, 64, (char *) &Lvalue
);
650 flip_bytes (&Lvalue
, 8);
652 if (INVALID_FLOAT (&Lvalue
, 8))
653 sprintf (result
, "<<invalid long 0x%.8x%.8x>>",
654 *(((int *) &Lvalue
) + 1), *(int *) &Lvalue
);
655 else /* assume host has ieee float */
656 sprintf (result
, "$%g", Lvalue
);
662 disp1
= get_displacement (buffer
, aoffsetp
);
663 sprintf (result
, "@|%d|", disp1
);
666 /* External EXT(disp1) + disp2 (Mod table stuff) */
667 disp1
= get_displacement (buffer
, aoffsetp
);
668 disp2
= get_displacement (buffer
, aoffsetp
);
669 sprintf (result
, "EXT(%d) + %d", disp1
, disp2
);
672 /* Top of stack tos */
673 sprintf (result
, "tos");
676 /* Memory space disp(FP) */
677 disp1
= get_displacement (buffer
, aoffsetp
);
678 sprintf (result
, "%d(fp)", disp1
);
681 /* Memory space disp(SP) */
682 disp1
= get_displacement (buffer
, aoffsetp
);
683 sprintf (result
, "%d(sp)", disp1
);
686 /* Memory space disp(SB) */
687 disp1
= get_displacement (buffer
, aoffsetp
);
688 sprintf (result
, "%d(sb)", disp1
);
691 /* Memory space disp(PC) */
692 disp1
= get_displacement (buffer
, aoffsetp
);
693 *result
++ = NEXT_IS_ADDR
;
694 sprintf_vma (result
, addr
+ disp1
);
695 result
+= strlen (result
);
696 *result
++ = NEXT_IS_ADDR
;
703 /* Scaled index basemode[R0 -- R7:B,W,D,Q] */
704 index
= bit_extract (buffer
, index_offset
- 8, 3);
705 print_insn_arg (d
, index_offset
, aoffsetp
, buffer
, addr
,
708 static const char *ind
= "bwdq";
711 off
= result
+ strlen (result
);
712 sprintf (off
, "[r%d:%c]", index
,
720 Ivalue
= bit_extract (buffer
, ioffset
-4, 4);
721 Ivalue
= sign_extend (Ivalue
, 4);
722 sprintf (result
, "%d", Ivalue
);
726 Ivalue
= bit_extract (buffer
, ioffset
-3, 3);
727 sprintf (result
, "r%d", Ivalue
&7);
731 sprintf (result
, "%d", get_displacement (buffer
, aoffsetp
));
734 Ivalue
= get_displacement (buffer
, aoffsetp
);
736 * Warning!! HACK ALERT!
737 * Operand type 'b' is only used by the cmp{b,w,d} and
738 * movm{b,w,d} instructions; we need to know whether
739 * it's a `b' or `w' or `d' instruction; and for both
740 * cmpm and movm it's stored at the same place so we
741 * just grab two bits of the opcode and look at it...
744 size
= bit_extract(buffer
, ioffset
-6, 2);
745 if (size
== 0) /* 00 => b */
747 else if (size
== 1) /* 01 => w */
750 size
= 4; /* 11 => d */
752 sprintf (result
, "%d", (Ivalue
/ size
) + 1);
755 *result
++ = NEXT_IS_ADDR
;
756 sprintf_vma (result
, addr
+ get_displacement (buffer
, aoffsetp
));
757 result
+= strlen (result
);
758 *result
++ = NEXT_IS_ADDR
;
762 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
764 sprintf (result
, "0x%x", Ivalue
);
767 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
768 optlist(Ivalue
, opt_u
, result
);
772 Ivalue
= bit_extract(buffer
, *aoffsetp
, 8);
773 optlist(Ivalue
, opt_U
, result
);
777 Ivalue
= bit_extract(buffer
, ioffset
-9, 9);
778 optlist(Ivalue
, opt_O
, result
);
782 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
783 optlist(Ivalue
, opt_C
, result
);
787 Ivalue
= bit_extract(buffer
, ioffset
- 8, 8);
788 optlist(Ivalue
, opt_S
, result
);
792 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
793 list_search(Ivalue
, 0 ? list_M032
: list_M532
, result
);
797 Ivalue
= bit_extract(buffer
, ioffset
-4, 4);
798 list_search(Ivalue
, 0 ? list_P032
: list_P532
, result
);
802 Ivalue
= bit_extract(buffer
, *aoffsetp
, 3);
803 sprintf(result
, "%d", Ivalue
);
807 Ivalue
= bit_extract(buffer
, *aoffsetp
, 5);
808 sprintf(result
, "%d", Ivalue
+ 1);
816 get_displacement (buffer
, aoffsetp
)
823 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
824 switch (Ivalue
& 0xc0)
828 Ivalue
= sign_extend (Ivalue
, 7);
832 Ivalue2
= bit_extract (buffer
, *aoffsetp
, 16);
833 flip_bytes (&Ivalue2
, 2);
834 Ivalue
= sign_extend (Ivalue2
, 14);
838 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
839 flip_bytes (&Ivalue
, 4);
840 Ivalue
= sign_extend (Ivalue
, 30);
848 #if 1 /* a version that should work on ns32k f's&d's on any machine */
850 invalid_float (p
, len
)
857 val
= (bit_extract_simple(p
, 23, 8)/*exponent*/ == 0xff
858 || (bit_extract_simple(p
, 23, 8)/*exponent*/ == 0 &&
859 bit_extract_simple(p
, 0, 23)/*mantisa*/ != 0));
861 val
= (bit_extract_simple(p
, 52, 11)/*exponent*/ == 0x7ff
862 || (bit_extract_simple(p
, 52, 11)/*exponent*/ == 0
863 && (bit_extract_simple(p
, 0, 32)/*low mantisa*/ != 0
864 || bit_extract_simple(p
, 32, 20)/*high mantisa*/ != 0)));
871 /* assumes the bytes have been swapped to local order */
872 typedef union { double d
;
874 struct { unsigned m
:23, e
:8, :1;} sf
;
875 struct { unsigned lm
; unsigned m
:20, e
:11, :1;} sd
;
879 invalid_float (p
, len
)
880 register float_type_u
*p
;
884 if ( len
== sizeof (float) )
885 val
= (p
->sf
.e
== 0xff
886 || (p
->sf
.e
== 0 && p
->sf
.m
!= 0));
887 else if ( len
== sizeof (double) )
888 val
= (p
->sd
.e
== 0x7ff
889 || (p
->sd
.e
== 0 && (p
->sd
.m
!= 0 || p
->sd
.lm
!= 0)));
This page took 0.04744 seconds and 4 git commands to generate.