Expect xscale-coff to fail simple objcopy test for the same reason as arm-coff.
[binutils.git] / opcodes / arm-dis.c
blob104b933bbc2fb1f1591701f703ea5de75ec09828
1 /* Instruction printing code for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modification by James G. Smith (jsmith@cygnus.co.uk)
7 This file is part of libopcodes.
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2 of the License, or (at your option)
12 any later version.
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #define DEFINE_TABLE
26 #include "arm-opc.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29 #include "opintl.h"
31 /* FIXME: This shouldn't be done here */
32 #include "elf-bfd.h"
33 #include "elf/internal.h"
34 #include "elf/arm.h"
36 #ifndef streq
37 #define streq(a,b) (strcmp ((a), (b)) == 0)
38 #endif
40 #ifndef strneq
41 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
42 #endif
44 #ifndef NUM_ELEM
45 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
46 #endif
48 static char * arm_conditional[] =
49 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
50 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
52 typedef struct
54 const char * name;
55 const char * description;
56 const char * reg_names[16];
58 arm_regname;
60 static arm_regname regnames[] =
62 { "raw" , "Select raw register names",
63 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
64 { "gcc", "Select register names used by GCC",
65 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
66 { "std", "Select register names used in ARM's ISA documentation",
67 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
68 { "apcs", "Select register names used in the APCS",
69 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
70 { "atpcs", "Select register names used in the ATPCS",
71 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
72 { "special-atpcs", "Select special register names used in the ATPCS",
73 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}
76 /* Default to GCC register name set. */
77 static unsigned int regname_selected = 1;
79 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
80 #define arm_regnames regnames[regname_selected].reg_names
82 static boolean force_thumb = false;
84 static char * arm_fp_const[] =
85 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
87 static char * arm_shift[] =
88 {"lsl", "lsr", "asr", "ror"};
90 /* Forward declarations. */
91 static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *));
92 static int print_insn_arm PARAMS ((bfd_vma, struct disassemble_info *, long));
93 static int print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
94 static void parse_disassembler_options PARAMS ((char *));
95 static int print_insn PARAMS ((bfd_vma, struct disassemble_info *, boolean));
96 int get_arm_regname_num_options (void);
97 int set_arm_regname_option (int option);
98 int get_arm_regnames (int option, const char **setname,
99 const char **setdescription,
100 const char ***register_names);
102 /* Functions. */
104 get_arm_regname_num_options (void)
106 return NUM_ARM_REGNAMES;
110 set_arm_regname_option (int option)
112 int old = regname_selected;
113 regname_selected = option;
114 return old;
118 get_arm_regnames (int option, const char **setname,
119 const char **setdescription,
120 const char ***register_names)
122 *setname = regnames[option].name;
123 *setdescription = regnames[option].description;
124 *register_names = regnames[option].reg_names;
125 return 16;
128 static void
129 arm_decode_shift (given, func, stream)
130 long given;
131 fprintf_ftype func;
132 void * stream;
134 func (stream, "%s", arm_regnames[given & 0xf]);
136 if ((given & 0xff0) != 0)
138 if ((given & 0x10) == 0)
140 int amount = (given & 0xf80) >> 7;
141 int shift = (given & 0x60) >> 5;
143 if (amount == 0)
145 if (shift == 3)
147 func (stream, ", rrx");
148 return;
151 amount = 32;
154 func (stream, ", %s #%d", arm_shift[shift], amount);
156 else
157 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
158 arm_regnames[(given & 0xf00) >> 8]);
162 /* Print one instruction from PC on INFO->STREAM.
163 Return the size of the instruction (always 4 on ARM). */
164 static int
165 print_insn_arm (pc, info, given)
166 bfd_vma pc;
167 struct disassemble_info * info;
168 long given;
170 struct arm_opcode * insn;
171 void * stream = info->stream;
172 fprintf_ftype func = info->fprintf_func;
174 for (insn = arm_opcodes; insn->assembler; insn++)
176 if ((given & insn->mask) == insn->value)
178 char * c;
180 for (c = insn->assembler; *c; c++)
182 if (*c == '%')
184 switch (*++c)
186 case '%':
187 func (stream, "%%");
188 break;
190 case 'a':
191 if (((given & 0x000f0000) == 0x000f0000)
192 && ((given & 0x02000000) == 0))
194 int offset = given & 0xfff;
196 func (stream, "[pc");
198 if (given & 0x01000000)
200 if ((given & 0x00800000) == 0)
201 offset = - offset;
203 /* pre-indexed */
204 func (stream, ", #%d]", offset);
206 offset += pc + 8;
208 /* Cope with the possibility of write-back
209 being used. Probably a very dangerous thing
210 for the programmer to do, but who are we to
211 argue ? */
212 if (given & 0x00200000)
213 func (stream, "!");
215 else
217 /* Post indexed. */
218 func (stream, "], #%d", offset);
220 offset = pc + 8; /* ie ignore the offset. */
223 func (stream, "\t; ");
224 info->print_address_func (offset, info);
226 else
228 func (stream, "[%s",
229 arm_regnames[(given >> 16) & 0xf]);
230 if ((given & 0x01000000) != 0)
232 if ((given & 0x02000000) == 0)
234 int offset = given & 0xfff;
235 if (offset)
236 func (stream, ", %s#%d",
237 (((given & 0x00800000) == 0)
238 ? "-" : ""), offset);
240 else
242 func (stream, ", %s",
243 (((given & 0x00800000) == 0)
244 ? "-" : ""));
245 arm_decode_shift (given, func, stream);
248 func (stream, "]%s",
249 ((given & 0x00200000) != 0) ? "!" : "");
251 else
253 if ((given & 0x02000000) == 0)
255 int offset = given & 0xfff;
256 if (offset)
257 func (stream, "], %s#%d",
258 (((given & 0x00800000) == 0)
259 ? "-" : ""), offset);
260 else
261 func (stream, "]");
263 else
265 func (stream, "], %s",
266 (((given & 0x00800000) == 0)
267 ? "-" : ""));
268 arm_decode_shift (given, func, stream);
272 break;
274 case 's':
275 if ((given & 0x004f0000) == 0x004f0000)
277 /* PC relative with immediate offset. */
278 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
280 if ((given & 0x00800000) == 0)
281 offset = -offset;
283 func (stream, "[pc, #%d]\t; ", offset);
285 (*info->print_address_func)
286 (offset + pc + 8, info);
288 else
290 func (stream, "[%s",
291 arm_regnames[(given >> 16) & 0xf]);
292 if ((given & 0x01000000) != 0)
294 /* Pre-indexed. */
295 if ((given & 0x00400000) == 0x00400000)
297 /* Immediate. */
298 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
299 if (offset)
300 func (stream, ", %s#%d",
301 (((given & 0x00800000) == 0)
302 ? "-" : ""), offset);
304 else
306 /* Register. */
307 func (stream, ", %s%s",
308 (((given & 0x00800000) == 0)
309 ? "-" : ""),
310 arm_regnames[given & 0xf]);
313 func (stream, "]%s",
314 ((given & 0x00200000) != 0) ? "!" : "");
316 else
318 /* Post-indexed. */
319 if ((given & 0x00400000) == 0x00400000)
321 /* Immediate. */
322 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
323 if (offset)
324 func (stream, "], %s#%d",
325 (((given & 0x00800000) == 0)
326 ? "-" : ""), offset);
327 else
328 func (stream, "]");
330 else
332 /* Register. */
333 func (stream, "], %s%s",
334 (((given & 0x00800000) == 0)
335 ? "-" : ""),
336 arm_regnames[given & 0xf]);
340 break;
342 case 'b':
343 (*info->print_address_func)
344 (BDISP (given) * 4 + pc + 8, info);
345 break;
347 case 'c':
348 func (stream, "%s",
349 arm_conditional [(given >> 28) & 0xf]);
350 break;
352 case 'm':
354 int started = 0;
355 int reg;
357 func (stream, "{");
358 for (reg = 0; reg < 16; reg++)
359 if ((given & (1 << reg)) != 0)
361 if (started)
362 func (stream, ", ");
363 started = 1;
364 func (stream, "%s", arm_regnames[reg]);
366 func (stream, "}");
368 break;
370 case 'o':
371 if ((given & 0x02000000) != 0)
373 int rotate = (given & 0xf00) >> 7;
374 int immed = (given & 0xff);
375 immed = (((immed << (32 - rotate))
376 | (immed >> rotate)) & 0xffffffff);
377 func (stream, "#%d\t; 0x%x", immed, immed);
379 else
380 arm_decode_shift (given, func, stream);
381 break;
383 case 'p':
384 if ((given & 0x0000f000) == 0x0000f000)
385 func (stream, "p");
386 break;
388 case 't':
389 if ((given & 0x01200000) == 0x00200000)
390 func (stream, "t");
391 break;
393 case 'h':
394 if ((given & 0x00000020) == 0x00000020)
395 func (stream, "h");
396 else
397 func (stream, "b");
398 break;
400 case 'A':
401 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
402 if ((given & 0x01000000) != 0)
404 int offset = given & 0xff;
405 if (offset)
406 func (stream, ", %s#%d]%s",
407 ((given & 0x00800000) == 0 ? "-" : ""),
408 offset * 4,
409 ((given & 0x00200000) != 0 ? "!" : ""));
410 else
411 func (stream, "]");
413 else
415 int offset = given & 0xff;
416 if (offset)
417 func (stream, "], %s#%d",
418 ((given & 0x00800000) == 0 ? "-" : ""),
419 offset * 4);
420 else
421 func (stream, "]");
423 break;
425 case 'B':
426 /* Print ARM V5 BLX(1) address: pc+25 bits. */
428 bfd_vma address;
429 bfd_vma offset = 0;
431 if (given & 0x00800000)
432 /* Is signed, hi bits should be ones. */
433 offset = (-1) ^ 0x00ffffff;
435 /* Offset is (SignExtend(offset field)<<2). */
436 offset += given & 0x00ffffff;
437 offset <<= 2;
438 address = offset + pc + 8;
440 if (given & 0x01000000)
441 /* H bit allows addressing to 2-byte boundaries. */
442 address += 2;
444 info->print_address_func (address, info);
446 break;
448 case 'I':
449 /* Print a Cirrus/DSP shift immediate. */
450 /* Immediates are 7bit signed ints with bits 0..3 in
451 bits 0..3 of opcode and bits 4..6 in bits 5..7
452 of opcode. */
454 int imm;
456 imm = (given & 0xf) | ((given & 0xe0) >> 1);
458 /* Is ``imm'' a negative number? */
459 if (imm & 0x40)
460 imm |= (-1 << 7);
462 func (stream, "%d", imm);
465 break;
467 case 'C':
468 func (stream, "_");
469 if (given & 0x80000)
470 func (stream, "f");
471 if (given & 0x40000)
472 func (stream, "s");
473 if (given & 0x20000)
474 func (stream, "x");
475 if (given & 0x10000)
476 func (stream, "c");
477 break;
479 case 'F':
480 switch (given & 0x00408000)
482 case 0:
483 func (stream, "4");
484 break;
485 case 0x8000:
486 func (stream, "1");
487 break;
488 case 0x00400000:
489 func (stream, "2");
490 break;
491 default:
492 func (stream, "3");
494 break;
496 case 'P':
497 switch (given & 0x00080080)
499 case 0:
500 func (stream, "s");
501 break;
502 case 0x80:
503 func (stream, "d");
504 break;
505 case 0x00080000:
506 func (stream, "e");
507 break;
508 default:
509 func (stream, _("<illegal precision>"));
510 break;
512 break;
513 case 'Q':
514 switch (given & 0x00408000)
516 case 0:
517 func (stream, "s");
518 break;
519 case 0x8000:
520 func (stream, "d");
521 break;
522 case 0x00400000:
523 func (stream, "e");
524 break;
525 default:
526 func (stream, "p");
527 break;
529 break;
530 case 'R':
531 switch (given & 0x60)
533 case 0:
534 break;
535 case 0x20:
536 func (stream, "p");
537 break;
538 case 0x40:
539 func (stream, "m");
540 break;
541 default:
542 func (stream, "z");
543 break;
545 break;
547 case '0': case '1': case '2': case '3': case '4':
548 case '5': case '6': case '7': case '8': case '9':
550 int bitstart = *c++ - '0';
551 int bitend = 0;
552 while (*c >= '0' && *c <= '9')
553 bitstart = (bitstart * 10) + *c++ - '0';
555 switch (*c)
557 case '-':
558 c++;
560 while (*c >= '0' && *c <= '9')
561 bitend = (bitend * 10) + *c++ - '0';
563 if (!bitend)
564 abort ();
566 switch (*c)
568 case 'r':
570 long reg;
572 reg = given >> bitstart;
573 reg &= (2 << (bitend - bitstart)) - 1;
575 func (stream, "%s", arm_regnames[reg]);
577 break;
578 case 'd':
580 long reg;
582 reg = given >> bitstart;
583 reg &= (2 << (bitend - bitstart)) - 1;
585 func (stream, "%d", reg);
587 break;
588 case 'x':
590 long reg;
592 reg = given >> bitstart;
593 reg &= (2 << (bitend - bitstart)) - 1;
595 func (stream, "0x%08x", reg);
597 /* Some SWI instructions have special
598 meanings. */
599 if ((given & 0x0fffffff) == 0x0FF00000)
600 func (stream, "\t; IMB");
601 else if ((given & 0x0fffffff) == 0x0FF00001)
602 func (stream, "\t; IMBRange");
604 break;
605 case 'X':
607 long reg;
609 reg = given >> bitstart;
610 reg &= (2 << (bitend - bitstart)) - 1;
612 func (stream, "%01x", reg & 0xf);
614 break;
615 case 'f':
617 long reg;
619 reg = given >> bitstart;
620 reg &= (2 << (bitend - bitstart)) - 1;
622 if (reg > 7)
623 func (stream, "#%s",
624 arm_fp_const[reg & 7]);
625 else
626 func (stream, "f%d", reg);
628 break;
629 default:
630 abort ();
632 break;
634 case '`':
635 c++;
636 if ((given & (1 << bitstart)) == 0)
637 func (stream, "%c", *c);
638 break;
639 case '\'':
640 c++;
641 if ((given & (1 << bitstart)) != 0)
642 func (stream, "%c", *c);
643 break;
644 case '?':
645 ++c;
646 if ((given & (1 << bitstart)) != 0)
647 func (stream, "%c", *c++);
648 else
649 func (stream, "%c", *++c);
650 break;
651 default:
652 abort ();
654 break;
656 default:
657 abort ();
661 else
662 func (stream, "%c", *c);
664 return 4;
667 abort ();
670 /* Print one instruction from PC on INFO->STREAM.
671 Return the size of the instruction. */
672 static int
673 print_insn_thumb (pc, info, given)
674 bfd_vma pc;
675 struct disassemble_info * info;
676 long given;
678 struct thumb_opcode * insn;
679 void * stream = info->stream;
680 fprintf_ftype func = info->fprintf_func;
682 for (insn = thumb_opcodes; insn->assembler; insn++)
684 if ((given & insn->mask) == insn->value)
686 char * c = insn->assembler;
688 /* Special processing for Thumb 2 instruction BL sequence: */
689 if (!*c) /* Check for empty (not NULL) assembler string. */
691 long offset;
693 info->bytes_per_chunk = 4;
694 info->bytes_per_line = 4;
696 offset = BDISP23 (given);
698 if ((given & 0x10000000) == 0)
700 func (stream, "blx\t");
702 /* The spec says that bit 1 of the branch's destination
703 address comes from bit 1 of the instruction's
704 address and not from the offset in the instruction. */
705 if (offset & 0x1)
707 /* func (stream, "*malformed!* "); */
708 offset &= ~ 0x1;
711 offset |= ((pc & 0x2) >> 1);
713 else
714 func (stream, "bl\t");
716 info->print_address_func (offset * 2 + pc + 4, info);
717 return 4;
719 else
721 info->bytes_per_chunk = 2;
722 info->bytes_per_line = 4;
724 given &= 0xffff;
726 for (; *c; c++)
728 if (*c == '%')
730 int domaskpc = 0;
731 int domasklr = 0;
733 switch (*++c)
735 case '%':
736 func (stream, "%%");
737 break;
739 case 'S':
741 long reg;
743 reg = (given >> 3) & 0x7;
744 if (given & (1 << 6))
745 reg += 8;
747 func (stream, "%s", arm_regnames[reg]);
749 break;
751 case 'D':
753 long reg;
755 reg = given & 0x7;
756 if (given & (1 << 7))
757 reg += 8;
759 func (stream, "%s", arm_regnames[reg]);
761 break;
763 case 'T':
764 func (stream, "%s",
765 arm_conditional [(given >> 8) & 0xf]);
766 break;
768 case 'N':
769 if (given & (1 << 8))
770 domasklr = 1;
771 /* Fall through. */
772 case 'O':
773 if (*c == 'O' && (given & (1 << 8)))
774 domaskpc = 1;
775 /* Fall through. */
776 case 'M':
778 int started = 0;
779 int reg;
781 func (stream, "{");
783 /* It would be nice if we could spot
784 ranges, and generate the rS-rE format: */
785 for (reg = 0; (reg < 8); reg++)
786 if ((given & (1 << reg)) != 0)
788 if (started)
789 func (stream, ", ");
790 started = 1;
791 func (stream, "%s", arm_regnames[reg]);
794 if (domasklr)
796 if (started)
797 func (stream, ", ");
798 started = 1;
799 func (stream, arm_regnames[14] /* "lr" */);
802 if (domaskpc)
804 if (started)
805 func (stream, ", ");
806 func (stream, arm_regnames[15] /* "pc" */);
809 func (stream, "}");
811 break;
814 case '0': case '1': case '2': case '3': case '4':
815 case '5': case '6': case '7': case '8': case '9':
817 int bitstart = *c++ - '0';
818 int bitend = 0;
820 while (*c >= '0' && *c <= '9')
821 bitstart = (bitstart * 10) + *c++ - '0';
823 switch (*c)
825 case '-':
827 long reg;
829 c++;
830 while (*c >= '0' && *c <= '9')
831 bitend = (bitend * 10) + *c++ - '0';
832 if (!bitend)
833 abort ();
834 reg = given >> bitstart;
835 reg &= (2 << (bitend - bitstart)) - 1;
836 switch (*c)
838 case 'r':
839 func (stream, "%s", arm_regnames[reg]);
840 break;
842 case 'd':
843 func (stream, "%d", reg);
844 break;
846 case 'H':
847 func (stream, "%d", reg << 1);
848 break;
850 case 'W':
851 func (stream, "%d", reg << 2);
852 break;
854 case 'a':
855 /* PC-relative address -- the bottom two
856 bits of the address are dropped
857 before the calculation. */
858 info->print_address_func
859 (((pc + 4) & ~3) + (reg << 2), info);
860 break;
862 case 'x':
863 func (stream, "0x%04x", reg);
864 break;
866 case 'I':
867 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
868 func (stream, "%d", reg);
869 break;
871 case 'B':
872 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
873 (*info->print_address_func)
874 (reg * 2 + pc + 4, info);
875 break;
877 default:
878 abort ();
881 break;
883 case '\'':
884 c++;
885 if ((given & (1 << bitstart)) != 0)
886 func (stream, "%c", *c);
887 break;
889 case '?':
890 ++c;
891 if ((given & (1 << bitstart)) != 0)
892 func (stream, "%c", *c++);
893 else
894 func (stream, "%c", *++c);
895 break;
897 default:
898 abort ();
901 break;
903 default:
904 abort ();
907 else
908 func (stream, "%c", *c);
911 return 2;
915 /* No match. */
916 abort ();
919 /* Parse an individual disassembler option. */
920 void
921 parse_arm_disassembler_option (option)
922 char * option;
924 if (option == NULL)
925 return;
927 if (strneq (option, "reg-names-", 10))
929 int i;
931 option += 10;
933 for (i = NUM_ARM_REGNAMES; i--;)
934 if (streq (option, regnames[i].name))
936 regname_selected = i;
937 break;
940 if (i < 0)
941 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
943 else if (streq (option, "force-thumb"))
944 force_thumb = 1;
945 else if (streq (option, "no-force-thumb"))
946 force_thumb = 0;
947 else
948 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
950 return;
953 /* Parse the string of disassembler options, spliting it at whitespaces. */
954 static void
955 parse_disassembler_options (options)
956 char * options;
958 char * space;
960 if (options == NULL)
961 return;
965 space = strchr (options, ' ');
967 if (space)
969 * space = '\0';
970 parse_arm_disassembler_option (options);
971 * space = ' ';
972 options = space + 1;
974 else
975 parse_arm_disassembler_option (options);
977 while (space);
980 /* NOTE: There are no checks in these routines that
981 the relevant number of data bytes exist. */
982 static int
983 print_insn (pc, info, little)
984 bfd_vma pc;
985 struct disassemble_info * info;
986 boolean little;
988 unsigned char b[4];
989 long given;
990 int status;
991 int is_thumb;
993 if (info->disassembler_options)
995 parse_disassembler_options (info->disassembler_options);
997 /* To avoid repeated parsing of these options, we remove them here. */
998 info->disassembler_options = NULL;
1001 is_thumb = force_thumb;
1003 if (!is_thumb && info->symbols != NULL)
1005 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1007 coff_symbol_type * cs;
1009 cs = coffsymbol (*info->symbols);
1010 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
1011 || cs->native->u.syment.n_sclass == C_THUMBSTAT
1012 || cs->native->u.syment.n_sclass == C_THUMBLABEL
1013 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1014 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1016 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1018 elf_symbol_type * es;
1019 unsigned int type;
1021 es = *(elf_symbol_type **)(info->symbols);
1022 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1024 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1028 info->bytes_per_chunk = 4;
1029 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1031 if (little)
1033 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1034 if (status != 0 && is_thumb)
1036 info->bytes_per_chunk = 2;
1038 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1039 b[3] = b[2] = 0;
1042 if (status != 0)
1044 info->memory_error_func (status, pc, info);
1045 return -1;
1048 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1050 else
1052 status = info->read_memory_func
1053 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1054 if (status != 0)
1056 info->memory_error_func (status, pc, info);
1057 return -1;
1060 if (is_thumb)
1062 if (pc & 0x2)
1064 given = (b[2] << 8) | b[3];
1066 status = info->read_memory_func
1067 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1068 if (status != 0)
1070 info->memory_error_func (status, pc + 4, info);
1071 return -1;
1074 given |= (b[0] << 24) | (b[1] << 16);
1076 else
1077 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1079 else
1080 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1083 if (info->flags & INSN_HAS_RELOC)
1084 /* If the instruction has a reloc associated with it, then
1085 the offset field in the instruction will actually be the
1086 addend for the reloc. (We are using REL type relocs).
1087 In such cases, we can ignore the pc when computing
1088 addresses, since the addend is not currently pc-relative. */
1089 pc = 0;
1091 if (is_thumb)
1092 status = print_insn_thumb (pc, info, given);
1093 else
1094 status = print_insn_arm (pc, info, given);
1096 return status;
1100 print_insn_big_arm (pc, info)
1101 bfd_vma pc;
1102 struct disassemble_info * info;
1104 return print_insn (pc, info, false);
1108 print_insn_little_arm (pc, info)
1109 bfd_vma pc;
1110 struct disassemble_info * info;
1112 return print_insn (pc, info, true);
1115 void
1116 print_arm_disassembler_options (FILE * stream)
1118 int i;
1120 fprintf (stream, _("\n\
1121 The following ARM specific disassembler options are supported for use with\n\
1122 the -M switch:\n"));
1124 for (i = NUM_ARM_REGNAMES; i--;)
1125 fprintf (stream, " reg-names-%s %*c%s\n",
1126 regnames[i].name,
1127 (int)(14 - strlen (regnames[i].name)), ' ',
1128 regnames[i].description);
1130 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1131 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");