1 /* Instruction printing code for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
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"
31 /* FIXME: This shouldn't be done here. */
33 #include "elf/internal.h"
37 #define streq(a,b) (strcmp ((a), (b)) == 0)
41 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
45 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
48 static char * arm_conditional
[] =
49 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
50 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
55 const char * description
;
56 const char * reg_names
[16];
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 bfd_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
92 PARAMS ((long, fprintf_ftype
, void *));
93 static int print_insn_arm
94 PARAMS ((bfd_vma
, struct disassemble_info
*, long));
95 static int print_insn_thumb
96 PARAMS ((bfd_vma
, struct disassemble_info
*, long));
97 static void parse_disassembler_options
100 PARAMS ((bfd_vma
, struct disassemble_info
*, bfd_boolean
));
101 int get_arm_regname_num_options (void);
102 int set_arm_regname_option (int option
);
103 int get_arm_regnames (int option
, const char **setname
,
104 const char **setdescription
,
105 const char ***register_names
);
109 get_arm_regname_num_options ()
111 return NUM_ARM_REGNAMES
;
115 set_arm_regname_option (option
)
118 int old
= regname_selected
;
119 regname_selected
= option
;
124 get_arm_regnames (option
, setname
, setdescription
, register_names
)
126 const char **setname
;
127 const char **setdescription
;
128 const char ***register_names
;
130 *setname
= regnames
[option
].name
;
131 *setdescription
= regnames
[option
].description
;
132 *register_names
= regnames
[option
].reg_names
;
137 arm_decode_shift (given
, func
, stream
)
142 func (stream
, "%s", arm_regnames
[given
& 0xf]);
144 if ((given
& 0xff0) != 0)
146 if ((given
& 0x10) == 0)
148 int amount
= (given
& 0xf80) >> 7;
149 int shift
= (given
& 0x60) >> 5;
155 func (stream
, ", rrx");
162 func (stream
, ", %s #%d", arm_shift
[shift
], amount
);
165 func (stream
, ", %s %s", arm_shift
[(given
& 0x60) >> 5],
166 arm_regnames
[(given
& 0xf00) >> 8]);
170 /* Print one instruction from PC on INFO->STREAM.
171 Return the size of the instruction (always 4 on ARM). */
174 print_insn_arm (pc
, info
, given
)
176 struct disassemble_info
*info
;
179 const struct arm_opcode
*insn
;
180 void *stream
= info
->stream
;
181 fprintf_ftype func
= info
->fprintf_func
;
183 for (insn
= arm_opcodes
; insn
->assembler
; insn
++)
185 if ((given
& insn
->mask
) == insn
->value
)
189 for (c
= insn
->assembler
; *c
; c
++)
200 if (((given
& 0x000f0000) == 0x000f0000)
201 && ((given
& 0x02000000) == 0))
203 int offset
= given
& 0xfff;
205 func (stream
, "[pc");
207 if (given
& 0x01000000)
209 if ((given
& 0x00800000) == 0)
213 func (stream
, ", #%d]", offset
);
217 /* Cope with the possibility of write-back
218 being used. Probably a very dangerous thing
219 for the programmer to do, but who are we to
221 if (given
& 0x00200000)
227 func (stream
, "], #%d", offset
);
229 /* ie ignore the offset. */
233 func (stream
, "\t; ");
234 info
->print_address_func (offset
, info
);
239 arm_regnames
[(given
>> 16) & 0xf]);
240 if ((given
& 0x01000000) != 0)
242 if ((given
& 0x02000000) == 0)
244 int offset
= given
& 0xfff;
246 func (stream
, ", %s#%d",
247 (((given
& 0x00800000) == 0)
248 ? "-" : ""), offset
);
252 func (stream
, ", %s",
253 (((given
& 0x00800000) == 0)
255 arm_decode_shift (given
, func
, stream
);
259 ((given
& 0x00200000) != 0) ? "!" : "");
263 if ((given
& 0x02000000) == 0)
265 int offset
= given
& 0xfff;
267 func (stream
, "], %s#%d",
268 (((given
& 0x00800000) == 0)
269 ? "-" : ""), offset
);
275 func (stream
, "], %s",
276 (((given
& 0x00800000) == 0)
278 arm_decode_shift (given
, func
, stream
);
285 if ((given
& 0x004f0000) == 0x004f0000)
287 /* PC relative with immediate offset. */
288 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
290 if ((given
& 0x00800000) == 0)
293 func (stream
, "[pc, #%d]\t; ", offset
);
295 (*info
->print_address_func
)
296 (offset
+ pc
+ 8, info
);
301 arm_regnames
[(given
>> 16) & 0xf]);
302 if ((given
& 0x01000000) != 0)
305 if ((given
& 0x00400000) == 0x00400000)
308 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
310 func (stream
, ", %s#%d",
311 (((given
& 0x00800000) == 0)
312 ? "-" : ""), offset
);
317 func (stream
, ", %s%s",
318 (((given
& 0x00800000) == 0)
320 arm_regnames
[given
& 0xf]);
324 ((given
& 0x00200000) != 0) ? "!" : "");
329 if ((given
& 0x00400000) == 0x00400000)
332 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
334 func (stream
, "], %s#%d",
335 (((given
& 0x00800000) == 0)
336 ? "-" : ""), offset
);
343 func (stream
, "], %s%s",
344 (((given
& 0x00800000) == 0)
346 arm_regnames
[given
& 0xf]);
353 (*info
->print_address_func
)
354 (BDISP (given
) * 4 + pc
+ 8, info
);
359 arm_conditional
[(given
>> 28) & 0xf]);
368 for (reg
= 0; reg
< 16; reg
++)
369 if ((given
& (1 << reg
)) != 0)
374 func (stream
, "%s", arm_regnames
[reg
]);
381 if ((given
& 0x02000000) != 0)
383 int rotate
= (given
& 0xf00) >> 7;
384 int immed
= (given
& 0xff);
385 immed
= (((immed
<< (32 - rotate
))
386 | (immed
>> rotate
)) & 0xffffffff);
387 func (stream
, "#%d\t; 0x%x", immed
, immed
);
390 arm_decode_shift (given
, func
, stream
);
394 if ((given
& 0x0000f000) == 0x0000f000)
399 if ((given
& 0x01200000) == 0x00200000)
404 func (stream
, "[%s", arm_regnames
[(given
>> 16) & 0xf]);
405 if ((given
& 0x01000000) != 0)
407 int offset
= given
& 0xff;
409 func (stream
, ", %s#%d]%s",
410 ((given
& 0x00800000) == 0 ? "-" : ""),
412 ((given
& 0x00200000) != 0 ? "!" : ""));
418 int offset
= given
& 0xff;
420 func (stream
, "], %s#%d",
421 ((given
& 0x00800000) == 0 ? "-" : ""),
429 /* Print ARM V5 BLX(1) address: pc+25 bits. */
434 if (given
& 0x00800000)
435 /* Is signed, hi bits should be ones. */
436 offset
= (-1) ^ 0x00ffffff;
438 /* Offset is (SignExtend(offset field)<<2). */
439 offset
+= given
& 0x00ffffff;
441 address
= offset
+ pc
+ 8;
443 if (given
& 0x01000000)
444 /* H bit allows addressing to 2-byte boundaries. */
447 info
->print_address_func (address
, info
);
452 /* Print a Cirrus/DSP shift immediate. */
453 /* Immediates are 7bit signed ints with bits 0..3 in
454 bits 0..3 of opcode and bits 4..6 in bits 5..7
459 imm
= (given
& 0xf) | ((given
& 0xe0) >> 1);
461 /* Is ``imm'' a negative number? */
465 func (stream
, "%d", imm
);
483 switch (given
& 0x00408000)
500 switch (given
& 0x00080080)
512 func (stream
, _("<illegal precision>"));
517 switch (given
& 0x00408000)
534 switch (given
& 0x60)
550 case '0': case '1': case '2': case '3': case '4':
551 case '5': case '6': case '7': case '8': case '9':
553 int bitstart
= *c
++ - '0';
555 while (*c
>= '0' && *c
<= '9')
556 bitstart
= (bitstart
* 10) + *c
++ - '0';
563 while (*c
>= '0' && *c
<= '9')
564 bitend
= (bitend
* 10) + *c
++ - '0';
575 reg
= given
>> bitstart
;
576 reg
&= (2 << (bitend
- bitstart
)) - 1;
578 func (stream
, "%s", arm_regnames
[reg
]);
585 reg
= given
>> bitstart
;
586 reg
&= (2 << (bitend
- bitstart
)) - 1;
588 func (stream
, "%d", reg
);
595 reg
= given
>> bitstart
;
596 reg
&= (2 << (bitend
- bitstart
)) - 1;
598 func (stream
, "0x%08x", reg
);
600 /* Some SWI instructions have special
602 if ((given
& 0x0fffffff) == 0x0FF00000)
603 func (stream
, "\t; IMB");
604 else if ((given
& 0x0fffffff) == 0x0FF00001)
605 func (stream
, "\t; IMBRange");
612 reg
= given
>> bitstart
;
613 reg
&= (2 << (bitend
- bitstart
)) - 1;
615 func (stream
, "%01x", reg
& 0xf);
622 reg
= given
>> bitstart
;
623 reg
&= (2 << (bitend
- bitstart
)) - 1;
627 arm_fp_const
[reg
& 7]);
629 func (stream
, "f%d", reg
);
640 int single
= *c
== 'y';
645 case 4: /* Sm pair */
649 regno
= given
& 0x0000000f;
653 regno
+= (given
>> 5) & 1;
658 regno
= (given
>> 12) & 0x0000000f;
662 regno
+= (given
>> 22) & 1;
667 regno
= (given
>> 16) & 0x0000000f;
671 regno
+= (given
>> 7) & 1;
677 regno
= (given
>> 12) & 0x0000000f;
681 regno
+= (given
>> 22) & 1;
690 func (stream
, "%c%d", single
? 's' : 'd', regno
);
694 int count
= given
& 0xff;
701 func (stream
, "-%c%d",
708 else if (bitstart
== 4)
709 func (stream
, ", %c%d}", single
? 's' : 'd',
717 if ((given
& (1 << bitstart
)) == 0)
718 func (stream
, "%c", *c
);
722 if ((given
& (1 << bitstart
)) != 0)
723 func (stream
, "%c", *c
);
727 if ((given
& (1 << bitstart
)) != 0)
728 func (stream
, "%c", *c
++);
730 func (stream
, "%c", *++c
);
743 func (stream
, "%c", *c
);
751 /* Print one instruction from PC on INFO->STREAM.
752 Return the size of the instruction. */
755 print_insn_thumb (pc
, info
, given
)
757 struct disassemble_info
*info
;
760 const struct thumb_opcode
*insn
;
761 void *stream
= info
->stream
;
762 fprintf_ftype func
= info
->fprintf_func
;
764 for (insn
= thumb_opcodes
; insn
->assembler
; insn
++)
766 if ((given
& insn
->mask
) == insn
->value
)
768 char * c
= insn
->assembler
;
770 /* Special processing for Thumb 2 instruction BL sequence: */
771 if (!*c
) /* Check for empty (not NULL) assembler string. */
775 info
->bytes_per_chunk
= 4;
776 info
->bytes_per_line
= 4;
778 offset
= BDISP23 (given
);
779 offset
= offset
* 2 + pc
+ 4;
781 if ((given
& 0x10000000) == 0)
783 func (stream
, "blx\t");
784 offset
&= 0xfffffffc;
787 func (stream
, "bl\t");
789 info
->print_address_func (offset
, info
);
794 info
->bytes_per_chunk
= 2;
795 info
->bytes_per_line
= 4;
816 reg
= (given
>> 3) & 0x7;
817 if (given
& (1 << 6))
820 func (stream
, "%s", arm_regnames
[reg
]);
829 if (given
& (1 << 7))
832 func (stream
, "%s", arm_regnames
[reg
]);
838 arm_conditional
[(given
>> 8) & 0xf]);
842 if (given
& (1 << 8))
846 if (*c
== 'O' && (given
& (1 << 8)))
856 /* It would be nice if we could spot
857 ranges, and generate the rS-rE format: */
858 for (reg
= 0; (reg
< 8); reg
++)
859 if ((given
& (1 << reg
)) != 0)
864 func (stream
, "%s", arm_regnames
[reg
]);
872 func (stream
, arm_regnames
[14] /* "lr" */);
879 func (stream
, arm_regnames
[15] /* "pc" */);
887 case '0': case '1': case '2': case '3': case '4':
888 case '5': case '6': case '7': case '8': case '9':
890 int bitstart
= *c
++ - '0';
893 while (*c
>= '0' && *c
<= '9')
894 bitstart
= (bitstart
* 10) + *c
++ - '0';
903 while (*c
>= '0' && *c
<= '9')
904 bitend
= (bitend
* 10) + *c
++ - '0';
907 reg
= given
>> bitstart
;
908 reg
&= (2 << (bitend
- bitstart
)) - 1;
912 func (stream
, "%s", arm_regnames
[reg
]);
916 func (stream
, "%d", reg
);
920 func (stream
, "%d", reg
<< 1);
924 func (stream
, "%d", reg
<< 2);
928 /* PC-relative address -- the bottom two
929 bits of the address are dropped
930 before the calculation. */
931 info
->print_address_func
932 (((pc
+ 4) & ~3) + (reg
<< 2), info
);
936 func (stream
, "0x%04x", reg
);
940 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
941 func (stream
, "%d", reg
);
945 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
946 (*info
->print_address_func
)
947 (reg
* 2 + pc
+ 4, info
);
958 if ((given
& (1 << bitstart
)) != 0)
959 func (stream
, "%c", *c
);
964 if ((given
& (1 << bitstart
)) != 0)
965 func (stream
, "%c", *c
++);
967 func (stream
, "%c", *++c
);
981 func (stream
, "%c", *c
);
992 /* Parse an individual disassembler option. */
995 parse_arm_disassembler_option (option
)
1001 if (strneq (option
, "reg-names-", 10))
1007 for (i
= NUM_ARM_REGNAMES
; i
--;)
1008 if (streq (option
, regnames
[i
].name
))
1010 regname_selected
= i
;
1015 fprintf (stderr
, _("Unrecognised register name set: %s\n"), option
);
1017 else if (streq (option
, "force-thumb"))
1019 else if (streq (option
, "no-force-thumb"))
1022 fprintf (stderr
, _("Unrecognised disassembler option: %s\n"), option
);
1027 /* Parse the string of disassembler options, spliting it at whitespaces. */
1030 parse_disassembler_options (options
)
1035 if (options
== NULL
)
1040 space
= strchr (options
, ' ');
1045 parse_arm_disassembler_option (options
);
1047 options
= space
+ 1;
1050 parse_arm_disassembler_option (options
);
1055 /* NOTE: There are no checks in these routines that
1056 the relevant number of data bytes exist. */
1059 print_insn (pc
, info
, little
)
1061 struct disassemble_info
* info
;
1069 if (info
->disassembler_options
)
1071 parse_disassembler_options (info
->disassembler_options
);
1073 /* To avoid repeated parsing of these options, we remove them here. */
1074 info
->disassembler_options
= NULL
;
1077 is_thumb
= force_thumb
;
1079 if (!is_thumb
&& info
->symbols
!= NULL
)
1081 if (bfd_asymbol_flavour (*info
->symbols
) == bfd_target_coff_flavour
)
1083 coff_symbol_type
* cs
;
1085 cs
= coffsymbol (*info
->symbols
);
1086 is_thumb
= ( cs
->native
->u
.syment
.n_sclass
== C_THUMBEXT
1087 || cs
->native
->u
.syment
.n_sclass
== C_THUMBSTAT
1088 || cs
->native
->u
.syment
.n_sclass
== C_THUMBLABEL
1089 || cs
->native
->u
.syment
.n_sclass
== C_THUMBEXTFUNC
1090 || cs
->native
->u
.syment
.n_sclass
== C_THUMBSTATFUNC
);
1092 else if (bfd_asymbol_flavour (*info
->symbols
) == bfd_target_elf_flavour
)
1094 elf_symbol_type
* es
;
1097 es
= *(elf_symbol_type
**)(info
->symbols
);
1098 type
= ELF_ST_TYPE (es
->internal_elf_sym
.st_info
);
1100 is_thumb
= (type
== STT_ARM_TFUNC
) || (type
== STT_ARM_16BIT
);
1104 info
->bytes_per_chunk
= 4;
1105 info
->display_endian
= little
? BFD_ENDIAN_LITTLE
: BFD_ENDIAN_BIG
;
1109 status
= info
->read_memory_func (pc
, (bfd_byte
*) &b
[0], 4, info
);
1110 if (status
!= 0 && is_thumb
)
1112 info
->bytes_per_chunk
= 2;
1114 status
= info
->read_memory_func (pc
, (bfd_byte
*) b
, 2, info
);
1120 info
->memory_error_func (status
, pc
, info
);
1124 given
= (b
[0]) | (b
[1] << 8) | (b
[2] << 16) | (b
[3] << 24);
1128 status
= info
->read_memory_func
1129 (pc
& ~ 0x3, (bfd_byte
*) &b
[0], 4, info
);
1132 info
->memory_error_func (status
, pc
, info
);
1140 given
= (b
[2] << 8) | b
[3];
1142 status
= info
->read_memory_func
1143 ((pc
+ 4) & ~ 0x3, (bfd_byte
*) b
, 4, info
);
1146 info
->memory_error_func (status
, pc
+ 4, info
);
1150 given
|= (b
[0] << 24) | (b
[1] << 16);
1153 given
= (b
[0] << 8) | b
[1] | (b
[2] << 24) | (b
[3] << 16);
1156 given
= (b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | (b
[3]);
1159 if (info
->flags
& INSN_HAS_RELOC
)
1160 /* If the instruction has a reloc associated with it, then
1161 the offset field in the instruction will actually be the
1162 addend for the reloc. (We are using REL type relocs).
1163 In such cases, we can ignore the pc when computing
1164 addresses, since the addend is not currently pc-relative. */
1168 status
= print_insn_thumb (pc
, info
, given
);
1170 status
= print_insn_arm (pc
, info
, given
);
1176 print_insn_big_arm (pc
, info
)
1178 struct disassemble_info
* info
;
1180 return print_insn (pc
, info
, FALSE
);
1184 print_insn_little_arm (pc
, info
)
1186 struct disassemble_info
* info
;
1188 return print_insn (pc
, info
, TRUE
);
1192 print_arm_disassembler_options (FILE * stream
)
1196 fprintf (stream
, _("\n\
1197 The following ARM specific disassembler options are supported for use with\n\
1198 the -M switch:\n"));
1200 for (i
= NUM_ARM_REGNAMES
; i
--;)
1201 fprintf (stream
, " reg-names-%s %*c%s\n",
1203 (int)(14 - strlen (regnames
[i
].name
)), ' ',
1204 regnames
[i
].description
);
1206 fprintf (stream
, " force-thumb Assume all insns are Thumb insns\n");
1207 fprintf (stream
, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");