1 /* Print National Semiconductor 32000 instructions.
2 Copyright (C) 1986-2020 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library 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 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 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., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
23 #include "disassemble.h"
24 #if !defined(const) && !defined(__STDC__)
27 #include "opcode/ns32k.h"
30 static disassemble_info
*dis_info
;
32 /* Hacks to get it to compile <= READ THESE AS FIXES NEEDED. */
33 #define INVALID_FLOAT(val, size) invalid_float ((bfd_byte *) val, size)
36 read_memory_integer (unsigned char * addr
, int nr
)
41 for (val
= 0, i
= nr
- 1; i
>= 0; i
--)
44 val
|= (0xff & *(addr
+ i
));
49 /* 32000 instructions are never longer than this. */
56 /* Points to first byte not fetched. */
57 bfd_byte
*max_fetched
;
58 bfd_byte the_buffer
[MAXLEN
];
60 OPCODES_SIGJMP_BUF bailout
;
64 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
65 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
67 #define FETCH_DATA(info, addr) \
68 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
69 ? 1 : fetch_data ((info), (addr)))
72 fetch_data (struct disassemble_info
*info
, bfd_byte
*addr
)
75 struct private *priv
= (struct private *) info
->private_data
;
76 bfd_vma start
= priv
->insn_start
+ (priv
->max_fetched
- priv
->the_buffer
);
78 status
= (*info
->read_memory_func
) (start
,
80 addr
- priv
->max_fetched
,
84 (*info
->memory_error_func
) (status
, start
, info
);
85 OPCODES_SIGLONGJMP (priv
->bailout
, 1);
88 priv
->max_fetched
= addr
;
92 /* Number of elements in the opcode table. */
93 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
95 #define NEXT_IS_ADDR '|'
100 char *pattern
; /* The option itself. */
101 unsigned long value
; /* Binary value of the option. */
102 unsigned long match
; /* These bits must match. */
106 static const struct ns32k_option opt_u
[]= /* Restore, exit. */
108 { "r0", 0x80, 0x80 },
109 { "r1", 0x40, 0x40 },
110 { "r2", 0x20, 0x20 },
111 { "r3", 0x10, 0x10 },
112 { "r4", 0x08, 0x08 },
113 { "r5", 0x04, 0x04 },
114 { "r6", 0x02, 0x02 },
115 { "r7", 0x01, 0x01 },
119 static const struct ns32k_option opt_U
[]= /* Save, enter. */
121 { "r0", 0x01, 0x01 },
122 { "r1", 0x02, 0x02 },
123 { "r2", 0x04, 0x04 },
124 { "r3", 0x08, 0x08 },
125 { "r4", 0x10, 0x10 },
126 { "r5", 0x20, 0x20 },
127 { "r6", 0x40, 0x40 },
128 { "r7", 0x80, 0x80 },
132 static const struct ns32k_option opt_O
[]= /* Setcfg. */
141 static const struct ns32k_option opt_C
[]= /* Cinv. */
149 static const struct ns32k_option opt_S
[]= /* String inst. */
157 static const struct ns32k_option list_P532
[]= /* Lpr spr. */
170 { "intbase", 0xe, 0xf },
175 static const struct ns32k_option list_M532
[]= /* Lmr smr. */
179 { "tear", 0xb, 0xf },
180 { "ptb0", 0xc, 0xf },
181 { "ptb1", 0xd, 0xf },
182 { "ivar0", 0xe, 0xf },
183 { "ivar1", 0xf, 0xf },
187 static const struct ns32k_option list_P032
[]= /* Lpr spr. */
189 { "upsr", 0x0, 0xf },
194 { "intbase", 0xe, 0xf },
199 static const struct ns32k_option list_M032
[]= /* Lmr smr. */
201 { "bpr0", 0x0, 0xf },
202 { "bpr1", 0x1, 0xf },
207 { "bcnt", 0xb, 0xf },
208 { "ptb0", 0xc, 0xf },
209 { "ptb1", 0xd, 0xf },
215 /* Figure out which options are present. */
218 optlist (int options
, const struct ns32k_option
* optionP
, char * result
)
222 sprintf (result
, "[]");
226 sprintf (result
, "[");
228 for (; (options
!= 0) && optionP
->pattern
; optionP
++)
230 if ((options
& optionP
->match
) == optionP
->value
)
232 /* We found a match, update result and options. */
233 strcat (result
, optionP
->pattern
);
234 options
&= ~optionP
->value
;
235 if (options
!= 0) /* More options to come. */
236 strcat (result
, ",");
241 strcat (result
, "undefined");
243 strcat (result
, "]");
247 list_search (int reg_value
, const struct ns32k_option
*optionP
, char *result
)
249 for (; optionP
->pattern
; optionP
++)
251 if ((reg_value
& optionP
->match
) == optionP
->value
)
253 sprintf (result
, "%s", optionP
->pattern
);
257 sprintf (result
, "undefined");
260 /* Extract "count" bits starting "offset" bits into buffer. */
263 bit_extract (bfd_byte
*buffer
, int offset
, int count
)
268 if (offset
< 0 || count
< 0)
270 buffer
+= offset
>> 3;
276 FETCH_DATA (dis_info
, buffer
+ 1);
277 if ((*buffer
& (1 << offset
)))
289 /* Like bit extract but the buffer is valid and doen't need to be fetched. */
292 bit_extract_simple (bfd_byte
*buffer
, int offset
, int count
)
297 if (offset
< 0 || count
< 0)
299 buffer
+= offset
>> 3;
305 if ((*buffer
& (1 << offset
)))
318 bit_copy (bfd_byte
*buffer
, int offset
, int count
, char *to
)
320 if (offset
< 0 || count
< 0)
322 for (; count
> 8; count
-= 8, to
++, offset
+= 8)
323 *to
= bit_extract (buffer
, offset
, 8);
324 *to
= bit_extract (buffer
, offset
, count
);
328 sign_extend (unsigned int value
, unsigned int bits
)
330 unsigned int sign
= 1u << (bits
- 1);
331 return ((value
& (sign
+ sign
- 1)) ^ sign
) - sign
;
335 flip_bytes (char *ptr
, int count
)
342 ptr
[0] = ptr
[count
- 1];
343 ptr
[count
- 1] = tmp
;
349 /* Given a character C, does it represent a general addressing mode? */
350 #define Is_gen(c) (strchr ("FLBWDAIZf", (c)) != NULL)
352 /* Adressing modes. */
353 #define Adrmod_index_byte 0x1c
354 #define Adrmod_index_word 0x1d
355 #define Adrmod_index_doubleword 0x1e
356 #define Adrmod_index_quadword 0x1f
358 /* Is MODE an indexed addressing mode? */
359 #define Adrmod_is_index(mode) \
360 ( mode == Adrmod_index_byte \
361 || mode == Adrmod_index_word \
362 || mode == Adrmod_index_doubleword \
363 || mode == Adrmod_index_quadword)
367 get_displacement (bfd_byte
*buffer
, int *aoffsetp
)
372 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
373 switch (Ivalue
& 0xc0)
377 Ivalue
= sign_extend (Ivalue
, 7);
381 Ivalue2
= bit_extract (buffer
, *aoffsetp
, 16);
382 flip_bytes ((char *) & Ivalue2
, 2);
383 Ivalue
= sign_extend (Ivalue2
, 14);
387 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
388 flip_bytes ((char *) & Ivalue
, 4);
389 Ivalue
= sign_extend (Ivalue
, 30);
396 #if 1 /* A version that should work on ns32k f's&d's on any machine. */
398 invalid_float (bfd_byte
*p
, int len
)
403 val
= (bit_extract_simple (p
, 23, 8)/*exponent*/ == 0xff
404 || (bit_extract_simple (p
, 23, 8)/*exponent*/ == 0
405 && bit_extract_simple (p
, 0, 23)/*mantisa*/ != 0));
407 val
= (bit_extract_simple (p
, 52, 11)/*exponent*/ == 0x7ff
408 || (bit_extract_simple (p
, 52, 11)/*exponent*/ == 0
409 && (bit_extract_simple (p
, 0, 32)/*low mantisa*/ != 0
410 || bit_extract_simple (p
, 32, 20)/*high mantisa*/ != 0)));
416 /* Assumes the bytes have been swapped to local order. */
421 struct { unsigned m
:23, e
:8, :1;} sf
;
422 struct { unsigned lm
; unsigned m
:20, e
:11, :1;} sd
;
426 invalid_float (float_type_u
*p
, int len
)
430 if (len
== sizeof (float))
431 val
= (p
->sf
.e
== 0xff
432 || (p
->sf
.e
== 0 && p
->sf
.m
!= 0));
433 else if (len
== sizeof (double))
434 val
= (p
->sd
.e
== 0x7ff
435 || (p
->sd
.e
== 0 && (p
->sd
.m
!= 0 || p
->sd
.lm
!= 0)));
442 /* Print an instruction operand of category given by d. IOFFSET is
443 the bit position below which small (<1 byte) parts of the operand can
444 be found (usually in the basic instruction, but for indexed
445 addressing it can be in the index byte). AOFFSETP is a pointer to the
446 bit position of the addressing extension. BUFFER contains the
447 instruction. ADDR is where BUFFER was read from. Put the disassembled
448 version of the operand in RESULT. INDEX_OFFSET is the bit position
449 of the index byte (it contains -1 if this operand is not a
450 general operand using scaled indexed addressing mode). */
453 print_insn_arg (int d
,
475 /* A "gen" operand but 5 bits from the end of instruction. */
486 addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
490 case 0x0: case 0x1: case 0x2: case 0x3:
491 case 0x4: case 0x5: case 0x6: case 0x7:
492 /* Register mode R0 -- R7. */
498 sprintf (result
, "f%d", addr_mode
);
501 sprintf (result
, "r%d", addr_mode
);
504 case 0x8: case 0x9: case 0xa: case 0xb:
505 case 0xc: case 0xd: case 0xe: case 0xf:
506 /* Register relative disp(R0 -- R7). */
507 disp1
= get_displacement (buffer
, aoffsetp
);
508 sprintf (result
, "%d(r%d)", disp1
, addr_mode
& 7);
513 /* Memory relative disp2(disp1(FP, SP, SB)). */
514 disp1
= get_displacement (buffer
, aoffsetp
);
515 disp2
= get_displacement (buffer
, aoffsetp
);
516 sprintf (result
, "%d(%d(%s))", disp2
, disp1
,
517 addr_mode
== 0x10 ? "fp" : addr_mode
== 0x11 ? "sp" : "sb");
521 sprintf (result
, "reserved");
530 /* I and Z are output operands and can`t be immediate
531 A is an address and we can`t have the address of
532 an immediate either. We don't know how much to increase
533 aoffsetp by since whatever generated this is broken
535 sprintf (result
, _("$<undefined>"));
538 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
539 Ivalue
= sign_extend (Ivalue
, 8);
541 sprintf (result
, "$%d", Ivalue
);
544 Ivalue
= bit_extract (buffer
, *aoffsetp
, 16);
545 flip_bytes ((char *) & Ivalue
, 2);
547 Ivalue
= sign_extend (Ivalue
, 16);
548 sprintf (result
, "$%d", Ivalue
);
551 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
552 flip_bytes ((char *) & Ivalue
, 4);
554 sprintf (result
, "$%d", Ivalue
);
557 bit_copy (buffer
, *aoffsetp
, 32, (char *) &value
.f
);
558 flip_bytes ((char *) &value
.f
, 4);
560 if (INVALID_FLOAT (&value
.f
, 4))
561 sprintf (result
, "<<invalid float 0x%.8x>>", value
.i
[0]);
562 else /* Assume host has ieee float. */
563 sprintf (result
, "$%g", value
.f
);
566 bit_copy (buffer
, *aoffsetp
, 64, (char *) &value
.d
);
567 flip_bytes ((char *) &value
.d
, 8);
569 if (INVALID_FLOAT (&value
.d
, 8))
570 sprintf (result
, "<<invalid double 0x%.8x%.8x>>",
571 value
.i
[1], value
.i
[0]);
572 else /* Assume host has ieee float. */
573 sprintf (result
, "$%g", value
.d
);
578 /* Absolute @disp. */
579 disp1
= get_displacement (buffer
, aoffsetp
);
580 sprintf (result
, "@|%d|", disp1
);
583 /* External EXT(disp1) + disp2 (Mod table stuff). */
584 disp1
= get_displacement (buffer
, aoffsetp
);
585 disp2
= get_displacement (buffer
, aoffsetp
);
586 sprintf (result
, "EXT(%d) + %d", disp1
, disp2
);
589 /* Top of stack tos. */
590 sprintf (result
, "tos");
593 /* Memory space disp(FP). */
594 disp1
= get_displacement (buffer
, aoffsetp
);
595 sprintf (result
, "%d(fp)", disp1
);
598 /* Memory space disp(SP). */
599 disp1
= get_displacement (buffer
, aoffsetp
);
600 sprintf (result
, "%d(sp)", disp1
);
603 /* Memory space disp(SB). */
604 disp1
= get_displacement (buffer
, aoffsetp
);
605 sprintf (result
, "%d(sb)", disp1
);
608 /* Memory space disp(PC). */
609 disp1
= get_displacement (buffer
, aoffsetp
);
610 *result
++ = NEXT_IS_ADDR
;
611 sprintf_vma (result
, addr
+ disp1
);
612 result
+= strlen (result
);
613 *result
++ = NEXT_IS_ADDR
;
622 static const char *ind
= "bwdq";
625 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
626 bit_index
= bit_extract (buffer
, index_offset
- 8, 3);
627 print_insn_arg (d
, index_offset
, aoffsetp
, buffer
, addr
,
629 off
= result
+ strlen (result
);
630 sprintf (off
, "[r%d:%c]", bit_index
, ind
[addr_mode
& 3]);
637 Ivalue
= bit_extract (buffer
, ioffset
-4, 4);
638 Ivalue
= sign_extend (Ivalue
, 4);
639 sprintf (result
, "%d", Ivalue
);
643 Ivalue
= bit_extract (buffer
, ioffset
-3, 3);
644 sprintf (result
, "r%d", Ivalue
&7);
648 sprintf (result
, "%d", get_displacement (buffer
, aoffsetp
));
651 Ivalue
= get_displacement (buffer
, aoffsetp
);
652 /* Warning!! HACK ALERT!
653 Operand type 'b' is only used by the cmp{b,w,d} and
654 movm{b,w,d} instructions; we need to know whether
655 it's a `b' or `w' or `d' instruction; and for both
656 cmpm and movm it's stored at the same place so we
657 just grab two bits of the opcode and look at it... */
658 size
= bit_extract(buffer
, ioffset
-6, 2);
659 if (size
== 0) /* 00 => b. */
661 else if (size
== 1) /* 01 => w. */
664 size
= 4; /* 11 => d. */
666 sprintf (result
, "%d", (Ivalue
/ size
) + 1);
669 *result
++ = NEXT_IS_ADDR
;
670 sprintf_vma (result
, addr
+ get_displacement (buffer
, aoffsetp
));
671 result
+= strlen (result
);
672 *result
++ = NEXT_IS_ADDR
;
676 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
678 sprintf (result
, "0x%x", Ivalue
);
681 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
682 optlist (Ivalue
, opt_u
, result
);
686 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
687 optlist (Ivalue
, opt_U
, result
);
691 Ivalue
= bit_extract (buffer
, ioffset
- 9, 9);
692 optlist (Ivalue
, opt_O
, result
);
696 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
697 optlist (Ivalue
, opt_C
, result
);
701 Ivalue
= bit_extract (buffer
, ioffset
- 8, 8);
702 optlist (Ivalue
, opt_S
, result
);
706 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
707 list_search (Ivalue
, 0 ? list_M032
: list_M532
, result
);
711 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
712 list_search (Ivalue
, 0 ? list_P032
: list_P532
, result
);
716 Ivalue
= bit_extract (buffer
, *aoffsetp
, 3);
717 sprintf (result
, "%d", Ivalue
);
721 Ivalue
= bit_extract(buffer
, *aoffsetp
, 5);
722 sprintf (result
, "%d", Ivalue
+ 1);
730 /* Print the 32000 instruction at address MEMADDR in debugged memory,
731 on STREAM. Returns length of the instruction, in bytes. */
734 print_insn_ns32k (bfd_vma memaddr
, disassemble_info
*info
)
738 unsigned short first_word
;
739 int ioffset
; /* Bits into instruction. */
740 int aoffset
; /* Bits into arguments. */
741 char arg_bufs
[MAX_ARGS
+1][ARG_LEN
];
745 bfd_byte
*buffer
= priv
.the_buffer
;
748 info
->private_data
= & priv
;
749 priv
.max_fetched
= priv
.the_buffer
;
750 priv
.insn_start
= memaddr
;
751 if (OPCODES_SIGSETJMP (priv
.bailout
) != 0)
755 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
756 us over the end of accessible data unnecessarilly. */
757 FETCH_DATA (info
, buffer
+ 1);
758 for (i
= 0; i
< NOPCODES
; i
++)
759 if (ns32k_opcodes
[i
].opcode_id_size
<= 8
761 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
762 == ns32k_opcodes
[i
].opcode_seed
))
766 /* Maybe it is 9 to 16 bits big. */
767 FETCH_DATA (info
, buffer
+ 2);
768 first_word
= read_memory_integer(buffer
, 2);
770 for (i
= 0; i
< NOPCODES
; i
++)
772 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
773 == ns32k_opcodes
[i
].opcode_seed
)
776 /* Handle undefined instructions. */
779 (*dis_info
->fprintf_func
)(dis_info
->stream
, "0%o", buffer
[0]);
784 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%s", ns32k_opcodes
[i
].name
);
786 ioffset
= ns32k_opcodes
[i
].opcode_size
;
787 aoffset
= ns32k_opcodes
[i
].opcode_size
;
788 d
= ns32k_opcodes
[i
].operands
;
792 /* Offset in bits of the first thing beyond each index byte.
793 Element 0 is for operand A and element 1 is for operand B. */
796 /* 0 for operand A, 1 for operand B, greater for other args. */
799 (*dis_info
->fprintf_func
)(dis_info
->stream
, "\t");
803 /* First we have to find and keep track of the index bytes,
804 if we are using scaled indexed addressing mode, since the index
805 bytes occur right after the basic instruction, not as part
806 of the addressing extension. */
807 index_offset
[0] = -1;
808 index_offset
[1] = -1;
811 int bitoff
= d
[1] == 'f' ? 10 : 5;
812 int addr_mode
= bit_extract (buffer
, ioffset
- bitoff
, 5);
814 if (Adrmod_is_index (addr_mode
))
817 index_offset
[0] = aoffset
;
821 if (d
[2] && Is_gen (d
[3]))
823 int addr_mode
= bit_extract (buffer
, ioffset
- 10, 5);
825 if (Adrmod_is_index (addr_mode
))
828 index_offset
[1] = aoffset
;
835 if (argnum
>= MAX_ARGS
)
840 ioffset
= print_insn_arg (*d
, ioffset
, &aoffset
, buffer
,
841 memaddr
, arg_bufs
[argnum
],
842 whicharg
> 1 ? -1 : index_offset
[whicharg
]);
847 for (argnum
= 0; argnum
<= maxarg
; argnum
++)
852 for (ch
= arg_bufs
[argnum
]; *ch
;)
854 if (*ch
== NEXT_IS_ADDR
)
857 addr
= bfd_scan_vma (ch
, NULL
, 16);
858 (*dis_info
->print_address_func
) (addr
, dis_info
);
859 while (*ch
&& *ch
!= NEXT_IS_ADDR
)
865 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%c", *ch
++);
868 (*dis_info
->fprintf_func
)(dis_info
->stream
, ", ");