1 /* Disassemble MN10300 instructions.
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 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 #include "opcode/mn10300.h"
29 #define HAVE_AM33_2 (info->mach == AM33_2)
30 #define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
31 #define HAVE_AM30 (info->mach == AM30)
34 disassemble (bfd_vma memaddr
,
35 struct disassemble_info
*info
,
39 struct mn10300_opcode
*op
= (struct mn10300_opcode
*) mn10300_opcodes
;
40 const struct mn10300_operand
*operand
;
42 unsigned long extension
= 0;
43 int status
, match
= 0;
45 /* Find the opcode. */
48 int mysize
, extra_shift
;
50 if (op
->format
== FMT_S0
)
52 else if (op
->format
== FMT_S1
53 || op
->format
== FMT_D0
)
55 else if (op
->format
== FMT_S2
56 || op
->format
== FMT_D1
)
58 else if (op
->format
== FMT_S4
)
60 else if (op
->format
== FMT_D2
)
62 else if (op
->format
== FMT_D3
)
64 else if (op
->format
== FMT_D4
)
66 else if (op
->format
== FMT_D6
)
68 else if (op
->format
== FMT_D7
|| op
->format
== FMT_D10
)
70 else if (op
->format
== FMT_D8
)
72 else if (op
->format
== FMT_D9
)
77 if ((op
->mask
& insn
) == op
->opcode
78 && size
== (unsigned int) mysize
80 || (op
->machine
== AM33_2
&& HAVE_AM33_2
)
81 || (op
->machine
== AM33
&& HAVE_AM33
)
82 || (op
->machine
== AM30
&& HAVE_AM30
)))
84 const unsigned char *opindex_ptr
;
88 if (op
->format
== FMT_D1
|| op
->format
== FMT_S1
)
90 else if (op
->format
== FMT_D2
|| op
->format
== FMT_D4
91 || op
->format
== FMT_S2
|| op
->format
== FMT_S4
92 || op
->format
== FMT_S6
|| op
->format
== FMT_D5
)
94 else if (op
->format
== FMT_D7
95 || op
->format
== FMT_D8
96 || op
->format
== FMT_D9
)
101 if (size
== 1 || size
== 2)
105 && (op
->format
== FMT_D1
106 || op
->opcode
== 0xdf0000
107 || op
->opcode
== 0xde0000))
111 && op
->format
== FMT_D6
)
117 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
120 (*info
->memory_error_func
) (status
, memaddr
, info
);
124 insn
|= bfd_getl16 (buffer
);
128 && (op
->opcode
== 0xfaf80000
129 || op
->opcode
== 0xfaf00000
130 || op
->opcode
== 0xfaf40000))
134 && (op
->format
== FMT_D7
135 || op
->format
== FMT_D10
))
141 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
144 (*info
->memory_error_func
) (status
, memaddr
, info
);
148 insn
|= bfd_getl16 (buffer
);
151 else if (size
== 5 && op
->opcode
== 0xdc000000)
153 unsigned long temp
= 0;
155 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
158 (*info
->memory_error_func
) (status
, memaddr
, info
);
161 temp
|= bfd_getl32 (buffer
);
164 insn
|= (temp
& 0xffffff00) >> 8;
165 extension
= temp
& 0xff;
167 else if (size
== 5 && op
->format
== FMT_D3
)
169 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
172 (*info
->memory_error_func
) (status
, memaddr
, info
);
176 insn
|= bfd_getl16 (buffer
);
178 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
181 (*info
->memory_error_func
) (status
, memaddr
, info
);
184 extension
= *(unsigned char *) buffer
;
188 unsigned long temp
= 0;
190 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
193 (*info
->memory_error_func
) (status
, memaddr
, info
);
196 temp
|= bfd_getl16 (buffer
);
201 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
204 (*info
->memory_error_func
) (status
, memaddr
, info
);
207 extension
= *(unsigned char *) buffer
;
209 else if (size
== 6 && op
->format
== FMT_D8
)
212 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 1, info
);
215 (*info
->memory_error_func
) (status
, memaddr
, info
);
218 insn
|= *(unsigned char *) buffer
;
220 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 2, info
);
223 (*info
->memory_error_func
) (status
, memaddr
, info
);
226 extension
= bfd_getl16 (buffer
);
230 unsigned long temp
= 0;
232 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
235 (*info
->memory_error_func
) (status
, memaddr
, info
);
238 temp
|= bfd_getl32 (buffer
);
241 insn
|= (temp
>> 16) & 0xffff;
242 extension
= temp
& 0xffff;
244 else if (size
== 7 && op
->format
== FMT_D9
)
247 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 4, info
);
250 (*info
->memory_error_func
) (status
, memaddr
, info
);
253 extension
= bfd_getl32 (buffer
);
254 insn
|= (extension
& 0xff000000) >> 24;
255 extension
&= 0xffffff;
257 else if (size
== 7 && op
->opcode
== 0xdd000000)
259 unsigned long temp
= 0;
261 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
264 (*info
->memory_error_func
) (status
, memaddr
, info
);
267 temp
|= bfd_getl32 (buffer
);
270 insn
|= (temp
>> 8) & 0xffffff;
271 extension
= (temp
& 0xff) << 16;
273 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 2, info
);
276 (*info
->memory_error_func
) (status
, memaddr
, info
);
279 extension
|= bfd_getb16 (buffer
);
283 unsigned long temp
= 0;
285 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
288 (*info
->memory_error_func
) (status
, memaddr
, info
);
291 temp
|= bfd_getl32 (buffer
);
294 insn
|= (temp
>> 16) & 0xffff;
295 extension
= (temp
& 0xffff) << 8;
297 status
= (*info
->read_memory_func
) (memaddr
+ 6, buffer
, 1, info
);
300 (*info
->memory_error_func
) (status
, memaddr
, info
);
303 extension
|= *(unsigned char *) buffer
;
307 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
309 /* Now print the operands. */
310 for (opindex_ptr
= op
->operands
, nocomma
= 1;
316 operand
= &mn10300_operands
[*opindex_ptr
];
318 /* If this operand is a PLUS (autoincrement), then do not emit
319 a comma before emitting the plus. */
320 if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
323 if ((operand
->flags
& MN10300_OPERAND_SPLIT
) != 0)
327 value
= insn
& ((1 << operand
->bits
) - 1);
328 value
<<= (32 - operand
->bits
);
329 temp
= extension
>> operand
->shift
;
330 temp
&= ((1 << (32 - operand
->bits
)) - 1);
332 value
= ((value
^ (((unsigned long) 1) << 31))
333 - (((unsigned long) 1) << 31));
335 else if ((operand
->flags
& MN10300_OPERAND_24BIT
) != 0)
339 value
= insn
& ((1 << operand
->bits
) - 1);
340 value
<<= (24 - operand
->bits
);
341 temp
= extension
>> operand
->shift
;
342 temp
&= ((1 << (24 - operand
->bits
)) - 1);
344 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0)
345 value
= ((value
& 0xffffff) ^ 0x800000) - 0x800000;
347 else if ((operand
->flags
& (MN10300_OPERAND_FSREG
348 | MN10300_OPERAND_FDREG
)))
350 /* See m10300-opc.c just before #define FSM0 for an
351 explanation of these variables. Note that
352 FMT-implied shifts are not taken into account for
354 unsigned long mask_low
, mask_high
;
355 int shl_low
, shr_high
, shl_high
;
357 switch (operand
->bits
)
360 /* Handle regular FP registers. */
361 if (operand
->shift
>= 0)
363 /* This is an `m' register. */
364 shl_low
= operand
->shift
;
365 shl_high
= 8 + (8 & shl_low
) + (shl_low
& 4) / 4;
369 /* This is an `n' register. */
370 shl_low
= -operand
->shift
;
371 shl_high
= shl_low
/ 4;
379 /* Handle accumulators. */
380 shl_low
= -operand
->shift
;
390 value
= ((((insn
>> shl_high
) << shr_high
) & mask_high
)
391 | ((insn
>> shl_low
) & mask_low
));
393 else if ((operand
->flags
& MN10300_OPERAND_EXTENDED
) != 0)
394 value
= ((extension
>> (operand
->shift
))
395 & ((1 << operand
->bits
) - 1));
398 value
= ((insn
>> (operand
->shift
))
399 & ((1 << operand
->bits
) - 1));
401 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0
402 /* These are properly extended by the code above. */
403 && ((operand
->flags
& MN10300_OPERAND_24BIT
) == 0))
404 value
= ((value
^ (((unsigned long) 1) << (operand
->bits
- 1)))
405 - (((unsigned long) 1) << (operand
->bits
- 1)));
409 || ((operand
->flags
& MN10300_OPERAND_PAREN
) == 0)))
410 (*info
->fprintf_func
) (info
->stream
, ",");
414 if ((operand
->flags
& MN10300_OPERAND_DREG
) != 0)
416 value
= ((insn
>> (operand
->shift
+ extra_shift
))
417 & ((1 << operand
->bits
) - 1));
418 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
);
421 else if ((operand
->flags
& MN10300_OPERAND_AREG
) != 0)
423 value
= ((insn
>> (operand
->shift
+ extra_shift
))
424 & ((1 << operand
->bits
) - 1));
425 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
);
428 else if ((operand
->flags
& MN10300_OPERAND_SP
) != 0)
429 (*info
->fprintf_func
) (info
->stream
, "sp");
431 else if ((operand
->flags
& MN10300_OPERAND_PSW
) != 0)
432 (*info
->fprintf_func
) (info
->stream
, "psw");
434 else if ((operand
->flags
& MN10300_OPERAND_MDR
) != 0)
435 (*info
->fprintf_func
) (info
->stream
, "mdr");
437 else if ((operand
->flags
& MN10300_OPERAND_RREG
) != 0)
439 value
= ((insn
>> (operand
->shift
+ extra_shift
))
440 & ((1 << operand
->bits
) - 1));
442 (*info
->fprintf_func
) (info
->stream
, "r%d", (int) value
);
444 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
- 8);
446 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
- 12);
449 else if ((operand
->flags
& MN10300_OPERAND_XRREG
) != 0)
451 value
= ((insn
>> (operand
->shift
+ extra_shift
))
452 & ((1 << operand
->bits
) - 1));
454 (*info
->fprintf_func
) (info
->stream
, "sp");
456 (*info
->fprintf_func
) (info
->stream
, "xr%d", (int) value
);
459 else if ((operand
->flags
& MN10300_OPERAND_FSREG
) != 0)
460 (*info
->fprintf_func
) (info
->stream
, "fs%d", (int) value
);
462 else if ((operand
->flags
& MN10300_OPERAND_FDREG
) != 0)
463 (*info
->fprintf_func
) (info
->stream
, "fd%d", (int) value
);
465 else if ((operand
->flags
& MN10300_OPERAND_FPCR
) != 0)
466 (*info
->fprintf_func
) (info
->stream
, "fpcr");
468 else if ((operand
->flags
& MN10300_OPERAND_USP
) != 0)
469 (*info
->fprintf_func
) (info
->stream
, "usp");
471 else if ((operand
->flags
& MN10300_OPERAND_SSP
) != 0)
472 (*info
->fprintf_func
) (info
->stream
, "ssp");
474 else if ((operand
->flags
& MN10300_OPERAND_MSP
) != 0)
475 (*info
->fprintf_func
) (info
->stream
, "msp");
477 else if ((operand
->flags
& MN10300_OPERAND_PC
) != 0)
478 (*info
->fprintf_func
) (info
->stream
, "pc");
480 else if ((operand
->flags
& MN10300_OPERAND_EPSW
) != 0)
481 (*info
->fprintf_func
) (info
->stream
, "epsw");
483 else if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
484 (*info
->fprintf_func
) (info
->stream
, "+");
486 else if ((operand
->flags
& MN10300_OPERAND_PAREN
) != 0)
489 (*info
->fprintf_func
) (info
->stream
, ")");
492 (*info
->fprintf_func
) (info
->stream
, "(");
498 else if ((operand
->flags
& MN10300_OPERAND_PCREL
) != 0)
499 (*info
->print_address_func
) ((long) value
+ memaddr
, info
);
501 else if ((operand
->flags
& MN10300_OPERAND_MEMADDR
) != 0)
502 (*info
->print_address_func
) (value
, info
);
504 else if ((operand
->flags
& MN10300_OPERAND_REG_LIST
) != 0)
508 (*info
->fprintf_func
) (info
->stream
, "[");
511 (*info
->fprintf_func
) (info
->stream
, "d2");
518 (*info
->fprintf_func
) (info
->stream
, ",");
519 (*info
->fprintf_func
) (info
->stream
, "d3");
526 (*info
->fprintf_func
) (info
->stream
, ",");
527 (*info
->fprintf_func
) (info
->stream
, "a2");
534 (*info
->fprintf_func
) (info
->stream
, ",");
535 (*info
->fprintf_func
) (info
->stream
, "a3");
542 (*info
->fprintf_func
) (info
->stream
, ",");
543 (*info
->fprintf_func
) (info
->stream
, "other");
550 (*info
->fprintf_func
) (info
->stream
, ",");
551 (*info
->fprintf_func
) (info
->stream
, "exreg0");
557 (*info
->fprintf_func
) (info
->stream
, ",");
558 (*info
->fprintf_func
) (info
->stream
, "exreg1");
564 (*info
->fprintf_func
) (info
->stream
, ",");
565 (*info
->fprintf_func
) (info
->stream
, "exother");
568 (*info
->fprintf_func
) (info
->stream
, "]");
572 (*info
->fprintf_func
) (info
->stream
, "%ld", (long) value
);
581 /* xgettext:c-format */
582 (*info
->fprintf_func
) (info
->stream
, _("unknown\t0x%04lx"), insn
);
586 print_insn_mn10300 (bfd_vma memaddr
, struct disassemble_info
*info
)
591 unsigned int consume
;
593 /* First figure out how big the opcode is. */
594 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 1, info
);
597 (*info
->memory_error_func
) (status
, memaddr
, info
);
600 insn
= *(unsigned char *) buffer
;
602 /* These are one byte insns. */
603 if ((insn
& 0xf3) == 0x00
604 || (insn
& 0xf0) == 0x10
605 || (insn
& 0xfc) == 0x3c
606 || (insn
& 0xf3) == 0x41
607 || (insn
& 0xf3) == 0x40
608 || (insn
& 0xfc) == 0x50
609 || (insn
& 0xfc) == 0x54
610 || (insn
& 0xf0) == 0x60
611 || (insn
& 0xf0) == 0x70
612 || ((insn
& 0xf0) == 0x80
613 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
614 || ((insn
& 0xf0) == 0x90
615 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
616 || ((insn
& 0xf0) == 0xa0
617 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
618 || ((insn
& 0xf0) == 0xb0
619 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
620 || (insn
& 0xff) == 0xcb
621 || (insn
& 0xfc) == 0xd0
622 || (insn
& 0xfc) == 0xd4
623 || (insn
& 0xfc) == 0xd8
624 || (insn
& 0xf0) == 0xe0
625 || (insn
& 0xff) == 0xff)
630 /* These are two byte insns. */
631 else if ((insn
& 0xf0) == 0x80
632 || (insn
& 0xf0) == 0x90
633 || (insn
& 0xf0) == 0xa0
634 || (insn
& 0xf0) == 0xb0
635 || (insn
& 0xfc) == 0x20
636 || (insn
& 0xfc) == 0x28
637 || (insn
& 0xf3) == 0x43
638 || (insn
& 0xf3) == 0x42
639 || (insn
& 0xfc) == 0x58
640 || (insn
& 0xfc) == 0x5c
641 || ((insn
& 0xf0) == 0xc0
642 && (insn
& 0xff) != 0xcb
643 && (insn
& 0xff) != 0xcc
644 && (insn
& 0xff) != 0xcd)
645 || (insn
& 0xff) == 0xf0
646 || (insn
& 0xff) == 0xf1
647 || (insn
& 0xff) == 0xf2
648 || (insn
& 0xff) == 0xf3
649 || (insn
& 0xff) == 0xf4
650 || (insn
& 0xff) == 0xf5
651 || (insn
& 0xff) == 0xf6)
653 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
656 (*info
->memory_error_func
) (status
, memaddr
, info
);
659 insn
= bfd_getb16 (buffer
);
663 /* These are three byte insns. */
664 else if ((insn
& 0xff) == 0xf8
665 || (insn
& 0xff) == 0xcc
666 || (insn
& 0xff) == 0xf9
667 || (insn
& 0xf3) == 0x01
668 || (insn
& 0xf3) == 0x02
669 || (insn
& 0xf3) == 0x03
670 || (insn
& 0xfc) == 0x24
671 || (insn
& 0xfc) == 0x2c
672 || (insn
& 0xfc) == 0x30
673 || (insn
& 0xfc) == 0x34
674 || (insn
& 0xfc) == 0x38
675 || (insn
& 0xff) == 0xde
676 || (insn
& 0xff) == 0xdf
677 || (insn
& 0xff) == 0xf9
678 || (insn
& 0xff) == 0xcc)
680 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
683 (*info
->memory_error_func
) (status
, memaddr
, info
);
686 insn
= bfd_getb16 (buffer
);
688 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 1, info
);
691 (*info
->memory_error_func
) (status
, memaddr
, info
);
694 insn
|= *(unsigned char *) buffer
;
698 /* These are four byte insns. */
699 else if ((insn
& 0xff) == 0xfa
700 || (insn
& 0xff) == 0xf7
701 || (insn
& 0xff) == 0xfb)
703 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
706 (*info
->memory_error_func
) (status
, memaddr
, info
);
709 insn
= bfd_getb32 (buffer
);
713 /* These are five byte insns. */
714 else if ((insn
& 0xff) == 0xcd
715 || (insn
& 0xff) == 0xdc)
717 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
720 (*info
->memory_error_func
) (status
, memaddr
, info
);
723 insn
= bfd_getb32 (buffer
);
727 /* These are six byte insns. */
728 else if ((insn
& 0xff) == 0xfd
729 || (insn
& 0xff) == 0xfc)
731 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
734 (*info
->memory_error_func
) (status
, memaddr
, info
);
738 insn
= bfd_getb32 (buffer
);
742 /* Else its a seven byte insns (in theory). */
745 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
748 (*info
->memory_error_func
) (status
, memaddr
, info
);
752 insn
= bfd_getb32 (buffer
);
754 /* Handle the 5-byte extended instruction codes. */
755 if ((insn
& 0xfff80000) == 0xfe800000)
759 disassemble (memaddr
, info
, insn
, consume
);