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