1 /* Print National Semiconductor 32000 instructions.
2 Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007
3 Free Software Foundation, Inc.
5 This file is part of the GNU opcodes library.
7 This library 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 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 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., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
25 #if !defined(const) && !defined(__STDC__)
28 #include "opcode/ns32k.h"
31 static disassemble_info
*dis_info
;
33 /* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
34 #define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
37 read_memory_integer (unsigned char * addr
, int nr
)
42 for (val
= 0, i
= nr
- 1; i
>= 0; i
--)
45 val
|= (0xff & *(addr
+ i
));
50 /* 32000 instructions are never longer than this. */
57 /* Points to first byte not fetched. */
58 bfd_byte
*max_fetched
;
59 bfd_byte the_buffer
[MAXLEN
];
65 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
66 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
68 #define FETCH_DATA(info, addr) \
69 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
70 ? 1 : fetch_data ((info), (addr)))
73 fetch_data (struct disassemble_info
*info
, bfd_byte
*addr
)
76 struct private *priv
= (struct private *) info
->private_data
;
77 bfd_vma start
= priv
->insn_start
+ (priv
->max_fetched
- priv
->the_buffer
);
79 status
= (*info
->read_memory_func
) (start
,
81 addr
- priv
->max_fetched
,
85 (*info
->memory_error_func
) (status
, start
, info
);
86 longjmp (priv
->bailout
, 1);
89 priv
->max_fetched
= addr
;
93 /* Number of elements in the opcode table. */
94 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
96 #define NEXT_IS_ADDR '|'
101 char *pattern
; /* The option itself. */
102 unsigned long value
; /* Binary value of the option. */
103 unsigned long match
; /* These bits must match. */
107 static const struct ns32k_option opt_u
[]= /* Restore, exit. */
109 { "r0", 0x80, 0x80 },
110 { "r1", 0x40, 0x40 },
111 { "r2", 0x20, 0x20 },
112 { "r3", 0x10, 0x10 },
113 { "r4", 0x08, 0x08 },
114 { "r5", 0x04, 0x04 },
115 { "r6", 0x02, 0x02 },
116 { "r7", 0x01, 0x01 },
120 static const struct ns32k_option opt_U
[]= /* Save, enter. */
122 { "r0", 0x01, 0x01 },
123 { "r1", 0x02, 0x02 },
124 { "r2", 0x04, 0x04 },
125 { "r3", 0x08, 0x08 },
126 { "r4", 0x10, 0x10 },
127 { "r5", 0x20, 0x20 },
128 { "r6", 0x40, 0x40 },
129 { "r7", 0x80, 0x80 },
133 static const struct ns32k_option opt_O
[]= /* Setcfg. */
142 static const struct ns32k_option opt_C
[]= /* Cinv. */
150 static const struct ns32k_option opt_S
[]= /* String inst. */
158 static const struct ns32k_option list_P532
[]= /* Lpr spr. */
171 { "intbase", 0xe, 0xf },
176 static const struct ns32k_option list_M532
[]= /* Lmr smr. */
180 { "tear", 0xb, 0xf },
181 { "ptb0", 0xc, 0xf },
182 { "ptb1", 0xd, 0xf },
183 { "ivar0", 0xe, 0xf },
184 { "ivar1", 0xf, 0xf },
188 static const struct ns32k_option list_P032
[]= /* Lpr spr. */
190 { "upsr", 0x0, 0xf },
195 { "intbase", 0xe, 0xf },
200 static const struct ns32k_option list_M032
[]= /* Lmr smr. */
202 { "bpr0", 0x0, 0xf },
203 { "bpr1", 0x1, 0xf },
208 { "bcnt", 0xb, 0xf },
209 { "ptb0", 0xc, 0xf },
210 { "ptb1", 0xd, 0xf },
216 /* Figure out which options are present. */
219 optlist (int options
, const struct ns32k_option
* optionP
, char * result
)
223 sprintf (result
, "[]");
227 sprintf (result
, "[");
229 for (; (options
!= 0) && optionP
->pattern
; optionP
++)
231 if ((options
& optionP
->match
) == optionP
->value
)
233 /* We found a match, update result and options. */
234 strcat (result
, optionP
->pattern
);
235 options
&= ~optionP
->value
;
236 if (options
!= 0) /* More options to come. */
237 strcat (result
, ",");
242 strcat (result
, "undefined");
244 strcat (result
, "]");
248 list_search (int reg_value
, const struct ns32k_option
*optionP
, char *result
)
250 for (; optionP
->pattern
; optionP
++)
252 if ((reg_value
& optionP
->match
) == optionP
->value
)
254 sprintf (result
, "%s", optionP
->pattern
);
258 sprintf (result
, "undefined");
261 /* Extract "count" bits starting "offset" bits into buffer. */
264 bit_extract (bfd_byte
*buffer
, int offset
, int count
)
269 buffer
+= offset
>> 3;
275 FETCH_DATA (dis_info
, buffer
+ 1);
276 if ((*buffer
& (1 << offset
)))
288 /* Like bit extract but the buffer is valid and doen't need to be fetched. */
291 bit_extract_simple (bfd_byte
*buffer
, int offset
, int count
)
296 buffer
+= offset
>> 3;
302 if ((*buffer
& (1 << offset
)))
315 bit_copy (bfd_byte
*buffer
, int offset
, int count
, char *to
)
317 for (; count
> 8; count
-= 8, to
++, offset
+= 8)
318 *to
= bit_extract (buffer
, offset
, 8);
319 *to
= bit_extract (buffer
, offset
, count
);
323 sign_extend (int value
, int bits
)
325 value
= value
& ((1 << bits
) - 1);
326 return (value
& (1 << (bits
- 1))
327 ? value
| (~((1 << bits
) - 1))
332 flip_bytes (char *ptr
, int count
)
339 ptr
[0] = ptr
[count
- 1];
340 ptr
[count
- 1] = tmp
;
346 /* Given a character C, does it represent a general addressing mode? */
348 ((c) == 'F' || (c) == 'L' || (c) == 'B' \
349 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')
351 /* Adressing modes. */
352 #define Adrmod_index_byte 0x1c
353 #define Adrmod_index_word 0x1d
354 #define Adrmod_index_doubleword 0x1e
355 #define Adrmod_index_quadword 0x1f
357 /* Is MODE an indexed addressing mode? */
358 #define Adrmod_is_index(mode) \
359 ( mode == Adrmod_index_byte \
360 || mode == Adrmod_index_word \
361 || mode == Adrmod_index_doubleword \
362 || mode == Adrmod_index_quadword)
366 get_displacement (bfd_byte
*buffer
, int *aoffsetp
)
371 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
372 switch (Ivalue
& 0xc0)
376 Ivalue
= sign_extend (Ivalue
, 7);
380 Ivalue2
= bit_extract (buffer
, *aoffsetp
, 16);
381 flip_bytes ((char *) & Ivalue2
, 2);
382 Ivalue
= sign_extend (Ivalue2
, 14);
386 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
387 flip_bytes ((char *) & Ivalue
, 4);
388 Ivalue
= sign_extend (Ivalue
, 30);
395 #if 1 /* A version that should work on ns32k f's&d's on any machine. */
397 invalid_float (bfd_byte
*p
, int len
)
402 val
= (bit_extract_simple (p
, 23, 8)/*exponent*/ == 0xff
403 || (bit_extract_simple (p
, 23, 8)/*exponent*/ == 0
404 && bit_extract_simple (p
, 0, 23)/*mantisa*/ != 0));
406 val
= (bit_extract_simple (p
, 52, 11)/*exponent*/ == 0x7ff
407 || (bit_extract_simple (p
, 52, 11)/*exponent*/ == 0
408 && (bit_extract_simple (p
, 0, 32)/*low mantisa*/ != 0
409 || bit_extract_simple (p
, 32, 20)/*high mantisa*/ != 0)));
415 /* Assumes the bytes have been swapped to local order. */
420 struct { unsigned m
:23, e
:8, :1;} sf
;
421 struct { unsigned lm
; unsigned m
:20, e
:11, :1;} sd
;
425 invalid_float (float_type_u
*p
, int len
)
429 if (len
== sizeof (float))
430 val
= (p
->sf
.e
== 0xff
431 || (p
->sf
.e
== 0 && p
->sf
.m
!= 0));
432 else if (len
== sizeof (double))
433 val
= (p
->sd
.e
== 0x7ff
434 || (p
->sd
.e
== 0 && (p
->sd
.m
!= 0 || p
->sd
.lm
!= 0)));
441 /* Print an instruction operand of category given by d. IOFFSET is
442 the bit position below which small (<1 byte) parts of the operand can
443 be found (usually in the basic instruction, but for indexed
444 addressing it can be in the index byte). AOFFSETP is a pointer to the
445 bit position of the addressing extension. BUFFER contains the
446 instruction. ADDR is where BUFFER was read from. Put the disassembled
447 version of the operand in RESULT. INDEX_OFFSET is the bit position
448 of the index byte (it contains garbage if this operand is not a
449 general operand using scaled indexed addressing mode). */
452 print_insn_arg (int d
,
475 /* A "gen" operand but 5 bits from the end of instruction. */
485 addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
489 case 0x0: case 0x1: case 0x2: case 0x3:
490 case 0x4: case 0x5: case 0x6: case 0x7:
491 /* Register mode R0 -- R7. */
497 sprintf (result
, "f%d", addr_mode
);
500 sprintf (result
, "r%d", addr_mode
);
503 case 0x8: case 0x9: case 0xa: case 0xb:
504 case 0xc: case 0xd: case 0xe: case 0xf:
505 /* Register relative disp(R0 -- R7). */
506 disp1
= get_displacement (buffer
, aoffsetp
);
507 sprintf (result
, "%d(r%d)", disp1
, addr_mode
& 7);
512 /* Memory relative disp2(disp1(FP, SP, SB)). */
513 disp1
= get_displacement (buffer
, aoffsetp
);
514 disp2
= get_displacement (buffer
, aoffsetp
);
515 sprintf (result
, "%d(%d(%s))", disp2
, disp1
,
516 addr_mode
== 0x10 ? "fp" : addr_mode
== 0x11 ? "sp" : "sb");
520 sprintf (result
, "reserved");
529 /* I and Z are output operands and can`t be immediate
530 A is an address and we can`t have the address of
531 an immediate either. We don't know how much to increase
532 aoffsetp by since whatever generated this is broken
534 sprintf (result
, _("$<undefined>"));
537 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
538 Ivalue
= sign_extend (Ivalue
, 8);
540 sprintf (result
, "$%d", Ivalue
);
543 Ivalue
= bit_extract (buffer
, *aoffsetp
, 16);
544 flip_bytes ((char *) & Ivalue
, 2);
546 Ivalue
= sign_extend (Ivalue
, 16);
547 sprintf (result
, "$%d", Ivalue
);
550 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
551 flip_bytes ((char *) & Ivalue
, 4);
553 sprintf (result
, "$%d", Ivalue
);
556 bit_copy (buffer
, *aoffsetp
, 32, (char *) &value
.f
);
557 flip_bytes ((char *) &value
.f
, 4);
559 if (INVALID_FLOAT (&value
.f
, 4))
560 sprintf (result
, "<<invalid float 0x%.8x>>", value
.i
[0]);
561 else /* Assume host has ieee float. */
562 sprintf (result
, "$%g", value
.f
);
565 bit_copy (buffer
, *aoffsetp
, 64, (char *) &value
.d
);
566 flip_bytes ((char *) &value
.d
, 8);
568 if (INVALID_FLOAT (&value
.d
, 8))
569 sprintf (result
, "<<invalid double 0x%.8x%.8x>>",
570 value
.i
[1], value
.i
[0]);
571 else /* Assume host has ieee float. */
572 sprintf (result
, "$%g", value
.d
);
577 /* Absolute @disp. */
578 disp1
= get_displacement (buffer
, aoffsetp
);
579 sprintf (result
, "@|%d|", disp1
);
582 /* External EXT(disp1) + disp2 (Mod table stuff). */
583 disp1
= get_displacement (buffer
, aoffsetp
);
584 disp2
= get_displacement (buffer
, aoffsetp
);
585 sprintf (result
, "EXT(%d) + %d", disp1
, disp2
);
588 /* Top of stack tos. */
589 sprintf (result
, "tos");
592 /* Memory space disp(FP). */
593 disp1
= get_displacement (buffer
, aoffsetp
);
594 sprintf (result
, "%d(fp)", disp1
);
597 /* Memory space disp(SP). */
598 disp1
= get_displacement (buffer
, aoffsetp
);
599 sprintf (result
, "%d(sp)", disp1
);
602 /* Memory space disp(SB). */
603 disp1
= get_displacement (buffer
, aoffsetp
);
604 sprintf (result
, "%d(sb)", disp1
);
607 /* Memory space disp(PC). */
608 disp1
= get_displacement (buffer
, aoffsetp
);
609 *result
++ = NEXT_IS_ADDR
;
610 sprintf_vma (result
, addr
+ disp1
);
611 result
+= strlen (result
);
612 *result
++ = NEXT_IS_ADDR
;
619 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
620 index
= bit_extract (buffer
, index_offset
- 8, 3);
621 print_insn_arg (d
, index_offset
, aoffsetp
, buffer
, addr
,
624 static const char *ind
= "bwdq";
627 off
= result
+ strlen (result
);
628 sprintf (off
, "[r%d:%c]", index
,
636 Ivalue
= bit_extract (buffer
, ioffset
-4, 4);
637 Ivalue
= sign_extend (Ivalue
, 4);
638 sprintf (result
, "%d", Ivalue
);
642 Ivalue
= bit_extract (buffer
, ioffset
-3, 3);
643 sprintf (result
, "r%d", Ivalue
&7);
647 sprintf (result
, "%d", get_displacement (buffer
, aoffsetp
));
650 Ivalue
= get_displacement (buffer
, aoffsetp
);
651 /* Warning!! HACK ALERT!
652 Operand type 'b' is only used by the cmp{b,w,d} and
653 movm{b,w,d} instructions; we need to know whether
654 it's a `b' or `w' or `d' instruction; and for both
655 cmpm and movm it's stored at the same place so we
656 just grab two bits of the opcode and look at it... */
657 size
= bit_extract(buffer
, ioffset
-6, 2);
658 if (size
== 0) /* 00 => b. */
660 else if (size
== 1) /* 01 => w. */
663 size
= 4; /* 11 => d. */
665 sprintf (result
, "%d", (Ivalue
/ size
) + 1);
668 *result
++ = NEXT_IS_ADDR
;
669 sprintf_vma (result
, addr
+ get_displacement (buffer
, aoffsetp
));
670 result
+= strlen (result
);
671 *result
++ = NEXT_IS_ADDR
;
675 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
677 sprintf (result
, "0x%x", Ivalue
);
680 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
681 optlist (Ivalue
, opt_u
, result
);
685 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
686 optlist (Ivalue
, opt_U
, result
);
690 Ivalue
= bit_extract (buffer
, ioffset
- 9, 9);
691 optlist (Ivalue
, opt_O
, result
);
695 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
696 optlist (Ivalue
, opt_C
, result
);
700 Ivalue
= bit_extract (buffer
, ioffset
- 8, 8);
701 optlist (Ivalue
, opt_S
, result
);
705 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
706 list_search (Ivalue
, 0 ? list_M032
: list_M532
, result
);
710 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
711 list_search (Ivalue
, 0 ? list_P032
: list_P532
, result
);
715 Ivalue
= bit_extract (buffer
, *aoffsetp
, 3);
716 sprintf (result
, "%d", Ivalue
);
720 Ivalue
= bit_extract(buffer
, *aoffsetp
, 5);
721 sprintf (result
, "%d", Ivalue
+ 1);
729 /* Print the 32000 instruction at address MEMADDR in debugged memory,
730 on STREAM. Returns length of the instruction, in bytes. */
733 print_insn_ns32k (bfd_vma memaddr
, disassemble_info
*info
)
737 unsigned short first_word
;
738 int ioffset
; /* Bits into instruction. */
739 int aoffset
; /* Bits into arguments. */
740 char arg_bufs
[MAX_ARGS
+1][ARG_LEN
];
744 bfd_byte
*buffer
= priv
.the_buffer
;
747 info
->private_data
= & priv
;
748 priv
.max_fetched
= priv
.the_buffer
;
749 priv
.insn_start
= memaddr
;
750 if (setjmp (priv
.bailout
) != 0)
754 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
755 us over the end of accessible data unnecessarilly. */
756 FETCH_DATA (info
, buffer
+ 1);
757 for (i
= 0; i
< NOPCODES
; i
++)
758 if (ns32k_opcodes
[i
].opcode_id_size
<= 8
760 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
761 == ns32k_opcodes
[i
].opcode_seed
))
765 /* Maybe it is 9 to 16 bits big. */
766 FETCH_DATA (info
, buffer
+ 2);
767 first_word
= read_memory_integer(buffer
, 2);
769 for (i
= 0; i
< NOPCODES
; i
++)
771 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
772 == ns32k_opcodes
[i
].opcode_seed
)
775 /* Handle undefined instructions. */
778 (*dis_info
->fprintf_func
)(dis_info
->stream
, "0%o", buffer
[0]);
783 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%s", ns32k_opcodes
[i
].name
);
785 ioffset
= ns32k_opcodes
[i
].opcode_size
;
786 aoffset
= ns32k_opcodes
[i
].opcode_size
;
787 d
= ns32k_opcodes
[i
].operands
;
791 /* Offset in bits of the first thing beyond each index byte.
792 Element 0 is for operand A and element 1 is for operand B.
793 The rest are irrelevant, but we put them here so we don't
794 index outside the array. */
795 int index_offset
[MAX_ARGS
];
797 /* 0 for operand A, 1 for operand B, greater for other args. */
800 (*dis_info
->fprintf_func
)(dis_info
->stream
, "\t");
804 /* First we have to find and keep track of the index bytes,
805 if we are using scaled indexed addressing mode, since the index
806 bytes occur right after the basic instruction, not as part
807 of the addressing extension. */
810 int addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
812 if (Adrmod_is_index (addr_mode
))
815 index_offset
[0] = aoffset
;
819 if (d
[2] && Is_gen(d
[3]))
821 int addr_mode
= bit_extract (buffer
, ioffset
- 10, 5);
823 if (Adrmod_is_index (addr_mode
))
826 index_offset
[1] = aoffset
;
834 if (argnum
> maxarg
&& argnum
< MAX_ARGS
)
836 ioffset
= print_insn_arg (*d
, ioffset
, &aoffset
, buffer
,
837 memaddr
, arg_bufs
[argnum
],
838 index_offset
[whicharg
]);
842 for (argnum
= 0; argnum
<= maxarg
; argnum
++)
847 for (ch
= arg_bufs
[argnum
]; *ch
;)
849 if (*ch
== NEXT_IS_ADDR
)
852 addr
= bfd_scan_vma (ch
, NULL
, 16);
853 (*dis_info
->print_address_func
) (addr
, dis_info
);
854 while (*ch
&& *ch
!= NEXT_IS_ADDR
)
860 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%c", *ch
++);
863 (*dis_info
->fprintf_func
)(dis_info
->stream
, ", ");