1 /* Disassemble MN10300 instructions.
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2007, 2012
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. */
24 #include "opcode/mn10300.h"
28 #define HAVE_AM33_2 (info->mach == AM33_2)
29 #define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
30 #define HAVE_AM30 (info->mach == AM30)
33 disassemble (bfd_vma memaddr
,
34 struct disassemble_info
*info
,
38 struct mn10300_opcode
*op
= (struct mn10300_opcode
*) mn10300_opcodes
;
39 const struct mn10300_operand
*operand
;
41 unsigned long extension
= 0;
42 int status
, match
= 0;
44 /* Find the opcode. */
47 int mysize
, extra_shift
;
49 if (op
->format
== FMT_S0
)
51 else if (op
->format
== FMT_S1
52 || op
->format
== FMT_D0
)
54 else if (op
->format
== FMT_S2
55 || op
->format
== FMT_D1
)
57 else if (op
->format
== FMT_S4
)
59 else if (op
->format
== FMT_D2
)
61 else if (op
->format
== FMT_D3
)
63 else if (op
->format
== FMT_D4
)
65 else if (op
->format
== FMT_D6
)
67 else if (op
->format
== FMT_D7
|| op
->format
== FMT_D10
)
69 else if (op
->format
== FMT_D8
)
71 else if (op
->format
== FMT_D9
)
76 if ((op
->mask
& insn
) == op
->opcode
77 && size
== (unsigned int) mysize
79 || (op
->machine
== AM33_2
&& HAVE_AM33_2
)
80 || (op
->machine
== AM33
&& HAVE_AM33
)
81 || (op
->machine
== AM30
&& HAVE_AM30
)))
83 const unsigned char *opindex_ptr
;
87 if (op
->format
== FMT_D1
|| op
->format
== FMT_S1
)
89 else if (op
->format
== FMT_D2
|| op
->format
== FMT_D4
90 || op
->format
== FMT_S2
|| op
->format
== FMT_S4
91 || op
->format
== FMT_S6
|| op
->format
== FMT_D5
)
93 else if (op
->format
== FMT_D7
94 || op
->format
== FMT_D8
95 || op
->format
== FMT_D9
)
100 if (size
== 1 || size
== 2)
104 && (op
->format
== FMT_D1
105 || op
->opcode
== 0xdf0000
106 || op
->opcode
== 0xde0000))
110 && op
->format
== FMT_D6
)
116 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
119 (*info
->memory_error_func
) (status
, memaddr
, info
);
123 insn
|= bfd_getl16 (buffer
);
127 && (op
->opcode
== 0xfaf80000
128 || op
->opcode
== 0xfaf00000
129 || op
->opcode
== 0xfaf40000))
133 && (op
->format
== FMT_D7
134 || op
->format
== FMT_D10
))
140 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
143 (*info
->memory_error_func
) (status
, memaddr
, info
);
147 insn
|= bfd_getl16 (buffer
);
150 else if (size
== 5 && op
->opcode
== 0xdc000000)
152 unsigned long temp
= 0;
154 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
157 (*info
->memory_error_func
) (status
, memaddr
, info
);
160 temp
|= bfd_getl32 (buffer
);
163 insn
|= (temp
& 0xffffff00) >> 8;
164 extension
= temp
& 0xff;
166 else if (size
== 5 && op
->format
== FMT_D3
)
168 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
171 (*info
->memory_error_func
) (status
, memaddr
, info
);
175 insn
|= bfd_getl16 (buffer
);
177 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
180 (*info
->memory_error_func
) (status
, memaddr
, info
);
183 extension
= *(unsigned char *) buffer
;
187 unsigned long temp
= 0;
189 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
192 (*info
->memory_error_func
) (status
, memaddr
, info
);
195 temp
|= bfd_getl16 (buffer
);
200 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
203 (*info
->memory_error_func
) (status
, memaddr
, info
);
206 extension
= *(unsigned char *) buffer
;
208 else if (size
== 6 && op
->format
== FMT_D8
)
211 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 1, info
);
214 (*info
->memory_error_func
) (status
, memaddr
, info
);
217 insn
|= *(unsigned char *) buffer
;
219 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 2, info
);
222 (*info
->memory_error_func
) (status
, memaddr
, info
);
225 extension
= bfd_getl16 (buffer
);
229 unsigned long temp
= 0;
231 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
234 (*info
->memory_error_func
) (status
, memaddr
, info
);
237 temp
|= bfd_getl32 (buffer
);
240 insn
|= (temp
>> 16) & 0xffff;
241 extension
= temp
& 0xffff;
243 else if (size
== 7 && op
->format
== FMT_D9
)
246 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 4, info
);
249 (*info
->memory_error_func
) (status
, memaddr
, info
);
252 extension
= bfd_getl32 (buffer
);
253 insn
|= (extension
& 0xff000000) >> 24;
254 extension
&= 0xffffff;
256 else if (size
== 7 && op
->opcode
== 0xdd000000)
258 unsigned long temp
= 0;
260 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
263 (*info
->memory_error_func
) (status
, memaddr
, info
);
266 temp
|= bfd_getl32 (buffer
);
269 insn
|= (temp
>> 8) & 0xffffff;
270 extension
= (temp
& 0xff) << 16;
272 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 2, info
);
275 (*info
->memory_error_func
) (status
, memaddr
, info
);
278 extension
|= bfd_getb16 (buffer
);
282 unsigned long temp
= 0;
284 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
287 (*info
->memory_error_func
) (status
, memaddr
, info
);
290 temp
|= bfd_getl32 (buffer
);
293 insn
|= (temp
>> 16) & 0xffff;
294 extension
= (temp
& 0xffff) << 8;
296 status
= (*info
->read_memory_func
) (memaddr
+ 6, buffer
, 1, info
);
299 (*info
->memory_error_func
) (status
, memaddr
, info
);
302 extension
|= *(unsigned char *) buffer
;
306 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
308 /* Now print the operands. */
309 for (opindex_ptr
= op
->operands
, nocomma
= 1;
315 operand
= &mn10300_operands
[*opindex_ptr
];
317 /* If this operand is a PLUS (autoincrement), then do not emit
318 a comma before emitting the plus. */
319 if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
322 if ((operand
->flags
& MN10300_OPERAND_SPLIT
) != 0)
326 value
= insn
& ((1 << operand
->bits
) - 1);
327 value
<<= (32 - operand
->bits
);
328 temp
= extension
>> operand
->shift
;
329 temp
&= ((1 << (32 - operand
->bits
)) - 1);
331 value
= ((value
^ (((unsigned long) 1) << 31))
332 - (((unsigned long) 1) << 31));
334 else if ((operand
->flags
& MN10300_OPERAND_24BIT
) != 0)
338 value
= insn
& ((1 << operand
->bits
) - 1);
339 value
<<= (24 - operand
->bits
);
340 temp
= extension
>> operand
->shift
;
341 temp
&= ((1 << (24 - operand
->bits
)) - 1);
343 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0)
344 value
= ((value
& 0xffffff) ^ 0x800000) - 0x800000;
346 else if ((operand
->flags
& (MN10300_OPERAND_FSREG
347 | MN10300_OPERAND_FDREG
)))
349 /* See m10300-opc.c just before #define FSM0 for an
350 explanation of these variables. Note that
351 FMT-implied shifts are not taken into account for
353 unsigned long mask_low
, mask_high
;
354 int shl_low
, shr_high
, shl_high
;
356 switch (operand
->bits
)
359 /* Handle regular FP registers. */
360 if (operand
->shift
>= 0)
362 /* This is an `m' register. */
363 shl_low
= operand
->shift
;
364 shl_high
= 8 + (8 & shl_low
) + (shl_low
& 4) / 4;
368 /* This is an `n' register. */
369 shl_low
= -operand
->shift
;
370 shl_high
= shl_low
/ 4;
378 /* Handle accumulators. */
379 shl_low
= -operand
->shift
;
389 value
= ((((insn
>> shl_high
) << shr_high
) & mask_high
)
390 | ((insn
>> shl_low
) & mask_low
));
392 else if ((operand
->flags
& MN10300_OPERAND_EXTENDED
) != 0)
393 value
= ((extension
>> (operand
->shift
))
394 & ((1 << operand
->bits
) - 1));
397 value
= ((insn
>> (operand
->shift
))
398 & ((1 << operand
->bits
) - 1));
400 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0
401 /* These are properly extended by the code above. */
402 && ((operand
->flags
& MN10300_OPERAND_24BIT
) == 0))
403 value
= ((value
^ (((unsigned long) 1) << (operand
->bits
- 1)))
404 - (((unsigned long) 1) << (operand
->bits
- 1)));
408 || ((operand
->flags
& MN10300_OPERAND_PAREN
) == 0)))
409 (*info
->fprintf_func
) (info
->stream
, ",");
413 if ((operand
->flags
& MN10300_OPERAND_DREG
) != 0)
415 value
= ((insn
>> (operand
->shift
+ extra_shift
))
416 & ((1 << operand
->bits
) - 1));
417 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
);
420 else if ((operand
->flags
& MN10300_OPERAND_AREG
) != 0)
422 value
= ((insn
>> (operand
->shift
+ extra_shift
))
423 & ((1 << operand
->bits
) - 1));
424 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
);
427 else if ((operand
->flags
& MN10300_OPERAND_SP
) != 0)
428 (*info
->fprintf_func
) (info
->stream
, "sp");
430 else if ((operand
->flags
& MN10300_OPERAND_PSW
) != 0)
431 (*info
->fprintf_func
) (info
->stream
, "psw");
433 else if ((operand
->flags
& MN10300_OPERAND_MDR
) != 0)
434 (*info
->fprintf_func
) (info
->stream
, "mdr");
436 else if ((operand
->flags
& MN10300_OPERAND_RREG
) != 0)
438 value
= ((insn
>> (operand
->shift
+ extra_shift
))
439 & ((1 << operand
->bits
) - 1));
441 (*info
->fprintf_func
) (info
->stream
, "r%d", (int) value
);
443 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
- 8);
445 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
- 12);
448 else if ((operand
->flags
& MN10300_OPERAND_XRREG
) != 0)
450 value
= ((insn
>> (operand
->shift
+ extra_shift
))
451 & ((1 << operand
->bits
) - 1));
453 (*info
->fprintf_func
) (info
->stream
, "sp");
455 (*info
->fprintf_func
) (info
->stream
, "xr%d", (int) value
);
458 else if ((operand
->flags
& MN10300_OPERAND_FSREG
) != 0)
459 (*info
->fprintf_func
) (info
->stream
, "fs%d", (int) value
);
461 else if ((operand
->flags
& MN10300_OPERAND_FDREG
) != 0)
462 (*info
->fprintf_func
) (info
->stream
, "fd%d", (int) value
);
464 else if ((operand
->flags
& MN10300_OPERAND_FPCR
) != 0)
465 (*info
->fprintf_func
) (info
->stream
, "fpcr");
467 else if ((operand
->flags
& MN10300_OPERAND_USP
) != 0)
468 (*info
->fprintf_func
) (info
->stream
, "usp");
470 else if ((operand
->flags
& MN10300_OPERAND_SSP
) != 0)
471 (*info
->fprintf_func
) (info
->stream
, "ssp");
473 else if ((operand
->flags
& MN10300_OPERAND_MSP
) != 0)
474 (*info
->fprintf_func
) (info
->stream
, "msp");
476 else if ((operand
->flags
& MN10300_OPERAND_PC
) != 0)
477 (*info
->fprintf_func
) (info
->stream
, "pc");
479 else if ((operand
->flags
& MN10300_OPERAND_EPSW
) != 0)
480 (*info
->fprintf_func
) (info
->stream
, "epsw");
482 else if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
483 (*info
->fprintf_func
) (info
->stream
, "+");
485 else if ((operand
->flags
& MN10300_OPERAND_PAREN
) != 0)
488 (*info
->fprintf_func
) (info
->stream
, ")");
491 (*info
->fprintf_func
) (info
->stream
, "(");
497 else if ((operand
->flags
& MN10300_OPERAND_PCREL
) != 0)
498 (*info
->print_address_func
) ((long) value
+ memaddr
, info
);
500 else if ((operand
->flags
& MN10300_OPERAND_MEMADDR
) != 0)
501 (*info
->print_address_func
) (value
, info
);
503 else if ((operand
->flags
& MN10300_OPERAND_REG_LIST
) != 0)
507 (*info
->fprintf_func
) (info
->stream
, "[");
510 (*info
->fprintf_func
) (info
->stream
, "d2");
517 (*info
->fprintf_func
) (info
->stream
, ",");
518 (*info
->fprintf_func
) (info
->stream
, "d3");
525 (*info
->fprintf_func
) (info
->stream
, ",");
526 (*info
->fprintf_func
) (info
->stream
, "a2");
533 (*info
->fprintf_func
) (info
->stream
, ",");
534 (*info
->fprintf_func
) (info
->stream
, "a3");
541 (*info
->fprintf_func
) (info
->stream
, ",");
542 (*info
->fprintf_func
) (info
->stream
, "other");
549 (*info
->fprintf_func
) (info
->stream
, ",");
550 (*info
->fprintf_func
) (info
->stream
, "exreg0");
556 (*info
->fprintf_func
) (info
->stream
, ",");
557 (*info
->fprintf_func
) (info
->stream
, "exreg1");
563 (*info
->fprintf_func
) (info
->stream
, ",");
564 (*info
->fprintf_func
) (info
->stream
, "exother");
567 (*info
->fprintf_func
) (info
->stream
, "]");
571 (*info
->fprintf_func
) (info
->stream
, "%ld", (long) value
);
580 /* xgettext:c-format */
581 (*info
->fprintf_func
) (info
->stream
, _("unknown\t0x%04lx"), insn
);
585 print_insn_mn10300 (bfd_vma memaddr
, struct disassemble_info
*info
)
590 unsigned int consume
;
592 /* First figure out how big the opcode is. */
593 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 1, info
);
596 (*info
->memory_error_func
) (status
, memaddr
, info
);
599 insn
= *(unsigned char *) buffer
;
601 /* These are one byte insns. */
602 if ((insn
& 0xf3) == 0x00
603 || (insn
& 0xf0) == 0x10
604 || (insn
& 0xfc) == 0x3c
605 || (insn
& 0xf3) == 0x41
606 || (insn
& 0xf3) == 0x40
607 || (insn
& 0xfc) == 0x50
608 || (insn
& 0xfc) == 0x54
609 || (insn
& 0xf0) == 0x60
610 || (insn
& 0xf0) == 0x70
611 || ((insn
& 0xf0) == 0x80
612 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
613 || ((insn
& 0xf0) == 0x90
614 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
615 || ((insn
& 0xf0) == 0xa0
616 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
617 || ((insn
& 0xf0) == 0xb0
618 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
619 || (insn
& 0xff) == 0xcb
620 || (insn
& 0xfc) == 0xd0
621 || (insn
& 0xfc) == 0xd4
622 || (insn
& 0xfc) == 0xd8
623 || (insn
& 0xf0) == 0xe0
624 || (insn
& 0xff) == 0xff)
629 /* These are two byte insns. */
630 else if ((insn
& 0xf0) == 0x80
631 || (insn
& 0xf0) == 0x90
632 || (insn
& 0xf0) == 0xa0
633 || (insn
& 0xf0) == 0xb0
634 || (insn
& 0xfc) == 0x20
635 || (insn
& 0xfc) == 0x28
636 || (insn
& 0xf3) == 0x43
637 || (insn
& 0xf3) == 0x42
638 || (insn
& 0xfc) == 0x58
639 || (insn
& 0xfc) == 0x5c
640 || ((insn
& 0xf0) == 0xc0
641 && (insn
& 0xff) != 0xcb
642 && (insn
& 0xff) != 0xcc
643 && (insn
& 0xff) != 0xcd)
644 || (insn
& 0xff) == 0xf0
645 || (insn
& 0xff) == 0xf1
646 || (insn
& 0xff) == 0xf2
647 || (insn
& 0xff) == 0xf3
648 || (insn
& 0xff) == 0xf4
649 || (insn
& 0xff) == 0xf5
650 || (insn
& 0xff) == 0xf6)
652 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
655 (*info
->memory_error_func
) (status
, memaddr
, info
);
658 insn
= bfd_getb16 (buffer
);
662 /* These are three byte insns. */
663 else if ((insn
& 0xff) == 0xf8
664 || (insn
& 0xff) == 0xcc
665 || (insn
& 0xff) == 0xf9
666 || (insn
& 0xf3) == 0x01
667 || (insn
& 0xf3) == 0x02
668 || (insn
& 0xf3) == 0x03
669 || (insn
& 0xfc) == 0x24
670 || (insn
& 0xfc) == 0x2c
671 || (insn
& 0xfc) == 0x30
672 || (insn
& 0xfc) == 0x34
673 || (insn
& 0xfc) == 0x38
674 || (insn
& 0xff) == 0xde
675 || (insn
& 0xff) == 0xdf
676 || (insn
& 0xff) == 0xf9
677 || (insn
& 0xff) == 0xcc)
679 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
682 (*info
->memory_error_func
) (status
, memaddr
, info
);
685 insn
= bfd_getb16 (buffer
);
687 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 1, info
);
690 (*info
->memory_error_func
) (status
, memaddr
, info
);
693 insn
|= *(unsigned char *) buffer
;
697 /* These are four byte insns. */
698 else if ((insn
& 0xff) == 0xfa
699 || (insn
& 0xff) == 0xf7
700 || (insn
& 0xff) == 0xfb)
702 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
705 (*info
->memory_error_func
) (status
, memaddr
, info
);
708 insn
= bfd_getb32 (buffer
);
712 /* These are five byte insns. */
713 else if ((insn
& 0xff) == 0xcd
714 || (insn
& 0xff) == 0xdc)
716 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
719 (*info
->memory_error_func
) (status
, memaddr
, info
);
722 insn
= bfd_getb32 (buffer
);
726 /* These are six byte insns. */
727 else if ((insn
& 0xff) == 0xfd
728 || (insn
& 0xff) == 0xfc)
730 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
733 (*info
->memory_error_func
) (status
, memaddr
, info
);
737 insn
= bfd_getb32 (buffer
);
741 /* Else its a seven byte insns (in theory). */
744 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
747 (*info
->memory_error_func
) (status
, memaddr
, info
);
751 insn
= bfd_getb32 (buffer
);
753 /* Handle the 5-byte extended instruction codes. */
754 if ((insn
& 0xfff80000) == 0xfe800000)
758 disassemble (memaddr
, info
, insn
, consume
);