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)
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 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
);
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
;
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
;
129 arm_decode_shift (given
, func
, 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;
147 func (stream
, ", rrx");
154 func (stream
, ", %s #%d", arm_shift
[shift
], amount
);
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). */
165 print_insn_arm (pc
, info
, given
)
167 struct disassemble_info
* info
;
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
)
180 for (c
= insn
->assembler
; *c
; c
++)
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)
204 func (stream
, ", #%d]", offset
);
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
212 if (given
& 0x00200000)
218 func (stream
, "], #%d", offset
);
220 offset
= pc
+ 8; /* ie ignore the offset. */
223 func (stream
, "\t; ");
224 info
->print_address_func (offset
, info
);
229 arm_regnames
[(given
>> 16) & 0xf]);
230 if ((given
& 0x01000000) != 0)
232 if ((given
& 0x02000000) == 0)
234 int offset
= given
& 0xfff;
236 func (stream
, ", %s#%d",
237 (((given
& 0x00800000) == 0)
238 ? "-" : ""), offset
);
242 func (stream
, ", %s",
243 (((given
& 0x00800000) == 0)
245 arm_decode_shift (given
, func
, stream
);
249 ((given
& 0x00200000) != 0) ? "!" : "");
253 if ((given
& 0x02000000) == 0)
255 int offset
= given
& 0xfff;
257 func (stream
, "], %s#%d",
258 (((given
& 0x00800000) == 0)
259 ? "-" : ""), offset
);
265 func (stream
, "], %s",
266 (((given
& 0x00800000) == 0)
268 arm_decode_shift (given
, func
, stream
);
275 if ((given
& 0x004f0000) == 0x004f0000)
277 /* PC relative with immediate offset. */
278 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
280 if ((given
& 0x00800000) == 0)
283 func (stream
, "[pc, #%d]\t; ", offset
);
285 (*info
->print_address_func
)
286 (offset
+ pc
+ 8, info
);
291 arm_regnames
[(given
>> 16) & 0xf]);
292 if ((given
& 0x01000000) != 0)
295 if ((given
& 0x00400000) == 0x00400000)
298 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
300 func (stream
, ", %s#%d",
301 (((given
& 0x00800000) == 0)
302 ? "-" : ""), offset
);
307 func (stream
, ", %s%s",
308 (((given
& 0x00800000) == 0)
310 arm_regnames
[given
& 0xf]);
314 ((given
& 0x00200000) != 0) ? "!" : "");
319 if ((given
& 0x00400000) == 0x00400000)
322 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
324 func (stream
, "], %s#%d",
325 (((given
& 0x00800000) == 0)
326 ? "-" : ""), offset
);
333 func (stream
, "], %s%s",
334 (((given
& 0x00800000) == 0)
336 arm_regnames
[given
& 0xf]);
343 (*info
->print_address_func
)
344 (BDISP (given
) * 4 + pc
+ 8, info
);
349 arm_conditional
[(given
>> 28) & 0xf]);
358 for (reg
= 0; reg
< 16; reg
++)
359 if ((given
& (1 << reg
)) != 0)
364 func (stream
, "%s", arm_regnames
[reg
]);
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
);
380 arm_decode_shift (given
, func
, stream
);
384 if ((given
& 0x0000f000) == 0x0000f000)
389 if ((given
& 0x01200000) == 0x00200000)
394 if ((given
& 0x00000020) == 0x00000020)
401 func (stream
, "[%s", arm_regnames
[(given
>> 16) & 0xf]);
402 if ((given
& 0x01000000) != 0)
404 int offset
= given
& 0xff;
406 func (stream
, ", %s#%d]%s",
407 ((given
& 0x00800000) == 0 ? "-" : ""),
409 ((given
& 0x00200000) != 0 ? "!" : ""));
415 int offset
= given
& 0xff;
417 func (stream
, "], %s#%d",
418 ((given
& 0x00800000) == 0 ? "-" : ""),
426 /* Print ARM V5 BLX(1) address: pc+25 bits. */
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;
438 address
= offset
+ pc
+ 8;
440 if (given
& 0x01000000)
441 /* H bit allows addressing to 2-byte boundaries. */
444 info
->print_address_func (address
, info
);
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
456 imm
= (given
& 0xf) | ((given
& 0xe0) >> 1);
458 /* Is ``imm'' a negative number? */
462 func (stream
, "%d", imm
);
480 switch (given
& 0x00408000)
497 switch (given
& 0x00080080)
509 func (stream
, _("<illegal precision>"));
514 switch (given
& 0x00408000)
531 switch (given
& 0x60)
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';
552 while (*c
>= '0' && *c
<= '9')
553 bitstart
= (bitstart
* 10) + *c
++ - '0';
560 while (*c
>= '0' && *c
<= '9')
561 bitend
= (bitend
* 10) + *c
++ - '0';
572 reg
= given
>> bitstart
;
573 reg
&= (2 << (bitend
- bitstart
)) - 1;
575 func (stream
, "%s", arm_regnames
[reg
]);
582 reg
= given
>> bitstart
;
583 reg
&= (2 << (bitend
- bitstart
)) - 1;
585 func (stream
, "%d", reg
);
592 reg
= given
>> bitstart
;
593 reg
&= (2 << (bitend
- bitstart
)) - 1;
595 func (stream
, "0x%08x", reg
);
597 /* Some SWI instructions have special
599 if ((given
& 0x0fffffff) == 0x0FF00000)
600 func (stream
, "\t; IMB");
601 else if ((given
& 0x0fffffff) == 0x0FF00001)
602 func (stream
, "\t; IMBRange");
609 reg
= given
>> bitstart
;
610 reg
&= (2 << (bitend
- bitstart
)) - 1;
612 func (stream
, "%01x", reg
& 0xf);
619 reg
= given
>> bitstart
;
620 reg
&= (2 << (bitend
- bitstart
)) - 1;
624 arm_fp_const
[reg
& 7]);
626 func (stream
, "f%d", reg
);
636 if ((given
& (1 << bitstart
)) == 0)
637 func (stream
, "%c", *c
);
641 if ((given
& (1 << bitstart
)) != 0)
642 func (stream
, "%c", *c
);
646 if ((given
& (1 << bitstart
)) != 0)
647 func (stream
, "%c", *c
++);
649 func (stream
, "%c", *++c
);
662 func (stream
, "%c", *c
);
670 /* Print one instruction from PC on INFO->STREAM.
671 Return the size of the instruction. */
673 print_insn_thumb (pc
, info
, given
)
675 struct disassemble_info
* info
;
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. */
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. */
707 /* func (stream, "*malformed!* "); */
711 offset
|= ((pc
& 0x2) >> 1);
714 func (stream
, "bl\t");
716 info
->print_address_func (offset
* 2 + pc
+ 4, info
);
721 info
->bytes_per_chunk
= 2;
722 info
->bytes_per_line
= 4;
743 reg
= (given
>> 3) & 0x7;
744 if (given
& (1 << 6))
747 func (stream
, "%s", arm_regnames
[reg
]);
756 if (given
& (1 << 7))
759 func (stream
, "%s", arm_regnames
[reg
]);
765 arm_conditional
[(given
>> 8) & 0xf]);
769 if (given
& (1 << 8))
773 if (*c
== 'O' && (given
& (1 << 8)))
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)
791 func (stream
, "%s", arm_regnames
[reg
]);
799 func (stream
, arm_regnames
[14] /* "lr" */);
806 func (stream
, arm_regnames
[15] /* "pc" */);
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';
820 while (*c
>= '0' && *c
<= '9')
821 bitstart
= (bitstart
* 10) + *c
++ - '0';
830 while (*c
>= '0' && *c
<= '9')
831 bitend
= (bitend
* 10) + *c
++ - '0';
834 reg
= given
>> bitstart
;
835 reg
&= (2 << (bitend
- bitstart
)) - 1;
839 func (stream
, "%s", arm_regnames
[reg
]);
843 func (stream
, "%d", reg
);
847 func (stream
, "%d", reg
<< 1);
851 func (stream
, "%d", reg
<< 2);
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
);
863 func (stream
, "0x%04x", reg
);
867 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
868 func (stream
, "%d", reg
);
872 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
873 (*info
->print_address_func
)
874 (reg
* 2 + pc
+ 4, info
);
885 if ((given
& (1 << bitstart
)) != 0)
886 func (stream
, "%c", *c
);
891 if ((given
& (1 << bitstart
)) != 0)
892 func (stream
, "%c", *c
++);
894 func (stream
, "%c", *++c
);
908 func (stream
, "%c", *c
);
919 /* Parse an individual disassembler option. */
921 parse_arm_disassembler_option (option
)
927 if (strneq (option
, "reg-names-", 10))
933 for (i
= NUM_ARM_REGNAMES
; i
--;)
934 if (streq (option
, regnames
[i
].name
))
936 regname_selected
= i
;
941 fprintf (stderr
, _("Unrecognised register name set: %s\n"), option
);
943 else if (streq (option
, "force-thumb"))
945 else if (streq (option
, "no-force-thumb"))
948 fprintf (stderr
, _("Unrecognised disassembler option: %s\n"), option
);
953 /* Parse the string of disassembler options, spliting it at whitespaces. */
955 parse_disassembler_options (options
)
965 space
= strchr (options
, ' ');
970 parse_arm_disassembler_option (options
);
975 parse_arm_disassembler_option (options
);
980 /* NOTE: There are no checks in these routines that
981 the relevant number of data bytes exist. */
983 print_insn (pc
, info
, little
)
985 struct disassemble_info
* info
;
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
;
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
;
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
);
1044 info
->memory_error_func (status
, pc
, info
);
1048 given
= (b
[0]) | (b
[1] << 8) | (b
[2] << 16) | (b
[3] << 24);
1052 status
= info
->read_memory_func
1053 (pc
& ~ 0x3, (bfd_byte
*) &b
[0], 4, info
);
1056 info
->memory_error_func (status
, pc
, info
);
1064 given
= (b
[2] << 8) | b
[3];
1066 status
= info
->read_memory_func
1067 ((pc
+ 4) & ~ 0x3, (bfd_byte
*) b
, 4, info
);
1070 info
->memory_error_func (status
, pc
+ 4, info
);
1074 given
|= (b
[0] << 24) | (b
[1] << 16);
1077 given
= (b
[0] << 8) | b
[1] | (b
[2] << 24) | (b
[3] << 16);
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. */
1092 status
= print_insn_thumb (pc
, info
, given
);
1094 status
= print_insn_arm (pc
, info
, given
);
1100 print_insn_big_arm (pc
, info
)
1102 struct disassemble_info
* info
;
1104 return print_insn (pc
, info
, false);
1108 print_insn_little_arm (pc
, info
)
1110 struct disassemble_info
* info
;
1112 return print_insn (pc
, info
, true);
1116 print_arm_disassembler_options (FILE * stream
)
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",
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");