1 /* Instruction printing code for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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)
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
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. */
27 #include "coff/internal.h"
30 #include "safe-ctype.h"
32 /* FIXME: This shouldn't be done here. */
34 #include "elf/internal.h"
38 #define streq(a,b) (strcmp ((a), (b)) == 0)
42 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
46 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
49 static char * arm_conditional
[] =
50 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
51 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
56 const char * description
;
57 const char * reg_names
[16];
61 static arm_regname regnames
[] =
63 { "raw" , "Select raw register names",
64 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
65 { "gcc", "Select register names used by GCC",
66 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
67 { "std", "Select register names used in ARM's ISA documentation",
68 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
69 { "apcs", "Select register names used in the APCS",
70 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
71 { "atpcs", "Select register names used in the ATPCS",
72 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
73 { "special-atpcs", "Select special register names used in the ATPCS",
74 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }},
75 { "iwmmxt_regnames", "Select register names used on the Intel Wireless MMX technology coprocessor",
76 { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"}},
77 { "iwmmxt_Cregnames", "Select control register names used on the Intel Wireless MMX technology coprocessor",
78 {"wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"}}
81 static char * iwmmxt_wwnames
[] =
84 static char * iwmmxt_wwssnames
[] =
85 {"b", "bus", "b", "bss",
86 "h", "hus", "h", "hss",
87 "w", "wus", "w", "wss",
88 "d", "dus", "d", "dss"
91 /* Default to GCC register name set. */
92 static unsigned int regname_selected
= 1;
94 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
95 #define arm_regnames regnames[regname_selected].reg_names
97 static bfd_boolean force_thumb
= FALSE
;
99 static char * arm_fp_const
[] =
100 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
102 static char * arm_shift
[] =
103 {"lsl", "lsr", "asr", "ror"};
105 /* Forward declarations. */
106 static void arm_decode_shift
107 PARAMS ((long, fprintf_ftype
, void *));
108 static int print_insn_arm
109 PARAMS ((bfd_vma
, struct disassemble_info
*, long));
110 static int print_insn_thumb
111 PARAMS ((bfd_vma
, struct disassemble_info
*, long));
112 static void parse_disassembler_options
114 static int print_insn
115 PARAMS ((bfd_vma
, struct disassemble_info
*, bfd_boolean
));
116 static int set_iwmmxt_regnames
119 int get_arm_regname_num_options
121 int set_arm_regname_option
124 PARAMS ((int, const char **, const char **, const char ***));
128 get_arm_regname_num_options ()
130 return NUM_ARM_REGNAMES
;
134 set_arm_regname_option (option
)
137 int old
= regname_selected
;
138 regname_selected
= option
;
143 get_arm_regnames (option
, setname
, setdescription
, register_names
)
145 const char **setname
;
146 const char **setdescription
;
147 const char ***register_names
;
149 *setname
= regnames
[option
].name
;
150 *setdescription
= regnames
[option
].description
;
151 *register_names
= regnames
[option
].reg_names
;
156 arm_decode_shift (given
, func
, stream
)
161 func (stream
, "%s", arm_regnames
[given
& 0xf]);
163 if ((given
& 0xff0) != 0)
165 if ((given
& 0x10) == 0)
167 int amount
= (given
& 0xf80) >> 7;
168 int shift
= (given
& 0x60) >> 5;
174 func (stream
, ", rrx");
181 func (stream
, ", %s #%d", arm_shift
[shift
], amount
);
184 func (stream
, ", %s %s", arm_shift
[(given
& 0x60) >> 5],
185 arm_regnames
[(given
& 0xf00) >> 8]);
190 set_iwmmxt_regnames ()
192 const char * setname
;
193 const char * setdesc
;
194 const char ** regnames
;
195 int iwmmxt_regnames
= 0;
196 int num_regnames
= get_arm_regname_num_options ();
198 get_arm_regnames (iwmmxt_regnames
, &setname
,
199 &setdesc
, ®names
);
200 while ((strcmp ("iwmmxt_regnames", setname
))
201 && (iwmmxt_regnames
< num_regnames
))
202 get_arm_regnames (++iwmmxt_regnames
, &setname
, &setdesc
, ®names
);
204 return iwmmxt_regnames
;
207 /* Print one instruction from PC on INFO->STREAM.
208 Return the size of the instruction (always 4 on ARM). */
211 print_insn_arm (pc
, info
, given
)
213 struct disassemble_info
*info
;
216 const struct arm_opcode
*insn
;
217 void *stream
= info
->stream
;
218 fprintf_ftype func
= info
->fprintf_func
;
219 static int iwmmxt_regnames
= 0;
221 for (insn
= arm_opcodes
; insn
->assembler
; insn
++)
223 if (insn
->value
== FIRST_IWMMXT_INSN
224 && info
->mach
!= bfd_mach_arm_XScale
225 && info
->mach
!= bfd_mach_arm_iWMMXt
)
226 insn
= insn
+ IWMMXT_INSN_COUNT
;
228 if ((given
& insn
->mask
) == insn
->value
)
232 for (c
= insn
->assembler
; *c
; c
++)
243 if (((given
& 0x000f0000) == 0x000f0000)
244 && ((given
& 0x02000000) == 0))
246 int offset
= given
& 0xfff;
248 func (stream
, "[pc");
250 if (given
& 0x01000000)
252 if ((given
& 0x00800000) == 0)
256 func (stream
, ", #%d]", offset
);
260 /* Cope with the possibility of write-back
261 being used. Probably a very dangerous thing
262 for the programmer to do, but who are we to
264 if (given
& 0x00200000)
270 func (stream
, "], #%d", offset
);
272 /* ie ignore the offset. */
276 func (stream
, "\t; ");
277 info
->print_address_func (offset
, info
);
282 arm_regnames
[(given
>> 16) & 0xf]);
283 if ((given
& 0x01000000) != 0)
285 if ((given
& 0x02000000) == 0)
287 int offset
= given
& 0xfff;
289 func (stream
, ", #%s%d",
290 (((given
& 0x00800000) == 0)
291 ? "-" : ""), offset
);
295 func (stream
, ", %s",
296 (((given
& 0x00800000) == 0)
298 arm_decode_shift (given
, func
, stream
);
302 ((given
& 0x00200000) != 0) ? "!" : "");
306 if ((given
& 0x02000000) == 0)
308 int offset
= given
& 0xfff;
310 func (stream
, "], #%s%d",
311 (((given
& 0x00800000) == 0)
312 ? "-" : ""), offset
);
318 func (stream
, "], %s",
319 (((given
& 0x00800000) == 0)
321 arm_decode_shift (given
, func
, stream
);
328 if ((given
& 0x004f0000) == 0x004f0000)
330 /* PC relative with immediate offset. */
331 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
333 if ((given
& 0x00800000) == 0)
336 func (stream
, "[pc, #%d]\t; ", offset
);
338 (*info
->print_address_func
)
339 (offset
+ pc
+ 8, info
);
344 arm_regnames
[(given
>> 16) & 0xf]);
345 if ((given
& 0x01000000) != 0)
348 if ((given
& 0x00400000) == 0x00400000)
351 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
353 func (stream
, ", #%s%d",
354 (((given
& 0x00800000) == 0)
355 ? "-" : ""), offset
);
360 func (stream
, ", %s%s",
361 (((given
& 0x00800000) == 0)
363 arm_regnames
[given
& 0xf]);
367 ((given
& 0x00200000) != 0) ? "!" : "");
372 if ((given
& 0x00400000) == 0x00400000)
375 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
377 func (stream
, "], #%s%d",
378 (((given
& 0x00800000) == 0)
379 ? "-" : ""), offset
);
386 func (stream
, "], %s%s",
387 (((given
& 0x00800000) == 0)
389 arm_regnames
[given
& 0xf]);
396 (*info
->print_address_func
)
397 (BDISP (given
) * 4 + pc
+ 8, info
);
402 arm_conditional
[(given
>> 28) & 0xf]);
411 for (reg
= 0; reg
< 16; reg
++)
412 if ((given
& (1 << reg
)) != 0)
417 func (stream
, "%s", arm_regnames
[reg
]);
424 if ((given
& 0x02000000) != 0)
426 int rotate
= (given
& 0xf00) >> 7;
427 int immed
= (given
& 0xff);
428 immed
= (((immed
<< (32 - rotate
))
429 | (immed
>> rotate
)) & 0xffffffff);
430 func (stream
, "#%d\t; 0x%x", immed
, immed
);
433 arm_decode_shift (given
, func
, stream
);
437 if ((given
& 0x0000f000) == 0x0000f000)
442 if ((given
& 0x01200000) == 0x00200000)
447 func (stream
, "[%s", arm_regnames
[(given
>> 16) & 0xf]);
449 if ((given
& (1 << 24)) != 0)
451 int offset
= given
& 0xff;
454 func (stream
, ", #%s%d]%s",
455 ((given
& 0x00800000) == 0 ? "-" : ""),
457 ((given
& 0x00200000) != 0 ? "!" : ""));
463 int offset
= given
& 0xff;
467 if (given
& (1 << 21))
470 func (stream
, ", #%s%d",
471 ((given
& 0x00800000) == 0 ? "-" : ""),
475 func (stream
, ", {%d}", offset
);
480 /* Print ARM V5 BLX(1) address: pc+25 bits. */
485 if (given
& 0x00800000)
486 /* Is signed, hi bits should be ones. */
487 offset
= (-1) ^ 0x00ffffff;
489 /* Offset is (SignExtend(offset field)<<2). */
490 offset
+= given
& 0x00ffffff;
492 address
= offset
+ pc
+ 8;
494 if (given
& 0x01000000)
495 /* H bit allows addressing to 2-byte boundaries. */
498 info
->print_address_func (address
, info
);
503 /* Print a Cirrus/DSP shift immediate. */
504 /* Immediates are 7bit signed ints with bits 0..3 in
505 bits 0..3 of opcode and bits 4..6 in bits 5..7
510 imm
= (given
& 0xf) | ((given
& 0xe0) >> 1);
512 /* Is ``imm'' a negative number? */
516 func (stream
, "%d", imm
);
534 switch (given
& 0x00408000)
551 switch (given
& 0x00080080)
563 func (stream
, _("<illegal precision>"));
568 switch (given
& 0x00408000)
585 switch (given
& 0x60)
601 case '0': case '1': case '2': case '3': case '4':
602 case '5': case '6': case '7': case '8': case '9':
604 int bitstart
= *c
++ - '0';
606 while (*c
>= '0' && *c
<= '9')
607 bitstart
= (bitstart
* 10) + *c
++ - '0';
614 while (*c
>= '0' && *c
<= '9')
615 bitend
= (bitend
* 10) + *c
++ - '0';
626 reg
= given
>> bitstart
;
627 reg
&= (2 << (bitend
- bitstart
)) - 1;
629 func (stream
, "%s", arm_regnames
[reg
]);
636 reg
= given
>> bitstart
;
637 reg
&= (2 << (bitend
- bitstart
)) - 1;
639 func (stream
, "%d", reg
);
646 reg
= given
>> bitstart
;
647 reg
&= (2 << (bitend
- bitstart
)) - 1;
649 func (stream
, "%d", reg
+ 1);
656 reg
= given
>> bitstart
;
657 reg
&= (2 << (bitend
- bitstart
)) - 1;
659 func (stream
, "0x%08x", reg
);
661 /* Some SWI instructions have special
663 if ((given
& 0x0fffffff) == 0x0FF00000)
664 func (stream
, "\t; IMB");
665 else if ((given
& 0x0fffffff) == 0x0FF00001)
666 func (stream
, "\t; IMBRange");
673 reg
= given
>> bitstart
;
674 reg
&= (2 << (bitend
- bitstart
)) - 1;
676 func (stream
, "%01x", reg
& 0xf);
683 reg
= given
>> bitstart
;
684 reg
&= (2 << (bitend
- bitstart
)) - 1;
688 arm_fp_const
[reg
& 7]);
690 func (stream
, "f%d", reg
);
698 if (bitstart
!= bitend
)
700 reg
= given
>> bitstart
;
701 reg
&= (2 << (bitend
- bitstart
)) - 1;
702 if (bitend
- bitstart
== 1)
703 func (stream
, "%s", iwmmxt_wwnames
[reg
]);
705 func (stream
, "%s", iwmmxt_wwssnames
[reg
]);
709 reg
= (((given
>> 8) & 0x1) |
710 ((given
>> 22) & 0x1));
711 func (stream
, "%s", iwmmxt_wwnames
[reg
]);
719 int current_regnames
;
721 if (! iwmmxt_regnames
)
722 iwmmxt_regnames
= set_iwmmxt_regnames ();
723 current_regnames
= set_arm_regname_option
726 reg
= given
>> bitstart
;
727 reg
&= (2 << (bitend
- bitstart
)) - 1;
728 func (stream
, "%s", arm_regnames
[reg
]);
729 set_arm_regname_option (current_regnames
);
736 int current_regnames
;
738 if (! iwmmxt_regnames
)
739 iwmmxt_regnames
= set_iwmmxt_regnames ();
740 current_regnames
= set_arm_regname_option
741 (iwmmxt_regnames
+ 1);
743 reg
= given
>> bitstart
;
744 reg
&= (2 << (bitend
- bitstart
)) - 1;
745 func (stream
, "%s", arm_regnames
[reg
]);
746 set_arm_regname_option (current_regnames
);
758 int single
= *c
== 'y';
763 case 4: /* Sm pair */
767 regno
= given
& 0x0000000f;
771 regno
+= (given
>> 5) & 1;
776 regno
= (given
>> 12) & 0x0000000f;
780 regno
+= (given
>> 22) & 1;
785 regno
= (given
>> 16) & 0x0000000f;
789 regno
+= (given
>> 7) & 1;
795 regno
= (given
>> 12) & 0x0000000f;
799 regno
+= (given
>> 22) & 1;
808 func (stream
, "%c%d", single
? 's' : 'd', regno
);
812 int count
= given
& 0xff;
819 func (stream
, "-%c%d",
826 else if (bitstart
== 4)
827 func (stream
, ", %c%d}", single
? 's' : 'd',
835 if ((given
& (1 << bitstart
)) == 0)
836 func (stream
, "%c", *c
);
840 if ((given
& (1 << bitstart
)) != 0)
841 func (stream
, "%c", *c
);
845 if ((given
& (1 << bitstart
)) != 0)
846 func (stream
, "%c", *c
++);
848 func (stream
, "%c", *++c
);
856 switch (given
& 0x00400100)
858 case 0x00000000: func (stream
, "b"); break;
859 case 0x00400000: func (stream
, "h"); break;
860 case 0x00000100: func (stream
, "w"); break;
861 case 0x00400100: func (stream
, "d"); break;
870 /* given (20, 23) | given (0, 3) */
871 value
= ((given
>> 16) & 0xf0) | (given
& 0xf);
872 func (stream
, "%d", value
);
877 /* This is like the 'A' operator, except that if
878 the width field "M" is zero, then the offset is
879 *not* multiplied by four. */
881 int offset
= given
& 0xff;
882 int multiplier
= (given
& 0x00000100) ? 4 : 1;
884 func (stream
, "[%s", arm_regnames
[(given
>> 16) & 0xf]);
888 if ((given
& 0x01000000) != 0)
889 func (stream
, ", #%s%d]%s",
890 ((given
& 0x00800000) == 0 ? "-" : ""),
892 ((given
& 0x00200000) != 0 ? "!" : ""));
894 func (stream
, "], #%s%d",
895 ((given
& 0x00800000) == 0 ? "-" : ""),
896 offset
* multiplier
);
907 imm
= (given
& 0xf) | ((given
& 0xfff00) >> 4);
908 func (stream
, "%d", imm
);
918 func (stream
, "%c", *c
);
926 /* Print one instruction from PC on INFO->STREAM.
927 Return the size of the instruction. */
930 print_insn_thumb (pc
, info
, given
)
932 struct disassemble_info
*info
;
935 const struct thumb_opcode
*insn
;
936 void *stream
= info
->stream
;
937 fprintf_ftype func
= info
->fprintf_func
;
939 for (insn
= thumb_opcodes
; insn
->assembler
; insn
++)
941 if ((given
& insn
->mask
) == insn
->value
)
943 char * c
= insn
->assembler
;
945 /* Special processing for Thumb 2 instruction BL sequence: */
946 if (!*c
) /* Check for empty (not NULL) assembler string. */
950 info
->bytes_per_chunk
= 4;
951 info
->bytes_per_line
= 4;
953 offset
= BDISP23 (given
);
954 offset
= offset
* 2 + pc
+ 4;
956 if ((given
& 0x10000000) == 0)
958 func (stream
, "blx\t");
959 offset
&= 0xfffffffc;
962 func (stream
, "bl\t");
964 info
->print_address_func (offset
, info
);
969 info
->bytes_per_chunk
= 2;
970 info
->bytes_per_line
= 4;
991 reg
= (given
>> 3) & 0x7;
992 if (given
& (1 << 6))
995 func (stream
, "%s", arm_regnames
[reg
]);
1004 if (given
& (1 << 7))
1007 func (stream
, "%s", arm_regnames
[reg
]);
1013 arm_conditional
[(given
>> 8) & 0xf]);
1017 if (given
& (1 << 8))
1021 if (*c
== 'O' && (given
& (1 << 8)))
1031 /* It would be nice if we could spot
1032 ranges, and generate the rS-rE format: */
1033 for (reg
= 0; (reg
< 8); reg
++)
1034 if ((given
& (1 << reg
)) != 0)
1037 func (stream
, ", ");
1039 func (stream
, "%s", arm_regnames
[reg
]);
1045 func (stream
, ", ");
1047 func (stream
, arm_regnames
[14] /* "lr" */);
1053 func (stream
, ", ");
1054 func (stream
, arm_regnames
[15] /* "pc" */);
1062 case '0': case '1': case '2': case '3': case '4':
1063 case '5': case '6': case '7': case '8': case '9':
1065 int bitstart
= *c
++ - '0';
1068 while (*c
>= '0' && *c
<= '9')
1069 bitstart
= (bitstart
* 10) + *c
++ - '0';
1078 while (*c
>= '0' && *c
<= '9')
1079 bitend
= (bitend
* 10) + *c
++ - '0';
1082 reg
= given
>> bitstart
;
1083 reg
&= (2 << (bitend
- bitstart
)) - 1;
1087 func (stream
, "%s", arm_regnames
[reg
]);
1091 func (stream
, "%d", reg
);
1095 func (stream
, "%d", reg
<< 1);
1099 func (stream
, "%d", reg
<< 2);
1103 /* PC-relative address -- the bottom two
1104 bits of the address are dropped
1105 before the calculation. */
1106 info
->print_address_func
1107 (((pc
+ 4) & ~3) + (reg
<< 2), info
);
1111 func (stream
, "0x%04x", reg
);
1115 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
1116 func (stream
, "%d", reg
);
1120 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
1121 (*info
->print_address_func
)
1122 (reg
* 2 + pc
+ 4, info
);
1133 if ((given
& (1 << bitstart
)) != 0)
1134 func (stream
, "%c", *c
);
1139 if ((given
& (1 << bitstart
)) != 0)
1140 func (stream
, "%c", *c
++);
1142 func (stream
, "%c", *++c
);
1156 func (stream
, "%c", *c
);
1167 /* Disallow mapping symbols ($a, $b, $d, $t etc) from
1168 being displayed in symbol relative addresses. */
1171 arm_symbol_is_valid (asymbol
* sym
,
1172 struct disassemble_info
* info ATTRIBUTE_UNUSED
)
1179 name
= bfd_asymbol_name (sym
);
1181 return (name
&& *name
!= '$');
1184 /* Parse an individual disassembler option. */
1187 parse_arm_disassembler_option (option
)
1193 if (strneq (option
, "reg-names-", 10))
1199 for (i
= NUM_ARM_REGNAMES
; i
--;)
1200 if (strneq (option
, regnames
[i
].name
, strlen (regnames
[i
].name
)))
1202 regname_selected
= i
;
1207 /* XXX - should break 'option' at following delimiter. */
1208 fprintf (stderr
, _("Unrecognised register name set: %s\n"), option
);
1210 else if (strneq (option
, "force-thumb", 11))
1212 else if (strneq (option
, "no-force-thumb", 14))
1215 /* XXX - should break 'option' at following delimiter. */
1216 fprintf (stderr
, _("Unrecognised disassembler option: %s\n"), option
);
1221 /* Parse the string of disassembler options, spliting it at whitespaces
1222 or commas. (Whitespace separators supported for backwards compatibility). */
1225 parse_disassembler_options (options
)
1228 if (options
== NULL
)
1233 parse_arm_disassembler_option (options
);
1235 /* Skip forward to next seperator. */
1236 while ((*options
) && (! ISSPACE (*options
)) && (*options
!= ','))
1238 /* Skip forward past seperators. */
1239 while (ISSPACE (*options
) || (*options
== ','))
1244 /* NOTE: There are no checks in these routines that
1245 the relevant number of data bytes exist. */
1248 print_insn (pc
, info
, little
)
1250 struct disassemble_info
* info
;
1258 if (info
->disassembler_options
)
1260 parse_disassembler_options (info
->disassembler_options
);
1262 /* To avoid repeated parsing of these options, we remove them here. */
1263 info
->disassembler_options
= NULL
;
1266 is_thumb
= force_thumb
;
1268 if (!is_thumb
&& info
->symbols
!= NULL
)
1270 if (bfd_asymbol_flavour (*info
->symbols
) == bfd_target_coff_flavour
)
1272 coff_symbol_type
* cs
;
1274 cs
= coffsymbol (*info
->symbols
);
1275 is_thumb
= ( cs
->native
->u
.syment
.n_sclass
== C_THUMBEXT
1276 || cs
->native
->u
.syment
.n_sclass
== C_THUMBSTAT
1277 || cs
->native
->u
.syment
.n_sclass
== C_THUMBLABEL
1278 || cs
->native
->u
.syment
.n_sclass
== C_THUMBEXTFUNC
1279 || cs
->native
->u
.syment
.n_sclass
== C_THUMBSTATFUNC
);
1281 else if (bfd_asymbol_flavour (*info
->symbols
) == bfd_target_elf_flavour
)
1283 elf_symbol_type
* es
;
1286 es
= *(elf_symbol_type
**)(info
->symbols
);
1287 type
= ELF_ST_TYPE (es
->internal_elf_sym
.st_info
);
1289 is_thumb
= (type
== STT_ARM_TFUNC
) || (type
== STT_ARM_16BIT
);
1293 info
->bytes_per_chunk
= 4;
1294 info
->display_endian
= little
? BFD_ENDIAN_LITTLE
: BFD_ENDIAN_BIG
;
1298 status
= info
->read_memory_func (pc
, (bfd_byte
*) &b
[0], 4, info
);
1299 if (status
!= 0 && is_thumb
)
1301 info
->bytes_per_chunk
= 2;
1303 status
= info
->read_memory_func (pc
, (bfd_byte
*) b
, 2, info
);
1309 info
->memory_error_func (status
, pc
, info
);
1313 given
= (b
[0]) | (b
[1] << 8) | (b
[2] << 16) | (b
[3] << 24);
1317 status
= info
->read_memory_func
1318 (pc
& ~ 0x3, (bfd_byte
*) &b
[0], 4, info
);
1321 info
->memory_error_func (status
, pc
, info
);
1329 given
= (b
[2] << 8) | b
[3];
1331 status
= info
->read_memory_func
1332 ((pc
+ 4) & ~ 0x3, (bfd_byte
*) b
, 4, info
);
1335 info
->memory_error_func (status
, pc
+ 4, info
);
1339 given
|= (b
[0] << 24) | (b
[1] << 16);
1342 given
= (b
[0] << 8) | b
[1] | (b
[2] << 24) | (b
[3] << 16);
1345 given
= (b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | (b
[3]);
1348 if (info
->flags
& INSN_HAS_RELOC
)
1349 /* If the instruction has a reloc associated with it, then
1350 the offset field in the instruction will actually be the
1351 addend for the reloc. (We are using REL type relocs).
1352 In such cases, we can ignore the pc when computing
1353 addresses, since the addend is not currently pc-relative. */
1357 status
= print_insn_thumb (pc
, info
, given
);
1359 status
= print_insn_arm (pc
, info
, given
);
1365 print_insn_big_arm (pc
, info
)
1367 struct disassemble_info
* info
;
1369 return print_insn (pc
, info
, FALSE
);
1373 print_insn_little_arm (pc
, info
)
1375 struct disassemble_info
* info
;
1377 return print_insn (pc
, info
, TRUE
);
1381 print_arm_disassembler_options (FILE * stream
)
1385 fprintf (stream
, _("\n\
1386 The following ARM specific disassembler options are supported for use with\n\
1387 the -M switch:\n"));
1389 for (i
= NUM_ARM_REGNAMES
; i
--;)
1390 fprintf (stream
, " reg-names-%s %*c%s\n",
1392 (int)(14 - strlen (regnames
[i
].name
)), ' ',
1393 regnames
[i
].description
);
1395 fprintf (stream
, " force-thumb Assume all insns are Thumb insns\n");
1396 fprintf (stream
, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");