2008-08-28 Tristan Gingold <gingold@adacore.com>
[binutils.git] / opcodes / m10300-dis.c
blob1ed50f174273727eb0278c9dd42e0c552fa21d81
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)
10 any later version.
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. */
22 #include <stdio.h>
24 #include "sysdep.h"
25 #include "opcode/mn10300.h"
26 #include "dis-asm.h"
27 #include "opintl.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)
33 static void
34 disassemble (bfd_vma memaddr,
35 struct disassemble_info *info,
36 unsigned long insn,
37 unsigned int size)
39 struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
40 const struct mn10300_operand *operand;
41 bfd_byte buffer[4];
42 unsigned long extension = 0;
43 int status, match = 0;
45 /* Find the opcode. */
46 while (op->name)
48 int mysize, extra_shift;
50 if (op->format == FMT_S0)
51 mysize = 1;
52 else if (op->format == FMT_S1
53 || op->format == FMT_D0)
54 mysize = 2;
55 else if (op->format == FMT_S2
56 || op->format == FMT_D1)
57 mysize = 3;
58 else if (op->format == FMT_S4)
59 mysize = 5;
60 else if (op->format == FMT_D2)
61 mysize = 4;
62 else if (op->format == FMT_D3)
63 mysize = 5;
64 else if (op->format == FMT_D4)
65 mysize = 6;
66 else if (op->format == FMT_D6)
67 mysize = 3;
68 else if (op->format == FMT_D7 || op->format == FMT_D10)
69 mysize = 4;
70 else if (op->format == FMT_D8)
71 mysize = 6;
72 else if (op->format == FMT_D9)
73 mysize = 7;
74 else
75 mysize = 7;
77 if ((op->mask & insn) == op->opcode
78 && size == (unsigned int) mysize
79 && (op->machine == 0
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;
85 unsigned int nocomma;
86 int paren = 0;
88 if (op->format == FMT_D1 || op->format == FMT_S1)
89 extra_shift = 8;
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)
93 extra_shift = 16;
94 else if (op->format == FMT_D7
95 || op->format == FMT_D8
96 || op->format == FMT_D9)
97 extra_shift = 8;
98 else
99 extra_shift = 0;
101 if (size == 1 || size == 2)
102 extension = 0;
104 else if (size == 3
105 && (op->format == FMT_D1
106 || op->opcode == 0xdf0000
107 || op->opcode == 0xde0000))
108 extension = 0;
110 else if (size == 3
111 && op->format == FMT_D6)
112 extension = 0;
114 else if (size == 3)
116 insn &= 0xff0000;
117 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
118 if (status != 0)
120 (*info->memory_error_func) (status, memaddr, info);
121 return;
124 insn |= bfd_getl16 (buffer);
125 extension = 0;
127 else if (size == 4
128 && (op->opcode == 0xfaf80000
129 || op->opcode == 0xfaf00000
130 || op->opcode == 0xfaf40000))
131 extension = 0;
133 else if (size == 4
134 && (op->format == FMT_D7
135 || op->format == FMT_D10))
136 extension = 0;
138 else if (size == 4)
140 insn &= 0xffff0000;
141 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
142 if (status != 0)
144 (*info->memory_error_func) (status, memaddr, info);
145 return;
148 insn |= bfd_getl16 (buffer);
149 extension = 0;
151 else if (size == 5 && op->opcode == 0xdc000000)
153 unsigned long temp = 0;
155 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
156 if (status != 0)
158 (*info->memory_error_func) (status, memaddr, info);
159 return;
161 temp |= bfd_getl32 (buffer);
163 insn &= 0xff000000;
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);
170 if (status != 0)
172 (*info->memory_error_func) (status, memaddr, info);
173 return;
175 insn &= 0xffff0000;
176 insn |= bfd_getl16 (buffer);
178 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
179 if (status != 0)
181 (*info->memory_error_func) (status, memaddr, info);
182 return;
184 extension = *(unsigned char *) buffer;
186 else if (size == 5)
188 unsigned long temp = 0;
190 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
191 if (status != 0)
193 (*info->memory_error_func) (status, memaddr, info);
194 return;
196 temp |= bfd_getl16 (buffer);
198 insn &= 0xff0000ff;
199 insn |= temp << 8;
201 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
202 if (status != 0)
204 (*info->memory_error_func) (status, memaddr, info);
205 return;
207 extension = *(unsigned char *) buffer;
209 else if (size == 6 && op->format == FMT_D8)
211 insn &= 0xffffff00;
212 status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
213 if (status != 0)
215 (*info->memory_error_func) (status, memaddr, info);
216 return;
218 insn |= *(unsigned char *) buffer;
220 status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
221 if (status != 0)
223 (*info->memory_error_func) (status, memaddr, info);
224 return;
226 extension = bfd_getl16 (buffer);
228 else if (size == 6)
230 unsigned long temp = 0;
232 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
233 if (status != 0)
235 (*info->memory_error_func) (status, memaddr, info);
236 return;
238 temp |= bfd_getl32 (buffer);
240 insn &= 0xffff0000;
241 insn |= (temp >> 16) & 0xffff;
242 extension = temp & 0xffff;
244 else if (size == 7 && op->format == FMT_D9)
246 insn &= 0xffffff00;
247 status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
248 if (status != 0)
250 (*info->memory_error_func) (status, memaddr, info);
251 return;
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);
262 if (status != 0)
264 (*info->memory_error_func) (status, memaddr, info);
265 return;
267 temp |= bfd_getl32 (buffer);
269 insn &= 0xff000000;
270 insn |= (temp >> 8) & 0xffffff;
271 extension = (temp & 0xff) << 16;
273 status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
274 if (status != 0)
276 (*info->memory_error_func) (status, memaddr, info);
277 return;
279 extension |= bfd_getb16 (buffer);
281 else if (size == 7)
283 unsigned long temp = 0;
285 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
286 if (status != 0)
288 (*info->memory_error_func) (status, memaddr, info);
289 return;
291 temp |= bfd_getl32 (buffer);
293 insn &= 0xffff0000;
294 insn |= (temp >> 16) & 0xffff;
295 extension = (temp & 0xffff) << 8;
297 status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
298 if (status != 0)
300 (*info->memory_error_func) (status, memaddr, info);
301 return;
303 extension |= *(unsigned char *) buffer;
306 match = 1;
307 (*info->fprintf_func) (info->stream, "%s\t", op->name);
309 /* Now print the operands. */
310 for (opindex_ptr = op->operands, nocomma = 1;
311 *opindex_ptr != 0;
312 opindex_ptr++)
314 unsigned long value;
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)
321 nocomma = 1;
323 if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
325 unsigned long temp;
327 value = insn & ((1 << operand->bits) - 1);
328 value <<= (32 - operand->bits);
329 temp = extension >> operand->shift;
330 temp &= ((1 << (32 - operand->bits)) - 1);
331 value |= temp;
332 value = ((value ^ (((unsigned long) 1) << 31))
333 - (((unsigned long) 1) << 31));
335 else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
337 unsigned long temp;
339 value = insn & ((1 << operand->bits) - 1);
340 value <<= (24 - operand->bits);
341 temp = extension >> operand->shift;
342 temp &= ((1 << (24 - operand->bits)) - 1);
343 value |= temp;
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
353 FP registers. */
354 unsigned long mask_low, mask_high;
355 int shl_low, shr_high, shl_high;
357 switch (operand->bits)
359 case 5:
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;
367 else
369 /* This is an `n' register. */
370 shl_low = -operand->shift;
371 shl_high = shl_low / 4;
373 mask_low = 0x0f;
374 mask_high = 0x10;
375 shr_high = 4;
376 break;
378 case 3:
379 /* Handle accumulators. */
380 shl_low = -operand->shift;
381 shl_high = 0;
382 mask_low = 0x03;
383 mask_high = 0x04;
384 shr_high = 2;
385 break;
387 default:
388 abort ();
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));
397 else
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)));
407 if (!nocomma
408 && (!paren
409 || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
410 (*info->fprintf_func) (info->stream, ",");
412 nocomma = 0;
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));
441 if (value < 8)
442 (*info->fprintf_func) (info->stream, "r%d", (int) value);
443 else if (value < 12)
444 (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
445 else
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));
453 if (value == 0)
454 (*info->fprintf_func) (info->stream, "sp");
455 else
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)
488 if (paren)
489 (*info->fprintf_func) (info->stream, ")");
490 else
492 (*info->fprintf_func) (info->stream, "(");
493 nocomma = 1;
495 paren = !paren;
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)
506 int comma = 0;
508 (*info->fprintf_func) (info->stream, "[");
509 if (value & 0x80)
511 (*info->fprintf_func) (info->stream, "d2");
512 comma = 1;
515 if (value & 0x40)
517 if (comma)
518 (*info->fprintf_func) (info->stream, ",");
519 (*info->fprintf_func) (info->stream, "d3");
520 comma = 1;
523 if (value & 0x20)
525 if (comma)
526 (*info->fprintf_func) (info->stream, ",");
527 (*info->fprintf_func) (info->stream, "a2");
528 comma = 1;
531 if (value & 0x10)
533 if (comma)
534 (*info->fprintf_func) (info->stream, ",");
535 (*info->fprintf_func) (info->stream, "a3");
536 comma = 1;
539 if (value & 0x08)
541 if (comma)
542 (*info->fprintf_func) (info->stream, ",");
543 (*info->fprintf_func) (info->stream, "other");
544 comma = 1;
547 if (value & 0x04)
549 if (comma)
550 (*info->fprintf_func) (info->stream, ",");
551 (*info->fprintf_func) (info->stream, "exreg0");
552 comma = 1;
554 if (value & 0x02)
556 if (comma)
557 (*info->fprintf_func) (info->stream, ",");
558 (*info->fprintf_func) (info->stream, "exreg1");
559 comma = 1;
561 if (value & 0x01)
563 if (comma)
564 (*info->fprintf_func) (info->stream, ",");
565 (*info->fprintf_func) (info->stream, "exother");
566 comma = 1;
568 (*info->fprintf_func) (info->stream, "]");
571 else
572 (*info->fprintf_func) (info->stream, "%ld", (long) value);
574 /* All done. */
575 break;
577 op++;
580 if (!match)
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)
588 int status;
589 bfd_byte buffer[4];
590 unsigned long insn;
591 unsigned int consume;
593 /* First figure out how big the opcode is. */
594 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
595 if (status != 0)
597 (*info->memory_error_func) (status, memaddr, info);
598 return -1;
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)
627 consume = 1;
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);
654 if (status != 0)
656 (*info->memory_error_func) (status, memaddr, info);
657 return -1;
659 insn = bfd_getb16 (buffer);
660 consume = 2;
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);
681 if (status != 0)
683 (*info->memory_error_func) (status, memaddr, info);
684 return -1;
686 insn = bfd_getb16 (buffer);
687 insn <<= 8;
688 status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
689 if (status != 0)
691 (*info->memory_error_func) (status, memaddr, info);
692 return -1;
694 insn |= *(unsigned char *) buffer;
695 consume = 3;
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);
704 if (status != 0)
706 (*info->memory_error_func) (status, memaddr, info);
707 return -1;
709 insn = bfd_getb32 (buffer);
710 consume = 4;
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);
718 if (status != 0)
720 (*info->memory_error_func) (status, memaddr, info);
721 return -1;
723 insn = bfd_getb32 (buffer);
724 consume = 5;
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);
732 if (status != 0)
734 (*info->memory_error_func) (status, memaddr, info);
735 return -1;
738 insn = bfd_getb32 (buffer);
739 consume = 6;
742 /* Else its a seven byte insns (in theory). */
743 else
745 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
746 if (status != 0)
748 (*info->memory_error_func) (status, memaddr, info);
749 return -1;
752 insn = bfd_getb32 (buffer);
753 consume = 7;
754 /* Handle the 5-byte extended instruction codes. */
755 if ((insn & 0xfff80000) == 0xfe800000)
756 consume = 5;
759 disassemble (memaddr, info, insn, consume);
761 return consume;