]> git.proxmox.com Git - qemu.git/blame_incremental - arm-dis.c
x86_64 target support
[qemu.git] / arm-dis.c
... / ...
CommitLineData
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)
6
7This file is part of libopcodes.
8
9This program is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 2 of the License, or (at your option)
12any later version.
13
14This program is distributed in the hope that it will be useful, but WITHOUT
15ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23#include "dis-asm.h"
24
25struct arm_opcode {
26 unsigned long value, mask; /* recognise instruction if (op&mask)==value */
27 char *assembler; /* how to disassemble this instruction */
28};
29
30struct thumb_opcode
31{
32 unsigned short value, mask; /* recognise instruction if (op&mask)==value */
33 char * assembler; /* how to disassemble this instruction */
34};
35
36/* format of the assembler string :
37
38 %% %
39 %<bitfield>d print the bitfield in decimal
40 %<bitfield>x print the bitfield in hex
41 %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
42 %<bitfield>r print as an ARM register
43 %<bitfield>f print a floating point constant if >7 else a
44 floating point register
45 %<code>y print a single precision VFP reg.
46 Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
47 %<code>z print a double precision VFP reg
48 Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
49 %c print condition code (always bits 28-31)
50 %P print floating point precision in arithmetic insn
51 %Q print floating point precision in ldf/stf insn
52 %R print floating point rounding mode
53 %<bitnum>'c print specified char iff bit is one
54 %<bitnum>`c print specified char iff bit is zero
55 %<bitnum>?ab print a if bit is one else print b
56 %p print 'p' iff bits 12-15 are 15
57 %t print 't' iff bit 21 set and bit 24 clear
58 %o print operand2 (immediate or register + shift)
59 %a print address for ldr/str instruction
60 %s print address for ldr/str halfword/signextend instruction
61 %b print branch destination
62 %B print arm BLX(1) destination
63 %A print address for ldc/stc/ldf/stf instruction
64 %m print register mask for ldm/stm instruction
65 %C print the PSR sub type.
66 %F print the COUNT field of a LFM/SFM instruction.
67Thumb specific format options:
68 %D print Thumb register (bits 0..2 as high number if bit 7 set)
69 %S print Thumb register (bits 3..5 as high number if bit 6 set)
70 %<bitfield>I print bitfield as a signed decimal
71 (top bit of range being the sign bit)
72 %M print Thumb register mask
73 %N print Thumb register mask (with LR)
74 %O print Thumb register mask (with PC)
75 %T print Thumb condition code (always bits 8-11)
76 %I print cirrus signed shift immediate: bits 0..3|4..6
77 %<bitfield>B print Thumb branch destination (signed displacement)
78 %<bitfield>W print (bitfield * 4) as a decimal
79 %<bitfield>H print (bitfield * 2) as a decimal
80 %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
81*/
82
83/* Note: There is a partial ordering in this table - it must be searched from
84 the top to obtain a correct match. */
85
86static struct arm_opcode arm_opcodes[] =
87{
88 /* ARM instructions. */
89 {0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
90 {0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
91 {0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
92 {0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
93 {0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
94 {0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
95 {0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
96
97 /* V5J instruction. */
98 {0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
99
100 /* XScale instructions. */
101 {0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
102 {0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
103 {0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
104 {0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
105 {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
106 {0xf450f000, 0xfc70f000, "pld\t%a"},
107
108 /* V5 Instructions. */
109 {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
110 {0xfa000000, 0xfe000000, "blx\t%B"},
111 {0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
112 {0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
113 {0xfc100000, 0xfe100000, "ldc2%22'l\t%8-11d, cr%12-15d, %A"},
114 {0xfc000000, 0xfe100000, "stc2%22'l\t%8-11d, cr%12-15d, %A"},
115 {0xfe000000, 0xff000010, "cdp2\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
116 {0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
117 {0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
118
119 /* V5E "El Segundo" Instructions. */
120 {0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
121 {0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
122 {0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
123 {0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
124 {0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
125 {0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
126
127 {0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
128 {0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
129
130 {0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
131 {0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
132 {0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
133 {0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
134
135 {0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
136 {0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
137 {0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
138 {0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
139
140 {0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
141 {0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
142
143 {0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
144 {0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
145 {0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
146 {0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
147
148 {0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
149 {0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
150
151 /* ARM Instructions. */
152 {0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
153 {0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
154 {0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
155 {0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
156 {0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
157 {0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
158 {0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
159 {0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
160 {0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
161 {0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
162 {0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
163 {0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
164 {0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
165 {0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
166 {0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
167 {0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
168 {0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
169 {0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
170 {0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
171 {0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
172 {0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
173 {0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
174 {0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
175 {0x06000010, 0x0e000010, "undefined"},
176 {0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
177 {0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
178 {0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
179 {0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
180 {0x0f000000, 0x0f000000, "swi%c\t%0-23x"},
181
182 /* Floating point coprocessor (FPA) instructions */
183 {0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
184 {0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
185 {0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
186 {0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
187 {0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
188 {0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
189 {0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
190 {0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
191 {0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
192 {0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
193 {0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
194 {0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
195 {0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
196 {0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
197 {0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
198 {0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
199 {0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
200 {0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
201 {0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
202 {0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
203 {0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
204 {0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
205 {0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
206 {0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
207 {0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
208 {0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
209 {0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
210 {0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
211 {0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
212 {0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
213 {0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
214 {0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
215 {0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
216 {0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
217 {0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
218 {0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
219 {0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
220 {0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
221 {0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
222 {0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
223 {0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
224 {0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
225 {0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
226
227 /* Floating point coprocessor (VFP) instructions */
228 {0x0eb00bc0, 0x0fff0ff0, "fabsd%c\t%1z, %0z"},
229 {0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%1y, %0y"},
230 {0x0e300b00, 0x0ff00ff0, "faddd%c\t%1z, %2z, %0z"},
231 {0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %1y"},
232 {0x0eb40b40, 0x0fff0f70, "fcmp%7'ed%c\t%1z, %0z"},
233 {0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%1y, %0y"},
234 {0x0eb50b40, 0x0fff0f70, "fcmp%7'ezd%c\t%1z"},
235 {0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%1y"},
236 {0x0eb00b40, 0x0fff0ff0, "fcpyd%c\t%1z, %0z"},
237 {0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%1y, %0y"},
238 {0x0eb70ac0, 0x0fff0fd0, "fcvtds%c\t%1z, %0y"},
239 {0x0eb70bc0, 0x0fbf0ff0, "fcvtsd%c\t%1y, %0z"},
240 {0x0e800b00, 0x0ff00ff0, "fdivd%c\t%1z, %2z, %0z"},
241 {0x0e800a00, 0x0fb00f50, "fdivs%c\t%1y, %2y, %0y"},
242 {0x0d100b00, 0x0f700f00, "fldd%c\t%1z, %A"},
243 {0x0c900b00, 0x0fd00f00, "fldmia%0?xd%c\t%16-19r%21'!, %3z"},
244 {0x0d300b00, 0x0ff00f00, "fldmdb%0?xd%c\t%16-19r!, %3z"},
245 {0x0d100a00, 0x0f300f00, "flds%c\t%1y, %A"},
246 {0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %3y"},
247 {0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %3y"},
248 {0x0e000b00, 0x0ff00ff0, "fmacd%c\t%1z, %2z, %0z"},
249 {0x0e000a00, 0x0fb00f50, "fmacs%c\t%1y, %2y, %0y"},
250 {0x0e200b10, 0x0ff00fff, "fmdhr%c\t%2z, %12-15r"},
251 {0x0e000b10, 0x0ff00fff, "fmdlr%c\t%2z, %12-15r"},
252 {0x0c400b10, 0x0ff00ff0, "fmdrr%c\t%0z, %12-15r, %16-19r"},
253 {0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %2z"},
254 {0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %2z"},
255 {0x0c500b10, 0x0ff00ff0, "fmrrd%c\t%12-15r, %16-19r, %0z"},
256 {0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %4y"},
257 {0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %2y"},
258 {0x0ef1fa10, 0x0fffffff, "fmstat%c"},
259 {0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
260 {0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
261 {0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
262 {0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
263 {0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
264 {0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def 0x%16-19x>"},
265 {0x0e100b00, 0x0ff00ff0, "fmscd%c\t%1z, %2z, %0z"},
266 {0x0e100a00, 0x0fb00f50, "fmscs%c\t%1y, %2y, %0y"},
267 {0x0e000a10, 0x0ff00f7f, "fmsr%c\t%2y, %12-15r"},
268 {0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%12-15r, %16-19r, %4y"},
269 {0x0e200b00, 0x0ff00ff0, "fmuld%c\t%1z, %2z, %0z"},
270 {0x0e200a00, 0x0fb00f50, "fmuls%c\t%1y, %2y, %0y"},
271 {0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
272 {0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
273 {0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
274 {0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
275 {0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
276 {0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def 0x%16-19x>, %12-15r"},
277 {0x0eb10b40, 0x0fff0ff0, "fnegd%c\t%1z, %0z"},
278 {0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%1y, %0y"},
279 {0x0e000b40, 0x0ff00ff0, "fnmacd%c\t%1z, %2z, %0z"},
280 {0x0e000a40, 0x0fb00f50, "fnmacs%c\t%1y, %2y, %0y"},
281 {0x0e100b40, 0x0ff00ff0, "fnmscd%c\t%1z, %2z, %0z"},
282 {0x0e100a40, 0x0fb00f50, "fnmscs%c\t%1y, %2y, %0y"},
283 {0x0e200b40, 0x0ff00ff0, "fnmuld%c\t%1z, %2z, %0z"},
284 {0x0e200a40, 0x0fb00f50, "fnmuls%c\t%1y, %2y, %0y"},
285 {0x0eb80bc0, 0x0fff0fd0, "fsitod%c\t%1z, %0y"},
286 {0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%1y, %0y"},
287 {0x0eb10bc0, 0x0fff0ff0, "fsqrtd%c\t%1z, %0z"},
288 {0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%1y, %0y"},
289 {0x0d000b00, 0x0f700f00, "fstd%c\t%1z, %A"},
290 {0x0c800b00, 0x0fd00f00, "fstmia%0?xd%c\t%16-19r%21'!, %3z"},
291 {0x0d200b00, 0x0ff00f00, "fstmdb%0?xd%c\t%16-19r!, %3z"},
292 {0x0d000a00, 0x0f300f00, "fsts%c\t%1y, %A"},
293 {0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %3y"},
294 {0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %3y"},
295 {0x0e300b40, 0x0ff00ff0, "fsubd%c\t%1z, %2z, %0z"},
296 {0x0e300a40, 0x0fb00f50, "fsubs%c\t%1y, %2y, %0y"},
297 {0x0ebc0b40, 0x0fbe0f70, "fto%16?sui%7'zd%c\t%1y, %0z"},
298 {0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%1y, %0y"},
299 {0x0eb80b40, 0x0fff0fd0, "fuitod%c\t%1z, %0y"},
300 {0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%1y, %0y"},
301
302 /* Cirrus coprocessor instructions. */
303 {0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
304 {0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
305 {0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
306 {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
307 {0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
308 {0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
309 {0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
310 {0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
311 {0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
312 {0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
313 {0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
314 {0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
315 {0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
316 {0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
317 {0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
318 {0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
319 {0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
320 {0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
321 {0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
322 {0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
323 {0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
324 {0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
325 {0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
326 {0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
327 {0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
328 {0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
329 {0x0e100610, 0x0ff0fff0, "cfmval32%c\tmvax%0-3d, mvfx%16-19d"},
330 {0x0e000610, 0x0ff0fff0, "cfmv32al%c\tmvfx%0-3d, mvax%16-19d"},
331 {0x0e100630, 0x0ff0fff0, "cfmvam32%c\tmvax%0-3d, mvfx%16-19d"},
332 {0x0e000630, 0x0ff0fff0, "cfmv32am%c\tmvfx%0-3d, mvax%16-19d"},
333 {0x0e100650, 0x0ff0fff0, "cfmvah32%c\tmvax%0-3d, mvfx%16-19d"},
334 {0x0e000650, 0x0ff0fff0, "cfmv32ah%c\tmvfx%0-3d, mvax%16-19d"},
335 {0x0e000670, 0x0ff0fff0, "cfmv32a%c\tmvfx%0-3d, mvax%16-19d"},
336 {0x0e100670, 0x0ff0fff0, "cfmva32%c\tmvax%0-3d, mvfx%16-19d"},
337 {0x0e000690, 0x0ff0fff0, "cfmv64a%c\tmvdx%0-3d, mvax%16-19d"},
338 {0x0e100690, 0x0ff0fff0, "cfmva64%c\tmvax%0-3d, mvdx%16-19d"},
339 {0x0e1006b0, 0x0ff0fff0, "cfmvsc32%c\tdspsc, mvfx%16-19d"},
340 {0x0e0006b0, 0x0ff0fff0, "cfmv32sc%c\tmvfx%0-3d, dspsc"},
341 {0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
342 {0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
343 {0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
344 {0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
345 {0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
346 {0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
347 {0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
348 {0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
349 {0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
350 {0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
351 {0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
352 {0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
353 {0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
354 {0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
355 {0x0e000500, 0x0ff00f00, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
356 {0x0e200500, 0x0ff00f00, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
357 {0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
358 {0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
359 {0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
360 {0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
361 {0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
362 {0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
363 {0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
364 {0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
365 {0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
366 {0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
367 {0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
368 {0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
369 {0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
370 {0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
371 {0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
372 {0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
373 {0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
374 {0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
375 {0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
376 {0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
377 {0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
378 {0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
379 {0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
380 {0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
381 {0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
382 {0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
383 {0x0e000600, 0x0ff00f00, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
384 {0x0e100600, 0x0ff00f00, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
385 {0x0e200600, 0x0ff00f00, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
386 {0x0e300600, 0x0ff00f00, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
387
388 /* Generic coprocessor instructions */
389 {0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
390 {0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
391 {0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
392 {0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
393 {0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
394
395 /* The rest. */
396 {0x00000000, 0x00000000, "undefined instruction %0-31x"},
397 {0x00000000, 0x00000000, 0}
398};
399
400#define BDISP(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000) /* 26 bit */
401
402static struct thumb_opcode thumb_opcodes[] =
403{
404 /* Thumb instructions. */
405
406 /* ARM V5 ISA extends Thumb. */
407 {0xbe00, 0xff00, "bkpt\t%0-7x"},
408 {0x4780, 0xff87, "blx\t%3-6r"}, /* note: 4 bit register number. */
409 /* Note: this is BLX(2). BLX(1) is done in arm-dis.c/print_insn_thumb()
410 as an extension of the special processing there for Thumb BL.
411 BL and BLX(1) involve 2 successive 16-bit instructions, which must
412 always appear together in the correct order. So, the empty
413 string is put in this table, and the string interpreter takes <empty>
414 to mean it has a pair of BL-ish instructions. */
415 {0x46C0, 0xFFFF, "nop\t\t\t(mov r8, r8)"},
416 /* Format 5 instructions do not update the PSR. */
417 {0x1C00, 0xFFC0, "mov\t%0-2r, %3-5r\t\t(add %0-2r, %3-5r, #%6-8d)"},
418 /* Format 4. */
419 {0x4000, 0xFFC0, "and\t%0-2r, %3-5r"},
420 {0x4040, 0xFFC0, "eor\t%0-2r, %3-5r"},
421 {0x4080, 0xFFC0, "lsl\t%0-2r, %3-5r"},
422 {0x40C0, 0xFFC0, "lsr\t%0-2r, %3-5r"},
423 {0x4100, 0xFFC0, "asr\t%0-2r, %3-5r"},
424 {0x4140, 0xFFC0, "adc\t%0-2r, %3-5r"},
425 {0x4180, 0xFFC0, "sbc\t%0-2r, %3-5r"},
426 {0x41C0, 0xFFC0, "ror\t%0-2r, %3-5r"},
427 {0x4200, 0xFFC0, "tst\t%0-2r, %3-5r"},
428 {0x4240, 0xFFC0, "neg\t%0-2r, %3-5r"},
429 {0x4280, 0xFFC0, "cmp\t%0-2r, %3-5r"},
430 {0x42C0, 0xFFC0, "cmn\t%0-2r, %3-5r"},
431 {0x4300, 0xFFC0, "orr\t%0-2r, %3-5r"},
432 {0x4340, 0xFFC0, "mul\t%0-2r, %3-5r"},
433 {0x4380, 0xFFC0, "bic\t%0-2r, %3-5r"},
434 {0x43C0, 0xFFC0, "mvn\t%0-2r, %3-5r"},
435 /* format 13 */
436 {0xB000, 0xFF80, "add\tsp, #%0-6W"},
437 {0xB080, 0xFF80, "sub\tsp, #%0-6W"},
438 /* format 5 */
439 {0x4700, 0xFF80, "bx\t%S"},
440 {0x4400, 0xFF00, "add\t%D, %S"},
441 {0x4500, 0xFF00, "cmp\t%D, %S"},
442 {0x4600, 0xFF00, "mov\t%D, %S"},
443 /* format 14 */
444 {0xB400, 0xFE00, "push\t%N"},
445 {0xBC00, 0xFE00, "pop\t%O"},
446 /* format 2 */
447 {0x1800, 0xFE00, "add\t%0-2r, %3-5r, %6-8r"},
448 {0x1A00, 0xFE00, "sub\t%0-2r, %3-5r, %6-8r"},
449 {0x1C00, 0xFE00, "add\t%0-2r, %3-5r, #%6-8d"},
450 {0x1E00, 0xFE00, "sub\t%0-2r, %3-5r, #%6-8d"},
451 /* format 8 */
452 {0x5200, 0xFE00, "strh\t%0-2r, [%3-5r, %6-8r]"},
453 {0x5A00, 0xFE00, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
454 {0x5600, 0xF600, "ldrs%11?hb\t%0-2r, [%3-5r, %6-8r]"},
455 /* format 7 */
456 {0x5000, 0xFA00, "str%10'b\t%0-2r, [%3-5r, %6-8r]"},
457 {0x5800, 0xFA00, "ldr%10'b\t%0-2r, [%3-5r, %6-8r]"},
458 /* format 1 */
459 {0x0000, 0xF800, "lsl\t%0-2r, %3-5r, #%6-10d"},
460 {0x0800, 0xF800, "lsr\t%0-2r, %3-5r, #%6-10d"},
461 {0x1000, 0xF800, "asr\t%0-2r, %3-5r, #%6-10d"},
462 /* format 3 */
463 {0x2000, 0xF800, "mov\t%8-10r, #%0-7d"},
464 {0x2800, 0xF800, "cmp\t%8-10r, #%0-7d"},
465 {0x3000, 0xF800, "add\t%8-10r, #%0-7d"},
466 {0x3800, 0xF800, "sub\t%8-10r, #%0-7d"},
467 /* format 6 */
468 {0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
469 /* format 9 */
470 {0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
471 {0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
472 {0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
473 {0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
474 /* format 10 */
475 {0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
476 {0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
477 /* format 11 */
478 {0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
479 {0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
480 /* format 12 */
481 {0xA000, 0xF800, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
482 {0xA800, 0xF800, "add\t%8-10r, sp, #%0-7W"},
483 /* format 15 */
484 {0xC000, 0xF800, "stmia\t%8-10r!,%M"},
485 {0xC800, 0xF800, "ldmia\t%8-10r!,%M"},
486 /* format 18 */
487 {0xE000, 0xF800, "b\t%0-10B"},
488 {0xE800, 0xF800, "undefined"},
489 /* format 19 */
490 {0xF000, 0xF800, ""}, /* special processing required in disassembler */
491 {0xF800, 0xF800, "second half of BL instruction %0-15x"},
492 /* format 16 */
493 {0xD000, 0xFF00, "beq\t%0-7B"},
494 {0xD100, 0xFF00, "bne\t%0-7B"},
495 {0xD200, 0xFF00, "bcs\t%0-7B"},
496 {0xD300, 0xFF00, "bcc\t%0-7B"},
497 {0xD400, 0xFF00, "bmi\t%0-7B"},
498 {0xD500, 0xFF00, "bpl\t%0-7B"},
499 {0xD600, 0xFF00, "bvs\t%0-7B"},
500 {0xD700, 0xFF00, "bvc\t%0-7B"},
501 {0xD800, 0xFF00, "bhi\t%0-7B"},
502 {0xD900, 0xFF00, "bls\t%0-7B"},
503 {0xDA00, 0xFF00, "bge\t%0-7B"},
504 {0xDB00, 0xFF00, "blt\t%0-7B"},
505 {0xDC00, 0xFF00, "bgt\t%0-7B"},
506 {0xDD00, 0xFF00, "ble\t%0-7B"},
507 /* format 17 */
508 {0xDE00, 0xFF00, "bal\t%0-7B"},
509 {0xDF00, 0xFF00, "swi\t%0-7d"},
510 /* format 9 */
511 {0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
512 {0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
513 {0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
514 {0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
515 /* the rest */
516 {0x0000, 0x0000, "undefined instruction %0-15x"},
517 {0x0000, 0x0000, 0}
518};
519
520#define BDISP23(x) ((((((x) & 0x07ff) << 11) | (((x) & 0x07ff0000) >> 16)) \
521 ^ 0x200000) - 0x200000) /* 23bit */
522
523#ifndef streq
524#define streq(a,b) (strcmp ((a), (b)) == 0)
525#endif
526
527#ifndef strneq
528#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
529#endif
530
531#ifndef NUM_ELEM
532#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
533#endif
534
535static char * arm_conditional[] =
536{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
537 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
538
539typedef struct
540{
541 const char * name;
542 const char * description;
543 const char * reg_names[16];
544}
545arm_regname;
546
547static arm_regname regnames[] =
548{
549 { "raw" , "Select raw register names",
550 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
551 { "gcc", "Select register names used by GCC",
552 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
553 { "std", "Select register names used in ARM's ISA documentation",
554 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
555 { "apcs", "Select register names used in the APCS",
556 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
557 { "atpcs", "Select register names used in the ATPCS",
558 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
559 { "special-atpcs", "Select special register names used in the ATPCS",
560 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}
561};
562
563/* Default to STD register name set. */
564static unsigned int regname_selected = 2;
565
566#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
567#define arm_regnames regnames[regname_selected].reg_names
568
569static boolean force_thumb = false;
570
571static char * arm_fp_const[] =
572{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
573
574static char * arm_shift[] =
575{"lsl", "lsr", "asr", "ror"};
576\f
577/* Forward declarations. */
578static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *));
579static int print_insn_arm1 PARAMS ((bfd_vma, struct disassemble_info *, long));
580static int print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
581static void parse_disassembler_options PARAMS ((char *));
582int get_arm_regname_num_options (void);
583int set_arm_regname_option (int option);
584int get_arm_regnames (int option, const char **setname,
585 const char **setdescription,
586 const char ***register_names);
587\f
588/* Functions. */
589int
590get_arm_regname_num_options ()
591{
592 return NUM_ARM_REGNAMES;
593}
594
595int
596set_arm_regname_option (option)
597 int option;
598{
599 int old = regname_selected;
600 regname_selected = option;
601 return old;
602}
603
604int
605get_arm_regnames (option, setname, setdescription, register_names)
606 int option;
607 const char **setname;
608 const char **setdescription;
609 const char ***register_names;
610{
611 *setname = regnames[option].name;
612 *setdescription = regnames[option].description;
613 *register_names = regnames[option].reg_names;
614 return 16;
615}
616
617static void
618arm_decode_shift (given, func, stream)
619 long given;
620 fprintf_ftype func;
621 void * stream;
622{
623 func (stream, "%s", arm_regnames[given & 0xf]);
624
625 if ((given & 0xff0) != 0)
626 {
627 if ((given & 0x10) == 0)
628 {
629 int amount = (given & 0xf80) >> 7;
630 int shift = (given & 0x60) >> 5;
631
632 if (amount == 0)
633 {
634 if (shift == 3)
635 {
636 func (stream, ", rrx");
637 return;
638 }
639
640 amount = 32;
641 }
642
643 func (stream, ", %s #%d", arm_shift[shift], amount);
644 }
645 else
646 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
647 arm_regnames[(given & 0xf00) >> 8]);
648 }
649}
650
651/* Print one instruction from PC on INFO->STREAM.
652 Return the size of the instruction (always 4 on ARM). */
653
654static int
655print_insn_arm1 (pc, info, given)
656 bfd_vma pc;
657 struct disassemble_info * info;
658 long given;
659{
660 struct arm_opcode * insn;
661 void * stream = info->stream;
662 fprintf_ftype func = info->fprintf_func;
663
664 for (insn = arm_opcodes; insn->assembler; insn++)
665 {
666 if ((given & insn->mask) == insn->value)
667 {
668 char * c;
669
670 for (c = insn->assembler; *c; c++)
671 {
672 if (*c == '%')
673 {
674 switch (*++c)
675 {
676 case '%':
677 func (stream, "%%");
678 break;
679
680 case 'a':
681 if (((given & 0x000f0000) == 0x000f0000)
682 && ((given & 0x02000000) == 0))
683 {
684 int offset = given & 0xfff;
685
686 func (stream, "[pc");
687
688 if (given & 0x01000000)
689 {
690 if ((given & 0x00800000) == 0)
691 offset = - offset;
692
693 /* Pre-indexed. */
694 func (stream, ", #%d]", offset);
695
696 offset += pc + 8;
697
698 /* Cope with the possibility of write-back
699 being used. Probably a very dangerous thing
700 for the programmer to do, but who are we to
701 argue ? */
702 if (given & 0x00200000)
703 func (stream, "!");
704 }
705 else
706 {
707 /* Post indexed. */
708 func (stream, "], #%d", offset);
709
710 /* ie ignore the offset. */
711 offset = pc + 8;
712 }
713
714 func (stream, "\t; ");
715 info->print_address_func (offset, info);
716 }
717 else
718 {
719 func (stream, "[%s",
720 arm_regnames[(given >> 16) & 0xf]);
721 if ((given & 0x01000000) != 0)
722 {
723 if ((given & 0x02000000) == 0)
724 {
725 int offset = given & 0xfff;
726 if (offset)
727 func (stream, ", %s#%d",
728 (((given & 0x00800000) == 0)
729 ? "-" : ""), offset);
730 }
731 else
732 {
733 func (stream, ", %s",
734 (((given & 0x00800000) == 0)
735 ? "-" : ""));
736 arm_decode_shift (given, func, stream);
737 }
738
739 func (stream, "]%s",
740 ((given & 0x00200000) != 0) ? "!" : "");
741 }
742 else
743 {
744 if ((given & 0x02000000) == 0)
745 {
746 int offset = given & 0xfff;
747 if (offset)
748 func (stream, "], %s#%d",
749 (((given & 0x00800000) == 0)
750 ? "-" : ""), offset);
751 else
752 func (stream, "]");
753 }
754 else
755 {
756 func (stream, "], %s",
757 (((given & 0x00800000) == 0)
758 ? "-" : ""));
759 arm_decode_shift (given, func, stream);
760 }
761 }
762 }
763 break;
764
765 case 's':
766 if ((given & 0x004f0000) == 0x004f0000)
767 {
768 /* PC relative with immediate offset. */
769 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
770
771 if ((given & 0x00800000) == 0)
772 offset = -offset;
773
774 func (stream, "[pc, #%d]\t; ", offset);
775
776 (*info->print_address_func)
777 (offset + pc + 8, info);
778 }
779 else
780 {
781 func (stream, "[%s",
782 arm_regnames[(given >> 16) & 0xf]);
783 if ((given & 0x01000000) != 0)
784 {
785 /* Pre-indexed. */
786 if ((given & 0x00400000) == 0x00400000)
787 {
788 /* Immediate. */
789 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
790 if (offset)
791 func (stream, ", %s#%d",
792 (((given & 0x00800000) == 0)
793 ? "-" : ""), offset);
794 }
795 else
796 {
797 /* Register. */
798 func (stream, ", %s%s",
799 (((given & 0x00800000) == 0)
800 ? "-" : ""),
801 arm_regnames[given & 0xf]);
802 }
803
804 func (stream, "]%s",
805 ((given & 0x00200000) != 0) ? "!" : "");
806 }
807 else
808 {
809 /* Post-indexed. */
810 if ((given & 0x00400000) == 0x00400000)
811 {
812 /* Immediate. */
813 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
814 if (offset)
815 func (stream, "], %s#%d",
816 (((given & 0x00800000) == 0)
817 ? "-" : ""), offset);
818 else
819 func (stream, "]");
820 }
821 else
822 {
823 /* Register. */
824 func (stream, "], %s%s",
825 (((given & 0x00800000) == 0)
826 ? "-" : ""),
827 arm_regnames[given & 0xf]);
828 }
829 }
830 }
831 break;
832
833 case 'b':
834 (*info->print_address_func)
835 (BDISP (given) * 4 + pc + 8, info);
836 break;
837
838 case 'c':
839 func (stream, "%s",
840 arm_conditional [(given >> 28) & 0xf]);
841 break;
842
843 case 'm':
844 {
845 int started = 0;
846 int reg;
847
848 func (stream, "{");
849 for (reg = 0; reg < 16; reg++)
850 if ((given & (1 << reg)) != 0)
851 {
852 if (started)
853 func (stream, ", ");
854 started = 1;
855 func (stream, "%s", arm_regnames[reg]);
856 }
857 func (stream, "}");
858 }
859 break;
860
861 case 'o':
862 if ((given & 0x02000000) != 0)
863 {
864 int rotate = (given & 0xf00) >> 7;
865 int immed = (given & 0xff);
866 immed = (((immed << (32 - rotate))
867 | (immed >> rotate)) & 0xffffffff);
868 func (stream, "#%d\t; 0x%x", immed, immed);
869 }
870 else
871 arm_decode_shift (given, func, stream);
872 break;
873
874 case 'p':
875 if ((given & 0x0000f000) == 0x0000f000)
876 func (stream, "p");
877 break;
878
879 case 't':
880 if ((given & 0x01200000) == 0x00200000)
881 func (stream, "t");
882 break;
883
884 case 'A':
885 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
886 if ((given & 0x01000000) != 0)
887 {
888 int offset = given & 0xff;
889 if (offset)
890 func (stream, ", %s#%d]%s",
891 ((given & 0x00800000) == 0 ? "-" : ""),
892 offset * 4,
893 ((given & 0x00200000) != 0 ? "!" : ""));
894 else
895 func (stream, "]");
896 }
897 else
898 {
899 int offset = given & 0xff;
900 if (offset)
901 func (stream, "], %s#%d",
902 ((given & 0x00800000) == 0 ? "-" : ""),
903 offset * 4);
904 else
905 func (stream, "]");
906 }
907 break;
908
909 case 'B':
910 /* Print ARM V5 BLX(1) address: pc+25 bits. */
911 {
912 bfd_vma address;
913 bfd_vma offset = 0;
914
915 if (given & 0x00800000)
916 /* Is signed, hi bits should be ones. */
917 offset = (-1) ^ 0x00ffffff;
918
919 /* Offset is (SignExtend(offset field)<<2). */
920 offset += given & 0x00ffffff;
921 offset <<= 2;
922 address = offset + pc + 8;
923
924 if (given & 0x01000000)
925 /* H bit allows addressing to 2-byte boundaries. */
926 address += 2;
927
928 info->print_address_func (address, info);
929 }
930 break;
931
932 case 'I':
933 /* Print a Cirrus/DSP shift immediate. */
934 /* Immediates are 7bit signed ints with bits 0..3 in
935 bits 0..3 of opcode and bits 4..6 in bits 5..7
936 of opcode. */
937 {
938 int imm;
939
940 imm = (given & 0xf) | ((given & 0xe0) >> 1);
941
942 /* Is ``imm'' a negative number? */
943 if (imm & 0x40)
944 imm |= (-1 << 7);
945
946 func (stream, "%d", imm);
947 }
948
949 break;
950
951 case 'C':
952 func (stream, "_");
953 if (given & 0x80000)
954 func (stream, "f");
955 if (given & 0x40000)
956 func (stream, "s");
957 if (given & 0x20000)
958 func (stream, "x");
959 if (given & 0x10000)
960 func (stream, "c");
961 break;
962
963 case 'F':
964 switch (given & 0x00408000)
965 {
966 case 0:
967 func (stream, "4");
968 break;
969 case 0x8000:
970 func (stream, "1");
971 break;
972 case 0x00400000:
973 func (stream, "2");
974 break;
975 default:
976 func (stream, "3");
977 }
978 break;
979
980 case 'P':
981 switch (given & 0x00080080)
982 {
983 case 0:
984 func (stream, "s");
985 break;
986 case 0x80:
987 func (stream, "d");
988 break;
989 case 0x00080000:
990 func (stream, "e");
991 break;
992 default:
993 func (stream, _("<illegal precision>"));
994 break;
995 }
996 break;
997 case 'Q':
998 switch (given & 0x00408000)
999 {
1000 case 0:
1001 func (stream, "s");
1002 break;
1003 case 0x8000:
1004 func (stream, "d");
1005 break;
1006 case 0x00400000:
1007 func (stream, "e");
1008 break;
1009 default:
1010 func (stream, "p");
1011 break;
1012 }
1013 break;
1014 case 'R':
1015 switch (given & 0x60)
1016 {
1017 case 0:
1018 break;
1019 case 0x20:
1020 func (stream, "p");
1021 break;
1022 case 0x40:
1023 func (stream, "m");
1024 break;
1025 default:
1026 func (stream, "z");
1027 break;
1028 }
1029 break;
1030
1031 case '0': case '1': case '2': case '3': case '4':
1032 case '5': case '6': case '7': case '8': case '9':
1033 {
1034 int bitstart = *c++ - '0';
1035 int bitend = 0;
1036 while (*c >= '0' && *c <= '9')
1037 bitstart = (bitstart * 10) + *c++ - '0';
1038
1039 switch (*c)
1040 {
1041 case '-':
1042 c++;
1043
1044 while (*c >= '0' && *c <= '9')
1045 bitend = (bitend * 10) + *c++ - '0';
1046
1047 if (!bitend)
1048 abort ();
1049
1050 switch (*c)
1051 {
1052 case 'r':
1053 {
1054 long reg;
1055
1056 reg = given >> bitstart;
1057 reg &= (2 << (bitend - bitstart)) - 1;
1058
1059 func (stream, "%s", arm_regnames[reg]);
1060 }
1061 break;
1062 case 'd':
1063 {
1064 long reg;
1065
1066 reg = given >> bitstart;
1067 reg &= (2 << (bitend - bitstart)) - 1;
1068
1069 func (stream, "%d", reg);
1070 }
1071 break;
1072 case 'x':
1073 {
1074 long reg;
1075
1076 reg = given >> bitstart;
1077 reg &= (2 << (bitend - bitstart)) - 1;
1078
1079 func (stream, "0x%08x", reg);
1080
1081 /* Some SWI instructions have special
1082 meanings. */
1083 if ((given & 0x0fffffff) == 0x0FF00000)
1084 func (stream, "\t; IMB");
1085 else if ((given & 0x0fffffff) == 0x0FF00001)
1086 func (stream, "\t; IMBRange");
1087 }
1088 break;
1089 case 'X':
1090 {
1091 long reg;
1092
1093 reg = given >> bitstart;
1094 reg &= (2 << (bitend - bitstart)) - 1;
1095
1096 func (stream, "%01x", reg & 0xf);
1097 }
1098 break;
1099 case 'f':
1100 {
1101 long reg;
1102
1103 reg = given >> bitstart;
1104 reg &= (2 << (bitend - bitstart)) - 1;
1105
1106 if (reg > 7)
1107 func (stream, "#%s",
1108 arm_fp_const[reg & 7]);
1109 else
1110 func (stream, "f%d", reg);
1111 }
1112 break;
1113 default:
1114 abort ();
1115 }
1116 break;
1117
1118 case 'y':
1119 case 'z':
1120 {
1121 int single = *c == 'y';
1122 int regno;
1123
1124 switch (bitstart)
1125 {
1126 case 4: /* Sm pair */
1127 func (stream, "{");
1128 /* Fall through. */
1129 case 0: /* Sm, Dm */
1130 regno = given & 0x0000000f;
1131 if (single)
1132 {
1133 regno <<= 1;
1134 regno += (given >> 5) & 1;
1135 }
1136 break;
1137
1138 case 1: /* Sd, Dd */
1139 regno = (given >> 12) & 0x0000000f;
1140 if (single)
1141 {
1142 regno <<= 1;
1143 regno += (given >> 22) & 1;
1144 }
1145 break;
1146
1147 case 2: /* Sn, Dn */
1148 regno = (given >> 16) & 0x0000000f;
1149 if (single)
1150 {
1151 regno <<= 1;
1152 regno += (given >> 7) & 1;
1153 }
1154 break;
1155
1156 case 3: /* List */
1157 func (stream, "{");
1158 regno = (given >> 12) & 0x0000000f;
1159 if (single)
1160 {
1161 regno <<= 1;
1162 regno += (given >> 22) & 1;
1163 }
1164 break;
1165
1166
1167 default:
1168 abort ();
1169 }
1170
1171 func (stream, "%c%d", single ? 's' : 'd', regno);
1172
1173 if (bitstart == 3)
1174 {
1175 int count = given & 0xff;
1176
1177 if (single == 0)
1178 count >>= 1;
1179
1180 if (--count)
1181 {
1182 func (stream, "-%c%d",
1183 single ? 's' : 'd',
1184 regno + count);
1185 }
1186
1187 func (stream, "}");
1188 }
1189 else if (bitstart == 4)
1190 func (stream, ", %c%d}", single ? 's' : 'd',
1191 regno + 1);
1192
1193 break;
1194 }
1195
1196 case '`':
1197 c++;
1198 if ((given & (1 << bitstart)) == 0)
1199 func (stream, "%c", *c);
1200 break;
1201 case '\'':
1202 c++;
1203 if ((given & (1 << bitstart)) != 0)
1204 func (stream, "%c", *c);
1205 break;
1206 case '?':
1207 ++c;
1208 if ((given & (1 << bitstart)) != 0)
1209 func (stream, "%c", *c++);
1210 else
1211 func (stream, "%c", *++c);
1212 break;
1213 default:
1214 abort ();
1215 }
1216 break;
1217
1218 default:
1219 abort ();
1220 }
1221 }
1222 }
1223 else
1224 func (stream, "%c", *c);
1225 }
1226 return 4;
1227 }
1228 }
1229 abort ();
1230}
1231
1232/* Print one instruction from PC on INFO->STREAM.
1233 Return the size of the instruction. */
1234
1235static int
1236print_insn_thumb (pc, info, given)
1237 bfd_vma pc;
1238 struct disassemble_info * info;
1239 long given;
1240{
1241 struct thumb_opcode * insn;
1242 void * stream = info->stream;
1243 fprintf_ftype func = info->fprintf_func;
1244
1245 for (insn = thumb_opcodes; insn->assembler; insn++)
1246 {
1247 if ((given & insn->mask) == insn->value)
1248 {
1249 char * c = insn->assembler;
1250
1251 /* Special processing for Thumb 2 instruction BL sequence: */
1252 if (!*c) /* Check for empty (not NULL) assembler string. */
1253 {
1254 long offset;
1255
1256 info->bytes_per_chunk = 4;
1257 info->bytes_per_line = 4;
1258
1259 offset = BDISP23 (given);
1260 offset = offset * 2 + pc + 4;
1261
1262 if ((given & 0x10000000) == 0)
1263 {
1264 func (stream, "blx\t");
1265 offset &= 0xfffffffc;
1266 }
1267 else
1268 func (stream, "bl\t");
1269
1270 info->print_address_func (offset, info);
1271 return 4;
1272 }
1273 else
1274 {
1275 info->bytes_per_chunk = 2;
1276 info->bytes_per_line = 4;
1277
1278 given &= 0xffff;
1279
1280 for (; *c; c++)
1281 {
1282 if (*c == '%')
1283 {
1284 int domaskpc = 0;
1285 int domasklr = 0;
1286
1287 switch (*++c)
1288 {
1289 case '%':
1290 func (stream, "%%");
1291 break;
1292
1293 case 'S':
1294 {
1295 long reg;
1296
1297 reg = (given >> 3) & 0x7;
1298 if (given & (1 << 6))
1299 reg += 8;
1300
1301 func (stream, "%s", arm_regnames[reg]);
1302 }
1303 break;
1304
1305 case 'D':
1306 {
1307 long reg;
1308
1309 reg = given & 0x7;
1310 if (given & (1 << 7))
1311 reg += 8;
1312
1313 func (stream, "%s", arm_regnames[reg]);
1314 }
1315 break;
1316
1317 case 'T':
1318 func (stream, "%s",
1319 arm_conditional [(given >> 8) & 0xf]);
1320 break;
1321
1322 case 'N':
1323 if (given & (1 << 8))
1324 domasklr = 1;
1325 /* Fall through. */
1326 case 'O':
1327 if (*c == 'O' && (given & (1 << 8)))
1328 domaskpc = 1;
1329 /* Fall through. */
1330 case 'M':
1331 {
1332 int started = 0;
1333 int reg;
1334
1335 func (stream, "{");
1336
1337 /* It would be nice if we could spot
1338 ranges, and generate the rS-rE format: */
1339 for (reg = 0; (reg < 8); reg++)
1340 if ((given & (1 << reg)) != 0)
1341 {
1342 if (started)
1343 func (stream, ", ");
1344 started = 1;
1345 func (stream, "%s", arm_regnames[reg]);
1346 }
1347
1348 if (domasklr)
1349 {
1350 if (started)
1351 func (stream, ", ");
1352 started = 1;
1353 func (stream, arm_regnames[14] /* "lr" */);
1354 }
1355
1356 if (domaskpc)
1357 {
1358 if (started)
1359 func (stream, ", ");
1360 func (stream, arm_regnames[15] /* "pc" */);
1361 }
1362
1363 func (stream, "}");
1364 }
1365 break;
1366
1367
1368 case '0': case '1': case '2': case '3': case '4':
1369 case '5': case '6': case '7': case '8': case '9':
1370 {
1371 int bitstart = *c++ - '0';
1372 int bitend = 0;
1373
1374 while (*c >= '0' && *c <= '9')
1375 bitstart = (bitstart * 10) + *c++ - '0';
1376
1377 switch (*c)
1378 {
1379 case '-':
1380 {
1381 long reg;
1382
1383 c++;
1384 while (*c >= '0' && *c <= '9')
1385 bitend = (bitend * 10) + *c++ - '0';
1386 if (!bitend)
1387 abort ();
1388 reg = given >> bitstart;
1389 reg &= (2 << (bitend - bitstart)) - 1;
1390 switch (*c)
1391 {
1392 case 'r':
1393 func (stream, "%s", arm_regnames[reg]);
1394 break;
1395
1396 case 'd':
1397 func (stream, "%d", reg);
1398 break;
1399
1400 case 'H':
1401 func (stream, "%d", reg << 1);
1402 break;
1403
1404 case 'W':
1405 func (stream, "%d", reg << 2);
1406 break;
1407
1408 case 'a':
1409 /* PC-relative address -- the bottom two
1410 bits of the address are dropped
1411 before the calculation. */
1412 info->print_address_func
1413 (((pc + 4) & ~3) + (reg << 2), info);
1414 break;
1415
1416 case 'x':
1417 func (stream, "0x%04x", reg);
1418 break;
1419
1420 case 'I':
1421 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1422 func (stream, "%d", reg);
1423 break;
1424
1425 case 'B':
1426 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
1427 (*info->print_address_func)
1428 (reg * 2 + pc + 4, info);
1429 break;
1430
1431 default:
1432 abort ();
1433 }
1434 }
1435 break;
1436
1437 case '\'':
1438 c++;
1439 if ((given & (1 << bitstart)) != 0)
1440 func (stream, "%c", *c);
1441 break;
1442
1443 case '?':
1444 ++c;
1445 if ((given & (1 << bitstart)) != 0)
1446 func (stream, "%c", *c++);
1447 else
1448 func (stream, "%c", *++c);
1449 break;
1450
1451 default:
1452 abort ();
1453 }
1454 }
1455 break;
1456
1457 default:
1458 abort ();
1459 }
1460 }
1461 else
1462 func (stream, "%c", *c);
1463 }
1464 }
1465 return 2;
1466 }
1467 }
1468
1469 /* No match. */
1470 abort ();
1471}
1472
1473/* Parse an individual disassembler option. */
1474
1475void
1476parse_arm_disassembler_option (option)
1477 char * option;
1478{
1479 if (option == NULL)
1480 return;
1481
1482 if (strneq (option, "reg-names-", 10))
1483 {
1484 int i;
1485
1486 option += 10;
1487
1488 for (i = NUM_ARM_REGNAMES; i--;)
1489 if (streq (option, regnames[i].name))
1490 {
1491 regname_selected = i;
1492 break;
1493 }
1494
1495 if (i < 0)
1496 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
1497 }
1498 else if (streq (option, "force-thumb"))
1499 force_thumb = 1;
1500 else if (streq (option, "no-force-thumb"))
1501 force_thumb = 0;
1502 else
1503 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
1504
1505 return;
1506}
1507
1508/* Parse the string of disassembler options, spliting it at whitespaces. */
1509
1510static void
1511parse_disassembler_options (options)
1512 char * options;
1513{
1514 char * space;
1515
1516 if (options == NULL)
1517 return;
1518
1519 do
1520 {
1521 space = strchr (options, ' ');
1522
1523 if (space)
1524 {
1525 * space = '\0';
1526 parse_arm_disassembler_option (options);
1527 * space = ' ';
1528 options = space + 1;
1529 }
1530 else
1531 parse_arm_disassembler_option (options);
1532 }
1533 while (space);
1534}
1535
1536/* NOTE: There are no checks in these routines that
1537 the relevant number of data bytes exist. */
1538
1539int
1540print_insn_arm (pc, info)
1541 bfd_vma pc;
1542 struct disassemble_info * info;
1543{
1544 unsigned char b[4];
1545 long given;
1546 int status;
1547 int is_thumb;
1548 int little;
1549
1550 if (info->disassembler_options)
1551 {
1552 parse_disassembler_options (info->disassembler_options);
1553
1554 /* To avoid repeated parsing of these options, we remove them here. */
1555 info->disassembler_options = NULL;
1556 }
1557
1558 is_thumb = force_thumb;
1559
1560#if 0
1561 if (!is_thumb && info->symbols != NULL)
1562 {
1563 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
1564 {
1565 coff_symbol_type * cs;
1566
1567 cs = coffsymbol (*info->symbols);
1568 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
1569 || cs->native->u.syment.n_sclass == C_THUMBSTAT
1570 || cs->native->u.syment.n_sclass == C_THUMBLABEL
1571 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
1572 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
1573 }
1574 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
1575 {
1576 elf_symbol_type * es;
1577 unsigned int type;
1578
1579 es = *(elf_symbol_type **)(info->symbols);
1580 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
1581
1582 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
1583 }
1584 }
1585#endif
1586
1587 little = (info->endian == BFD_ENDIAN_LITTLE);
1588 info->bytes_per_chunk = 4;
1589 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
1590
1591 if (little)
1592 {
1593 status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
1594 if (status != 0 && is_thumb)
1595 {
1596 info->bytes_per_chunk = 2;
1597
1598 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
1599 b[3] = b[2] = 0;
1600 }
1601
1602 if (status != 0)
1603 {
1604 info->memory_error_func (status, pc, info);
1605 return -1;
1606 }
1607
1608 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
1609 }
1610 else
1611 {
1612 status = info->read_memory_func
1613 (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
1614 if (status != 0)
1615 {
1616 info->memory_error_func (status, pc, info);
1617 return -1;
1618 }
1619
1620 if (is_thumb)
1621 {
1622 if (pc & 0x2)
1623 {
1624 given = (b[2] << 8) | b[3];
1625
1626 status = info->read_memory_func
1627 ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
1628 if (status != 0)
1629 {
1630 info->memory_error_func (status, pc + 4, info);
1631 return -1;
1632 }
1633
1634 given |= (b[0] << 24) | (b[1] << 16);
1635 }
1636 else
1637 given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
1638 }
1639 else
1640 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
1641 }
1642
1643 if (info->flags & INSN_HAS_RELOC)
1644 /* If the instruction has a reloc associated with it, then
1645 the offset field in the instruction will actually be the
1646 addend for the reloc. (We are using REL type relocs).
1647 In such cases, we can ignore the pc when computing
1648 addresses, since the addend is not currently pc-relative. */
1649 pc = 0;
1650 if (is_thumb)
1651 status = print_insn_thumb (pc, info, given);
1652 else
1653 status = print_insn_arm1 (pc, info, given);
1654
1655 return status;
1656}
1657
1658void
1659print_arm_disassembler_options (FILE * stream)
1660{
1661 int i;
1662
1663 fprintf (stream, _("\n\
1664The following ARM specific disassembler options are supported for use with\n\
1665the -M switch:\n"));
1666
1667 for (i = NUM_ARM_REGNAMES; i--;)
1668 fprintf (stream, " reg-names-%s %*c%s\n",
1669 regnames[i].name,
1670 (int)(14 - strlen (regnames[i].name)), ' ',
1671 regnames[i].description);
1672
1673 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
1674 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
1675}