1 /* Disassemble MN10300 instructions.
2 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "opcode/mn10300.h"
26 static void disassemble
PARAMS ((bfd_vma
, struct disassemble_info
*,
27 unsigned long insn
, unsigned int));
29 #define HAVE_AM33 (info->mach == AM33)
30 #define HAVE_AM30 (info->mach == AM30)
33 print_insn_mn10300 (memaddr
, info
)
35 struct disassemble_info
*info
;
42 /* First figure out how big the opcode is. */
43 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 1, info
);
46 (*info
->memory_error_func
) (status
, memaddr
, info
);
49 insn
= *(unsigned char *) buffer
;
51 /* These are one byte insns. */
52 if ((insn
& 0xf3) == 0x00
53 || (insn
& 0xf0) == 0x10
54 || (insn
& 0xfc) == 0x3c
55 || (insn
& 0xf3) == 0x41
56 || (insn
& 0xf3) == 0x40
57 || (insn
& 0xfc) == 0x50
58 || (insn
& 0xfc) == 0x54
59 || (insn
& 0xf0) == 0x60
60 || (insn
& 0xf0) == 0x70
61 || ((insn
& 0xf0) == 0x80
62 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
63 || ((insn
& 0xf0) == 0x90
64 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
65 || ((insn
& 0xf0) == 0xa0
66 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
67 || ((insn
& 0xf0) == 0xb0
68 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
69 || (insn
& 0xff) == 0xcb
70 || (insn
& 0xfc) == 0xd0
71 || (insn
& 0xfc) == 0xd4
72 || (insn
& 0xfc) == 0xd8
73 || (insn
& 0xf0) == 0xe0
74 || (insn
& 0xff) == 0xff)
79 /* These are two byte insns. */
80 else if ((insn
& 0xf0) == 0x80
81 || (insn
& 0xf0) == 0x90
82 || (insn
& 0xf0) == 0xa0
83 || (insn
& 0xf0) == 0xb0
84 || (insn
& 0xfc) == 0x20
85 || (insn
& 0xfc) == 0x28
86 || (insn
& 0xf3) == 0x43
87 || (insn
& 0xf3) == 0x42
88 || (insn
& 0xfc) == 0x58
89 || (insn
& 0xfc) == 0x5c
90 || ((insn
& 0xf0) == 0xc0
91 && (insn
& 0xff) != 0xcb
92 && (insn
& 0xff) != 0xcc
93 && (insn
& 0xff) != 0xcd)
94 || (insn
& 0xff) == 0xf0
95 || (insn
& 0xff) == 0xf1
96 || (insn
& 0xff) == 0xf2
97 || (insn
& 0xff) == 0xf3
98 || (insn
& 0xff) == 0xf4
99 || (insn
& 0xff) == 0xf5
100 || (insn
& 0xff) == 0xf6)
102 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
105 (*info
->memory_error_func
) (status
, memaddr
, info
);
108 insn
= bfd_getb16 (buffer
);
112 /* These are three byte insns. */
113 else if ((insn
& 0xff) == 0xf8
114 || (insn
& 0xff) == 0xcc
115 || (insn
& 0xff) == 0xf9
116 || (insn
& 0xf3) == 0x01
117 || (insn
& 0xf3) == 0x02
118 || (insn
& 0xf3) == 0x03
119 || (insn
& 0xfc) == 0x24
120 || (insn
& 0xfc) == 0x2c
121 || (insn
& 0xfc) == 0x30
122 || (insn
& 0xfc) == 0x34
123 || (insn
& 0xfc) == 0x38
124 || (insn
& 0xff) == 0xde
125 || (insn
& 0xff) == 0xdf
126 || (insn
& 0xff) == 0xf9
127 || (insn
& 0xff) == 0xcc)
129 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
132 (*info
->memory_error_func
) (status
, memaddr
, info
);
135 insn
= bfd_getb16 (buffer
);
137 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 1, info
);
140 (*info
->memory_error_func
) (status
, memaddr
, info
);
143 insn
|= *(unsigned char *)buffer
;
147 /* These are four byte insns. */
148 else if ((insn
& 0xff) == 0xfa
149 || (insn
& 0xff) == 0xf7
150 || (insn
& 0xff) == 0xfb)
152 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
155 (*info
->memory_error_func
) (status
, memaddr
, info
);
158 insn
= bfd_getb32 (buffer
);
162 /* These are five byte insns. */
163 else if ((insn
& 0xff) == 0xcd
164 || (insn
& 0xff) == 0xdc)
166 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
169 (*info
->memory_error_func
) (status
, memaddr
, info
);
172 insn
= bfd_getb32 (buffer
);
176 /* These are six byte insns. */
177 else if ((insn
& 0xff) == 0xfd
178 || (insn
& 0xff) == 0xfc)
180 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
183 (*info
->memory_error_func
) (status
, memaddr
, info
);
187 insn
= bfd_getb32 (buffer
);
191 /* Else its a seven byte insns (in theory). */
194 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
197 (*info
->memory_error_func
) (status
, memaddr
, info
);
201 insn
= bfd_getb32 (buffer
);
205 disassemble (memaddr
, info
, insn
, consume
);
211 disassemble (memaddr
, info
, insn
, size
)
213 struct disassemble_info
*info
;
217 struct mn10300_opcode
*op
= (struct mn10300_opcode
*)mn10300_opcodes
;
218 const struct mn10300_operand
*operand
;
220 unsigned long extension
= 0;
221 int status
, match
= 0;
223 /* Find the opcode. */
226 int mysize
, extra_shift
;
228 if (op
->format
== FMT_S0
)
230 else if (op
->format
== FMT_S1
231 || op
->format
== FMT_D0
)
233 else if (op
->format
== FMT_S2
234 || op
->format
== FMT_D1
)
236 else if (op
->format
== FMT_S4
)
238 else if (op
->format
== FMT_D2
)
240 else if (op
->format
== FMT_D4
)
242 else if (op
->format
== FMT_D6
)
244 else if (op
->format
== FMT_D7
|| op
->format
== FMT_D10
)
246 else if (op
->format
== FMT_D8
)
248 else if (op
->format
== FMT_D9
)
253 if ((op
->mask
& insn
) == op
->opcode
254 && size
== (unsigned int) mysize
256 || (op
->machine
== AM33
&& HAVE_AM33
)
257 || (op
->machine
== AM30
&& HAVE_AM30
)))
259 const unsigned char *opindex_ptr
;
260 unsigned int nocomma
;
263 if (op
->format
== FMT_D1
|| op
->format
== FMT_S1
)
265 else if (op
->format
== FMT_D2
|| op
->format
== FMT_D4
266 || op
->format
== FMT_S2
|| op
->format
== FMT_S4
267 || op
->format
== FMT_S6
|| op
->format
== FMT_D5
)
269 else if (op
->format
== FMT_D7
270 || op
->format
== FMT_D8
271 || op
->format
== FMT_D9
)
276 if (size
== 1 || size
== 2)
281 && (op
->format
== FMT_D1
282 || op
->opcode
== 0xdf0000
283 || op
->opcode
== 0xde0000))
288 && op
->format
== FMT_D6
)
295 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
298 (*info
->memory_error_func
) (status
, memaddr
, info
);
302 insn
|= bfd_getl16 (buffer
);
306 && (op
->opcode
== 0xfaf80000
307 || op
->opcode
== 0xfaf00000
308 || op
->opcode
== 0xfaf40000))
313 && (op
->format
== FMT_D7
314 || op
->format
== FMT_D10
))
321 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
324 (*info
->memory_error_func
) (status
, memaddr
, info
);
328 insn
|= bfd_getl16 (buffer
);
331 else if (size
== 5 && op
->opcode
== 0xdc000000)
333 unsigned long temp
= 0;
334 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
337 (*info
->memory_error_func
) (status
, memaddr
, info
);
340 temp
|= bfd_getl32 (buffer
);
343 insn
|= (temp
& 0xffffff00) >> 8;
344 extension
= temp
& 0xff;
348 unsigned long temp
= 0;
349 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
352 (*info
->memory_error_func
) (status
, memaddr
, info
);
355 temp
|= bfd_getl16 (buffer
);
360 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
363 (*info
->memory_error_func
) (status
, memaddr
, info
);
366 extension
= *(unsigned char *)buffer
;
368 else if (size
== 6 && op
->format
== FMT_D8
)
371 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 1, info
);
374 (*info
->memory_error_func
) (status
, memaddr
, info
);
377 insn
|= *(unsigned char *)buffer
;
379 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 2, info
);
382 (*info
->memory_error_func
) (status
, memaddr
, info
);
385 extension
= bfd_getl16 (buffer
);
389 unsigned long temp
= 0;
390 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
393 (*info
->memory_error_func
) (status
, memaddr
, info
);
396 temp
|= bfd_getl32 (buffer
);
399 insn
|= (temp
>> 16) & 0xffff;
400 extension
= temp
& 0xffff;
402 else if (size
== 7 && op
->format
== FMT_D9
)
405 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 4, info
);
408 (*info
->memory_error_func
) (status
, memaddr
, info
);
411 extension
= bfd_getl32 (buffer
);
412 insn
|= (extension
& 0xff000000) >> 24;
413 extension
&= 0xffffff;
415 else if (size
== 7 && op
->opcode
== 0xdd000000)
417 unsigned long temp
= 0;
418 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
421 (*info
->memory_error_func
) (status
, memaddr
, info
);
424 temp
|= bfd_getl32 (buffer
);
427 insn
|= (temp
>> 8) & 0xffffff;
428 extension
= (temp
& 0xff) << 16;
430 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 2, info
);
433 (*info
->memory_error_func
) (status
, memaddr
, info
);
436 extension
|= bfd_getb16 (buffer
);
440 unsigned long temp
= 0;
441 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
444 (*info
->memory_error_func
) (status
, memaddr
, info
);
447 temp
|= bfd_getl32 (buffer
);
450 insn
|= (temp
>> 16) & 0xffff;
451 extension
= (temp
& 0xffff) << 8;
453 status
= (*info
->read_memory_func
) (memaddr
+ 6, buffer
, 1, info
);
456 (*info
->memory_error_func
) (status
, memaddr
, info
);
459 extension
|= *(unsigned char *)buffer
;
463 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
465 /* Now print the operands. */
466 for (opindex_ptr
= op
->operands
, nocomma
= 1;
472 operand
= &mn10300_operands
[*opindex_ptr
];
474 /* If this operand is a PLUS (autoincrement), then do not emit
475 a comma before emitting the plus. */
476 if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
479 if ((operand
->flags
& MN10300_OPERAND_SPLIT
) != 0)
482 value
= insn
& ((1 << operand
->bits
) - 1);
483 value
<<= (32 - operand
->bits
);
484 temp
= extension
>> operand
->shift
;
485 temp
&= ((1 << (32 - operand
->bits
)) - 1);
487 value
= ((value
^ (((unsigned long)1) << 31))
488 - (((unsigned long)1) << 31));
490 else if ((operand
->flags
& MN10300_OPERAND_24BIT
) != 0)
493 value
= insn
& ((1 << operand
->bits
) - 1);
494 value
<<= (24 - operand
->bits
);
495 temp
= extension
>> operand
->shift
;
496 temp
&= ((1 << (24 - operand
->bits
)) - 1);
498 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0)
499 value
= ((value
& 0xffffff) ^ 0x800000) - 0x800000;
501 else if ((operand
->flags
& MN10300_OPERAND_EXTENDED
) != 0)
503 value
= ((extension
>> (operand
->shift
))
504 & ((1 << operand
->bits
) - 1));
508 value
= ((insn
>> (operand
->shift
))
509 & ((1 << operand
->bits
) - 1));
512 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0
513 /* These are properly extended by the code above. */
514 && ((operand
->flags
& MN10300_OPERAND_24BIT
) == 0))
515 value
= ((value
^ (((unsigned long)1) << (operand
->bits
- 1)))
516 - (((unsigned long)1) << (operand
->bits
- 1)));
520 || ((operand
->flags
& MN10300_OPERAND_PAREN
) == 0)))
521 (*info
->fprintf_func
) (info
->stream
, ",");
525 if ((operand
->flags
& MN10300_OPERAND_DREG
) != 0)
527 value
= ((insn
>> (operand
->shift
+ extra_shift
))
528 & ((1 << operand
->bits
) - 1));
529 (*info
->fprintf_func
) (info
->stream
, "d%d", (int)value
);
532 else if ((operand
->flags
& MN10300_OPERAND_AREG
) != 0)
534 value
= ((insn
>> (operand
->shift
+ extra_shift
))
535 & ((1 << operand
->bits
) - 1));
536 (*info
->fprintf_func
) (info
->stream
, "a%d", (int)value
);
539 else if ((operand
->flags
& MN10300_OPERAND_SP
) != 0)
540 (*info
->fprintf_func
) (info
->stream
, "sp");
542 else if ((operand
->flags
& MN10300_OPERAND_PSW
) != 0)
543 (*info
->fprintf_func
) (info
->stream
, "psw");
545 else if ((operand
->flags
& MN10300_OPERAND_MDR
) != 0)
546 (*info
->fprintf_func
) (info
->stream
, "mdr");
548 else if ((operand
->flags
& MN10300_OPERAND_RREG
) != 0)
550 value
= ((insn
>> (operand
->shift
+ extra_shift
))
551 & ((1 << operand
->bits
) - 1));
553 (*info
->fprintf_func
) (info
->stream
, "r%d", (int)value
);
555 (*info
->fprintf_func
) (info
->stream
, "a%d", (int)value
- 8);
557 (*info
->fprintf_func
) (info
->stream
, "d%d", (int)value
- 12);
560 else if ((operand
->flags
& MN10300_OPERAND_XRREG
) != 0)
562 value
= ((insn
>> (operand
->shift
+ extra_shift
))
563 & ((1 << operand
->bits
) - 1));
565 (*info
->fprintf_func
) (info
->stream
, "sp", value
);
567 (*info
->fprintf_func
) (info
->stream
, "xr%d", (int)value
);
570 else if ((operand
->flags
& MN10300_OPERAND_USP
) != 0)
571 (*info
->fprintf_func
) (info
->stream
, "usp");
573 else if ((operand
->flags
& MN10300_OPERAND_SSP
) != 0)
574 (*info
->fprintf_func
) (info
->stream
, "ssp");
576 else if ((operand
->flags
& MN10300_OPERAND_MSP
) != 0)
577 (*info
->fprintf_func
) (info
->stream
, "msp");
579 else if ((operand
->flags
& MN10300_OPERAND_PC
) != 0)
580 (*info
->fprintf_func
) (info
->stream
, "pc");
582 else if ((operand
->flags
& MN10300_OPERAND_EPSW
) != 0)
583 (*info
->fprintf_func
) (info
->stream
, "epsw");
585 else if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
586 (*info
->fprintf_func
) (info
->stream
, "+");
588 else if ((operand
->flags
& MN10300_OPERAND_PAREN
) != 0)
591 (*info
->fprintf_func
) (info
->stream
, ")");
594 (*info
->fprintf_func
) (info
->stream
, "(");
600 else if ((operand
->flags
& MN10300_OPERAND_PCREL
) != 0)
601 (*info
->print_address_func
) ((long) value
+ memaddr
, info
);
603 else if ((operand
->flags
& MN10300_OPERAND_MEMADDR
) != 0)
604 (*info
->print_address_func
) (value
, info
);
606 else if ((operand
->flags
& MN10300_OPERAND_REG_LIST
) != 0)
610 (*info
->fprintf_func
) (info
->stream
, "[");
613 (*info
->fprintf_func
) (info
->stream
, "d2");
620 (*info
->fprintf_func
) (info
->stream
, ",");
621 (*info
->fprintf_func
) (info
->stream
, "d3");
628 (*info
->fprintf_func
) (info
->stream
, ",");
629 (*info
->fprintf_func
) (info
->stream
, "a2");
636 (*info
->fprintf_func
) (info
->stream
, ",");
637 (*info
->fprintf_func
) (info
->stream
, "a3");
644 (*info
->fprintf_func
) (info
->stream
, ",");
645 (*info
->fprintf_func
) (info
->stream
, "other");
652 (*info
->fprintf_func
) (info
->stream
, ",");
653 (*info
->fprintf_func
) (info
->stream
, "exreg0");
659 (*info
->fprintf_func
) (info
->stream
, ",");
660 (*info
->fprintf_func
) (info
->stream
, "exreg1");
666 (*info
->fprintf_func
) (info
->stream
, ",");
667 (*info
->fprintf_func
) (info
->stream
, "exother");
670 (*info
->fprintf_func
) (info
->stream
, "]");
674 (*info
->fprintf_func
) (info
->stream
, "%ld", (long)value
);
684 /* xgettext:c-format */
685 (*info
->fprintf_func
) (info
->stream
, _("unknown\t0x%04x"), insn
);