* m10300-dis.c (disassemble): Don't assume 32-bit longs when
[deliverable/binutils-gdb.git] / opcodes / m10300-dis.c
1 /* Disassemble MN10300 instructions.
2 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3
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.
8
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.
13
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. */
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
26 static 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
32 int
33 print_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
210 static void
211 disassemble (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 }
This page took 0.061003 seconds and 5 git commands to generate.