1 /* Disassemble MN10300 instructions.
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "opcode/mn10300.h"
27 static void disassemble
PARAMS ((bfd_vma
, struct disassemble_info
*,
28 unsigned long insn
, unsigned int));
30 #define HAVE_AM33_2 (info->mach == AM33_2)
31 #define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
32 #define HAVE_AM30 (info->mach == AM30)
35 print_insn_mn10300 (memaddr
, info
)
37 struct disassemble_info
*info
;
44 /* First figure out how big the opcode is. */
45 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 1, info
);
48 (*info
->memory_error_func
) (status
, memaddr
, info
);
51 insn
= *(unsigned char *) buffer
;
53 /* These are one byte insns. */
54 if ((insn
& 0xf3) == 0x00
55 || (insn
& 0xf0) == 0x10
56 || (insn
& 0xfc) == 0x3c
57 || (insn
& 0xf3) == 0x41
58 || (insn
& 0xf3) == 0x40
59 || (insn
& 0xfc) == 0x50
60 || (insn
& 0xfc) == 0x54
61 || (insn
& 0xf0) == 0x60
62 || (insn
& 0xf0) == 0x70
63 || ((insn
& 0xf0) == 0x80
64 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
65 || ((insn
& 0xf0) == 0x90
66 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
67 || ((insn
& 0xf0) == 0xa0
68 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
69 || ((insn
& 0xf0) == 0xb0
70 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
71 || (insn
& 0xff) == 0xcb
72 || (insn
& 0xfc) == 0xd0
73 || (insn
& 0xfc) == 0xd4
74 || (insn
& 0xfc) == 0xd8
75 || (insn
& 0xf0) == 0xe0
76 || (insn
& 0xff) == 0xff)
81 /* These are two byte insns. */
82 else if ((insn
& 0xf0) == 0x80
83 || (insn
& 0xf0) == 0x90
84 || (insn
& 0xf0) == 0xa0
85 || (insn
& 0xf0) == 0xb0
86 || (insn
& 0xfc) == 0x20
87 || (insn
& 0xfc) == 0x28
88 || (insn
& 0xf3) == 0x43
89 || (insn
& 0xf3) == 0x42
90 || (insn
& 0xfc) == 0x58
91 || (insn
& 0xfc) == 0x5c
92 || ((insn
& 0xf0) == 0xc0
93 && (insn
& 0xff) != 0xcb
94 && (insn
& 0xff) != 0xcc
95 && (insn
& 0xff) != 0xcd)
96 || (insn
& 0xff) == 0xf0
97 || (insn
& 0xff) == 0xf1
98 || (insn
& 0xff) == 0xf2
99 || (insn
& 0xff) == 0xf3
100 || (insn
& 0xff) == 0xf4
101 || (insn
& 0xff) == 0xf5
102 || (insn
& 0xff) == 0xf6)
104 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
107 (*info
->memory_error_func
) (status
, memaddr
, info
);
110 insn
= bfd_getb16 (buffer
);
114 /* These are three byte insns. */
115 else if ((insn
& 0xff) == 0xf8
116 || (insn
& 0xff) == 0xcc
117 || (insn
& 0xff) == 0xf9
118 || (insn
& 0xf3) == 0x01
119 || (insn
& 0xf3) == 0x02
120 || (insn
& 0xf3) == 0x03
121 || (insn
& 0xfc) == 0x24
122 || (insn
& 0xfc) == 0x2c
123 || (insn
& 0xfc) == 0x30
124 || (insn
& 0xfc) == 0x34
125 || (insn
& 0xfc) == 0x38
126 || (insn
& 0xff) == 0xde
127 || (insn
& 0xff) == 0xdf
128 || (insn
& 0xff) == 0xf9
129 || (insn
& 0xff) == 0xcc)
131 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
134 (*info
->memory_error_func
) (status
, memaddr
, info
);
137 insn
= bfd_getb16 (buffer
);
139 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 1, info
);
142 (*info
->memory_error_func
) (status
, memaddr
, info
);
145 insn
|= *(unsigned char *) buffer
;
149 /* These are four byte insns. */
150 else if ((insn
& 0xff) == 0xfa
151 || (insn
& 0xff) == 0xf7
152 || (insn
& 0xff) == 0xfb)
154 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
157 (*info
->memory_error_func
) (status
, memaddr
, info
);
160 insn
= bfd_getb32 (buffer
);
164 /* These are five byte insns. */
165 else if ((insn
& 0xff) == 0xcd
166 || (insn
& 0xff) == 0xdc)
168 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
171 (*info
->memory_error_func
) (status
, memaddr
, info
);
174 insn
= bfd_getb32 (buffer
);
178 /* These are six byte insns. */
179 else if ((insn
& 0xff) == 0xfd
180 || (insn
& 0xff) == 0xfc)
182 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
185 (*info
->memory_error_func
) (status
, memaddr
, info
);
189 insn
= bfd_getb32 (buffer
);
193 /* Else its a seven byte insns (in theory). */
196 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
199 (*info
->memory_error_func
) (status
, memaddr
, info
);
203 insn
= bfd_getb32 (buffer
);
205 /* Handle the 5-byte extended instruction codes. */
206 if ((insn
& 0xfff80000) == 0xfe800000)
210 disassemble (memaddr
, info
, insn
, consume
);
216 disassemble (memaddr
, info
, insn
, size
)
218 struct disassemble_info
*info
;
222 struct mn10300_opcode
*op
= (struct mn10300_opcode
*)mn10300_opcodes
;
223 const struct mn10300_operand
*operand
;
225 unsigned long extension
= 0;
226 int status
, match
= 0;
228 /* Find the opcode. */
231 int mysize
, extra_shift
;
233 if (op
->format
== FMT_S0
)
235 else if (op
->format
== FMT_S1
236 || op
->format
== FMT_D0
)
238 else if (op
->format
== FMT_S2
239 || op
->format
== FMT_D1
)
241 else if (op
->format
== FMT_S4
)
243 else if (op
->format
== FMT_D2
)
245 else if (op
->format
== FMT_D3
)
247 else if (op
->format
== FMT_D4
)
249 else if (op
->format
== FMT_D6
)
251 else if (op
->format
== FMT_D7
|| op
->format
== FMT_D10
)
253 else if (op
->format
== FMT_D8
)
255 else if (op
->format
== FMT_D9
)
260 if ((op
->mask
& insn
) == op
->opcode
261 && size
== (unsigned int) mysize
263 || (op
->machine
== AM33_2
&& HAVE_AM33_2
)
264 || (op
->machine
== AM33
&& HAVE_AM33
)
265 || (op
->machine
== AM30
&& HAVE_AM30
)))
267 const unsigned char *opindex_ptr
;
268 unsigned int nocomma
;
271 if (op
->format
== FMT_D1
|| op
->format
== FMT_S1
)
273 else if (op
->format
== FMT_D2
|| op
->format
== FMT_D4
274 || op
->format
== FMT_S2
|| op
->format
== FMT_S4
275 || op
->format
== FMT_S6
|| op
->format
== FMT_D5
)
277 else if (op
->format
== FMT_D7
278 || op
->format
== FMT_D8
279 || op
->format
== FMT_D9
)
284 if (size
== 1 || size
== 2)
289 && (op
->format
== FMT_D1
290 || op
->opcode
== 0xdf0000
291 || op
->opcode
== 0xde0000))
296 && op
->format
== FMT_D6
)
303 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
306 (*info
->memory_error_func
) (status
, memaddr
, info
);
310 insn
|= bfd_getl16 (buffer
);
314 && (op
->opcode
== 0xfaf80000
315 || op
->opcode
== 0xfaf00000
316 || op
->opcode
== 0xfaf40000))
321 && (op
->format
== FMT_D7
322 || op
->format
== FMT_D10
))
329 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
332 (*info
->memory_error_func
) (status
, memaddr
, info
);
336 insn
|= bfd_getl16 (buffer
);
339 else if (size
== 5 && op
->opcode
== 0xdc000000)
341 unsigned long temp
= 0;
342 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
345 (*info
->memory_error_func
) (status
, memaddr
, info
);
348 temp
|= bfd_getl32 (buffer
);
351 insn
|= (temp
& 0xffffff00) >> 8;
352 extension
= temp
& 0xff;
354 else if (size
== 5 && op
->format
== FMT_D3
)
356 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
359 (*info
->memory_error_func
) (status
, memaddr
, info
);
363 insn
|= bfd_getl16 (buffer
);
365 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
368 (*info
->memory_error_func
) (status
, memaddr
, info
);
371 extension
= *(unsigned char *) buffer
;
375 unsigned long temp
= 0;
376 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
379 (*info
->memory_error_func
) (status
, memaddr
, info
);
382 temp
|= bfd_getl16 (buffer
);
387 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
390 (*info
->memory_error_func
) (status
, memaddr
, info
);
393 extension
= *(unsigned char *) buffer
;
395 else if (size
== 6 && op
->format
== FMT_D8
)
398 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 1, info
);
401 (*info
->memory_error_func
) (status
, memaddr
, info
);
404 insn
|= *(unsigned char *) buffer
;
406 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 2, info
);
409 (*info
->memory_error_func
) (status
, memaddr
, info
);
412 extension
= bfd_getl16 (buffer
);
416 unsigned long temp
= 0;
417 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
420 (*info
->memory_error_func
) (status
, memaddr
, info
);
423 temp
|= bfd_getl32 (buffer
);
426 insn
|= (temp
>> 16) & 0xffff;
427 extension
= temp
& 0xffff;
429 else if (size
== 7 && op
->format
== FMT_D9
)
432 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 4, info
);
435 (*info
->memory_error_func
) (status
, memaddr
, info
);
438 extension
= bfd_getl32 (buffer
);
439 insn
|= (extension
& 0xff000000) >> 24;
440 extension
&= 0xffffff;
442 else if (size
== 7 && op
->opcode
== 0xdd000000)
444 unsigned long temp
= 0;
445 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
448 (*info
->memory_error_func
) (status
, memaddr
, info
);
451 temp
|= bfd_getl32 (buffer
);
454 insn
|= (temp
>> 8) & 0xffffff;
455 extension
= (temp
& 0xff) << 16;
457 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 2, info
);
460 (*info
->memory_error_func
) (status
, memaddr
, info
);
463 extension
|= bfd_getb16 (buffer
);
467 unsigned long temp
= 0;
468 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
471 (*info
->memory_error_func
) (status
, memaddr
, info
);
474 temp
|= bfd_getl32 (buffer
);
477 insn
|= (temp
>> 16) & 0xffff;
478 extension
= (temp
& 0xffff) << 8;
480 status
= (*info
->read_memory_func
) (memaddr
+ 6, buffer
, 1, info
);
483 (*info
->memory_error_func
) (status
, memaddr
, info
);
486 extension
|= *(unsigned char *) buffer
;
490 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
492 /* Now print the operands. */
493 for (opindex_ptr
= op
->operands
, nocomma
= 1;
499 operand
= &mn10300_operands
[*opindex_ptr
];
501 /* If this operand is a PLUS (autoincrement), then do not emit
502 a comma before emitting the plus. */
503 if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
506 if ((operand
->flags
& MN10300_OPERAND_SPLIT
) != 0)
509 value
= insn
& ((1 << operand
->bits
) - 1);
510 value
<<= (32 - operand
->bits
);
511 temp
= extension
>> operand
->shift
;
512 temp
&= ((1 << (32 - operand
->bits
)) - 1);
514 value
= ((value
^ (((unsigned long) 1) << 31))
515 - (((unsigned long) 1) << 31));
517 else if ((operand
->flags
& MN10300_OPERAND_24BIT
) != 0)
520 value
= insn
& ((1 << operand
->bits
) - 1);
521 value
<<= (24 - operand
->bits
);
522 temp
= extension
>> operand
->shift
;
523 temp
&= ((1 << (24 - operand
->bits
)) - 1);
525 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0)
526 value
= ((value
& 0xffffff) ^ 0x800000) - 0x800000;
528 else if ((operand
->flags
& (MN10300_OPERAND_FSREG
529 | MN10300_OPERAND_FDREG
)))
531 /* See m10300-opc.c just before #define FSM0 for an
532 explanation of these variables. Note that
533 FMT-implied shifts are not taken into account for
535 unsigned long mask_low
, mask_high
;
536 int shl_low
, shr_high
, shl_high
;
538 switch (operand
->bits
)
541 /* Handle regular FP registers. */
542 if (operand
->shift
>= 0)
544 /* This is an `m' register. */
545 shl_low
= operand
->shift
;
546 shl_high
= 8 + (8 & shl_low
) + (shl_low
& 4) / 4;
550 /* This is an `n' register. */
551 shl_low
= -operand
->shift
;
552 shl_high
= shl_low
/ 4;
560 /* Handle accumulators. */
561 shl_low
= -operand
->shift
;
571 value
= ((((insn
>> shl_high
) << shr_high
) & mask_high
)
572 | ((insn
>> shl_low
) & mask_low
));
574 else if ((operand
->flags
& MN10300_OPERAND_EXTENDED
) != 0)
576 value
= ((extension
>> (operand
->shift
))
577 & ((1 << operand
->bits
) - 1));
581 value
= ((insn
>> (operand
->shift
))
582 & ((1 << operand
->bits
) - 1));
585 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0
586 /* These are properly extended by the code above. */
587 && ((operand
->flags
& MN10300_OPERAND_24BIT
) == 0))
588 value
= ((value
^ (((unsigned long) 1) << (operand
->bits
- 1)))
589 - (((unsigned long) 1) << (operand
->bits
- 1)));
593 || ((operand
->flags
& MN10300_OPERAND_PAREN
) == 0)))
594 (*info
->fprintf_func
) (info
->stream
, ",");
598 if ((operand
->flags
& MN10300_OPERAND_DREG
) != 0)
600 value
= ((insn
>> (operand
->shift
+ extra_shift
))
601 & ((1 << operand
->bits
) - 1));
602 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
);
605 else if ((operand
->flags
& MN10300_OPERAND_AREG
) != 0)
607 value
= ((insn
>> (operand
->shift
+ extra_shift
))
608 & ((1 << operand
->bits
) - 1));
609 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
);
612 else if ((operand
->flags
& MN10300_OPERAND_SP
) != 0)
613 (*info
->fprintf_func
) (info
->stream
, "sp");
615 else if ((operand
->flags
& MN10300_OPERAND_PSW
) != 0)
616 (*info
->fprintf_func
) (info
->stream
, "psw");
618 else if ((operand
->flags
& MN10300_OPERAND_MDR
) != 0)
619 (*info
->fprintf_func
) (info
->stream
, "mdr");
621 else if ((operand
->flags
& MN10300_OPERAND_RREG
) != 0)
623 value
= ((insn
>> (operand
->shift
+ extra_shift
))
624 & ((1 << operand
->bits
) - 1));
626 (*info
->fprintf_func
) (info
->stream
, "r%d", (int) value
);
628 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
- 8);
630 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
- 12);
633 else if ((operand
->flags
& MN10300_OPERAND_XRREG
) != 0)
635 value
= ((insn
>> (operand
->shift
+ extra_shift
))
636 & ((1 << operand
->bits
) - 1));
638 (*info
->fprintf_func
) (info
->stream
, "sp", value
);
640 (*info
->fprintf_func
) (info
->stream
, "xr%d", (int) value
);
643 else if ((operand
->flags
& MN10300_OPERAND_FSREG
) != 0)
644 (*info
->fprintf_func
) (info
->stream
, "fs%d", (int) value
);
646 else if ((operand
->flags
& MN10300_OPERAND_FDREG
) != 0)
647 (*info
->fprintf_func
) (info
->stream
, "fd%d", (int) value
);
649 else if ((operand
->flags
& MN10300_OPERAND_FPCR
) != 0)
650 (*info
->fprintf_func
) (info
->stream
, "fpcr");
652 else if ((operand
->flags
& MN10300_OPERAND_USP
) != 0)
653 (*info
->fprintf_func
) (info
->stream
, "usp");
655 else if ((operand
->flags
& MN10300_OPERAND_SSP
) != 0)
656 (*info
->fprintf_func
) (info
->stream
, "ssp");
658 else if ((operand
->flags
& MN10300_OPERAND_MSP
) != 0)
659 (*info
->fprintf_func
) (info
->stream
, "msp");
661 else if ((operand
->flags
& MN10300_OPERAND_PC
) != 0)
662 (*info
->fprintf_func
) (info
->stream
, "pc");
664 else if ((operand
->flags
& MN10300_OPERAND_EPSW
) != 0)
665 (*info
->fprintf_func
) (info
->stream
, "epsw");
667 else if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
668 (*info
->fprintf_func
) (info
->stream
, "+");
670 else if ((operand
->flags
& MN10300_OPERAND_PAREN
) != 0)
673 (*info
->fprintf_func
) (info
->stream
, ")");
676 (*info
->fprintf_func
) (info
->stream
, "(");
682 else if ((operand
->flags
& MN10300_OPERAND_PCREL
) != 0)
683 (*info
->print_address_func
) ((long) value
+ memaddr
, info
);
685 else if ((operand
->flags
& MN10300_OPERAND_MEMADDR
) != 0)
686 (*info
->print_address_func
) (value
, info
);
688 else if ((operand
->flags
& MN10300_OPERAND_REG_LIST
) != 0)
692 (*info
->fprintf_func
) (info
->stream
, "[");
695 (*info
->fprintf_func
) (info
->stream
, "d2");
702 (*info
->fprintf_func
) (info
->stream
, ",");
703 (*info
->fprintf_func
) (info
->stream
, "d3");
710 (*info
->fprintf_func
) (info
->stream
, ",");
711 (*info
->fprintf_func
) (info
->stream
, "a2");
718 (*info
->fprintf_func
) (info
->stream
, ",");
719 (*info
->fprintf_func
) (info
->stream
, "a3");
726 (*info
->fprintf_func
) (info
->stream
, ",");
727 (*info
->fprintf_func
) (info
->stream
, "other");
734 (*info
->fprintf_func
) (info
->stream
, ",");
735 (*info
->fprintf_func
) (info
->stream
, "exreg0");
741 (*info
->fprintf_func
) (info
->stream
, ",");
742 (*info
->fprintf_func
) (info
->stream
, "exreg1");
748 (*info
->fprintf_func
) (info
->stream
, ",");
749 (*info
->fprintf_func
) (info
->stream
, "exother");
752 (*info
->fprintf_func
) (info
->stream
, "]");
756 (*info
->fprintf_func
) (info
->stream
, "%ld", (long) value
);
766 /* xgettext:c-format */
767 (*info
->fprintf_func
) (info
->stream
, _("unknown\t0x%04x"), insn
);