* m10300-dis.c (print_insn_mn10300): 0xf7 opcode prefix specifies
[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 "ansidecl.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 int
30 print_insn_mn10300 (memaddr, info)
31 bfd_vma memaddr;
32 struct disassemble_info *info;
33 {
34 int status;
35 bfd_byte buffer[4];
36 unsigned long insn;
37 unsigned int consume;
38
39 /* First figure out how big the opcode is. */
40 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
41 if (status != 0)
42 {
43 (*info->memory_error_func) (status, memaddr, info);
44 return -1;
45 }
46 insn = *(unsigned char *) buffer;
47
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)
72 {
73 consume = 1;
74 }
75
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)
98 {
99 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
100 if (status != 0)
101 {
102 (*info->memory_error_func) (status, memaddr, info);
103 return -1;
104 }
105 insn = bfd_getb16 (buffer);
106 consume = 2;
107 }
108
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)
127 {
128 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
129 if (status != 0)
130 {
131 (*info->memory_error_func) (status, memaddr, info);
132 return -1;
133 }
134 insn = bfd_getb16 (buffer);
135 insn <<= 8;
136 status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
137 if (status != 0)
138 {
139 (*info->memory_error_func) (status, memaddr, info);
140 return -1;
141 }
142 insn |= *(unsigned char *)buffer;
143 consume = 3;
144 }
145
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)
152 {
153 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
154 if (status != 0)
155 {
156 (*info->memory_error_func) (status, memaddr, info);
157 return -1;
158 }
159 insn = bfd_getb32 (buffer);
160 consume = 4;
161 }
162
163 /* These are five byte insns. */
164 else if ((insn & 0xff) == 0xcd
165 || (insn & 0xff) == 0xdc)
166 {
167 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
168 if (status != 0)
169 {
170 (*info->memory_error_func) (status, memaddr, info);
171 return -1;
172 }
173 insn = bfd_getb32 (buffer);
174 consume = 5;
175 }
176
177 /* These are six byte insns. */
178 else if ((insn & 0xff) == 0xfd
179 || (insn & 0xff) == 0xfc)
180 {
181 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
182 if (status != 0)
183 {
184 (*info->memory_error_func) (status, memaddr, info);
185 return -1;
186 }
187
188 insn = bfd_getb32 (buffer);
189 consume = 6;
190 }
191
192 /* Else its a seven byte insns (in theory). */
193 else
194 {
195 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
196 if (status != 0)
197 {
198 (*info->memory_error_func) (status, memaddr, info);
199 return -1;
200 }
201
202 insn = bfd_getb32 (buffer);
203 consume = 7;
204 }
205
206 disassemble (memaddr, info, insn, consume);
207
208 return consume;
209 }
210
211 static void
212 disassemble (memaddr, info, insn, size)
213 bfd_vma memaddr;
214 struct disassemble_info *info;
215 unsigned long insn;
216 unsigned int size;
217 {
218 struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
219 const struct mn10300_operand *operand;
220 bfd_byte buffer[4];
221 unsigned long extension = 0;
222 int status, match = 0;
223
224 /* Find the opcode. */
225 while (op->name)
226 {
227 int mysize, extra_shift;
228
229 if (op->format == FMT_S0)
230 mysize = 1;
231 else if (op->format == FMT_S1
232 || op->format == FMT_D0)
233 mysize = 2;
234 else if (op->format == FMT_S2
235 || op->format == FMT_D1)
236 mysize = 3;
237 else if (op->format == FMT_S4)
238 mysize = 5;
239 else if (op->format == FMT_D2)
240 mysize = 4;
241 else if (op->format == FMT_D4)
242 mysize = 6;
243 /* start-sanitize-am33 */
244 else if (op->format == FMT_D6)
245 mysize = 3;
246 else if (op->format == FMT_D7 || op->format == FMT_D10)
247 mysize = 4;
248 else if (op->format == FMT_D8)
249 mysize = 6;
250 else if (op->format == FMT_D9)
251 mysize = 7;
252 /* end-sanitize-am33 */
253 else
254 mysize = 7;
255
256 if ((op->mask & insn) == op->opcode
257 && size == (unsigned int) mysize)
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 /* start-sanitize-am33 */
270 else if (op->format == FMT_D7
271 || op->format == FMT_D8
272 || op->format == FMT_D9)
273 extra_shift = 8;
274 /* end-sanitize-am33 */
275 else
276 extra_shift = 0;
277
278 if (size == 1 || size == 2)
279 {
280 extension = 0;
281 }
282 else if (size == 3
283 && (op->format == FMT_D1
284 || op->opcode == 0xdf0000
285 || op->opcode == 0xde0000))
286 {
287 extension = 0;
288 }
289 /* start-sanitize-am33 */
290 else if (size == 3
291 && op->format == FMT_D6)
292 {
293 extension = 0;
294 }
295 /* end-sanitize-am33 */
296 else if (size == 3)
297 {
298 insn &= 0xff0000;
299 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
300 if (status != 0)
301 {
302 (*info->memory_error_func) (status, memaddr, info);
303 return;
304 }
305
306 insn |= bfd_getl16 (buffer);
307 extension = 0;
308 }
309 else if (size == 4
310 && (op->opcode == 0xfaf80000
311 || op->opcode == 0xfaf00000
312 || op->opcode == 0xfaf40000))
313 {
314 extension = 0;
315 }
316 /* start-sanitize-am33 */
317 else if (size == 4
318 && (op->format == FMT_D7
319 || op->format == FMT_D10))
320 {
321 extension = 0;
322 }
323 /* end-sanitize-am33 */
324 else if (size == 4)
325 {
326 insn &= 0xffff0000;
327 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
328 if (status != 0)
329 {
330 (*info->memory_error_func) (status, memaddr, info);
331 return;
332 }
333
334 insn |= bfd_getl16 (buffer);
335 extension = 0;
336 }
337 else if (size == 5 && op->opcode == 0xdc000000)
338 {
339 unsigned long temp = 0;
340 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
341 if (status != 0)
342 {
343 (*info->memory_error_func) (status, memaddr, info);
344 return;
345 }
346 temp |= bfd_getl32 (buffer);
347
348 insn &= 0xff000000;
349 insn |= (temp & 0xffffff00) >> 8;
350 extension = temp & 0xff;
351 }
352 else if (size == 5)
353 {
354 unsigned long temp = 0;
355 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
356 if (status != 0)
357 {
358 (*info->memory_error_func) (status, memaddr, info);
359 return;
360 }
361 temp |= bfd_getl16 (buffer);
362
363 insn &= 0xff0000ff;
364 insn |= temp << 8;
365
366 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
367 if (status != 0)
368 {
369 (*info->memory_error_func) (status, memaddr, info);
370 return;
371 }
372 extension = *(unsigned char *)buffer;
373 }
374 /* start-sanitize-am33 */
375 else if (size == 6 && op->format == FMT_D8)
376 {
377 insn &= 0xffffff00;
378 status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
379 if (status != 0)
380 {
381 (*info->memory_error_func) (status, memaddr, info);
382 return;
383 }
384 insn |= *(unsigned char *)buffer;
385
386 status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
387 if (status != 0)
388 {
389 (*info->memory_error_func) (status, memaddr, info);
390 return;
391 }
392 extension = bfd_getl16 (buffer);
393 }
394 /* end-sanitize-am33 */
395 else if (size == 6)
396 {
397 unsigned long temp = 0;
398 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
399 if (status != 0)
400 {
401 (*info->memory_error_func) (status, memaddr, info);
402 return;
403 }
404 temp |= bfd_getl32 (buffer);
405
406 insn &= 0xffff0000;
407 insn |= (temp >> 16) & 0xffff;
408 extension = temp & 0xffff;
409 }
410 /* start-sanitize-am33 */
411 else if (size == 7 && op->format == FMT_D9)
412 {
413 insn &= 0xffffff00;
414 status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
415 if (status != 0)
416 {
417 (*info->memory_error_func) (status, memaddr, info);
418 return;
419 }
420 extension = bfd_getl32 (buffer);
421 insn |= (extension & 0xff000000) >> 24;
422 extension &= 0xffffff;
423 }
424 /* end-sanitize-am33 */
425 else if (size == 7 && op->opcode == 0xdd000000)
426 {
427 unsigned long temp = 0;
428 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
429 if (status != 0)
430 {
431 (*info->memory_error_func) (status, memaddr, info);
432 return;
433 }
434 temp |= bfd_getl32 (buffer);
435
436 insn &= 0xff000000;
437 insn |= (temp >> 8) & 0xffffff;
438 extension = (temp & 0xff) << 16;
439
440 status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
441 if (status != 0)
442 {
443 (*info->memory_error_func) (status, memaddr, info);
444 return;
445 }
446 extension |= bfd_getb16 (buffer);
447 }
448 else if (size == 7)
449 {
450 unsigned long temp = 0;
451 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
452 if (status != 0)
453 {
454 (*info->memory_error_func) (status, memaddr, info);
455 return;
456 }
457 temp |= bfd_getl32 (buffer);
458
459 insn &= 0xffff0000;
460 insn |= (temp >> 16) & 0xffff;
461 extension = (temp & 0xffff) << 8;
462
463 status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
464 if (status != 0)
465 {
466 (*info->memory_error_func) (status, memaddr, info);
467 return;
468 }
469 extension |= *(unsigned char *)buffer;
470 }
471
472 match = 1;
473 (*info->fprintf_func) (info->stream, "%s\t", op->name);
474
475 /* Now print the operands. */
476 for (opindex_ptr = op->operands, nocomma = 1;
477 *opindex_ptr != 0;
478 opindex_ptr++)
479 {
480 unsigned long value;
481
482 operand = &mn10300_operands[*opindex_ptr];
483
484 if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
485 {
486 unsigned long temp;
487 value = insn & ((1 << operand->bits) - 1);
488 value <<= (32 - operand->bits);
489 temp = extension >> operand->shift;
490 temp &= ((1 << (32 - operand->bits)) - 1);
491 value |= temp;
492 }
493 /* start-sanitize-am33 */
494 else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
495 {
496 unsigned long temp;
497 value = insn & ((1 << operand->bits) - 1);
498 value <<= (24 - operand->bits);
499 temp = extension >> operand->shift;
500 temp &= ((1 << (24 - operand->bits)) - 1);
501 value |= temp;
502 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
503 value = ((value & 0xffffff) ^ (~0x7fffff)) + 0x800000;
504 }
505 /* end-sanitize-am33 */
506 else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
507 {
508 value = ((extension >> (operand->shift))
509 & ((1 << operand->bits) - 1));
510 }
511 else
512 {
513 value = ((insn >> (operand->shift))
514 & ((1 << operand->bits) - 1));
515 }
516
517 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
518 /* start-sanitize-am33 */
519 /* These are properly extended by the code above. */
520 && ((operand->flags & MN10300_OPERAND_24BIT) == 0)
521 /* end-sanitize-am33 */
522 )
523 value = ((long)(value << (32 - operand->bits))
524 >> (32 - operand->bits));
525
526 if (!nocomma
527 && (!paren
528 || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
529 (*info->fprintf_func) (info->stream, ",");
530
531 nocomma = 0;
532
533 if ((operand->flags & MN10300_OPERAND_DREG) != 0)
534 {
535 value = ((insn >> (operand->shift + extra_shift))
536 & ((1 << operand->bits) - 1));
537 (*info->fprintf_func) (info->stream, "d%d", value);
538 }
539
540 else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
541 {
542 value = ((insn >> (operand->shift + extra_shift))
543 & ((1 << operand->bits) - 1));
544 (*info->fprintf_func) (info->stream, "a%d", value);
545 }
546
547 else if ((operand->flags & MN10300_OPERAND_SP) != 0)
548 (*info->fprintf_func) (info->stream, "sp");
549
550 else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
551 (*info->fprintf_func) (info->stream, "psw");
552
553 else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
554 (*info->fprintf_func) (info->stream, "mdr");
555
556 /* start-sanitize-am33 */
557 else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
558 {
559 value = ((insn >> (operand->shift + extra_shift))
560 & ((1 << operand->bits) - 1));
561 (*info->fprintf_func) (info->stream, "r%d", value);
562 }
563
564 else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
565 {
566 value = ((insn >> (operand->shift + extra_shift))
567 & ((1 << operand->bits) - 1));
568 (*info->fprintf_func) (info->stream, "xr%d", value);
569 }
570
571 else if ((operand->flags & MN10300_OPERAND_USP) != 0)
572 (*info->fprintf_func) (info->stream, "usp");
573
574 else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
575 (*info->fprintf_func) (info->stream, "ssp");
576
577 else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
578 (*info->fprintf_func) (info->stream, "msp");
579
580 else if ((operand->flags & MN10300_OPERAND_PC) != 0)
581 (*info->fprintf_func) (info->stream, "pc");
582
583 else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
584 (*info->fprintf_func) (info->stream, "epsw");
585
586 else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
587 (*info->fprintf_func) (info->stream, "+");
588 /* end-sanitize-am33 */
589
590 else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
591 {
592 if (paren)
593 (*info->fprintf_func) (info->stream, ")");
594 else
595 {
596 (*info->fprintf_func) (info->stream, "(");
597 nocomma = 1;
598 }
599 paren = !paren;
600 }
601
602 else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
603 (*info->print_address_func) ((long) value + memaddr, info);
604
605 else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
606 (*info->print_address_func) (value, info);
607
608 else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
609 {
610 int comma = 0;
611
612 (*info->fprintf_func) (info->stream, "[");
613 if (value & 0x80)
614 {
615 (*info->fprintf_func) (info->stream, "d2");
616 comma = 1;
617 }
618
619 if (value & 0x40)
620 {
621 if (comma)
622 (*info->fprintf_func) (info->stream, ",");
623 (*info->fprintf_func) (info->stream, "d3");
624 comma = 1;
625 }
626
627 if (value & 0x20)
628 {
629 if (comma)
630 (*info->fprintf_func) (info->stream, ",");
631 (*info->fprintf_func) (info->stream, "a2");
632 comma = 1;
633 }
634
635 if (value & 0x10)
636 {
637 if (comma)
638 (*info->fprintf_func) (info->stream, ",");
639 (*info->fprintf_func) (info->stream, "a3");
640 comma = 1;
641 }
642
643 if (value & 0x08)
644 {
645 if (comma)
646 (*info->fprintf_func) (info->stream, ",");
647 (*info->fprintf_func) (info->stream, "other");
648 comma = 1;
649 }
650
651 /* start-sanitize-am33 */
652 if (value & 0x04)
653 {
654 if (comma)
655 (*info->fprintf_func) (info->stream, ",");
656 (*info->fprintf_func) (info->stream, "exreg0");
657 comma = 1;
658 }
659 if (value & 0x02)
660 {
661 if (comma)
662 (*info->fprintf_func) (info->stream, ",");
663 (*info->fprintf_func) (info->stream, "exreg1");
664 comma = 1;
665 }
666 if (value & 0x01)
667 {
668 if (comma)
669 (*info->fprintf_func) (info->stream, ",");
670 (*info->fprintf_func) (info->stream, "exother");
671 comma = 1;
672 }
673 /* end-sanitize-am33 */
674 (*info->fprintf_func) (info->stream, "]");
675 }
676
677 else
678 (*info->fprintf_func) (info->stream, "%d", value);
679 }
680 /* All done. */
681 break;
682 }
683 op++;
684 }
685
686 if (!match)
687 {
688 /* xgettext:c-format */
689 (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
690 }
691 }
This page took 0.063552 seconds and 5 git commands to generate.