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. */
26 unsigned long value
, mask
; /* recognise instruction if (op&mask)==value */
27 char *assembler
; /* how to disassemble this instruction */
32 unsigned short value
, mask
; /* recognise instruction if (op&mask)==value */
33 char * assembler
; /* how to disassemble this instruction */
36 /* format of the assembler string :
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.
67 Thumb 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
83 /* Note: There is a partial ordering in this table - it must be searched from
84 the top to obtain a correct match. */
86 static struct arm_opcode arm_opcodes
[] =
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"},
97 /* V5J instruction. */
98 {0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
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"},
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}"},
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"},
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"},
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"},
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"},
140 {0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
141 {0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
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"},
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"},
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"},
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"},
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"},
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"},
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"},
396 {0x00000000, 0x00000000, "undefined instruction %0-31x"},
397 {0x00000000, 0x00000000, 0}
400 #define BDISP(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000) /* 26 bit */
402 static struct thumb_opcode thumb_opcodes
[] =
404 /* Thumb instructions. */
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)"},
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"},
436 {0xB000, 0xFF80, "add\tsp, #%0-6W"},
437 {0xB080, 0xFF80, "sub\tsp, #%0-6W"},
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"},
444 {0xB400, 0xFE00, "push\t%N"},
445 {0xBC00, 0xFE00, "pop\t%O"},
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"},
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]"},
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]"},
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"},
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"},
468 {0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
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]"},
475 {0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
476 {0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
478 {0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
479 {0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
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"},
484 {0xC000, 0xF800, "stmia\t%8-10r!,%M"},
485 {0xC800, 0xF800, "ldmia\t%8-10r!,%M"},
487 {0xE000, 0xF800, "b\t%0-10B"},
488 {0xE800, 0xF800, "undefined"},
490 {0xF000, 0xF800, ""}, /* special processing required in disassembler */
491 {0xF800, 0xF800, "second half of BL instruction %0-15x"},
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"},
508 {0xDE00, 0xFF00, "bal\t%0-7B"},
509 {0xDF00, 0xFF00, "swi\t%0-7d"},
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]"},
516 {0x0000, 0x0000, "undefined instruction %0-15x"},
520 #define BDISP23(x) ((((((x) & 0x07ff) << 11) | (((x) & 0x07ff0000) >> 16)) \
521 ^ 0x200000) - 0x200000) /* 23bit */
524 #define streq(a,b) (strcmp ((a), (b)) == 0)
528 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
532 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
535 static char * arm_conditional
[] =
536 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
537 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
542 const char * description
;
543 const char * reg_names
[16];
547 static arm_regname regnames
[] =
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" }}
563 /* Default to STD register name set. */
564 static unsigned int regname_selected
= 2;
566 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
567 #define arm_regnames regnames[regname_selected].reg_names
569 static boolean force_thumb
= false;
571 static char * arm_fp_const
[] =
572 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
574 static char * arm_shift
[] =
575 {"lsl", "lsr", "asr", "ror"};
577 /* Forward declarations. */
578 static void arm_decode_shift
PARAMS ((long, fprintf_ftype
, void *));
579 static int print_insn_arm1
PARAMS ((bfd_vma
, struct disassemble_info
*, long));
580 static int print_insn_thumb
PARAMS ((bfd_vma
, struct disassemble_info
*, long));
581 static void parse_disassembler_options
PARAMS ((char *));
582 int get_arm_regname_num_options (void);
583 int set_arm_regname_option (int option
);
584 int get_arm_regnames (int option
, const char **setname
,
585 const char **setdescription
,
586 const char ***register_names
);
590 get_arm_regname_num_options ()
592 return NUM_ARM_REGNAMES
;
596 set_arm_regname_option (option
)
599 int old
= regname_selected
;
600 regname_selected
= option
;
605 get_arm_regnames (option
, setname
, setdescription
, register_names
)
607 const char **setname
;
608 const char **setdescription
;
609 const char ***register_names
;
611 *setname
= regnames
[option
].name
;
612 *setdescription
= regnames
[option
].description
;
613 *register_names
= regnames
[option
].reg_names
;
618 arm_decode_shift (given
, func
, stream
)
623 func (stream
, "%s", arm_regnames
[given
& 0xf]);
625 if ((given
& 0xff0) != 0)
627 if ((given
& 0x10) == 0)
629 int amount
= (given
& 0xf80) >> 7;
630 int shift
= (given
& 0x60) >> 5;
636 func (stream
, ", rrx");
643 func (stream
, ", %s #%d", arm_shift
[shift
], amount
);
646 func (stream
, ", %s %s", arm_shift
[(given
& 0x60) >> 5],
647 arm_regnames
[(given
& 0xf00) >> 8]);
651 /* Print one instruction from PC on INFO->STREAM.
652 Return the size of the instruction (always 4 on ARM). */
655 print_insn_arm1 (pc
, info
, given
)
657 struct disassemble_info
* info
;
660 struct arm_opcode
* insn
;
661 void * stream
= info
->stream
;
662 fprintf_ftype func
= info
->fprintf_func
;
664 for (insn
= arm_opcodes
; insn
->assembler
; insn
++)
666 if ((given
& insn
->mask
) == insn
->value
)
670 for (c
= insn
->assembler
; *c
; c
++)
681 if (((given
& 0x000f0000) == 0x000f0000)
682 && ((given
& 0x02000000) == 0))
684 int offset
= given
& 0xfff;
686 func (stream
, "[pc");
688 if (given
& 0x01000000)
690 if ((given
& 0x00800000) == 0)
694 func (stream
, ", #%d]", offset
);
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
702 if (given
& 0x00200000)
708 func (stream
, "], #%d", offset
);
710 /* ie ignore the offset. */
714 func (stream
, "\t; ");
715 info
->print_address_func (offset
, info
);
720 arm_regnames
[(given
>> 16) & 0xf]);
721 if ((given
& 0x01000000) != 0)
723 if ((given
& 0x02000000) == 0)
725 int offset
= given
& 0xfff;
727 func (stream
, ", %s#%d",
728 (((given
& 0x00800000) == 0)
729 ? "-" : ""), offset
);
733 func (stream
, ", %s",
734 (((given
& 0x00800000) == 0)
736 arm_decode_shift (given
, func
, stream
);
740 ((given
& 0x00200000) != 0) ? "!" : "");
744 if ((given
& 0x02000000) == 0)
746 int offset
= given
& 0xfff;
748 func (stream
, "], %s#%d",
749 (((given
& 0x00800000) == 0)
750 ? "-" : ""), offset
);
756 func (stream
, "], %s",
757 (((given
& 0x00800000) == 0)
759 arm_decode_shift (given
, func
, stream
);
766 if ((given
& 0x004f0000) == 0x004f0000)
768 /* PC relative with immediate offset. */
769 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
771 if ((given
& 0x00800000) == 0)
774 func (stream
, "[pc, #%d]\t; ", offset
);
776 (*info
->print_address_func
)
777 (offset
+ pc
+ 8, info
);
782 arm_regnames
[(given
>> 16) & 0xf]);
783 if ((given
& 0x01000000) != 0)
786 if ((given
& 0x00400000) == 0x00400000)
789 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
791 func (stream
, ", %s#%d",
792 (((given
& 0x00800000) == 0)
793 ? "-" : ""), offset
);
798 func (stream
, ", %s%s",
799 (((given
& 0x00800000) == 0)
801 arm_regnames
[given
& 0xf]);
805 ((given
& 0x00200000) != 0) ? "!" : "");
810 if ((given
& 0x00400000) == 0x00400000)
813 int offset
= ((given
& 0xf00) >> 4) | (given
& 0xf);
815 func (stream
, "], %s#%d",
816 (((given
& 0x00800000) == 0)
817 ? "-" : ""), offset
);
824 func (stream
, "], %s%s",
825 (((given
& 0x00800000) == 0)
827 arm_regnames
[given
& 0xf]);
834 (*info
->print_address_func
)
835 (BDISP (given
) * 4 + pc
+ 8, info
);
840 arm_conditional
[(given
>> 28) & 0xf]);
849 for (reg
= 0; reg
< 16; reg
++)
850 if ((given
& (1 << reg
)) != 0)
855 func (stream
, "%s", arm_regnames
[reg
]);
862 if ((given
& 0x02000000) != 0)
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
);
871 arm_decode_shift (given
, func
, stream
);
875 if ((given
& 0x0000f000) == 0x0000f000)
880 if ((given
& 0x01200000) == 0x00200000)
885 func (stream
, "[%s", arm_regnames
[(given
>> 16) & 0xf]);
886 if ((given
& 0x01000000) != 0)
888 int offset
= given
& 0xff;
890 func (stream
, ", %s#%d]%s",
891 ((given
& 0x00800000) == 0 ? "-" : ""),
893 ((given
& 0x00200000) != 0 ? "!" : ""));
899 int offset
= given
& 0xff;
901 func (stream
, "], %s#%d",
902 ((given
& 0x00800000) == 0 ? "-" : ""),
910 /* Print ARM V5 BLX(1) address: pc+25 bits. */
915 if (given
& 0x00800000)
916 /* Is signed, hi bits should be ones. */
917 offset
= (-1) ^ 0x00ffffff;
919 /* Offset is (SignExtend(offset field)<<2). */
920 offset
+= given
& 0x00ffffff;
922 address
= offset
+ pc
+ 8;
924 if (given
& 0x01000000)
925 /* H bit allows addressing to 2-byte boundaries. */
928 info
->print_address_func (address
, info
);
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
940 imm
= (given
& 0xf) | ((given
& 0xe0) >> 1);
942 /* Is ``imm'' a negative number? */
946 func (stream
, "%d", imm
);
964 switch (given
& 0x00408000)
981 switch (given
& 0x00080080)
993 func (stream
, _("<illegal precision>"));
998 switch (given
& 0x00408000)
1015 switch (given
& 0x60)
1031 case '0': case '1': case '2': case '3': case '4':
1032 case '5': case '6': case '7': case '8': case '9':
1034 int bitstart
= *c
++ - '0';
1036 while (*c
>= '0' && *c
<= '9')
1037 bitstart
= (bitstart
* 10) + *c
++ - '0';
1044 while (*c
>= '0' && *c
<= '9')
1045 bitend
= (bitend
* 10) + *c
++ - '0';
1056 reg
= given
>> bitstart
;
1057 reg
&= (2 << (bitend
- bitstart
)) - 1;
1059 func (stream
, "%s", arm_regnames
[reg
]);
1066 reg
= given
>> bitstart
;
1067 reg
&= (2 << (bitend
- bitstart
)) - 1;
1069 func (stream
, "%d", reg
);
1076 reg
= given
>> bitstart
;
1077 reg
&= (2 << (bitend
- bitstart
)) - 1;
1079 func (stream
, "0x%08x", reg
);
1081 /* Some SWI instructions have special
1083 if ((given
& 0x0fffffff) == 0x0FF00000)
1084 func (stream
, "\t; IMB");
1085 else if ((given
& 0x0fffffff) == 0x0FF00001)
1086 func (stream
, "\t; IMBRange");
1093 reg
= given
>> bitstart
;
1094 reg
&= (2 << (bitend
- bitstart
)) - 1;
1096 func (stream
, "%01x", reg
& 0xf);
1103 reg
= given
>> bitstart
;
1104 reg
&= (2 << (bitend
- bitstart
)) - 1;
1107 func (stream
, "#%s",
1108 arm_fp_const
[reg
& 7]);
1110 func (stream
, "f%d", reg
);
1121 int single
= *c
== 'y';
1126 case 4: /* Sm pair */
1129 case 0: /* Sm, Dm */
1130 regno
= given
& 0x0000000f;
1134 regno
+= (given
>> 5) & 1;
1138 case 1: /* Sd, Dd */
1139 regno
= (given
>> 12) & 0x0000000f;
1143 regno
+= (given
>> 22) & 1;
1147 case 2: /* Sn, Dn */
1148 regno
= (given
>> 16) & 0x0000000f;
1152 regno
+= (given
>> 7) & 1;
1158 regno
= (given
>> 12) & 0x0000000f;
1162 regno
+= (given
>> 22) & 1;
1171 func (stream
, "%c%d", single
? 's' : 'd', regno
);
1175 int count
= given
& 0xff;
1182 func (stream
, "-%c%d",
1189 else if (bitstart
== 4)
1190 func (stream
, ", %c%d}", single
? 's' : 'd',
1198 if ((given
& (1 << bitstart
)) == 0)
1199 func (stream
, "%c", *c
);
1203 if ((given
& (1 << bitstart
)) != 0)
1204 func (stream
, "%c", *c
);
1208 if ((given
& (1 << bitstart
)) != 0)
1209 func (stream
, "%c", *c
++);
1211 func (stream
, "%c", *++c
);
1224 func (stream
, "%c", *c
);
1232 /* Print one instruction from PC on INFO->STREAM.
1233 Return the size of the instruction. */
1236 print_insn_thumb (pc
, info
, given
)
1238 struct disassemble_info
* info
;
1241 struct thumb_opcode
* insn
;
1242 void * stream
= info
->stream
;
1243 fprintf_ftype func
= info
->fprintf_func
;
1245 for (insn
= thumb_opcodes
; insn
->assembler
; insn
++)
1247 if ((given
& insn
->mask
) == insn
->value
)
1249 char * c
= insn
->assembler
;
1251 /* Special processing for Thumb 2 instruction BL sequence: */
1252 if (!*c
) /* Check for empty (not NULL) assembler string. */
1256 info
->bytes_per_chunk
= 4;
1257 info
->bytes_per_line
= 4;
1259 offset
= BDISP23 (given
);
1260 offset
= offset
* 2 + pc
+ 4;
1262 if ((given
& 0x10000000) == 0)
1264 func (stream
, "blx\t");
1265 offset
&= 0xfffffffc;
1268 func (stream
, "bl\t");
1270 info
->print_address_func (offset
, info
);
1275 info
->bytes_per_chunk
= 2;
1276 info
->bytes_per_line
= 4;
1290 func (stream
, "%%");
1297 reg
= (given
>> 3) & 0x7;
1298 if (given
& (1 << 6))
1301 func (stream
, "%s", arm_regnames
[reg
]);
1310 if (given
& (1 << 7))
1313 func (stream
, "%s", arm_regnames
[reg
]);
1319 arm_conditional
[(given
>> 8) & 0xf]);
1323 if (given
& (1 << 8))
1327 if (*c
== 'O' && (given
& (1 << 8)))
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)
1343 func (stream
, ", ");
1345 func (stream
, "%s", arm_regnames
[reg
]);
1351 func (stream
, ", ");
1353 func (stream
, arm_regnames
[14] /* "lr" */);
1359 func (stream
, ", ");
1360 func (stream
, arm_regnames
[15] /* "pc" */);
1368 case '0': case '1': case '2': case '3': case '4':
1369 case '5': case '6': case '7': case '8': case '9':
1371 int bitstart
= *c
++ - '0';
1374 while (*c
>= '0' && *c
<= '9')
1375 bitstart
= (bitstart
* 10) + *c
++ - '0';
1384 while (*c
>= '0' && *c
<= '9')
1385 bitend
= (bitend
* 10) + *c
++ - '0';
1388 reg
= given
>> bitstart
;
1389 reg
&= (2 << (bitend
- bitstart
)) - 1;
1393 func (stream
, "%s", arm_regnames
[reg
]);
1397 func (stream
, "%d", reg
);
1401 func (stream
, "%d", reg
<< 1);
1405 func (stream
, "%d", reg
<< 2);
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
);
1417 func (stream
, "0x%04x", reg
);
1421 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
1422 func (stream
, "%d", reg
);
1426 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
1427 (*info
->print_address_func
)
1428 (reg
* 2 + pc
+ 4, info
);
1439 if ((given
& (1 << bitstart
)) != 0)
1440 func (stream
, "%c", *c
);
1445 if ((given
& (1 << bitstart
)) != 0)
1446 func (stream
, "%c", *c
++);
1448 func (stream
, "%c", *++c
);
1462 func (stream
, "%c", *c
);
1473 /* Parse an individual disassembler option. */
1476 parse_arm_disassembler_option (option
)
1482 if (strneq (option
, "reg-names-", 10))
1488 for (i
= NUM_ARM_REGNAMES
; i
--;)
1489 if (streq (option
, regnames
[i
].name
))
1491 regname_selected
= i
;
1496 fprintf (stderr
, _("Unrecognised register name set: %s\n"), option
);
1498 else if (streq (option
, "force-thumb"))
1500 else if (streq (option
, "no-force-thumb"))
1503 fprintf (stderr
, _("Unrecognised disassembler option: %s\n"), option
);
1508 /* Parse the string of disassembler options, spliting it at whitespaces. */
1511 parse_disassembler_options (options
)
1516 if (options
== NULL
)
1521 space
= strchr (options
, ' ');
1526 parse_arm_disassembler_option (options
);
1528 options
= space
+ 1;
1531 parse_arm_disassembler_option (options
);
1536 /* NOTE: There are no checks in these routines that
1537 the relevant number of data bytes exist. */
1540 print_insn_arm (pc
, info
)
1542 struct disassemble_info
* info
;
1550 if (info
->disassembler_options
)
1552 parse_disassembler_options (info
->disassembler_options
);
1554 /* To avoid repeated parsing of these options, we remove them here. */
1555 info
->disassembler_options
= NULL
;
1558 is_thumb
= force_thumb
;
1566 if (!is_thumb
&& info
->symbols
!= NULL
)
1568 if (bfd_asymbol_flavour (*info
->symbols
) == bfd_target_coff_flavour
)
1570 coff_symbol_type
* cs
;
1572 cs
= coffsymbol (*info
->symbols
);
1573 is_thumb
= ( cs
->native
->u
.syment
.n_sclass
== C_THUMBEXT
1574 || cs
->native
->u
.syment
.n_sclass
== C_THUMBSTAT
1575 || cs
->native
->u
.syment
.n_sclass
== C_THUMBLABEL
1576 || cs
->native
->u
.syment
.n_sclass
== C_THUMBEXTFUNC
1577 || cs
->native
->u
.syment
.n_sclass
== C_THUMBSTATFUNC
);
1579 else if (bfd_asymbol_flavour (*info
->symbols
) == bfd_target_elf_flavour
)
1581 elf_symbol_type
* es
;
1584 es
= *(elf_symbol_type
**)(info
->symbols
);
1585 type
= ELF_ST_TYPE (es
->internal_elf_sym
.st_info
);
1587 is_thumb
= (type
== STT_ARM_TFUNC
) || (type
== STT_ARM_16BIT
);
1592 little
= (info
->endian
== BFD_ENDIAN_LITTLE
);
1593 info
->bytes_per_chunk
= 4;
1594 info
->display_endian
= little
? BFD_ENDIAN_LITTLE
: BFD_ENDIAN_BIG
;
1598 status
= info
->read_memory_func (pc
, (bfd_byte
*) &b
[0], 4, info
);
1599 if (status
!= 0 && is_thumb
)
1601 info
->bytes_per_chunk
= 2;
1603 status
= info
->read_memory_func (pc
, (bfd_byte
*) b
, 2, info
);
1609 info
->memory_error_func (status
, pc
, info
);
1613 given
= (b
[0]) | (b
[1] << 8) | (b
[2] << 16) | (b
[3] << 24);
1617 status
= info
->read_memory_func
1618 (pc
& ~ 0x3, (bfd_byte
*) &b
[0], 4, info
);
1621 info
->memory_error_func (status
, pc
, info
);
1629 given
= (b
[2] << 8) | b
[3];
1631 status
= info
->read_memory_func
1632 ((pc
+ 4) & ~ 0x3, (bfd_byte
*) b
, 4, info
);
1635 info
->memory_error_func (status
, pc
+ 4, info
);
1639 given
|= (b
[0] << 24) | (b
[1] << 16);
1642 given
= (b
[0] << 8) | b
[1] | (b
[2] << 24) | (b
[3] << 16);
1645 given
= (b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | (b
[3]);
1648 if (info
->flags
& INSN_HAS_RELOC
)
1649 /* If the instruction has a reloc associated with it, then
1650 the offset field in the instruction will actually be the
1651 addend for the reloc. (We are using REL type relocs).
1652 In such cases, we can ignore the pc when computing
1653 addresses, since the addend is not currently pc-relative. */
1656 status
= print_insn_thumb (pc
, info
, given
);
1658 status
= print_insn_arm1 (pc
, info
, given
);
1664 print_arm_disassembler_options (FILE * stream
)
1668 fprintf (stream
, _("\n\
1669 The following ARM specific disassembler options are supported for use with\n\
1670 the -M switch:\n"));
1672 for (i
= NUM_ARM_REGNAMES
; i
--;)
1673 fprintf (stream
, " reg-names-%s %*c%s\n",
1675 (int)(14 - strlen (regnames
[i
].name
)), ' ',
1676 regnames
[i
].description
);
1678 fprintf (stream
, " force-thumb Assume all insns are Thumb insns\n");
1679 fprintf (stream
, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");