1 /* Instruction printing code for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modification by James G. Smith (jsmith@cygnus.co.uk)
6
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 #include "sysdep.h"
24
25 #include "dis-asm.h"
26 #include "opcode/arm.h"
27 #include "opintl.h"
28 #include "safe-ctype.h"
29
30 /* FIXME: This shouldn't be done here. */
31 #include "coff/internal.h"
32 #include "libcoff.h"
33 #include "elf-bfd.h"
34 #include "elf/internal.h"
35 #include "elf/arm.h"
36
37 /* FIXME: Belongs in global header. */
38 #ifndef strneq
39 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
40 #endif
41
42 #ifndef NUM_ELEM
43 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
44 #endif
45
46 struct opcode32
47 {
48 unsigned long arch; /* Architecture defining this insn. */
49 unsigned long value, mask; /* Recognise insn if (op&mask)==value. */
50 const char *assembler; /* How to disassemble this insn. */
51 };
52
53 struct opcode16
54 {
55 unsigned long arch; /* Architecture defining this insn. */
56 unsigned short value, mask; /* Recognise insn if (op&mask)==value. */
57 const char *assembler; /* How to disassemble this insn. */
58 };
59
60 /* print_insn_coprocessor recognizes the following format control codes:
61
62 %% %
63
64 %c print condition code (always bits 28-31)
65 %A print address for ldc/stc/ldf/stf instruction
66 %I print cirrus signed shift immediate: bits 0..3|4..6
67 %F print the COUNT field of a LFM/SFM instruction.
68 %P print floating point precision in arithmetic insn
69 %Q print floating point precision in ldf/stf insn
70 %R print floating point rounding mode
71
72 %<bitfield>r print as an ARM register
73 %<bitfield>d print the bitfield in decimal
74 %<bitfield>x print the bitfield in hex
75 %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
76 %<bitfield>f print a floating point constant if >7 else a
77 floating point register
78 %<bitfield>w print as an iWMMXt width field - [bhwd]ss/us
79 %<bitfield>g print as an iWMMXt 64-bit register
80 %<bitfield>G print as an iWMMXt general purpose or control register
81
82 %<code>y print a single precision VFP reg.
83 Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
84 %<code>z print a double precision VFP reg
85 Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
86 %<bitnum>'c print specified char iff bit is one
87 %<bitnum>`c print specified char iff bit is zero
88 %<bitnum>?ab print a if bit is one else print b
89
90 %L print as an iWMMXt N/M width field.
91 %Z print the Immediate of a WSHUFH instruction.
92 %l like 'A' except use byte offsets for 'B' & 'H'
93 versions. */
94
95 /* Common coprocessor opcodes shared between Arm and Thumb-2. */
96
97 static const struct opcode32 coprocessor_opcodes[] =
98 {
99 /* XScale instructions. */
100 {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
101 {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
102 {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
103 {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
104 {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
105
106 /* Intel Wireless MMX technology instructions. */
107 #define FIRST_IWMMXT_INSN 0x0e130130
108 #define IWMMXT_INSN_COUNT 47
109 {ARM_CEXT_IWMMXT, 0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"},
110 {ARM_CEXT_XSCALE, 0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"},
111 {ARM_CEXT_XSCALE, 0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"},
112 {ARM_CEXT_XSCALE, 0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"},
113 {ARM_CEXT_XSCALE, 0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"},
114 {ARM_CEXT_XSCALE, 0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"},
115 {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"},
116 {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"},
117 {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"},
118 {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"},
119 {ARM_CEXT_XSCALE, 0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"},
120 {ARM_CEXT_XSCALE, 0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"},
121 {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"},
122 {ARM_CEXT_XSCALE, 0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"},
123 {ARM_CEXT_XSCALE, 0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"},
124 {ARM_CEXT_XSCALE, 0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"},
125 {ARM_CEXT_XSCALE, 0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"},
126 {ARM_CEXT_XSCALE, 0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"},
127 {ARM_CEXT_XSCALE, 0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"},
128 {ARM_CEXT_XSCALE, 0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"},
129 {ARM_CEXT_XSCALE, 0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"},
130 {ARM_CEXT_XSCALE, 0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
131 {ARM_CEXT_XSCALE, 0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"},
132 {ARM_CEXT_XSCALE, 0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"},
133 {ARM_CEXT_XSCALE, 0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"},
134 {ARM_CEXT_XSCALE, 0x0e800100, 0x0fd00ff0, "wmadd%21?su%c\t%12-15g, %16-19g, %0-3g"},
135 {ARM_CEXT_XSCALE, 0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
136 {ARM_CEXT_XSCALE, 0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
137 {ARM_CEXT_XSCALE, 0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%c\t%12-15g, %16-19g, %0-3g"},
138 {ARM_CEXT_XSCALE, 0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"},
139 {ARM_CEXT_XSCALE, 0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"},
140 {ARM_CEXT_XSCALE, 0x0e300040, 0x0f300ff0, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
141 {ARM_CEXT_XSCALE, 0x0e300148, 0x0f300ffc, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
142 {ARM_CEXT_XSCALE, 0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"},
143 {ARM_CEXT_XSCALE, 0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"},
144 {ARM_CEXT_XSCALE, 0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
145 {ARM_CEXT_XSCALE, 0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
146 {ARM_CEXT_XSCALE, 0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
147 {ARM_CEXT_XSCALE, 0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
148 {ARM_CEXT_XSCALE, 0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
149 {ARM_CEXT_XSCALE, 0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
150 {ARM_CEXT_XSCALE, 0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"},
151 {ARM_CEXT_XSCALE, 0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"},
152 {ARM_CEXT_XSCALE, 0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"},
153 {ARM_CEXT_XSCALE, 0x0e0000c0, 0x0f100fff, "wunpckeh%21?su%22-23w%c\t%12-15g, %16-19g"},
154 {ARM_CEXT_XSCALE, 0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"},
155 {ARM_CEXT_XSCALE, 0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"},
156 {ARM_CEXT_XSCALE, 0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"},
157 {ARM_CEXT_XSCALE, 0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"},
158
159 /* Floating point coprocessor (FPA) instructions */
160 {FPU_FPA_EXT_V1, 0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
161 {FPU_FPA_EXT_V1, 0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
162 {FPU_FPA_EXT_V1, 0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
163 {FPU_FPA_EXT_V1, 0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
164 {FPU_FPA_EXT_V1, 0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
165 {FPU_FPA_EXT_V1, 0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
166 {FPU_FPA_EXT_V1, 0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
167 {FPU_FPA_EXT_V1, 0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
168 {FPU_FPA_EXT_V1, 0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
169 {FPU_FPA_EXT_V1, 0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
170 {FPU_FPA_EXT_V1, 0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
171 {FPU_FPA_EXT_V1, 0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
172 {FPU_FPA_EXT_V1, 0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
173 {FPU_FPA_EXT_V1, 0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
174 {FPU_FPA_EXT_V1, 0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
175 {FPU_FPA_EXT_V1, 0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
176 {FPU_FPA_EXT_V1, 0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
177 {FPU_FPA_EXT_V1, 0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
178 {FPU_FPA_EXT_V1, 0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
179 {FPU_FPA_EXT_V1, 0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
180 {FPU_FPA_EXT_V1, 0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
181 {FPU_FPA_EXT_V1, 0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
182 {FPU_FPA_EXT_V1, 0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
183 {FPU_FPA_EXT_V1, 0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
184 {FPU_FPA_EXT_V1, 0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
185 {FPU_FPA_EXT_V1, 0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
186 {FPU_FPA_EXT_V1, 0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
187 {FPU_FPA_EXT_V1, 0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
188 {FPU_FPA_EXT_V1, 0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
189 {FPU_FPA_EXT_V1, 0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
190 {FPU_FPA_EXT_V1, 0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
191 {FPU_FPA_EXT_V1, 0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
192 {FPU_FPA_EXT_V1, 0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
193 {FPU_FPA_EXT_V1, 0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
194 {FPU_FPA_EXT_V1, 0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
195 {FPU_FPA_EXT_V1, 0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
196 {FPU_FPA_EXT_V1, 0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
197 {FPU_FPA_EXT_V1, 0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
198 {FPU_FPA_EXT_V1, 0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
199 {FPU_FPA_EXT_V1, 0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
200 {FPU_FPA_EXT_V1, 0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
201 {FPU_FPA_EXT_V2, 0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
202 {FPU_FPA_EXT_V2, 0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
203
204 /* Floating point coprocessor (VFP) instructions */
205 {FPU_VFP_EXT_V1, 0x0eb00bc0, 0x0fff0ff0, "fabsd%c\t%1z, %0z"},
206 {FPU_VFP_EXT_V1xD, 0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%1y, %0y"},
207 {FPU_VFP_EXT_V1, 0x0e300b00, 0x0ff00ff0, "faddd%c\t%1z, %2z, %0z"},
208 {FPU_VFP_EXT_V1xD, 0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %0y"},
209 {FPU_VFP_EXT_V1, 0x0eb40b40, 0x0fff0f70, "fcmp%7'ed%c\t%1z, %0z"},
210 {FPU_VFP_EXT_V1xD, 0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%1y, %0y"},
211 {FPU_VFP_EXT_V1, 0x0eb50b40, 0x0fff0f70, "fcmp%7'ezd%c\t%1z"},
212 {FPU_VFP_EXT_V1xD, 0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%1y"},
213 {FPU_VFP_EXT_V1, 0x0eb00b40, 0x0fff0ff0, "fcpyd%c\t%1z, %0z"},
214 {FPU_VFP_EXT_V1xD, 0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%1y, %0y"},
215 {FPU_VFP_EXT_V1, 0x0eb70ac0, 0x0fff0fd0, "fcvtds%c\t%1z, %0y"},
216 {FPU_VFP_EXT_V1, 0x0eb70bc0, 0x0fbf0ff0, "fcvtsd%c\t%1y, %0z"},
217 {FPU_VFP_EXT_V1, 0x0e800b00, 0x0ff00ff0, "fdivd%c\t%1z, %2z, %0z"},
218 {FPU_VFP_EXT_V1xD, 0x0e800a00, 0x0fb00f50, "fdivs%c\t%1y, %2y, %0y"},
219 {FPU_VFP_EXT_V1, 0x0d100b00, 0x0f700f00, "fldd%c\t%1z, %A"},
220 {FPU_VFP_EXT_V1xD, 0x0c900b00, 0x0fd00f00, "fldmia%0?xd%c\t%16-19r%21'!, %3z"},
221 {FPU_VFP_EXT_V1xD, 0x0d300b00, 0x0ff00f00, "fldmdb%0?xd%c\t%16-19r!, %3z"},
222 {FPU_VFP_EXT_V1xD, 0x0d100a00, 0x0f300f00, "flds%c\t%1y, %A"},
223 {FPU_VFP_EXT_V1xD, 0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %3y"},
224 {FPU_VFP_EXT_V1xD, 0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %3y"},
225 {FPU_VFP_EXT_V1, 0x0e000b00, 0x0ff00ff0, "fmacd%c\t%1z, %2z, %0z"},
226 {FPU_VFP_EXT_V1xD, 0x0e000a00, 0x0fb00f50, "fmacs%c\t%1y, %2y, %0y"},
227 {FPU_VFP_EXT_V1, 0x0e200b10, 0x0ff00fff, "fmdhr%c\t%2z, %12-15r"},
228 {FPU_VFP_EXT_V1, 0x0e000b10, 0x0ff00fff, "fmdlr%c\t%2z, %12-15r"},
229 {FPU_VFP_EXT_V2, 0x0c400b10, 0x0ff00ff0, "fmdrr%c\t%0z, %12-15r, %16-19r"},
230 {FPU_VFP_EXT_V1, 0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %2z"},
231 {FPU_VFP_EXT_V1, 0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %2z"},
232 {FPU_VFP_EXT_V1, 0x0c500b10, 0x0ff00ff0, "fmrrd%c\t%12-15r, %16-19r, %0z"},
233 {FPU_VFP_EXT_V2, 0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %4y"},
234 {FPU_VFP_EXT_V1xD, 0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %2y"},
235 {FPU_VFP_EXT_V1xD, 0x0ef1fa10, 0x0fffffff, "fmstat%c"},
236 {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
237 {FPU_VFP_EXT_V1xD, 0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
238 {FPU_VFP_EXT_V1xD, 0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
239 {FPU_VFP_EXT_V1xD, 0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
240 {FPU_VFP_EXT_V1xD, 0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
241 {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def 0x%16-19x>"},
242 {FPU_VFP_EXT_V1, 0x0e100b00, 0x0ff00ff0, "fmscd%c\t%1z, %2z, %0z"},
243 {FPU_VFP_EXT_V1xD, 0x0e100a00, 0x0fb00f50, "fmscs%c\t%1y, %2y, %0y"},
244 {FPU_VFP_EXT_V1xD, 0x0e000a10, 0x0ff00f7f, "fmsr%c\t%2y, %12-15r"},
245 {FPU_VFP_EXT_V2, 0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%12-15r, %16-19r, %4y"},
246 {FPU_VFP_EXT_V1, 0x0e200b00, 0x0ff00ff0, "fmuld%c\t%1z, %2z, %0z"},
247 {FPU_VFP_EXT_V1xD, 0x0e200a00, 0x0fb00f50, "fmuls%c\t%1y, %2y, %0y"},
248 {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
249 {FPU_VFP_EXT_V1xD, 0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
250 {FPU_VFP_EXT_V1xD, 0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
251 {FPU_VFP_EXT_V1xD, 0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
252 {FPU_VFP_EXT_V1xD, 0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
253 {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def 0x%16-19x>, %12-15r"},
254 {FPU_VFP_EXT_V1, 0x0eb10b40, 0x0fff0ff0, "fnegd%c\t%1z, %0z"},
255 {FPU_VFP_EXT_V1xD, 0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%1y, %0y"},
256 {FPU_VFP_EXT_V1, 0x0e000b40, 0x0ff00ff0, "fnmacd%c\t%1z, %2z, %0z"},
257 {FPU_VFP_EXT_V1xD, 0x0e000a40, 0x0fb00f50, "fnmacs%c\t%1y, %2y, %0y"},
258 {FPU_VFP_EXT_V1, 0x0e100b40, 0x0ff00ff0, "fnmscd%c\t%1z, %2z, %0z"},
259 {FPU_VFP_EXT_V1xD, 0x0e100a40, 0x0fb00f50, "fnmscs%c\t%1y, %2y, %0y"},
260 {FPU_VFP_EXT_V1, 0x0e200b40, 0x0ff00ff0, "fnmuld%c\t%1z, %2z, %0z"},
261 {FPU_VFP_EXT_V1xD, 0x0e200a40, 0x0fb00f50, "fnmuls%c\t%1y, %2y, %0y"},
262 {FPU_VFP_EXT_V1, 0x0eb80bc0, 0x0fff0fd0, "fsitod%c\t%1z, %0y"},
263 {FPU_VFP_EXT_V1xD, 0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%1y, %0y"},
264 {FPU_VFP_EXT_V1, 0x0eb10bc0, 0x0fff0ff0, "fsqrtd%c\t%1z, %0z"},
265 {FPU_VFP_EXT_V1xD, 0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%1y, %0y"},
266 {FPU_VFP_EXT_V1, 0x0d000b00, 0x0f700f00, "fstd%c\t%1z, %A"},
267 {FPU_VFP_EXT_V1xD, 0x0c800b00, 0x0fd00f00, "fstmia%0?xd%c\t%16-19r%21'!, %3z"},
268 {FPU_VFP_EXT_V1xD, 0x0d200b00, 0x0ff00f00, "fstmdb%0?xd%c\t%16-19r!, %3z"},
269 {FPU_VFP_EXT_V1xD, 0x0d000a00, 0x0f300f00, "fsts%c\t%1y, %A"},
270 {FPU_VFP_EXT_V1xD, 0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %3y"},
271 {FPU_VFP_EXT_V1xD, 0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %3y"},
272 {FPU_VFP_EXT_V1, 0x0e300b40, 0x0ff00ff0, "fsubd%c\t%1z, %2z, %0z"},
273 {FPU_VFP_EXT_V1xD, 0x0e300a40, 0x0fb00f50, "fsubs%c\t%1y, %2y, %0y"},
274 {FPU_VFP_EXT_V1, 0x0ebc0b40, 0x0fbe0f70, "fto%16?sui%7'zd%c\t%1y, %0z"},
275 {FPU_VFP_EXT_V1xD, 0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%1y, %0y"},
276 {FPU_VFP_EXT_V1, 0x0eb80b40, 0x0fff0fd0, "fuitod%c\t%1z, %0y"},
277 {FPU_VFP_EXT_V1xD, 0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%1y, %0y"},
278
279 /* Cirrus coprocessor instructions. */
280 {ARM_CEXT_MAVERICK, 0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
281 {ARM_CEXT_MAVERICK, 0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
282 {ARM_CEXT_MAVERICK, 0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
283 {ARM_CEXT_MAVERICK, 0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
284 {ARM_CEXT_MAVERICK, 0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
285 {ARM_CEXT_MAVERICK, 0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
286 {ARM_CEXT_MAVERICK, 0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
287 {ARM_CEXT_MAVERICK, 0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
288 {ARM_CEXT_MAVERICK, 0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
289 {ARM_CEXT_MAVERICK, 0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
290 {ARM_CEXT_MAVERICK, 0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
291 {ARM_CEXT_MAVERICK, 0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
292 {ARM_CEXT_MAVERICK, 0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
293 {ARM_CEXT_MAVERICK, 0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
294 {ARM_CEXT_MAVERICK, 0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
295 {ARM_CEXT_MAVERICK, 0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
296 {ARM_CEXT_MAVERICK, 0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
297 {ARM_CEXT_MAVERICK, 0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
298 {ARM_CEXT_MAVERICK, 0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
299 {ARM_CEXT_MAVERICK, 0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
300 {ARM_CEXT_MAVERICK, 0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
301 {ARM_CEXT_MAVERICK, 0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
302 {ARM_CEXT_MAVERICK, 0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
303 {ARM_CEXT_MAVERICK, 0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
304 {ARM_CEXT_MAVERICK, 0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
305 {ARM_CEXT_MAVERICK, 0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
306 {ARM_CEXT_MAVERICK, 0x0e200440, 0x0ff00fff, "cfmval32%c\tmvax%12-15d, mvfx%16-19d"},
307 {ARM_CEXT_MAVERICK, 0x0e100440, 0x0ff00fff, "cfmv32al%c\tmvfx%12-15d, mvax%16-19d"},
308 {ARM_CEXT_MAVERICK, 0x0e200460, 0x0ff00fff, "cfmvam32%c\tmvax%12-15d, mvfx%16-19d"},
309 {ARM_CEXT_MAVERICK, 0x0e100460, 0x0ff00fff, "cfmv32am%c\tmvfx%12-15d, mvax%16-19d"},
310 {ARM_CEXT_MAVERICK, 0x0e200480, 0x0ff00fff, "cfmvah32%c\tmvax%12-15d, mvfx%16-19d"},
311 {ARM_CEXT_MAVERICK, 0x0e100480, 0x0ff00fff, "cfmv32ah%c\tmvfx%12-15d, mvax%16-19d"},
312 {ARM_CEXT_MAVERICK, 0x0e2004a0, 0x0ff00fff, "cfmva32%c\tmvax%12-15d, mvfx%16-19d"},
313 {ARM_CEXT_MAVERICK, 0x0e1004a0, 0x0ff00fff, "cfmv32a%c\tmvfx%12-15d, mvax%16-19d"},
314 {ARM_CEXT_MAVERICK, 0x0e2004c0, 0x0ff00fff, "cfmva64%c\tmvax%12-15d, mvdx%16-19d"},
315 {ARM_CEXT_MAVERICK, 0x0e1004c0, 0x0ff00fff, "cfmv64a%c\tmvdx%12-15d, mvax%16-19d"},
316 {ARM_CEXT_MAVERICK, 0x0e2004e0, 0x0fff0fff, "cfmvsc32%c\tdspsc, mvdx%12-15d"},
317 {ARM_CEXT_MAVERICK, 0x0e1004e0, 0x0fff0fff, "cfmv32sc%c\tmvdx%12-15d, dspsc"},
318 {ARM_CEXT_MAVERICK, 0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
319 {ARM_CEXT_MAVERICK, 0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
320 {ARM_CEXT_MAVERICK, 0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
321 {ARM_CEXT_MAVERICK, 0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
322 {ARM_CEXT_MAVERICK, 0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
323 {ARM_CEXT_MAVERICK, 0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
324 {ARM_CEXT_MAVERICK, 0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
325 {ARM_CEXT_MAVERICK, 0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
326 {ARM_CEXT_MAVERICK, 0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
327 {ARM_CEXT_MAVERICK, 0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
328 {ARM_CEXT_MAVERICK, 0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
329 {ARM_CEXT_MAVERICK, 0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
330 {ARM_CEXT_MAVERICK, 0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
331 {ARM_CEXT_MAVERICK, 0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
332 {ARM_CEXT_MAVERICK, 0x0e000500, 0x0ff00f10, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
333 {ARM_CEXT_MAVERICK, 0x0e200500, 0x0ff00f10, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
334 {ARM_CEXT_MAVERICK, 0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
335 {ARM_CEXT_MAVERICK, 0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
336 {ARM_CEXT_MAVERICK, 0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
337 {ARM_CEXT_MAVERICK, 0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
338 {ARM_CEXT_MAVERICK, 0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
339 {ARM_CEXT_MAVERICK, 0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
340 {ARM_CEXT_MAVERICK, 0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
341 {ARM_CEXT_MAVERICK, 0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
342 {ARM_CEXT_MAVERICK, 0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
343 {ARM_CEXT_MAVERICK, 0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
344 {ARM_CEXT_MAVERICK, 0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
345 {ARM_CEXT_MAVERICK, 0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
346 {ARM_CEXT_MAVERICK, 0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
347 {ARM_CEXT_MAVERICK, 0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
348 {ARM_CEXT_MAVERICK, 0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
349 {ARM_CEXT_MAVERICK, 0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
350 {ARM_CEXT_MAVERICK, 0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
351 {ARM_CEXT_MAVERICK, 0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
352 {ARM_CEXT_MAVERICK, 0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
353 {ARM_CEXT_MAVERICK, 0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
354 {ARM_CEXT_MAVERICK, 0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
355 {ARM_CEXT_MAVERICK, 0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
356 {ARM_CEXT_MAVERICK, 0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
357 {ARM_CEXT_MAVERICK, 0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
358 {ARM_CEXT_MAVERICK, 0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
359 {ARM_CEXT_MAVERICK, 0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
360 {ARM_CEXT_MAVERICK, 0x0e000600, 0x0ff00f10, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
361 {ARM_CEXT_MAVERICK, 0x0e100600, 0x0ff00f10, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
362 {ARM_CEXT_MAVERICK, 0x0e200600, 0x0ff00f10, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
363 {ARM_CEXT_MAVERICK, 0x0e300600, 0x0ff00f10, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
364
365 /* Generic coprocessor instructions */
366 {ARM_EXT_V2, 0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
367 {ARM_EXT_V2, 0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
368 {ARM_EXT_V2, 0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
369 {ARM_EXT_V2, 0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
370 {ARM_EXT_V2, 0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
371 {ARM_EXT_V2, 0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
372 {ARM_EXT_V2, 0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
373
374 /* V6 coprocessor instructions */
375 {ARM_EXT_V6, 0xfc500000, 0xfff00000, "mrrc2\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
376 {ARM_EXT_V6, 0xfc400000, 0xfff00000, "mcrr2\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
377
378 /* V5 coprocessor instructions */
379 {ARM_EXT_V5, 0xfc100000, 0xfe100000, "ldc2%22'l\t%8-11d, cr%12-15d, %A"},
380 {ARM_EXT_V5, 0xfc000000, 0xfe100000, "stc2%22'l\t%8-11d, cr%12-15d, %A"},
381 {ARM_EXT_V5, 0xfe000000, 0xff000010, "cdp2\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
382 {ARM_EXT_V5, 0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
383 {ARM_EXT_V5, 0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
384 {0, 0, 0, 0}
385 };
386
387 /* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially
388 ordered: they must be searched linearly from the top to obtain a correct
389 match. */
390
391 /* print_insn_arm recognizes the following format control codes:
392
393 %% %
394
395 %a print address for ldr/str instruction
396 %s print address for ldr/str halfword/signextend instruction
397 %b print branch destination
398 %c print condition code (always bits 28-31)
399 %m print register mask for ldm/stm instruction
400 %o print operand2 (immediate or register + shift)
401 %p print 'p' iff bits 12-15 are 15
402 %t print 't' iff bit 21 set and bit 24 clear
403 %B print arm BLX(1) destination
404 %C print the PSR sub type.
405 %U print barrier type.
406 %P print address for pli instruction.
407
408 %<bitfield>r print as an ARM register
409 %<bitfield>d print the bitfield in decimal
410 %<bitfield>W print the bitfield plus one in decimal
411 %<bitfield>x print the bitfield in hex
412 %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
413
414 %<bitnum>'c print specified char iff bit is one
415 %<bitnum>`c print specified char iff bit is zero
416 %<bitnum>?ab print a if bit is one else print b
417
418 %e print arm SMI operand (bits 0..7,8..19).
419 %E print the LSB and WIDTH fields of a BFI or BFC instruction.
420 %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
421
422 static const struct opcode32 arm_opcodes[] =
423 {
424 /* ARM instructions. */
425 {ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
426 {ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
427 {ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
428 {ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
429 {ARM_EXT_V2S, 0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
430 {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
431 {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
432
433 /* V7 instructions. */
434 {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"},
435 {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"},
436 {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"},
437 {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"},
438 {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"},
439
440 /* ARM V6T2 instructions. */
441 {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"},
442 {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"},
443 {ARM_EXT_V6T2, 0x00600090, 0x0ff000f0, "mls%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
444 {ARM_EXT_V6T2, 0x006000b0, 0x0f7000f0, "str%cht\t%12-15r, %s"},
445 {ARM_EXT_V6T2, 0x00300090, 0x0f300090, "ldr%c%6's%5?hbt\t%12-15r, %s"},
446 {ARM_EXT_V6T2, 0x03000000, 0x0ff00000, "movw%c\t%12-15r, %V"},
447 {ARM_EXT_V6T2, 0x03400000, 0x0ff00000, "movt%c\t%12-15r, %V"},
448 {ARM_EXT_V6T2, 0x03ff0f30, 0x0fff0ff0, "rbit%c\t%12-15r, %0-3r"},
449 {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"},
450
451 /* ARM V6Z instructions. */
452 {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"},
453
454 /* ARM V6K instructions. */
455 {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"},
456 {ARM_EXT_V6K, 0x01d00f9f, 0x0ff00fff, "ldrexb%c\t%12-15r, [%16-19r]"},
457 {ARM_EXT_V6K, 0x01b00f9f, 0x0ff00fff, "ldrexd%c\t%12-15r, [%16-19r]"},
458 {ARM_EXT_V6K, 0x01f00f9f, 0x0ff00fff, "ldrexh%c\t%12-15r, [%16-19r]"},
459 {ARM_EXT_V6K, 0x01c00f90, 0x0ff00ff0, "strexb%c\t%12-15r, %0-3r, [%16-19r]"},
460 {ARM_EXT_V6K, 0x01a00f90, 0x0ff00ff0, "strexd%c\t%12-15r, %0-3r, [%16-19r]"},
461 {ARM_EXT_V6K, 0x01e00f90, 0x0ff00ff0, "strexh%c\t%12-15r, %0-3r, [%16-19r]"},
462
463 /* ARM V6K NOP hints. */
464 {ARM_EXT_V6K, 0x0320f001, 0x0fffffff, "yield%c"},
465 {ARM_EXT_V6K, 0x0320f002, 0x0fffffff, "wfe%c"},
466 {ARM_EXT_V6K, 0x0320f003, 0x0fffffff, "wfi%c"},
467 {ARM_EXT_V6K, 0x0320f004, 0x0fffffff, "sev%c"},
468 {ARM_EXT_V6K, 0x0320f000, 0x0fffff00, "nop%c\t{%0-7d}"},
469
470 /* ARM V6 instructions. */
471 {ARM_EXT_V6, 0xf1080000, 0xfffdfe3f, "cpsie\t%8'a%7'i%6'f"},
472 {ARM_EXT_V6, 0xf1080000, 0xfffdfe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"},
473 {ARM_EXT_V6, 0xf10C0000, 0xfffdfe3f, "cpsid\t%8'a%7'i%6'f"},
474 {ARM_EXT_V6, 0xf10C0000, 0xfffdfe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"},
475 {ARM_EXT_V6, 0xf1000000, 0xfff1fe20, "cps\t#%0-4d"},
476 {ARM_EXT_V6, 0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"},
477 {ARM_EXT_V6, 0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, LSL #%7-11d"},
478 {ARM_EXT_V6, 0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #32"},
479 {ARM_EXT_V6, 0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #%7-11d"},
480 {ARM_EXT_V6, 0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"},
481 {ARM_EXT_V6, 0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"},
482 {ARM_EXT_V6, 0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"},
483 {ARM_EXT_V6, 0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"},
484 {ARM_EXT_V6, 0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"},
485 {ARM_EXT_V6, 0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"},
486 {ARM_EXT_V6, 0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"},
487 {ARM_EXT_V6, 0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"},
488 {ARM_EXT_V6, 0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"},
489 {ARM_EXT_V6, 0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"},
490 {ARM_EXT_V6, 0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"},
491 {ARM_EXT_V6, 0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"},
492 {ARM_EXT_V6, 0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"},
493 {ARM_EXT_V6, 0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"},
494 {ARM_EXT_V6, 0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"},
495 {ARM_EXT_V6, 0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"},
496 {ARM_EXT_V6, 0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"},
497 {ARM_EXT_V6, 0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"},
498 {ARM_EXT_V6, 0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"},
499 {ARM_EXT_V6, 0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"},
500 {ARM_EXT_V6, 0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"},
501 {ARM_EXT_V6, 0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"},
502 {ARM_EXT_V6, 0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"},
503 {ARM_EXT_V6, 0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"},
504 {ARM_EXT_V6, 0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"},
505 {ARM_EXT_V6, 0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"},
506 {ARM_EXT_V6, 0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"},
507 {ARM_EXT_V6, 0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"},
508 {ARM_EXT_V6, 0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"},
509 {ARM_EXT_V6, 0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"},
510 {ARM_EXT_V6, 0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"},
511 {ARM_EXT_V6, 0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"},
512 {ARM_EXT_V6, 0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"},
513 {ARM_EXT_V6, 0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"},
514 {ARM_EXT_V6, 0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"},
515 {ARM_EXT_V6, 0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"},
516 {ARM_EXT_V6, 0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"},
517 {ARM_EXT_V6, 0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"},
518 {ARM_EXT_V6, 0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"},
519 {ARM_EXT_V6, 0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"},
520 {ARM_EXT_V6, 0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"},
521 {ARM_EXT_V6, 0x06bf0070, 0x0fff0ff0, "sxth%c %12-15r,%0-3r"},
522 {ARM_EXT_V6, 0x06bf0470, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #8"},
523 {ARM_EXT_V6, 0x06bf0870, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #16"},
524 {ARM_EXT_V6, 0x06bf0c70, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #24"},
525 {ARM_EXT_V6, 0x068f0070, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r"},
526 {ARM_EXT_V6, 0x068f0470, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #8"},
527 {ARM_EXT_V6, 0x068f0870, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #16"},
528 {ARM_EXT_V6, 0x068f0c70, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #24"},
529 {ARM_EXT_V6, 0x06af0070, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r"},
530 {ARM_EXT_V6, 0x06af0470, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #8"},
531 {ARM_EXT_V6, 0x06af0870, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #16"},
532 {ARM_EXT_V6, 0x06af0c70, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #24"},
533 {ARM_EXT_V6, 0x06ff0070, 0x0fff0ff0, "uxth%c %12-15r,%0-3r"},
534 {ARM_EXT_V6, 0x06ff0470, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #8"},
535 {ARM_EXT_V6, 0x06ff0870, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #16"},
536 {ARM_EXT_V6, 0x06ff0c70, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #24"},
537 {ARM_EXT_V6, 0x06cf0070, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r"},
538 {ARM_EXT_V6, 0x06cf0470, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #8"},
539 {ARM_EXT_V6, 0x06cf0870, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #16"},
540 {ARM_EXT_V6, 0x06cf0c70, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #24"},
541 {ARM_EXT_V6, 0x06ef0070, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r"},
542 {ARM_EXT_V6, 0x06ef0470, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #8"},
543 {ARM_EXT_V6, 0x06ef0870, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #16"},
544 {ARM_EXT_V6, 0x06ef0c70, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #24"},
545 {ARM_EXT_V6, 0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"},
546 {ARM_EXT_V6, 0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
547 {ARM_EXT_V6, 0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
548 {ARM_EXT_V6, 0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
549 {ARM_EXT_V6, 0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"},
550 {ARM_EXT_V6, 0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
551 {ARM_EXT_V6, 0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
552 {ARM_EXT_V6, 0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
553 {ARM_EXT_V6, 0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"},
554 {ARM_EXT_V6, 0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
555 {ARM_EXT_V6, 0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
556 {ARM_EXT_V6, 0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
557 {ARM_EXT_V6, 0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"},
558 {ARM_EXT_V6, 0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
559 {ARM_EXT_V6, 0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
560 {ARM_EXT_V6, 0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
561 {ARM_EXT_V6, 0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"},
562 {ARM_EXT_V6, 0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
563 {ARM_EXT_V6, 0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
564 {ARM_EXT_V6, 0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
565 {ARM_EXT_V6, 0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"},
566 {ARM_EXT_V6, 0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
567 {ARM_EXT_V6, 0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
568 {ARM_EXT_V6, 0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
569 {ARM_EXT_V6, 0x06800fb0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"},
570 {ARM_EXT_V6, 0xf1010000, 0xfffffc00, "setend\t%9?ble"},
571 {ARM_EXT_V6, 0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"},
572 {ARM_EXT_V6, 0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"},
573 {ARM_EXT_V6, 0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
574 {ARM_EXT_V6, 0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
575 {ARM_EXT_V6, 0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
576 {ARM_EXT_V6, 0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
577 {ARM_EXT_V6, 0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"},
578 {ARM_EXT_V6, 0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
579 {ARM_EXT_V6, 0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
580 {ARM_EXT_V6, 0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t#%0-4d%21'!"},
581 {ARM_EXT_V6, 0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"},
582 {ARM_EXT_V6, 0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, LSL #%7-11d"},
583 {ARM_EXT_V6, 0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, ASR #%7-11d"},
584 {ARM_EXT_V6, 0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"},
585 {ARM_EXT_V6, 0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"},
586 {ARM_EXT_V6, 0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
587 {ARM_EXT_V6, 0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"},
588 {ARM_EXT_V6, 0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
589 {ARM_EXT_V6, 0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"},
590 {ARM_EXT_V6, 0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, LSL #%7-11d"},
591 {ARM_EXT_V6, 0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, ASR #%7-11d"},
592 {ARM_EXT_V6, 0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"},
593
594 /* V5J instruction. */
595 {ARM_EXT_V5J, 0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
596
597 /* V5 Instructions. */
598 {ARM_EXT_V5, 0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
599 {ARM_EXT_V5, 0xfa000000, 0xfe000000, "blx\t%B"},
600 {ARM_EXT_V5, 0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
601 {ARM_EXT_V5, 0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
602
603 /* V5E "El Segundo" Instructions. */
604 {ARM_EXT_V5E, 0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
605 {ARM_EXT_V5E, 0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
606 {ARM_EXT_V5E, 0xf450f000, 0xfc70f000, "pld\t%a"},
607 {ARM_EXT_V5ExP, 0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
608 {ARM_EXT_V5ExP, 0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
609 {ARM_EXT_V5ExP, 0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
610 {ARM_EXT_V5ExP, 0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
611
612 {ARM_EXT_V5ExP, 0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
613 {ARM_EXT_V5ExP, 0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
614
615 {ARM_EXT_V5ExP, 0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
616 {ARM_EXT_V5ExP, 0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
617 {ARM_EXT_V5ExP, 0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
618 {ARM_EXT_V5ExP, 0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
619
620 {ARM_EXT_V5ExP, 0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
621 {ARM_EXT_V5ExP, 0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
622 {ARM_EXT_V5ExP, 0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
623 {ARM_EXT_V5ExP, 0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
624
625 {ARM_EXT_V5ExP, 0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
626 {ARM_EXT_V5ExP, 0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
627
628 {ARM_EXT_V5ExP, 0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
629 {ARM_EXT_V5ExP, 0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
630 {ARM_EXT_V5ExP, 0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
631 {ARM_EXT_V5ExP, 0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
632
633 /* ARM Instructions. */
634 {ARM_EXT_V1, 0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
635 {ARM_EXT_V1, 0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
636 {ARM_EXT_V1, 0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
637 {ARM_EXT_V1, 0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
638 {ARM_EXT_V1, 0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
639 {ARM_EXT_V1, 0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
640 {ARM_EXT_V1, 0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
641 {ARM_EXT_V1, 0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
642 {ARM_EXT_V1, 0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
643 {ARM_EXT_V1, 0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
644 {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
645 {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
646 {ARM_EXT_V1, 0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
647 {ARM_EXT_V1, 0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
648 {ARM_EXT_V1, 0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
649 {ARM_EXT_V1, 0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
650 {ARM_EXT_V1, 0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
651 {ARM_EXT_V1, 0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
652 {ARM_EXT_V1, 0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
653 {ARM_EXT_V1, 0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
654 {ARM_EXT_V1, 0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
655 {ARM_EXT_V1, 0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
656 {ARM_EXT_V1, 0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
657 {ARM_EXT_V1, 0x06000010, 0x0e000010, "undefined"},
658 {ARM_EXT_V1, 0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
659 {ARM_EXT_V1, 0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
660 {ARM_EXT_V1, 0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
661 {ARM_EXT_V1, 0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
662 {ARM_EXT_V1, 0x0f000000, 0x0f000000, "svc%c\t%0-23x"},
663
664 /* The rest. */
665 {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined instruction %0-31x"},
666 {0, 0x00000000, 0x00000000, 0}
667 };
668
669 /* print_insn_thumb16 recognizes the following format control codes:
670
671 %S print Thumb register (bits 3..5 as high number if bit 6 set)
672 %D print Thumb register (bits 0..2 as high number if bit 7 set)
673 %<bitfield>I print bitfield as a signed decimal
674 (top bit of range being the sign bit)
675 %N print Thumb register mask (with LR)
676 %O print Thumb register mask (with PC)
677 %M print Thumb register mask
678 %b print CZB's 6-bit unsigned branch destination
679 %s print Thumb right-shift immediate (6..10; 0 == 32).
680 %<bitfield>r print bitfield as an ARM register
681 %<bitfield>d print bitfield as a decimal
682 %<bitfield>H print (bitfield * 2) as a decimal
683 %<bitfield>W print (bitfield * 4) as a decimal
684 %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
685 %<bitfield>B print Thumb branch destination (signed displacement)
686 %<bitfield>c print bitfield as a condition code
687 %<bitnum>'c print specified char iff bit is one
688 %<bitnum>?ab print a if bit is one else print b. */
689
690 static const struct opcode16 thumb_opcodes[] =
691 {
692 /* Thumb instructions. */
693
694 /* ARM V6K no-argument instructions. */
695 {ARM_EXT_V6K, 0xbf00, 0xffff, "nop"},
696 {ARM_EXT_V6K, 0xbf10, 0xffff, "yield"},
697 {ARM_EXT_V6K, 0xbf20, 0xffff, "wfe"},
698 {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi"},
699 {ARM_EXT_V6K, 0xbf40, 0xffff, "sev"},
700 {ARM_EXT_V6K, 0xbf00, 0xff0f, "nop\t{%4-7d}"},
701
702 /* ARM V6T2 instructions. */
703 {ARM_EXT_V6T2, 0xb900, 0xfd00, "cbnz\t%0-2r, %b"},
704 {ARM_EXT_V6T2, 0xb100, 0xfd00, "cbz\t%0-2r, %b"},
705 {ARM_EXT_V6T2, 0xbf08, 0xff0f, "it\t%4-7c"},
706 {ARM_EXT_V6T2, 0xbf14, 0xff17, "it%3?te\t%4-7c"},
707 {ARM_EXT_V6T2, 0xbf04, 0xff17, "it%3?et\t%4-7c"},
708 {ARM_EXT_V6T2, 0xbf12, 0xff13, "it%3?te%2?te\t%4-7c"},
709 {ARM_EXT_V6T2, 0xbf02, 0xff13, "it%3?et%2?et\t%4-7c"},
710 {ARM_EXT_V6T2, 0xbf11, 0xff11, "it%3?te%2?te%1?te\t%4-7c"},
711 {ARM_EXT_V6T2, 0xbf01, 0xff11, "it%3?et%2?et%1?et\t%4-7c"},
712
713 /* ARM V6. */
714 {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f"},
715 {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f"},
716 {ARM_EXT_V6, 0x4600, 0xffc0, "mov\t%0-2r, %3-5r"},
717 {ARM_EXT_V6, 0xba00, 0xffc0, "rev\t%0-2r, %3-5r"},
718 {ARM_EXT_V6, 0xba40, 0xffc0, "rev16\t%0-2r, %3-5r"},
719 {ARM_EXT_V6, 0xbac0, 0xffc0, "revsh\t%0-2r, %3-5r"},
720 {ARM_EXT_V6, 0xb650, 0xfff7, "setend\t%3?ble"},
721 {ARM_EXT_V6, 0xb200, 0xffc0, "sxth\t%0-2r, %3-5r"},
722 {ARM_EXT_V6, 0xb240, 0xffc0, "sxtb\t%0-2r, %3-5r"},
723 {ARM_EXT_V6, 0xb280, 0xffc0, "uxth\t%0-2r, %3-5r"},
724 {ARM_EXT_V6, 0xb2c0, 0xffc0, "uxtb\t%0-2r, %3-5r"},
725
726 /* ARM V5 ISA extends Thumb. */
727 {ARM_EXT_V5T, 0xbe00, 0xff00, "bkpt\t%0-7x"},
728 /* This is BLX(2). BLX(1) is a 32-bit instruction. */
729 {ARM_EXT_V5T, 0x4780, 0xff87, "blx\t%3-6r"}, /* note: 4 bit register number. */
730 /* ARM V4T ISA (Thumb v1). */
731 {ARM_EXT_V4T, 0x46C0, 0xFFFF, "nop\t\t\t(mov r8, r8)"},
732 /* Format 4. */
733 {ARM_EXT_V4T, 0x4000, 0xFFC0, "ands\t%0-2r, %3-5r"},
734 {ARM_EXT_V4T, 0x4040, 0xFFC0, "eors\t%0-2r, %3-5r"},
735 {ARM_EXT_V4T, 0x4080, 0xFFC0, "lsls\t%0-2r, %3-5r"},
736 {ARM_EXT_V4T, 0x40C0, 0xFFC0, "lsrs\t%0-2r, %3-5r"},
737 {ARM_EXT_V4T, 0x4100, 0xFFC0, "asrs\t%0-2r, %3-5r"},
738 {ARM_EXT_V4T, 0x4140, 0xFFC0, "adcs\t%0-2r, %3-5r"},
739 {ARM_EXT_V4T, 0x4180, 0xFFC0, "sbcs\t%0-2r, %3-5r"},
740 {ARM_EXT_V4T, 0x41C0, 0xFFC0, "rors\t%0-2r, %3-5r"},
741 {ARM_EXT_V4T, 0x4200, 0xFFC0, "tst\t%0-2r, %3-5r"},
742 {ARM_EXT_V4T, 0x4240, 0xFFC0, "negs\t%0-2r, %3-5r"},
743 {ARM_EXT_V4T, 0x4280, 0xFFC0, "cmp\t%0-2r, %3-5r"},
744 {ARM_EXT_V4T, 0x42C0, 0xFFC0, "cmn\t%0-2r, %3-5r"},
745 {ARM_EXT_V4T, 0x4300, 0xFFC0, "orrs\t%0-2r, %3-5r"},
746 {ARM_EXT_V4T, 0x4340, 0xFFC0, "muls\t%0-2r, %3-5r"},
747 {ARM_EXT_V4T, 0x4380, 0xFFC0, "bics\t%0-2r, %3-5r"},
748 {ARM_EXT_V4T, 0x43C0, 0xFFC0, "mvns\t%0-2r, %3-5r"},
749 /* format 13 */
750 {ARM_EXT_V4T, 0xB000, 0xFF80, "add\tsp, #%0-6W"},
751 {ARM_EXT_V4T, 0xB080, 0xFF80, "sub\tsp, #%0-6W"},
752 /* format 5 */
753 {ARM_EXT_V4T, 0x4700, 0xFF80, "bx\t%S"},
754 {ARM_EXT_V4T, 0x4400, 0xFF00, "add\t%D, %S"},
755 {ARM_EXT_V4T, 0x4500, 0xFF00, "cmp\t%D, %S"},
756 {ARM_EXT_V4T, 0x4600, 0xFF00, "mov\t%D, %S"},
757 /* format 14 */
758 {ARM_EXT_V4T, 0xB400, 0xFE00, "push\t%N"},
759 {ARM_EXT_V4T, 0xBC00, 0xFE00, "pop\t%O"},
760 /* format 2 */
761 {ARM_EXT_V4T, 0x1800, 0xFE00, "adds\t%0-2r, %3-5r, %6-8r"},
762 {ARM_EXT_V4T, 0x1A00, 0xFE00, "subs\t%0-2r, %3-5r, %6-8r"},
763 {ARM_EXT_V4T, 0x1C00, 0xFE00, "adds\t%0-2r, %3-5r, #%6-8d"},
764 {ARM_EXT_V4T, 0x1E00, 0xFE00, "subs\t%0-2r, %3-5r, #%6-8d"},
765 /* format 8 */
766 {ARM_EXT_V4T, 0x5200, 0xFE00, "strh\t%0-2r, [%3-5r, %6-8r]"},
767 {ARM_EXT_V4T, 0x5A00, 0xFE00, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
768 {ARM_EXT_V4T, 0x5600, 0xF600, "ldrs%11?hb\t%0-2r, [%3-5r, %6-8r]"},
769 /* format 7 */
770 {ARM_EXT_V4T, 0x5000, 0xFA00, "str%10'b\t%0-2r, [%3-5r, %6-8r]"},
771 {ARM_EXT_V4T, 0x5800, 0xFA00, "ldr%10'b\t%0-2r, [%3-5r, %6-8r]"},
772 /* format 1 */
773 {ARM_EXT_V4T, 0x0000, 0xF800, "lsls\t%0-2r, %3-5r, #%6-10d"},
774 {ARM_EXT_V4T, 0x0800, 0xF800, "lsrs\t%0-2r, %3-5r, %s"},
775 {ARM_EXT_V4T, 0x1000, 0xF800, "asrs\t%0-2r, %3-5r, %s"},
776 /* format 3 */
777 {ARM_EXT_V4T, 0x2000, 0xF800, "movs\t%8-10r, #%0-7d"},
778 {ARM_EXT_V4T, 0x2800, 0xF800, "cmp\t%8-10r, #%0-7d"},
779 {ARM_EXT_V4T, 0x3000, 0xF800, "adds\t%8-10r, #%0-7d"},
780 {ARM_EXT_V4T, 0x3800, 0xF800, "subs\t%8-10r, #%0-7d"},
781 /* format 6 */
782 {ARM_EXT_V4T, 0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
783 /* format 9 */
784 {ARM_EXT_V4T, 0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
785 {ARM_EXT_V4T, 0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
786 {ARM_EXT_V4T, 0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
787 {ARM_EXT_V4T, 0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
788 /* format 10 */
789 {ARM_EXT_V4T, 0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
790 {ARM_EXT_V4T, 0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
791 /* format 11 */
792 {ARM_EXT_V4T, 0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
793 {ARM_EXT_V4T, 0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
794 /* format 12 */
795 {ARM_EXT_V4T, 0xA000, 0xF800, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
796 {ARM_EXT_V4T, 0xA800, 0xF800, "add\t%8-10r, sp, #%0-7W"},
797 /* format 15 */
798 {ARM_EXT_V4T, 0xC000, 0xF800, "stmia\t%8-10r!, %M"},
799 {ARM_EXT_V4T, 0xC800, 0xF800, "ldmia\t%8-10r!, %M"},
800 /* format 17 */
801 {ARM_EXT_V4T, 0xDF00, 0xFF00, "svc\t%0-7d"},
802 /* format 16 */
803 {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B"},
804 /* format 18 */
805 {ARM_EXT_V4T, 0xE000, 0xF800, "b.n\t%0-10B"},
806
807 /* The E800 .. FFFF range is unconditionally redirected to the
808 32-bit table, because even in pre-V6T2 ISAs, BL and BLX(1) pairs
809 are processed via that table. Thus, we can never encounter a
810 bare "second half of BL/BLX(1)" instruction here. */
811 {ARM_EXT_V1, 0x0000, 0x0000, "undefined"},
812 {0, 0, 0, 0}
813 };
814
815 /* Thumb32 opcodes use the same table structure as the ARM opcodes.
816 We adopt the convention that hw1 is the high 16 bits of .value and
817 .mask, hw2 the low 16 bits.
818
819 print_insn_thumb32 recognizes the following format control codes:
820
821 %% %
822
823 %I print a 12-bit immediate from hw1[10],hw2[14:12,7:0]
824 %M print a modified 12-bit immediate (same location)
825 %J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
826 %K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
827 %S print a possibly-shifted Rm
828
829 %a print the address of a plain load/store
830 %w print the width and signedness of a core load/store
831 %m print register mask for ldm/stm
832
833 %E print the lsb and width fields of a bfc/bfi instruction
834 %F print the lsb and width fields of a sbfx/ubfx instruction
835 %b print a conditional branch offset
836 %B print an unconditional branch offset
837 %s print the shift field of an SSAT instruction
838 %R print the rotation field of an SXT instruction
839 %U print barrier type.
840 %P print address for pli instruction.
841
842 %<bitfield>d print bitfield in decimal
843 %<bitfield>W print bitfield*4 in decimal
844 %<bitfield>r print bitfield as an ARM register
845 %<bitfield>c print bitfield as a condition code
846
847 %<bitnum>'c print "c" iff bit is one
848 %<bitnum>`c print "c" iff bit is zero
849 %<bitnum>?ab print "a" if bit is one, else "b"
850
851 With one exception at the bottom (done because BL and BLX(1) need
852 to come dead last), this table was machine-sorted first in
853 decreasing order of number of bits set in the mask, then in
854 increasing numeric order of mask, then in increasing numeric order
855 of opcode. This order is not the clearest for a human reader, but
856 is guaranteed never to catch a special-case bit pattern with a more
857 general mask, which is important, because this instruction encoding
858 makes heavy use of special-case bit patterns. */
859 static const struct opcode32 thumb32_opcodes[] =
860 {
861 /* V7 instructions. */
862 {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli\t%a"},
863 {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg\t#%0-3d"},
864 {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb\t%U"},
865 {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb\t%U"},
866 {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb\t%U"},
867 {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv\t%8-11r, %16-19r, %0-3r"},
868 {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv\t%8-11r, %16-19r, %0-3r"},
869
870 /* Instructions defined in the basic V6T2 set. */
871 {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop.w"},
872 {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield.w"},
873 {ARM_EXT_V6T2, 0xf3af8002, 0xffffffff, "wfe.w"},
874 {ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi.w"},
875 {ARM_EXT_V6T2, 0xf3af9004, 0xffffffff, "sev.w"},
876 {ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop.w\t{%0-7d}"},
877
878 {ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex"},
879 {ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f"},
880 {ARM_EXT_V6T2, 0xf3af8600, 0xffffff1f, "cpsid.w\t%7'a%6'i%5'f"},
881 {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj\t%16-19r"},
882 {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb\t%16-19r%21'!"},
883 {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia\t%16-19r%21'!"},
884 {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs\t%8-11r, %D"},
885 {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d"},
886 {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb\t[%16-19r, %0-3r]"},
887 {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r, lsl #1]"},
888 {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d"},
889 {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d"},
890 {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs\tpc, lr, #%0-7d"},
891 {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr\t%C, %16-19r"},
892 {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex\t%12-15r, [%16-19r]"},
893 {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb\t%12-15r, [%16-19r]"},
894 {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb\t#%0-4d%21'!"},
895 {ARM_EXT_V6T2, 0xe980c000, 0xffd0ffe0, "srsia\t#%0-4d%21'!"},
896 {ARM_EXT_V6T2, 0xfa0ff080, 0xfffff0c0, "sxth.w\t%8-11r, %0-3r%R"},
897 {ARM_EXT_V6T2, 0xfa1ff080, 0xfffff0c0, "uxth.w\t%8-11r, %0-3r%R"},
898 {ARM_EXT_V6T2, 0xfa2ff080, 0xfffff0c0, "sxtb16\t%8-11r, %0-3r%R"},
899 {ARM_EXT_V6T2, 0xfa3ff080, 0xfffff0c0, "uxtb16\t%8-11r, %0-3r%R"},
900 {ARM_EXT_V6T2, 0xfa4ff080, 0xfffff0c0, "sxtb.w\t%8-11r, %0-3r%R"},
901 {ARM_EXT_V6T2, 0xfa5ff080, 0xfffff0c0, "uxtb.w\t%8-11r, %0-3r%R"},
902 {ARM_EXT_V6T2, 0xe8400000, 0xfff000ff, "strex\t%8-11r, %12-15r, [%16-19r]"},
903 {ARM_EXT_V6T2, 0xe8d0007f, 0xfff000ff, "ldrexd\t%12-15r, %8-11r, [%16-19r]"},
904 {ARM_EXT_V6T2, 0xfa80f000, 0xfff0f0f0, "sadd8\t%8-11r, %16-19r, %0-3r"},
905 {ARM_EXT_V6T2, 0xfa80f010, 0xfff0f0f0, "qadd8\t%8-11r, %16-19r, %0-3r"},
906 {ARM_EXT_V6T2, 0xfa80f020, 0xfff0f0f0, "shadd8\t%8-11r, %16-19r, %0-3r"},
907 {ARM_EXT_V6T2, 0xfa80f040, 0xfff0f0f0, "uadd8\t%8-11r, %16-19r, %0-3r"},
908 {ARM_EXT_V6T2, 0xfa80f050, 0xfff0f0f0, "uqadd8\t%8-11r, %16-19r, %0-3r"},
909 {ARM_EXT_V6T2, 0xfa80f060, 0xfff0f0f0, "uhadd8\t%8-11r, %16-19r, %0-3r"},
910 {ARM_EXT_V6T2, 0xfa80f080, 0xfff0f0f0, "qadd\t%8-11r, %0-3r, %16-19r"},
911 {ARM_EXT_V6T2, 0xfa80f090, 0xfff0f0f0, "qdadd\t%8-11r, %0-3r, %16-19r"},
912 {ARM_EXT_V6T2, 0xfa80f0a0, 0xfff0f0f0, "qsub\t%8-11r, %0-3r, %16-19r"},
913 {ARM_EXT_V6T2, 0xfa80f0b0, 0xfff0f0f0, "qdsub\t%8-11r, %0-3r, %16-19r"},
914 {ARM_EXT_V6T2, 0xfa90f000, 0xfff0f0f0, "sadd16\t%8-11r, %16-19r, %0-3r"},
915 {ARM_EXT_V6T2, 0xfa90f010, 0xfff0f0f0, "qadd16\t%8-11r, %16-19r, %0-3r"},
916 {ARM_EXT_V6T2, 0xfa90f020, 0xfff0f0f0, "shadd16\t%8-11r, %16-19r, %0-3r"},
917 {ARM_EXT_V6T2, 0xfa90f040, 0xfff0f0f0, "uadd16\t%8-11r, %16-19r, %0-3r"},
918 {ARM_EXT_V6T2, 0xfa90f050, 0xfff0f0f0, "uqadd16\t%8-11r, %16-19r, %0-3r"},
919 {ARM_EXT_V6T2, 0xfa90f060, 0xfff0f0f0, "uhadd16\t%8-11r, %16-19r, %0-3r"},
920 {ARM_EXT_V6T2, 0xfa90f080, 0xfff0f0f0, "rev.w\t%8-11r, %16-19r"},
921 {ARM_EXT_V6T2, 0xfa90f090, 0xfff0f0f0, "rev16.w\t%8-11r, %16-19r"},
922 {ARM_EXT_V6T2, 0xfa90f0a0, 0xfff0f0f0, "rbit\t%8-11r, %16-19r"},
923 {ARM_EXT_V6T2, 0xfa90f0b0, 0xfff0f0f0, "revsh.w\t%8-11r, %16-19r"},
924 {ARM_EXT_V6T2, 0xfaa0f000, 0xfff0f0f0, "saddsubx\t%8-11r, %16-19r, %0-3r"},
925 {ARM_EXT_V6T2, 0xfaa0f010, 0xfff0f0f0, "qaddsubx\t%8-11r, %16-19r, %0-3r"},
926 {ARM_EXT_V6T2, 0xfaa0f020, 0xfff0f0f0, "shaddsubx\t%8-11r, %16-19r, %0-3r"},
927 {ARM_EXT_V6T2, 0xfaa0f040, 0xfff0f0f0, "uaddsubx\t%8-11r, %16-19r, %0-3r"},
928 {ARM_EXT_V6T2, 0xfaa0f050, 0xfff0f0f0, "uqaddsubx\t%8-11r, %16-19r, %0-3r"},
929 {ARM_EXT_V6T2, 0xfaa0f060, 0xfff0f0f0, "uhaddsubx\t%8-11r, %16-19r, %0-3r"},
930 {ARM_EXT_V6T2, 0xfaa0f080, 0xfff0f0f0, "sel\t%8-11r, %16-19r, %0-3r"},
931 {ARM_EXT_V6T2, 0xfab0f080, 0xfff0f0f0, "clz\t%8-11r, %16-19r"},
932 {ARM_EXT_V6T2, 0xfac0f000, 0xfff0f0f0, "ssub8\t%8-11r, %16-19r, %0-3r"},
933 {ARM_EXT_V6T2, 0xfac0f010, 0xfff0f0f0, "qsub8\t%8-11r, %16-19r, %0-3r"},
934 {ARM_EXT_V6T2, 0xfac0f020, 0xfff0f0f0, "shsub8\t%8-11r, %16-19r, %0-3r"},
935 {ARM_EXT_V6T2, 0xfac0f040, 0xfff0f0f0, "usub8\t%8-11r, %16-19r, %0-3r"},
936 {ARM_EXT_V6T2, 0xfac0f050, 0xfff0f0f0, "uqsub8\t%8-11r, %16-19r, %0-3r"},
937 {ARM_EXT_V6T2, 0xfac0f060, 0xfff0f0f0, "uhsub8\t%8-11r, %16-19r, %0-3r"},
938 {ARM_EXT_V6T2, 0xfad0f000, 0xfff0f0f0, "ssub16\t%8-11r, %16-19r, %0-3r"},
939 {ARM_EXT_V6T2, 0xfad0f010, 0xfff0f0f0, "qsub16\t%8-11r, %16-19r, %0-3r"},
940 {ARM_EXT_V6T2, 0xfad0f020, 0xfff0f0f0, "shsub16\t%8-11r, %16-19r, %0-3r"},
941 {ARM_EXT_V6T2, 0xfad0f040, 0xfff0f0f0, "usub16\t%8-11r, %16-19r, %0-3r"},
942 {ARM_EXT_V6T2, 0xfad0f050, 0xfff0f0f0, "uqsub16\t%8-11r, %16-19r, %0-3r"},
943 {ARM_EXT_V6T2, 0xfad0f060, 0xfff0f0f0, "uhsub16\t%8-11r, %16-19r, %0-3r"},
944 {ARM_EXT_V6T2, 0xfae0f000, 0xfff0f0f0, "ssubaddx\t%8-11r, %16-19r, %0-3r"},
945 {ARM_EXT_V6T2, 0xfae0f010, 0xfff0f0f0, "qsubaddx\t%8-11r, %16-19r, %0-3r"},
946 {ARM_EXT_V6T2, 0xfae0f020, 0xfff0f0f0, "shsubaddx\t%8-11r, %16-19r, %0-3r"},
947 {ARM_EXT_V6T2, 0xfae0f040, 0xfff0f0f0, "usubaddx\t%8-11r, %16-19r, %0-3r"},
948 {ARM_EXT_V6T2, 0xfae0f050, 0xfff0f0f0, "uqsubaddx\t%8-11r, %16-19r, %0-3r"},
949 {ARM_EXT_V6T2, 0xfae0f060, 0xfff0f0f0, "uhsubaddx\t%8-11r, %16-19r, %0-3r"},
950 {ARM_EXT_V6T2, 0xfb00f000, 0xfff0f0f0, "mul.w\t%8-11r, %16-19r, %0-3r"},
951 {ARM_EXT_V6T2, 0xfb70f000, 0xfff0f0f0, "usad8\t%8-11r, %16-19r, %0-3r"},
952 {ARM_EXT_V6T2, 0xfa00f000, 0xffe0f0f0, "lsl%20's.w\t%8-11r, %16-19r, %0-3r"},
953 {ARM_EXT_V6T2, 0xfa20f000, 0xffe0f0f0, "lsr%20's.w\t%8-11r, %16-19r, %0-3r"},
954 {ARM_EXT_V6T2, 0xfa40f000, 0xffe0f0f0, "asr%20's.w\t%8-11r, %16-19r, %0-3r"},
955 {ARM_EXT_V6T2, 0xfa60f000, 0xffe0f0f0, "ror%20's.w\t%8-11r, %16-19r, %0-3r"},
956 {ARM_EXT_V6T2, 0xe8c00f40, 0xfff00fe0, "strex%4?hb\t%0-3r, %12-15r, [%16-19r]"},
957 {ARM_EXT_V6T2, 0xf3200000, 0xfff0f0e0, "ssat16\t%8-11r, #%0-4d, %16-19r"},
958 {ARM_EXT_V6T2, 0xf3a00000, 0xfff0f0e0, "usat16\t%8-11r, #%0-4d, %16-19r"},
959 {ARM_EXT_V6T2, 0xfb20f000, 0xfff0f0e0, "smuad%4'x\t%8-11r, %16-19r, %0-3r"},
960 {ARM_EXT_V6T2, 0xfb30f000, 0xfff0f0e0, "smulw%4?tb\t%8-11r, %16-19r, %0-3r"},
961 {ARM_EXT_V6T2, 0xfb40f000, 0xfff0f0e0, "smusd%4'x\t%8-11r, %16-19r, %0-3r"},
962 {ARM_EXT_V6T2, 0xfb50f000, 0xfff0f0e0, "smmul%4'r\t%8-11r, %16-19r, %0-3r"},
963 {ARM_EXT_V6T2, 0xfa00f080, 0xfff0f0c0, "sxtah\t%8-11r, %16-19r, %0-3r%R"},
964 {ARM_EXT_V6T2, 0xfa10f080, 0xfff0f0c0, "uxtah\t%8-11r, %16-19r, %0-3r%R"},
965 {ARM_EXT_V6T2, 0xfa20f080, 0xfff0f0c0, "sxtab16\t%8-11r, %16-19r, %0-3r%R"},
966 {ARM_EXT_V6T2, 0xfa30f080, 0xfff0f0c0, "uxtab16\t%8-11r, %16-19r, %0-3r%R"},
967 {ARM_EXT_V6T2, 0xfa40f080, 0xfff0f0c0, "sxtab\t%8-11r, %16-19r, %0-3r%R"},
968 {ARM_EXT_V6T2, 0xfa50f080, 0xfff0f0c0, "uxtab\t%8-11r, %16-19r, %0-3r%R"},
969 {ARM_EXT_V6T2, 0xfb10f000, 0xfff0f0c0, "smul%5?tb%4?tb\t%8-11r, %16-19r, %0-3r"},
970 {ARM_EXT_V6T2, 0xf36f0000, 0xffff8020, "bfc\t%8-11r, %E"},
971 {ARM_EXT_V6T2, 0xea100f00, 0xfff08f00, "tst.w\t%16-19r, %S"},
972 {ARM_EXT_V6T2, 0xea900f00, 0xfff08f00, "teq\t%16-19r, %S"},
973 {ARM_EXT_V6T2, 0xeb100f00, 0xfff08f00, "cmn.w\t%16-19r, %S"},
974 {ARM_EXT_V6T2, 0xebb00f00, 0xfff08f00, "cmp.w\t%16-19r, %S"},
975 {ARM_EXT_V6T2, 0xf0100f00, 0xfbf08f00, "tst.w\t%16-19r, %M"},
976 {ARM_EXT_V6T2, 0xf0900f00, 0xfbf08f00, "teq\t%16-19r, %M"},
977 {ARM_EXT_V6T2, 0xf1100f00, 0xfbf08f00, "cmn.w\t%16-19r, %M"},
978 {ARM_EXT_V6T2, 0xf1b00f00, 0xfbf08f00, "cmp.w\t%16-19r, %M"},
979 {ARM_EXT_V6T2, 0xea4f0000, 0xffef8000, "mov%20's.w\t%8-11r, %S"},
980 {ARM_EXT_V6T2, 0xea6f0000, 0xffef8000, "mvn%20's.w\t%8-11r, %S"},
981 {ARM_EXT_V6T2, 0xe8c00070, 0xfff000f0, "strexd\t%0-3r, %12-15r, %8-11r, [%16-19r]"},
982 {ARM_EXT_V6T2, 0xfb000000, 0xfff000f0, "mla\t%8-11r, %16-19r, %0-3r, %12-15r"},
983 {ARM_EXT_V6T2, 0xfb000010, 0xfff000f0, "mls\t%8-11r, %16-19r, %0-3r, %12-15r"},
984 {ARM_EXT_V6T2, 0xfb700000, 0xfff000f0, "usada8\t%8-11r, %16-19r, %0-3r, %12-15r"},
985 {ARM_EXT_V6T2, 0xfb800000, 0xfff000f0, "smull\t%12-15r, %8-11r, %16-19r, %0-3r"},
986 {ARM_EXT_V6T2, 0xfba00000, 0xfff000f0, "umull\t%12-15r, %8-11r, %16-19r, %0-3r"},
987 {ARM_EXT_V6T2, 0xfbc00000, 0xfff000f0, "smlal\t%12-15r, %8-11r, %16-19r, %0-3r"},
988 {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal\t%12-15r, %8-11r, %16-19r, %0-3r"},
989 {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal\t%12-15r, %8-11r, %16-19r, %0-3r"},
990 {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex\t%12-15r, [%16-19r, #%0-7W]"},
991 {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc\t%K"},
992 {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's.w\t%8-11r, %M"},
993 {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's.w\t%8-11r, %M"},
994 {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld\t%a"},
995 {ARM_EXT_V6T2, 0xfb200000, 0xfff000e0, "smlad%4'x\t%8-11r, %16-19r, %0-3r, %12-15r"},
996 {ARM_EXT_V6T2, 0xfb300000, 0xfff000e0, "smlaw%4?tb\t%8-11r, %16-19r, %0-3r, %12-15r"},
997 {ARM_EXT_V6T2, 0xfb400000, 0xfff000e0, "smlsd%4'x\t%8-11r, %16-19r, %0-3r, %12-15r"},
998 {ARM_EXT_V6T2, 0xfb500000, 0xfff000e0, "smmla%4'r\t%8-11r, %16-19r, %0-3r, %12-15r"},
999 {ARM_EXT_V6T2, 0xfb600000, 0xfff000e0, "smmls%4'r\t%8-11r, %16-19r, %0-3r, %12-15r"},
1000 {ARM_EXT_V6T2, 0xfbc000c0, 0xfff000e0, "smlald%4'x\t%12-15r, %8-11r, %16-19r, %0-3r"},
1001 {ARM_EXT_V6T2, 0xfbd000c0, 0xfff000e0, "smlsld%4'x\t%12-15r, %8-11r, %16-19r, %0-3r"},
1002 {ARM_EXT_V6T2, 0xeac00000, 0xfff08030, "pkhbt\t%8-11r, %16-19r, %S"},
1003 {ARM_EXT_V6T2, 0xeac00020, 0xfff08030, "pkhtb\t%8-11r, %16-19r, %S"},
1004 {ARM_EXT_V6T2, 0xf3400000, 0xfff08020, "sbfx\t%8-11r, %16-19r, %F"},
1005 {ARM_EXT_V6T2, 0xf3c00000, 0xfff08020, "ubfx\t%8-11r, %16-19r, %F"},
1006 {ARM_EXT_V6T2, 0xf8000e00, 0xff900f00, "str%wt\t%12-15r, %a"},
1007 {ARM_EXT_V6T2, 0xfb100000, 0xfff000c0, "smla%5?tb%4?tb\t%8-11r, %16-19r, %0-3r, %12-15r"},
1008 {ARM_EXT_V6T2, 0xfbc00080, 0xfff000c0, "smlal%5?tb%4?tb\t%12-15r, %8-11r, %16-19r, %0-3r"},
1009 {ARM_EXT_V6T2, 0xf3600000, 0xfff08020, "bfi\t%8-11r, %16-19r, %E"},
1010 {ARM_EXT_V6T2, 0xf8100e00, 0xfe900f00, "ldr%wt\t%12-15r, %a"},
1011 {ARM_EXT_V6T2, 0xf3000000, 0xffd08020, "ssat\t%8-11r, #%0-4d, %16-19r%s"},
1012 {ARM_EXT_V6T2, 0xf3800000, 0xffd08020, "usat\t%8-11r, #%0-4d, %16-19r%s"},
1013 {ARM_EXT_V6T2, 0xf2000000, 0xfbf08000, "addw\t%8-11r, %16-19r, %I"},
1014 {ARM_EXT_V6T2, 0xf2400000, 0xfbf08000, "movw\t%8-11r, %J"},
1015 {ARM_EXT_V6T2, 0xf2a00000, 0xfbf08000, "subw\t%8-11r, %16-19r, %I"},
1016 {ARM_EXT_V6T2, 0xf2c00000, 0xfbf08000, "movt\t%8-11r, %J"},
1017 {ARM_EXT_V6T2, 0xea000000, 0xffe08000, "and%20's.w\t%8-11r, %16-19r, %S"},
1018 {ARM_EXT_V6T2, 0xea200000, 0xffe08000, "bic%20's.w\t%8-11r, %16-19r, %S"},
1019 {ARM_EXT_V6T2, 0xea400000, 0xffe08000, "orr%20's.w\t%8-11r, %16-19r, %S"},
1020 {ARM_EXT_V6T2, 0xea600000, 0xffe08000, "orn%20's\t%8-11r, %16-19r, %S"},
1021 {ARM_EXT_V6T2, 0xea800000, 0xffe08000, "eor%20's.w\t%8-11r, %16-19r, %S"},
1022 {ARM_EXT_V6T2, 0xeb000000, 0xffe08000, "add%20's.w\t%8-11r, %16-19r, %S"},
1023 {ARM_EXT_V6T2, 0xeb400000, 0xffe08000, "adc%20's.w\t%8-11r, %16-19r, %S"},
1024 {ARM_EXT_V6T2, 0xeb600000, 0xffe08000, "sbc%20's.w\t%8-11r, %16-19r, %S"},
1025 {ARM_EXT_V6T2, 0xeba00000, 0xffe08000, "sub%20's.w\t%8-11r, %16-19r, %S"},
1026 {ARM_EXT_V6T2, 0xebc00000, 0xffe08000, "rsb%20's\t%8-11r, %16-19r, %S"},
1027 {ARM_EXT_V6T2, 0xe8400000, 0xfff00000, "strex\t%8-11r, %12-15r, [%16-19r, #%0-7W]"},
1028 {ARM_EXT_V6T2, 0xf0000000, 0xfbe08000, "and%20's.w\t%8-11r, %16-19r, %M"},
1029 {ARM_EXT_V6T2, 0xf0200000, 0xfbe08000, "bic%20's.w\t%8-11r, %16-19r, %M"},
1030 {ARM_EXT_V6T2, 0xf0400000, 0xfbe08000, "orr%20's.w\t%8-11r, %16-19r, %M"},
1031 {ARM_EXT_V6T2, 0xf0600000, 0xfbe08000, "orn%20's\t%8-11r, %16-19r, %M"},
1032 {ARM_EXT_V6T2, 0xf0800000, 0xfbe08000, "eor%20's.w\t%8-11r, %16-19r, %M"},
1033 {ARM_EXT_V6T2, 0xf1000000, 0xfbe08000, "add%20's.w\t%8-11r, %16-19r, %M"},
1034 {ARM_EXT_V6T2, 0xf1400000, 0xfbe08000, "adc%20's.w\t%8-11r, %16-19r, %M"},
1035 {ARM_EXT_V6T2, 0xf1600000, 0xfbe08000, "sbc%20's.w\t%8-11r, %16-19r, %M"},
1036 {ARM_EXT_V6T2, 0xf1a00000, 0xfbe08000, "sub%20's.w\t%8-11r, %16-19r, %M"},
1037 {ARM_EXT_V6T2, 0xf1c00000, 0xfbe08000, "rsb%20's\t%8-11r, %16-19r, %M"},
1038 {ARM_EXT_V6T2, 0xe8800000, 0xffd00000, "stmia.w\t%16-19r%21'!, %m"},
1039 {ARM_EXT_V6T2, 0xe8900000, 0xffd00000, "ldmia.w\t%16-19r%21'!, %m"},
1040 {ARM_EXT_V6T2, 0xe9000000, 0xffd00000, "stmdb\t%16-19r%21'!, %m"},
1041 {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb\t%16-19r%21'!, %m"},
1042 {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd\t%12-15r, %8-11r, [%16-19r]"},
1043 {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd\t%12-15r, %8-11r, [%16-19r]"},
1044 {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]"},
1045 {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]"},
1046 {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w.w\t%12-15r, %a"},
1047 {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w.w\t%12-15r, %a"},
1048
1049 /* Filter out Bcc with cond=E or F, which are used for other instructions. */
1050 {ARM_EXT_V6T2, 0xf3c08000, 0xfbc0d000, "undefined (bcc, cond=0xF)"},
1051 {ARM_EXT_V6T2, 0xf3808000, 0xfbc0d000, "undefined (bcc, cond=0xE)"},
1052 {ARM_EXT_V6T2, 0xf0008000, 0xf800d000, "b%22-25c.w\t%b"},
1053 {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b.w\t%B"},
1054
1055 /* These have been 32-bit since the invention of Thumb. */
1056 {ARM_EXT_V4T, 0xf000c000, 0xf800d000, "blx\t%B"},
1057 {ARM_EXT_V4T, 0xf000d000, 0xf800d000, "bl\t%B"},
1058
1059 /* Fallback. */
1060 {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined"},
1061 {0, 0, 0, 0}
1062 };
1063
1064 static const char *const arm_conditional[] =
1065 {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
1066 "hi", "ls", "ge", "lt", "gt", "le", "", "<und>"};
1067
1068 static const char *const arm_fp_const[] =
1069 {"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
1070
1071 static const char *const arm_shift[] =
1072 {"lsl", "lsr", "asr", "ror"};
1073
1074 typedef struct
1075 {
1076 const char *name;
1077 const char *description;
1078 const char *reg_names[16];
1079 }
1080 arm_regname;
1081
1082 static const arm_regname regnames[] =
1083 {
1084 { "raw" , "Select raw register names",
1085 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
1086 { "gcc", "Select register names used by GCC",
1087 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
1088 { "std", "Select register names used in ARM's ISA documentation",
1089 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
1090 { "apcs", "Select register names used in the APCS",
1091 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
1092 { "atpcs", "Select register names used in the ATPCS",
1093 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
1094 { "special-atpcs", "Select special register names used in the ATPCS",
1095 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }},
1096 };
1097
1098 static const char *const iwmmxt_wwnames[] =
1099 {"b", "h", "w", "d"};
1100
1101 static const char *const iwmmxt_wwssnames[] =
1102 {"b", "bus", "b", "bss",
1103 "h", "hus", "h", "hss",
1104 "w", "wus", "w", "wss",
1105 "d", "dus", "d", "dss"
1106 };
1107
1108 static const char *const iwmmxt_regnames[] =
1109 { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
1110 "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"
1111 };
1112
1113 static const char *const iwmmxt_cregnames[] =
1114 { "wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved",
1115 "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"
1116 };
1117
1118 /* Default to GCC register name set. */
1119 static unsigned int regname_selected = 1;
1120
1121 #define NUM_ARM_REGNAMES NUM_ELEM (regnames)
1122 #define arm_regnames regnames[regname_selected].reg_names
1123
1124 static bfd_boolean force_thumb = FALSE;
1125
1126
1127 /* Functions. */
1128 int
get_arm_regname_num_options(void)1129 get_arm_regname_num_options (void)
1130 {
1131 return NUM_ARM_REGNAMES;
1132 }
1133
1134 int
set_arm_regname_option(int option)1135 set_arm_regname_option (int option)
1136 {
1137 int old = regname_selected;
1138 regname_selected = option;
1139 return old;
1140 }
1141
1142 int
get_arm_regnames(int option,const char ** setname,const char ** setdescription,const char * const ** register_names)1143 get_arm_regnames (int option, const char **setname, const char **setdescription,
1144 const char *const **register_names)
1145 {
1146 *setname = regnames[option].name;
1147 *setdescription = regnames[option].description;
1148 *register_names = regnames[option].reg_names;
1149 return 16;
1150 }
1151
1152 static void
arm_decode_shift(long given,fprintf_ftype func,void * stream)1153 arm_decode_shift (long given, fprintf_ftype func, void *stream)
1154 {
1155 func (stream, "%s", arm_regnames[given & 0xf]);
1156
1157 if ((given & 0xff0) != 0)
1158 {
1159 if ((given & 0x10) == 0)
1160 {
1161 int amount = (given & 0xf80) >> 7;
1162 int shift = (given & 0x60) >> 5;
1163
1164 if (amount == 0)
1165 {
1166 if (shift == 3)
1167 {
1168 func (stream, ", rrx");
1169 return;
1170 }
1171
1172 amount = 32;
1173 }
1174
1175 func (stream, ", %s #%d", arm_shift[shift], amount);
1176 }
1177 else
1178 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
1179 arm_regnames[(given & 0xf00) >> 8]);
1180 }
1181 }
1182
1183 /* Print one coprocessor instruction on INFO->STREAM.
1184 Return TRUE if the instuction matched, FALSE if this is not a
1185 recognised coprocessor instruction. */
1186
1187 static bfd_boolean
print_insn_coprocessor(struct disassemble_info * info,long given,bfd_boolean thumb)1188 print_insn_coprocessor (struct disassemble_info *info, long given,
1189 bfd_boolean thumb)
1190 {
1191 const struct opcode32 *insn;
1192 void *stream = info->stream;
1193 fprintf_ftype func = info->fprintf_func;
1194 unsigned long mask;
1195 unsigned long value;
1196
1197 for (insn = coprocessor_opcodes; insn->assembler; insn++)
1198 {
1199 if (insn->value == FIRST_IWMMXT_INSN
1200 && info->mach != bfd_mach_arm_XScale
1201 && info->mach != bfd_mach_arm_iWMMXt)
1202 insn = insn + IWMMXT_INSN_COUNT;
1203
1204 mask = insn->mask;
1205 value = insn->value;
1206 if (thumb)
1207 {
1208 /* The high 4 bits are 0xe for Arm conditional instructions, and
1209 0xe for arm unconditional instructions. The rest of the
1210 encoding is the same. */
1211 mask |= 0xf0000000;
1212 value |= 0xe0000000;
1213 }
1214 else
1215 {
1216 /* Only match unconditional instuctions against unconditional
1217 patterns. */
1218 if ((given & 0xf0000000) == 0xf0000000)
1219 mask |= 0xf0000000;
1220 }
1221 if ((given & mask) == value)
1222 {
1223 const char *c;
1224
1225 for (c = insn->assembler; *c; c++)
1226 {
1227 if (*c == '%')
1228 {
1229 switch (*++c)
1230 {
1231 case '%':
1232 func (stream, "%%");
1233 break;
1234
1235 case 'A':
1236 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
1237
1238 if ((given & (1 << 24)) != 0)
1239 {
1240 int offset = given & 0xff;
1241
1242 if (offset)
1243 func (stream, ", #%s%d]%s",
1244 ((given & 0x00800000) == 0 ? "-" : ""),
1245 offset * 4,
1246 ((given & 0x00200000) != 0 ? "!" : ""));
1247 else
1248 func (stream, "]");
1249 }
1250 else
1251 {
1252 int offset = given & 0xff;
1253
1254 func (stream, "]");
1255
1256 if (given & (1 << 21))
1257 {
1258 if (offset)
1259 func (stream, ", #%s%d",
1260 ((given & 0x00800000) == 0 ? "-" : ""),
1261 offset * 4);
1262 }
1263 else
1264 func (stream, ", {%d}", offset);
1265 }
1266 break;
1267
1268 case 'c':
1269 func (stream, "%s",
1270 arm_conditional [(given >> 28) & 0xf]);
1271 break;
1272
1273 case 'I':
1274 /* Print a Cirrus/DSP shift immediate. */
1275 /* Immediates are 7bit signed ints with bits 0..3 in
1276 bits 0..3 of opcode and bits 4..6 in bits 5..7
1277 of opcode. */
1278 {
1279 int imm;
1280
1281 imm = (given & 0xf) | ((given & 0xe0) >> 1);
1282
1283 /* Is ``imm'' a negative number? */
1284 if (imm & 0x40)
1285 imm |= (-1 << 7);
1286
1287 func (stream, "%d", imm);
1288 }
1289
1290 break;
1291
1292 case 'F':
1293 switch (given & 0x00408000)
1294 {
1295 case 0:
1296 func (stream, "4");
1297 break;
1298 case 0x8000:
1299 func (stream, "1");
1300 break;
1301 case 0x00400000:
1302 func (stream, "2");
1303 break;
1304 default:
1305 func (stream, "3");
1306 }
1307 break;
1308
1309 case 'P':
1310 switch (given & 0x00080080)
1311 {
1312 case 0:
1313 func (stream, "s");
1314 break;
1315 case 0x80:
1316 func (stream, "d");
1317 break;
1318 case 0x00080000:
1319 func (stream, "e");
1320 break;
1321 default:
1322 func (stream, _("<illegal precision>"));
1323 break;
1324 }
1325 break;
1326 case 'Q':
1327 switch (given & 0x00408000)
1328 {
1329 case 0:
1330 func (stream, "s");
1331 break;
1332 case 0x8000:
1333 func (stream, "d");
1334 break;
1335 case 0x00400000:
1336 func (stream, "e");
1337 break;
1338 default:
1339 func (stream, "p");
1340 break;
1341 }
1342 break;
1343 case 'R':
1344 switch (given & 0x60)
1345 {
1346 case 0:
1347 break;
1348 case 0x20:
1349 func (stream, "p");
1350 break;
1351 case 0x40:
1352 func (stream, "m");
1353 break;
1354 default:
1355 func (stream, "z");
1356 break;
1357 }
1358 break;
1359
1360 case '0': case '1': case '2': case '3': case '4':
1361 case '5': case '6': case '7': case '8': case '9':
1362 {
1363 int bitstart = *c++ - '0';
1364 int bitend = 0;
1365 while (*c >= '0' && *c <= '9')
1366 bitstart = (bitstart * 10) + *c++ - '0';
1367
1368 switch (*c)
1369 {
1370 case '-':
1371 c++;
1372
1373 while (*c >= '0' && *c <= '9')
1374 bitend = (bitend * 10) + *c++ - '0';
1375
1376 if (!bitend)
1377 abort ();
1378
1379 switch (*c)
1380 {
1381 case 'r':
1382 {
1383 long reg;
1384
1385 reg = given >> bitstart;
1386 reg &= (2 << (bitend - bitstart)) - 1;
1387
1388 func (stream, "%s", arm_regnames[reg]);
1389 }
1390 break;
1391 case 'd':
1392 {
1393 long reg;
1394
1395 reg = given >> bitstart;
1396 reg &= (2 << (bitend - bitstart)) - 1;
1397
1398 func (stream, "%ld", reg);
1399 }
1400 break;
1401 case 'f':
1402 {
1403 long reg;
1404
1405 reg = given >> bitstart;
1406 reg &= (2 << (bitend - bitstart)) - 1;
1407
1408 if (reg > 7)
1409 func (stream, "#%s",
1410 arm_fp_const[reg & 7]);
1411 else
1412 func (stream, "f%ld", reg);
1413 }
1414 break;
1415
1416 case 'w':
1417 {
1418 long reg;
1419
1420 if (bitstart != bitend)
1421 {
1422 reg = given >> bitstart;
1423 reg &= (2 << (bitend - bitstart)) - 1;
1424 if (bitend - bitstart == 1)
1425 func (stream, "%s", iwmmxt_wwnames[reg]);
1426 else
1427 func (stream, "%s", iwmmxt_wwssnames[reg]);
1428 }
1429 else
1430 {
1431 reg = (((given >> 8) & 0x1) |
1432 ((given >> 22) & 0x1));
1433 func (stream, "%s", iwmmxt_wwnames[reg]);
1434 }
1435 }
1436 break;
1437
1438 case 'g':
1439 {
1440 long reg;
1441 reg = given >> bitstart;
1442 reg &= (2 << (bitend - bitstart)) - 1;
1443 func (stream, "%s", iwmmxt_regnames[reg]);
1444 }
1445 break;
1446
1447 case 'G':
1448 {
1449 long reg;
1450 reg = given >> bitstart;
1451 reg &= (2 << (bitend - bitstart)) - 1;
1452 func (stream, "%s", iwmmxt_cregnames[reg]);
1453 }
1454 break;
1455
1456 default:
1457 abort ();
1458 }
1459 break;
1460
1461 case 'y':
1462 case 'z':
1463 {
1464 int single = *c == 'y';
1465 int regno;
1466
1467 switch (bitstart)
1468 {
1469 case 4: /* Sm pair */
1470 func (stream, "{");
1471 /* Fall through. */
1472 case 0: /* Sm, Dm */
1473 regno = given & 0x0000000f;
1474 if (single)
1475 {
1476 regno <<= 1;
1477 regno += (given >> 5) & 1;
1478 }
1479 break;
1480
1481 case 1: /* Sd, Dd */
1482 regno = (given >> 12) & 0x0000000f;
1483 if (single)
1484 {
1485 regno <<= 1;
1486 regno += (given >> 22) & 1;
1487 }
1488 break;
1489
1490 case 2: /* Sn, Dn */
1491 regno = (given >> 16) & 0x0000000f;
1492 if (single)
1493 {
1494 regno <<= 1;
1495 regno += (given >> 7) & 1;
1496 }
1497 break;
1498
1499 case 3: /* List */
1500 func (stream, "{");
1501 regno = (given >> 12) & 0x0000000f;
1502 if (single)
1503 {
1504 regno <<= 1;
1505 regno += (given >> 22) & 1;
1506 }
1507 break;
1508
1509
1510 default:
1511 abort ();
1512 }
1513
1514 func (stream, "%c%d", single ? 's' : 'd', regno);
1515
1516 if (bitstart == 3)
1517 {
1518 int count = given & 0xff;
1519
1520 if (single == 0)
1521 count >>= 1;
1522
1523 if (--count)
1524 {
1525 func (stream, "-%c%d",
1526 single ? 's' : 'd',
1527 regno + count);
1528 }
1529
1530 func (stream, "}");
1531 }
1532 else if (bitstart == 4)
1533 func (stream, ", %c%d}", single ? 's' : 'd',
1534 regno + 1);
1535
1536 break;
1537 }
1538
1539 break;
1540
1541 case '`':
1542 c++;
1543 if ((given & (1 << bitstart)) == 0)
1544 func (stream, "%c", *c);
1545 break;
1546 case '\'':
1547 c++;
1548 if ((given & (1 << bitstart)) != 0)
1549 func (stream, "%c", *c);
1550 break;
1551 case '?':
1552 ++c;
1553 if ((given & (1 << bitstart)) != 0)
1554 func (stream, "%c", *c++);
1555 else
1556 func (stream, "%c", *++c);
1557 break;
1558 default:
1559 abort ();
1560 }
1561 break;
1562
1563 case 'L':
1564 switch (given & 0x00400100)
1565 {
1566 case 0x00000000: func (stream, "b"); break;
1567 case 0x00400000: func (stream, "h"); break;
1568 case 0x00000100: func (stream, "w"); break;
1569 case 0x00400100: func (stream, "d"); break;
1570 default:
1571 break;
1572 }
1573 break;
1574
1575 case 'Z':
1576 {
1577 int value;
1578 /* given (20, 23) | given (0, 3) */
1579 value = ((given >> 16) & 0xf0) | (given & 0xf);
1580 func (stream, "%d", value);
1581 }
1582 break;
1583
1584 case 'l':
1585 /* This is like the 'A' operator, except that if
1586 the width field "M" is zero, then the offset is
1587 *not* multiplied by four. */
1588 {
1589 int offset = given & 0xff;
1590 int multiplier = (given & 0x00000100) ? 4 : 1;
1591
1592 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
1593
1594 if (offset)
1595 {
1596 if ((given & 0x01000000) != 0)
1597 func (stream, ", #%s%d]%s",
1598 ((given & 0x00800000) == 0 ? "-" : ""),
1599 offset * multiplier,
1600 ((given & 0x00200000) != 0 ? "!" : ""));
1601 else
1602 func (stream, "], #%s%d",
1603 ((given & 0x00800000) == 0 ? "-" : ""),
1604 offset * multiplier);
1605 }
1606 else
1607 func (stream, "]");
1608 }
1609 break;
1610
1611 default:
1612 abort ();
1613 }
1614 }
1615 }
1616 else
1617 func (stream, "%c", *c);
1618 }
1619 return TRUE;
1620 }
1621 }
1622 return FALSE;
1623 }
1624
1625 static void
print_arm_address(bfd_vma pc,struct disassemble_info * info,long given)1626 print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
1627 {
1628 void *stream = info->stream;
1629 fprintf_ftype func = info->fprintf_func;
1630
1631 if (((given & 0x000f0000) == 0x000f0000)
1632 && ((given & 0x02000000) == 0))
1633 {
1634 int offset = given & 0xfff;
1635
1636 func (stream, "[pc");
1637
1638 if (given & 0x01000000)
1639 {
1640 if ((given & 0x00800000) == 0)
1641 offset = - offset;
1642
1643 /* Pre-indexed. */
1644 func (stream, ", #%d]", offset);
1645
1646 offset += pc + 8;
1647
1648 /* Cope with the possibility of write-back
1649 being used. Probably a very dangerous thing
1650 for the programmer to do, but who are we to
1651 argue ? */
1652 if (given & 0x00200000)
1653 func (stream, "!");
1654 }
1655 else
1656 {
1657 /* Post indexed. */
1658 func (stream, "], #%d", offset);
1659
1660 /* ie ignore the offset. */
1661 offset = pc + 8;
1662 }
1663
1664 func (stream, "\t; ");
1665 info->print_address_func (offset, info);
1666 }
1667 else
1668 {
1669 func (stream, "[%s",
1670 arm_regnames[(given >> 16) & 0xf]);
1671 if ((given & 0x01000000) != 0)
1672 {
1673 if ((given & 0x02000000) == 0)
1674 {
1675 int offset = given & 0xfff;
1676 if (offset)
1677 func (stream, ", #%s%d",
1678 (((given & 0x00800000) == 0)
1679 ? "-" : ""), offset);
1680 }
1681 else
1682 {
1683 func (stream, ", %s",
1684 (((given & 0x00800000) == 0)
1685 ? "-" : ""));
1686 arm_decode_shift (given, func, stream);
1687 }
1688
1689 func (stream, "]%s",
1690 ((given & 0x00200000) != 0) ? "!" : "");
1691 }
1692 else
1693 {
1694 if ((given & 0x02000000) == 0)
1695 {
1696 int offset = given & 0xfff;
1697 if (offset)
1698 func (stream, "], #%s%d",
1699 (((given & 0x00800000) == 0)
1700 ? "-" : ""), offset);
1701 else
1702 func (stream, "]");
1703 }
1704 else
1705 {
1706 func (stream, "], %s",
1707 (((given & 0x00800000) == 0)
1708 ? "-" : ""));
1709 arm_decode_shift (given, func, stream);
1710 }
1711 }
1712 }
1713 }
1714
1715 /* Print one ARM instruction from PC on INFO->STREAM. */
1716
1717 static void
print_insn_arm(bfd_vma pc,struct disassemble_info * info,long given)1718 print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
1719 {
1720 const struct opcode32 *insn;
1721 void *stream = info->stream;
1722 fprintf_ftype func = info->fprintf_func;
1723
1724 if (print_insn_coprocessor (info, given, FALSE))
1725 return;
1726
1727 for (insn = arm_opcodes; insn->assembler; insn++)
1728 {
1729 if (insn->value == FIRST_IWMMXT_INSN
1730 && info->mach != bfd_mach_arm_XScale
1731 && info->mach != bfd_mach_arm_iWMMXt)
1732 insn = insn + IWMMXT_INSN_COUNT;
1733
1734 if ((given & insn->mask) == insn->value
1735 /* Special case: an instruction with all bits set in the condition field
1736 (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
1737 or by the catchall at the end of the table. */
1738 && ((given & 0xF0000000) != 0xF0000000
1739 || (insn->mask & 0xF0000000) == 0xF0000000
1740 || (insn->mask == 0 && insn->value == 0)))
1741 {
1742 const char *c;
1743
1744 for (c = insn->assembler; *c; c++)
1745 {
1746 if (*c == '%')
1747 {
1748 switch (*++c)
1749 {
1750 case '%':
1751 func (stream, "%%");
1752 break;
1753
1754 case 'a':
1755 print_arm_address (pc, info, given);
1756 break;
1757
1758 case 'P':
1759 /* Set P address bit and use normal address
1760 printing routine. */
1761 print_arm_address (pc, info, given | (1 << 24));
1762 break;
1763
1764 case 's':
1765 if ((given & 0x004f0000) == 0x004f0000)
1766 {
1767 /* PC relative with immediate offset. */
1768 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
1769
1770 if ((given & 0x00800000) == 0)
1771 offset = -offset;
1772
1773 func (stream, "[pc, #%d]\t; ", offset);
1774 info->print_address_func (offset + pc + 8, info);
1775 }
1776 else
1777 {
1778 func (stream, "[%s",
1779 arm_regnames[(given >> 16) & 0xf]);
1780 if ((given & 0x01000000) != 0)
1781 {
1782 /* Pre-indexed. */
1783 if ((given & 0x00400000) == 0x00400000)
1784 {
1785 /* Immediate. */
1786 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
1787 if (offset)
1788 func (stream, ", #%s%d",
1789 (((given & 0x00800000) == 0)
1790 ? "-" : ""), offset);
1791 }
1792 else
1793 {
1794 /* Register. */
1795 func (stream, ", %s%s",
1796 (((given & 0x00800000) == 0)
1797 ? "-" : ""),
1798 arm_regnames[given & 0xf]);
1799 }
1800
1801 func (stream, "]%s",
1802 ((given & 0x00200000) != 0) ? "!" : "");
1803 }
1804 else
1805 {
1806 /* Post-indexed. */
1807 if ((given & 0x00400000) == 0x00400000)
1808 {
1809 /* Immediate. */
1810 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
1811 if (offset)
1812 func (stream, "], #%s%d",
1813 (((given & 0x00800000) == 0)
1814 ? "-" : ""), offset);
1815 else
1816 func (stream, "]");
1817 }
1818 else
1819 {
1820 /* Register. */
1821 func (stream, "], %s%s",
1822 (((given & 0x00800000) == 0)
1823 ? "-" : ""),
1824 arm_regnames[given & 0xf]);
1825 }
1826 }
1827 }
1828 break;
1829
1830 case 'b':
1831 {
1832 int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000);
1833 info->print_address_func (disp*4 + pc + 8, info);
1834 }
1835 break;
1836
1837 case 'c':
1838 func (stream, "%s",
1839 arm_conditional [(given >> 28) & 0xf]);
1840 break;
1841
1842 case 'm':
1843 {
1844 int started = 0;
1845 int reg;
1846
1847 func (stream, "{");
1848 for (reg = 0; reg < 16; reg++)
1849 if ((given & (1 << reg)) != 0)
1850 {
1851 if (started)
1852 func (stream, ", ");
1853 started = 1;
1854 func (stream, "%s", arm_regnames[reg]);
1855 }
1856 func (stream, "}");
1857 }
1858 break;
1859
1860 case 'o':
1861 if ((given & 0x02000000) != 0)
1862 {
1863 int rotate = (given & 0xf00) >> 7;
1864 int immed = (given & 0xff);
1865 immed = (((immed << (32 - rotate))
1866 | (immed >> rotate)) & 0xffffffff);
1867 func (stream, "#%d\t; 0x%x", immed, immed);
1868 }
1869 else
1870 arm_decode_shift (given, func, stream);
1871 break;
1872
1873 case 'p':
1874 if ((given & 0x0000f000) == 0x0000f000)
1875 func (stream, "p");
1876 break;
1877
1878 case 't':
1879 if ((given & 0x01200000) == 0x00200000)
1880 func (stream, "t");
1881 break;
1882
1883 case 'A':
1884 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
1885
1886 if ((given & (1 << 24)) != 0)
1887 {
1888 int offset = given & 0xff;
1889
1890 if (offset)
1891 func (stream, ", #%s%d]%s",
1892 ((given & 0x00800000) == 0 ? "-" : ""),
1893 offset * 4,
1894 ((given & 0x00200000) != 0 ? "!" : ""));
1895 else
1896 func (stream, "]");
1897 }
1898 else
1899 {
1900 int offset = given & 0xff;
1901
1902 func (stream, "]");
1903
1904 if (given & (1 << 21))
1905 {
1906 if (offset)
1907 func (stream, ", #%s%d",
1908 ((given & 0x00800000) == 0 ? "-" : ""),
1909 offset * 4);
1910 }
1911 else
1912 func (stream, ", {%d}", offset);
1913 }
1914 break;
1915
1916 case 'B':
1917 /* Print ARM V5 BLX(1) address: pc+25 bits. */
1918 {
1919 bfd_vma address;
1920 bfd_vma offset = 0;
1921
1922 if (given & 0x00800000)
1923 /* Is signed, hi bits should be ones. */
1924 offset = (-1) ^ 0x00ffffff;
1925
1926 /* Offset is (SignExtend(offset field)<<2). */
1927 offset += given & 0x00ffffff;
1928 offset <<= 2;
1929 address = offset + pc + 8;
1930
1931 if (given & 0x01000000)
1932 /* H bit allows addressing to 2-byte boundaries. */
1933 address += 2;
1934
1935 info->print_address_func (address, info);
1936 }
1937 break;
1938
1939 case 'C':
1940 func (stream, "_");
1941 if (given & 0x80000)
1942 func (stream, "f");
1943 if (given & 0x40000)
1944 func (stream, "s");
1945 if (given & 0x20000)
1946 func (stream, "x");
1947 if (given & 0x10000)
1948 func (stream, "c");
1949 break;
1950
1951 case 'U':
1952 switch (given & 0xf)
1953 {
1954 case 0x2: func(stream, "oshst"); break;
1955 case 0x3: func(stream, "osh"); break;
1956 case 0x6: func(stream, "nshst"); break;
1957 case 0x7: func(stream, "nsh"); break;
1958 case 0xa: func(stream, "ishst"); break;
1959 case 0xb: func(stream, "ish"); break;
1960 case 0xe: func(stream, "st"); break;
1961 case 0xf: func(stream, "sy"); break;
1962 default:
1963 func(stream, "#%d", (int)given & 0xf);
1964 break;
1965 }
1966 break;
1967
1968 case '0': case '1': case '2': case '3': case '4':
1969 case '5': case '6': case '7': case '8': case '9':
1970 {
1971 int bitstart = *c++ - '0';
1972 int bitend = 0;
1973 while (*c >= '0' && *c <= '9')
1974 bitstart = (bitstart * 10) + *c++ - '0';
1975
1976 switch (*c)
1977 {
1978 case '-':
1979 c++;
1980
1981 while (*c >= '0' && *c <= '9')
1982 bitend = (bitend * 10) + *c++ - '0';
1983
1984 if (!bitend)
1985 abort ();
1986
1987 switch (*c)
1988 {
1989 case 'r':
1990 {
1991 long reg;
1992
1993 reg = given >> bitstart;
1994 reg &= (2 << (bitend - bitstart)) - 1;
1995
1996 func (stream, "%s", arm_regnames[reg]);
1997 }
1998 break;
1999 case 'd':
2000 {
2001 long reg;
2002
2003 reg = given >> bitstart;
2004 reg &= (2 << (bitend - bitstart)) - 1;
2005
2006 func (stream, "%ld", reg);
2007 }
2008 break;
2009 case 'W':
2010 {
2011 long reg;
2012
2013 reg = given >> bitstart;
2014 reg &= (2 << (bitend - bitstart)) - 1;
2015
2016 func (stream, "%ld", reg + 1);
2017 }
2018 break;
2019 case 'x':
2020 {
2021 long reg;
2022
2023 reg = given >> bitstart;
2024 reg &= (2 << (bitend - bitstart)) - 1;
2025
2026 func (stream, "0x%08lx", reg);
2027
2028 /* Some SWI instructions have special
2029 meanings. */
2030 if ((given & 0x0fffffff) == 0x0FF00000)
2031 func (stream, "\t; IMB");
2032 else if ((given & 0x0fffffff) == 0x0FF00001)
2033 func (stream, "\t; IMBRange");
2034 }
2035 break;
2036 case 'X':
2037 {
2038 long reg;
2039
2040 reg = given >> bitstart;
2041 reg &= (2 << (bitend - bitstart)) - 1;
2042
2043 func (stream, "%01lx", reg & 0xf);
2044 }
2045 break;
2046 default:
2047 abort ();
2048 }
2049 break;
2050
2051 case '`':
2052 c++;
2053 if ((given & (1 << bitstart)) == 0)
2054 func (stream, "%c", *c);
2055 break;
2056 case '\'':
2057 c++;
2058 if ((given & (1 << bitstart)) != 0)
2059 func (stream, "%c", *c);
2060 break;
2061 case '?':
2062 ++c;
2063 if ((given & (1 << bitstart)) != 0)
2064 func (stream, "%c", *c++);
2065 else
2066 func (stream, "%c", *++c);
2067 break;
2068 default:
2069 abort ();
2070 }
2071 break;
2072
2073 case 'e':
2074 {
2075 int imm;
2076
2077 imm = (given & 0xf) | ((given & 0xfff00) >> 4);
2078 func (stream, "%d", imm);
2079 }
2080 break;
2081
2082 case 'E':
2083 /* LSB and WIDTH fields of BFI or BFC. The machine-
2084 language instruction encodes LSB and MSB. */
2085 {
2086 long msb = (given & 0x001f0000) >> 16;
2087 long lsb = (given & 0x00000f80) >> 7;
2088
2089 long width = msb - lsb + 1;
2090 if (width > 0)
2091 func (stream, "#%lu, #%lu", lsb, width);
2092 else
2093 func (stream, "(invalid: %lu:%lu)", lsb, msb);
2094 }
2095 break;
2096
2097 case 'V':
2098 /* 16-bit unsigned immediate from a MOVT or MOVW
2099 instruction, encoded in bits 0:11 and 15:19. */
2100 {
2101 long hi = (given & 0x000f0000) >> 4;
2102 long lo = (given & 0x00000fff);
2103 long imm16 = hi | lo;
2104 func (stream, "#%lu\t; 0x%lx", imm16, imm16);
2105 }
2106 break;
2107
2108 default:
2109 abort ();
2110 }
2111 }
2112 }
2113 else
2114 func (stream, "%c", *c);
2115 }
2116 return;
2117 }
2118 }
2119 abort ();
2120 }
2121
2122 /* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */
2123
2124 static void
print_insn_thumb16(bfd_vma pc,struct disassemble_info * info,long given)2125 print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
2126 {
2127 const struct opcode16 *insn;
2128 void *stream = info->stream;
2129 fprintf_ftype func = info->fprintf_func;
2130
2131 for (insn = thumb_opcodes; insn->assembler; insn++)
2132 if ((given & insn->mask) == insn->value)
2133 {
2134 const char *c = insn->assembler;
2135 for (; *c; c++)
2136 {
2137 int domaskpc = 0;
2138 int domasklr = 0;
2139
2140 if (*c != '%')
2141 {
2142 func (stream, "%c", *c);
2143 continue;
2144 }
2145
2146 switch (*++c)
2147 {
2148 case '%':
2149 func (stream, "%%");
2150 break;
2151
2152 case 'S':
2153 {
2154 long reg;
2155
2156 reg = (given >> 3) & 0x7;
2157 if (given & (1 << 6))
2158 reg += 8;
2159
2160 func (stream, "%s", arm_regnames[reg]);
2161 }
2162 break;
2163
2164 case 'D':
2165 {
2166 long reg;
2167
2168 reg = given & 0x7;
2169 if (given & (1 << 7))
2170 reg += 8;
2171
2172 func (stream, "%s", arm_regnames[reg]);
2173 }
2174 break;
2175
2176 case 'N':
2177 if (given & (1 << 8))
2178 domasklr = 1;
2179 /* Fall through. */
2180 case 'O':
2181 if (*c == 'O' && (given & (1 << 8)))
2182 domaskpc = 1;
2183 /* Fall through. */
2184 case 'M':
2185 {
2186 int started = 0;
2187 int reg;
2188
2189 func (stream, "{");
2190
2191 /* It would be nice if we could spot
2192 ranges, and generate the rS-rE format: */
2193 for (reg = 0; (reg < 8); reg++)
2194 if ((given & (1 << reg)) != 0)
2195 {
2196 if (started)
2197 func (stream, ", ");
2198 started = 1;
2199 func (stream, "%s", arm_regnames[reg]);
2200 }
2201
2202 if (domasklr)
2203 {
2204 if (started)
2205 func (stream, ", ");
2206 started = 1;
2207 func (stream, arm_regnames[14] /* "lr" */);
2208 }
2209
2210 if (domaskpc)
2211 {
2212 if (started)
2213 func (stream, ", ");
2214 func (stream, arm_regnames[15] /* "pc" */);
2215 }
2216
2217 func (stream, "}");
2218 }
2219 break;
2220
2221 case 'b':
2222 /* Print ARM V6T2 CZB address: pc+4+6 bits. */
2223 {
2224 bfd_vma address = (pc + 4
2225 + ((given & 0x00f8) >> 2)
2226 + ((given & 0x0200) >> 3));
2227 info->print_address_func (address, info);
2228 }
2229 break;
2230
2231 case 's':
2232 /* Right shift immediate -- bits 6..10; 1-31 print
2233 as themselves, 0 prints as 32. */
2234 {
2235 long imm = (given & 0x07c0) >> 6;
2236 if (imm == 0)
2237 imm = 32;
2238 func (stream, "#%ld", imm);
2239 }
2240 break;
2241
2242 case '0': case '1': case '2': case '3': case '4':
2243 case '5': case '6': case '7': case '8': case '9':
2244 {
2245 int bitstart = *c++ - '0';
2246 int bitend = 0;
2247
2248 while (*c >= '0' && *c <= '9')
2249 bitstart = (bitstart * 10) + *c++ - '0';
2250
2251 switch (*c)
2252 {
2253 case '-':
2254 {
2255 long reg;
2256
2257 c++;
2258 while (*c >= '0' && *c <= '9')
2259 bitend = (bitend * 10) + *c++ - '0';
2260 if (!bitend)
2261 abort ();
2262 reg = given >> bitstart;
2263 reg &= (2 << (bitend - bitstart)) - 1;
2264 switch (*c)
2265 {
2266 case 'r':
2267 func (stream, "%s", arm_regnames[reg]);
2268 break;
2269
2270 case 'd':
2271 func (stream, "%ld", reg);
2272 break;
2273
2274 case 'H':
2275 func (stream, "%ld", reg << 1);
2276 break;
2277
2278 case 'W':
2279 func (stream, "%ld", reg << 2);
2280 break;
2281
2282 case 'a':
2283 /* PC-relative address -- the bottom two
2284 bits of the address are dropped
2285 before the calculation. */
2286 info->print_address_func
2287 (((pc + 4) & ~3) + (reg << 2), info);
2288 break;
2289
2290 case 'x':
2291 func (stream, "0x%04lx", reg);
2292 break;
2293
2294 case 'B':
2295 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
2296 info->print_address_func (reg * 2 + pc + 4, info);
2297 break;
2298
2299 case 'c':
2300 {
2301 /* Must print 0xE as 'al' to distinguish
2302 unconditional B from conditional BAL. */
2303 if (reg == 0xE)
2304 func (stream, "al");
2305 else
2306 func (stream, "%s", arm_conditional [reg]);
2307 }
2308 break;
2309
2310 default:
2311 abort ();
2312 }
2313 }
2314 break;
2315
2316 case '\'':
2317 c++;
2318 if ((given & (1 << bitstart)) != 0)
2319 func (stream, "%c", *c);
2320 break;
2321
2322 case '?':
2323 ++c;
2324 if ((given & (1 << bitstart)) != 0)
2325 func (stream, "%c", *c++);
2326 else
2327 func (stream, "%c", *++c);
2328 break;
2329
2330 default:
2331 abort ();
2332 }
2333 }
2334 break;
2335
2336 default:
2337 abort ();
2338 }
2339 }
2340 return;
2341 }
2342
2343 /* No match. */
2344 abort ();
2345 }
2346
2347 /* Return the name of an V7M special register. */
2348 static const char *
psr_name(int regno)2349 psr_name (int regno)
2350 {
2351 switch (regno)
2352 {
2353 case 0: return "APSR";
2354 case 1: return "IAPSR";
2355 case 2: return "EAPSR";
2356 case 3: return "PSR";
2357 case 5: return "IPSR";
2358 case 6: return "EPSR";
2359 case 7: return "IEPSR";
2360 case 8: return "MSP";
2361 case 9: return "PSP";
2362 case 16: return "PRIMASK";
2363 case 17: return "BASEPRI";
2364 case 18: return "BASEPRI_MASK";
2365 case 19: return "FAULTMASK";
2366 case 20: return "CONTROL";
2367 default: return "<unknown>";
2368 }
2369 }
2370
2371 /* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */
2372
2373 static void
print_insn_thumb32(bfd_vma pc,struct disassemble_info * info,long given)2374 print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
2375 {
2376 const struct opcode32 *insn;
2377 void *stream = info->stream;
2378 fprintf_ftype func = info->fprintf_func;
2379
2380 if (print_insn_coprocessor (info, given, TRUE))
2381 return;
2382
2383 for (insn = thumb32_opcodes; insn->assembler; insn++)
2384 if ((given & insn->mask) == insn->value)
2385 {
2386 const char *c = insn->assembler;
2387 for (; *c; c++)
2388 {
2389 if (*c != '%')
2390 {
2391 func (stream, "%c", *c);
2392 continue;
2393 }
2394
2395 switch (*++c)
2396 {
2397 case '%':
2398 func (stream, "%%");
2399 break;
2400
2401 case 'I':
2402 {
2403 unsigned int imm12 = 0;
2404 imm12 |= (given & 0x000000ffu);
2405 imm12 |= (given & 0x00007000u) >> 4;
2406 imm12 |= (given & 0x04000000u) >> 15;
2407 func (stream, "#%u\t; 0x%x", imm12, imm12);
2408 }
2409 break;
2410
2411 case 'M':
2412 {
2413 unsigned int bits = 0, imm, imm8, mod;
2414 bits |= (given & 0x000000ffu);
2415 bits |= (given & 0x00007000u) >> 4;
2416 bits |= (given & 0x04000000u) >> 15;
2417 imm8 = (bits & 0x0ff);
2418 mod = (bits & 0xf00) >> 8;
2419 switch (mod)
2420 {
2421 case 0: imm = imm8; break;
2422 case 1: imm = ((imm8<<16) | imm8); break;
2423 case 2: imm = ((imm8<<24) | (imm8 << 8)); break;
2424 case 3: imm = ((imm8<<24) | (imm8 << 16) | (imm8 << 8) | imm8); break;
2425 default:
2426 mod = (bits & 0xf80) >> 7;
2427 imm8 = (bits & 0x07f) | 0x80;
2428 imm = (((imm8 << (32 - mod)) | (imm8 >> mod)) & 0xffffffff);
2429 }
2430 func (stream, "#%u\t; 0x%x", imm, imm);
2431 }
2432 break;
2433
2434 case 'J':
2435 {
2436 unsigned int imm = 0;
2437 imm |= (given & 0x000000ffu);
2438 imm |= (given & 0x00007000u) >> 4;
2439 imm |= (given & 0x04000000u) >> 15;
2440 imm |= (given & 0x000f0000u) >> 4;
2441 func (stream, "#%u\t; 0x%x", imm, imm);
2442 }
2443 break;
2444
2445 case 'K':
2446 {
2447 unsigned int imm = 0;
2448 imm |= (given & 0x000f0000u) >> 16;
2449 imm |= (given & 0x00000ff0u) >> 0;
2450 imm |= (given & 0x0000000fu) << 12;
2451 func (stream, "#%u\t; 0x%x", imm, imm);
2452 }
2453 break;
2454
2455 case 'S':
2456 {
2457 unsigned int reg = (given & 0x0000000fu);
2458 unsigned int stp = (given & 0x00000030u) >> 4;
2459 unsigned int imm = 0;
2460 imm |= (given & 0x000000c0u) >> 6;
2461 imm |= (given & 0x00007000u) >> 10;
2462
2463 func (stream, "%s", arm_regnames[reg]);
2464 switch (stp)
2465 {
2466 case 0:
2467 if (imm > 0)
2468 func (stream, ", lsl #%u", imm);
2469 break;
2470
2471 case 1:
2472 if (imm == 0)
2473 imm = 32;
2474 func (stream, ", lsr #%u", imm);
2475 break;
2476
2477 case 2:
2478 if (imm == 0)
2479 imm = 32;
2480 func (stream, ", asr #%u", imm);
2481 break;
2482
2483 case 3:
2484 if (imm == 0)
2485 func (stream, ", rrx");
2486 else
2487 func (stream, ", ror #%u", imm);
2488 }
2489 }
2490 break;
2491
2492 case 'a':
2493 {
2494 unsigned int Rn = (given & 0x000f0000) >> 16;
2495 unsigned int U = (given & 0x00800000) >> 23;
2496 unsigned int op = (given & 0x00000f00) >> 8;
2497 unsigned int i12 = (given & 0x00000fff);
2498 unsigned int i8 = (given & 0x000000ff);
2499 bfd_boolean writeback = FALSE, postind = FALSE;
2500 int offset = 0;
2501
2502 func (stream, "[%s", arm_regnames[Rn]);
2503 if (U) /* 12-bit positive immediate offset */
2504 offset = i12;
2505 else if (Rn == 15) /* 12-bit negative immediate offset */
2506 offset = -(int)i12;
2507 else if (op == 0x0) /* shifted register offset */
2508 {
2509 unsigned int Rm = (i8 & 0x0f);
2510 unsigned int sh = (i8 & 0x30) >> 4;
2511 func (stream, ", %s", arm_regnames[Rm]);
2512 if (sh)
2513 func (stream, ", lsl #%u", sh);
2514 func (stream, "]");
2515 break;
2516 }
2517 else switch (op)
2518 {
2519 case 0xE: /* 8-bit positive immediate offset */
2520 offset = i8;
2521 break;
2522
2523 case 0xC: /* 8-bit negative immediate offset */
2524 offset = -i8;
2525 break;
2526
2527 case 0xF: /* 8-bit + preindex with wb */
2528 offset = i8;
2529 writeback = TRUE;
2530 break;
2531
2532 case 0xD: /* 8-bit - preindex with wb */
2533 offset = -i8;
2534 writeback = TRUE;
2535 break;
2536
2537 case 0xB: /* 8-bit + postindex */
2538 offset = i8;
2539 postind = TRUE;
2540 break;
2541
2542 case 0x9: /* 8-bit - postindex */
2543 offset = -i8;
2544 postind = TRUE;
2545 break;
2546
2547 default:
2548 func (stream, ", <undefined>]");
2549 goto skip;
2550 }
2551
2552 if (postind)
2553 func (stream, "], #%d", offset);
2554 else
2555 {
2556 if (offset)
2557 func (stream, ", #%d", offset);
2558 func (stream, writeback ? "]!" : "]");
2559 }
2560
2561 if (Rn == 15)
2562 {
2563 func (stream, "\t; ");
2564 info->print_address_func (((pc + 4) & ~3) + offset, info);
2565 }
2566 }
2567 skip:
2568 break;
2569
2570 case 'A':
2571 {
2572 unsigned int P = (given & 0x01000000) >> 24;
2573 unsigned int U = (given & 0x00800000) >> 23;
2574 unsigned int W = (given & 0x00400000) >> 21;
2575 unsigned int Rn = (given & 0x000f0000) >> 16;
2576 unsigned int off = (given & 0x000000ff);
2577
2578 func (stream, "[%s", arm_regnames[Rn]);
2579 if (P)
2580 {
2581 if (off || !U)
2582 func (stream, ", #%c%u", U ? '+' : '-', off * 4);
2583 func (stream, "]");
2584 if (W)
2585 func (stream, "!");
2586 }
2587 else
2588 {
2589 func (stream, "], ");
2590 if (W)
2591 func (stream, "#%c%u", U ? '+' : '-', off * 4);
2592 else
2593 func (stream, "{%u}", off);
2594 }
2595 }
2596 break;
2597
2598 case 'w':
2599 {
2600 unsigned int Sbit = (given & 0x01000000) >> 24;
2601 unsigned int type = (given & 0x00600000) >> 21;
2602 switch (type)
2603 {
2604 case 0: func (stream, Sbit ? "sb" : "b"); break;
2605 case 1: func (stream, Sbit ? "sh" : "h"); break;
2606 case 2:
2607 if (Sbit)
2608 func (stream, "??");
2609 break;
2610 case 3:
2611 func (stream, "??");
2612 break;
2613 }
2614 }
2615 break;
2616
2617 case 'm':
2618 {
2619 int started = 0;
2620 int reg;
2621
2622 func (stream, "{");
2623 for (reg = 0; reg < 16; reg++)
2624 if ((given & (1 << reg)) != 0)
2625 {
2626 if (started)
2627 func (stream, ", ");
2628 started = 1;
2629 func (stream, "%s", arm_regnames[reg]);
2630 }
2631 func (stream, "}");
2632 }
2633 break;
2634
2635 case 'E':
2636 {
2637 unsigned int msb = (given & 0x0000001f);
2638 unsigned int lsb = 0;
2639 lsb |= (given & 0x000000c0u) >> 6;
2640 lsb |= (given & 0x00007000u) >> 10;
2641 func (stream, "#%u, #%u", lsb, msb - lsb + 1);
2642 }
2643 break;
2644
2645 case 'F':
2646 {
2647 unsigned int width = (given & 0x0000001f) + 1;
2648 unsigned int lsb = 0;
2649 lsb |= (given & 0x000000c0u) >> 6;
2650 lsb |= (given & 0x00007000u) >> 10;
2651 func (stream, "#%u, #%u", lsb, width);
2652 }
2653 break;
2654
2655 case 'b':
2656 {
2657 unsigned int S = (given & 0x04000000u) >> 26;
2658 unsigned int J1 = (given & 0x00002000u) >> 13;
2659 unsigned int J2 = (given & 0x00000800u) >> 11;
2660 int offset = 0;
2661
2662 offset |= !S << 20;
2663 offset |= J2 << 19;
2664 offset |= J1 << 18;
2665 offset |= (given & 0x003f0000) >> 4;
2666 offset |= (given & 0x000007ff) << 1;
2667 offset -= (1 << 20);
2668
2669 info->print_address_func (pc + 4 + offset, info);
2670 }
2671 break;
2672
2673 case 'B':
2674 {
2675 unsigned int S = (given & 0x04000000u) >> 26;
2676 unsigned int I1 = (given & 0x00002000u) >> 13;
2677 unsigned int I2 = (given & 0x00000800u) >> 11;
2678 int offset = 0;
2679
2680 offset |= !S << 24;
2681 offset |= !(I1 ^ S) << 23;
2682 offset |= !(I2 ^ S) << 22;
2683 offset |= (given & 0x03ff0000u) >> 4;
2684 offset |= (given & 0x000007ffu) << 1;
2685 offset -= (1 << 24);
2686 offset += pc + 4;
2687
2688 /* BLX target addresses are always word aligned. */
2689 if ((given & 0x00001000u) == 0)
2690 offset &= ~2u;
2691
2692 info->print_address_func (offset, info);
2693 }
2694 break;
2695
2696 case 's':
2697 {
2698 unsigned int shift = 0;
2699 shift |= (given & 0x000000c0u) >> 6;
2700 shift |= (given & 0x00007000u) >> 10;
2701 if (given & 0x00200000u)
2702 func (stream, ", asr #%u", shift);
2703 else if (shift)
2704 func (stream, ", lsl #%u", shift);
2705 /* else print nothing - lsl #0 */
2706 }
2707 break;
2708
2709 case 'R':
2710 {
2711 unsigned int rot = (given & 0x00000030) >> 4;
2712 if (rot)
2713 func (stream, ", ror #%u", rot * 8);
2714 }
2715 break;
2716
2717 case 'U':
2718 switch (given & 0xf)
2719 {
2720 case 0x2: func(stream, "oshst"); break;
2721 case 0x3: func(stream, "osh"); break;
2722 case 0x6: func(stream, "nshst"); break;
2723 case 0x7: func(stream, "nsh"); break;
2724 case 0xa: func(stream, "ishst"); break;
2725 case 0xb: func(stream, "ish"); break;
2726 case 0xe: func(stream, "st"); break;
2727 case 0xf: func(stream, "sy"); break;
2728 default:
2729 func(stream, "#%d", (int)given & 0xf);
2730 break;
2731 }
2732 break;
2733
2734 case 'C':
2735 if ((given & 0xff) == 0)
2736 {
2737 func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C');
2738 if (given & 0x800)
2739 func (stream, "f");
2740 if (given & 0x400)
2741 func (stream, "s");
2742 if (given & 0x200)
2743 func (stream, "x");
2744 if (given & 0x100)
2745 func (stream, "c");
2746 }
2747 else
2748 {
2749 func (stream, psr_name (given & 0xff));
2750 }
2751 break;
2752
2753 case 'D':
2754 if ((given & 0xff) == 0)
2755 func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C');
2756 else
2757 func (stream, psr_name (given & 0xff));
2758 break;
2759
2760 case '0': case '1': case '2': case '3': case '4':
2761 case '5': case '6': case '7': case '8': case '9':
2762 {
2763 int bitstart = *c++ - '0';
2764 int bitend = 0;
2765 unsigned int val;
2766 while (*c >= '0' && *c <= '9')
2767 bitstart = (bitstart * 10) + *c++ - '0';
2768
2769 if (*c == '-')
2770 {
2771 c++;
2772 while (*c >= '0' && *c <= '9')
2773 bitend = (bitend * 10) + *c++ - '0';
2774 if (!bitend)
2775 abort ();
2776
2777 val = given >> bitstart;
2778 val &= (2 << (bitend - bitstart)) - 1;
2779 }
2780 else
2781 val = (given >> bitstart) & 1;
2782
2783 switch (*c)
2784 {
2785 case 'd': func (stream, "%u", val); break;
2786 case 'W': func (stream, "%u", val * 4); break;
2787 case 'r': func (stream, "%s", arm_regnames[val]); break;
2788
2789 case 'c':
2790 if (val == 0xE)
2791 func (stream, "al");
2792 else
2793 func (stream, "%s", arm_conditional[val]);
2794 break;
2795
2796 case '\'':
2797 if (val)
2798 func (stream, "%c", c[1]);
2799 c++;
2800 break;
2801
2802 case '`':
2803 if (!val)
2804 func (stream, "%c", c[1]);
2805 c++;
2806 break;
2807
2808 case '?':
2809 func (stream, "%c", val ? c[1] : c[2]);
2810 c += 2;
2811 break;
2812
2813 default:
2814 abort ();
2815 }
2816 }
2817 break;
2818
2819 default:
2820 abort ();
2821 }
2822 }
2823 return;
2824 }
2825
2826 /* No match. */
2827 abort ();
2828 }
2829
2830 /* Disallow mapping symbols ($a, $b, $d, $t etc) from
2831 being displayed in symbol relative addresses. */
2832
2833 bfd_boolean
arm_symbol_is_valid(asymbol * sym,struct disassemble_info * info ATTRIBUTE_UNUSED)2834 arm_symbol_is_valid (asymbol * sym,
2835 struct disassemble_info * info ATTRIBUTE_UNUSED)
2836 {
2837 const char * name;
2838
2839 if (sym == NULL)
2840 return FALSE;
2841
2842 name = bfd_asymbol_name (sym);
2843
2844 return (name && *name != '$');
2845 }
2846
2847 /* Parse an individual disassembler option. */
2848
2849 void
parse_arm_disassembler_option(char * option)2850 parse_arm_disassembler_option (char *option)
2851 {
2852 if (option == NULL)
2853 return;
2854
2855 if (strneq (option, "reg-names-", 10))
2856 {
2857 int i;
2858
2859 option += 10;
2860
2861 for (i = NUM_ARM_REGNAMES; i--;)
2862 if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
2863 {
2864 regname_selected = i;
2865 break;
2866 }
2867
2868 if (i < 0)
2869 /* XXX - should break 'option' at following delimiter. */
2870 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
2871 }
2872 else if (strneq (option, "force-thumb", 11))
2873 force_thumb = 1;
2874 else if (strneq (option, "no-force-thumb", 14))
2875 force_thumb = 0;
2876 else
2877 /* XXX - should break 'option' at following delimiter. */
2878 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
2879
2880 return;
2881 }
2882
2883 /* Parse the string of disassembler options, spliting it at whitespaces
2884 or commas. (Whitespace separators supported for backwards compatibility). */
2885
2886 static void
parse_disassembler_options(char * options)2887 parse_disassembler_options (char *options)
2888 {
2889 if (options == NULL)
2890 return;
2891
2892 while (*options)
2893 {
2894 parse_arm_disassembler_option (options);
2895
2896 /* Skip forward to next seperator. */
2897 while ((*options) && (! ISSPACE (*options)) && (*options != ','))
2898 ++ options;
2899 /* Skip forward past seperators. */
2900 while (ISSPACE (*options) || (*options == ','))
2901 ++ options;
2902 }
2903 }
2904
2905 /* NOTE: There are no checks in these routines that
2906 the relevant number of data bytes exist. */
2907
2908 static int
print_insn(bfd_vma pc,struct disassemble_info * info,bfd_boolean little)2909 print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
2910 {
2911 unsigned char b[4];
2912 long given;
2913 int status;
2914 int is_thumb;
2915 int size;
2916 void (*printer) (bfd_vma, struct disassemble_info *, long);
2917
2918 if (info->disassembler_options)
2919 {
2920 parse_disassembler_options (info->disassembler_options);
2921
2922 /* To avoid repeated parsing of these options, we remove them here. */
2923 info->disassembler_options = NULL;
2924 }
2925
2926 is_thumb = force_thumb;
2927
2928 if (!is_thumb && info->symbols != NULL)
2929 {
2930 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
2931 {
2932 coff_symbol_type * cs;
2933
2934 cs = coffsymbol (*info->symbols);
2935 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
2936 || cs->native->u.syment.n_sclass == C_THUMBSTAT
2937 || cs->native->u.syment.n_sclass == C_THUMBLABEL
2938 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
2939 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
2940 }
2941 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
2942 {
2943 elf_symbol_type * es;
2944 unsigned int type;
2945
2946 es = *(elf_symbol_type **)(info->symbols);
2947 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
2948
2949 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
2950 }
2951 }
2952
2953 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
2954 info->bytes_per_line = 4;
2955
2956 if (!is_thumb)
2957 {
2958 /* In ARM mode endianness is a straightforward issue: the instruction
2959 is four bytes long and is either ordered 0123 or 3210. */
2960 printer = print_insn_arm;
2961 info->bytes_per_chunk = 4;
2962 size = 4;
2963
2964 status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
2965 if (little)
2966 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
2967 else
2968 given = (b[3]) | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2969 }
2970 else
2971 {
2972 /* In Thumb mode we have the additional wrinkle of two
2973 instruction lengths. Fortunately, the bits that determine
2974 the length of the current instruction are always to be found
2975 in the first two bytes. */
2976 printer = print_insn_thumb16;
2977 info->bytes_per_chunk = 2;
2978 size = 2;
2979
2980 status = info->read_memory_func (pc, (bfd_byte *)b, 2, info);
2981 if (little)
2982 given = (b[0]) | (b[1] << 8);
2983 else
2984 given = (b[1]) | (b[0] << 8);
2985
2986 if (!status)
2987 {
2988 /* These bit patterns signal a four-byte Thumb
2989 instruction. */
2990 if ((given & 0xF800) == 0xF800
2991 || (given & 0xF800) == 0xF000
2992 || (given & 0xF800) == 0xE800)
2993 {
2994 status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info);
2995 if (little)
2996 given = (b[0]) | (b[1] << 8) | (given << 16);
2997 else
2998 given = (b[1]) | (b[0] << 8) | (given << 16);
2999
3000 printer = print_insn_thumb32;
3001 size = 4;
3002 }
3003 }
3004 }
3005
3006 if (status)
3007 {
3008 info->memory_error_func (status, pc, info);
3009 return -1;
3010 }
3011 if (info->flags & INSN_HAS_RELOC)
3012 /* If the instruction has a reloc associated with it, then
3013 the offset field in the instruction will actually be the
3014 addend for the reloc. (We are using REL type relocs).
3015 In such cases, we can ignore the pc when computing
3016 addresses, since the addend is not currently pc-relative. */
3017 pc = 0;
3018
3019 printer (pc, info, given);
3020 return size;
3021 }
3022
3023 int
print_insn_big_arm(bfd_vma pc,struct disassemble_info * info)3024 print_insn_big_arm (bfd_vma pc, struct disassemble_info *info)
3025 {
3026 return print_insn (pc, info, FALSE);
3027 }
3028
3029 int
print_insn_little_arm(bfd_vma pc,struct disassemble_info * info)3030 print_insn_little_arm (bfd_vma pc, struct disassemble_info *info)
3031 {
3032 return print_insn (pc, info, TRUE);
3033 }
3034
3035 void
print_arm_disassembler_options(FILE * stream)3036 print_arm_disassembler_options (FILE *stream)
3037 {
3038 int i;
3039
3040 fprintf (stream, _("\n\
3041 The following ARM specific disassembler options are supported for use with\n\
3042 the -M switch:\n"));
3043
3044 for (i = NUM_ARM_REGNAMES; i--;)
3045 fprintf (stream, " reg-names-%s %*c%s\n",
3046 regnames[i].name,
3047 (int)(14 - strlen (regnames[i].name)), ' ',
3048 regnames[i].description);
3049
3050 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
3051 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
3052 }
3053