|
1 /* Instruction printing code for the ARM |
|
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 |
|
3 2007, 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 |
|
7 This file is part of libopcodes. |
|
8 |
|
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) |
|
12 any later version. |
|
13 |
|
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 |
|
17 more details. |
|
18 |
|
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
|
22 |
|
23 /* Start of qemu specific additions. Mostly this is stub definitions |
|
24 for things we don't care about. */ |
|
25 |
|
26 #include "dis-asm.h" |
|
27 #define FALSE 0 |
|
28 #define TRUE (!FALSE) |
|
29 #define ATTRIBUTE_UNUSED __attribute__((unused)) |
|
30 #define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n') |
|
31 |
|
32 #define ARM_EXT_V1 0 |
|
33 #define ARM_EXT_V2 0 |
|
34 #define ARM_EXT_V2S 0 |
|
35 #define ARM_EXT_V3 0 |
|
36 #define ARM_EXT_V3M 0 |
|
37 #define ARM_EXT_V4 0 |
|
38 #define ARM_EXT_V4T 0 |
|
39 #define ARM_EXT_V5 0 |
|
40 #define ARM_EXT_V5T 0 |
|
41 #define ARM_EXT_V5ExP 0 |
|
42 #define ARM_EXT_V5E 0 |
|
43 #define ARM_EXT_V5J 0 |
|
44 #define ARM_EXT_V6 0 |
|
45 #define ARM_EXT_V6K 0 |
|
46 #define ARM_EXT_V6Z 0 |
|
47 #define ARM_EXT_V6T2 0 |
|
48 #define ARM_EXT_V7 0 |
|
49 #define ARM_EXT_DIV 0 |
|
50 |
|
51 /* Co-processor space extensions. */ |
|
52 #define ARM_CEXT_XSCALE 0 |
|
53 #define ARM_CEXT_MAVERICK 0 |
|
54 #define ARM_CEXT_IWMMXT 0 |
|
55 |
|
56 #define FPU_FPA_EXT_V1 0 |
|
57 #define FPU_FPA_EXT_V2 0 |
|
58 #define FPU_VFP_EXT_NONE 0 |
|
59 #define FPU_VFP_EXT_V1xD 0 |
|
60 #define FPU_VFP_EXT_V1 0 |
|
61 #define FPU_VFP_EXT_V2 0 |
|
62 #define FPU_MAVERICK 0 |
|
63 #define FPU_VFP_EXT_V3 0 |
|
64 #define FPU_NEON_EXT_V1 0 |
|
65 |
|
66 int floatformat_ieee_single_little; |
|
67 /* Assume host uses ieee float. */ |
|
68 static void floatformat_to_double (int *ignored, unsigned char *data, |
|
69 double *dest) |
|
70 { |
|
71 union { |
|
72 uint32_t i; |
|
73 float f; |
|
74 } u; |
|
75 u.i = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); |
|
76 *dest = u.f; |
|
77 } |
|
78 |
|
79 /* End of qemu specific additions. */ |
|
80 |
|
81 /* FIXME: Belongs in global header. */ |
|
82 #ifndef strneq |
|
83 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) |
|
84 #endif |
|
85 |
|
86 #ifndef NUM_ELEM |
|
87 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) |
|
88 #endif |
|
89 |
|
90 struct opcode32 |
|
91 { |
|
92 unsigned long arch; /* Architecture defining this insn. */ |
|
93 unsigned long value, mask; /* Recognise insn if (op&mask)==value. */ |
|
94 const char *assembler; /* How to disassemble this insn. */ |
|
95 }; |
|
96 |
|
97 struct opcode16 |
|
98 { |
|
99 unsigned long arch; /* Architecture defining this insn. */ |
|
100 unsigned short value, mask; /* Recognise insn if (op&mask)==value. */ |
|
101 const char *assembler; /* How to disassemble this insn. */ |
|
102 }; |
|
103 |
|
104 /* print_insn_coprocessor recognizes the following format control codes: |
|
105 |
|
106 %% % |
|
107 |
|
108 %c print condition code (always bits 28-31 in ARM mode) |
|
109 %q print shifter argument |
|
110 %u print condition code (unconditional in ARM mode) |
|
111 %A print address for ldc/stc/ldf/stf instruction |
|
112 %B print vstm/vldm register list |
|
113 %C print vstr/vldr address operand |
|
114 %I print cirrus signed shift immediate: bits 0..3|4..6 |
|
115 %F print the COUNT field of a LFM/SFM instruction. |
|
116 %P print floating point precision in arithmetic insn |
|
117 %Q print floating point precision in ldf/stf insn |
|
118 %R print floating point rounding mode |
|
119 |
|
120 %<bitfield>r print as an ARM register |
|
121 %<bitfield>d print the bitfield in decimal |
|
122 %<bitfield>k print immediate for VFPv3 conversion instruction |
|
123 %<bitfield>x print the bitfield in hex |
|
124 %<bitfield>X print the bitfield as 1 hex digit without leading "0x" |
|
125 %<bitfield>f print a floating point constant if >7 else a |
|
126 floating point register |
|
127 %<bitfield>w print as an iWMMXt width field - [bhwd]ss/us |
|
128 %<bitfield>g print as an iWMMXt 64-bit register |
|
129 %<bitfield>G print as an iWMMXt general purpose or control register |
|
130 %<bitfield>D print as a NEON D register |
|
131 %<bitfield>Q print as a NEON Q register |
|
132 |
|
133 %y<code> print a single precision VFP reg. |
|
134 Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair |
|
135 %z<code> print a double precision VFP reg |
|
136 Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list |
|
137 |
|
138 %<bitfield>'c print specified char iff bitfield is all ones |
|
139 %<bitfield>`c print specified char iff bitfield is all zeroes |
|
140 %<bitfield>?ab... select from array of values in big endian order |
|
141 |
|
142 %L print as an iWMMXt N/M width field. |
|
143 %Z print the Immediate of a WSHUFH instruction. |
|
144 %l like 'A' except use byte offsets for 'B' & 'H' |
|
145 versions. |
|
146 %i print 5-bit immediate in bits 8,3..0 |
|
147 (print "32" when 0) |
|
148 %r print register offset address for wldt/wstr instruction |
|
149 */ |
|
150 |
|
151 /* Common coprocessor opcodes shared between Arm and Thumb-2. */ |
|
152 |
|
153 static const struct opcode32 coprocessor_opcodes[] = |
|
154 { |
|
155 /* XScale instructions. */ |
|
156 {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"}, |
|
157 {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"}, |
|
158 {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"}, |
|
159 {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"}, |
|
160 {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"}, |
|
161 |
|
162 /* Intel Wireless MMX technology instructions. */ |
|
163 #define FIRST_IWMMXT_INSN 0x0e130130 |
|
164 #define IWMMXT_INSN_COUNT 73 |
|
165 {ARM_CEXT_IWMMXT, 0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"}, |
|
166 {ARM_CEXT_XSCALE, 0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"}, |
|
167 {ARM_CEXT_XSCALE, 0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"}, |
|
168 {ARM_CEXT_XSCALE, 0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"}, |
|
169 {ARM_CEXT_XSCALE, 0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"}, |
|
170 {ARM_CEXT_XSCALE, 0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"}, |
|
171 {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"}, |
|
172 {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"}, |
|
173 {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"}, |
|
174 {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"}, |
|
175 {ARM_CEXT_XSCALE, 0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"}, |
|
176 {ARM_CEXT_XSCALE, 0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"}, |
|
177 {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"}, |
|
178 {ARM_CEXT_XSCALE, 0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"}, |
|
179 {ARM_CEXT_XSCALE, 0x0e130190, 0x0f3f0fff, "torvsc%22-23w%c\t%12-15r"}, |
|
180 {ARM_CEXT_XSCALE, 0x0e2001c0, 0x0f300fff, "wabs%22-23w%c\t%12-15g, %16-19g"}, |
|
181 {ARM_CEXT_XSCALE, 0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"}, |
|
182 {ARM_CEXT_XSCALE, 0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
183 {ARM_CEXT_XSCALE, 0x0e2001a0, 0x0f300ff0, "waddbhus%22?ml%c\t%12-15g, %16-19g, %0-3g"}, |
|
184 {ARM_CEXT_XSCALE, 0x0ea001a0, 0x0ff00ff0, "waddsubhx%c\t%12-15g, %16-19g, %0-3g"}, |
|
185 {ARM_CEXT_XSCALE, 0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"}, |
|
186 {ARM_CEXT_XSCALE, 0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"}, |
|
187 {ARM_CEXT_XSCALE, 0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"}, |
|
188 {ARM_CEXT_XSCALE, 0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"}, |
|
189 {ARM_CEXT_XSCALE, 0x0e400000, 0x0fe00ff0, "wavg4%20'r%c\t%12-15g, %16-19g, %0-3g"}, |
|
190 {ARM_CEXT_XSCALE, 0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
191 {ARM_CEXT_XSCALE, 0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
192 {ARM_CEXT_XSCALE, 0xfc500100, 0xfe500f00, "wldrd\t%12-15g, %r"}, |
|
193 {ARM_CEXT_XSCALE, 0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"}, |
|
194 {ARM_CEXT_XSCALE, 0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"}, |
|
195 {ARM_CEXT_XSCALE, 0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"}, |
|
196 {ARM_CEXT_XSCALE, 0x0e800100, 0x0fc00ff0, "wmadd%21?su%20'x%c\t%12-15g, %16-19g, %0-3g"}, |
|
197 {ARM_CEXT_XSCALE, 0x0ec00100, 0x0fd00ff0, "wmadd%21?sun%c\t%12-15g, %16-19g, %0-3g"}, |
|
198 {ARM_CEXT_XSCALE, 0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
199 {ARM_CEXT_XSCALE, 0x0e000080, 0x0f100fe0, "wmerge%c\t%12-15g, %16-19g, %0-3g, #%21-23d"}, |
|
200 {ARM_CEXT_XSCALE, 0x0e0000a0, 0x0f800ff0, "wmia%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"}, |
|
201 {ARM_CEXT_XSCALE, 0x0e800120, 0x0f800ff0, "wmiaw%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"}, |
|
202 {ARM_CEXT_XSCALE, 0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
203 {ARM_CEXT_XSCALE, 0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%23'r%c\t%12-15g, %16-19g, %0-3g"}, |
|
204 {ARM_CEXT_XSCALE, 0x0ed00100, 0x0fd00ff0, "wmul%21?sumr%c\t%12-15g, %16-19g, %0-3g"}, |
|
205 {ARM_CEXT_XSCALE, 0x0ee000c0, 0x0fe00ff0, "wmulwsm%20`r%c\t%12-15g, %16-19g, %0-3g"}, |
|
206 {ARM_CEXT_XSCALE, 0x0ec000c0, 0x0fe00ff0, "wmulwum%20`r%c\t%12-15g, %16-19g, %0-3g"}, |
|
207 {ARM_CEXT_XSCALE, 0x0eb000c0, 0x0ff00ff0, "wmulwl%c\t%12-15g, %16-19g, %0-3g"}, |
|
208 {ARM_CEXT_XSCALE, 0x0e8000a0, 0x0f800ff0, "wqmia%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"}, |
|
209 {ARM_CEXT_XSCALE, 0x0e100080, 0x0fd00ff0, "wqmulm%21'r%c\t%12-15g, %16-19g, %0-3g"}, |
|
210 {ARM_CEXT_XSCALE, 0x0ec000e0, 0x0fd00ff0, "wqmulwm%21'r%c\t%12-15g, %16-19g, %0-3g"}, |
|
211 {ARM_CEXT_XSCALE, 0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"}, |
|
212 {ARM_CEXT_XSCALE, 0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
213 {ARM_CEXT_XSCALE, 0xfe300040, 0xff300ef0, "wror%22-23w\t%12-15g, %16-19g, #%i"}, |
|
214 {ARM_CEXT_XSCALE, 0x0e300040, 0x0f300ff0, "wror%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
215 {ARM_CEXT_XSCALE, 0x0e300140, 0x0f300ff0, "wror%22-23wg%c\t%12-15g, %16-19g, %0-3G"}, |
|
216 {ARM_CEXT_XSCALE, 0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"}, |
|
217 {ARM_CEXT_XSCALE, 0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"}, |
|
218 {ARM_CEXT_XSCALE, 0xfe100040, 0xff300ef0, "wsll%22-23w\t%12-15g, %16-19g, #%i"}, |
|
219 {ARM_CEXT_XSCALE, 0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, |
|
220 {ARM_CEXT_XSCALE, 0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, |
|
221 {ARM_CEXT_XSCALE, 0xfe000040, 0xff300ef0, "wsra%22-23w\t%12-15g, %16-19g, #%i"}, |
|
222 {ARM_CEXT_XSCALE, 0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, |
|
223 {ARM_CEXT_XSCALE, 0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, |
|
224 {ARM_CEXT_XSCALE, 0xfe200040, 0xff300ef0, "wsrl%22-23w\t%12-15g, %16-19g, #%i"}, |
|
225 {ARM_CEXT_XSCALE, 0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, |
|
226 {ARM_CEXT_XSCALE, 0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, |
|
227 {ARM_CEXT_XSCALE, 0xfc400100, 0xfe500f00, "wstrd\t%12-15g, %r"}, |
|
228 {ARM_CEXT_XSCALE, 0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"}, |
|
229 {ARM_CEXT_XSCALE, 0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"}, |
|
230 {ARM_CEXT_XSCALE, 0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
231 {ARM_CEXT_XSCALE, 0x0ed001c0, 0x0ff00ff0, "wsubaddhx%c\t%12-15g, %16-19g, %0-3g"}, |
|
232 {ARM_CEXT_XSCALE, 0x0e1001c0, 0x0f300ff0, "wabsdiff%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
233 {ARM_CEXT_XSCALE, 0x0e0000c0, 0x0fd00fff, "wunpckeh%21?sub%c\t%12-15g, %16-19g"}, |
|
234 {ARM_CEXT_XSCALE, 0x0e4000c0, 0x0fd00fff, "wunpckeh%21?suh%c\t%12-15g, %16-19g"}, |
|
235 {ARM_CEXT_XSCALE, 0x0e8000c0, 0x0fd00fff, "wunpckeh%21?suw%c\t%12-15g, %16-19g"}, |
|
236 {ARM_CEXT_XSCALE, 0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"}, |
|
237 {ARM_CEXT_XSCALE, 0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
238 {ARM_CEXT_XSCALE, 0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"}, |
|
239 {ARM_CEXT_XSCALE, 0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"}, |
|
240 |
|
241 /* Floating point coprocessor (FPA) instructions */ |
|
242 {FPU_FPA_EXT_V1, 0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
243 {FPU_FPA_EXT_V1, 0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
244 {FPU_FPA_EXT_V1, 0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
245 {FPU_FPA_EXT_V1, 0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
246 {FPU_FPA_EXT_V1, 0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
247 {FPU_FPA_EXT_V1, 0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
248 {FPU_FPA_EXT_V1, 0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
249 {FPU_FPA_EXT_V1, 0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
250 {FPU_FPA_EXT_V1, 0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
251 {FPU_FPA_EXT_V1, 0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
252 {FPU_FPA_EXT_V1, 0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
253 {FPU_FPA_EXT_V1, 0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
254 {FPU_FPA_EXT_V1, 0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"}, |
|
255 {FPU_FPA_EXT_V1, 0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"}, |
|
256 {FPU_FPA_EXT_V1, 0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"}, |
|
257 {FPU_FPA_EXT_V1, 0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"}, |
|
258 {FPU_FPA_EXT_V1, 0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"}, |
|
259 {FPU_FPA_EXT_V1, 0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"}, |
|
260 {FPU_FPA_EXT_V1, 0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"}, |
|
261 {FPU_FPA_EXT_V1, 0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"}, |
|
262 {FPU_FPA_EXT_V1, 0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"}, |
|
263 {FPU_FPA_EXT_V1, 0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"}, |
|
264 {FPU_FPA_EXT_V1, 0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"}, |
|
265 {FPU_FPA_EXT_V1, 0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"}, |
|
266 {FPU_FPA_EXT_V1, 0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"}, |
|
267 {FPU_FPA_EXT_V1, 0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"}, |
|
268 {FPU_FPA_EXT_V1, 0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"}, |
|
269 {FPU_FPA_EXT_V1, 0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"}, |
|
270 {FPU_FPA_EXT_V1, 0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"}, |
|
271 {FPU_FPA_EXT_V1, 0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"}, |
|
272 {FPU_FPA_EXT_V1, 0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"}, |
|
273 {FPU_FPA_EXT_V1, 0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"}, |
|
274 {FPU_FPA_EXT_V1, 0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"}, |
|
275 {FPU_FPA_EXT_V1, 0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"}, |
|
276 {FPU_FPA_EXT_V1, 0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"}, |
|
277 {FPU_FPA_EXT_V1, 0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"}, |
|
278 {FPU_FPA_EXT_V1, 0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"}, |
|
279 {FPU_FPA_EXT_V1, 0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"}, |
|
280 {FPU_FPA_EXT_V1, 0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"}, |
|
281 {FPU_FPA_EXT_V1, 0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"}, |
|
282 {FPU_FPA_EXT_V1, 0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"}, |
|
283 {FPU_FPA_EXT_V2, 0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"}, |
|
284 {FPU_FPA_EXT_V2, 0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"}, |
|
285 |
|
286 /* Register load/store */ |
|
287 {FPU_NEON_EXT_V1, 0x0d200b00, 0x0fb00f01, "vstmdb%c\t%16-19r%21'!, %B"}, |
|
288 {FPU_NEON_EXT_V1, 0x0d300b00, 0x0fb00f01, "vldmdb%c\t%16-19r%21'!, %B"}, |
|
289 {FPU_NEON_EXT_V1, 0x0c800b00, 0x0f900f01, "vstmia%c\t%16-19r%21'!, %B"}, |
|
290 {FPU_NEON_EXT_V1, 0x0c900b00, 0x0f900f01, "vldmia%c\t%16-19r%21'!, %B"}, |
|
291 {FPU_NEON_EXT_V1, 0x0d000b00, 0x0f300f00, "vstr%c\t%12-15,22D, %C"}, |
|
292 {FPU_NEON_EXT_V1, 0x0d100b00, 0x0f300f00, "vldr%c\t%12-15,22D, %C"}, |
|
293 |
|
294 /* Data transfer between ARM and NEON registers */ |
|
295 {FPU_NEON_EXT_V1, 0x0e800b10, 0x0ff00f70, "vdup%c.32\t%16-19,7D, %12-15r"}, |
|
296 {FPU_NEON_EXT_V1, 0x0e800b30, 0x0ff00f70, "vdup%c.16\t%16-19,7D, %12-15r"}, |
|
297 {FPU_NEON_EXT_V1, 0x0ea00b10, 0x0ff00f70, "vdup%c.32\t%16-19,7Q, %12-15r"}, |
|
298 {FPU_NEON_EXT_V1, 0x0ea00b30, 0x0ff00f70, "vdup%c.16\t%16-19,7Q, %12-15r"}, |
|
299 {FPU_NEON_EXT_V1, 0x0ec00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7D, %12-15r"}, |
|
300 {FPU_NEON_EXT_V1, 0x0ee00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7Q, %12-15r"}, |
|
301 {FPU_NEON_EXT_V1, 0x0c400b10, 0x0ff00fd0, "vmov%c\t%0-3,5D, %12-15r, %16-19r"}, |
|
302 {FPU_NEON_EXT_V1, 0x0c500b10, 0x0ff00fd0, "vmov%c\t%12-15r, %16-19r, %0-3,5D"}, |
|
303 {FPU_NEON_EXT_V1, 0x0e000b10, 0x0fd00f70, "vmov%c.32\t%16-19,7D[%21d], %12-15r"}, |
|
304 {FPU_NEON_EXT_V1, 0x0e100b10, 0x0f500f70, "vmov%c.32\t%12-15r, %16-19,7D[%21d]"}, |
|
305 {FPU_NEON_EXT_V1, 0x0e000b30, 0x0fd00f30, "vmov%c.16\t%16-19,7D[%6,21d], %12-15r"}, |
|
306 {FPU_NEON_EXT_V1, 0x0e100b30, 0x0f500f30, "vmov%c.%23?us16\t%12-15r, %16-19,7D[%6,21d]"}, |
|
307 {FPU_NEON_EXT_V1, 0x0e400b10, 0x0fd00f10, "vmov%c.8\t%16-19,7D[%5,6,21d], %12-15r"}, |
|
308 {FPU_NEON_EXT_V1, 0x0e500b10, 0x0f500f10, "vmov%c.%23?us8\t%12-15r, %16-19,7D[%5,6,21d]"}, |
|
309 |
|
310 /* Floating point coprocessor (VFP) instructions */ |
|
311 {FPU_VFP_EXT_V1xD, 0x0ef1fa10, 0x0fffffff, "fmstat%c"}, |
|
312 {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"}, |
|
313 {FPU_VFP_EXT_V1xD, 0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"}, |
|
314 {FPU_VFP_EXT_V1xD, 0x0ee60a10, 0x0fff0fff, "fmxr%c\tmvfr1, %12-15r"}, |
|
315 {FPU_VFP_EXT_V1xD, 0x0ee70a10, 0x0fff0fff, "fmxr%c\tmvfr0, %12-15r"}, |
|
316 {FPU_VFP_EXT_V1xD, 0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"}, |
|
317 {FPU_VFP_EXT_V1xD, 0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"}, |
|
318 {FPU_VFP_EXT_V1xD, 0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"}, |
|
319 {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"}, |
|
320 {FPU_VFP_EXT_V1xD, 0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"}, |
|
321 {FPU_VFP_EXT_V1xD, 0x0ef60a10, 0x0fff0fff, "fmrx%c\t%12-15r, mvfr1"}, |
|
322 {FPU_VFP_EXT_V1xD, 0x0ef70a10, 0x0fff0fff, "fmrx%c\t%12-15r, mvfr0"}, |
|
323 {FPU_VFP_EXT_V1xD, 0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"}, |
|
324 {FPU_VFP_EXT_V1xD, 0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"}, |
|
325 {FPU_VFP_EXT_V1xD, 0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"}, |
|
326 {FPU_VFP_EXT_V1, 0x0e000b10, 0x0ff00fff, "fmdlr%c\t%z2, %12-15r"}, |
|
327 {FPU_VFP_EXT_V1, 0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %z2"}, |
|
328 {FPU_VFP_EXT_V1, 0x0e200b10, 0x0ff00fff, "fmdhr%c\t%z2, %12-15r"}, |
|
329 {FPU_VFP_EXT_V1, 0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %z2"}, |
|
330 {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def %16-19x>, %12-15r"}, |
|
331 {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def %16-19x>"}, |
|
332 {FPU_VFP_EXT_V1xD, 0x0e000a10, 0x0ff00f7f, "fmsr%c\t%y2, %12-15r"}, |
|
333 {FPU_VFP_EXT_V1xD, 0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %y2"}, |
|
334 {FPU_VFP_EXT_V1xD, 0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%y1"}, |
|
335 {FPU_VFP_EXT_V1, 0x0eb50b40, 0x0fbf0f70, "fcmp%7'ezd%c\t%z1"}, |
|
336 {FPU_VFP_EXT_V1xD, 0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%y1, %y0"}, |
|
337 {FPU_VFP_EXT_V1xD, 0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%y1, %y0"}, |
|
338 {FPU_VFP_EXT_V1, 0x0eb00b40, 0x0fbf0fd0, "fcpyd%c\t%z1, %z0"}, |
|
339 {FPU_VFP_EXT_V1, 0x0eb00bc0, 0x0fbf0fd0, "fabsd%c\t%z1, %z0"}, |
|
340 {FPU_VFP_EXT_V1xD, 0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%y1, %y0"}, |
|
341 {FPU_VFP_EXT_V1xD, 0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%y1, %y0"}, |
|
342 {FPU_VFP_EXT_V1, 0x0eb10b40, 0x0fbf0fd0, "fnegd%c\t%z1, %z0"}, |
|
343 {FPU_VFP_EXT_V1, 0x0eb10bc0, 0x0fbf0fd0, "fsqrtd%c\t%z1, %z0"}, |
|
344 {FPU_VFP_EXT_V1, 0x0eb70ac0, 0x0fbf0fd0, "fcvtds%c\t%z1, %y0"}, |
|
345 {FPU_VFP_EXT_V1, 0x0eb70bc0, 0x0fbf0fd0, "fcvtsd%c\t%y1, %z0"}, |
|
346 {FPU_VFP_EXT_V1xD, 0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%y1, %y0"}, |
|
347 {FPU_VFP_EXT_V1xD, 0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%y1, %y0"}, |
|
348 {FPU_VFP_EXT_V1, 0x0eb80b40, 0x0fbf0fd0, "fuitod%c\t%z1, %y0"}, |
|
349 {FPU_VFP_EXT_V1, 0x0eb80bc0, 0x0fbf0fd0, "fsitod%c\t%z1, %y0"}, |
|
350 {FPU_VFP_EXT_V1xD, 0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%y1, %y0"}, |
|
351 {FPU_VFP_EXT_V1, 0x0eb40b40, 0x0fbf0f50, "fcmp%7'ed%c\t%z1, %z0"}, |
|
352 {FPU_VFP_EXT_V3, 0x0eba0a40, 0x0fbe0f50, "f%16?us%7?lhtos%c\t%y1, #%5,0-3k"}, |
|
353 {FPU_VFP_EXT_V3, 0x0eba0b40, 0x0fbe0f50, "f%16?us%7?lhtod%c\t%z1, #%5,0-3k"}, |
|
354 {FPU_VFP_EXT_V1xD, 0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%y1, %y0"}, |
|
355 {FPU_VFP_EXT_V1, 0x0ebc0b40, 0x0fbe0f50, "fto%16?sui%7'zd%c\t%y1, %z0"}, |
|
356 {FPU_VFP_EXT_V3, 0x0ebe0a40, 0x0fbe0f50, "fto%16?us%7?lhs%c\t%y1, #%5,0-3k"}, |
|
357 {FPU_VFP_EXT_V3, 0x0ebe0b40, 0x0fbe0f50, "fto%16?us%7?lhd%c\t%z1, #%5,0-3k"}, |
|
358 {FPU_VFP_EXT_V1, 0x0c500b10, 0x0fb00ff0, "fmrrd%c\t%12-15r, %16-19r, %z0"}, |
|
359 {FPU_VFP_EXT_V3, 0x0eb00a00, 0x0fb00ff0, "fconsts%c\t%y1, #%0-3,16-19d"}, |
|
360 {FPU_VFP_EXT_V3, 0x0eb00b00, 0x0fb00ff0, "fconstd%c\t%z1, #%0-3,16-19d"}, |
|
361 {FPU_VFP_EXT_V2, 0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%y4, %12-15r, %16-19r"}, |
|
362 {FPU_VFP_EXT_V2, 0x0c400b10, 0x0ff00fd0, "fmdrr%c\t%z0, %12-15r, %16-19r"}, |
|
363 {FPU_VFP_EXT_V2, 0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %y4"}, |
|
364 {FPU_VFP_EXT_V1xD, 0x0e000a00, 0x0fb00f50, "fmacs%c\t%y1, %y2, %y0"}, |
|
365 {FPU_VFP_EXT_V1xD, 0x0e000a40, 0x0fb00f50, "fnmacs%c\t%y1, %y2, %y0"}, |
|
366 {FPU_VFP_EXT_V1, 0x0e000b00, 0x0fb00f50, "fmacd%c\t%z1, %z2, %z0"}, |
|
367 {FPU_VFP_EXT_V1, 0x0e000b40, 0x0fb00f50, "fnmacd%c\t%z1, %z2, %z0"}, |
|
368 {FPU_VFP_EXT_V1xD, 0x0e100a00, 0x0fb00f50, "fmscs%c\t%y1, %y2, %y0"}, |
|
369 {FPU_VFP_EXT_V1xD, 0x0e100a40, 0x0fb00f50, "fnmscs%c\t%y1, %y2, %y0"}, |
|
370 {FPU_VFP_EXT_V1, 0x0e100b00, 0x0fb00f50, "fmscd%c\t%z1, %z2, %z0"}, |
|
371 {FPU_VFP_EXT_V1, 0x0e100b40, 0x0fb00f50, "fnmscd%c\t%z1, %z2, %z0"}, |
|
372 {FPU_VFP_EXT_V1xD, 0x0e200a00, 0x0fb00f50, "fmuls%c\t%y1, %y2, %y0"}, |
|
373 {FPU_VFP_EXT_V1xD, 0x0e200a40, 0x0fb00f50, "fnmuls%c\t%y1, %y2, %y0"}, |
|
374 {FPU_VFP_EXT_V1, 0x0e200b00, 0x0fb00f50, "fmuld%c\t%z1, %z2, %z0"}, |
|
375 {FPU_VFP_EXT_V1, 0x0e200b40, 0x0fb00f50, "fnmuld%c\t%z1, %z2, %z0"}, |
|
376 {FPU_VFP_EXT_V1xD, 0x0e300a00, 0x0fb00f50, "fadds%c\t%y1, %y2, %y0"}, |
|
377 {FPU_VFP_EXT_V1xD, 0x0e300a40, 0x0fb00f50, "fsubs%c\t%y1, %y2, %y0"}, |
|
378 {FPU_VFP_EXT_V1, 0x0e300b00, 0x0fb00f50, "faddd%c\t%z1, %z2, %z0"}, |
|
379 {FPU_VFP_EXT_V1, 0x0e300b40, 0x0fb00f50, "fsubd%c\t%z1, %z2, %z0"}, |
|
380 {FPU_VFP_EXT_V1xD, 0x0e800a00, 0x0fb00f50, "fdivs%c\t%y1, %y2, %y0"}, |
|
381 {FPU_VFP_EXT_V1, 0x0e800b00, 0x0fb00f50, "fdivd%c\t%z1, %z2, %z0"}, |
|
382 {FPU_VFP_EXT_V1xD, 0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %y3"}, |
|
383 {FPU_VFP_EXT_V1xD, 0x0d200b00, 0x0fb00f00, "fstmdb%0?xd%c\t%16-19r!, %z3"}, |
|
384 {FPU_VFP_EXT_V1xD, 0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %y3"}, |
|
385 {FPU_VFP_EXT_V1xD, 0x0d300b00, 0x0fb00f00, "fldmdb%0?xd%c\t%16-19r!, %z3"}, |
|
386 {FPU_VFP_EXT_V1xD, 0x0d000a00, 0x0f300f00, "fsts%c\t%y1, %A"}, |
|
387 {FPU_VFP_EXT_V1, 0x0d000b00, 0x0f300f00, "fstd%c\t%z1, %A"}, |
|
388 {FPU_VFP_EXT_V1xD, 0x0d100a00, 0x0f300f00, "flds%c\t%y1, %A"}, |
|
389 {FPU_VFP_EXT_V1, 0x0d100b00, 0x0f300f00, "fldd%c\t%z1, %A"}, |
|
390 {FPU_VFP_EXT_V1xD, 0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %y3"}, |
|
391 {FPU_VFP_EXT_V1xD, 0x0c800b00, 0x0f900f00, "fstmia%0?xd%c\t%16-19r%21'!, %z3"}, |
|
392 {FPU_VFP_EXT_V1xD, 0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %y3"}, |
|
393 {FPU_VFP_EXT_V1xD, 0x0c900b00, 0x0f900f00, "fldmia%0?xd%c\t%16-19r%21'!, %z3"}, |
|
394 |
|
395 /* Cirrus coprocessor instructions. */ |
|
396 {ARM_CEXT_MAVERICK, 0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"}, |
|
397 {ARM_CEXT_MAVERICK, 0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"}, |
|
398 {ARM_CEXT_MAVERICK, 0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"}, |
|
399 {ARM_CEXT_MAVERICK, 0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"}, |
|
400 {ARM_CEXT_MAVERICK, 0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"}, |
|
401 {ARM_CEXT_MAVERICK, 0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"}, |
|
402 {ARM_CEXT_MAVERICK, 0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"}, |
|
403 {ARM_CEXT_MAVERICK, 0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"}, |
|
404 {ARM_CEXT_MAVERICK, 0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"}, |
|
405 {ARM_CEXT_MAVERICK, 0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"}, |
|
406 {ARM_CEXT_MAVERICK, 0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"}, |
|
407 {ARM_CEXT_MAVERICK, 0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"}, |
|
408 {ARM_CEXT_MAVERICK, 0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"}, |
|
409 {ARM_CEXT_MAVERICK, 0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"}, |
|
410 {ARM_CEXT_MAVERICK, 0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"}, |
|
411 {ARM_CEXT_MAVERICK, 0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"}, |
|
412 {ARM_CEXT_MAVERICK, 0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"}, |
|
413 {ARM_CEXT_MAVERICK, 0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"}, |
|
414 {ARM_CEXT_MAVERICK, 0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"}, |
|
415 {ARM_CEXT_MAVERICK, 0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"}, |
|
416 {ARM_CEXT_MAVERICK, 0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"}, |
|
417 {ARM_CEXT_MAVERICK, 0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"}, |
|
418 {ARM_CEXT_MAVERICK, 0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"}, |
|
419 {ARM_CEXT_MAVERICK, 0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"}, |
|
420 {ARM_CEXT_MAVERICK, 0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"}, |
|
421 {ARM_CEXT_MAVERICK, 0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"}, |
|
422 {ARM_CEXT_MAVERICK, 0x0e200440, 0x0ff00fff, "cfmval32%c\tmvax%12-15d, mvfx%16-19d"}, |
|
423 {ARM_CEXT_MAVERICK, 0x0e100440, 0x0ff00fff, "cfmv32al%c\tmvfx%12-15d, mvax%16-19d"}, |
|
424 {ARM_CEXT_MAVERICK, 0x0e200460, 0x0ff00fff, "cfmvam32%c\tmvax%12-15d, mvfx%16-19d"}, |
|
425 {ARM_CEXT_MAVERICK, 0x0e100460, 0x0ff00fff, "cfmv32am%c\tmvfx%12-15d, mvax%16-19d"}, |
|
426 {ARM_CEXT_MAVERICK, 0x0e200480, 0x0ff00fff, "cfmvah32%c\tmvax%12-15d, mvfx%16-19d"}, |
|
427 {ARM_CEXT_MAVERICK, 0x0e100480, 0x0ff00fff, "cfmv32ah%c\tmvfx%12-15d, mvax%16-19d"}, |
|
428 {ARM_CEXT_MAVERICK, 0x0e2004a0, 0x0ff00fff, "cfmva32%c\tmvax%12-15d, mvfx%16-19d"}, |
|
429 {ARM_CEXT_MAVERICK, 0x0e1004a0, 0x0ff00fff, "cfmv32a%c\tmvfx%12-15d, mvax%16-19d"}, |
|
430 {ARM_CEXT_MAVERICK, 0x0e2004c0, 0x0ff00fff, "cfmva64%c\tmvax%12-15d, mvdx%16-19d"}, |
|
431 {ARM_CEXT_MAVERICK, 0x0e1004c0, 0x0ff00fff, "cfmv64a%c\tmvdx%12-15d, mvax%16-19d"}, |
|
432 {ARM_CEXT_MAVERICK, 0x0e2004e0, 0x0fff0fff, "cfmvsc32%c\tdspsc, mvdx%12-15d"}, |
|
433 {ARM_CEXT_MAVERICK, 0x0e1004e0, 0x0fff0fff, "cfmv32sc%c\tmvdx%12-15d, dspsc"}, |
|
434 {ARM_CEXT_MAVERICK, 0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"}, |
|
435 {ARM_CEXT_MAVERICK, 0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"}, |
|
436 {ARM_CEXT_MAVERICK, 0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"}, |
|
437 {ARM_CEXT_MAVERICK, 0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"}, |
|
438 {ARM_CEXT_MAVERICK, 0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"}, |
|
439 {ARM_CEXT_MAVERICK, 0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"}, |
|
440 {ARM_CEXT_MAVERICK, 0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"}, |
|
441 {ARM_CEXT_MAVERICK, 0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"}, |
|
442 {ARM_CEXT_MAVERICK, 0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"}, |
|
443 {ARM_CEXT_MAVERICK, 0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"}, |
|
444 {ARM_CEXT_MAVERICK, 0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"}, |
|
445 {ARM_CEXT_MAVERICK, 0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"}, |
|
446 {ARM_CEXT_MAVERICK, 0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"}, |
|
447 {ARM_CEXT_MAVERICK, 0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"}, |
|
448 {ARM_CEXT_MAVERICK, 0x0e000500, 0x0ff00f10, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"}, |
|
449 {ARM_CEXT_MAVERICK, 0x0e200500, 0x0ff00f10, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"}, |
|
450 {ARM_CEXT_MAVERICK, 0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"}, |
|
451 {ARM_CEXT_MAVERICK, 0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"}, |
|
452 {ARM_CEXT_MAVERICK, 0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"}, |
|
453 {ARM_CEXT_MAVERICK, 0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"}, |
|
454 {ARM_CEXT_MAVERICK, 0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"}, |
|
455 {ARM_CEXT_MAVERICK, 0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"}, |
|
456 {ARM_CEXT_MAVERICK, 0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"}, |
|
457 {ARM_CEXT_MAVERICK, 0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"}, |
|
458 {ARM_CEXT_MAVERICK, 0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"}, |
|
459 {ARM_CEXT_MAVERICK, 0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"}, |
|
460 {ARM_CEXT_MAVERICK, 0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"}, |
|
461 {ARM_CEXT_MAVERICK, 0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"}, |
|
462 {ARM_CEXT_MAVERICK, 0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"}, |
|
463 {ARM_CEXT_MAVERICK, 0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"}, |
|
464 {ARM_CEXT_MAVERICK, 0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"}, |
|
465 {ARM_CEXT_MAVERICK, 0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"}, |
|
466 {ARM_CEXT_MAVERICK, 0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"}, |
|
467 {ARM_CEXT_MAVERICK, 0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"}, |
|
468 {ARM_CEXT_MAVERICK, 0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
469 {ARM_CEXT_MAVERICK, 0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"}, |
|
470 {ARM_CEXT_MAVERICK, 0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
471 {ARM_CEXT_MAVERICK, 0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"}, |
|
472 {ARM_CEXT_MAVERICK, 0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
473 {ARM_CEXT_MAVERICK, 0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"}, |
|
474 {ARM_CEXT_MAVERICK, 0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
475 {ARM_CEXT_MAVERICK, 0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
476 {ARM_CEXT_MAVERICK, 0x0e000600, 0x0ff00f10, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
477 {ARM_CEXT_MAVERICK, 0x0e100600, 0x0ff00f10, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
478 {ARM_CEXT_MAVERICK, 0x0e200600, 0x0ff00f10, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
479 {ARM_CEXT_MAVERICK, 0x0e300600, 0x0ff00f10, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"}, |
|
480 |
|
481 /* Generic coprocessor instructions */ |
|
482 {ARM_EXT_V2, 0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, |
|
483 {ARM_EXT_V2, 0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, |
|
484 {ARM_EXT_V2, 0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"}, |
|
485 {ARM_EXT_V2, 0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, |
|
486 {ARM_EXT_V2, 0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, |
|
487 {ARM_EXT_V2, 0x0c000000, 0x0e100000, "stc%22'l%c\t%8-11d, cr%12-15d, %A"}, |
|
488 {ARM_EXT_V2, 0x0c100000, 0x0e100000, "ldc%22'l%c\t%8-11d, cr%12-15d, %A"}, |
|
489 |
|
490 /* V6 coprocessor instructions */ |
|
491 {ARM_EXT_V6, 0xfc500000, 0xfff00000, "mrrc2%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, |
|
492 {ARM_EXT_V6, 0xfc400000, 0xfff00000, "mcrr2%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, |
|
493 |
|
494 /* V5 coprocessor instructions */ |
|
495 {ARM_EXT_V5, 0xfc100000, 0xfe100000, "ldc2%22'l%c\t%8-11d, cr%12-15d, %A"}, |
|
496 {ARM_EXT_V5, 0xfc000000, 0xfe100000, "stc2%22'l%c\t%8-11d, cr%12-15d, %A"}, |
|
497 {ARM_EXT_V5, 0xfe000000, 0xff000010, "cdp2%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"}, |
|
498 {ARM_EXT_V5, 0xfe000010, 0xff100010, "mcr2%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, |
|
499 {ARM_EXT_V5, 0xfe100010, 0xff100010, "mrc2%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, |
|
500 |
|
501 {0, 0, 0, 0} |
|
502 }; |
|
503 |
|
504 /* Neon opcode table: This does not encode the top byte -- that is |
|
505 checked by the print_insn_neon routine, as it depends on whether we are |
|
506 doing thumb32 or arm32 disassembly. */ |
|
507 |
|
508 /* print_insn_neon recognizes the following format control codes: |
|
509 |
|
510 %% % |
|
511 |
|
512 %c print condition code |
|
513 %A print v{st,ld}[1234] operands |
|
514 %B print v{st,ld}[1234] any one operands |
|
515 %C print v{st,ld}[1234] single->all operands |
|
516 %D print scalar |
|
517 %E print vmov, vmvn, vorr, vbic encoded constant |
|
518 %F print vtbl,vtbx register list |
|
519 |
|
520 %<bitfield>r print as an ARM register |
|
521 %<bitfield>d print the bitfield in decimal |
|
522 %<bitfield>e print the 2^N - bitfield in decimal |
|
523 %<bitfield>D print as a NEON D register |
|
524 %<bitfield>Q print as a NEON Q register |
|
525 %<bitfield>R print as a NEON D or Q register |
|
526 %<bitfield>Sn print byte scaled width limited by n |
|
527 %<bitfield>Tn print short scaled width limited by n |
|
528 %<bitfield>Un print long scaled width limited by n |
|
529 |
|
530 %<bitfield>'c print specified char iff bitfield is all ones |
|
531 %<bitfield>`c print specified char iff bitfield is all zeroes |
|
532 %<bitfield>?ab... select from array of values in big endian order */ |
|
533 |
|
534 static const struct opcode32 neon_opcodes[] = |
|
535 { |
|
536 /* Extract */ |
|
537 {FPU_NEON_EXT_V1, 0xf2b00840, 0xffb00850, "vext%c.8\t%12-15,22R, %16-19,7R, %0-3,5R, #%8-11d"}, |
|
538 {FPU_NEON_EXT_V1, 0xf2b00000, 0xffb00810, "vext%c.8\t%12-15,22R, %16-19,7R, %0-3,5R, #%8-11d"}, |
|
539 |
|
540 /* Move data element to all lanes */ |
|
541 {FPU_NEON_EXT_V1, 0xf3b40c00, 0xffb70f90, "vdup%c.32\t%12-15,22R, %0-3,5D[%19d]"}, |
|
542 {FPU_NEON_EXT_V1, 0xf3b20c00, 0xffb30f90, "vdup%c.16\t%12-15,22R, %0-3,5D[%18-19d]"}, |
|
543 {FPU_NEON_EXT_V1, 0xf3b10c00, 0xffb10f90, "vdup%c.8\t%12-15,22R, %0-3,5D[%17-19d]"}, |
|
544 |
|
545 /* Table lookup */ |
|
546 {FPU_NEON_EXT_V1, 0xf3b00800, 0xffb00c50, "vtbl%c.8\t%12-15,22D, %F, %0-3,5D"}, |
|
547 {FPU_NEON_EXT_V1, 0xf3b00840, 0xffb00c50, "vtbx%c.8\t%12-15,22D, %F, %0-3,5D"}, |
|
548 |
|
549 /* Two registers, miscellaneous */ |
|
550 {FPU_NEON_EXT_V1, 0xf2880a10, 0xfebf0fd0, "vmovl%c.%24?us8\t%12-15,22Q, %0-3,5D"}, |
|
551 {FPU_NEON_EXT_V1, 0xf2900a10, 0xfebf0fd0, "vmovl%c.%24?us16\t%12-15,22Q, %0-3,5D"}, |
|
552 {FPU_NEON_EXT_V1, 0xf2a00a10, 0xfebf0fd0, "vmovl%c.%24?us32\t%12-15,22Q, %0-3,5D"}, |
|
553 {FPU_NEON_EXT_V1, 0xf3b00500, 0xffbf0f90, "vcnt%c.8\t%12-15,22R, %0-3,5R"}, |
|
554 {FPU_NEON_EXT_V1, 0xf3b00580, 0xffbf0f90, "vmvn%c\t%12-15,22R, %0-3,5R"}, |
|
555 {FPU_NEON_EXT_V1, 0xf3b20000, 0xffbf0f90, "vswp%c\t%12-15,22R, %0-3,5R"}, |
|
556 {FPU_NEON_EXT_V1, 0xf3b20200, 0xffb30fd0, "vmovn%c.i%18-19T2\t%12-15,22D, %0-3,5Q"}, |
|
557 {FPU_NEON_EXT_V1, 0xf3b20240, 0xffb30fd0, "vqmovun%c.s%18-19T2\t%12-15,22D, %0-3,5Q"}, |
|
558 {FPU_NEON_EXT_V1, 0xf3b20280, 0xffb30fd0, "vqmovn%c.s%18-19T2\t%12-15,22D, %0-3,5Q"}, |
|
559 {FPU_NEON_EXT_V1, 0xf3b202c0, 0xffb30fd0, "vqmovn%c.u%18-19T2\t%12-15,22D, %0-3,5Q"}, |
|
560 {FPU_NEON_EXT_V1, 0xf3b20300, 0xffb30fd0, "vshll%c.i%18-19S2\t%12-15,22Q, %0-3,5D, #%18-19S2"}, |
|
561 {FPU_NEON_EXT_V1, 0xf3bb0400, 0xffbf0e90, "vrecpe%c.%8?fu%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
562 {FPU_NEON_EXT_V1, 0xf3bb0480, 0xffbf0e90, "vrsqrte%c.%8?fu%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
563 {FPU_NEON_EXT_V1, 0xf3b00000, 0xffb30f90, "vrev64%c.%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
564 {FPU_NEON_EXT_V1, 0xf3b00080, 0xffb30f90, "vrev32%c.%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
565 {FPU_NEON_EXT_V1, 0xf3b00100, 0xffb30f90, "vrev16%c.%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
566 {FPU_NEON_EXT_V1, 0xf3b00400, 0xffb30f90, "vcls%c.s%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
567 {FPU_NEON_EXT_V1, 0xf3b00480, 0xffb30f90, "vclz%c.i%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
568 {FPU_NEON_EXT_V1, 0xf3b00700, 0xffb30f90, "vqabs%c.s%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
569 {FPU_NEON_EXT_V1, 0xf3b00780, 0xffb30f90, "vqneg%c.s%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
570 {FPU_NEON_EXT_V1, 0xf3b20080, 0xffb30f90, "vtrn%c.%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
571 {FPU_NEON_EXT_V1, 0xf3b20100, 0xffb30f90, "vuzp%c.%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
572 {FPU_NEON_EXT_V1, 0xf3b20180, 0xffb30f90, "vzip%c.%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
573 {FPU_NEON_EXT_V1, 0xf3b10000, 0xffb30b90, "vcgt%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, |
|
574 {FPU_NEON_EXT_V1, 0xf3b10080, 0xffb30b90, "vcge%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, |
|
575 {FPU_NEON_EXT_V1, 0xf3b10100, 0xffb30b90, "vceq%c.%10?fi%18-19S2\t%12-15,22R, %0-3,5R, #0"}, |
|
576 {FPU_NEON_EXT_V1, 0xf3b10180, 0xffb30b90, "vcle%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, |
|
577 {FPU_NEON_EXT_V1, 0xf3b10200, 0xffb30b90, "vclt%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, |
|
578 {FPU_NEON_EXT_V1, 0xf3b10300, 0xffb30b90, "vabs%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
579 {FPU_NEON_EXT_V1, 0xf3b10380, 0xffb30b90, "vneg%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
580 {FPU_NEON_EXT_V1, 0xf3b00200, 0xffb30f10, "vpaddl%c.%7?us%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
581 {FPU_NEON_EXT_V1, 0xf3b00600, 0xffb30f10, "vpadal%c.%7?us%18-19S2\t%12-15,22R, %0-3,5R"}, |
|
582 {FPU_NEON_EXT_V1, 0xf3b30600, 0xffb30e10, "vcvt%c.%7-8?usff%18-19Sa.%7-8?ffus%18-19Sa\t%12-15,22R, %0-3,5R"}, |
|
583 |
|
584 /* Three registers of the same length */ |
|
585 {FPU_NEON_EXT_V1, 0xf2000110, 0xffb00f10, "vand%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
586 {FPU_NEON_EXT_V1, 0xf2100110, 0xffb00f10, "vbic%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
587 {FPU_NEON_EXT_V1, 0xf2200110, 0xffb00f10, "vorr%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
588 {FPU_NEON_EXT_V1, 0xf2300110, 0xffb00f10, "vorn%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
589 {FPU_NEON_EXT_V1, 0xf3000110, 0xffb00f10, "veor%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
590 {FPU_NEON_EXT_V1, 0xf3100110, 0xffb00f10, "vbsl%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
591 {FPU_NEON_EXT_V1, 0xf3200110, 0xffb00f10, "vbit%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
592 {FPU_NEON_EXT_V1, 0xf3300110, 0xffb00f10, "vbif%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
593 {FPU_NEON_EXT_V1, 0xf2000d00, 0xffa00f10, "vadd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
594 {FPU_NEON_EXT_V1, 0xf2000d10, 0xffa00f10, "vmla%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
595 {FPU_NEON_EXT_V1, 0xf2000e00, 0xffa00f10, "vceq%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
596 {FPU_NEON_EXT_V1, 0xf2000f00, 0xffa00f10, "vmax%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
597 {FPU_NEON_EXT_V1, 0xf2000f10, 0xffa00f10, "vrecps%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
598 {FPU_NEON_EXT_V1, 0xf2200d00, 0xffa00f10, "vsub%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
599 {FPU_NEON_EXT_V1, 0xf2200d10, 0xffa00f10, "vmls%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
600 {FPU_NEON_EXT_V1, 0xf2200f00, 0xffa00f10, "vmin%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
601 {FPU_NEON_EXT_V1, 0xf2200f10, 0xffa00f10, "vrsqrts%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
602 {FPU_NEON_EXT_V1, 0xf3000d00, 0xffa00f10, "vpadd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
603 {FPU_NEON_EXT_V1, 0xf3000d10, 0xffa00f10, "vmul%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
604 {FPU_NEON_EXT_V1, 0xf3000e00, 0xffa00f10, "vcge%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
605 {FPU_NEON_EXT_V1, 0xf3000e10, 0xffa00f10, "vacge%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
606 {FPU_NEON_EXT_V1, 0xf3000f00, 0xffa00f10, "vpmax%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
607 {FPU_NEON_EXT_V1, 0xf3200d00, 0xffa00f10, "vabd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
608 {FPU_NEON_EXT_V1, 0xf3200e00, 0xffa00f10, "vcgt%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
609 {FPU_NEON_EXT_V1, 0xf3200e10, 0xffa00f10, "vacgt%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
610 {FPU_NEON_EXT_V1, 0xf3200f00, 0xffa00f10, "vpmin%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
611 {FPU_NEON_EXT_V1, 0xf2000800, 0xff800f10, "vadd%c.i%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
612 {FPU_NEON_EXT_V1, 0xf2000810, 0xff800f10, "vtst%c.%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
613 {FPU_NEON_EXT_V1, 0xf2000900, 0xff800f10, "vmla%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
614 {FPU_NEON_EXT_V1, 0xf2000b00, 0xff800f10, "vqdmulh%c.s%20-21S6\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
615 {FPU_NEON_EXT_V1, 0xf2000b10, 0xff800f10, "vpadd%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
616 {FPU_NEON_EXT_V1, 0xf3000800, 0xff800f10, "vsub%c.i%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
617 {FPU_NEON_EXT_V1, 0xf3000810, 0xff800f10, "vceq%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
618 {FPU_NEON_EXT_V1, 0xf3000900, 0xff800f10, "vmls%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
619 {FPU_NEON_EXT_V1, 0xf3000b00, 0xff800f10, "vqrdmulh%c.s%20-21S6\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
620 {FPU_NEON_EXT_V1, 0xf2000000, 0xfe800f10, "vhadd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
621 {FPU_NEON_EXT_V1, 0xf2000010, 0xfe800f10, "vqadd%c.%24?us%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
622 {FPU_NEON_EXT_V1, 0xf2000100, 0xfe800f10, "vrhadd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
623 {FPU_NEON_EXT_V1, 0xf2000200, 0xfe800f10, "vhsub%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
624 {FPU_NEON_EXT_V1, 0xf2000210, 0xfe800f10, "vqsub%c.%24?us%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
625 {FPU_NEON_EXT_V1, 0xf2000300, 0xfe800f10, "vcgt%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
626 {FPU_NEON_EXT_V1, 0xf2000310, 0xfe800f10, "vcge%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
627 {FPU_NEON_EXT_V1, 0xf2000400, 0xfe800f10, "vshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, |
|
628 {FPU_NEON_EXT_V1, 0xf2000410, 0xfe800f10, "vqshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, |
|
629 {FPU_NEON_EXT_V1, 0xf2000500, 0xfe800f10, "vrshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, |
|
630 {FPU_NEON_EXT_V1, 0xf2000510, 0xfe800f10, "vqrshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, |
|
631 {FPU_NEON_EXT_V1, 0xf2000600, 0xfe800f10, "vmax%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
632 {FPU_NEON_EXT_V1, 0xf2000610, 0xfe800f10, "vmin%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
633 {FPU_NEON_EXT_V1, 0xf2000700, 0xfe800f10, "vabd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
634 {FPU_NEON_EXT_V1, 0xf2000710, 0xfe800f10, "vaba%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
635 {FPU_NEON_EXT_V1, 0xf2000910, 0xfe800f10, "vmul%c.%24?pi%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
636 {FPU_NEON_EXT_V1, 0xf2000a00, 0xfe800f10, "vpmax%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
637 {FPU_NEON_EXT_V1, 0xf2000a10, 0xfe800f10, "vpmin%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, |
|
638 |
|
639 /* One register and an immediate value */ |
|
640 {FPU_NEON_EXT_V1, 0xf2800e10, 0xfeb80fb0, "vmov%c.i8\t%12-15,22R, %E"}, |
|
641 {FPU_NEON_EXT_V1, 0xf2800e30, 0xfeb80fb0, "vmov%c.i64\t%12-15,22R, %E"}, |
|
642 {FPU_NEON_EXT_V1, 0xf2800f10, 0xfeb80fb0, "vmov%c.f32\t%12-15,22R, %E"}, |
|
643 {FPU_NEON_EXT_V1, 0xf2800810, 0xfeb80db0, "vmov%c.i16\t%12-15,22R, %E"}, |
|
644 {FPU_NEON_EXT_V1, 0xf2800830, 0xfeb80db0, "vmvn%c.i16\t%12-15,22R, %E"}, |
|
645 {FPU_NEON_EXT_V1, 0xf2800910, 0xfeb80db0, "vorr%c.i16\t%12-15,22R, %E"}, |
|
646 {FPU_NEON_EXT_V1, 0xf2800930, 0xfeb80db0, "vbic%c.i16\t%12-15,22R, %E"}, |
|
647 {FPU_NEON_EXT_V1, 0xf2800c10, 0xfeb80eb0, "vmov%c.i32\t%12-15,22R, %E"}, |
|
648 {FPU_NEON_EXT_V1, 0xf2800c30, 0xfeb80eb0, "vmvn%c.i32\t%12-15,22R, %E"}, |
|
649 {FPU_NEON_EXT_V1, 0xf2800110, 0xfeb809b0, "vorr%c.i32\t%12-15,22R, %E"}, |
|
650 {FPU_NEON_EXT_V1, 0xf2800130, 0xfeb809b0, "vbic%c.i32\t%12-15,22R, %E"}, |
|
651 {FPU_NEON_EXT_V1, 0xf2800010, 0xfeb808b0, "vmov%c.i32\t%12-15,22R, %E"}, |
|
652 {FPU_NEON_EXT_V1, 0xf2800030, 0xfeb808b0, "vmvn%c.i32\t%12-15,22R, %E"}, |
|
653 |
|
654 /* Two registers and a shift amount */ |
|
655 {FPU_NEON_EXT_V1, 0xf2880810, 0xffb80fd0, "vshrn%c.i16\t%12-15,22D, %0-3,5Q, #%16-18e"}, |
|
656 {FPU_NEON_EXT_V1, 0xf2880850, 0xffb80fd0, "vrshrn%c.i16\t%12-15,22D, %0-3,5Q, #%16-18e"}, |
|
657 {FPU_NEON_EXT_V1, 0xf2880810, 0xfeb80fd0, "vqshrun%c.s16\t%12-15,22D, %0-3,5Q, #%16-18e"}, |
|
658 {FPU_NEON_EXT_V1, 0xf2880850, 0xfeb80fd0, "vqrshrun%c.s16\t%12-15,22D, %0-3,5Q, #%16-18e"}, |
|
659 {FPU_NEON_EXT_V1, 0xf2880910, 0xfeb80fd0, "vqshrn%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-18e"}, |
|
660 {FPU_NEON_EXT_V1, 0xf2880950, 0xfeb80fd0, "vqrshrn%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-18e"}, |
|
661 {FPU_NEON_EXT_V1, 0xf2880a10, 0xfeb80fd0, "vshll%c.%24?us8\t%12-15,22D, %0-3,5Q, #%16-18d"}, |
|
662 {FPU_NEON_EXT_V1, 0xf2900810, 0xffb00fd0, "vshrn%c.i32\t%12-15,22D, %0-3,5Q, #%16-19e"}, |
|
663 {FPU_NEON_EXT_V1, 0xf2900850, 0xffb00fd0, "vrshrn%c.i32\t%12-15,22D, %0-3,5Q, #%16-19e"}, |
|
664 {FPU_NEON_EXT_V1, 0xf2880510, 0xffb80f90, "vshl%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18d"}, |
|
665 {FPU_NEON_EXT_V1, 0xf3880410, 0xffb80f90, "vsri%c.8\t%12-15,22R, %0-3,5R, #%16-18e"}, |
|
666 {FPU_NEON_EXT_V1, 0xf3880510, 0xffb80f90, "vsli%c.8\t%12-15,22R, %0-3,5R, #%16-18d"}, |
|
667 {FPU_NEON_EXT_V1, 0xf3880610, 0xffb80f90, "vqshlu%c.s8\t%12-15,22R, %0-3,5R, #%16-18d"}, |
|
668 {FPU_NEON_EXT_V1, 0xf2900810, 0xfeb00fd0, "vqshrun%c.s32\t%12-15,22D, %0-3,5Q, #%16-19e"}, |
|
669 {FPU_NEON_EXT_V1, 0xf2900850, 0xfeb00fd0, "vqrshrun%c.s32\t%12-15,22D, %0-3,5Q, #%16-19e"}, |
|
670 {FPU_NEON_EXT_V1, 0xf2900910, 0xfeb00fd0, "vqshrn%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-19e"}, |
|
671 {FPU_NEON_EXT_V1, 0xf2900950, 0xfeb00fd0, "vqrshrn%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-19e"}, |
|
672 {FPU_NEON_EXT_V1, 0xf2900a10, 0xfeb00fd0, "vshll%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-19d"}, |
|
673 {FPU_NEON_EXT_V1, 0xf2880010, 0xfeb80f90, "vshr%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, |
|
674 {FPU_NEON_EXT_V1, 0xf2880110, 0xfeb80f90, "vsra%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, |
|
675 {FPU_NEON_EXT_V1, 0xf2880210, 0xfeb80f90, "vrshr%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, |
|
676 {FPU_NEON_EXT_V1, 0xf2880310, 0xfeb80f90, "vrsra%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, |
|
677 {FPU_NEON_EXT_V1, 0xf2880710, 0xfeb80f90, "vqshl%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18d"}, |
|
678 {FPU_NEON_EXT_V1, 0xf2a00810, 0xffa00fd0, "vshrn%c.i64\t%12-15,22D, %0-3,5Q, #%16-20e"}, |
|
679 {FPU_NEON_EXT_V1, 0xf2a00850, 0xffa00fd0, "vrshrn%c.i64\t%12-15,22D, %0-3,5Q, #%16-20e"}, |
|
680 {FPU_NEON_EXT_V1, 0xf2900510, 0xffb00f90, "vshl%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19d"}, |
|
681 {FPU_NEON_EXT_V1, 0xf3900410, 0xffb00f90, "vsri%c.16\t%12-15,22R, %0-3,5R, #%16-19e"}, |
|
682 {FPU_NEON_EXT_V1, 0xf3900510, 0xffb00f90, "vsli%c.16\t%12-15,22R, %0-3,5R, #%16-19d"}, |
|
683 {FPU_NEON_EXT_V1, 0xf3900610, 0xffb00f90, "vqshlu%c.s16\t%12-15,22R, %0-3,5R, #%16-19d"}, |
|
684 {FPU_NEON_EXT_V1, 0xf2a00a10, 0xfea00fd0, "vshll%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-20d"}, |
|
685 {FPU_NEON_EXT_V1, 0xf2900010, 0xfeb00f90, "vshr%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, |
|
686 {FPU_NEON_EXT_V1, 0xf2900110, 0xfeb00f90, "vsra%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, |
|
687 {FPU_NEON_EXT_V1, 0xf2900210, 0xfeb00f90, "vrshr%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, |
|
688 {FPU_NEON_EXT_V1, 0xf2900310, 0xfeb00f90, "vrsra%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, |
|
689 {FPU_NEON_EXT_V1, 0xf2900710, 0xfeb00f90, "vqshl%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19d"}, |
|
690 {FPU_NEON_EXT_V1, 0xf2800810, 0xfec00fd0, "vqshrun%c.s64\t%12-15,22D, %0-3,5Q, #%16-20e"}, |
|
691 {FPU_NEON_EXT_V1, 0xf2800850, 0xfec00fd0, "vqrshrun%c.s64\t%12-15,22D, %0-3,5Q, #%16-20e"}, |
|
692 {FPU_NEON_EXT_V1, 0xf2800910, 0xfec00fd0, "vqshrn%c.%24?us64\t%12-15,22D, %0-3,5Q, #%16-20e"}, |
|
693 {FPU_NEON_EXT_V1, 0xf2800950, 0xfec00fd0, "vqrshrn%c.%24?us64\t%12-15,22D, %0-3,5Q, #%16-20e"}, |
|
694 {FPU_NEON_EXT_V1, 0xf2a00510, 0xffa00f90, "vshl%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20d"}, |
|
695 {FPU_NEON_EXT_V1, 0xf3a00410, 0xffa00f90, "vsri%c.32\t%12-15,22R, %0-3,5R, #%16-20e"}, |
|
696 {FPU_NEON_EXT_V1, 0xf3a00510, 0xffa00f90, "vsli%c.32\t%12-15,22R, %0-3,5R, #%16-20d"}, |
|
697 {FPU_NEON_EXT_V1, 0xf3a00610, 0xffa00f90, "vqshlu%c.s32\t%12-15,22R, %0-3,5R, #%16-20d"}, |
|
698 {FPU_NEON_EXT_V1, 0xf2a00010, 0xfea00f90, "vshr%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, |
|
699 {FPU_NEON_EXT_V1, 0xf2a00110, 0xfea00f90, "vsra%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, |
|
700 {FPU_NEON_EXT_V1, 0xf2a00210, 0xfea00f90, "vrshr%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, |
|
701 {FPU_NEON_EXT_V1, 0xf2a00310, 0xfea00f90, "vrsra%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, |
|
702 {FPU_NEON_EXT_V1, 0xf2a00710, 0xfea00f90, "vqshl%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20d"}, |
|
703 {FPU_NEON_EXT_V1, 0xf2800590, 0xff800f90, "vshl%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21d"}, |
|
704 {FPU_NEON_EXT_V1, 0xf3800490, 0xff800f90, "vsri%c.64\t%12-15,22R, %0-3,5R, #%16-21e"}, |
|
705 {FPU_NEON_EXT_V1, 0xf3800590, 0xff800f90, "vsli%c.64\t%12-15,22R, %0-3,5R, #%16-21d"}, |
|
706 {FPU_NEON_EXT_V1, 0xf3800690, 0xff800f90, "vqshlu%c.s64\t%12-15,22R, %0-3,5R, #%16-21d"}, |
|
707 {FPU_NEON_EXT_V1, 0xf2800090, 0xfe800f90, "vshr%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, |
|
708 {FPU_NEON_EXT_V1, 0xf2800190, 0xfe800f90, "vsra%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, |
|
709 {FPU_NEON_EXT_V1, 0xf2800290, 0xfe800f90, "vrshr%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, |
|
710 {FPU_NEON_EXT_V1, 0xf2800390, 0xfe800f90, "vrsra%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, |
|
711 {FPU_NEON_EXT_V1, 0xf2800790, 0xfe800f90, "vqshl%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21d"}, |
|
712 {FPU_NEON_EXT_V1, 0xf2a00e10, 0xfea00e90, "vcvt%c.%24,8?usff32.%24,8?ffus32\t%12-15,22R, %0-3,5R, #%16-20e"}, |
|
713 |
|
714 /* Three registers of different lengths */ |
|
715 {FPU_NEON_EXT_V1, 0xf2800e00, 0xfea00f50, "vmull%c.p%20S0\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
716 {FPU_NEON_EXT_V1, 0xf2800400, 0xff800f50, "vaddhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, |
|
717 {FPU_NEON_EXT_V1, 0xf2800600, 0xff800f50, "vsubhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, |
|
718 {FPU_NEON_EXT_V1, 0xf2800900, 0xff800f50, "vqdmlal%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
719 {FPU_NEON_EXT_V1, 0xf2800b00, 0xff800f50, "vqdmlsl%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
720 {FPU_NEON_EXT_V1, 0xf2800d00, 0xff800f50, "vqdmull%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
721 {FPU_NEON_EXT_V1, 0xf3800400, 0xff800f50, "vraddhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, |
|
722 {FPU_NEON_EXT_V1, 0xf3800600, 0xff800f50, "vrsubhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, |
|
723 {FPU_NEON_EXT_V1, 0xf2800000, 0xfe800f50, "vaddl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
724 {FPU_NEON_EXT_V1, 0xf2800100, 0xfe800f50, "vaddw%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7Q, %0-3,5D"}, |
|
725 {FPU_NEON_EXT_V1, 0xf2800200, 0xfe800f50, "vsubl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
726 {FPU_NEON_EXT_V1, 0xf2800300, 0xfe800f50, "vsubw%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7Q, %0-3,5D"}, |
|
727 {FPU_NEON_EXT_V1, 0xf2800500, 0xfe800f50, "vabal%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
728 {FPU_NEON_EXT_V1, 0xf2800700, 0xfe800f50, "vabdl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
729 {FPU_NEON_EXT_V1, 0xf2800800, 0xfe800f50, "vmlal%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
730 {FPU_NEON_EXT_V1, 0xf2800a00, 0xfe800f50, "vmlsl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
731 {FPU_NEON_EXT_V1, 0xf2800c00, 0xfe800f50, "vmull%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, |
|
732 |
|
733 /* Two registers and a scalar */ |
|
734 {FPU_NEON_EXT_V1, 0xf2800040, 0xff800f50, "vmla%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"}, |
|
735 {FPU_NEON_EXT_V1, 0xf2800140, 0xff800f50, "vmla%c.f%20-21Sa\t%12-15,22D, %16-19,7D, %D"}, |
|
736 {FPU_NEON_EXT_V1, 0xf2800340, 0xff800f50, "vqdmlal%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, |
|
737 {FPU_NEON_EXT_V1, 0xf2800440, 0xff800f50, "vmls%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"}, |
|
738 {FPU_NEON_EXT_V1, 0xf2800540, 0xff800f50, "vmls%c.f%20-21S6\t%12-15,22D, %16-19,7D, %D"}, |
|
739 {FPU_NEON_EXT_V1, 0xf2800740, 0xff800f50, "vqdmlsl%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, |
|
740 {FPU_NEON_EXT_V1, 0xf2800840, 0xff800f50, "vmul%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"}, |
|
741 {FPU_NEON_EXT_V1, 0xf2800940, 0xff800f50, "vmul%c.f%20-21Sa\t%12-15,22D, %16-19,7D, %D"}, |
|
742 {FPU_NEON_EXT_V1, 0xf2800b40, 0xff800f50, "vqdmull%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, |
|
743 {FPU_NEON_EXT_V1, 0xf2800c40, 0xff800f50, "vqdmulh%c.s%20-21S6\t%12-15,22D, %16-19,7D, %D"}, |
|
744 {FPU_NEON_EXT_V1, 0xf2800d40, 0xff800f50, "vqrdmulh%c.s%20-21S6\t%12-15,22D, %16-19,7D, %D"}, |
|
745 {FPU_NEON_EXT_V1, 0xf3800040, 0xff800f50, "vmla%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, |
|
746 {FPU_NEON_EXT_V1, 0xf3800140, 0xff800f50, "vmla%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"}, |
|
747 {FPU_NEON_EXT_V1, 0xf3800440, 0xff800f50, "vmls%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, |
|
748 {FPU_NEON_EXT_V1, 0xf3800540, 0xff800f50, "vmls%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"}, |
|
749 {FPU_NEON_EXT_V1, 0xf3800840, 0xff800f50, "vmul%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, |
|
750 {FPU_NEON_EXT_V1, 0xf3800940, 0xff800f50, "vmul%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"}, |
|
751 {FPU_NEON_EXT_V1, 0xf3800c40, 0xff800f50, "vqdmulh%c.s%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, |
|
752 {FPU_NEON_EXT_V1, 0xf3800d40, 0xff800f50, "vqrdmulh%c.s%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, |
|
753 {FPU_NEON_EXT_V1, 0xf2800240, 0xfe800f50, "vmlal%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, |
|
754 {FPU_NEON_EXT_V1, 0xf2800640, 0xfe800f50, "vmlsl%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, |
|
755 {FPU_NEON_EXT_V1, 0xf2800a40, 0xfe800f50, "vmull%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, |
|
756 |
|
757 /* Element and structure load/store */ |
|
758 {FPU_NEON_EXT_V1, 0xf4a00fc0, 0xffb00fc0, "vld4%c.32\t%C"}, |
|
759 {FPU_NEON_EXT_V1, 0xf4a00c00, 0xffb00f00, "vld1%c.%6-7S2\t%C"}, |
|
760 {FPU_NEON_EXT_V1, 0xf4a00d00, 0xffb00f00, "vld2%c.%6-7S2\t%C"}, |
|
761 {FPU_NEON_EXT_V1, 0xf4a00e00, 0xffb00f00, "vld3%c.%6-7S2\t%C"}, |
|
762 {FPU_NEON_EXT_V1, 0xf4a00f00, 0xffb00f00, "vld4%c.%6-7S2\t%C"}, |
|
763 {FPU_NEON_EXT_V1, 0xf4000200, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, |
|
764 {FPU_NEON_EXT_V1, 0xf4000300, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"}, |
|
765 {FPU_NEON_EXT_V1, 0xf4000400, 0xff900f00, "v%21?ls%21?dt3%c.%6-7S2\t%A"}, |
|
766 {FPU_NEON_EXT_V1, 0xf4000500, 0xff900f00, "v%21?ls%21?dt3%c.%6-7S2\t%A"}, |
|
767 {FPU_NEON_EXT_V1, 0xf4000600, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, |
|
768 {FPU_NEON_EXT_V1, 0xf4000700, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, |
|
769 {FPU_NEON_EXT_V1, 0xf4000800, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"}, |
|
770 {FPU_NEON_EXT_V1, 0xf4000900, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"}, |
|
771 {FPU_NEON_EXT_V1, 0xf4000a00, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, |
|
772 {FPU_NEON_EXT_V1, 0xf4000000, 0xff900e00, "v%21?ls%21?dt4%c.%6-7S2\t%A"}, |
|
773 {FPU_NEON_EXT_V1, 0xf4800000, 0xff900300, "v%21?ls%21?dt1%c.%10-11S2\t%B"}, |
|
774 {FPU_NEON_EXT_V1, 0xf4800100, 0xff900300, "v%21?ls%21?dt2%c.%10-11S2\t%B"}, |
|
775 {FPU_NEON_EXT_V1, 0xf4800200, 0xff900300, "v%21?ls%21?dt3%c.%10-11S2\t%B"}, |
|
776 {FPU_NEON_EXT_V1, 0xf4800300, 0xff900300, "v%21?ls%21?dt4%c.%10-11S2\t%B"}, |
|
777 |
|
778 {0,0 ,0, 0} |
|
779 }; |
|
780 |
|
781 /* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially |
|
782 ordered: they must be searched linearly from the top to obtain a correct |
|
783 match. */ |
|
784 |
|
785 /* print_insn_arm recognizes the following format control codes: |
|
786 |
|
787 %% % |
|
788 |
|
789 %a print address for ldr/str instruction |
|
790 %s print address for ldr/str halfword/signextend instruction |
|
791 %b print branch destination |
|
792 %c print condition code (always bits 28-31) |
|
793 %m print register mask for ldm/stm instruction |
|
794 %o print operand2 (immediate or register + shift) |
|
795 %p print 'p' iff bits 12-15 are 15 |
|
796 %t print 't' iff bit 21 set and bit 24 clear |
|
797 %B print arm BLX(1) destination |
|
798 %C print the PSR sub type. |
|
799 %U print barrier type. |
|
800 %P print address for pli instruction. |
|
801 |
|
802 %<bitfield>r print as an ARM register |
|
803 %<bitfield>d print the bitfield in decimal |
|
804 %<bitfield>W print the bitfield plus one in decimal |
|
805 %<bitfield>x print the bitfield in hex |
|
806 %<bitfield>X print the bitfield as 1 hex digit without leading "0x" |
|
807 |
|
808 %<bitfield>'c print specified char iff bitfield is all ones |
|
809 %<bitfield>`c print specified char iff bitfield is all zeroes |
|
810 %<bitfield>?ab... select from array of values in big endian order |
|
811 |
|
812 %e print arm SMI operand (bits 0..7,8..19). |
|
813 %E print the LSB and WIDTH fields of a BFI or BFC instruction. |
|
814 %V print the 16-bit immediate field of a MOVT or MOVW instruction. */ |
|
815 |
|
816 static const struct opcode32 arm_opcodes[] = |
|
817 { |
|
818 /* ARM instructions. */ |
|
819 {ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"}, |
|
820 {ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"}, |
|
821 {ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%20's%c\t%16-19r, %0-3r, %8-11r"}, |
|
822 {ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%20's%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
823 {ARM_EXT_V2S, 0x01000090, 0x0fb00ff0, "swp%22'b%c\t%12-15r, %0-3r, [%16-19r]"}, |
|
824 {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
825 {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
826 |
|
827 /* V7 instructions. */ |
|
828 {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"}, |
|
829 {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"}, |
|
830 {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"}, |
|
831 {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"}, |
|
832 {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"}, |
|
833 |
|
834 /* ARM V6T2 instructions. */ |
|
835 {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"}, |
|
836 {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"}, |
|
837 {ARM_EXT_V6T2, 0x00600090, 0x0ff000f0, "mls%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
838 {ARM_EXT_V6T2, 0x006000b0, 0x0f7000f0, "strht%c\t%12-15r, %s"}, |
|
839 {ARM_EXT_V6T2, 0x00300090, 0x0f300090, "ldr%6's%5?hbt%c\t%12-15r, %s"}, |
|
840 {ARM_EXT_V6T2, 0x03000000, 0x0ff00000, "movw%c\t%12-15r, %V"}, |
|
841 {ARM_EXT_V6T2, 0x03400000, 0x0ff00000, "movt%c\t%12-15r, %V"}, |
|
842 {ARM_EXT_V6T2, 0x06ff0f30, 0x0fff0ff0, "rbit%c\t%12-15r, %0-3r"}, |
|
843 {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"}, |
|
844 |
|
845 /* ARM V6Z instructions. */ |
|
846 {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"}, |
|
847 |
|
848 /* ARM V6K instructions. */ |
|
849 {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"}, |
|
850 {ARM_EXT_V6K, 0x01d00f9f, 0x0ff00fff, "ldrexb%c\t%12-15r, [%16-19r]"}, |
|
851 {ARM_EXT_V6K, 0x01b00f9f, 0x0ff00fff, "ldrexd%c\t%12-15r, [%16-19r]"}, |
|
852 {ARM_EXT_V6K, 0x01f00f9f, 0x0ff00fff, "ldrexh%c\t%12-15r, [%16-19r]"}, |
|
853 {ARM_EXT_V6K, 0x01c00f90, 0x0ff00ff0, "strexb%c\t%12-15r, %0-3r, [%16-19r]"}, |
|
854 {ARM_EXT_V6K, 0x01a00f90, 0x0ff00ff0, "strexd%c\t%12-15r, %0-3r, [%16-19r]"}, |
|
855 {ARM_EXT_V6K, 0x01e00f90, 0x0ff00ff0, "strexh%c\t%12-15r, %0-3r, [%16-19r]"}, |
|
856 |
|
857 /* ARM V6K NOP hints. */ |
|
858 {ARM_EXT_V6K, 0x0320f001, 0x0fffffff, "yield%c"}, |
|
859 {ARM_EXT_V6K, 0x0320f002, 0x0fffffff, "wfe%c"}, |
|
860 {ARM_EXT_V6K, 0x0320f003, 0x0fffffff, "wfi%c"}, |
|
861 {ARM_EXT_V6K, 0x0320f004, 0x0fffffff, "sev%c"}, |
|
862 {ARM_EXT_V6K, 0x0320f000, 0x0fffff00, "nop%c\t{%0-7d}"}, |
|
863 |
|
864 /* ARM V6 instructions. */ |
|
865 {ARM_EXT_V6, 0xf1080000, 0xfffffe3f, "cpsie\t%8'a%7'i%6'f"}, |
|
866 {ARM_EXT_V6, 0xf10a0000, 0xfffffe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"}, |
|
867 {ARM_EXT_V6, 0xf10C0000, 0xfffffe3f, "cpsid\t%8'a%7'i%6'f"}, |
|
868 {ARM_EXT_V6, 0xf10e0000, 0xfffffe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"}, |
|
869 {ARM_EXT_V6, 0xf1000000, 0xfff1fe20, "cps\t#%0-4d"}, |
|
870 {ARM_EXT_V6, 0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"}, |
|
871 {ARM_EXT_V6, 0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, lsl #%7-11d"}, |
|
872 {ARM_EXT_V6, 0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, asr #32"}, |
|
873 {ARM_EXT_V6, 0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, asr #%7-11d"}, |
|
874 {ARM_EXT_V6, 0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"}, |
|
875 {ARM_EXT_V6, 0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"}, |
|
876 {ARM_EXT_V6, 0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"}, |
|
877 {ARM_EXT_V6, 0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"}, |
|
878 {ARM_EXT_V6, 0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"}, |
|
879 {ARM_EXT_V6, 0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"}, |
|
880 {ARM_EXT_V6, 0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
881 {ARM_EXT_V6, 0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"}, |
|
882 {ARM_EXT_V6, 0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"}, |
|
883 {ARM_EXT_V6, 0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
884 {ARM_EXT_V6, 0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"}, |
|
885 {ARM_EXT_V6, 0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"}, |
|
886 {ARM_EXT_V6, 0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"}, |
|
887 {ARM_EXT_V6, 0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"}, |
|
888 {ARM_EXT_V6, 0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"}, |
|
889 {ARM_EXT_V6, 0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
890 {ARM_EXT_V6, 0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"}, |
|
891 {ARM_EXT_V6, 0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"}, |
|
892 {ARM_EXT_V6, 0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
893 {ARM_EXT_V6, 0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"}, |
|
894 {ARM_EXT_V6, 0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"}, |
|
895 {ARM_EXT_V6, 0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"}, |
|
896 {ARM_EXT_V6, 0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"}, |
|
897 {ARM_EXT_V6, 0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"}, |
|
898 {ARM_EXT_V6, 0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"}, |
|
899 {ARM_EXT_V6, 0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"}, |
|
900 {ARM_EXT_V6, 0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"}, |
|
901 {ARM_EXT_V6, 0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
902 {ARM_EXT_V6, 0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"}, |
|
903 {ARM_EXT_V6, 0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"}, |
|
904 {ARM_EXT_V6, 0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"}, |
|
905 {ARM_EXT_V6, 0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"}, |
|
906 {ARM_EXT_V6, 0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"}, |
|
907 {ARM_EXT_V6, 0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
908 {ARM_EXT_V6, 0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"}, |
|
909 {ARM_EXT_V6, 0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"}, |
|
910 {ARM_EXT_V6, 0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"}, |
|
911 {ARM_EXT_V6, 0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"}, |
|
912 {ARM_EXT_V6, 0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"}, |
|
913 {ARM_EXT_V6, 0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"}, |
|
914 {ARM_EXT_V6, 0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"}, |
|
915 {ARM_EXT_V6, 0x06bf0070, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r"}, |
|
916 {ARM_EXT_V6, 0x06bf0470, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #8"}, |
|
917 {ARM_EXT_V6, 0x06bf0870, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #16"}, |
|
918 {ARM_EXT_V6, 0x06bf0c70, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #24"}, |
|
919 {ARM_EXT_V6, 0x068f0070, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r"}, |
|
920 {ARM_EXT_V6, 0x068f0470, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #8"}, |
|
921 {ARM_EXT_V6, 0x068f0870, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #16"}, |
|
922 {ARM_EXT_V6, 0x068f0c70, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #24"}, |
|
923 {ARM_EXT_V6, 0x06af0070, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r"}, |
|
924 {ARM_EXT_V6, 0x06af0470, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #8"}, |
|
925 {ARM_EXT_V6, 0x06af0870, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #16"}, |
|
926 {ARM_EXT_V6, 0x06af0c70, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #24"}, |
|
927 {ARM_EXT_V6, 0x06ff0070, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r"}, |
|
928 {ARM_EXT_V6, 0x06ff0470, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #8"}, |
|
929 {ARM_EXT_V6, 0x06ff0870, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #16"}, |
|
930 {ARM_EXT_V6, 0x06ff0c70, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #24"}, |
|
931 {ARM_EXT_V6, 0x06cf0070, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r"}, |
|
932 {ARM_EXT_V6, 0x06cf0470, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #8"}, |
|
933 {ARM_EXT_V6, 0x06cf0870, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #16"}, |
|
934 {ARM_EXT_V6, 0x06cf0c70, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #24"}, |
|
935 {ARM_EXT_V6, 0x06ef0070, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r"}, |
|
936 {ARM_EXT_V6, 0x06ef0470, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #8"}, |
|
937 {ARM_EXT_V6, 0x06ef0870, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #16"}, |
|
938 {ARM_EXT_V6, 0x06ef0c70, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #24"}, |
|
939 {ARM_EXT_V6, 0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"}, |
|
940 {ARM_EXT_V6, 0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #8"}, |
|
941 {ARM_EXT_V6, 0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #16"}, |
|
942 {ARM_EXT_V6, 0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #24"}, |
|
943 {ARM_EXT_V6, 0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"}, |
|
944 {ARM_EXT_V6, 0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #8"}, |
|
945 {ARM_EXT_V6, 0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #16"}, |
|
946 {ARM_EXT_V6, 0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #24"}, |
|
947 {ARM_EXT_V6, 0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"}, |
|
948 {ARM_EXT_V6, 0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #8"}, |
|
949 {ARM_EXT_V6, 0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #16"}, |
|
950 {ARM_EXT_V6, 0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #24"}, |
|
951 {ARM_EXT_V6, 0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"}, |
|
952 {ARM_EXT_V6, 0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #8"}, |
|
953 {ARM_EXT_V6, 0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #16"}, |
|
954 {ARM_EXT_V6, 0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #24"}, |
|
955 {ARM_EXT_V6, 0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"}, |
|
956 {ARM_EXT_V6, 0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ror #8"}, |
|
957 {ARM_EXT_V6, 0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ror #16"}, |
|
958 {ARM_EXT_V6, 0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, |
|
959 {ARM_EXT_V6, 0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"}, |
|
960 {ARM_EXT_V6, 0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #8"}, |
|
961 {ARM_EXT_V6, 0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #16"}, |
|
962 {ARM_EXT_V6, 0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #24"}, |
|
963 {ARM_EXT_V6, 0x06800fb0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"}, |
|
964 {ARM_EXT_V6, 0xf1010000, 0xfffffc00, "setend\t%9?ble"}, |
|
965 {ARM_EXT_V6, 0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"}, |
|
966 {ARM_EXT_V6, 0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"}, |
|
967 {ARM_EXT_V6, 0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
968 {ARM_EXT_V6, 0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
969 {ARM_EXT_V6, 0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
970 {ARM_EXT_V6, 0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
971 {ARM_EXT_V6, 0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"}, |
|
972 {ARM_EXT_V6, 0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
973 {ARM_EXT_V6, 0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
974 {ARM_EXT_V6, 0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t%16-19r%21'!, #%0-4d"}, |
|
975 {ARM_EXT_V6, 0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"}, |
|
976 {ARM_EXT_V6, 0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, lsl #%7-11d"}, |
|
977 {ARM_EXT_V6, 0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, asr #%7-11d"}, |
|
978 {ARM_EXT_V6, 0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"}, |
|
979 {ARM_EXT_V6, 0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"}, |
|
980 {ARM_EXT_V6, 0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
981 {ARM_EXT_V6, 0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"}, |
|
982 {ARM_EXT_V6, 0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
983 {ARM_EXT_V6, 0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"}, |
|
984 {ARM_EXT_V6, 0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, lsl #%7-11d"}, |
|
985 {ARM_EXT_V6, 0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, asr #%7-11d"}, |
|
986 {ARM_EXT_V6, 0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"}, |
|
987 |
|
988 /* V5J instruction. */ |
|
989 {ARM_EXT_V5J, 0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"}, |
|
990 |
|
991 /* V5 Instructions. */ |
|
992 {ARM_EXT_V5, 0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"}, |
|
993 {ARM_EXT_V5, 0xfa000000, 0xfe000000, "blx\t%B"}, |
|
994 {ARM_EXT_V5, 0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"}, |
|
995 {ARM_EXT_V5, 0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"}, |
|
996 |
|
997 /* V5E "El Segundo" Instructions. */ |
|
998 {ARM_EXT_V5E, 0x000000d0, 0x0e1000f0, "ldrd%c\t%12-15r, %s"}, |
|
999 {ARM_EXT_V5E, 0x000000f0, 0x0e1000f0, "strd%c\t%12-15r, %s"}, |
|
1000 {ARM_EXT_V5E, 0xf450f000, 0xfc70f000, "pld\t%a"}, |
|
1001 {ARM_EXT_V5ExP, 0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
1002 {ARM_EXT_V5ExP, 0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
1003 {ARM_EXT_V5ExP, 0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
1004 {ARM_EXT_V5ExP, 0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
1005 |
|
1006 {ARM_EXT_V5ExP, 0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
1007 {ARM_EXT_V5ExP, 0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, |
|
1008 |
|
1009 {ARM_EXT_V5ExP, 0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
1010 {ARM_EXT_V5ExP, 0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
1011 {ARM_EXT_V5ExP, 0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
1012 {ARM_EXT_V5ExP, 0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, |
|
1013 |
|
1014 {ARM_EXT_V5ExP, 0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"}, |
|
1015 {ARM_EXT_V5ExP, 0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"}, |
|
1016 {ARM_EXT_V5ExP, 0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"}, |
|
1017 {ARM_EXT_V5ExP, 0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"}, |
|
1018 |
|
1019 {ARM_EXT_V5ExP, 0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"}, |
|
1020 {ARM_EXT_V5ExP, 0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"}, |
|
1021 |
|
1022 {ARM_EXT_V5ExP, 0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"}, |
|
1023 {ARM_EXT_V5ExP, 0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"}, |
|
1024 {ARM_EXT_V5ExP, 0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"}, |
|
1025 {ARM_EXT_V5ExP, 0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"}, |
|
1026 |
|
1027 /* ARM Instructions. */ |
|
1028 {ARM_EXT_V1, 0x00000090, 0x0e100090, "str%6's%5?hb%c\t%12-15r, %s"}, |
|
1029 {ARM_EXT_V1, 0x00100090, 0x0e100090, "ldr%6's%5?hb%c\t%12-15r, %s"}, |
|
1030 {ARM_EXT_V1, 0x00000000, 0x0de00000, "and%20's%c\t%12-15r, %16-19r, %o"}, |
|
1031 {ARM_EXT_V1, 0x00200000, 0x0de00000, "eor%20's%c\t%12-15r, %16-19r, %o"}, |
|
1032 {ARM_EXT_V1, 0x00400000, 0x0de00000, "sub%20's%c\t%12-15r, %16-19r, %o"}, |
|
1033 {ARM_EXT_V1, 0x00600000, 0x0de00000, "rsb%20's%c\t%12-15r, %16-19r, %o"}, |
|
1034 {ARM_EXT_V1, 0x00800000, 0x0de00000, "add%20's%c\t%12-15r, %16-19r, %o"}, |
|
1035 {ARM_EXT_V1, 0x00a00000, 0x0de00000, "adc%20's%c\t%12-15r, %16-19r, %o"}, |
|
1036 {ARM_EXT_V1, 0x00c00000, 0x0de00000, "sbc%20's%c\t%12-15r, %16-19r, %o"}, |
|
1037 {ARM_EXT_V1, 0x00e00000, 0x0de00000, "rsc%20's%c\t%12-15r, %16-19r, %o"}, |
|
1038 {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"}, |
|
1039 {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"}, |
|
1040 {ARM_EXT_V1, 0x01000000, 0x0de00000, "tst%p%c\t%16-19r, %o"}, |
|
1041 {ARM_EXT_V1, 0x01200000, 0x0de00000, "teq%p%c\t%16-19r, %o"}, |
|
1042 {ARM_EXT_V1, 0x01400000, 0x0de00000, "cmp%p%c\t%16-19r, %o"}, |
|
1043 {ARM_EXT_V1, 0x01600000, 0x0de00000, "cmn%p%c\t%16-19r, %o"}, |
|
1044 {ARM_EXT_V1, 0x01800000, 0x0de00000, "orr%20's%c\t%12-15r, %16-19r, %o"}, |
|
1045 {ARM_EXT_V1, 0x03a00000, 0x0fef0000, "mov%20's%c\t%12-15r, %o"}, |
|
1046 {ARM_EXT_V1, 0x01a00000, 0x0def0ff0, "mov%20's%c\t%12-15r, %0-3r"}, |
|
1047 {ARM_EXT_V1, 0x01a00000, 0x0def0060, "lsl%20's%c\t%12-15r, %q"}, |
|
1048 {ARM_EXT_V1, 0x01a00020, 0x0def0060, "lsr%20's%c\t%12-15r, %q"}, |
|
1049 {ARM_EXT_V1, 0x01a00040, 0x0def0060, "asr%20's%c\t%12-15r, %q"}, |
|
1050 {ARM_EXT_V1, 0x01a00060, 0x0def0ff0, "rrx%20's%c\t%12-15r, %0-3r"}, |
|
1051 {ARM_EXT_V1, 0x01a00060, 0x0def0060, "ror%20's%c\t%12-15r, %q"}, |
|
1052 {ARM_EXT_V1, 0x01c00000, 0x0de00000, "bic%20's%c\t%12-15r, %16-19r, %o"}, |
|
1053 {ARM_EXT_V1, 0x01e00000, 0x0de00000, "mvn%20's%c\t%12-15r, %o"}, |
|
1054 {ARM_EXT_V1, 0x052d0004, 0x0fff0fff, "push%c\t{%12-15r}\t\t; (str%c %12-15r, %a)"}, |
|
1055 {ARM_EXT_V1, 0x04000000, 0x0e100000, "str%22'b%t%c\t%12-15r, %a"}, |
|
1056 {ARM_EXT_V1, 0x06000000, 0x0e100ff0, "str%22'b%t%c\t%12-15r, %a"}, |
|
1057 {ARM_EXT_V1, 0x04000000, 0x0c100010, "str%22'b%t%c\t%12-15r, %a"}, |
|
1058 {ARM_EXT_V1, 0x06000010, 0x0e000010, "undefined"}, |
|
1059 {ARM_EXT_V1, 0x049d0004, 0x0fff0fff, "pop%c\t{%12-15r}\t\t; (ldr%c %12-15r, %a)"}, |
|
1060 {ARM_EXT_V1, 0x04100000, 0x0c100000, "ldr%22'b%t%c\t%12-15r, %a"}, |
|
1061 {ARM_EXT_V1, 0x092d0000, 0x0fff0000, "push%c\t%m"}, |
|
1062 {ARM_EXT_V1, 0x08800000, 0x0ff00000, "stm%c\t%16-19r%21'!, %m%22'^"}, |
|
1063 {ARM_EXT_V1, 0x08000000, 0x0e100000, "stm%23?id%24?ba%c\t%16-19r%21'!, %m%22'^"}, |
|
1064 {ARM_EXT_V1, 0x08bd0000, 0x0fff0000, "pop%c\t%m"}, |
|
1065 {ARM_EXT_V1, 0x08900000, 0x0f900000, "ldm%c\t%16-19r%21'!, %m%22'^"}, |
|
1066 {ARM_EXT_V1, 0x08100000, 0x0e100000, "ldm%23?id%24?ba%c\t%16-19r%21'!, %m%22'^"}, |
|
1067 {ARM_EXT_V1, 0x0a000000, 0x0e000000, "b%24'l%c\t%b"}, |
|
1068 {ARM_EXT_V1, 0x0f000000, 0x0f000000, "svc%c\t%0-23x"}, |
|
1069 |
|
1070 /* The rest. */ |
|
1071 {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined instruction %0-31x"}, |
|
1072 {0, 0x00000000, 0x00000000, 0} |
|
1073 }; |
|
1074 |
|
1075 /* print_insn_thumb16 recognizes the following format control codes: |
|
1076 |
|
1077 %S print Thumb register (bits 3..5 as high number if bit 6 set) |
|
1078 %D print Thumb register (bits 0..2 as high number if bit 7 set) |
|
1079 %<bitfield>I print bitfield as a signed decimal |
|
1080 (top bit of range being the sign bit) |
|
1081 %N print Thumb register mask (with LR) |
|
1082 %O print Thumb register mask (with PC) |
|
1083 %M print Thumb register mask |
|
1084 %b print CZB's 6-bit unsigned branch destination |
|
1085 %s print Thumb right-shift immediate (6..10; 0 == 32). |
|
1086 %c print the condition code |
|
1087 %C print the condition code, or "s" if not conditional |
|
1088 %x print warning if conditional an not at end of IT block" |
|
1089 %X print "\t; unpredictable <IT:code>" if conditional |
|
1090 %I print IT instruction suffix and operands |
|
1091 %<bitfield>r print bitfield as an ARM register |
|
1092 %<bitfield>d print bitfield as a decimal |
|
1093 %<bitfield>H print (bitfield * 2) as a decimal |
|
1094 %<bitfield>W print (bitfield * 4) as a decimal |
|
1095 %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol |
|
1096 %<bitfield>B print Thumb branch destination (signed displacement) |
|
1097 %<bitfield>c print bitfield as a condition code |
|
1098 %<bitnum>'c print specified char iff bit is one |
|
1099 %<bitnum>?ab print a if bit is one else print b. */ |
|
1100 |
|
1101 static const struct opcode16 thumb_opcodes[] = |
|
1102 { |
|
1103 /* Thumb instructions. */ |
|
1104 |
|
1105 /* ARM V6K no-argument instructions. */ |
|
1106 {ARM_EXT_V6K, 0xbf00, 0xffff, "nop%c"}, |
|
1107 {ARM_EXT_V6K, 0xbf10, 0xffff, "yield%c"}, |
|
1108 {ARM_EXT_V6K, 0xbf20, 0xffff, "wfe%c"}, |
|
1109 {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi%c"}, |
|
1110 {ARM_EXT_V6K, 0xbf40, 0xffff, "sev%c"}, |
|
1111 {ARM_EXT_V6K, 0xbf00, 0xff0f, "nop%c\t{%4-7d}"}, |
|
1112 |
|
1113 /* ARM V6T2 instructions. */ |
|
1114 {ARM_EXT_V6T2, 0xb900, 0xfd00, "cbnz\t%0-2r, %b%X"}, |
|
1115 {ARM_EXT_V6T2, 0xb100, 0xfd00, "cbz\t%0-2r, %b%X"}, |
|
1116 {ARM_EXT_V6T2, 0xbf00, 0xff00, "it%I%X"}, |
|
1117 |
|
1118 /* ARM V6. */ |
|
1119 {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f%X"}, |
|
1120 {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f%X"}, |
|
1121 {ARM_EXT_V6, 0x4600, 0xffc0, "mov%c\t%0-2r, %3-5r"}, |
|
1122 {ARM_EXT_V6, 0xba00, 0xffc0, "rev%c\t%0-2r, %3-5r"}, |
|
1123 {ARM_EXT_V6, 0xba40, 0xffc0, "rev16%c\t%0-2r, %3-5r"}, |
|
1124 {ARM_EXT_V6, 0xbac0, 0xffc0, "revsh%c\t%0-2r, %3-5r"}, |
|
1125 {ARM_EXT_V6, 0xb650, 0xfff7, "setend\t%3?ble%X"}, |
|
1126 {ARM_EXT_V6, 0xb200, 0xffc0, "sxth%c\t%0-2r, %3-5r"}, |
|
1127 {ARM_EXT_V6, 0xb240, 0xffc0, "sxtb%c\t%0-2r, %3-5r"}, |
|
1128 {ARM_EXT_V6, 0xb280, 0xffc0, "uxth%c\t%0-2r, %3-5r"}, |
|
1129 {ARM_EXT_V6, 0xb2c0, 0xffc0, "uxtb%c\t%0-2r, %3-5r"}, |
|
1130 |
|
1131 /* ARM V5 ISA extends Thumb. */ |
|
1132 {ARM_EXT_V5T, 0xbe00, 0xff00, "bkpt\t%0-7x"}, /* Is always unconditional. */ |
|
1133 /* This is BLX(2). BLX(1) is a 32-bit instruction. */ |
|
1134 {ARM_EXT_V5T, 0x4780, 0xff87, "blx%c\t%3-6r%x"}, /* note: 4 bit register number. */ |
|
1135 /* ARM V4T ISA (Thumb v1). */ |
|
1136 {ARM_EXT_V4T, 0x46C0, 0xFFFF, "nop%c\t\t\t(mov r8, r8)"}, |
|
1137 /* Format 4. */ |
|
1138 {ARM_EXT_V4T, 0x4000, 0xFFC0, "and%C\t%0-2r, %3-5r"}, |
|
1139 {ARM_EXT_V4T, 0x4040, 0xFFC0, "eor%C\t%0-2r, %3-5r"}, |
|
1140 {ARM_EXT_V4T, 0x4080, 0xFFC0, "lsl%C\t%0-2r, %3-5r"}, |
|
1141 {ARM_EXT_V4T, 0x40C0, 0xFFC0, "lsr%C\t%0-2r, %3-5r"}, |
|
1142 {ARM_EXT_V4T, 0x4100, 0xFFC0, "asr%C\t%0-2r, %3-5r"}, |
|
1143 {ARM_EXT_V4T, 0x4140, 0xFFC0, "adc%C\t%0-2r, %3-5r"}, |
|
1144 {ARM_EXT_V4T, 0x4180, 0xFFC0, "sbc%C\t%0-2r, %3-5r"}, |
|
1145 {ARM_EXT_V4T, 0x41C0, 0xFFC0, "ror%C\t%0-2r, %3-5r"}, |
|
1146 {ARM_EXT_V4T, 0x4200, 0xFFC0, "tst%c\t%0-2r, %3-5r"}, |
|
1147 {ARM_EXT_V4T, 0x4240, 0xFFC0, "neg%C\t%0-2r, %3-5r"}, |
|
1148 {ARM_EXT_V4T, 0x4280, 0xFFC0, "cmp%c\t%0-2r, %3-5r"}, |
|
1149 {ARM_EXT_V4T, 0x42C0, 0xFFC0, "cmn%c\t%0-2r, %3-5r"}, |
|
1150 {ARM_EXT_V4T, 0x4300, 0xFFC0, "orr%C\t%0-2r, %3-5r"}, |
|
1151 {ARM_EXT_V4T, 0x4340, 0xFFC0, "mul%C\t%0-2r, %3-5r"}, |
|
1152 {ARM_EXT_V4T, 0x4380, 0xFFC0, "bic%C\t%0-2r, %3-5r"}, |
|
1153 {ARM_EXT_V4T, 0x43C0, 0xFFC0, "mvn%C\t%0-2r, %3-5r"}, |
|
1154 /* format 13 */ |
|
1155 {ARM_EXT_V4T, 0xB000, 0xFF80, "add%c\tsp, #%0-6W"}, |
|
1156 {ARM_EXT_V4T, 0xB080, 0xFF80, "sub%c\tsp, #%0-6W"}, |
|
1157 /* format 5 */ |
|
1158 {ARM_EXT_V4T, 0x4700, 0xFF80, "bx%c\t%S%x"}, |
|
1159 {ARM_EXT_V4T, 0x4400, 0xFF00, "add%c\t%D, %S"}, |
|
1160 {ARM_EXT_V4T, 0x4500, 0xFF00, "cmp%c\t%D, %S"}, |
|
1161 {ARM_EXT_V4T, 0x4600, 0xFF00, "mov%c\t%D, %S"}, |
|
1162 /* format 14 */ |
|
1163 {ARM_EXT_V4T, 0xB400, 0xFE00, "push%c\t%N"}, |
|
1164 {ARM_EXT_V4T, 0xBC00, 0xFE00, "pop%c\t%O"}, |
|
1165 /* format 2 */ |
|
1166 {ARM_EXT_V4T, 0x1800, 0xFE00, "add%C\t%0-2r, %3-5r, %6-8r"}, |
|
1167 {ARM_EXT_V4T, 0x1A00, 0xFE00, "sub%C\t%0-2r, %3-5r, %6-8r"}, |
|
1168 {ARM_EXT_V4T, 0x1C00, 0xFE00, "add%C\t%0-2r, %3-5r, #%6-8d"}, |
|
1169 {ARM_EXT_V4T, 0x1E00, 0xFE00, "sub%C\t%0-2r, %3-5r, #%6-8d"}, |
|
1170 /* format 8 */ |
|
1171 {ARM_EXT_V4T, 0x5200, 0xFE00, "strh%c\t%0-2r, [%3-5r, %6-8r]"}, |
|
1172 {ARM_EXT_V4T, 0x5A00, 0xFE00, "ldrh%c\t%0-2r, [%3-5r, %6-8r]"}, |
|
1173 {ARM_EXT_V4T, 0x5600, 0xF600, "ldrs%11?hb%c\t%0-2r, [%3-5r, %6-8r]"}, |
|
1174 /* format 7 */ |
|
1175 {ARM_EXT_V4T, 0x5000, 0xFA00, "str%10'b%c\t%0-2r, [%3-5r, %6-8r]"}, |
|
1176 {ARM_EXT_V4T, 0x5800, 0xFA00, "ldr%10'b%c\t%0-2r, [%3-5r, %6-8r]"}, |
|
1177 /* format 1 */ |
|
1178 {ARM_EXT_V4T, 0x0000, 0xF800, "lsl%C\t%0-2r, %3-5r, #%6-10d"}, |
|
1179 {ARM_EXT_V4T, 0x0800, 0xF800, "lsr%C\t%0-2r, %3-5r, %s"}, |
|
1180 {ARM_EXT_V4T, 0x1000, 0xF800, "asr%C\t%0-2r, %3-5r, %s"}, |
|
1181 /* format 3 */ |
|
1182 {ARM_EXT_V4T, 0x2000, 0xF800, "mov%C\t%8-10r, #%0-7d"}, |
|
1183 {ARM_EXT_V4T, 0x2800, 0xF800, "cmp%c\t%8-10r, #%0-7d"}, |
|
1184 {ARM_EXT_V4T, 0x3000, 0xF800, "add%C\t%8-10r, #%0-7d"}, |
|
1185 {ARM_EXT_V4T, 0x3800, 0xF800, "sub%C\t%8-10r, #%0-7d"}, |
|
1186 /* format 6 */ |
|
1187 {ARM_EXT_V4T, 0x4800, 0xF800, "ldr%c\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */ |
|
1188 /* format 9 */ |
|
1189 {ARM_EXT_V4T, 0x6000, 0xF800, "str%c\t%0-2r, [%3-5r, #%6-10W]"}, |
|
1190 {ARM_EXT_V4T, 0x6800, 0xF800, "ldr%c\t%0-2r, [%3-5r, #%6-10W]"}, |
|
1191 {ARM_EXT_V4T, 0x7000, 0xF800, "strb%c\t%0-2r, [%3-5r, #%6-10d]"}, |
|
1192 {ARM_EXT_V4T, 0x7800, 0xF800, "ldrb%c\t%0-2r, [%3-5r, #%6-10d]"}, |
|
1193 /* format 10 */ |
|
1194 {ARM_EXT_V4T, 0x8000, 0xF800, "strh%c\t%0-2r, [%3-5r, #%6-10H]"}, |
|
1195 {ARM_EXT_V4T, 0x8800, 0xF800, "ldrh%c\t%0-2r, [%3-5r, #%6-10H]"}, |
|
1196 /* format 11 */ |
|
1197 {ARM_EXT_V4T, 0x9000, 0xF800, "str%c\t%8-10r, [sp, #%0-7W]"}, |
|
1198 {ARM_EXT_V4T, 0x9800, 0xF800, "ldr%c\t%8-10r, [sp, #%0-7W]"}, |
|
1199 /* format 12 */ |
|
1200 {ARM_EXT_V4T, 0xA000, 0xF800, "add%c\t%8-10r, pc, #%0-7W\t(adr %8-10r, %0-7a)"}, |
|
1201 {ARM_EXT_V4T, 0xA800, 0xF800, "add%c\t%8-10r, sp, #%0-7W"}, |
|
1202 /* format 15 */ |
|
1203 {ARM_EXT_V4T, 0xC000, 0xF800, "stmia%c\t%8-10r!, %M"}, |
|
1204 {ARM_EXT_V4T, 0xC800, 0xF800, "ldmia%c\t%8-10r!, %M"}, |
|
1205 /* format 17 */ |
|
1206 {ARM_EXT_V4T, 0xDF00, 0xFF00, "svc%c\t%0-7d"}, |
|
1207 /* format 16 */ |
|
1208 {ARM_EXT_V4T, 0xDE00, 0xFE00, "undefined"}, |
|
1209 {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B%X"}, |
|
1210 /* format 18 */ |
|
1211 {ARM_EXT_V4T, 0xE000, 0xF800, "b%c.n\t%0-10B%x"}, |
|
1212 |
|
1213 /* The E800 .. FFFF range is unconditionally redirected to the |
|
1214 32-bit table, because even in pre-V6T2 ISAs, BL and BLX(1) pairs |
|
1215 are processed via that table. Thus, we can never encounter a |
|
1216 bare "second half of BL/BLX(1)" instruction here. */ |
|
1217 {ARM_EXT_V1, 0x0000, 0x0000, "undefined"}, |
|
1218 {0, 0, 0, 0} |
|
1219 }; |
|
1220 |
|
1221 /* Thumb32 opcodes use the same table structure as the ARM opcodes. |
|
1222 We adopt the convention that hw1 is the high 16 bits of .value and |
|
1223 .mask, hw2 the low 16 bits. |
|
1224 |
|
1225 print_insn_thumb32 recognizes the following format control codes: |
|
1226 |
|
1227 %% % |
|
1228 |
|
1229 %I print a 12-bit immediate from hw1[10],hw2[14:12,7:0] |
|
1230 %M print a modified 12-bit immediate (same location) |
|
1231 %J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0] |
|
1232 %K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4] |
|
1233 %S print a possibly-shifted Rm |
|
1234 |
|
1235 %a print the address of a plain load/store |
|
1236 %w print the width and signedness of a core load/store |
|
1237 %m print register mask for ldm/stm |
|
1238 |
|
1239 %E print the lsb and width fields of a bfc/bfi instruction |
|
1240 %F print the lsb and width fields of a sbfx/ubfx instruction |
|
1241 %b print a conditional branch offset |
|
1242 %B print an unconditional branch offset |
|
1243 %s print the shift field of an SSAT instruction |
|
1244 %R print the rotation field of an SXT instruction |
|
1245 %U print barrier type. |
|
1246 %P print address for pli instruction. |
|
1247 %c print the condition code |
|
1248 %x print warning if conditional an not at end of IT block" |
|
1249 %X print "\t; unpredictable <IT:code>" if conditional |
|
1250 |
|
1251 %<bitfield>d print bitfield in decimal |
|
1252 %<bitfield>W print bitfield*4 in decimal |
|
1253 %<bitfield>r print bitfield as an ARM register |
|
1254 %<bitfield>c print bitfield as a condition code |
|
1255 |
|
1256 %<bitfield>'c print specified char iff bitfield is all ones |
|
1257 %<bitfield>`c print specified char iff bitfield is all zeroes |
|
1258 %<bitfield>?ab... select from array of values in big endian order |
|
1259 |
|
1260 With one exception at the bottom (done because BL and BLX(1) need |
|
1261 to come dead last), this table was machine-sorted first in |
|
1262 decreasing order of number of bits set in the mask, then in |
|
1263 increasing numeric order of mask, then in increasing numeric order |
|
1264 of opcode. This order is not the clearest for a human reader, but |
|
1265 is guaranteed never to catch a special-case bit pattern with a more |
|
1266 general mask, which is important, because this instruction encoding |
|
1267 makes heavy use of special-case bit patterns. */ |
|
1268 static const struct opcode32 thumb32_opcodes[] = |
|
1269 { |
|
1270 /* V7 instructions. */ |
|
1271 {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli%c\t%a"}, |
|
1272 {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg%c\t#%0-3d"}, |
|
1273 {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb%c\t%U"}, |
|
1274 {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb%c\t%U"}, |
|
1275 {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb%c\t%U"}, |
|
1276 {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv%c\t%8-11r, %16-19r, %0-3r"}, |
|
1277 {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv%c\t%8-11r, %16-19r, %0-3r"}, |
|
1278 |
|
1279 /* Instructions defined in the basic V6T2 set. */ |
|
1280 {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop%c.w"}, |
|
1281 {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield%c.w"}, |
|
1282 {ARM_EXT_V6T2, 0xf3af8002, 0xffffffff, "wfe%c.w"}, |
|
1283 {ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi%c.w"}, |
|
1284 {ARM_EXT_V6T2, 0xf3af9004, 0xffffffff, "sev%c.w"}, |
|
1285 {ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop%c.w\t{%0-7d}"}, |
|
1286 |
|
1287 {ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex%c"}, |
|
1288 {ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f%X"}, |
|
1289 {ARM_EXT_V6T2, 0xf3af8600, 0xffffff1f, "cpsid.w\t%7'a%6'i%5'f%X"}, |
|
1290 {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj%c\t%16-19r%x"}, |
|
1291 {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb%c\t%16-19r%21'!"}, |
|
1292 {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia%c\t%16-19r%21'!"}, |
|
1293 {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs%c\t%8-11r, %D"}, |
|
1294 {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d%X"}, |
|
1295 {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb%c\t[%16-19r, %0-3r]%x"}, |
|
1296 {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh%c\t[%16-19r, %0-3r, lsl #1]%x"}, |
|
1297 {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d%X"}, |
|
1298 {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d%X"}, |
|
1299 {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs%c\tpc, lr, #%0-7d"}, |
|
1300 {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr%c\t%C, %16-19r"}, |
|
1301 {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex%c\t%12-15r, [%16-19r]"}, |
|
1302 {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb%c\t%12-15r, [%16-19r]"}, |
|
1303 {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb%c\t%16-19r%21'!, #%0-4d"}, |
|
1304 {ARM_EXT_V6T2, 0xe980c000, 0xffd0ffe0, "srsia%c\t%16-19r%21'!, #%0-4d"}, |
|
1305 {ARM_EXT_V6T2, 0xfa0ff080, 0xfffff0c0, "sxth%c.w\t%8-11r, %0-3r%R"}, |
|
1306 {ARM_EXT_V6T2, 0xfa1ff080, 0xfffff0c0, "uxth%c.w\t%8-11r, %0-3r%R"}, |
|
1307 {ARM_EXT_V6T2, 0xfa2ff080, 0xfffff0c0, "sxtb16%c\t%8-11r, %0-3r%R"}, |
|
1308 {ARM_EXT_V6T2, 0xfa3ff080, 0xfffff0c0, "uxtb16%c\t%8-11r, %0-3r%R"}, |
|
1309 {ARM_EXT_V6T2, 0xfa4ff080, 0xfffff0c0, "sxtb%c.w\t%8-11r, %0-3r%R"}, |
|
1310 {ARM_EXT_V6T2, 0xfa5ff080, 0xfffff0c0, "uxtb%c.w\t%8-11r, %0-3r%R"}, |
|
1311 {ARM_EXT_V6T2, 0xe8400000, 0xfff000ff, "strex%c\t%8-11r, %12-15r, [%16-19r]"}, |
|
1312 {ARM_EXT_V6T2, 0xe8d0007f, 0xfff000ff, "ldrexd%c\t%12-15r, %8-11r, [%16-19r]"}, |
|
1313 {ARM_EXT_V6T2, 0xfa80f000, 0xfff0f0f0, "sadd8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1314 {ARM_EXT_V6T2, 0xfa80f010, 0xfff0f0f0, "qadd8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1315 {ARM_EXT_V6T2, 0xfa80f020, 0xfff0f0f0, "shadd8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1316 {ARM_EXT_V6T2, 0xfa80f040, 0xfff0f0f0, "uadd8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1317 {ARM_EXT_V6T2, 0xfa80f050, 0xfff0f0f0, "uqadd8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1318 {ARM_EXT_V6T2, 0xfa80f060, 0xfff0f0f0, "uhadd8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1319 {ARM_EXT_V6T2, 0xfa80f080, 0xfff0f0f0, "qadd%c\t%8-11r, %0-3r, %16-19r"}, |
|
1320 {ARM_EXT_V6T2, 0xfa80f090, 0xfff0f0f0, "qdadd%c\t%8-11r, %0-3r, %16-19r"}, |
|
1321 {ARM_EXT_V6T2, 0xfa80f0a0, 0xfff0f0f0, "qsub%c\t%8-11r, %0-3r, %16-19r"}, |
|
1322 {ARM_EXT_V6T2, 0xfa80f0b0, 0xfff0f0f0, "qdsub%c\t%8-11r, %0-3r, %16-19r"}, |
|
1323 {ARM_EXT_V6T2, 0xfa90f000, 0xfff0f0f0, "sadd16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1324 {ARM_EXT_V6T2, 0xfa90f010, 0xfff0f0f0, "qadd16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1325 {ARM_EXT_V6T2, 0xfa90f020, 0xfff0f0f0, "shadd16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1326 {ARM_EXT_V6T2, 0xfa90f040, 0xfff0f0f0, "uadd16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1327 {ARM_EXT_V6T2, 0xfa90f050, 0xfff0f0f0, "uqadd16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1328 {ARM_EXT_V6T2, 0xfa90f060, 0xfff0f0f0, "uhadd16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1329 {ARM_EXT_V6T2, 0xfa90f080, 0xfff0f0f0, "rev%c.w\t%8-11r, %16-19r"}, |
|
1330 {ARM_EXT_V6T2, 0xfa90f090, 0xfff0f0f0, "rev16%c.w\t%8-11r, %16-19r"}, |
|
1331 {ARM_EXT_V6T2, 0xfa90f0a0, 0xfff0f0f0, "rbit%c\t%8-11r, %16-19r"}, |
|
1332 {ARM_EXT_V6T2, 0xfa90f0b0, 0xfff0f0f0, "revsh%c.w\t%8-11r, %16-19r"}, |
|
1333 {ARM_EXT_V6T2, 0xfaa0f000, 0xfff0f0f0, "saddsubx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1334 {ARM_EXT_V6T2, 0xfaa0f010, 0xfff0f0f0, "qaddsubx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1335 {ARM_EXT_V6T2, 0xfaa0f020, 0xfff0f0f0, "shaddsubx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1336 {ARM_EXT_V6T2, 0xfaa0f040, 0xfff0f0f0, "uaddsubx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1337 {ARM_EXT_V6T2, 0xfaa0f050, 0xfff0f0f0, "uqaddsubx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1338 {ARM_EXT_V6T2, 0xfaa0f060, 0xfff0f0f0, "uhaddsubx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1339 {ARM_EXT_V6T2, 0xfaa0f080, 0xfff0f0f0, "sel%c\t%8-11r, %16-19r, %0-3r"}, |
|
1340 {ARM_EXT_V6T2, 0xfab0f080, 0xfff0f0f0, "clz%c\t%8-11r, %16-19r"}, |
|
1341 {ARM_EXT_V6T2, 0xfac0f000, 0xfff0f0f0, "ssub8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1342 {ARM_EXT_V6T2, 0xfac0f010, 0xfff0f0f0, "qsub8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1343 {ARM_EXT_V6T2, 0xfac0f020, 0xfff0f0f0, "shsub8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1344 {ARM_EXT_V6T2, 0xfac0f040, 0xfff0f0f0, "usub8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1345 {ARM_EXT_V6T2, 0xfac0f050, 0xfff0f0f0, "uqsub8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1346 {ARM_EXT_V6T2, 0xfac0f060, 0xfff0f0f0, "uhsub8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1347 {ARM_EXT_V6T2, 0xfad0f000, 0xfff0f0f0, "ssub16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1348 {ARM_EXT_V6T2, 0xfad0f010, 0xfff0f0f0, "qsub16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1349 {ARM_EXT_V6T2, 0xfad0f020, 0xfff0f0f0, "shsub16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1350 {ARM_EXT_V6T2, 0xfad0f040, 0xfff0f0f0, "usub16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1351 {ARM_EXT_V6T2, 0xfad0f050, 0xfff0f0f0, "uqsub16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1352 {ARM_EXT_V6T2, 0xfad0f060, 0xfff0f0f0, "uhsub16%c\t%8-11r, %16-19r, %0-3r"}, |
|
1353 {ARM_EXT_V6T2, 0xfae0f000, 0xfff0f0f0, "ssubaddx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1354 {ARM_EXT_V6T2, 0xfae0f010, 0xfff0f0f0, "qsubaddx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1355 {ARM_EXT_V6T2, 0xfae0f020, 0xfff0f0f0, "shsubaddx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1356 {ARM_EXT_V6T2, 0xfae0f040, 0xfff0f0f0, "usubaddx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1357 {ARM_EXT_V6T2, 0xfae0f050, 0xfff0f0f0, "uqsubaddx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1358 {ARM_EXT_V6T2, 0xfae0f060, 0xfff0f0f0, "uhsubaddx%c\t%8-11r, %16-19r, %0-3r"}, |
|
1359 {ARM_EXT_V6T2, 0xfb00f000, 0xfff0f0f0, "mul%c.w\t%8-11r, %16-19r, %0-3r"}, |
|
1360 {ARM_EXT_V6T2, 0xfb70f000, 0xfff0f0f0, "usad8%c\t%8-11r, %16-19r, %0-3r"}, |
|
1361 {ARM_EXT_V6T2, 0xfa00f000, 0xffe0f0f0, "lsl%20's%c.w\t%8-11r, %16-19r, %0-3r"}, |
|
1362 {ARM_EXT_V6T2, 0xfa20f000, 0xffe0f0f0, "lsr%20's%c.w\t%8-11r, %16-19r, %0-3r"}, |
|
1363 {ARM_EXT_V6T2, 0xfa40f000, 0xffe0f0f0, "asr%20's%c.w\t%8-11r, %16-19r, %0-3r"}, |
|
1364 {ARM_EXT_V6T2, 0xfa60f000, 0xffe0f0f0, "ror%20's%c.w\t%8-11r, %16-19r, %0-3r"}, |
|
1365 {ARM_EXT_V6T2, 0xe8c00f40, 0xfff00fe0, "strex%4?hb%c\t%0-3r, %12-15r, [%16-19r]"}, |
|
1366 {ARM_EXT_V6T2, 0xf3200000, 0xfff0f0e0, "ssat16%c\t%8-11r, #%0-4d, %16-19r"}, |
|
1367 {ARM_EXT_V6T2, 0xf3a00000, 0xfff0f0e0, "usat16%c\t%8-11r, #%0-4d, %16-19r"}, |
|
1368 {ARM_EXT_V6T2, 0xfb20f000, 0xfff0f0e0, "smuad%4'x%c\t%8-11r, %16-19r, %0-3r"}, |
|
1369 {ARM_EXT_V6T2, 0xfb30f000, 0xfff0f0e0, "smulw%4?tb%c\t%8-11r, %16-19r, %0-3r"}, |
|
1370 {ARM_EXT_V6T2, 0xfb40f000, 0xfff0f0e0, "smusd%4'x%c\t%8-11r, %16-19r, %0-3r"}, |
|
1371 {ARM_EXT_V6T2, 0xfb50f000, 0xfff0f0e0, "smmul%4'r%c\t%8-11r, %16-19r, %0-3r"}, |
|
1372 {ARM_EXT_V6T2, 0xfa00f080, 0xfff0f0c0, "sxtah%c\t%8-11r, %16-19r, %0-3r%R"}, |
|
1373 {ARM_EXT_V6T2, 0xfa10f080, 0xfff0f0c0, "uxtah%c\t%8-11r, %16-19r, %0-3r%R"}, |
|
1374 {ARM_EXT_V6T2, 0xfa20f080, 0xfff0f0c0, "sxtab16%c\t%8-11r, %16-19r, %0-3r%R"}, |
|
1375 {ARM_EXT_V6T2, 0xfa30f080, 0xfff0f0c0, "uxtab16%c\t%8-11r, %16-19r, %0-3r%R"}, |
|
1376 {ARM_EXT_V6T2, 0xfa40f080, 0xfff0f0c0, "sxtab%c\t%8-11r, %16-19r, %0-3r%R"}, |
|
1377 {ARM_EXT_V6T2, 0xfa50f080, 0xfff0f0c0, "uxtab%c\t%8-11r, %16-19r, %0-3r%R"}, |
|
1378 {ARM_EXT_V6T2, 0xfb10f000, 0xfff0f0c0, "smul%5?tb%4?tb%c\t%8-11r, %16-19r, %0-3r"}, |
|
1379 {ARM_EXT_V6T2, 0xf36f0000, 0xffff8020, "bfc%c\t%8-11r, %E"}, |
|
1380 {ARM_EXT_V6T2, 0xea100f00, 0xfff08f00, "tst%c.w\t%16-19r, %S"}, |
|
1381 {ARM_EXT_V6T2, 0xea900f00, 0xfff08f00, "teq%c\t%16-19r, %S"}, |
|
1382 {ARM_EXT_V6T2, 0xeb100f00, 0xfff08f00, "cmn%c.w\t%16-19r, %S"}, |
|
1383 {ARM_EXT_V6T2, 0xebb00f00, 0xfff08f00, "cmp%c.w\t%16-19r, %S"}, |
|
1384 {ARM_EXT_V6T2, 0xf0100f00, 0xfbf08f00, "tst%c.w\t%16-19r, %M"}, |
|
1385 {ARM_EXT_V6T2, 0xf0900f00, 0xfbf08f00, "teq%c\t%16-19r, %M"}, |
|
1386 {ARM_EXT_V6T2, 0xf1100f00, 0xfbf08f00, "cmn%c.w\t%16-19r, %M"}, |
|
1387 {ARM_EXT_V6T2, 0xf1b00f00, 0xfbf08f00, "cmp%c.w\t%16-19r, %M"}, |
|
1388 {ARM_EXT_V6T2, 0xea4f0000, 0xffef8000, "mov%20's%c.w\t%8-11r, %S"}, |
|
1389 {ARM_EXT_V6T2, 0xea6f0000, 0xffef8000, "mvn%20's%c.w\t%8-11r, %S"}, |
|
1390 {ARM_EXT_V6T2, 0xe8c00070, 0xfff000f0, "strexd%c\t%0-3r, %12-15r, %8-11r, [%16-19r]"}, |
|
1391 {ARM_EXT_V6T2, 0xfb000000, 0xfff000f0, "mla%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1392 {ARM_EXT_V6T2, 0xfb000010, 0xfff000f0, "mls%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1393 {ARM_EXT_V6T2, 0xfb700000, 0xfff000f0, "usada8%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1394 {ARM_EXT_V6T2, 0xfb800000, 0xfff000f0, "smull%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1395 {ARM_EXT_V6T2, 0xfba00000, 0xfff000f0, "umull%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1396 {ARM_EXT_V6T2, 0xfbc00000, 0xfff000f0, "smlal%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1397 {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1398 {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1399 {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex%c\t%12-15r, [%16-19r, #%0-7W]"}, |
|
1400 {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc%c\t%K"}, |
|
1401 {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's%c.w\t%8-11r, %M"}, |
|
1402 {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's%c.w\t%8-11r, %M"}, |
|
1403 {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld%c\t%a"}, |
|
1404 {ARM_EXT_V6T2, 0xfb200000, 0xfff000e0, "smlad%4'x%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1405 {ARM_EXT_V6T2, 0xfb300000, 0xfff000e0, "smlaw%4?tb%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1406 {ARM_EXT_V6T2, 0xfb400000, 0xfff000e0, "smlsd%4'x%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1407 {ARM_EXT_V6T2, 0xfb500000, 0xfff000e0, "smmla%4'r%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1408 {ARM_EXT_V6T2, 0xfb600000, 0xfff000e0, "smmls%4'r%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1409 {ARM_EXT_V6T2, 0xfbc000c0, 0xfff000e0, "smlald%4'x%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1410 {ARM_EXT_V6T2, 0xfbd000c0, 0xfff000e0, "smlsld%4'x%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1411 {ARM_EXT_V6T2, 0xeac00000, 0xfff08030, "pkhbt%c\t%8-11r, %16-19r, %S"}, |
|
1412 {ARM_EXT_V6T2, 0xeac00020, 0xfff08030, "pkhtb%c\t%8-11r, %16-19r, %S"}, |
|
1413 {ARM_EXT_V6T2, 0xf3400000, 0xfff08020, "sbfx%c\t%8-11r, %16-19r, %F"}, |
|
1414 {ARM_EXT_V6T2, 0xf3c00000, 0xfff08020, "ubfx%c\t%8-11r, %16-19r, %F"}, |
|
1415 {ARM_EXT_V6T2, 0xf8000e00, 0xff900f00, "str%wt%c\t%12-15r, %a"}, |
|
1416 {ARM_EXT_V6T2, 0xfb100000, 0xfff000c0, "smla%5?tb%4?tb%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, |
|
1417 {ARM_EXT_V6T2, 0xfbc00080, 0xfff000c0, "smlal%5?tb%4?tb%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, |
|
1418 {ARM_EXT_V6T2, 0xf3600000, 0xfff08020, "bfi%c\t%8-11r, %16-19r, %E"}, |
|
1419 {ARM_EXT_V6T2, 0xf8100e00, 0xfe900f00, "ldr%wt%c\t%12-15r, %a"}, |
|
1420 {ARM_EXT_V6T2, 0xf3000000, 0xffd08020, "ssat%c\t%8-11r, #%0-4d, %16-19r%s"}, |
|
1421 {ARM_EXT_V6T2, 0xf3800000, 0xffd08020, "usat%c\t%8-11r, #%0-4d, %16-19r%s"}, |
|
1422 {ARM_EXT_V6T2, 0xf2000000, 0xfbf08000, "addw%c\t%8-11r, %16-19r, %I"}, |
|
1423 {ARM_EXT_V6T2, 0xf2400000, 0xfbf08000, "movw%c\t%8-11r, %J"}, |
|
1424 {ARM_EXT_V6T2, 0xf2a00000, 0xfbf08000, "subw%c\t%8-11r, %16-19r, %I"}, |
|
1425 {ARM_EXT_V6T2, 0xf2c00000, 0xfbf08000, "movt%c\t%8-11r, %J"}, |
|
1426 {ARM_EXT_V6T2, 0xea000000, 0xffe08000, "and%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1427 {ARM_EXT_V6T2, 0xea200000, 0xffe08000, "bic%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1428 {ARM_EXT_V6T2, 0xea400000, 0xffe08000, "orr%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1429 {ARM_EXT_V6T2, 0xea600000, 0xffe08000, "orn%20's%c\t%8-11r, %16-19r, %S"}, |
|
1430 {ARM_EXT_V6T2, 0xea800000, 0xffe08000, "eor%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1431 {ARM_EXT_V6T2, 0xeb000000, 0xffe08000, "add%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1432 {ARM_EXT_V6T2, 0xeb400000, 0xffe08000, "adc%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1433 {ARM_EXT_V6T2, 0xeb600000, 0xffe08000, "sbc%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1434 {ARM_EXT_V6T2, 0xeba00000, 0xffe08000, "sub%20's%c.w\t%8-11r, %16-19r, %S"}, |
|
1435 {ARM_EXT_V6T2, 0xebc00000, 0xffe08000, "rsb%20's%c\t%8-11r, %16-19r, %S"}, |
|
1436 {ARM_EXT_V6T2, 0xe8400000, 0xfff00000, "strex%c\t%8-11r, %12-15r, [%16-19r, #%0-7W]"}, |
|
1437 {ARM_EXT_V6T2, 0xf0000000, 0xfbe08000, "and%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1438 {ARM_EXT_V6T2, 0xf0200000, 0xfbe08000, "bic%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1439 {ARM_EXT_V6T2, 0xf0400000, 0xfbe08000, "orr%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1440 {ARM_EXT_V6T2, 0xf0600000, 0xfbe08000, "orn%20's%c\t%8-11r, %16-19r, %M"}, |
|
1441 {ARM_EXT_V6T2, 0xf0800000, 0xfbe08000, "eor%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1442 {ARM_EXT_V6T2, 0xf1000000, 0xfbe08000, "add%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1443 {ARM_EXT_V6T2, 0xf1400000, 0xfbe08000, "adc%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1444 {ARM_EXT_V6T2, 0xf1600000, 0xfbe08000, "sbc%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1445 {ARM_EXT_V6T2, 0xf1a00000, 0xfbe08000, "sub%20's%c.w\t%8-11r, %16-19r, %M"}, |
|
1446 {ARM_EXT_V6T2, 0xf1c00000, 0xfbe08000, "rsb%20's%c\t%8-11r, %16-19r, %M"}, |
|
1447 {ARM_EXT_V6T2, 0xe8800000, 0xffd00000, "stmia%c.w\t%16-19r%21'!, %m"}, |
|
1448 {ARM_EXT_V6T2, 0xe8900000, 0xffd00000, "ldmia%c.w\t%16-19r%21'!, %m"}, |
|
1449 {ARM_EXT_V6T2, 0xe9000000, 0xffd00000, "stmdb%c\t%16-19r%21'!, %m"}, |
|
1450 {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb%c\t%16-19r%21'!, %m"}, |
|
1451 {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd%c\t%12-15r, %8-11r, [%16-19r]"}, |
|
1452 {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd%c\t%12-15r, %8-11r, [%16-19r]"}, |
|
1453 {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"}, |
|
1454 {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"}, |
|
1455 {ARM_EXT_V6T2, 0xe8600000, 0xff700000, "strd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"}, |
|
1456 {ARM_EXT_V6T2, 0xe8700000, 0xff700000, "ldrd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"}, |
|
1457 {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w%c.w\t%12-15r, %a"}, |
|
1458 {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w%c.w\t%12-15r, %a"}, |
|
1459 |
|
1460 /* Filter out Bcc with cond=E or F, which are used for other instructions. */ |
|
1461 {ARM_EXT_V6T2, 0xf3c08000, 0xfbc0d000, "undefined (bcc, cond=0xF)"}, |
|
1462 {ARM_EXT_V6T2, 0xf3808000, 0xfbc0d000, "undefined (bcc, cond=0xE)"}, |
|
1463 {ARM_EXT_V6T2, 0xf0008000, 0xf800d000, "b%22-25c.w\t%b%X"}, |
|
1464 {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b%c.w\t%B%x"}, |
|
1465 |
|
1466 /* These have been 32-bit since the invention of Thumb. */ |
|
1467 {ARM_EXT_V4T, 0xf000c000, 0xf800d000, "blx%c\t%B%x"}, |
|
1468 {ARM_EXT_V4T, 0xf000d000, 0xf800d000, "bl%c\t%B%x"}, |
|
1469 |
|
1470 /* Fallback. */ |
|
1471 {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined"}, |
|
1472 {0, 0, 0, 0} |
|
1473 }; |
|
1474 |
|
1475 static const char *const arm_conditional[] = |
|
1476 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", |
|
1477 "hi", "ls", "ge", "lt", "gt", "le", "al", "<und>", ""}; |
|
1478 |
|
1479 static const char *const arm_fp_const[] = |
|
1480 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"}; |
|
1481 |
|
1482 static const char *const arm_shift[] = |
|
1483 {"lsl", "lsr", "asr", "ror"}; |
|
1484 |
|
1485 typedef struct |
|
1486 { |
|
1487 const char *name; |
|
1488 const char *description; |
|
1489 const char *reg_names[16]; |
|
1490 } |
|
1491 arm_regname; |
|
1492 |
|
1493 static const arm_regname regnames[] = |
|
1494 { |
|
1495 { "raw" , "Select raw register names", |
|
1496 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}, |
|
1497 { "gcc", "Select register names used by GCC", |
|
1498 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }}, |
|
1499 { "std", "Select register names used in ARM's ISA documentation", |
|
1500 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }}, |
|
1501 { "apcs", "Select register names used in the APCS", |
|
1502 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }}, |
|
1503 { "atpcs", "Select register names used in the ATPCS", |
|
1504 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, |
|
1505 { "special-atpcs", "Select special register names used in the ATPCS", |
|
1506 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}, |
|
1507 }; |
|
1508 |
|
1509 static const char *const iwmmxt_wwnames[] = |
|
1510 {"b", "h", "w", "d"}; |
|
1511 |
|
1512 static const char *const iwmmxt_wwssnames[] = |
|
1513 {"b", "bus", "bc", "bss", |
|
1514 "h", "hus", "hc", "hss", |
|
1515 "w", "wus", "wc", "wss", |
|
1516 "d", "dus", "dc", "dss" |
|
1517 }; |
|
1518 |
|
1519 static const char *const iwmmxt_regnames[] = |
|
1520 { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", |
|
1521 "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15" |
|
1522 }; |
|
1523 |
|
1524 static const char *const iwmmxt_cregnames[] = |
|
1525 { "wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", |
|
1526 "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved" |
|
1527 }; |
|
1528 |
|
1529 /* Default to GCC register name set. */ |
|
1530 static unsigned int regname_selected = 1; |
|
1531 |
|
1532 #define NUM_ARM_REGNAMES NUM_ELEM (regnames) |
|
1533 #define arm_regnames regnames[regname_selected].reg_names |
|
1534 |
|
1535 static bfd_boolean force_thumb = FALSE; |
|
1536 |
|
1537 /* Current IT instruction state. This contains the same state as the IT |
|
1538 bits in the CPSR. */ |
|
1539 static unsigned int ifthen_state; |
|
1540 /* IT state for the next instruction. */ |
|
1541 static unsigned int ifthen_next_state; |
|
1542 /* The address of the insn for which the IT state is valid. */ |
|
1543 static bfd_vma ifthen_address; |
|
1544 #define IFTHEN_COND ((ifthen_state >> 4) & 0xf) |
|
1545 |
|
1546 /* Cached mapping symbol state. */ |
|
1547 enum map_type { |
|
1548 MAP_ARM, |
|
1549 MAP_THUMB, |
|
1550 MAP_DATA |
|
1551 }; |
|
1552 |
|
1553 enum map_type last_type; |
|
1554 int last_mapping_sym = -1; |
|
1555 bfd_vma last_mapping_addr = 0; |
|
1556 |
|
1557 |
|
1558 /* Functions. */ |
|
1559 int |
|
1560 get_arm_regname_num_options (void) |
|
1561 { |
|
1562 return NUM_ARM_REGNAMES; |
|
1563 } |
|
1564 |
|
1565 int |
|
1566 set_arm_regname_option (int option) |
|
1567 { |
|
1568 int old = regname_selected; |
|
1569 regname_selected = option; |
|
1570 return old; |
|
1571 } |
|
1572 |
|
1573 int |
|
1574 get_arm_regnames (int option, const char **setname, const char **setdescription, |
|
1575 const char *const **register_names) |
|
1576 { |
|
1577 *setname = regnames[option].name; |
|
1578 *setdescription = regnames[option].description; |
|
1579 *register_names = regnames[option].reg_names; |
|
1580 return 16; |
|
1581 } |
|
1582 |
|
1583 /* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?. |
|
1584 Returns pointer to following character of the format string and |
|
1585 fills in *VALUEP and *WIDTHP with the extracted value and number of |
|
1586 bits extracted. WIDTHP can be NULL. */ |
|
1587 |
|
1588 static const char * |
|
1589 arm_decode_bitfield (const char *ptr, unsigned long insn, |
|
1590 unsigned long *valuep, int *widthp) |
|
1591 { |
|
1592 unsigned long value = 0; |
|
1593 int width = 0; |
|
1594 |
|
1595 do |
|
1596 { |
|
1597 int start, end; |
|
1598 int bits; |
|
1599 |
|
1600 for (start = 0; *ptr >= '0' && *ptr <= '9'; ptr++) |
|
1601 start = start * 10 + *ptr - '0'; |
|
1602 if (*ptr == '-') |
|
1603 for (end = 0, ptr++; *ptr >= '0' && *ptr <= '9'; ptr++) |
|
1604 end = end * 10 + *ptr - '0'; |
|
1605 else |
|
1606 end = start; |
|
1607 bits = end - start; |
|
1608 if (bits < 0) |
|
1609 abort (); |
|
1610 value |= ((insn >> start) & ((2ul << bits) - 1)) << width; |
|
1611 width += bits + 1; |
|
1612 } |
|
1613 while (*ptr++ == ','); |
|
1614 *valuep = value; |
|
1615 if (widthp) |
|
1616 *widthp = width; |
|
1617 return ptr - 1; |
|
1618 } |
|
1619 |
|
1620 static void |
|
1621 arm_decode_shift (long given, fprintf_ftype func, void *stream, |
|
1622 int print_shift) |
|
1623 { |
|
1624 func (stream, "%s", arm_regnames[given & 0xf]); |
|
1625 |
|
1626 if ((given & 0xff0) != 0) |
|
1627 { |
|
1628 if ((given & 0x10) == 0) |
|
1629 { |
|
1630 int amount = (given & 0xf80) >> 7; |
|
1631 int shift = (given & 0x60) >> 5; |
|
1632 |
|
1633 if (amount == 0) |
|
1634 { |
|
1635 if (shift == 3) |
|
1636 { |
|
1637 func (stream, ", rrx"); |
|
1638 return; |
|
1639 } |
|
1640 |
|
1641 amount = 32; |
|
1642 } |
|
1643 |
|
1644 if (print_shift) |
|
1645 func (stream, ", %s #%d", arm_shift[shift], amount); |
|
1646 else |
|
1647 func (stream, ", #%d", amount); |
|
1648 } |
|
1649 else if (print_shift) |
|
1650 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5], |
|
1651 arm_regnames[(given & 0xf00) >> 8]); |
|
1652 else |
|
1653 func (stream, ", %s", arm_regnames[(given & 0xf00) >> 8]); |
|
1654 } |
|
1655 } |
|
1656 |
|
1657 /* Print one coprocessor instruction on INFO->STREAM. |
|
1658 Return TRUE if the instuction matched, FALSE if this is not a |
|
1659 recognised coprocessor instruction. */ |
|
1660 |
|
1661 static bfd_boolean |
|
1662 print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given, |
|
1663 bfd_boolean thumb) |
|
1664 { |
|
1665 const struct opcode32 *insn; |
|
1666 void *stream = info->stream; |
|
1667 fprintf_ftype func = info->fprintf_func; |
|
1668 unsigned long mask; |
|
1669 unsigned long value; |
|
1670 int cond; |
|
1671 |
|
1672 for (insn = coprocessor_opcodes; insn->assembler; insn++) |
|
1673 { |
|
1674 if (insn->value == FIRST_IWMMXT_INSN |
|
1675 && info->mach != bfd_mach_arm_XScale |
|
1676 && info->mach != bfd_mach_arm_iWMMXt |
|
1677 && info->mach != bfd_mach_arm_iWMMXt2) |
|
1678 insn = insn + IWMMXT_INSN_COUNT; |
|
1679 |
|
1680 mask = insn->mask; |
|
1681 value = insn->value; |
|
1682 if (thumb) |
|
1683 { |
|
1684 /* The high 4 bits are 0xe for Arm conditional instructions, and |
|
1685 0xe for arm unconditional instructions. The rest of the |
|
1686 encoding is the same. */ |
|
1687 mask |= 0xf0000000; |
|
1688 value |= 0xe0000000; |
|
1689 if (ifthen_state) |
|
1690 cond = IFTHEN_COND; |
|
1691 else |
|
1692 cond = 16; |
|
1693 } |
|
1694 else |
|
1695 { |
|
1696 /* Only match unconditional instuctions against unconditional |
|
1697 patterns. */ |
|
1698 if ((given & 0xf0000000) == 0xf0000000) |
|
1699 { |
|
1700 mask |= 0xf0000000; |
|
1701 cond = 16; |
|
1702 } |
|
1703 else |
|
1704 { |
|
1705 cond = (given >> 28) & 0xf; |
|
1706 if (cond == 0xe) |
|
1707 cond = 16; |
|
1708 } |
|
1709 } |
|
1710 if ((given & mask) == value) |
|
1711 { |
|
1712 const char *c; |
|
1713 |
|
1714 for (c = insn->assembler; *c; c++) |
|
1715 { |
|
1716 if (*c == '%') |
|
1717 { |
|
1718 switch (*++c) |
|
1719 { |
|
1720 case '%': |
|
1721 func (stream, "%%"); |
|
1722 break; |
|
1723 |
|
1724 case 'A': |
|
1725 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); |
|
1726 |
|
1727 if ((given & (1 << 24)) != 0) |
|
1728 { |
|
1729 int offset = given & 0xff; |
|
1730 |
|
1731 if (offset) |
|
1732 func (stream, ", #%s%d]%s", |
|
1733 ((given & 0x00800000) == 0 ? "-" : ""), |
|
1734 offset * 4, |
|
1735 ((given & 0x00200000) != 0 ? "!" : "")); |
|
1736 else |
|
1737 func (stream, "]"); |
|
1738 } |
|
1739 else |
|
1740 { |
|
1741 int offset = given & 0xff; |
|
1742 |
|
1743 func (stream, "]"); |
|
1744 |
|
1745 if (given & (1 << 21)) |
|
1746 { |
|
1747 if (offset) |
|
1748 func (stream, ", #%s%d", |
|
1749 ((given & 0x00800000) == 0 ? "-" : ""), |
|
1750 offset * 4); |
|
1751 } |
|
1752 else |
|
1753 func (stream, ", {%d}", offset); |
|
1754 } |
|
1755 break; |
|
1756 |
|
1757 case 'B': |
|
1758 { |
|
1759 int regno = ((given >> 12) & 0xf) | ((given >> (22 - 4)) & 0x10); |
|
1760 int offset = (given >> 1) & 0x3f; |
|
1761 |
|
1762 if (offset == 1) |
|
1763 func (stream, "{d%d}", regno); |
|
1764 else if (regno + offset > 32) |
|
1765 func (stream, "{d%d-<overflow reg d%d>}", regno, regno + offset - 1); |
|
1766 else |
|
1767 func (stream, "{d%d-d%d}", regno, regno + offset - 1); |
|
1768 } |
|
1769 break; |
|
1770 |
|
1771 case 'C': |
|
1772 { |
|
1773 int rn = (given >> 16) & 0xf; |
|
1774 int offset = (given & 0xff) * 4; |
|
1775 int add = (given >> 23) & 1; |
|
1776 |
|
1777 func (stream, "[%s", arm_regnames[rn]); |
|
1778 |
|
1779 if (offset) |
|
1780 { |
|
1781 if (!add) |
|
1782 offset = -offset; |
|
1783 func (stream, ", #%d", offset); |
|
1784 } |
|
1785 func (stream, "]"); |
|
1786 if (rn == 15) |
|
1787 { |
|
1788 func (stream, "\t; "); |
|
1789 /* FIXME: Unsure if info->bytes_per_chunk is the |
|
1790 right thing to use here. */ |
|
1791 info->print_address_func (offset + pc |
|
1792 + info->bytes_per_chunk * 2, info); |
|
1793 } |
|
1794 } |
|
1795 break; |
|
1796 |
|
1797 case 'c': |
|
1798 func (stream, "%s", arm_conditional[cond]); |
|
1799 break; |
|
1800 |
|
1801 case 'I': |
|
1802 /* Print a Cirrus/DSP shift immediate. */ |
|
1803 /* Immediates are 7bit signed ints with bits 0..3 in |
|
1804 bits 0..3 of opcode and bits 4..6 in bits 5..7 |
|
1805 of opcode. */ |
|
1806 { |
|
1807 int imm; |
|
1808 |
|
1809 imm = (given & 0xf) | ((given & 0xe0) >> 1); |
|
1810 |
|
1811 /* Is ``imm'' a negative number? */ |
|
1812 if (imm & 0x40) |
|
1813 imm |= (-1 << 7); |
|
1814 |
|
1815 func (stream, "%d", imm); |
|
1816 } |
|
1817 |
|
1818 break; |
|
1819 |
|
1820 case 'F': |
|
1821 switch (given & 0x00408000) |
|
1822 { |
|
1823 case 0: |
|
1824 func (stream, "4"); |
|
1825 break; |
|
1826 case 0x8000: |
|
1827 func (stream, "1"); |
|
1828 break; |
|
1829 case 0x00400000: |
|
1830 func (stream, "2"); |
|
1831 break; |
|
1832 default: |
|
1833 func (stream, "3"); |
|
1834 } |
|
1835 break; |
|
1836 |
|
1837 case 'P': |
|
1838 switch (given & 0x00080080) |
|
1839 { |
|
1840 case 0: |
|
1841 func (stream, "s"); |
|
1842 break; |
|
1843 case 0x80: |
|
1844 func (stream, "d"); |
|
1845 break; |
|
1846 case 0x00080000: |
|
1847 func (stream, "e"); |
|
1848 break; |
|
1849 default: |
|
1850 func (stream, _("<illegal precision>")); |
|
1851 break; |
|
1852 } |
|
1853 break; |
|
1854 case 'Q': |
|
1855 switch (given & 0x00408000) |
|
1856 { |
|
1857 case 0: |
|
1858 func (stream, "s"); |
|
1859 break; |
|
1860 case 0x8000: |
|
1861 func (stream, "d"); |
|
1862 break; |
|
1863 case 0x00400000: |
|
1864 func (stream, "e"); |
|
1865 break; |
|
1866 default: |
|
1867 func (stream, "p"); |
|
1868 break; |
|
1869 } |
|
1870 break; |
|
1871 case 'R': |
|
1872 switch (given & 0x60) |
|
1873 { |
|
1874 case 0: |
|
1875 break; |
|
1876 case 0x20: |
|
1877 func (stream, "p"); |
|
1878 break; |
|
1879 case 0x40: |
|
1880 func (stream, "m"); |
|
1881 break; |
|
1882 default: |
|
1883 func (stream, "z"); |
|
1884 break; |
|
1885 } |
|
1886 break; |
|
1887 |
|
1888 case '0': case '1': case '2': case '3': case '4': |
|
1889 case '5': case '6': case '7': case '8': case '9': |
|
1890 { |
|
1891 int width; |
|
1892 unsigned long value; |
|
1893 |
|
1894 c = arm_decode_bitfield (c, given, &value, &width); |
|
1895 |
|
1896 switch (*c) |
|
1897 { |
|
1898 case 'r': |
|
1899 func (stream, "%s", arm_regnames[value]); |
|
1900 break; |
|
1901 case 'D': |
|
1902 func (stream, "d%ld", value); |
|
1903 break; |
|
1904 case 'Q': |
|
1905 if (value & 1) |
|
1906 func (stream, "<illegal reg q%ld.5>", value >> 1); |
|
1907 else |
|
1908 func (stream, "q%ld", value >> 1); |
|
1909 break; |
|
1910 case 'd': |
|
1911 func (stream, "%ld", value); |
|
1912 break; |
|
1913 case 'k': |
|
1914 { |
|
1915 int from = (given & (1 << 7)) ? 32 : 16; |
|
1916 func (stream, "%ld", from - value); |
|
1917 } |
|
1918 break; |
|
1919 |
|
1920 case 'f': |
|
1921 if (value > 7) |
|
1922 func (stream, "#%s", arm_fp_const[value & 7]); |
|
1923 else |
|
1924 func (stream, "f%ld", value); |
|
1925 break; |
|
1926 |
|
1927 case 'w': |
|
1928 if (width == 2) |
|
1929 func (stream, "%s", iwmmxt_wwnames[value]); |
|
1930 else |
|
1931 func (stream, "%s", iwmmxt_wwssnames[value]); |
|
1932 break; |
|
1933 |
|
1934 case 'g': |
|
1935 func (stream, "%s", iwmmxt_regnames[value]); |
|
1936 break; |
|
1937 case 'G': |
|
1938 func (stream, "%s", iwmmxt_cregnames[value]); |
|
1939 break; |
|
1940 |
|
1941 case 'x': |
|
1942 func (stream, "0x%lx", value); |
|
1943 break; |
|
1944 |
|
1945 case '`': |
|
1946 c++; |
|
1947 if (value == 0) |
|
1948 func (stream, "%c", *c); |
|
1949 break; |
|
1950 case '\'': |
|
1951 c++; |
|
1952 if (value == ((1ul << width) - 1)) |
|
1953 func (stream, "%c", *c); |
|
1954 break; |
|
1955 case '?': |
|
1956 func (stream, "%c", c[(1 << width) - (int)value]); |
|
1957 c += 1 << width; |
|
1958 break; |
|
1959 default: |
|
1960 abort (); |
|
1961 } |
|
1962 break; |
|
1963 |
|
1964 case 'y': |
|
1965 case 'z': |
|
1966 { |
|
1967 int single = *c++ == 'y'; |
|
1968 int regno; |
|
1969 |
|
1970 switch (*c) |
|
1971 { |
|
1972 case '4': /* Sm pair */ |
|
1973 func (stream, "{"); |
|
1974 /* Fall through. */ |
|
1975 case '0': /* Sm, Dm */ |
|
1976 regno = given & 0x0000000f; |
|
1977 if (single) |
|
1978 { |
|
1979 regno <<= 1; |
|
1980 regno += (given >> 5) & 1; |
|
1981 } |
|
1982 else |
|
1983 regno += ((given >> 5) & 1) << 4; |
|
1984 break; |
|
1985 |
|
1986 case '1': /* Sd, Dd */ |
|
1987 regno = (given >> 12) & 0x0000000f; |
|
1988 if (single) |
|
1989 { |
|
1990 regno <<= 1; |
|
1991 regno += (given >> 22) & 1; |
|
1992 } |
|
1993 else |
|
1994 regno += ((given >> 22) & 1) << 4; |
|
1995 break; |
|
1996 |
|
1997 case '2': /* Sn, Dn */ |
|
1998 regno = (given >> 16) & 0x0000000f; |
|
1999 if (single) |
|
2000 { |
|
2001 regno <<= 1; |
|
2002 regno += (given >> 7) & 1; |
|
2003 } |
|
2004 else |
|
2005 regno += ((given >> 7) & 1) << 4; |
|
2006 break; |
|
2007 |
|
2008 case '3': /* List */ |
|
2009 func (stream, "{"); |
|
2010 regno = (given >> 12) & 0x0000000f; |
|
2011 if (single) |
|
2012 { |
|
2013 regno <<= 1; |
|
2014 regno += (given >> 22) & 1; |
|
2015 } |
|
2016 else |
|
2017 regno += ((given >> 22) & 1) << 4; |
|
2018 break; |
|
2019 |
|
2020 default: |
|
2021 abort (); |
|
2022 } |
|
2023 |
|
2024 func (stream, "%c%d", single ? 's' : 'd', regno); |
|
2025 |
|
2026 if (*c == '3') |
|
2027 { |
|
2028 int count = given & 0xff; |
|
2029 |
|
2030 if (single == 0) |
|
2031 count >>= 1; |
|
2032 |
|
2033 if (--count) |
|
2034 { |
|
2035 func (stream, "-%c%d", |
|
2036 single ? 's' : 'd', |
|
2037 regno + count); |
|
2038 } |
|
2039 |
|
2040 func (stream, "}"); |
|
2041 } |
|
2042 else if (*c == '4') |
|
2043 func (stream, ", %c%d}", single ? 's' : 'd', |
|
2044 regno + 1); |
|
2045 } |
|
2046 break; |
|
2047 |
|
2048 case 'L': |
|
2049 switch (given & 0x00400100) |
|
2050 { |
|
2051 case 0x00000000: func (stream, "b"); break; |
|
2052 case 0x00400000: func (stream, "h"); break; |
|
2053 case 0x00000100: func (stream, "w"); break; |
|
2054 case 0x00400100: func (stream, "d"); break; |
|
2055 default: |
|
2056 break; |
|
2057 } |
|
2058 break; |
|
2059 |
|
2060 case 'Z': |
|
2061 { |
|
2062 int value; |
|
2063 /* given (20, 23) | given (0, 3) */ |
|
2064 value = ((given >> 16) & 0xf0) | (given & 0xf); |
|
2065 func (stream, "%d", value); |
|
2066 } |
|
2067 break; |
|
2068 |
|
2069 case 'l': |
|
2070 /* This is like the 'A' operator, except that if |
|
2071 the width field "M" is zero, then the offset is |
|
2072 *not* multiplied by four. */ |
|
2073 { |
|
2074 int offset = given & 0xff; |
|
2075 int multiplier = (given & 0x00000100) ? 4 : 1; |
|
2076 |
|
2077 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); |
|
2078 |
|
2079 if (offset) |
|
2080 { |
|
2081 if ((given & 0x01000000) != 0) |
|
2082 func (stream, ", #%s%d]%s", |
|
2083 ((given & 0x00800000) == 0 ? "-" : ""), |
|
2084 offset * multiplier, |
|
2085 ((given & 0x00200000) != 0 ? "!" : "")); |
|
2086 else |
|
2087 func (stream, "], #%s%d", |
|
2088 ((given & 0x00800000) == 0 ? "-" : ""), |
|
2089 offset * multiplier); |
|
2090 } |
|
2091 else |
|
2092 func (stream, "]"); |
|
2093 } |
|
2094 break; |
|
2095 |
|
2096 case 'r': |
|
2097 { |
|
2098 int imm4 = (given >> 4) & 0xf; |
|
2099 int puw_bits = ((given >> 22) & 6) | ((given >> 21) & 1); |
|
2100 int ubit = (given >> 23) & 1; |
|
2101 const char *rm = arm_regnames [given & 0xf]; |
|
2102 const char *rn = arm_regnames [(given >> 16) & 0xf]; |
|
2103 |
|
2104 switch (puw_bits) |
|
2105 { |
|
2106 case 1: |
|
2107 /* fall through */ |
|
2108 case 3: |
|
2109 func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm); |
|
2110 if (imm4) |
|
2111 func (stream, ", lsl #%d", imm4); |
|
2112 break; |
|
2113 |
|
2114 case 4: |
|
2115 /* fall through */ |
|
2116 case 5: |
|
2117 /* fall through */ |
|
2118 case 6: |
|
2119 /* fall through */ |
|
2120 case 7: |
|
2121 func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm); |
|
2122 if (imm4 > 0) |
|
2123 func (stream, ", lsl #%d", imm4); |
|
2124 func (stream, "]"); |
|
2125 if (puw_bits == 5 || puw_bits == 7) |
|
2126 func (stream, "!"); |
|
2127 break; |
|
2128 |
|
2129 default: |
|
2130 func (stream, "INVALID"); |
|
2131 } |
|
2132 } |
|
2133 break; |
|
2134 |
|
2135 case 'i': |
|
2136 { |
|
2137 long imm5; |
|
2138 imm5 = ((given & 0x100) >> 4) | (given & 0xf); |
|
2139 func (stream, "%ld", (imm5 == 0) ? 32 : imm5); |
|
2140 } |
|
2141 break; |
|
2142 |
|
2143 default: |
|
2144 abort (); |
|
2145 } |
|
2146 } |
|
2147 } |
|
2148 else |
|
2149 func (stream, "%c", *c); |
|
2150 } |
|
2151 return TRUE; |
|
2152 } |
|
2153 } |
|
2154 return FALSE; |
|
2155 } |
|
2156 |
|
2157 static void |
|
2158 print_arm_address (bfd_vma pc, struct disassemble_info *info, long given) |
|
2159 { |
|
2160 void *stream = info->stream; |
|
2161 fprintf_ftype func = info->fprintf_func; |
|
2162 |
|
2163 if (((given & 0x000f0000) == 0x000f0000) |
|
2164 && ((given & 0x02000000) == 0)) |
|
2165 { |
|
2166 int offset = given & 0xfff; |
|
2167 |
|
2168 func (stream, "[pc"); |
|
2169 |
|
2170 if (given & 0x01000000) |
|
2171 { |
|
2172 if ((given & 0x00800000) == 0) |
|
2173 offset = - offset; |
|
2174 |
|
2175 /* Pre-indexed. */ |
|
2176 func (stream, ", #%d]", offset); |
|
2177 |
|
2178 offset += pc + 8; |
|
2179 |
|
2180 /* Cope with the possibility of write-back |
|
2181 being used. Probably a very dangerous thing |
|
2182 for the programmer to do, but who are we to |
|
2183 argue ? */ |
|
2184 if (given & 0x00200000) |
|
2185 func (stream, "!"); |
|
2186 } |
|
2187 else |
|
2188 { |
|
2189 /* Post indexed. */ |
|
2190 func (stream, "], #%d", offset); |
|
2191 |
|
2192 /* ie ignore the offset. */ |
|
2193 offset = pc + 8; |
|
2194 } |
|
2195 |
|
2196 func (stream, "\t; "); |
|
2197 info->print_address_func (offset, info); |
|
2198 } |
|
2199 else |
|
2200 { |
|
2201 func (stream, "[%s", |
|
2202 arm_regnames[(given >> 16) & 0xf]); |
|
2203 if ((given & 0x01000000) != 0) |
|
2204 { |
|
2205 if ((given & 0x02000000) == 0) |
|
2206 { |
|
2207 int offset = given & 0xfff; |
|
2208 if (offset) |
|
2209 func (stream, ", #%s%d", |
|
2210 (((given & 0x00800000) == 0) |
|
2211 ? "-" : ""), offset); |
|
2212 } |
|
2213 else |
|
2214 { |
|
2215 func (stream, ", %s", |
|
2216 (((given & 0x00800000) == 0) |
|
2217 ? "-" : "")); |
|
2218 arm_decode_shift (given, func, stream, 1); |
|
2219 } |
|
2220 |
|
2221 func (stream, "]%s", |
|
2222 ((given & 0x00200000) != 0) ? "!" : ""); |
|
2223 } |
|
2224 else |
|
2225 { |
|
2226 if ((given & 0x02000000) == 0) |
|
2227 { |
|
2228 int offset = given & 0xfff; |
|
2229 if (offset) |
|
2230 func (stream, "], #%s%d", |
|
2231 (((given & 0x00800000) == 0) |
|
2232 ? "-" : ""), offset); |
|
2233 else |
|
2234 func (stream, "]"); |
|
2235 } |
|
2236 else |
|
2237 { |
|
2238 func (stream, "], %s", |
|
2239 (((given & 0x00800000) == 0) |
|
2240 ? "-" : "")); |
|
2241 arm_decode_shift (given, func, stream, 1); |
|
2242 } |
|
2243 } |
|
2244 } |
|
2245 } |
|
2246 |
|
2247 /* Print one neon instruction on INFO->STREAM. |
|
2248 Return TRUE if the instuction matched, FALSE if this is not a |
|
2249 recognised neon instruction. */ |
|
2250 |
|
2251 static bfd_boolean |
|
2252 print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb) |
|
2253 { |
|
2254 const struct opcode32 *insn; |
|
2255 void *stream = info->stream; |
|
2256 fprintf_ftype func = info->fprintf_func; |
|
2257 |
|
2258 if (thumb) |
|
2259 { |
|
2260 if ((given & 0xef000000) == 0xef000000) |
|
2261 { |
|
2262 /* move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */ |
|
2263 unsigned long bit28 = given & (1 << 28); |
|
2264 |
|
2265 given &= 0x00ffffff; |
|
2266 if (bit28) |
|
2267 given |= 0xf3000000; |
|
2268 else |
|
2269 given |= 0xf2000000; |
|
2270 } |
|
2271 else if ((given & 0xff000000) == 0xf9000000) |
|
2272 given ^= 0xf9000000 ^ 0xf4000000; |
|
2273 else |
|
2274 return FALSE; |
|
2275 } |
|
2276 |
|
2277 for (insn = neon_opcodes; insn->assembler; insn++) |
|
2278 { |
|
2279 if ((given & insn->mask) == insn->value) |
|
2280 { |
|
2281 const char *c; |
|
2282 |
|
2283 for (c = insn->assembler; *c; c++) |
|
2284 { |
|
2285 if (*c == '%') |
|
2286 { |
|
2287 switch (*++c) |
|
2288 { |
|
2289 case '%': |
|
2290 func (stream, "%%"); |
|
2291 break; |
|
2292 |
|
2293 case 'c': |
|
2294 if (thumb && ifthen_state) |
|
2295 func (stream, "%s", arm_conditional[IFTHEN_COND]); |
|
2296 break; |
|
2297 |
|
2298 case 'A': |
|
2299 { |
|
2300 static const unsigned char enc[16] = |
|
2301 { |
|
2302 0x4, 0x14, /* st4 0,1 */ |
|
2303 0x4, /* st1 2 */ |
|
2304 0x4, /* st2 3 */ |
|
2305 0x3, /* st3 4 */ |
|
2306 0x13, /* st3 5 */ |
|
2307 0x3, /* st1 6 */ |
|
2308 0x1, /* st1 7 */ |
|
2309 0x2, /* st2 8 */ |
|
2310 0x12, /* st2 9 */ |
|
2311 0x2, /* st1 10 */ |
|
2312 0, 0, 0, 0, 0 |
|
2313 }; |
|
2314 int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4); |
|
2315 int rn = ((given >> 16) & 0xf); |
|
2316 int rm = ((given >> 0) & 0xf); |
|
2317 int align = ((given >> 4) & 0x3); |
|
2318 int type = ((given >> 8) & 0xf); |
|
2319 int n = enc[type] & 0xf; |
|
2320 int stride = (enc[type] >> 4) + 1; |
|
2321 int ix; |
|
2322 |
|
2323 func (stream, "{"); |
|
2324 if (stride > 1) |
|
2325 for (ix = 0; ix != n; ix++) |
|
2326 func (stream, "%sd%d", ix ? "," : "", rd + ix * stride); |
|
2327 else if (n == 1) |
|
2328 func (stream, "d%d", rd); |
|
2329 else |
|
2330 func (stream, "d%d-d%d", rd, rd + n - 1); |
|
2331 func (stream, "}, [%s", arm_regnames[rn]); |
|
2332 if (align) |
|
2333 func (stream, ", :%d", 32 << align); |
|
2334 func (stream, "]"); |
|
2335 if (rm == 0xd) |
|
2336 func (stream, "!"); |
|
2337 else if (rm != 0xf) |
|
2338 func (stream, ", %s", arm_regnames[rm]); |
|
2339 } |
|
2340 break; |
|
2341 |
|
2342 case 'B': |
|
2343 { |
|
2344 int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4); |
|
2345 int rn = ((given >> 16) & 0xf); |
|
2346 int rm = ((given >> 0) & 0xf); |
|
2347 int idx_align = ((given >> 4) & 0xf); |
|
2348 int align = 0; |
|
2349 int size = ((given >> 10) & 0x3); |
|
2350 int idx = idx_align >> (size + 1); |
|
2351 int length = ((given >> 8) & 3) + 1; |
|
2352 int stride = 1; |
|
2353 int i; |
|
2354 |
|
2355 if (length > 1 && size > 0) |
|
2356 stride = (idx_align & (1 << size)) ? 2 : 1; |
|
2357 |
|
2358 switch (length) |
|
2359 { |
|
2360 case 1: |
|
2361 { |
|
2362 int amask = (1 << size) - 1; |
|
2363 if ((idx_align & (1 << size)) != 0) |
|
2364 return FALSE; |
|
2365 if (size > 0) |
|
2366 { |
|
2367 if ((idx_align & amask) == amask) |
|
2368 align = 8 << size; |
|
2369 else if ((idx_align & amask) != 0) |
|
2370 return FALSE; |
|
2371 } |
|
2372 } |
|
2373 break; |
|
2374 |
|
2375 case 2: |
|
2376 if (size == 2 && (idx_align & 2) != 0) |
|
2377 return FALSE; |
|
2378 align = (idx_align & 1) ? 16 << size : 0; |
|
2379 break; |
|
2380 |
|
2381 case 3: |
|
2382 if ((size == 2 && (idx_align & 3) != 0) |
|
2383 || (idx_align & 1) != 0) |
|
2384 return FALSE; |
|
2385 break; |
|
2386 |
|
2387 case 4: |
|
2388 if (size == 2) |
|
2389 { |
|
2390 if ((idx_align & 3) == 3) |
|
2391 return FALSE; |
|
2392 align = (idx_align & 3) * 64; |
|
2393 } |
|
2394 else |
|
2395 align = (idx_align & 1) ? 32 << size : 0; |
|
2396 break; |
|
2397 |
|
2398 default: |
|
2399 abort (); |
|
2400 } |
|
2401 |
|
2402 func (stream, "{"); |
|
2403 for (i = 0; i < length; i++) |
|
2404 func (stream, "%sd%d[%d]", (i == 0) ? "" : ",", |
|
2405 rd + i * stride, idx); |
|
2406 func (stream, "}, [%s", arm_regnames[rn]); |
|
2407 if (align) |
|
2408 func (stream, ", :%d", align); |
|
2409 func (stream, "]"); |
|
2410 if (rm == 0xd) |
|
2411 func (stream, "!"); |
|
2412 else if (rm != 0xf) |
|
2413 func (stream, ", %s", arm_regnames[rm]); |
|
2414 } |
|
2415 break; |
|
2416 |
|
2417 case 'C': |
|
2418 { |
|
2419 int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4); |
|
2420 int rn = ((given >> 16) & 0xf); |
|
2421 int rm = ((given >> 0) & 0xf); |
|
2422 int align = ((given >> 4) & 0x1); |
|
2423 int size = ((given >> 6) & 0x3); |
|
2424 int type = ((given >> 8) & 0x3); |
|
2425 int n = type + 1; |
|
2426 int stride = ((given >> 5) & 0x1); |
|
2427 int ix; |
|
2428 |
|
2429 if (stride && (n == 1)) |
|
2430 n++; |
|
2431 else |
|
2432 stride++; |
|
2433 |
|
2434 func (stream, "{"); |
|
2435 if (stride > 1) |
|
2436 for (ix = 0; ix != n; ix++) |
|
2437 func (stream, "%sd%d[]", ix ? "," : "", rd + ix * stride); |
|
2438 else if (n == 1) |
|
2439 func (stream, "d%d[]", rd); |
|
2440 else |
|
2441 func (stream, "d%d[]-d%d[]", rd, rd + n - 1); |
|
2442 func (stream, "}, [%s", arm_regnames[rn]); |
|
2443 if (align) |
|
2444 { |
|
2445 int align = (8 * (type + 1)) << size; |
|
2446 if (type == 3) |
|
2447 align = (size > 1) ? align >> 1 : align; |
|
2448 if (type == 2 || (type == 0 && !size)) |
|
2449 func (stream, ", :<bad align %d>", align); |
|
2450 else |
|
2451 func (stream, ", :%d", align); |
|
2452 } |
|
2453 func (stream, "]"); |
|
2454 if (rm == 0xd) |
|
2455 func (stream, "!"); |
|
2456 else if (rm != 0xf) |
|
2457 func (stream, ", %s", arm_regnames[rm]); |
|
2458 } |
|
2459 break; |
|
2460 |
|
2461 case 'D': |
|
2462 { |
|
2463 int raw_reg = (given & 0xf) | ((given >> 1) & 0x10); |
|
2464 int size = (given >> 20) & 3; |
|
2465 int reg = raw_reg & ((4 << size) - 1); |
|
2466 int ix = raw_reg >> size >> 2; |
|
2467 |
|
2468 func (stream, "d%d[%d]", reg, ix); |
|
2469 } |
|
2470 break; |
|
2471 |
|
2472 case 'E': |
|
2473 /* Neon encoded constant for mov, mvn, vorr, vbic */ |
|
2474 { |
|
2475 int bits = 0; |
|
2476 int cmode = (given >> 8) & 0xf; |
|
2477 int op = (given >> 5) & 0x1; |
|
2478 unsigned long value = 0, hival = 0; |
|
2479 unsigned shift; |
|
2480 int size = 0; |
|
2481 int isfloat = 0; |
|
2482 |
|
2483 bits |= ((given >> 24) & 1) << 7; |
|
2484 bits |= ((given >> 16) & 7) << 4; |
|
2485 bits |= ((given >> 0) & 15) << 0; |
|
2486 |
|
2487 if (cmode < 8) |
|
2488 { |
|
2489 shift = (cmode >> 1) & 3; |
|
2490 value = (unsigned long)bits << (8 * shift); |
|
2491 size = 32; |
|
2492 } |
|
2493 else if (cmode < 12) |
|
2494 { |
|
2495 shift = (cmode >> 1) & 1; |
|
2496 value = (unsigned long)bits << (8 * shift); |
|
2497 size = 16; |
|
2498 } |
|
2499 else if (cmode < 14) |
|
2500 { |
|
2501 shift = (cmode & 1) + 1; |
|
2502 value = (unsigned long)bits << (8 * shift); |
|
2503 value |= (1ul << (8 * shift)) - 1; |
|
2504 size = 32; |
|
2505 } |
|
2506 else if (cmode == 14) |
|
2507 { |
|
2508 if (op) |
|
2509 { |
|
2510 /* bit replication into bytes */ |
|
2511 int ix; |
|
2512 unsigned long mask; |
|
2513 |
|
2514 value = 0; |
|
2515 hival = 0; |
|
2516 for (ix = 7; ix >= 0; ix--) |
|
2517 { |
|
2518 mask = ((bits >> ix) & 1) ? 0xff : 0; |
|
2519 if (ix <= 3) |
|
2520 value = (value << 8) | mask; |
|
2521 else |
|
2522 hival = (hival << 8) | mask; |
|
2523 } |
|
2524 size = 64; |
|
2525 } |
|
2526 else |
|
2527 { |
|
2528 /* byte replication */ |
|
2529 value = (unsigned long)bits; |
|
2530 size = 8; |
|
2531 } |
|
2532 } |
|
2533 else if (!op) |
|
2534 { |
|
2535 /* floating point encoding */ |
|
2536 int tmp; |
|
2537 |
|
2538 value = (unsigned long)(bits & 0x7f) << 19; |
|
2539 value |= (unsigned long)(bits & 0x80) << 24; |
|
2540 tmp = bits & 0x40 ? 0x3c : 0x40; |
|
2541 value |= (unsigned long)tmp << 24; |
|
2542 size = 32; |
|
2543 isfloat = 1; |
|
2544 } |
|
2545 else |
|
2546 { |
|
2547 func (stream, "<illegal constant %.8x:%x:%x>", |
|
2548 bits, cmode, op); |
|
2549 size = 32; |
|
2550 break; |
|
2551 } |
|
2552 switch (size) |
|
2553 { |
|
2554 case 8: |
|
2555 func (stream, "#%ld\t; 0x%.2lx", value, value); |
|
2556 break; |
|
2557 |
|
2558 case 16: |
|
2559 func (stream, "#%ld\t; 0x%.4lx", value, value); |
|
2560 break; |
|
2561 |
|
2562 case 32: |
|
2563 if (isfloat) |
|
2564 { |
|
2565 unsigned char valbytes[4]; |
|
2566 double fvalue; |
|
2567 |
|
2568 /* Do this a byte at a time so we don't have to |
|
2569 worry about the host's endianness. */ |
|
2570 valbytes[0] = value & 0xff; |
|
2571 valbytes[1] = (value >> 8) & 0xff; |
|
2572 valbytes[2] = (value >> 16) & 0xff; |
|
2573 valbytes[3] = (value >> 24) & 0xff; |
|
2574 |
|
2575 floatformat_to_double |
|
2576 (&floatformat_ieee_single_little, valbytes, |
|
2577 &fvalue); |
|
2578 |
|
2579 func (stream, "#%.7g\t; 0x%.8lx", fvalue, |
|
2580 value); |
|
2581 } |
|
2582 else |
|
2583 func (stream, "#%ld\t; 0x%.8lx", |
|
2584 (long) ((value & 0x80000000) |
|
2585 ? value | ~0xffffffffl : value), value); |
|
2586 break; |
|
2587 |
|
2588 case 64: |
|
2589 func (stream, "#0x%.8lx%.8lx", hival, value); |
|
2590 break; |
|
2591 |
|
2592 default: |
|
2593 abort (); |
|
2594 } |
|
2595 } |
|
2596 break; |
|
2597 |
|
2598 case 'F': |
|
2599 { |
|
2600 int regno = ((given >> 16) & 0xf) | ((given >> (7 - 4)) & 0x10); |
|
2601 int num = (given >> 8) & 0x3; |
|
2602 |
|
2603 if (!num) |
|
2604 func (stream, "{d%d}", regno); |
|
2605 else if (num + regno >= 32) |
|
2606 func (stream, "{d%d-<overflow reg d%d}", regno, regno + num); |
|
2607 else |
|
2608 func (stream, "{d%d-d%d}", regno, regno + num); |
|
2609 } |
|
2610 break; |
|
2611 |
|
2612 |
|
2613 case '0': case '1': case '2': case '3': case '4': |
|
2614 case '5': case '6': case '7': case '8': case '9': |
|
2615 { |
|
2616 int width; |
|
2617 unsigned long value; |
|
2618 |
|
2619 c = arm_decode_bitfield (c, given, &value, &width); |
|
2620 |
|
2621 switch (*c) |
|
2622 { |
|
2623 case 'r': |
|
2624 func (stream, "%s", arm_regnames[value]); |
|
2625 break; |
|
2626 case 'd': |
|
2627 func (stream, "%ld", value); |
|
2628 break; |
|
2629 case 'e': |
|
2630 func (stream, "%ld", (1ul << width) - value); |
|
2631 break; |
|
2632 |
|
2633 case 'S': |
|
2634 case 'T': |
|
2635 case 'U': |
|
2636 /* various width encodings */ |
|
2637 { |
|
2638 int base = 8 << (*c - 'S'); /* 8,16 or 32 */ |
|
2639 int limit; |
|
2640 unsigned low, high; |
|
2641 |
|
2642 c++; |
|
2643 if (*c >= '0' && *c <= '9') |
|
2644 limit = *c - '0'; |
|
2645 else if (*c >= 'a' && *c <= 'f') |
|
2646 limit = *c - 'a' + 10; |
|
2647 else |
|
2648 abort (); |
|
2649 low = limit >> 2; |
|
2650 high = limit & 3; |
|
2651 |
|
2652 if (value < low || value > high) |
|
2653 func (stream, "<illegal width %d>", base << value); |
|
2654 else |
|
2655 func (stream, "%d", base << value); |
|
2656 } |
|
2657 break; |
|
2658 case 'R': |
|
2659 if (given & (1 << 6)) |
|
2660 goto Q; |
|
2661 /* FALLTHROUGH */ |
|
2662 case 'D': |
|
2663 func (stream, "d%ld", value); |
|
2664 break; |
|
2665 case 'Q': |
|
2666 Q: |
|
2667 if (value & 1) |
|
2668 func (stream, "<illegal reg q%ld.5>", value >> 1); |
|
2669 else |
|
2670 func (stream, "q%ld", value >> 1); |
|
2671 break; |
|
2672 |
|
2673 case '`': |
|
2674 c++; |
|
2675 if (value == 0) |
|
2676 func (stream, "%c", *c); |
|
2677 break; |
|
2678 case '\'': |
|
2679 c++; |
|
2680 if (value == ((1ul << width) - 1)) |
|
2681 func (stream, "%c", *c); |
|
2682 break; |
|
2683 case '?': |
|
2684 func (stream, "%c", c[(1 << width) - (int)value]); |
|
2685 c += 1 << width; |
|
2686 break; |
|
2687 default: |
|
2688 abort (); |
|
2689 } |
|
2690 break; |
|
2691 |
|
2692 default: |
|
2693 abort (); |
|
2694 } |
|
2695 } |
|
2696 } |
|
2697 else |
|
2698 func (stream, "%c", *c); |
|
2699 } |
|
2700 return TRUE; |
|
2701 } |
|
2702 } |
|
2703 return FALSE; |
|
2704 } |
|
2705 |
|
2706 /* Print one ARM instruction from PC on INFO->STREAM. */ |
|
2707 |
|
2708 static void |
|
2709 print_insn_arm_internal (bfd_vma pc, struct disassemble_info *info, long given) |
|
2710 { |
|
2711 const struct opcode32 *insn; |
|
2712 void *stream = info->stream; |
|
2713 fprintf_ftype func = info->fprintf_func; |
|
2714 |
|
2715 if (print_insn_coprocessor (pc, info, given, FALSE)) |
|
2716 return; |
|
2717 |
|
2718 if (print_insn_neon (info, given, FALSE)) |
|
2719 return; |
|
2720 |
|
2721 for (insn = arm_opcodes; insn->assembler; insn++) |
|
2722 { |
|
2723 if (insn->value == FIRST_IWMMXT_INSN |
|
2724 && info->mach != bfd_mach_arm_XScale |
|
2725 && info->mach != bfd_mach_arm_iWMMXt) |
|
2726 insn = insn + IWMMXT_INSN_COUNT; |
|
2727 |
|
2728 if ((given & insn->mask) == insn->value |
|
2729 /* Special case: an instruction with all bits set in the condition field |
|
2730 (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask, |
|
2731 or by the catchall at the end of the table. */ |
|
2732 && ((given & 0xF0000000) != 0xF0000000 |
|
2733 || (insn->mask & 0xF0000000) == 0xF0000000 |
|
2734 || (insn->mask == 0 && insn->value == 0))) |
|
2735 { |
|
2736 const char *c; |
|
2737 |
|
2738 for (c = insn->assembler; *c; c++) |
|
2739 { |
|
2740 if (*c == '%') |
|
2741 { |
|
2742 switch (*++c) |
|
2743 { |
|
2744 case '%': |
|
2745 func (stream, "%%"); |
|
2746 break; |
|
2747 |
|
2748 case 'a': |
|
2749 print_arm_address (pc, info, given); |
|
2750 break; |
|
2751 |
|
2752 case 'P': |
|
2753 /* Set P address bit and use normal address |
|
2754 printing routine. */ |
|
2755 print_arm_address (pc, info, given | (1 << 24)); |
|
2756 break; |
|
2757 |
|
2758 case 's': |
|
2759 if ((given & 0x004f0000) == 0x004f0000) |
|
2760 { |
|
2761 /* PC relative with immediate offset. */ |
|
2762 int offset = ((given & 0xf00) >> 4) | (given & 0xf); |
|
2763 |
|
2764 if ((given & 0x00800000) == 0) |
|
2765 offset = -offset; |
|
2766 |
|
2767 func (stream, "[pc, #%d]\t; ", offset); |
|
2768 info->print_address_func (offset + pc + 8, info); |
|
2769 } |
|
2770 else |
|
2771 { |
|
2772 func (stream, "[%s", |
|
2773 arm_regnames[(given >> 16) & 0xf]); |
|
2774 if ((given & 0x01000000) != 0) |
|
2775 { |
|
2776 /* Pre-indexed. */ |
|
2777 if ((given & 0x00400000) == 0x00400000) |
|
2778 { |
|
2779 /* Immediate. */ |
|
2780 int offset = ((given & 0xf00) >> 4) | (given & 0xf); |
|
2781 if (offset) |
|
2782 func (stream, ", #%s%d", |
|
2783 (((given & 0x00800000) == 0) |
|
2784 ? "-" : ""), offset); |
|
2785 } |
|
2786 else |
|
2787 { |
|
2788 /* Register. */ |
|
2789 func (stream, ", %s%s", |
|
2790 (((given & 0x00800000) == 0) |
|
2791 ? "-" : ""), |
|
2792 arm_regnames[given & 0xf]); |
|
2793 } |
|
2794 |
|
2795 func (stream, "]%s", |
|
2796 ((given & 0x00200000) != 0) ? "!" : ""); |
|
2797 } |
|
2798 else |
|
2799 { |
|
2800 /* Post-indexed. */ |
|
2801 if ((given & 0x00400000) == 0x00400000) |
|
2802 { |
|
2803 /* Immediate. */ |
|
2804 int offset = ((given & 0xf00) >> 4) | (given & 0xf); |
|
2805 if (offset) |
|
2806 func (stream, "], #%s%d", |
|
2807 (((given & 0x00800000) == 0) |
|
2808 ? "-" : ""), offset); |
|
2809 else |
|
2810 func (stream, "]"); |
|
2811 } |
|
2812 else |
|
2813 { |
|
2814 /* Register. */ |
|
2815 func (stream, "], %s%s", |
|
2816 (((given & 0x00800000) == 0) |
|
2817 ? "-" : ""), |
|
2818 arm_regnames[given & 0xf]); |
|
2819 } |
|
2820 } |
|
2821 } |
|
2822 break; |
|
2823 |
|
2824 case 'b': |
|
2825 { |
|
2826 int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000); |
|
2827 info->print_address_func (disp*4 + pc + 8, info); |
|
2828 } |
|
2829 break; |
|
2830 |
|
2831 case 'c': |
|
2832 if (((given >> 28) & 0xf) != 0xe) |
|
2833 func (stream, "%s", |
|
2834 arm_conditional [(given >> 28) & 0xf]); |
|
2835 break; |
|
2836 |
|
2837 case 'm': |
|
2838 { |
|
2839 int started = 0; |
|
2840 int reg; |
|
2841 |
|
2842 func (stream, "{"); |
|
2843 for (reg = 0; reg < 16; reg++) |
|
2844 if ((given & (1 << reg)) != 0) |
|
2845 { |
|
2846 if (started) |
|
2847 func (stream, ", "); |
|
2848 started = 1; |
|
2849 func (stream, "%s", arm_regnames[reg]); |
|
2850 } |
|
2851 func (stream, "}"); |
|
2852 } |
|
2853 break; |
|
2854 |
|
2855 case 'q': |
|
2856 arm_decode_shift (given, func, stream, 0); |
|
2857 break; |
|
2858 |
|
2859 case 'o': |
|
2860 if ((given & 0x02000000) != 0) |
|
2861 { |
|
2862 int rotate = (given & 0xf00) >> 7; |
|
2863 int immed = (given & 0xff); |
|
2864 immed = (((immed << (32 - rotate)) |
|
2865 | (immed >> rotate)) & 0xffffffff); |
|
2866 func (stream, "#%d\t; 0x%x", immed, immed); |
|
2867 } |
|
2868 else |
|
2869 arm_decode_shift (given, func, stream, 1); |
|
2870 break; |
|
2871 |
|
2872 case 'p': |
|
2873 if ((given & 0x0000f000) == 0x0000f000) |
|
2874 func (stream, "p"); |
|
2875 break; |
|
2876 |
|
2877 case 't': |
|
2878 if ((given & 0x01200000) == 0x00200000) |
|
2879 func (stream, "t"); |
|
2880 break; |
|
2881 |
|
2882 case 'A': |
|
2883 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); |
|
2884 |
|
2885 if ((given & (1 << 24)) != 0) |
|
2886 { |
|
2887 int offset = given & 0xff; |
|
2888 |
|
2889 if (offset) |
|
2890 func (stream, ", #%s%d]%s", |
|
2891 ((given & 0x00800000) == 0 ? "-" : ""), |
|
2892 offset * 4, |
|
2893 ((given & 0x00200000) != 0 ? "!" : "")); |
|
2894 else |
|
2895 func (stream, "]"); |
|
2896 } |
|
2897 else |
|
2898 { |
|
2899 int offset = given & 0xff; |
|
2900 |
|
2901 func (stream, "]"); |
|
2902 |
|
2903 if (given & (1 << 21)) |
|
2904 { |
|
2905 if (offset) |
|
2906 func (stream, ", #%s%d", |
|
2907 ((given & 0x00800000) == 0 ? "-" : ""), |
|
2908 offset * 4); |
|
2909 } |
|
2910 else |
|
2911 func (stream, ", {%d}", offset); |
|
2912 } |
|
2913 break; |
|
2914 |
|
2915 case 'B': |
|
2916 /* Print ARM V5 BLX(1) address: pc+25 bits. */ |
|
2917 { |
|
2918 bfd_vma address; |
|
2919 bfd_vma offset = 0; |
|
2920 |
|
2921 if (given & 0x00800000) |
|
2922 /* Is signed, hi bits should be ones. */ |
|
2923 offset = (-1) ^ 0x00ffffff; |
|
2924 |
|
2925 /* Offset is (SignExtend(offset field)<<2). */ |
|
2926 offset += given & 0x00ffffff; |
|
2927 offset <<= 2; |
|
2928 address = offset + pc + 8; |
|
2929 |
|
2930 if (given & 0x01000000) |
|
2931 /* H bit allows addressing to 2-byte boundaries. */ |
|
2932 address += 2; |
|
2933 |
|
2934 info->print_address_func (address, info); |
|
2935 } |
|
2936 break; |
|
2937 |
|
2938 case 'C': |
|
2939 func (stream, "_"); |
|
2940 if (given & 0x80000) |
|
2941 func (stream, "f"); |
|
2942 if (given & 0x40000) |
|
2943 func (stream, "s"); |
|
2944 if (given & 0x20000) |
|
2945 func (stream, "x"); |
|
2946 if (given & 0x10000) |
|
2947 func (stream, "c"); |
|
2948 break; |
|
2949 |
|
2950 case 'U': |
|
2951 switch (given & 0xf) |
|
2952 { |
|
2953 case 0xf: func(stream, "sy"); break; |
|
2954 case 0x7: func(stream, "un"); break; |
|
2955 case 0xe: func(stream, "st"); break; |
|
2956 case 0x6: func(stream, "unst"); break; |
|
2957 default: |
|
2958 func(stream, "#%d", (int)given & 0xf); |
|
2959 break; |
|
2960 } |
|
2961 break; |
|
2962 |
|
2963 case '0': case '1': case '2': case '3': case '4': |
|
2964 case '5': case '6': case '7': case '8': case '9': |
|
2965 { |
|
2966 int width; |
|
2967 unsigned long value; |
|
2968 |
|
2969 c = arm_decode_bitfield (c, given, &value, &width); |
|
2970 |
|
2971 switch (*c) |
|
2972 { |
|
2973 case 'r': |
|
2974 func (stream, "%s", arm_regnames[value]); |
|
2975 break; |
|
2976 case 'd': |
|
2977 func (stream, "%ld", value); |
|
2978 break; |
|
2979 case 'b': |
|
2980 func (stream, "%ld", value * 8); |
|
2981 break; |
|
2982 case 'W': |
|
2983 func (stream, "%ld", value + 1); |
|
2984 break; |
|
2985 case 'x': |
|
2986 func (stream, "0x%08lx", value); |
|
2987 |
|
2988 /* Some SWI instructions have special |
|
2989 meanings. */ |
|
2990 if ((given & 0x0fffffff) == 0x0FF00000) |
|
2991 func (stream, "\t; IMB"); |
|
2992 else if ((given & 0x0fffffff) == 0x0FF00001) |
|
2993 func (stream, "\t; IMBRange"); |
|
2994 break; |
|
2995 case 'X': |
|
2996 func (stream, "%01lx", value & 0xf); |
|
2997 break; |
|
2998 case '`': |
|
2999 c++; |
|
3000 if (value == 0) |
|
3001 func (stream, "%c", *c); |
|
3002 break; |
|
3003 case '\'': |
|
3004 c++; |
|
3005 if (value == ((1ul << width) - 1)) |
|
3006 func (stream, "%c", *c); |
|
3007 break; |
|
3008 case '?': |
|
3009 func (stream, "%c", c[(1 << width) - (int)value]); |
|
3010 c += 1 << width; |
|
3011 break; |
|
3012 default: |
|
3013 abort (); |
|
3014 } |
|
3015 break; |
|
3016 |
|
3017 case 'e': |
|
3018 { |
|
3019 int imm; |
|
3020 |
|
3021 imm = (given & 0xf) | ((given & 0xfff00) >> 4); |
|
3022 func (stream, "%d", imm); |
|
3023 } |
|
3024 break; |
|
3025 |
|
3026 case 'E': |
|
3027 /* LSB and WIDTH fields of BFI or BFC. The machine- |
|
3028 language instruction encodes LSB and MSB. */ |
|
3029 { |
|
3030 long msb = (given & 0x001f0000) >> 16; |
|
3031 long lsb = (given & 0x00000f80) >> 7; |
|
3032 |
|
3033 long width = msb - lsb + 1; |
|
3034 if (width > 0) |
|
3035 func (stream, "#%lu, #%lu", lsb, width); |
|
3036 else |
|
3037 func (stream, "(invalid: %lu:%lu)", lsb, msb); |
|
3038 } |
|
3039 break; |
|
3040 |
|
3041 case 'V': |
|
3042 /* 16-bit unsigned immediate from a MOVT or MOVW |
|
3043 instruction, encoded in bits 0:11 and 15:19. */ |
|
3044 { |
|
3045 long hi = (given & 0x000f0000) >> 4; |
|
3046 long lo = (given & 0x00000fff); |
|
3047 long imm16 = hi | lo; |
|
3048 func (stream, "#%lu\t; 0x%lx", imm16, imm16); |
|
3049 } |
|
3050 break; |
|
3051 |
|
3052 default: |
|
3053 abort (); |
|
3054 } |
|
3055 } |
|
3056 } |
|
3057 else |
|
3058 func (stream, "%c", *c); |
|
3059 } |
|
3060 return; |
|
3061 } |
|
3062 } |
|
3063 abort (); |
|
3064 } |
|
3065 |
|
3066 /* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */ |
|
3067 |
|
3068 static void |
|
3069 print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given) |
|
3070 { |
|
3071 const struct opcode16 *insn; |
|
3072 void *stream = info->stream; |
|
3073 fprintf_ftype func = info->fprintf_func; |
|
3074 |
|
3075 for (insn = thumb_opcodes; insn->assembler; insn++) |
|
3076 if ((given & insn->mask) == insn->value) |
|
3077 { |
|
3078 const char *c = insn->assembler; |
|
3079 for (; *c; c++) |
|
3080 { |
|
3081 int domaskpc = 0; |
|
3082 int domasklr = 0; |
|
3083 |
|
3084 if (*c != '%') |
|
3085 { |
|
3086 func (stream, "%c", *c); |
|
3087 continue; |
|
3088 } |
|
3089 |
|
3090 switch (*++c) |
|
3091 { |
|
3092 case '%': |
|
3093 func (stream, "%%"); |
|
3094 break; |
|
3095 |
|
3096 case 'c': |
|
3097 if (ifthen_state) |
|
3098 func (stream, "%s", arm_conditional[IFTHEN_COND]); |
|
3099 break; |
|
3100 |
|
3101 case 'C': |
|
3102 if (ifthen_state) |
|
3103 func (stream, "%s", arm_conditional[IFTHEN_COND]); |
|
3104 else |
|
3105 func (stream, "s"); |
|
3106 break; |
|
3107 |
|
3108 case 'I': |
|
3109 { |
|
3110 unsigned int tmp; |
|
3111 |
|
3112 ifthen_next_state = given & 0xff; |
|
3113 for (tmp = given << 1; tmp & 0xf; tmp <<= 1) |
|
3114 func (stream, ((given ^ tmp) & 0x10) ? "e" : "t"); |
|
3115 func (stream, "\t%s", arm_conditional[(given >> 4) & 0xf]); |
|
3116 } |
|
3117 break; |
|
3118 |
|
3119 case 'x': |
|
3120 if (ifthen_next_state) |
|
3121 func (stream, "\t; unpredictable branch in IT block\n"); |
|
3122 break; |
|
3123 |
|
3124 case 'X': |
|
3125 if (ifthen_state) |
|
3126 func (stream, "\t; unpredictable <IT:%s>", |
|
3127 arm_conditional[IFTHEN_COND]); |
|
3128 break; |
|
3129 |
|
3130 case 'S': |
|
3131 { |
|
3132 long reg; |
|
3133 |
|
3134 reg = (given >> 3) & 0x7; |
|
3135 if (given & (1 << 6)) |
|
3136 reg += 8; |
|
3137 |
|
3138 func (stream, "%s", arm_regnames[reg]); |
|
3139 } |
|
3140 break; |
|
3141 |
|
3142 case 'D': |
|
3143 { |
|
3144 long reg; |
|
3145 |
|
3146 reg = given & 0x7; |
|
3147 if (given & (1 << 7)) |
|
3148 reg += 8; |
|
3149 |
|
3150 func (stream, "%s", arm_regnames[reg]); |
|
3151 } |
|
3152 break; |
|
3153 |
|
3154 case 'N': |
|
3155 if (given & (1 << 8)) |
|
3156 domasklr = 1; |
|
3157 /* Fall through. */ |
|
3158 case 'O': |
|
3159 if (*c == 'O' && (given & (1 << 8))) |
|
3160 domaskpc = 1; |
|
3161 /* Fall through. */ |
|
3162 case 'M': |
|
3163 { |
|
3164 int started = 0; |
|
3165 int reg; |
|
3166 |
|
3167 func (stream, "{"); |
|
3168 |
|
3169 /* It would be nice if we could spot |
|
3170 ranges, and generate the rS-rE format: */ |
|
3171 for (reg = 0; (reg < 8); reg++) |
|
3172 if ((given & (1 << reg)) != 0) |
|
3173 { |
|
3174 if (started) |
|
3175 func (stream, ", "); |
|
3176 started = 1; |
|
3177 func (stream, "%s", arm_regnames[reg]); |
|
3178 } |
|
3179 |
|
3180 if (domasklr) |
|
3181 { |
|
3182 if (started) |
|
3183 func (stream, ", "); |
|
3184 started = 1; |
|
3185 func (stream, arm_regnames[14] /* "lr" */); |
|
3186 } |
|
3187 |
|
3188 if (domaskpc) |
|
3189 { |
|
3190 if (started) |
|
3191 func (stream, ", "); |
|
3192 func (stream, arm_regnames[15] /* "pc" */); |
|
3193 } |
|
3194 |
|
3195 func (stream, "}"); |
|
3196 } |
|
3197 break; |
|
3198 |
|
3199 case 'b': |
|
3200 /* Print ARM V6T2 CZB address: pc+4+6 bits. */ |
|
3201 { |
|
3202 bfd_vma address = (pc + 4 |
|
3203 + ((given & 0x00f8) >> 2) |
|
3204 + ((given & 0x0200) >> 3)); |
|
3205 info->print_address_func (address, info); |
|
3206 } |
|
3207 break; |
|
3208 |
|
3209 case 's': |
|
3210 /* Right shift immediate -- bits 6..10; 1-31 print |
|
3211 as themselves, 0 prints as 32. */ |
|
3212 { |
|
3213 long imm = (given & 0x07c0) >> 6; |
|
3214 if (imm == 0) |
|
3215 imm = 32; |
|
3216 func (stream, "#%ld", imm); |
|
3217 } |
|
3218 break; |
|
3219 |
|
3220 case '0': case '1': case '2': case '3': case '4': |
|
3221 case '5': case '6': case '7': case '8': case '9': |
|
3222 { |
|
3223 int bitstart = *c++ - '0'; |
|
3224 int bitend = 0; |
|
3225 |
|
3226 while (*c >= '0' && *c <= '9') |
|
3227 bitstart = (bitstart * 10) + *c++ - '0'; |
|
3228 |
|
3229 switch (*c) |
|
3230 { |
|
3231 case '-': |
|
3232 { |
|
3233 long reg; |
|
3234 |
|
3235 c++; |
|
3236 while (*c >= '0' && *c <= '9') |
|
3237 bitend = (bitend * 10) + *c++ - '0'; |
|
3238 if (!bitend) |
|
3239 abort (); |
|
3240 reg = given >> bitstart; |
|
3241 reg &= (2 << (bitend - bitstart)) - 1; |
|
3242 switch (*c) |
|
3243 { |
|
3244 case 'r': |
|
3245 func (stream, "%s", arm_regnames[reg]); |
|
3246 break; |
|
3247 |
|
3248 case 'd': |
|
3249 func (stream, "%ld", reg); |
|
3250 break; |
|
3251 |
|
3252 case 'H': |
|
3253 func (stream, "%ld", reg << 1); |
|
3254 break; |
|
3255 |
|
3256 case 'W': |
|
3257 func (stream, "%ld", reg << 2); |
|
3258 break; |
|
3259 |
|
3260 case 'a': |
|
3261 /* PC-relative address -- the bottom two |
|
3262 bits of the address are dropped |
|
3263 before the calculation. */ |
|
3264 info->print_address_func |
|
3265 (((pc + 4) & ~3) + (reg << 2), info); |
|
3266 break; |
|
3267 |
|
3268 case 'x': |
|
3269 func (stream, "0x%04lx", reg); |
|
3270 break; |
|
3271 |
|
3272 case 'B': |
|
3273 reg = ((reg ^ (1 << bitend)) - (1 << bitend)); |
|
3274 info->print_address_func (reg * 2 + pc + 4, info); |
|
3275 break; |
|
3276 |
|
3277 case 'c': |
|
3278 func (stream, "%s", arm_conditional [reg]); |
|
3279 break; |
|
3280 |
|
3281 default: |
|
3282 abort (); |
|
3283 } |
|
3284 } |
|
3285 break; |
|
3286 |
|
3287 case '\'': |
|
3288 c++; |
|
3289 if ((given & (1 << bitstart)) != 0) |
|
3290 func (stream, "%c", *c); |
|
3291 break; |
|
3292 |
|
3293 case '?': |
|
3294 ++c; |
|
3295 if ((given & (1 << bitstart)) != 0) |
|
3296 func (stream, "%c", *c++); |
|
3297 else |
|
3298 func (stream, "%c", *++c); |
|
3299 break; |
|
3300 |
|
3301 default: |
|
3302 abort (); |
|
3303 } |
|
3304 } |
|
3305 break; |
|
3306 |
|
3307 default: |
|
3308 abort (); |
|
3309 } |
|
3310 } |
|
3311 return; |
|
3312 } |
|
3313 |
|
3314 /* No match. */ |
|
3315 abort (); |
|
3316 } |
|
3317 |
|
3318 /* Return the name of an V7M special register. */ |
|
3319 static const char * |
|
3320 psr_name (int regno) |
|
3321 { |
|
3322 switch (regno) |
|
3323 { |
|
3324 case 0: return "APSR"; |
|
3325 case 1: return "IAPSR"; |
|
3326 case 2: return "EAPSR"; |
|
3327 case 3: return "PSR"; |
|
3328 case 5: return "IPSR"; |
|
3329 case 6: return "EPSR"; |
|
3330 case 7: return "IEPSR"; |
|
3331 case 8: return "MSP"; |
|
3332 case 9: return "PSP"; |
|
3333 case 16: return "PRIMASK"; |
|
3334 case 17: return "BASEPRI"; |
|
3335 case 18: return "BASEPRI_MASK"; |
|
3336 case 19: return "FAULTMASK"; |
|
3337 case 20: return "CONTROL"; |
|
3338 default: return "<unknown>"; |
|
3339 } |
|
3340 } |
|
3341 |
|
3342 /* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */ |
|
3343 |
|
3344 static void |
|
3345 print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) |
|
3346 { |
|
3347 const struct opcode32 *insn; |
|
3348 void *stream = info->stream; |
|
3349 fprintf_ftype func = info->fprintf_func; |
|
3350 |
|
3351 if (print_insn_coprocessor (pc, info, given, TRUE)) |
|
3352 return; |
|
3353 |
|
3354 if (print_insn_neon (info, given, TRUE)) |
|
3355 return; |
|
3356 |
|
3357 for (insn = thumb32_opcodes; insn->assembler; insn++) |
|
3358 if ((given & insn->mask) == insn->value) |
|
3359 { |
|
3360 const char *c = insn->assembler; |
|
3361 for (; *c; c++) |
|
3362 { |
|
3363 if (*c != '%') |
|
3364 { |
|
3365 func (stream, "%c", *c); |
|
3366 continue; |
|
3367 } |
|
3368 |
|
3369 switch (*++c) |
|
3370 { |
|
3371 case '%': |
|
3372 func (stream, "%%"); |
|
3373 break; |
|
3374 |
|
3375 case 'c': |
|
3376 if (ifthen_state) |
|
3377 func (stream, "%s", arm_conditional[IFTHEN_COND]); |
|
3378 break; |
|
3379 |
|
3380 case 'x': |
|
3381 if (ifthen_next_state) |
|
3382 func (stream, "\t; unpredictable branch in IT block\n"); |
|
3383 break; |
|
3384 |
|
3385 case 'X': |
|
3386 if (ifthen_state) |
|
3387 func (stream, "\t; unpredictable <IT:%s>", |
|
3388 arm_conditional[IFTHEN_COND]); |
|
3389 break; |
|
3390 |
|
3391 case 'I': |
|
3392 { |
|
3393 unsigned int imm12 = 0; |
|
3394 imm12 |= (given & 0x000000ffu); |
|
3395 imm12 |= (given & 0x00007000u) >> 4; |
|
3396 imm12 |= (given & 0x04000000u) >> 15; |
|
3397 func (stream, "#%u\t; 0x%x", imm12, imm12); |
|
3398 } |
|
3399 break; |
|
3400 |
|
3401 case 'M': |
|
3402 { |
|
3403 unsigned int bits = 0, imm, imm8, mod; |
|
3404 bits |= (given & 0x000000ffu); |
|
3405 bits |= (given & 0x00007000u) >> 4; |
|
3406 bits |= (given & 0x04000000u) >> 15; |
|
3407 imm8 = (bits & 0x0ff); |
|
3408 mod = (bits & 0xf00) >> 8; |
|
3409 switch (mod) |
|
3410 { |
|
3411 case 0: imm = imm8; break; |
|
3412 case 1: imm = ((imm8<<16) | imm8); break; |
|
3413 case 2: imm = ((imm8<<24) | (imm8 << 8)); break; |
|
3414 case 3: imm = ((imm8<<24) | (imm8 << 16) | (imm8 << 8) | imm8); break; |
|
3415 default: |
|
3416 mod = (bits & 0xf80) >> 7; |
|
3417 imm8 = (bits & 0x07f) | 0x80; |
|
3418 imm = (((imm8 << (32 - mod)) | (imm8 >> mod)) & 0xffffffff); |
|
3419 } |
|
3420 func (stream, "#%u\t; 0x%x", imm, imm); |
|
3421 } |
|
3422 break; |
|
3423 |
|
3424 case 'J': |
|
3425 { |
|
3426 unsigned int imm = 0; |
|
3427 imm |= (given & 0x000000ffu); |
|
3428 imm |= (given & 0x00007000u) >> 4; |
|
3429 imm |= (given & 0x04000000u) >> 15; |
|
3430 imm |= (given & 0x000f0000u) >> 4; |
|
3431 func (stream, "#%u\t; 0x%x", imm, imm); |
|
3432 } |
|
3433 break; |
|
3434 |
|
3435 case 'K': |
|
3436 { |
|
3437 unsigned int imm = 0; |
|
3438 imm |= (given & 0x000f0000u) >> 16; |
|
3439 imm |= (given & 0x00000ff0u) >> 0; |
|
3440 imm |= (given & 0x0000000fu) << 12; |
|
3441 func (stream, "#%u\t; 0x%x", imm, imm); |
|
3442 } |
|
3443 break; |
|
3444 |
|
3445 case 'S': |
|
3446 { |
|
3447 unsigned int reg = (given & 0x0000000fu); |
|
3448 unsigned int stp = (given & 0x00000030u) >> 4; |
|
3449 unsigned int imm = 0; |
|
3450 imm |= (given & 0x000000c0u) >> 6; |
|
3451 imm |= (given & 0x00007000u) >> 10; |
|
3452 |
|
3453 func (stream, "%s", arm_regnames[reg]); |
|
3454 switch (stp) |
|
3455 { |
|
3456 case 0: |
|
3457 if (imm > 0) |
|
3458 func (stream, ", lsl #%u", imm); |
|
3459 break; |
|
3460 |
|
3461 case 1: |
|
3462 if (imm == 0) |
|
3463 imm = 32; |
|
3464 func (stream, ", lsr #%u", imm); |
|
3465 break; |
|
3466 |
|
3467 case 2: |
|
3468 if (imm == 0) |
|
3469 imm = 32; |
|
3470 func (stream, ", asr #%u", imm); |
|
3471 break; |
|
3472 |
|
3473 case 3: |
|
3474 if (imm == 0) |
|
3475 func (stream, ", rrx"); |
|
3476 else |
|
3477 func (stream, ", ror #%u", imm); |
|
3478 } |
|
3479 } |
|
3480 break; |
|
3481 |
|
3482 case 'a': |
|
3483 { |
|
3484 unsigned int Rn = (given & 0x000f0000) >> 16; |
|
3485 unsigned int U = (given & 0x00800000) >> 23; |
|
3486 unsigned int op = (given & 0x00000f00) >> 8; |
|
3487 unsigned int i12 = (given & 0x00000fff); |
|
3488 unsigned int i8 = (given & 0x000000ff); |
|
3489 bfd_boolean writeback = FALSE, postind = FALSE; |
|
3490 int offset = 0; |
|
3491 |
|
3492 func (stream, "[%s", arm_regnames[Rn]); |
|
3493 if (U) /* 12-bit positive immediate offset */ |
|
3494 offset = i12; |
|
3495 else if (Rn == 15) /* 12-bit negative immediate offset */ |
|
3496 offset = -(int)i12; |
|
3497 else if (op == 0x0) /* shifted register offset */ |
|
3498 { |
|
3499 unsigned int Rm = (i8 & 0x0f); |
|
3500 unsigned int sh = (i8 & 0x30) >> 4; |
|
3501 func (stream, ", %s", arm_regnames[Rm]); |
|
3502 if (sh) |
|
3503 func (stream, ", lsl #%u", sh); |
|
3504 func (stream, "]"); |
|
3505 break; |
|
3506 } |
|
3507 else switch (op) |
|
3508 { |
|
3509 case 0xE: /* 8-bit positive immediate offset */ |
|
3510 offset = i8; |
|
3511 break; |
|
3512 |
|
3513 case 0xC: /* 8-bit negative immediate offset */ |
|
3514 offset = -i8; |
|
3515 break; |
|
3516 |
|
3517 case 0xF: /* 8-bit + preindex with wb */ |
|
3518 offset = i8; |
|
3519 writeback = TRUE; |
|
3520 break; |
|
3521 |
|
3522 case 0xD: /* 8-bit - preindex with wb */ |
|
3523 offset = -i8; |
|
3524 writeback = TRUE; |
|
3525 break; |
|
3526 |
|
3527 case 0xB: /* 8-bit + postindex */ |
|
3528 offset = i8; |
|
3529 postind = TRUE; |
|
3530 break; |
|
3531 |
|
3532 case 0x9: /* 8-bit - postindex */ |
|
3533 offset = -i8; |
|
3534 postind = TRUE; |
|
3535 break; |
|
3536 |
|
3537 default: |
|
3538 func (stream, ", <undefined>]"); |
|
3539 goto skip; |
|
3540 } |
|
3541 |
|
3542 if (postind) |
|
3543 func (stream, "], #%d", offset); |
|
3544 else |
|
3545 { |
|
3546 if (offset) |
|
3547 func (stream, ", #%d", offset); |
|
3548 func (stream, writeback ? "]!" : "]"); |
|
3549 } |
|
3550 |
|
3551 if (Rn == 15) |
|
3552 { |
|
3553 func (stream, "\t; "); |
|
3554 info->print_address_func (((pc + 4) & ~3) + offset, info); |
|
3555 } |
|
3556 } |
|
3557 skip: |
|
3558 break; |
|
3559 |
|
3560 case 'A': |
|
3561 { |
|
3562 unsigned int P = (given & 0x01000000) >> 24; |
|
3563 unsigned int U = (given & 0x00800000) >> 23; |
|
3564 unsigned int W = (given & 0x00400000) >> 21; |
|
3565 unsigned int Rn = (given & 0x000f0000) >> 16; |
|
3566 unsigned int off = (given & 0x000000ff); |
|
3567 |
|
3568 func (stream, "[%s", arm_regnames[Rn]); |
|
3569 if (P) |
|
3570 { |
|
3571 if (off || !U) |
|
3572 func (stream, ", #%c%u", U ? '+' : '-', off * 4); |
|
3573 func (stream, "]"); |
|
3574 if (W) |
|
3575 func (stream, "!"); |
|
3576 } |
|
3577 else |
|
3578 { |
|
3579 func (stream, "], "); |
|
3580 if (W) |
|
3581 func (stream, "#%c%u", U ? '+' : '-', off * 4); |
|
3582 else |
|
3583 func (stream, "{%u}", off); |
|
3584 } |
|
3585 } |
|
3586 break; |
|
3587 |
|
3588 case 'w': |
|
3589 { |
|
3590 unsigned int Sbit = (given & 0x01000000) >> 24; |
|
3591 unsigned int type = (given & 0x00600000) >> 21; |
|
3592 switch (type) |
|
3593 { |
|
3594 case 0: func (stream, Sbit ? "sb" : "b"); break; |
|
3595 case 1: func (stream, Sbit ? "sh" : "h"); break; |
|
3596 case 2: |
|
3597 if (Sbit) |
|
3598 func (stream, "??"); |
|
3599 break; |
|
3600 case 3: |
|
3601 func (stream, "??"); |
|
3602 break; |
|
3603 } |
|
3604 } |
|
3605 break; |
|
3606 |
|
3607 case 'm': |
|
3608 { |
|
3609 int started = 0; |
|
3610 int reg; |
|
3611 |
|
3612 func (stream, "{"); |
|
3613 for (reg = 0; reg < 16; reg++) |
|
3614 if ((given & (1 << reg)) != 0) |
|
3615 { |
|
3616 if (started) |
|
3617 func (stream, ", "); |
|
3618 started = 1; |
|
3619 func (stream, "%s", arm_regnames[reg]); |
|
3620 } |
|
3621 func (stream, "}"); |
|
3622 } |
|
3623 break; |
|
3624 |
|
3625 case 'E': |
|
3626 { |
|
3627 unsigned int msb = (given & 0x0000001f); |
|
3628 unsigned int lsb = 0; |
|
3629 lsb |= (given & 0x000000c0u) >> 6; |
|
3630 lsb |= (given & 0x00007000u) >> 10; |
|
3631 func (stream, "#%u, #%u", lsb, msb - lsb + 1); |
|
3632 } |
|
3633 break; |
|
3634 |
|
3635 case 'F': |
|
3636 { |
|
3637 unsigned int width = (given & 0x0000001f) + 1; |
|
3638 unsigned int lsb = 0; |
|
3639 lsb |= (given & 0x000000c0u) >> 6; |
|
3640 lsb |= (given & 0x00007000u) >> 10; |
|
3641 func (stream, "#%u, #%u", lsb, width); |
|
3642 } |
|
3643 break; |
|
3644 |
|
3645 case 'b': |
|
3646 { |
|
3647 unsigned int S = (given & 0x04000000u) >> 26; |
|
3648 unsigned int J1 = (given & 0x00002000u) >> 13; |
|
3649 unsigned int J2 = (given & 0x00000800u) >> 11; |
|
3650 int offset = 0; |
|
3651 |
|
3652 offset |= !S << 20; |
|
3653 offset |= J2 << 19; |
|
3654 offset |= J1 << 18; |
|
3655 offset |= (given & 0x003f0000) >> 4; |
|
3656 offset |= (given & 0x000007ff) << 1; |
|
3657 offset -= (1 << 20); |
|
3658 |
|
3659 info->print_address_func (pc + 4 + offset, info); |
|
3660 } |
|
3661 break; |
|
3662 |
|
3663 case 'B': |
|
3664 { |
|
3665 unsigned int S = (given & 0x04000000u) >> 26; |
|
3666 unsigned int I1 = (given & 0x00002000u) >> 13; |
|
3667 unsigned int I2 = (given & 0x00000800u) >> 11; |
|
3668 int offset = 0; |
|
3669 |
|
3670 offset |= !S << 24; |
|
3671 offset |= !(I1 ^ S) << 23; |
|
3672 offset |= !(I2 ^ S) << 22; |
|
3673 offset |= (given & 0x03ff0000u) >> 4; |
|
3674 offset |= (given & 0x000007ffu) << 1; |
|
3675 offset -= (1 << 24); |
|
3676 offset += pc + 4; |
|
3677 |
|
3678 /* BLX target addresses are always word aligned. */ |
|
3679 if ((given & 0x00001000u) == 0) |
|
3680 offset &= ~2u; |
|
3681 |
|
3682 info->print_address_func (offset, info); |
|
3683 } |
|
3684 break; |
|
3685 |
|
3686 case 's': |
|
3687 { |
|
3688 unsigned int shift = 0; |
|
3689 shift |= (given & 0x000000c0u) >> 6; |
|
3690 shift |= (given & 0x00007000u) >> 10; |
|
3691 if (given & 0x00200000u) |
|
3692 func (stream, ", asr #%u", shift); |
|
3693 else if (shift) |
|
3694 func (stream, ", lsl #%u", shift); |
|
3695 /* else print nothing - lsl #0 */ |
|
3696 } |
|
3697 break; |
|
3698 |
|
3699 case 'R': |
|
3700 { |
|
3701 unsigned int rot = (given & 0x00000030) >> 4; |
|
3702 if (rot) |
|
3703 func (stream, ", ror #%u", rot * 8); |
|
3704 } |
|
3705 break; |
|
3706 |
|
3707 case 'U': |
|
3708 switch (given & 0xf) |
|
3709 { |
|
3710 case 0xf: func(stream, "sy"); break; |
|
3711 case 0x7: func(stream, "un"); break; |
|
3712 case 0xe: func(stream, "st"); break; |
|
3713 case 0x6: func(stream, "unst"); break; |
|
3714 default: |
|
3715 func(stream, "#%d", (int)given & 0xf); |
|
3716 break; |
|
3717 } |
|
3718 break; |
|
3719 |
|
3720 case 'C': |
|
3721 if ((given & 0xff) == 0) |
|
3722 { |
|
3723 func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C'); |
|
3724 if (given & 0x800) |
|
3725 func (stream, "f"); |
|
3726 if (given & 0x400) |
|
3727 func (stream, "s"); |
|
3728 if (given & 0x200) |
|
3729 func (stream, "x"); |
|
3730 if (given & 0x100) |
|
3731 func (stream, "c"); |
|
3732 } |
|
3733 else |
|
3734 { |
|
3735 func (stream, psr_name (given & 0xff)); |
|
3736 } |
|
3737 break; |
|
3738 |
|
3739 case 'D': |
|
3740 if ((given & 0xff) == 0) |
|
3741 func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C'); |
|
3742 else |
|
3743 func (stream, psr_name (given & 0xff)); |
|
3744 break; |
|
3745 |
|
3746 case '0': case '1': case '2': case '3': case '4': |
|
3747 case '5': case '6': case '7': case '8': case '9': |
|
3748 { |
|
3749 int width; |
|
3750 unsigned long val; |
|
3751 |
|
3752 c = arm_decode_bitfield (c, given, &val, &width); |
|
3753 |
|
3754 switch (*c) |
|
3755 { |
|
3756 case 'd': func (stream, "%lu", val); break; |
|
3757 case 'W': func (stream, "%lu", val * 4); break; |
|
3758 case 'r': func (stream, "%s", arm_regnames[val]); break; |
|
3759 |
|
3760 case 'c': |
|
3761 func (stream, "%s", arm_conditional[val]); |
|
3762 break; |
|
3763 |
|
3764 case '\'': |
|
3765 c++; |
|
3766 if (val == ((1ul << width) - 1)) |
|
3767 func (stream, "%c", *c); |
|
3768 break; |
|
3769 |
|
3770 case '`': |
|
3771 c++; |
|
3772 if (val == 0) |
|
3773 func (stream, "%c", *c); |
|
3774 break; |
|
3775 |
|
3776 case '?': |
|
3777 func (stream, "%c", c[(1 << width) - (int)val]); |
|
3778 c += 1 << width; |
|
3779 break; |
|
3780 |
|
3781 default: |
|
3782 abort (); |
|
3783 } |
|
3784 } |
|
3785 break; |
|
3786 |
|
3787 default: |
|
3788 abort (); |
|
3789 } |
|
3790 } |
|
3791 return; |
|
3792 } |
|
3793 |
|
3794 /* No match. */ |
|
3795 abort (); |
|
3796 } |
|
3797 |
|
3798 /* Print data bytes on INFO->STREAM. */ |
|
3799 |
|
3800 static void |
|
3801 print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED, struct disassemble_info *info, |
|
3802 long given) |
|
3803 { |
|
3804 switch (info->bytes_per_chunk) |
|
3805 { |
|
3806 case 1: |
|
3807 info->fprintf_func (info->stream, ".byte\t0x%02lx", given); |
|
3808 break; |
|
3809 case 2: |
|
3810 info->fprintf_func (info->stream, ".short\t0x%04lx", given); |
|
3811 break; |
|
3812 case 4: |
|
3813 info->fprintf_func (info->stream, ".word\t0x%08lx", given); |
|
3814 break; |
|
3815 default: |
|
3816 abort (); |
|
3817 } |
|
3818 } |
|
3819 |
|
3820 /* Search back through the insn stream to determine if this instruction is |
|
3821 conditionally executed. */ |
|
3822 static void |
|
3823 find_ifthen_state (bfd_vma pc, struct disassemble_info *info, |
|
3824 bfd_boolean little) |
|
3825 { |
|
3826 unsigned char b[2]; |
|
3827 unsigned int insn; |
|
3828 int status; |
|
3829 /* COUNT is twice the number of instructions seen. It will be odd if we |
|
3830 just crossed an instruction boundary. */ |
|
3831 int count; |
|
3832 int it_count; |
|
3833 unsigned int seen_it; |
|
3834 bfd_vma addr; |
|
3835 |
|
3836 ifthen_address = pc; |
|
3837 ifthen_state = 0; |
|
3838 |
|
3839 addr = pc; |
|
3840 count = 1; |
|
3841 it_count = 0; |
|
3842 seen_it = 0; |
|
3843 /* Scan backwards looking for IT instructions, keeping track of where |
|
3844 instruction boundaries are. We don't know if something is actually an |
|
3845 IT instruction until we find a definite instruction boundary. */ |
|
3846 for (;;) |
|
3847 { |
|
3848 if (addr == 0 || info->symbol_at_address_func(addr, info)) |
|
3849 { |
|
3850 /* A symbol must be on an instruction boundary, and will not |
|
3851 be within an IT block. */ |
|
3852 if (seen_it && (count & 1)) |
|
3853 break; |
|
3854 |
|
3855 return; |
|
3856 } |
|
3857 addr -= 2; |
|
3858 status = info->read_memory_func (addr, (bfd_byte *)b, 2, info); |
|
3859 if (status) |
|
3860 return; |
|
3861 |
|
3862 if (little) |
|
3863 insn = (b[0]) | (b[1] << 8); |
|
3864 else |
|
3865 insn = (b[1]) | (b[0] << 8); |
|
3866 if (seen_it) |
|
3867 { |
|
3868 if ((insn & 0xf800) < 0xe800) |
|
3869 { |
|
3870 /* Addr + 2 is an instruction boundary. See if this matches |
|
3871 the expected boundary based on the position of the last |
|
3872 IT candidate. */ |
|
3873 if (count & 1) |
|
3874 break; |
|
3875 seen_it = 0; |
|
3876 } |
|
3877 } |
|
3878 if ((insn & 0xff00) == 0xbf00 && (insn & 0xf) != 0) |
|
3879 { |
|
3880 /* This could be an IT instruction. */ |
|
3881 seen_it = insn; |
|
3882 it_count = count >> 1; |
|
3883 } |
|
3884 if ((insn & 0xf800) >= 0xe800) |
|
3885 count++; |
|
3886 else |
|
3887 count = (count + 2) | 1; |
|
3888 /* IT blocks contain at most 4 instructions. */ |
|
3889 if (count >= 8 && !seen_it) |
|
3890 return; |
|
3891 } |
|
3892 /* We found an IT instruction. */ |
|
3893 ifthen_state = (seen_it & 0xe0) | ((seen_it << it_count) & 0x1f); |
|
3894 if ((ifthen_state & 0xf) == 0) |
|
3895 ifthen_state = 0; |
|
3896 } |
|
3897 |
|
3898 /* NOTE: There are no checks in these routines that |
|
3899 the relevant number of data bytes exist. */ |
|
3900 |
|
3901 int |
|
3902 print_insn_arm (bfd_vma pc, struct disassemble_info *info) |
|
3903 { |
|
3904 unsigned char b[4]; |
|
3905 long given; |
|
3906 int status; |
|
3907 int is_thumb = FALSE; |
|
3908 int is_data = FALSE; |
|
3909 unsigned int size = 4; |
|
3910 void (*printer) (bfd_vma, struct disassemble_info *, long); |
|
3911 #if 0 |
|
3912 bfd_boolean found = FALSE; |
|
3913 |
|
3914 if (info->disassembler_options) |
|
3915 { |
|
3916 parse_disassembler_options (info->disassembler_options); |
|
3917 |
|
3918 /* To avoid repeated parsing of these options, we remove them here. */ |
|
3919 info->disassembler_options = NULL; |
|
3920 } |
|
3921 |
|
3922 /* First check the full symtab for a mapping symbol, even if there |
|
3923 are no usable non-mapping symbols for this address. */ |
|
3924 if (info->symtab != NULL |
|
3925 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) |
|
3926 { |
|
3927 bfd_vma addr; |
|
3928 int n; |
|
3929 int last_sym = -1; |
|
3930 enum map_type type = MAP_ARM; |
|
3931 |
|
3932 if (pc <= last_mapping_addr) |
|
3933 last_mapping_sym = -1; |
|
3934 is_thumb = (last_type == MAP_THUMB); |
|
3935 found = FALSE; |
|
3936 /* Start scanning at the start of the function, or wherever |
|
3937 we finished last time. */ |
|
3938 n = info->symtab_pos + 1; |
|
3939 if (n < last_mapping_sym) |
|
3940 n = last_mapping_sym; |
|
3941 |
|
3942 /* Scan up to the location being disassembled. */ |
|
3943 for (; n < info->symtab_size; n++) |
|
3944 { |
|
3945 addr = bfd_asymbol_value (info->symtab[n]); |
|
3946 if (addr > pc) |
|
3947 break; |
|
3948 if ((info->section == NULL |
|
3949 || info->section == info->symtab[n]->section) |
|
3950 && get_sym_code_type (info, n, &type)) |
|
3951 { |
|
3952 last_sym = n; |
|
3953 found = TRUE; |
|
3954 } |
|
3955 } |
|
3956 |
|
3957 if (!found) |
|
3958 { |
|
3959 n = info->symtab_pos; |
|
3960 if (n < last_mapping_sym - 1) |
|
3961 n = last_mapping_sym - 1; |
|
3962 |
|
3963 /* No mapping symbol found at this address. Look backwards |
|
3964 for a preceeding one. */ |
|
3965 for (; n >= 0; n--) |
|
3966 { |
|
3967 if (get_sym_code_type (info, n, &type)) |
|
3968 { |
|
3969 last_sym = n; |
|
3970 found = TRUE; |
|
3971 break; |
|
3972 } |
|
3973 } |
|
3974 } |
|
3975 |
|
3976 last_mapping_sym = last_sym; |
|
3977 last_type = type; |
|
3978 is_thumb = (last_type == MAP_THUMB); |
|
3979 is_data = (last_type == MAP_DATA); |
|
3980 |
|
3981 /* Look a little bit ahead to see if we should print out |
|
3982 two or four bytes of data. If there's a symbol, |
|
3983 mapping or otherwise, after two bytes then don't |
|
3984 print more. */ |
|
3985 if (is_data) |
|
3986 { |
|
3987 size = 4 - (pc & 3); |
|
3988 for (n = last_sym + 1; n < info->symtab_size; n++) |
|
3989 { |
|
3990 addr = bfd_asymbol_value (info->symtab[n]); |
|
3991 if (addr > pc) |
|
3992 { |
|
3993 if (addr - pc < size) |
|
3994 size = addr - pc; |
|
3995 break; |
|
3996 } |
|
3997 } |
|
3998 /* If the next symbol is after three bytes, we need to |
|
3999 print only part of the data, so that we can use either |
|
4000 .byte or .short. */ |
|
4001 if (size == 3) |
|
4002 size = (pc & 1) ? 1 : 2; |
|
4003 } |
|
4004 } |
|
4005 |
|
4006 if (info->symbols != NULL) |
|
4007 { |
|
4008 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour) |
|
4009 { |
|
4010 coff_symbol_type * cs; |
|
4011 |
|
4012 cs = coffsymbol (*info->symbols); |
|
4013 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT |
|
4014 || cs->native->u.syment.n_sclass == C_THUMBSTAT |
|
4015 || cs->native->u.syment.n_sclass == C_THUMBLABEL |
|
4016 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC |
|
4017 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC); |
|
4018 } |
|
4019 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour |
|
4020 && !found) |
|
4021 { |
|
4022 /* If no mapping symbol has been found then fall back to the type |
|
4023 of the function symbol. */ |
|
4024 elf_symbol_type * es; |
|
4025 unsigned int type; |
|
4026 |
|
4027 es = *(elf_symbol_type **)(info->symbols); |
|
4028 type = ELF_ST_TYPE (es->internal_elf_sym.st_info); |
|
4029 |
|
4030 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); |
|
4031 } |
|
4032 } |
|
4033 #else |
|
4034 int little; |
|
4035 |
|
4036 little = (info->endian == BFD_ENDIAN_LITTLE); |
|
4037 is_thumb |= (pc & 1); |
|
4038 pc &= ~(bfd_vma)1; |
|
4039 #endif |
|
4040 |
|
4041 if (force_thumb) |
|
4042 is_thumb = TRUE; |
|
4043 |
|
4044 info->bytes_per_line = 4; |
|
4045 |
|
4046 if (is_data) |
|
4047 { |
|
4048 int i; |
|
4049 |
|
4050 /* size was already set above. */ |
|
4051 info->bytes_per_chunk = size; |
|
4052 printer = print_insn_data; |
|
4053 |
|
4054 status = info->read_memory_func (pc, (bfd_byte *)b, size, info); |
|
4055 given = 0; |
|
4056 if (little) |
|
4057 for (i = size - 1; i >= 0; i--) |
|
4058 given = b[i] | (given << 8); |
|
4059 else |
|
4060 for (i = 0; i < (int) size; i++) |
|
4061 given = b[i] | (given << 8); |
|
4062 } |
|
4063 else if (!is_thumb) |
|
4064 { |
|
4065 /* In ARM mode endianness is a straightforward issue: the instruction |
|
4066 is four bytes long and is either ordered 0123 or 3210. */ |
|
4067 printer = print_insn_arm_internal; |
|
4068 info->bytes_per_chunk = 4; |
|
4069 size = 4; |
|
4070 |
|
4071 status = info->read_memory_func (pc, (bfd_byte *)b, 4, info); |
|
4072 if (little) |
|
4073 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); |
|
4074 else |
|
4075 given = (b[3]) | (b[2] << 8) | (b[1] << 16) | (b[0] << 24); |
|
4076 } |
|
4077 else |
|
4078 { |
|
4079 /* In Thumb mode we have the additional wrinkle of two |
|
4080 instruction lengths. Fortunately, the bits that determine |
|
4081 the length of the current instruction are always to be found |
|
4082 in the first two bytes. */ |
|
4083 printer = print_insn_thumb16; |
|
4084 info->bytes_per_chunk = 2; |
|
4085 size = 2; |
|
4086 |
|
4087 status = info->read_memory_func (pc, (bfd_byte *)b, 2, info); |
|
4088 if (little) |
|
4089 given = (b[0]) | (b[1] << 8); |
|
4090 else |
|
4091 given = (b[1]) | (b[0] << 8); |
|
4092 |
|
4093 if (!status) |
|
4094 { |
|
4095 /* These bit patterns signal a four-byte Thumb |
|
4096 instruction. */ |
|
4097 if ((given & 0xF800) == 0xF800 |
|
4098 || (given & 0xF800) == 0xF000 |
|
4099 || (given & 0xF800) == 0xE800) |
|
4100 { |
|
4101 status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info); |
|
4102 if (little) |
|
4103 given = (b[0]) | (b[1] << 8) | (given << 16); |
|
4104 else |
|
4105 given = (b[1]) | (b[0] << 8) | (given << 16); |
|
4106 |
|
4107 printer = print_insn_thumb32; |
|
4108 size = 4; |
|
4109 } |
|
4110 } |
|
4111 |
|
4112 if (ifthen_address != pc) |
|
4113 find_ifthen_state(pc, info, little); |
|
4114 |
|
4115 if (ifthen_state) |
|
4116 { |
|
4117 if ((ifthen_state & 0xf) == 0x8) |
|
4118 ifthen_next_state = 0; |
|
4119 else |
|
4120 ifthen_next_state = (ifthen_state & 0xe0) |
|
4121 | ((ifthen_state & 0xf) << 1); |
|
4122 } |
|
4123 } |
|
4124 |
|
4125 if (status) |
|
4126 { |
|
4127 info->memory_error_func (status, pc, info); |
|
4128 return -1; |
|
4129 } |
|
4130 if (info->flags & INSN_HAS_RELOC) |
|
4131 /* If the instruction has a reloc associated with it, then |
|
4132 the offset field in the instruction will actually be the |
|
4133 addend for the reloc. (We are using REL type relocs). |
|
4134 In such cases, we can ignore the pc when computing |
|
4135 addresses, since the addend is not currently pc-relative. */ |
|
4136 pc = 0; |
|
4137 |
|
4138 printer (pc, info, given); |
|
4139 |
|
4140 if (is_thumb) |
|
4141 { |
|
4142 ifthen_state = ifthen_next_state; |
|
4143 ifthen_address += size; |
|
4144 } |
|
4145 return size; |
|
4146 } |
|
4147 |
|
4148 void |
|
4149 print_arm_disassembler_options (FILE *stream) |
|
4150 { |
|
4151 int i; |
|
4152 |
|
4153 fprintf (stream, _("\n\ |
|
4154 The following ARM specific disassembler options are supported for use with\n\ |
|
4155 the -M switch:\n")); |
|
4156 |
|
4157 for (i = NUM_ARM_REGNAMES; i--;) |
|
4158 fprintf (stream, " reg-names-%s %*c%s\n", |
|
4159 regnames[i].name, |
|
4160 (int)(14 - strlen (regnames[i].name)), ' ', |
|
4161 regnames[i].description); |
|
4162 |
|
4163 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n"); |
|
4164 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n"); |
|
4165 } |