source: trunk/src/binutils/opcodes/m10300-dis.c@ 1489

Last change on this file since 1489 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 18.0 KB
Line 
1/* Disassemble MN10300 instructions.
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18
19#include <stdio.h>
20
21#include "sysdep.h"
22#include "opcode/mn10300.h"
23#include "dis-asm.h"
24#include "opintl.h"
25
26static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
27 unsigned long insn, unsigned int));
28
29#define HAVE_AM33 (info->mach == AM33)
30#define HAVE_AM30 (info->mach == AM30)
31
32int
33print_insn_mn10300 (memaddr, info)
34 bfd_vma memaddr;
35 struct disassemble_info *info;
36{
37 int status;
38 bfd_byte buffer[4];
39 unsigned long insn;
40 unsigned int consume;
41
42 /* First figure out how big the opcode is. */
43 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
44 if (status != 0)
45 {
46 (*info->memory_error_func) (status, memaddr, info);
47 return -1;
48 }
49 insn = *(unsigned char *) buffer;
50
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)
75 {
76 consume = 1;
77 }
78
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)
101 {
102 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
103 if (status != 0)
104 {
105 (*info->memory_error_func) (status, memaddr, info);
106 return -1;
107 }
108 insn = bfd_getb16 (buffer);
109 consume = 2;
110 }
111
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)
128 {
129 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
130 if (status != 0)
131 {
132 (*info->memory_error_func) (status, memaddr, info);
133 return -1;
134 }
135 insn = bfd_getb16 (buffer);
136 insn <<= 8;
137 status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
138 if (status != 0)
139 {
140 (*info->memory_error_func) (status, memaddr, info);
141 return -1;
142 }
143 insn |= *(unsigned char *) buffer;
144 consume = 3;
145 }
146
147 /* These are four byte insns. */
148 else if ((insn & 0xff) == 0xfa
149 || (insn & 0xff) == 0xf7
150 || (insn & 0xff) == 0xfb)
151 {
152 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
153 if (status != 0)
154 {
155 (*info->memory_error_func) (status, memaddr, info);
156 return -1;
157 }
158 insn = bfd_getb32 (buffer);
159 consume = 4;
160 }
161
162 /* These are five byte insns. */
163 else if ((insn & 0xff) == 0xcd
164 || (insn & 0xff) == 0xdc)
165 {
166 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
167 if (status != 0)
168 {
169 (*info->memory_error_func) (status, memaddr, info);
170 return -1;
171 }
172 insn = bfd_getb32 (buffer);
173 consume = 5;
174 }
175
176 /* These are six byte insns. */
177 else if ((insn & 0xff) == 0xfd
178 || (insn & 0xff) == 0xfc)
179 {
180 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
181 if (status != 0)
182 {
183 (*info->memory_error_func) (status, memaddr, info);
184 return -1;
185 }
186
187 insn = bfd_getb32 (buffer);
188 consume = 6;
189 }
190
191 /* Else its a seven byte insns (in theory). */
192 else
193 {
194 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
195 if (status != 0)
196 {
197 (*info->memory_error_func) (status, memaddr, info);
198 return -1;
199 }
200
201 insn = bfd_getb32 (buffer);
202 consume = 7;
203 }
204
205 disassemble (memaddr, info, insn, consume);
206
207 return consume;
208}
209
210static void
211disassemble (memaddr, info, insn, size)
212 bfd_vma memaddr;
213 struct disassemble_info *info;
214 unsigned long insn;
215 unsigned int size;
216{
217 struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
218 const struct mn10300_operand *operand;
219 bfd_byte buffer[4];
220 unsigned long extension = 0;
221 int status, match = 0;
222
223 /* Find the opcode. */
224 while (op->name)
225 {
226 int mysize, extra_shift;
227
228 if (op->format == FMT_S0)
229 mysize = 1;
230 else if (op->format == FMT_S1
231 || op->format == FMT_D0)
232 mysize = 2;
233 else if (op->format == FMT_S2
234 || op->format == FMT_D1)
235 mysize = 3;
236 else if (op->format == FMT_S4)
237 mysize = 5;
238 else if (op->format == FMT_D2)
239 mysize = 4;
240 else if (op->format == FMT_D4)
241 mysize = 6;
242 else if (op->format == FMT_D6)
243 mysize = 3;
244 else if (op->format == FMT_D7 || op->format == FMT_D10)
245 mysize = 4;
246 else if (op->format == FMT_D8)
247 mysize = 6;
248 else if (op->format == FMT_D9)
249 mysize = 7;
250 else
251 mysize = 7;
252
253 if ((op->mask & insn) == op->opcode
254 && size == (unsigned int) mysize
255 && (op->machine == 0
256 || (op->machine == AM33 && HAVE_AM33)
257 || (op->machine == AM30 && HAVE_AM30)))
258 {
259 const unsigned char *opindex_ptr;
260 unsigned int nocomma;
261 int paren = 0;
262
263 if (op->format == FMT_D1 || op->format == FMT_S1)
264 extra_shift = 8;
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)
268 extra_shift = 16;
269 else if (op->format == FMT_D7
270 || op->format == FMT_D8
271 || op->format == FMT_D9)
272 extra_shift = 8;
273 else
274 extra_shift = 0;
275
276 if (size == 1 || size == 2)
277 {
278 extension = 0;
279 }
280 else if (size == 3
281 && (op->format == FMT_D1
282 || op->opcode == 0xdf0000
283 || op->opcode == 0xde0000))
284 {
285 extension = 0;
286 }
287 else if (size == 3
288 && op->format == FMT_D6)
289 {
290 extension = 0;
291 }
292 else if (size == 3)
293 {
294 insn &= 0xff0000;
295 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
296 if (status != 0)
297 {
298 (*info->memory_error_func) (status, memaddr, info);
299 return;
300 }
301
302 insn |= bfd_getl16 (buffer);
303 extension = 0;
304 }
305 else if (size == 4
306 && (op->opcode == 0xfaf80000
307 || op->opcode == 0xfaf00000
308 || op->opcode == 0xfaf40000))
309 {
310 extension = 0;
311 }
312 else if (size == 4
313 && (op->format == FMT_D7
314 || op->format == FMT_D10))
315 {
316 extension = 0;
317 }
318 else if (size == 4)
319 {
320 insn &= 0xffff0000;
321 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
322 if (status != 0)
323 {
324 (*info->memory_error_func) (status, memaddr, info);
325 return;
326 }
327
328 insn |= bfd_getl16 (buffer);
329 extension = 0;
330 }
331 else if (size == 5 && op->opcode == 0xdc000000)
332 {
333 unsigned long temp = 0;
334 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
335 if (status != 0)
336 {
337 (*info->memory_error_func) (status, memaddr, info);
338 return;
339 }
340 temp |= bfd_getl32 (buffer);
341
342 insn &= 0xff000000;
343 insn |= (temp & 0xffffff00) >> 8;
344 extension = temp & 0xff;
345 }
346 else if (size == 5)
347 {
348 unsigned long temp = 0;
349 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
350 if (status != 0)
351 {
352 (*info->memory_error_func) (status, memaddr, info);
353 return;
354 }
355 temp |= bfd_getl16 (buffer);
356
357 insn &= 0xff0000ff;
358 insn |= temp << 8;
359
360 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
361 if (status != 0)
362 {
363 (*info->memory_error_func) (status, memaddr, info);
364 return;
365 }
366 extension = *(unsigned char *) buffer;
367 }
368 else if (size == 6 && op->format == FMT_D8)
369 {
370 insn &= 0xffffff00;
371 status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
372 if (status != 0)
373 {
374 (*info->memory_error_func) (status, memaddr, info);
375 return;
376 }
377 insn |= *(unsigned char *) buffer;
378
379 status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
380 if (status != 0)
381 {
382 (*info->memory_error_func) (status, memaddr, info);
383 return;
384 }
385 extension = bfd_getl16 (buffer);
386 }
387 else if (size == 6)
388 {
389 unsigned long temp = 0;
390 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
391 if (status != 0)
392 {
393 (*info->memory_error_func) (status, memaddr, info);
394 return;
395 }
396 temp |= bfd_getl32 (buffer);
397
398 insn &= 0xffff0000;
399 insn |= (temp >> 16) & 0xffff;
400 extension = temp & 0xffff;
401 }
402 else if (size == 7 && op->format == FMT_D9)
403 {
404 insn &= 0xffffff00;
405 status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
406 if (status != 0)
407 {
408 (*info->memory_error_func) (status, memaddr, info);
409 return;
410 }
411 extension = bfd_getl32 (buffer);
412 insn |= (extension & 0xff000000) >> 24;
413 extension &= 0xffffff;
414 }
415 else if (size == 7 && op->opcode == 0xdd000000)
416 {
417 unsigned long temp = 0;
418 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
419 if (status != 0)
420 {
421 (*info->memory_error_func) (status, memaddr, info);
422 return;
423 }
424 temp |= bfd_getl32 (buffer);
425
426 insn &= 0xff000000;
427 insn |= (temp >> 8) & 0xffffff;
428 extension = (temp & 0xff) << 16;
429
430 status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
431 if (status != 0)
432 {
433 (*info->memory_error_func) (status, memaddr, info);
434 return;
435 }
436 extension |= bfd_getb16 (buffer);
437 }
438 else if (size == 7)
439 {
440 unsigned long temp = 0;
441 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
442 if (status != 0)
443 {
444 (*info->memory_error_func) (status, memaddr, info);
445 return;
446 }
447 temp |= bfd_getl32 (buffer);
448
449 insn &= 0xffff0000;
450 insn |= (temp >> 16) & 0xffff;
451 extension = (temp & 0xffff) << 8;
452
453 status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
454 if (status != 0)
455 {
456 (*info->memory_error_func) (status, memaddr, info);
457 return;
458 }
459 extension |= *(unsigned char *) buffer;
460 }
461
462 match = 1;
463 (*info->fprintf_func) (info->stream, "%s\t", op->name);
464
465 /* Now print the operands. */
466 for (opindex_ptr = op->operands, nocomma = 1;
467 *opindex_ptr != 0;
468 opindex_ptr++)
469 {
470 unsigned long value;
471
472 operand = &mn10300_operands[*opindex_ptr];
473
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)
477 nocomma = 1;
478
479 if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
480 {
481 unsigned long temp;
482 value = insn & ((1 << operand->bits) - 1);
483 value <<= (32 - operand->bits);
484 temp = extension >> operand->shift;
485 temp &= ((1 << (32 - operand->bits)) - 1);
486 value |= temp;
487 value = ((value ^ (((unsigned long) 1) << 31))
488 - (((unsigned long) 1) << 31));
489 }
490 else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
491 {
492 unsigned long temp;
493 value = insn & ((1 << operand->bits) - 1);
494 value <<= (24 - operand->bits);
495 temp = extension >> operand->shift;
496 temp &= ((1 << (24 - operand->bits)) - 1);
497 value |= temp;
498 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
499 value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
500 }
501 else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
502 {
503 value = ((extension >> (operand->shift))
504 & ((1 << operand->bits) - 1));
505 }
506 else
507 {
508 value = ((insn >> (operand->shift))
509 & ((1 << operand->bits) - 1));
510 }
511
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)));
517
518 if (!nocomma
519 && (!paren
520 || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
521 (*info->fprintf_func) (info->stream, ",");
522
523 nocomma = 0;
524
525 if ((operand->flags & MN10300_OPERAND_DREG) != 0)
526 {
527 value = ((insn >> (operand->shift + extra_shift))
528 & ((1 << operand->bits) - 1));
529 (*info->fprintf_func) (info->stream, "d%d", (int) value);
530 }
531
532 else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
533 {
534 value = ((insn >> (operand->shift + extra_shift))
535 & ((1 << operand->bits) - 1));
536 (*info->fprintf_func) (info->stream, "a%d", (int) value);
537 }
538
539 else if ((operand->flags & MN10300_OPERAND_SP) != 0)
540 (*info->fprintf_func) (info->stream, "sp");
541
542 else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
543 (*info->fprintf_func) (info->stream, "psw");
544
545 else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
546 (*info->fprintf_func) (info->stream, "mdr");
547
548 else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
549 {
550 value = ((insn >> (operand->shift + extra_shift))
551 & ((1 << operand->bits) - 1));
552 if (value < 8)
553 (*info->fprintf_func) (info->stream, "r%d", (int) value);
554 else if (value < 12)
555 (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
556 else
557 (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
558 }
559
560 else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
561 {
562 value = ((insn >> (operand->shift + extra_shift))
563 & ((1 << operand->bits) - 1));
564 if (value == 0)
565 (*info->fprintf_func) (info->stream, "sp", value);
566 else
567 (*info->fprintf_func) (info->stream, "xr%d", (int) value);
568 }
569
570 else if ((operand->flags & MN10300_OPERAND_USP) != 0)
571 (*info->fprintf_func) (info->stream, "usp");
572
573 else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
574 (*info->fprintf_func) (info->stream, "ssp");
575
576 else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
577 (*info->fprintf_func) (info->stream, "msp");
578
579 else if ((operand->flags & MN10300_OPERAND_PC) != 0)
580 (*info->fprintf_func) (info->stream, "pc");
581
582 else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
583 (*info->fprintf_func) (info->stream, "epsw");
584
585 else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
586 (*info->fprintf_func) (info->stream, "+");
587
588 else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
589 {
590 if (paren)
591 (*info->fprintf_func) (info->stream, ")");
592 else
593 {
594 (*info->fprintf_func) (info->stream, "(");
595 nocomma = 1;
596 }
597 paren = !paren;
598 }
599
600 else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
601 (*info->print_address_func) ((long) value + memaddr, info);
602
603 else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
604 (*info->print_address_func) (value, info);
605
606 else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
607 {
608 int comma = 0;
609
610 (*info->fprintf_func) (info->stream, "[");
611 if (value & 0x80)
612 {
613 (*info->fprintf_func) (info->stream, "d2");
614 comma = 1;
615 }
616
617 if (value & 0x40)
618 {
619 if (comma)
620 (*info->fprintf_func) (info->stream, ",");
621 (*info->fprintf_func) (info->stream, "d3");
622 comma = 1;
623 }
624
625 if (value & 0x20)
626 {
627 if (comma)
628 (*info->fprintf_func) (info->stream, ",");
629 (*info->fprintf_func) (info->stream, "a2");
630 comma = 1;
631 }
632
633 if (value & 0x10)
634 {
635 if (comma)
636 (*info->fprintf_func) (info->stream, ",");
637 (*info->fprintf_func) (info->stream, "a3");
638 comma = 1;
639 }
640
641 if (value & 0x08)
642 {
643 if (comma)
644 (*info->fprintf_func) (info->stream, ",");
645 (*info->fprintf_func) (info->stream, "other");
646 comma = 1;
647 }
648
649 if (value & 0x04)
650 {
651 if (comma)
652 (*info->fprintf_func) (info->stream, ",");
653 (*info->fprintf_func) (info->stream, "exreg0");
654 comma = 1;
655 }
656 if (value & 0x02)
657 {
658 if (comma)
659 (*info->fprintf_func) (info->stream, ",");
660 (*info->fprintf_func) (info->stream, "exreg1");
661 comma = 1;
662 }
663 if (value & 0x01)
664 {
665 if (comma)
666 (*info->fprintf_func) (info->stream, ",");
667 (*info->fprintf_func) (info->stream, "exother");
668 comma = 1;
669 }
670 (*info->fprintf_func) (info->stream, "]");
671 }
672
673 else
674 (*info->fprintf_func) (info->stream, "%ld", (long) value);
675 }
676 /* All done. */
677 break;
678 }
679 op++;
680 }
681
682 if (!match)
683 {
684 /* xgettext:c-format */
685 (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
686 }
687}
Note: See TracBrowser for help on using the repository browser.