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));
30 print_insn_mn10300 (memaddr
, info
)
32 struct disassemble_info
*info
;
39 /* First figure out how big the opcode is. */
40 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 1, info
);
43 (*info
->memory_error_func
) (status
, memaddr
, info
);
46 insn
= *(unsigned char *) buffer
;
48 /* These are one byte insns. */
49 if ((insn
& 0xf3) == 0x00
50 || (insn
& 0xf0) == 0x10
51 || (insn
& 0xfc) == 0x3c
52 || (insn
& 0xf3) == 0x41
53 || (insn
& 0xf3) == 0x40
54 || (insn
& 0xfc) == 0x50
55 || (insn
& 0xfc) == 0x54
56 || (insn
& 0xf0) == 0x60
57 || (insn
& 0xf0) == 0x70
58 || ((insn
& 0xf0) == 0x80
59 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
60 || ((insn
& 0xf0) == 0x90
61 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
62 || ((insn
& 0xf0) == 0xa0
63 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
64 || ((insn
& 0xf0) == 0xb0
65 && (insn
& 0x0c) >> 2 != (insn
& 0x03))
66 || (insn
& 0xff) == 0xcb
67 || (insn
& 0xfc) == 0xd0
68 || (insn
& 0xfc) == 0xd4
69 || (insn
& 0xfc) == 0xd8
70 || (insn
& 0xf0) == 0xe0
71 || (insn
& 0xff) == 0xff)
76 /* These are two byte insns. */
77 else if ((insn
& 0xf0) == 0x80
78 || (insn
& 0xf0) == 0x90
79 || (insn
& 0xf0) == 0xa0
80 || (insn
& 0xf0) == 0xb0
81 || (insn
& 0xfc) == 0x20
82 || (insn
& 0xfc) == 0x28
83 || (insn
& 0xf3) == 0x43
84 || (insn
& 0xf3) == 0x42
85 || (insn
& 0xfc) == 0x58
86 || (insn
& 0xfc) == 0x5c
87 || ((insn
& 0xf0) == 0xc0
88 && (insn
& 0xff) != 0xcb
89 && (insn
& 0xff) != 0xcc
90 && (insn
& 0xff) != 0xcd)
91 || (insn
& 0xff) == 0xf0
92 || (insn
& 0xff) == 0xf1
93 || (insn
& 0xff) == 0xf2
94 || (insn
& 0xff) == 0xf3
95 || (insn
& 0xff) == 0xf4
96 || (insn
& 0xff) == 0xf5
97 || (insn
& 0xff) == 0xf6)
99 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
102 (*info
->memory_error_func
) (status
, memaddr
, info
);
105 insn
= bfd_getb16 (buffer
);
109 /* These are three byte insns. */
110 else if ((insn
& 0xff) == 0xf8
111 || (insn
& 0xff) == 0xcc
112 || (insn
& 0xff) == 0xf9
113 || (insn
& 0xf3) == 0x01
114 || (insn
& 0xf3) == 0x02
115 || (insn
& 0xf3) == 0x03
116 || (insn
& 0xfc) == 0x24
117 || (insn
& 0xfc) == 0x2c
118 || (insn
& 0xfc) == 0x30
119 || (insn
& 0xfc) == 0x34
120 || (insn
& 0xfc) == 0x38
121 || (insn
& 0xff) == 0xde
122 || (insn
& 0xff) == 0xdf
123 /* start-sanitize-am33 */
124 || (insn
& 0xff) == 0xf9
125 /* end-sanitize-am33 */
126 || (insn
& 0xff) == 0xcc)
128 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
131 (*info
->memory_error_func
) (status
, memaddr
, info
);
134 insn
= bfd_getb16 (buffer
);
136 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 1, info
);
139 (*info
->memory_error_func
) (status
, memaddr
, info
);
142 insn
|= *(unsigned char *)buffer
;
146 /* These are four byte insns. */
147 else if ((insn
& 0xff) == 0xfa
148 /* start-sanitize-am33 */
149 || (insn
& 0xff) == 0xf7
150 /* end-sanitize-am33 */
151 || (insn
& 0xff) == 0xfb)
153 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
156 (*info
->memory_error_func
) (status
, memaddr
, info
);
159 insn
= bfd_getb32 (buffer
);
163 /* These are five byte insns. */
164 else if ((insn
& 0xff) == 0xcd
165 || (insn
& 0xff) == 0xdc)
167 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
170 (*info
->memory_error_func
) (status
, memaddr
, info
);
173 insn
= bfd_getb32 (buffer
);
177 /* These are six byte insns. */
178 else if ((insn
& 0xff) == 0xfd
179 || (insn
& 0xff) == 0xfc)
181 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
184 (*info
->memory_error_func
) (status
, memaddr
, info
);
188 insn
= bfd_getb32 (buffer
);
192 /* Else its a seven byte insns (in theory). */
195 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
198 (*info
->memory_error_func
) (status
, memaddr
, info
);
202 insn
= bfd_getb32 (buffer
);
206 disassemble (memaddr
, info
, insn
, consume
);
212 disassemble (memaddr
, info
, insn
, size
)
214 struct disassemble_info
*info
;
218 struct mn10300_opcode
*op
= (struct mn10300_opcode
*)mn10300_opcodes
;
219 const struct mn10300_operand
*operand
;
221 unsigned long extension
= 0;
222 int status
, match
= 0;
224 /* Find the opcode. */
227 int mysize
, extra_shift
;
229 if (op
->format
== FMT_S0
)
231 else if (op
->format
== FMT_S1
232 || op
->format
== FMT_D0
)
234 else if (op
->format
== FMT_S2
235 || op
->format
== FMT_D1
)
237 else if (op
->format
== FMT_S4
)
239 else if (op
->format
== FMT_D2
)
241 else if (op
->format
== FMT_D4
)
243 /* start-sanitize-am33 */
244 else if (op
->format
== FMT_D6
)
246 else if (op
->format
== FMT_D7
|| op
->format
== FMT_D10
)
248 else if (op
->format
== FMT_D8
)
250 else if (op
->format
== FMT_D9
)
252 /* end-sanitize-am33 */
256 if ((op
->mask
& insn
) == op
->opcode
257 && size
== (unsigned int) mysize
259 || op
->machine
== info
->mach
))
261 const unsigned char *opindex_ptr
;
262 unsigned int nocomma
;
265 if (op
->format
== FMT_D1
|| op
->format
== FMT_S1
)
267 else if (op
->format
== FMT_D2
|| op
->format
== FMT_D4
268 || op
->format
== FMT_S2
|| op
->format
== FMT_S4
269 || op
->format
== FMT_S6
|| op
->format
== FMT_D5
)
271 /* start-sanitize-am33 */
272 else if (op
->format
== FMT_D7
273 || op
->format
== FMT_D8
274 || op
->format
== FMT_D9
)
276 /* end-sanitize-am33 */
280 if (size
== 1 || size
== 2)
285 && (op
->format
== FMT_D1
286 || op
->opcode
== 0xdf0000
287 || op
->opcode
== 0xde0000))
291 /* start-sanitize-am33 */
293 && op
->format
== FMT_D6
)
297 /* end-sanitize-am33 */
301 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
304 (*info
->memory_error_func
) (status
, memaddr
, info
);
308 insn
|= bfd_getl16 (buffer
);
312 && (op
->opcode
== 0xfaf80000
313 || op
->opcode
== 0xfaf00000
314 || op
->opcode
== 0xfaf40000))
318 /* start-sanitize-am33 */
320 && (op
->format
== FMT_D7
321 || op
->format
== FMT_D10
))
325 /* end-sanitize-am33 */
329 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
332 (*info
->memory_error_func
) (status
, memaddr
, info
);
336 insn
|= bfd_getl16 (buffer
);
339 else if (size
== 5 && op
->opcode
== 0xdc000000)
341 unsigned long temp
= 0;
342 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
345 (*info
->memory_error_func
) (status
, memaddr
, info
);
348 temp
|= bfd_getl32 (buffer
);
351 insn
|= (temp
& 0xffffff00) >> 8;
352 extension
= temp
& 0xff;
356 unsigned long temp
= 0;
357 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 2, info
);
360 (*info
->memory_error_func
) (status
, memaddr
, info
);
363 temp
|= bfd_getl16 (buffer
);
368 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 1, info
);
371 (*info
->memory_error_func
) (status
, memaddr
, info
);
374 extension
= *(unsigned char *)buffer
;
376 /* start-sanitize-am33 */
377 else if (size
== 6 && op
->format
== FMT_D8
)
380 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 1, info
);
383 (*info
->memory_error_func
) (status
, memaddr
, info
);
386 insn
|= *(unsigned char *)buffer
;
388 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 2, info
);
391 (*info
->memory_error_func
) (status
, memaddr
, info
);
394 extension
= bfd_getl16 (buffer
);
396 /* end-sanitize-am33 */
399 unsigned long temp
= 0;
400 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
403 (*info
->memory_error_func
) (status
, memaddr
, info
);
406 temp
|= bfd_getl32 (buffer
);
409 insn
|= (temp
>> 16) & 0xffff;
410 extension
= temp
& 0xffff;
412 /* start-sanitize-am33 */
413 else if (size
== 7 && op
->format
== FMT_D9
)
416 status
= (*info
->read_memory_func
) (memaddr
+ 3, buffer
, 4, info
);
419 (*info
->memory_error_func
) (status
, memaddr
, info
);
422 extension
= bfd_getl32 (buffer
);
423 insn
|= (extension
& 0xff000000) >> 24;
424 extension
&= 0xffffff;
426 /* end-sanitize-am33 */
427 else if (size
== 7 && op
->opcode
== 0xdd000000)
429 unsigned long temp
= 0;
430 status
= (*info
->read_memory_func
) (memaddr
+ 1, buffer
, 4, info
);
433 (*info
->memory_error_func
) (status
, memaddr
, info
);
436 temp
|= bfd_getl32 (buffer
);
439 insn
|= (temp
>> 8) & 0xffffff;
440 extension
= (temp
& 0xff) << 16;
442 status
= (*info
->read_memory_func
) (memaddr
+ 5, buffer
, 2, info
);
445 (*info
->memory_error_func
) (status
, memaddr
, info
);
448 extension
|= bfd_getb16 (buffer
);
452 unsigned long temp
= 0;
453 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 4, info
);
456 (*info
->memory_error_func
) (status
, memaddr
, info
);
459 temp
|= bfd_getl32 (buffer
);
462 insn
|= (temp
>> 16) & 0xffff;
463 extension
= (temp
& 0xffff) << 8;
465 status
= (*info
->read_memory_func
) (memaddr
+ 6, buffer
, 1, info
);
468 (*info
->memory_error_func
) (status
, memaddr
, info
);
471 extension
|= *(unsigned char *)buffer
;
475 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
477 /* Now print the operands. */
478 for (opindex_ptr
= op
->operands
, nocomma
= 1;
484 operand
= &mn10300_operands
[*opindex_ptr
];
486 if ((operand
->flags
& MN10300_OPERAND_SPLIT
) != 0)
489 value
= insn
& ((1 << operand
->bits
) - 1);
490 value
<<= (32 - operand
->bits
);
491 temp
= extension
>> operand
->shift
;
492 temp
&= ((1 << (32 - operand
->bits
)) - 1);
495 /* start-sanitize-am33 */
496 else if ((operand
->flags
& MN10300_OPERAND_24BIT
) != 0)
499 value
= insn
& ((1 << operand
->bits
) - 1);
500 value
<<= (24 - operand
->bits
);
501 temp
= extension
>> operand
->shift
;
502 temp
&= ((1 << (24 - operand
->bits
)) - 1);
504 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0)
505 value
= ((value
& 0xffffff) ^ (~0x7fffff)) + 0x800000;
507 /* end-sanitize-am33 */
508 else if ((operand
->flags
& MN10300_OPERAND_EXTENDED
) != 0)
510 value
= ((extension
>> (operand
->shift
))
511 & ((1 << operand
->bits
) - 1));
515 value
= ((insn
>> (operand
->shift
))
516 & ((1 << operand
->bits
) - 1));
519 if ((operand
->flags
& MN10300_OPERAND_SIGNED
) != 0
520 /* start-sanitize-am33 */
521 /* These are properly extended by the code above. */
522 && ((operand
->flags
& MN10300_OPERAND_24BIT
) == 0)
523 /* end-sanitize-am33 */
525 value
= ((long)(value
<< (32 - operand
->bits
))
526 >> (32 - operand
->bits
));
530 || ((operand
->flags
& MN10300_OPERAND_PAREN
) == 0)))
531 (*info
->fprintf_func
) (info
->stream
, ",");
535 if ((operand
->flags
& MN10300_OPERAND_DREG
) != 0)
537 value
= ((insn
>> (operand
->shift
+ extra_shift
))
538 & ((1 << operand
->bits
) - 1));
539 (*info
->fprintf_func
) (info
->stream
, "d%d", value
);
542 else if ((operand
->flags
& MN10300_OPERAND_AREG
) != 0)
544 value
= ((insn
>> (operand
->shift
+ extra_shift
))
545 & ((1 << operand
->bits
) - 1));
546 (*info
->fprintf_func
) (info
->stream
, "a%d", value
);
549 else if ((operand
->flags
& MN10300_OPERAND_SP
) != 0)
550 (*info
->fprintf_func
) (info
->stream
, "sp");
552 else if ((operand
->flags
& MN10300_OPERAND_PSW
) != 0)
553 (*info
->fprintf_func
) (info
->stream
, "psw");
555 else if ((operand
->flags
& MN10300_OPERAND_MDR
) != 0)
556 (*info
->fprintf_func
) (info
->stream
, "mdr");
558 /* start-sanitize-am33 */
559 else if ((operand
->flags
& MN10300_OPERAND_RREG
) != 0)
561 value
= ((insn
>> (operand
->shift
+ extra_shift
))
562 & ((1 << operand
->bits
) - 1));
563 (*info
->fprintf_func
) (info
->stream
, "r%d", value
);
566 else if ((operand
->flags
& MN10300_OPERAND_XRREG
) != 0)
568 value
= ((insn
>> (operand
->shift
+ extra_shift
))
569 & ((1 << operand
->bits
) - 1));
570 (*info
->fprintf_func
) (info
->stream
, "xr%d", value
);
573 else if ((operand
->flags
& MN10300_OPERAND_USP
) != 0)
574 (*info
->fprintf_func
) (info
->stream
, "usp");
576 else if ((operand
->flags
& MN10300_OPERAND_SSP
) != 0)
577 (*info
->fprintf_func
) (info
->stream
, "ssp");
579 else if ((operand
->flags
& MN10300_OPERAND_MSP
) != 0)
580 (*info
->fprintf_func
) (info
->stream
, "msp");
582 else if ((operand
->flags
& MN10300_OPERAND_PC
) != 0)
583 (*info
->fprintf_func
) (info
->stream
, "pc");
585 else if ((operand
->flags
& MN10300_OPERAND_EPSW
) != 0)
586 (*info
->fprintf_func
) (info
->stream
, "epsw");
588 else if ((operand
->flags
& MN10300_OPERAND_PLUS
) != 0)
589 (*info
->fprintf_func
) (info
->stream
, "+");
590 /* end-sanitize-am33 */
592 else if ((operand
->flags
& MN10300_OPERAND_PAREN
) != 0)
595 (*info
->fprintf_func
) (info
->stream
, ")");
598 (*info
->fprintf_func
) (info
->stream
, "(");
604 else if ((operand
->flags
& MN10300_OPERAND_PCREL
) != 0)
605 (*info
->print_address_func
) ((long) value
+ memaddr
, info
);
607 else if ((operand
->flags
& MN10300_OPERAND_MEMADDR
) != 0)
608 (*info
->print_address_func
) (value
, info
);
610 else if ((operand
->flags
& MN10300_OPERAND_REG_LIST
) != 0)
614 (*info
->fprintf_func
) (info
->stream
, "[");
617 (*info
->fprintf_func
) (info
->stream
, "d2");
624 (*info
->fprintf_func
) (info
->stream
, ",");
625 (*info
->fprintf_func
) (info
->stream
, "d3");
632 (*info
->fprintf_func
) (info
->stream
, ",");
633 (*info
->fprintf_func
) (info
->stream
, "a2");
640 (*info
->fprintf_func
) (info
->stream
, ",");
641 (*info
->fprintf_func
) (info
->stream
, "a3");
648 (*info
->fprintf_func
) (info
->stream
, ",");
649 (*info
->fprintf_func
) (info
->stream
, "other");
653 /* start-sanitize-am33 */
657 (*info
->fprintf_func
) (info
->stream
, ",");
658 (*info
->fprintf_func
) (info
->stream
, "exreg0");
664 (*info
->fprintf_func
) (info
->stream
, ",");
665 (*info
->fprintf_func
) (info
->stream
, "exreg1");
671 (*info
->fprintf_func
) (info
->stream
, ",");
672 (*info
->fprintf_func
) (info
->stream
, "exother");
675 /* end-sanitize-am33 */
676 (*info
->fprintf_func
) (info
->stream
, "]");
680 (*info
->fprintf_func
) (info
->stream
, "%d", value
);
690 /* xgettext:c-format */
691 (*info
->fprintf_func
) (info
->stream
, _("unknown\t0x%04x"), insn
);