1 /* Print National Semiconductor 32000 instructions.
2 Copyright 1986, 1988, 1991, 1992, 1994, 1998, 2001, 2002, 2005, 2007,
3 2009 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
,
474 /* A "gen" operand but 5 bits from the end of instruction. */
484 addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
488 case 0x0: case 0x1: case 0x2: case 0x3:
489 case 0x4: case 0x5: case 0x6: case 0x7:
490 /* Register mode R0 -- R7. */
496 sprintf (result
, "f%d", addr_mode
);
499 sprintf (result
, "r%d", addr_mode
);
502 case 0x8: case 0x9: case 0xa: case 0xb:
503 case 0xc: case 0xd: case 0xe: case 0xf:
504 /* Register relative disp(R0 -- R7). */
505 disp1
= get_displacement (buffer
, aoffsetp
);
506 sprintf (result
, "%d(r%d)", disp1
, addr_mode
& 7);
511 /* Memory relative disp2(disp1(FP, SP, SB)). */
512 disp1
= get_displacement (buffer
, aoffsetp
);
513 disp2
= get_displacement (buffer
, aoffsetp
);
514 sprintf (result
, "%d(%d(%s))", disp2
, disp1
,
515 addr_mode
== 0x10 ? "fp" : addr_mode
== 0x11 ? "sp" : "sb");
519 sprintf (result
, "reserved");
528 /* I and Z are output operands and can`t be immediate
529 A is an address and we can`t have the address of
530 an immediate either. We don't know how much to increase
531 aoffsetp by since whatever generated this is broken
533 sprintf (result
, _("$<undefined>"));
536 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
537 Ivalue
= sign_extend (Ivalue
, 8);
539 sprintf (result
, "$%d", Ivalue
);
542 Ivalue
= bit_extract (buffer
, *aoffsetp
, 16);
543 flip_bytes ((char *) & Ivalue
, 2);
545 Ivalue
= sign_extend (Ivalue
, 16);
546 sprintf (result
, "$%d", Ivalue
);
549 Ivalue
= bit_extract (buffer
, *aoffsetp
, 32);
550 flip_bytes ((char *) & Ivalue
, 4);
552 sprintf (result
, "$%d", Ivalue
);
555 bit_copy (buffer
, *aoffsetp
, 32, (char *) &value
.f
);
556 flip_bytes ((char *) &value
.f
, 4);
558 if (INVALID_FLOAT (&value
.f
, 4))
559 sprintf (result
, "<<invalid float 0x%.8x>>", value
.i
[0]);
560 else /* Assume host has ieee float. */
561 sprintf (result
, "$%g", value
.f
);
564 bit_copy (buffer
, *aoffsetp
, 64, (char *) &value
.d
);
565 flip_bytes ((char *) &value
.d
, 8);
567 if (INVALID_FLOAT (&value
.d
, 8))
568 sprintf (result
, "<<invalid double 0x%.8x%.8x>>",
569 value
.i
[1], value
.i
[0]);
570 else /* Assume host has ieee float. */
571 sprintf (result
, "$%g", value
.d
);
576 /* Absolute @disp. */
577 disp1
= get_displacement (buffer
, aoffsetp
);
578 sprintf (result
, "@|%d|", disp1
);
581 /* External EXT(disp1) + disp2 (Mod table stuff). */
582 disp1
= get_displacement (buffer
, aoffsetp
);
583 disp2
= get_displacement (buffer
, aoffsetp
);
584 sprintf (result
, "EXT(%d) + %d", disp1
, disp2
);
587 /* Top of stack tos. */
588 sprintf (result
, "tos");
591 /* Memory space disp(FP). */
592 disp1
= get_displacement (buffer
, aoffsetp
);
593 sprintf (result
, "%d(fp)", disp1
);
596 /* Memory space disp(SP). */
597 disp1
= get_displacement (buffer
, aoffsetp
);
598 sprintf (result
, "%d(sp)", disp1
);
601 /* Memory space disp(SB). */
602 disp1
= get_displacement (buffer
, aoffsetp
);
603 sprintf (result
, "%d(sb)", disp1
);
606 /* Memory space disp(PC). */
607 disp1
= get_displacement (buffer
, aoffsetp
);
608 *result
++ = NEXT_IS_ADDR
;
609 sprintf_vma (result
, addr
+ disp1
);
610 result
+= strlen (result
);
611 *result
++ = NEXT_IS_ADDR
;
620 static const char *ind
= "bwdq";
623 /* Scaled index basemode[R0 -- R7:B,W,D,Q]. */
624 bit_index
= bit_extract (buffer
, index_offset
- 8, 3);
625 print_insn_arg (d
, index_offset
, aoffsetp
, buffer
, addr
,
627 off
= result
+ strlen (result
);
628 sprintf (off
, "[r%d:%c]", bit_index
, ind
[addr_mode
& 3]);
635 Ivalue
= bit_extract (buffer
, ioffset
-4, 4);
636 Ivalue
= sign_extend (Ivalue
, 4);
637 sprintf (result
, "%d", Ivalue
);
641 Ivalue
= bit_extract (buffer
, ioffset
-3, 3);
642 sprintf (result
, "r%d", Ivalue
&7);
646 sprintf (result
, "%d", get_displacement (buffer
, aoffsetp
));
649 Ivalue
= get_displacement (buffer
, aoffsetp
);
650 /* Warning!! HACK ALERT!
651 Operand type 'b' is only used by the cmp{b,w,d} and
652 movm{b,w,d} instructions; we need to know whether
653 it's a `b' or `w' or `d' instruction; and for both
654 cmpm and movm it's stored at the same place so we
655 just grab two bits of the opcode and look at it... */
656 size
= bit_extract(buffer
, ioffset
-6, 2);
657 if (size
== 0) /* 00 => b. */
659 else if (size
== 1) /* 01 => w. */
662 size
= 4; /* 11 => d. */
664 sprintf (result
, "%d", (Ivalue
/ size
) + 1);
667 *result
++ = NEXT_IS_ADDR
;
668 sprintf_vma (result
, addr
+ get_displacement (buffer
, aoffsetp
));
669 result
+= strlen (result
);
670 *result
++ = NEXT_IS_ADDR
;
674 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
676 sprintf (result
, "0x%x", Ivalue
);
679 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
680 optlist (Ivalue
, opt_u
, result
);
684 Ivalue
= bit_extract (buffer
, *aoffsetp
, 8);
685 optlist (Ivalue
, opt_U
, result
);
689 Ivalue
= bit_extract (buffer
, ioffset
- 9, 9);
690 optlist (Ivalue
, opt_O
, result
);
694 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
695 optlist (Ivalue
, opt_C
, result
);
699 Ivalue
= bit_extract (buffer
, ioffset
- 8, 8);
700 optlist (Ivalue
, opt_S
, result
);
704 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
705 list_search (Ivalue
, 0 ? list_M032
: list_M532
, result
);
709 Ivalue
= bit_extract (buffer
, ioffset
- 4, 4);
710 list_search (Ivalue
, 0 ? list_P032
: list_P532
, result
);
714 Ivalue
= bit_extract (buffer
, *aoffsetp
, 3);
715 sprintf (result
, "%d", Ivalue
);
719 Ivalue
= bit_extract(buffer
, *aoffsetp
, 5);
720 sprintf (result
, "%d", Ivalue
+ 1);
728 /* Print the 32000 instruction at address MEMADDR in debugged memory,
729 on STREAM. Returns length of the instruction, in bytes. */
732 print_insn_ns32k (bfd_vma memaddr
, disassemble_info
*info
)
736 unsigned short first_word
;
737 int ioffset
; /* Bits into instruction. */
738 int aoffset
; /* Bits into arguments. */
739 char arg_bufs
[MAX_ARGS
+1][ARG_LEN
];
743 bfd_byte
*buffer
= priv
.the_buffer
;
746 info
->private_data
= & priv
;
747 priv
.max_fetched
= priv
.the_buffer
;
748 priv
.insn_start
= memaddr
;
749 if (setjmp (priv
.bailout
) != 0)
753 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
754 us over the end of accessible data unnecessarilly. */
755 FETCH_DATA (info
, buffer
+ 1);
756 for (i
= 0; i
< NOPCODES
; i
++)
757 if (ns32k_opcodes
[i
].opcode_id_size
<= 8
759 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
760 == ns32k_opcodes
[i
].opcode_seed
))
764 /* Maybe it is 9 to 16 bits big. */
765 FETCH_DATA (info
, buffer
+ 2);
766 first_word
= read_memory_integer(buffer
, 2);
768 for (i
= 0; i
< NOPCODES
; i
++)
770 & (((unsigned long) 1 << ns32k_opcodes
[i
].opcode_id_size
) - 1))
771 == ns32k_opcodes
[i
].opcode_seed
)
774 /* Handle undefined instructions. */
777 (*dis_info
->fprintf_func
)(dis_info
->stream
, "0%o", buffer
[0]);
782 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%s", ns32k_opcodes
[i
].name
);
784 ioffset
= ns32k_opcodes
[i
].opcode_size
;
785 aoffset
= ns32k_opcodes
[i
].opcode_size
;
786 d
= ns32k_opcodes
[i
].operands
;
790 /* Offset in bits of the first thing beyond each index byte.
791 Element 0 is for operand A and element 1 is for operand B.
792 The rest are irrelevant, but we put them here so we don't
793 index outside the array. */
794 int index_offset
[MAX_ARGS
];
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. */
809 int addr_mode
= bit_extract (buffer
, ioffset
- 5, 5);
811 if (Adrmod_is_index (addr_mode
))
814 index_offset
[0] = aoffset
;
818 if (d
[2] && Is_gen(d
[3]))
820 int addr_mode
= bit_extract (buffer
, ioffset
- 10, 5);
822 if (Adrmod_is_index (addr_mode
))
825 index_offset
[1] = aoffset
;
833 if (argnum
> maxarg
&& argnum
< MAX_ARGS
)
835 ioffset
= print_insn_arg (*d
, ioffset
, &aoffset
, buffer
,
836 memaddr
, arg_bufs
[argnum
],
837 index_offset
[whicharg
]);
841 for (argnum
= 0; argnum
<= maxarg
; argnum
++)
846 for (ch
= arg_bufs
[argnum
]; *ch
;)
848 if (*ch
== NEXT_IS_ADDR
)
851 addr
= bfd_scan_vma (ch
, NULL
, 16);
852 (*dis_info
->print_address_func
) (addr
, dis_info
);
853 while (*ch
&& *ch
!= NEXT_IS_ADDR
)
859 (*dis_info
->fprintf_func
)(dis_info
->stream
, "%c", *ch
++);
862 (*dis_info
->fprintf_func
)(dis_info
->stream
, ", ");
This page took 0.046511 seconds and 4 git commands to generate.