1 /* Disassemble MN10300 instructions.
2 Copyright (C) 1996-2016 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 "opcode/mn10300.h"
27 #define HAVE_AM33_2 (info->mach == AM33_2)
28 #define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
29 #define HAVE_AM30 (info->mach == AM30)
32 disassemble (bfd_vma memaddr
,
33 struct disassemble_info
*info
,
37 struct mn10300_opcode
*op
= (struct mn10300_opcode
*) mn10300_opcodes
;
38 const struct mn10300_operand
*operand
;
40 unsigned long extension
= 0;
41 int status
, match
= 0;
43 /* Find the opcode. */
46 int mysize
, extra_shift
;
48 if (op
->format
== FMT_S0
)
50 else if (op
->format
== FMT_S1
51 || op
->format
== FMT_D0
)
53 else if (op
->format
== FMT_S2
54 || op
->format
== FMT_D1
)
56 else if (op
->format
== FMT_S4
)
58 else if (op
->format
== FMT_D2
)
60 else if (op
->format
== FMT_D3
)
62 else if (op
->format
== FMT_D4
)
64 else if (op
->format
== FMT_D6
)
66 else if (op
->format
== FMT_D7
|| op
->format
== FMT_D10
)
68 else if (op
->format
== FMT_D8
)
70 else if (op
->format
== FMT_D9
)
75 if ((op
->mask
& insn
) == op
->opcode
76 && size
== (unsigned int) mysize
78 || (op
->machine
== AM33_2
&& HAVE_AM33_2
)
79 || (op
->machine
== AM33
&& HAVE_AM33
)
80 || (op
->machine
== AM30
&& HAVE_AM30
)))
82 const unsigned char *opindex_ptr
;
86 if (op
->format
== FMT_D1
|| op
->format
== FMT_S1
)
88 else if (op
->format
== FMT_D2
|| op
->format
== FMT_D4
89 || op
->format
== FMT_S2
|| op
->format
== FMT_S4
90 || op
->format
== FMT_S6
|| op
->format
== FMT_D5
)
92 else if (op
->format
== FMT_D7
93 || op
->format
== FMT_D8
94 || op
->format
== FMT_D9
)
99 if (size
== 1 || size
== 2)
103 && (op
->format
== FMT_D1
104 || op
->opcode
== 0xdf0000
105 || op
->opcode
== 0xde0000))
109 && op
->format
== FMT_D6
)
115 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
118 (*info
->memory_error_func
) (status
, memaddr
, info
);
122 insn
|= bfd_getl16 (buffer
);
126 && (op
->opcode
== 0xfaf80000
127 || op
->opcode
== 0xfaf00000
128 || op
->opcode
== 0xfaf40000))
132 && (op
->format
== FMT_D7
133 || op
->format
== FMT_D10
))
139 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
142 (*info
->memory_error_func
) (status
, memaddr
, info
);
146 insn
|= bfd_getl16 (buffer
);
149 else if (size
== 5 && op
->opcode
== 0xdc000000)
151 unsigned long temp
= 0;
153 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
156 (*info
->memory_error_func
) (status
, memaddr
, info
);
159 temp
|= bfd_getl32 (buffer
);
162 insn
|= (temp
& 0xffffff00) >> 8;
163 extension
= temp
& 0xff;
165 else if (size
== 5 && op
->format
== FMT_D3
)
167 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
170 (*info
->memory_error_func
) (status
, memaddr
, info
);
174 insn
|= bfd_getl16 (buffer
);
176 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
179 (*info
->memory_error_func
) (status
, memaddr
, info
);
182 extension
= *(unsigned char *) buffer
;
186 unsigned long temp
= 0;
188 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
191 (*info
->memory_error_func
) (status
, memaddr
, info
);
194 temp
|= bfd_getl16 (buffer
);
199 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
202 (*info
->memory_error_func
) (status
, memaddr
, info
);
205 extension
= *(unsigned char *) buffer
;
207 else if (size
== 6 && op
->format
== FMT_D8
)
210 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 1, info
);
213 (*info
->memory_error_func
) (status
, memaddr
, info
);
216 insn
|= *(unsigned char *) buffer
;
218 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 2, info
);
221 (*info
->memory_error_func
) (status
, memaddr
, info
);
224 extension
= bfd_getl16 (buffer
);
228 unsigned long temp
= 0;
230 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
233 (*info
->memory_error_func
) (status
, memaddr
, info
);
236 temp
|= bfd_getl32 (buffer
);
239 insn
|= (temp
>> 16) & 0xffff;
240 extension
= temp
& 0xffff;
242 else if (size
== 7 && op
->format
== FMT_D9
)
245 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 4, info
);
248 (*info
->memory_error_func
) (status
, memaddr
, info
);
251 extension
= bfd_getl32 (buffer
);
252 insn
|= (extension
& 0xff000000) >> 24;
253 extension
&= 0xffffff;
255 else if (size
== 7 && op
->opcode
== 0xdd000000)
257 unsigned long temp
= 0;
259 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
262 (*info
->memory_error_func
) (status
, memaddr
, info
);
265 temp
|= bfd_getl32 (buffer
);
268 insn
|= (temp
>> 8) & 0xffffff;
269 extension
= (temp
& 0xff) << 16;
271 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 2, info
);
274 (*info
->memory_error_func
) (status
, memaddr
, info
);
277 extension
|= bfd_getb16 (buffer
);
281 unsigned long temp
= 0;
283 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
286 (*info
->memory_error_func
) (status
, memaddr
, info
);
289 temp
|= bfd_getl32 (buffer
);
292 insn
|= (temp
>> 16) & 0xffff;
293 extension
= (temp
& 0xffff) << 8;
295 status
= (*info
->read_memory_func
) (memaddr
+ 6, buffer
, 1, info
);
298 (*info
->memory_error_func
) (status
, memaddr
, info
);
301 extension
|= *(unsigned char *) buffer
;
305 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
307 /* Now print the operands. */
308 for (opindex_ptr
= op
->operands
, nocomma
= 1;
314 operand
= &mn10300_operands
[*opindex_ptr
];
316 /* If this operand is a PLUS (autoincrement), then do not emit
317 a comma before emitting the plus. */
318 if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
321 if ((operand
->flags
& MN10300_OPERAND_SPLIT
) != 0)
325 value
= insn
& ((1 << operand
->bits
) - 1);
326 value
<<= (32 - operand
->bits
);
327 temp
= extension
>> operand
->shift
;
328 temp
&= ((1 << (32 - operand
->bits
)) - 1);
330 value
= ((value
^ (((unsigned long) 1) << 31))
331 - (((unsigned long) 1) << 31));
333 else if ((operand
->flags
& MN10300_OPERAND_24BIT
) != 0)
337 value
= insn
& ((1 << operand
->bits
) - 1);
338 value
<<= (24 - operand
->bits
);
339 temp
= extension
>> operand
->shift
;
340 temp
&= ((1 << (24 - operand
->bits
)) - 1);
342 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0)
343 value
= ((value
& 0xffffff) ^ 0x800000) - 0x800000;
345 else if ((operand
->flags
& (MN10300_OPERAND_FSREG
346 | MN10300_OPERAND_FDREG
)))
348 /* See m10300-opc.c just before #define FSM0 for an
349 explanation of these variables. Note that
350 FMT-implied shifts are not taken into account for
352 unsigned long mask_low
, mask_high
;
353 int shl_low
, shr_high
, shl_high
;
355 switch (operand
->bits
)
358 /* Handle regular FP registers. */
359 if (operand
->shift
>= 0)
361 /* This is an `m' register. */
362 shl_low
= operand
->shift
;
363 shl_high
= 8 + (8 & shl_low
) + (shl_low
& 4) / 4;
367 /* This is an `n' register. */
368 shl_low
= -operand
->shift
;
369 shl_high
= shl_low
/ 4;
377 /* Handle accumulators. */
378 shl_low
= -operand
->shift
;
388 value
= ((((insn
>> shl_high
) << shr_high
) & mask_high
)
389 | ((insn
>> shl_low
) & mask_low
));
391 else if ((operand
->flags
& MN10300_OPERAND_EXTENDED
) != 0)
392 value
= ((extension
>> (operand
->shift
))
393 & ((1 << operand
->bits
) - 1));
396 value
= ((insn
>> (operand
->shift
))
397 & ((1 << operand
->bits
) - 1));
399 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0
400 /* These are properly extended by the code above. */
401 && ((operand
->flags
& MN10300_OPERAND_24BIT
) == 0))
402 value
= ((value
^ (((unsigned long) 1) << (operand
->bits
- 1)))
403 - (((unsigned long) 1) << (operand
->bits
- 1)));
407 || ((operand
->flags
& MN10300_OPERAND_PAREN
) == 0)))
408 (*info
->fprintf_func
) (info
->stream
, ",");
412 if ((operand
->flags
& MN10300_OPERAND_DREG
) != 0)
414 value
= ((insn
>> (operand
->shift
+ extra_shift
))
415 & ((1 << operand
->bits
) - 1));
416 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
);
419 else if ((operand
->flags
& MN10300_OPERAND_AREG
) != 0)
421 value
= ((insn
>> (operand
->shift
+ extra_shift
))
422 & ((1 << operand
->bits
) - 1));
423 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
);
426 else if ((operand
->flags
& MN10300_OPERAND_SP
) != 0)
427 (*info
->fprintf_func
) (info
->stream
, "sp");
429 else if ((operand
->flags
& MN10300_OPERAND_PSW
) != 0)
430 (*info
->fprintf_func
) (info
->stream
, "psw");
432 else if ((operand
->flags
& MN10300_OPERAND_MDR
) != 0)
433 (*info
->fprintf_func
) (info
->stream
, "mdr");
435 else if ((operand
->flags
& MN10300_OPERAND_RREG
) != 0)
437 value
= ((insn
>> (operand
->shift
+ extra_shift
))
438 & ((1 << operand
->bits
) - 1));
440 (*info
->fprintf_func
) (info
->stream
, "r%d", (int) value
);
442 (*info
->fprintf_func
) (info
->stream
, "a%d", (int) value
- 8);
444 (*info
->fprintf_func
) (info
->stream
, "d%d", (int) value
- 12);
447 else if ((operand
->flags
& MN10300_OPERAND_XRREG
) != 0)
449 value
= ((insn
>> (operand
->shift
+ extra_shift
))
450 & ((1 << operand
->bits
) - 1));
452 (*info
->fprintf_func
) (info
->stream
, "sp");
454 (*info
->fprintf_func
) (info
->stream
, "xr%d", (int) value
);
457 else if ((operand
->flags
& MN10300_OPERAND_FSREG
) != 0)
458 (*info
->fprintf_func
) (info
->stream
, "fs%d", (int) value
);
460 else if ((operand
->flags
& MN10300_OPERAND_FDREG
) != 0)
461 (*info
->fprintf_func
) (info
->stream
, "fd%d", (int) value
);
463 else if ((operand
->flags
& MN10300_OPERAND_FPCR
) != 0)
464 (*info
->fprintf_func
) (info
->stream
, "fpcr");
466 else if ((operand
->flags
& MN10300_OPERAND_USP
) != 0)
467 (*info
->fprintf_func
) (info
->stream
, "usp");
469 else if ((operand
->flags
& MN10300_OPERAND_SSP
) != 0)
470 (*info
->fprintf_func
) (info
->stream
, "ssp");
472 else if ((operand
->flags
& MN10300_OPERAND_MSP
) != 0)
473 (*info
->fprintf_func
) (info
->stream
, "msp");
475 else if ((operand
->flags
& MN10300_OPERAND_PC
) != 0)
476 (*info
->fprintf_func
) (info
->stream
, "pc");
478 else if ((operand
->flags
& MN10300_OPERAND_EPSW
) != 0)
479 (*info
->fprintf_func
) (info
->stream
, "epsw");
481 else if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
482 (*info
->fprintf_func
) (info
->stream
, "+");
484 else if ((operand
->flags
& MN10300_OPERAND_PAREN
) != 0)
487 (*info
->fprintf_func
) (info
->stream
, ")");
490 (*info
->fprintf_func
) (info
->stream
, "(");
496 else if ((operand
->flags
& MN10300_OPERAND_PCREL
) != 0)
497 (*info
->print_address_func
) ((long) value
+ memaddr
, info
);
499 else if ((operand
->flags
& MN10300_OPERAND_MEMADDR
) != 0)
500 (*info
->print_address_func
) (value
, info
);
502 else if ((operand
->flags
& MN10300_OPERAND_REG_LIST
) != 0)
506 (*info
->fprintf_func
) (info
->stream
, "[");
509 (*info
->fprintf_func
) (info
->stream
, "d2");
516 (*info
->fprintf_func
) (info
->stream
, ",");
517 (*info
->fprintf_func
) (info
->stream
, "d3");
524 (*info
->fprintf_func
) (info
->stream
, ",");
525 (*info
->fprintf_func
) (info
->stream
, "a2");
532 (*info
->fprintf_func
) (info
->stream
, ",");
533 (*info
->fprintf_func
) (info
->stream
, "a3");
540 (*info
->fprintf_func
) (info
->stream
, ",");
541 (*info
->fprintf_func
) (info
->stream
, "other");
548 (*info
->fprintf_func
) (info
->stream
, ",");
549 (*info
->fprintf_func
) (info
->stream
, "exreg0");
555 (*info
->fprintf_func
) (info
->stream
, ",");
556 (*info
->fprintf_func
) (info
->stream
, "exreg1");
562 (*info
->fprintf_func
) (info
->stream
, ",");
563 (*info
->fprintf_func
) (info
->stream
, "exother");
566 (*info
->fprintf_func
) (info
->stream
, "]");
570 (*info
->fprintf_func
) (info
->stream
, "%ld", (long) value
);
579 /* xgettext:c-format */
580 (*info
->fprintf_func
) (info
->stream
, _("unknown\t0x%04lx"), insn
);
584 print_insn_mn10300 (bfd_vma memaddr
, struct disassemble_info
*info
)
589 unsigned int consume
;
591 /* First figure out how big the opcode is. */
592 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 1, info
);
595 (*info
->memory_error_func
) (status
, memaddr
, info
);
598 insn
= *(unsigned char *) buffer
;
600 /* These are one byte insns. */
601 if ((insn
& 0xf3) == 0x00
602 || (insn
& 0xf0) == 0x10
603 || (insn
& 0xfc) == 0x3c
604 || (insn
& 0xf3) == 0x41
605 || (insn
& 0xf3) == 0x40
606 || (insn
& 0xfc) == 0x50
607 || (insn
& 0xfc) == 0x54
608 || (insn
& 0xf0) == 0x60
609 || (insn
& 0xf0) == 0x70
610 || ((insn
& 0xf0) == 0x80
611 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
612 || ((insn
& 0xf0) == 0x90
613 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
614 || ((insn
& 0xf0) == 0xa0
615 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
616 || ((insn
& 0xf0) == 0xb0
617 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
618 || (insn
& 0xff) == 0xcb
619 || (insn
& 0xfc) == 0xd0
620 || (insn
& 0xfc) == 0xd4
621 || (insn
& 0xfc) == 0xd8
622 || (insn
& 0xf0) == 0xe0
623 || (insn
& 0xff) == 0xff)
628 /* These are two byte insns. */
629 else if ((insn
& 0xf0) == 0x80
630 || (insn
& 0xf0) == 0x90
631 || (insn
& 0xf0) == 0xa0
632 || (insn
& 0xf0) == 0xb0
633 || (insn
& 0xfc) == 0x20
634 || (insn
& 0xfc) == 0x28
635 || (insn
& 0xf3) == 0x43
636 || (insn
& 0xf3) == 0x42
637 || (insn
& 0xfc) == 0x58
638 || (insn
& 0xfc) == 0x5c
639 || ((insn
& 0xf0) == 0xc0
640 && (insn
& 0xff) != 0xcb
641 && (insn
& 0xff) != 0xcc
642 && (insn
& 0xff) != 0xcd)
643 || (insn
& 0xff) == 0xf0
644 || (insn
& 0xff) == 0xf1
645 || (insn
& 0xff) == 0xf2
646 || (insn
& 0xff) == 0xf3
647 || (insn
& 0xff) == 0xf4
648 || (insn
& 0xff) == 0xf5
649 || (insn
& 0xff) == 0xf6)
651 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
654 (*info
->memory_error_func
) (status
, memaddr
, info
);
657 insn
= bfd_getb16 (buffer
);
661 /* These are three byte insns. */
662 else if ((insn
& 0xff) == 0xf8
663 || (insn
& 0xff) == 0xcc
664 || (insn
& 0xff) == 0xf9
665 || (insn
& 0xf3) == 0x01
666 || (insn
& 0xf3) == 0x02
667 || (insn
& 0xf3) == 0x03
668 || (insn
& 0xfc) == 0x24
669 || (insn
& 0xfc) == 0x2c
670 || (insn
& 0xfc) == 0x30
671 || (insn
& 0xfc) == 0x34
672 || (insn
& 0xfc) == 0x38
673 || (insn
& 0xff) == 0xde
674 || (insn
& 0xff) == 0xdf
675 || (insn
& 0xff) == 0xf9
676 || (insn
& 0xff) == 0xcc)
678 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
681 (*info
->memory_error_func
) (status
, memaddr
, info
);
684 insn
= bfd_getb16 (buffer
);
686 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 1, info
);
689 (*info
->memory_error_func
) (status
, memaddr
, info
);
692 insn
|= *(unsigned char *) buffer
;
696 /* These are four byte insns. */
697 else if ((insn
& 0xff) == 0xfa
698 || (insn
& 0xff) == 0xf7
699 || (insn
& 0xff) == 0xfb)
701 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
704 (*info
->memory_error_func
) (status
, memaddr
, info
);
707 insn
= bfd_getb32 (buffer
);
711 /* These are five byte insns. */
712 else if ((insn
& 0xff) == 0xcd
713 || (insn
& 0xff) == 0xdc)
715 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
718 (*info
->memory_error_func
) (status
, memaddr
, info
);
721 insn
= bfd_getb32 (buffer
);
725 /* These are six byte insns. */
726 else if ((insn
& 0xff) == 0xfd
727 || (insn
& 0xff) == 0xfc)
729 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
732 (*info
->memory_error_func
) (status
, memaddr
, info
);
736 insn
= bfd_getb32 (buffer
);
740 /* Else its a seven byte insns (in theory). */
743 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
746 (*info
->memory_error_func
) (status
, memaddr
, info
);
750 insn
= bfd_getb32 (buffer
);
752 /* Handle the 5-byte extended instruction codes. */
753 if ((insn
& 0xfff80000) == 0xfe800000)
757 disassemble (memaddr
, info
, insn
, consume
);
This page took 0.055142 seconds and 4 git commands to generate.