Add mcore target
[deliverable/binutils-gdb.git] / opcodes / arm-dis.c
1 /* Instruction printing code for the ARM
2 Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
3 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4 Modification by James G. Smith (jsmith@cygnus.co.uk)
5
6 This file is part of libopcodes.
7
8 This program is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2 of the License, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "dis-asm.h"
23 #define DEFINE_TABLE
24 #include "arm-opc.h"
25 #include "coff/internal.h"
26 #include "libcoff.h"
27 #include "opintl.h"
28
29 /* FIXME: This shouldn't be done here */
30 #include "elf-bfd.h"
31 #include "elf/internal.h"
32 #include "elf/arm.h"
33
34 static char *arm_conditional[] =
35 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
36 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
37
38 static char *arm_regnames[] =
39 {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
40 "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc"};
41
42 static char *arm_fp_const[] =
43 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
44
45 static char *arm_shift[] =
46 {"lsl", "lsr", "asr", "ror"};
47
48 static int print_insn_arm PARAMS ((bfd_vma, struct disassemble_info *,
49 long));
50
51 static void
52 arm_decode_shift (given, func, stream)
53 long given;
54 fprintf_ftype func;
55 void *stream;
56 {
57 func (stream, "%s", arm_regnames[given & 0xf]);
58 if ((given & 0xff0) != 0)
59 {
60 if ((given & 0x10) == 0)
61 {
62 int amount = (given & 0xf80) >> 7;
63 int shift = (given & 0x60) >> 5;
64 if (amount == 0)
65 {
66 if (shift == 3)
67 {
68 func (stream, ", rrx");
69 return;
70 }
71 amount = 32;
72 }
73 func (stream, ", %s #%d", arm_shift[shift], amount);
74 }
75 else
76 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
77 arm_regnames[(given & 0xf00) >> 8]);
78 }
79 }
80
81 /* Print one instruction from PC on INFO->STREAM.
82 Return the size of the instruction (always 4 on ARM). */
83
84 static int
85 print_insn_arm (pc, info, given)
86 bfd_vma pc;
87 struct disassemble_info *info;
88 long given;
89 {
90 struct arm_opcode * insn;
91 void * stream = info->stream;
92 fprintf_ftype func = info->fprintf_func;
93
94 for (insn = arm_opcodes; insn->assembler; insn++)
95 {
96 if ((given & insn->mask) == insn->value)
97 {
98 char * c;
99
100 for (c = insn->assembler; *c; c++)
101 {
102 if (*c == '%')
103 {
104 switch (*++c)
105 {
106 case '%':
107 func (stream, "%%");
108 break;
109
110 case 'a':
111 if (((given & 0x000f0000) == 0x000f0000)
112 && ((given & 0x02000000) == 0))
113 {
114 int offset = given & 0xfff;
115
116 func (stream, "[pc");
117
118 if (given & 0x01000000)
119 {
120 if ((given & 0x00800000) == 0)
121 offset = - offset;
122
123 /* pre-indexed */
124 func (stream, ", #%x]", offset);
125
126 offset += pc + 8;
127
128 /* Cope with the possibility of write-back being used.
129 Probably a very dangerous thing for the programmer
130 to do, but who are we to argue ? */
131 if (given & 0x00200000)
132 func (stream, "!");
133 }
134 else
135 {
136 /* post indexed */
137 func (stream, "], #%x", offset);
138
139 offset = pc + 8; /* ie ignore the offset */
140 }
141
142 func (stream, "\t; ");
143 info->print_address_func (offset, info);
144 }
145 else
146 {
147 func (stream, "[%s",
148 arm_regnames[(given >> 16) & 0xf]);
149 if ((given & 0x01000000) != 0)
150 {
151 if ((given & 0x02000000) == 0)
152 {
153 int offset = given & 0xfff;
154 if (offset)
155 func (stream, ", %s#%d",
156 (((given & 0x00800000) == 0)
157 ? "-" : ""), offset);
158 }
159 else
160 {
161 func (stream, ", %s",
162 (((given & 0x00800000) == 0)
163 ? "-" : ""));
164 arm_decode_shift (given, func, stream);
165 }
166
167 func (stream, "]%s",
168 ((given & 0x00200000) != 0) ? "!" : "");
169 }
170 else
171 {
172 if ((given & 0x02000000) == 0)
173 {
174 int offset = given & 0xfff;
175 if (offset)
176 func (stream, "], %s#%d",
177 (((given & 0x00800000) == 0)
178 ? "-" : ""), offset);
179 else
180 func (stream, "]");
181 }
182 else
183 {
184 func (stream, "], %s",
185 (((given & 0x00800000) == 0)
186 ? "-" : ""));
187 arm_decode_shift (given, func, stream);
188 }
189 }
190 }
191 break;
192
193 case 's':
194 if ((given & 0x004f0000) == 0x004f0000)
195 {
196 /* PC relative with immediate offset */
197 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
198
199 if ((given & 0x00800000) == 0)
200 offset = -offset;
201
202 func (stream, "[pc, #%x]\t; ", offset);
203
204 (*info->print_address_func)
205 (offset + pc + 8, info);
206 }
207 else
208 {
209 func (stream, "[%s",
210 arm_regnames[(given >> 16) & 0xf]);
211 if ((given & 0x01000000) != 0)
212 {
213 /* pre-indexed */
214 if ((given & 0x00400000) == 0x00400000)
215 {
216 /* immediate */
217 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
218 if (offset)
219 func (stream, ", %s#%d",
220 (((given & 0x00800000) == 0)
221 ? "-" : ""), offset);
222 }
223 else
224 {
225 /* register */
226 func (stream, ", %s%s",
227 (((given & 0x00800000) == 0)
228 ? "-" : ""),
229 arm_regnames[given & 0xf]);
230 }
231
232 func (stream, "]%s",
233 ((given & 0x00200000) != 0) ? "!" : "");
234 }
235 else
236 {
237 /* post-indexed */
238 if ((given & 0x00400000) == 0x00400000)
239 {
240 /* immediate */
241 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
242 if (offset)
243 func (stream, "], %s#%d",
244 (((given & 0x00800000) == 0)
245 ? "-" : ""), offset);
246 else
247 func (stream, "]");
248 }
249 else
250 {
251 /* register */
252 func (stream, "], %s%s",
253 (((given & 0x00800000) == 0)
254 ? "-" : ""),
255 arm_regnames[given & 0xf]);
256 }
257 }
258 }
259 break;
260
261 case 'b':
262 (*info->print_address_func)
263 (BDISP (given) * 4 + pc + 8, info);
264 break;
265
266 case 'c':
267 func (stream, "%s",
268 arm_conditional [(given >> 28) & 0xf]);
269 break;
270
271 case 'm':
272 {
273 int started = 0;
274 int reg;
275
276 func (stream, "{");
277 for (reg = 0; reg < 16; reg++)
278 if ((given & (1 << reg)) != 0)
279 {
280 if (started)
281 func (stream, ", ");
282 started = 1;
283 func (stream, "%s", arm_regnames[reg]);
284 }
285 func (stream, "}");
286 }
287 break;
288
289 case 'o':
290 if ((given & 0x02000000) != 0)
291 {
292 int rotate = (given & 0xf00) >> 7;
293 int immed = (given & 0xff);
294 func (stream, "#%d",
295 ((immed << (32 - rotate))
296 | (immed >> rotate)) & 0xffffffff);
297 }
298 else
299 arm_decode_shift (given, func, stream);
300 break;
301
302 case 'p':
303 if ((given & 0x0000f000) == 0x0000f000)
304 func (stream, "p");
305 break;
306
307 case 't':
308 if ((given & 0x01200000) == 0x00200000)
309 func (stream, "t");
310 break;
311
312 case 'h':
313 if ((given & 0x00000020) == 0x00000020)
314 func (stream, "h");
315 else
316 func (stream, "b");
317 break;
318
319 case 'A':
320 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
321 if ((given & 0x01000000) != 0)
322 {
323 int offset = given & 0xff;
324 if (offset)
325 func (stream, ", %s#%d]%s",
326 ((given & 0x00800000) == 0 ? "-" : ""),
327 offset * 4,
328 ((given & 0x00200000) != 0 ? "!" : ""));
329 else
330 func (stream, "]");
331 }
332 else
333 {
334 int offset = given & 0xff;
335 if (offset)
336 func (stream, "], %s#%d",
337 ((given & 0x00800000) == 0 ? "-" : ""),
338 offset * 4);
339 else
340 func (stream, "]");
341 }
342 break;
343
344 case 'C':
345 switch (given & 0x00090000)
346 {
347 default:
348 func (stream, "_???");
349 break;
350 case 0x90000:
351 func (stream, "_all");
352 break;
353 case 0x10000:
354 func (stream, "_ctl");
355 break;
356 case 0x80000:
357 func (stream, "_flg");
358 break;
359 }
360 break;
361
362 case 'F':
363 switch (given & 0x00408000)
364 {
365 case 0:
366 func (stream, "4");
367 break;
368 case 0x8000:
369 func (stream, "1");
370 break;
371 case 0x00400000:
372 func (stream, "2");
373 break;
374 default:
375 func (stream, "3");
376 }
377 break;
378
379 case 'P':
380 switch (given & 0x00080080)
381 {
382 case 0:
383 func (stream, "s");
384 break;
385 case 0x80:
386 func (stream, "d");
387 break;
388 case 0x00080000:
389 func (stream, "e");
390 break;
391 default:
392 func (stream, _("<illegal precision>"));
393 break;
394 }
395 break;
396 case 'Q':
397 switch (given & 0x00408000)
398 {
399 case 0:
400 func (stream, "s");
401 break;
402 case 0x8000:
403 func (stream, "d");
404 break;
405 case 0x00400000:
406 func (stream, "e");
407 break;
408 default:
409 func (stream, "p");
410 break;
411 }
412 break;
413 case 'R':
414 switch (given & 0x60)
415 {
416 case 0:
417 break;
418 case 0x20:
419 func (stream, "p");
420 break;
421 case 0x40:
422 func (stream, "m");
423 break;
424 default:
425 func (stream, "z");
426 break;
427 }
428 break;
429
430 case '0': case '1': case '2': case '3': case '4':
431 case '5': case '6': case '7': case '8': case '9':
432 {
433 int bitstart = *c++ - '0';
434 int bitend = 0;
435 while (*c >= '0' && *c <= '9')
436 bitstart = (bitstart * 10) + *c++ - '0';
437
438 switch (*c)
439 {
440 case '-':
441 c++;
442 while (*c >= '0' && *c <= '9')
443 bitend = (bitend * 10) + *c++ - '0';
444 if (!bitend)
445 abort ();
446 switch (*c)
447 {
448 case 'r':
449 {
450 long reg;
451 reg = given >> bitstart;
452 reg &= (2 << (bitend - bitstart)) - 1;
453 func (stream, "%s", arm_regnames[reg]);
454 }
455 break;
456 case 'd':
457 {
458 long reg;
459 reg = given >> bitstart;
460 reg &= (2 << (bitend - bitstart)) - 1;
461 func (stream, "%d", reg);
462 }
463 break;
464 case 'x':
465 {
466 long reg;
467 reg = given >> bitstart;
468 reg &= (2 << (bitend - bitstart)) - 1;
469 func (stream, "0x%08x", reg);
470 }
471 break;
472 case 'f':
473 {
474 long reg;
475 reg = given >> bitstart;
476 reg &= (2 << (bitend - bitstart)) - 1;
477 if (reg > 7)
478 func (stream, "#%s",
479 arm_fp_const[reg & 7]);
480 else
481 func (stream, "f%d", reg);
482 }
483 break;
484 default:
485 abort ();
486 }
487 break;
488 case '`':
489 c++;
490 if ((given & (1 << bitstart)) == 0)
491 func (stream, "%c", *c);
492 break;
493 case '\'':
494 c++;
495 if ((given & (1 << bitstart)) != 0)
496 func (stream, "%c", *c);
497 break;
498 case '?':
499 ++c;
500 if ((given & (1 << bitstart)) != 0)
501 func (stream, "%c", *c++);
502 else
503 func (stream, "%c", *++c);
504 break;
505 default:
506 abort ();
507 }
508 break;
509
510 default:
511 abort ();
512 }
513 }
514 }
515 else
516 func (stream, "%c", *c);
517 }
518 return 4;
519 }
520 }
521 abort ();
522 }
523
524 /* Print one instruction from PC on INFO->STREAM.
525 Return the size of the instruction. */
526
527 static int
528 print_insn_thumb (pc, info, given)
529 bfd_vma pc;
530 struct disassemble_info *info;
531 long given;
532 {
533 struct thumb_opcode *insn;
534 void *stream = info->stream;
535 fprintf_ftype func = info->fprintf_func;
536
537 for (insn = thumb_opcodes; insn->assembler; insn++)
538 {
539 if ((given & insn->mask) == insn->value)
540 {
541 char *c = insn->assembler;
542
543 /* Special processing for Thumb 2 instruction BL sequence: */
544 if (!*c) /* check for empty (not NULL) assembler string */
545 {
546 info->bytes_per_chunk = 4;
547 info->bytes_per_line = 4;
548
549 func (stream, "%04x\tbl\t", given & 0xffff);
550 (*info->print_address_func)
551 (BDISP23 (given) * 2 + pc + 4, info);
552 return 4;
553 }
554 else
555 {
556 info->bytes_per_chunk = 2;
557 info->bytes_per_line = 4;
558
559 given &= 0xffff;
560 func (stream, "%04x\t", given);
561 for (; *c; c++)
562 {
563 if (*c == '%')
564 {
565 int domaskpc = 0;
566 int domasklr = 0;
567 switch (*++c)
568 {
569 case '%':
570 func (stream, "%%");
571 break;
572
573 case 'S':
574 {
575 long reg;
576 reg = (given >> 3) & 0x7;
577 if (given & (1 << 6))
578 reg += 8;
579 func (stream, "%s", arm_regnames[reg]);
580 }
581 break;
582
583 case 'D':
584 {
585 long reg;
586 reg = given & 0x7;
587 if (given & (1 << 7))
588 reg += 8;
589 func (stream, "%s", arm_regnames[reg]);
590 }
591 break;
592
593 case 'T':
594 func (stream, "%s",
595 arm_conditional [(given >> 8) & 0xf]);
596 break;
597
598 case 'N':
599 if (given & (1 << 8))
600 domasklr = 1;
601 /* fall through */
602 case 'O':
603 if (*c == 'O' && (given & (1 << 8)))
604 domaskpc = 1;
605 /* fall through */
606 case 'M':
607 {
608 int started = 0;
609 int reg;
610 func (stream, "{");
611 /* It would be nice if we could spot
612 ranges, and generate the rS-rE format: */
613 for (reg = 0; (reg < 8); reg++)
614 if ((given & (1 << reg)) != 0)
615 {
616 if (started)
617 func (stream, ", ");
618 started = 1;
619 func (stream, "%s", arm_regnames[reg]);
620 }
621
622 if (domasklr)
623 {
624 if (started)
625 func (stream, ", ");
626 started = 1;
627 func (stream, "lr");
628 }
629
630 if (domaskpc)
631 {
632 if (started)
633 func (stream, ", ");
634 func (stream, "pc");
635 }
636
637 func (stream, "}");
638 }
639 break;
640
641
642 case '0': case '1': case '2': case '3': case '4':
643 case '5': case '6': case '7': case '8': case '9':
644 {
645 int bitstart = *c++ - '0';
646 int bitend = 0;
647 while (*c >= '0' && *c <= '9')
648 bitstart = (bitstart * 10) + *c++ - '0';
649
650 switch (*c)
651 {
652 case '-':
653 {
654 long reg;
655 c++;
656 while (*c >= '0' && *c <= '9')
657 bitend = (bitend * 10) + *c++ - '0';
658 if (!bitend)
659 abort ();
660 reg = given >> bitstart;
661 reg &= (2 << (bitend - bitstart)) - 1;
662 switch (*c)
663 {
664 case 'r':
665 func (stream, "%s", arm_regnames[reg]);
666 break;
667
668 case 'd':
669 func (stream, "%d", reg);
670 break;
671
672 case 'H':
673 func (stream, "%d", reg << 1);
674 break;
675
676 case 'W':
677 func (stream, "%d", reg << 2);
678 break;
679
680 case 'a':
681 /* PC-relative address -- the bottom two
682 bits of the address are dropped before
683 the calculation. */
684 info->print_address_func
685 (((pc + 4) & ~3) + (reg << 2), info);
686 break;
687
688 case 'x':
689 func (stream, "0x%04x", reg);
690 break;
691
692 case 'I':
693 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
694 func (stream, "%d", reg);
695 break;
696
697 case 'B':
698 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
699 (*info->print_address_func)
700 (reg * 2 + pc + 4, info);
701 break;
702
703 default:
704 abort();
705 }
706 }
707 break;
708
709 case '\'':
710 c++;
711 if ((given & (1 << bitstart)) != 0)
712 func (stream, "%c", *c);
713 break;
714
715 case '?':
716 ++c;
717 if ((given & (1 << bitstart)) != 0)
718 func (stream, "%c", *c++);
719 else
720 func (stream, "%c", *++c);
721 break;
722
723 default:
724 abort();
725 }
726 }
727 break;
728
729 default:
730 abort ();
731 }
732 }
733 else
734 func (stream, "%c", *c);
735 }
736 }
737 return 2;
738 }
739 }
740
741 /* no match */
742 abort ();
743 }
744
745 /* NOTE: There are no checks in these routines that the relevant number of data bytes exist */
746
747 int
748 print_insn_big_arm (pc, info)
749 bfd_vma pc;
750 struct disassemble_info *info;
751 {
752 unsigned char b[4];
753 long given;
754 int status;
755 coff_symbol_type *cs;
756 elf_symbol_type *es;
757 int is_thumb;
758
759 is_thumb = false;
760 if (info->symbols != NULL)
761 {
762 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
763 {
764 cs = coffsymbol (*info->symbols);
765 is_thumb = (cs->native->u.syment.n_sclass == C_THUMBEXT
766 || cs->native->u.syment.n_sclass == C_THUMBSTAT
767 || cs->native->u.syment.n_sclass == C_THUMBLABEL
768 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
769 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
770
771 }
772 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
773 {
774 es = *(elf_symbol_type **)(info->symbols);
775 is_thumb = ELF_ST_TYPE (es->internal_elf_sym.st_info) ==
776 STT_ARM_TFUNC;
777 }
778 }
779
780 info->bytes_per_chunk = 4;
781 info->display_endian = BFD_ENDIAN_BIG;
782
783 /* Always fetch word aligned values. */
784
785 status = (*info->read_memory_func) (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
786 if (status != 0)
787 {
788 (*info->memory_error_func) (status, pc, info);
789 return -1;
790 }
791
792 if (is_thumb)
793 {
794 if (pc & 0x2)
795 {
796 given = (b[2] << 8) | b[3];
797
798 status = info->read_memory_func ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
799 if (status != 0)
800 {
801 info->memory_error_func (status, pc + 4, info);
802 return -1;
803 }
804
805 given |= (b[0] << 24) | (b[1] << 16);
806 }
807 else
808 {
809 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
810 }
811 }
812 else
813 {
814 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
815 }
816
817 if (is_thumb)
818 {
819 status = print_insn_thumb (pc, info, given);
820 }
821 else
822 {
823 status = print_insn_arm (pc, info, given);
824 }
825
826 return status;
827 }
828
829 int
830 print_insn_little_arm (pc, info)
831 bfd_vma pc;
832 struct disassemble_info * info;
833 {
834 unsigned char b[4];
835 long given;
836 int status;
837 coff_symbol_type *cs;
838 elf_symbol_type *es;
839 int is_thumb;
840
841 is_thumb = false;
842 if (info->symbols != NULL)
843 {
844 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
845 {
846 cs = coffsymbol (*info->symbols);
847 is_thumb = (cs->native->u.syment.n_sclass == C_THUMBEXT
848 || cs->native->u.syment.n_sclass == C_THUMBSTAT
849 || cs->native->u.syment.n_sclass == C_THUMBLABEL
850 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
851 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
852
853 }
854 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
855 {
856 es = *(elf_symbol_type **)(info->symbols);
857 is_thumb = ELF_ST_TYPE (es->internal_elf_sym.st_info) ==
858 STT_ARM_TFUNC;
859 }
860 }
861
862 info->bytes_per_chunk = 4;
863 info->display_endian = BFD_ENDIAN_LITTLE;
864
865 status = (*info->read_memory_func) (pc, (bfd_byte *) &b[0], 4, info);
866 if (status != 0 && is_thumb)
867 {
868 info->bytes_per_chunk = 2;
869
870 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
871 b[3] = b[2] = 0;
872 }
873 if (status != 0)
874 {
875 (*info->memory_error_func) (status, pc, info);
876 return -1;
877 }
878
879 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
880
881 if (is_thumb)
882 {
883 status = print_insn_thumb (pc, info, given);
884 }
885 else
886 {
887 status = print_insn_arm (pc, info, given);
888 }
889
890 return status;
891 }
This page took 0.06054 seconds and 4 git commands to generate.