2005-11-03 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / opcodes / arm-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARM
0dd132b6 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
060d22b0 3 Free Software Foundation, Inc.
252b5132
RH
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modification by James G. Smith (jsmith@cygnus.co.uk)
6
e16bb312 7 This file is part of libopcodes.
252b5132 8
e16bb312
NC
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.
252b5132 13
e16bb312
NC
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.
252b5132 18
e16bb312
NC
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
f4321104 21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
252b5132 22
cb6a5892 23#include "sysdep.h"
2fbad815 24
252b5132 25#include "dis-asm.h"
2fbad815 26#include "opcode/arm.h"
252b5132 27#include "opintl.h"
31e0f3cd 28#include "safe-ctype.h"
252b5132 29
baf0cc5e 30/* FIXME: This shouldn't be done here. */
6b5d3a4d
ZW
31#include "coff/internal.h"
32#include "libcoff.h"
252b5132
RH
33#include "elf-bfd.h"
34#include "elf/internal.h"
35#include "elf/arm.h"
36
6b5d3a4d 37/* FIXME: Belongs in global header. */
01c7f630 38#ifndef strneq
58efb6c0
NC
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])
01c7f630
NC
44#endif
45
6b5d3a4d
ZW
46struct 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
53struct 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};
b7693d02 59
8f06b2d8 60/* print_insn_coprocessor recognizes the following format control codes:
4a5329c6 61
2fbad815 62 %% %
4a5329c6 63
4a5329c6 64 %c print condition code (always bits 28-31)
4a5329c6 65 %A print address for ldc/stc/ldf/stf instruction
4a5329c6 66 %I print cirrus signed shift immediate: bits 0..3|4..6
4a5329c6
ZW
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
2fbad815
RE
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"
2fbad815
RE
76 %<bitfield>f print a floating point constant if >7 else a
77 floating point register
4a5329c6
ZW
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
2fbad815
RE
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
2fbad815
RE
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
4a5329c6 89
2fbad815 90 %L print as an iWMMXt N/M width field.
4a5329c6 91 %Z print the Immediate of a WSHUFH instruction.
8f06b2d8
PB
92 %l like 'A' except use byte offsets for 'B' & 'H'
93 versions. */
2fbad815 94
8f06b2d8 95/* Common coprocessor opcodes shared between Arm and Thumb-2. */
2fbad815 96
8f06b2d8 97static const struct opcode32 coprocessor_opcodes[] =
2fbad815 98{
2fbad815
RE
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
8f06b2d8
PB
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"},
2fbad815
RE
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"},
22f8fcbd 208 {FPU_VFP_EXT_V1xD, 0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %0y"},
2fbad815
RE
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"},
19590ef7
RE
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"},
2fbad815
RE
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"},
19590ef7
RE
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"},
2fbad815
RE
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
8f06b2d8
PB
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}"},
b13dd07a 384 {0, 0, 0, 0}
2fbad815
RE
385};
386
8f06b2d8
PB
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
406 %<bitfield>r print as an ARM register
407 %<bitfield>d print the bitfield in decimal
408 %<bitfield>W print the bitfield plus one in decimal
409 %<bitfield>x print the bitfield in hex
410 %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
4a5329c6 411
4a5329c6 412 %<bitnum>'c print specified char iff bit is one
8f06b2d8
PB
413 %<bitnum>`c print specified char iff bit is zero
414 %<bitnum>?ab print a if bit is one else print b
4a5329c6 415
8f06b2d8
PB
416 %e print arm SMI operand (bits 0..7,8..19).
417 %E print the LSB and WIDTH fields of a BFI or BFC instruction.
418 %V print the 16-bit immediate field of a MOVT or MOVW instruction. */
2fbad815 419
8f06b2d8
PB
420static const struct opcode32 arm_opcodes[] =
421{
422 /* ARM instructions. */
423 {ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
424 {ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
425 {ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
426 {ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
427 {ARM_EXT_V2S, 0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
428 {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
429 {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
c19d1205
ZW
430
431 /* ARM V6T2 instructions. */
8f06b2d8
PB
432 {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"},
433 {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"},
434 {ARM_EXT_V6T2, 0x00600090, 0x0ff000f0, "mls%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
435 {ARM_EXT_V6T2, 0x006000b0, 0x0f7000f0, "str%cht\t%12-15r, %s"},
436 {ARM_EXT_V6T2, 0x00300090, 0x0f300090, "ldr%c%6's%5?hbt\t%12-15r, %s"},
437 {ARM_EXT_V6T2, 0x03000000, 0x0ff00000, "movw%c\t%12-15r, %V"},
438 {ARM_EXT_V6T2, 0x03400000, 0x0ff00000, "movt%c\t%12-15r, %V"},
439 {ARM_EXT_V6T2, 0x03ff0f30, 0x0fff0ff0, "rbit%c\t%12-15r, %0-3r"},
440 {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"},
885fc257 441
8f06b2d8 442 /* ARM V6Z instructions. */
3eb17e6b 443 {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"},
2fbad815 444
8f06b2d8
PB
445 /* ARM V6K instructions. */
446 {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"},
447 {ARM_EXT_V6K, 0x01d00f9f, 0x0ff00fff, "ldrexb%c\t%12-15r, [%16-19r]"},
448 {ARM_EXT_V6K, 0x01b00f9f, 0x0ff00fff, "ldrexd%c\t%12-15r, [%16-19r]"},
449 {ARM_EXT_V6K, 0x01f00f9f, 0x0ff00fff, "ldrexh%c\t%12-15r, [%16-19r]"},
450 {ARM_EXT_V6K, 0x01c00f90, 0x0ff00ff0, "strexb%c\t%12-15r, %0-3r, [%16-19r]"},
451 {ARM_EXT_V6K, 0x01a00f90, 0x0ff00ff0, "strexd%c\t%12-15r, %0-3r, [%16-19r]"},
452 {ARM_EXT_V6K, 0x01e00f90, 0x0ff00ff0, "strexh%c\t%12-15r, %0-3r, [%16-19r]"},
c19d1205 453
8f06b2d8
PB
454 /* ARM V6K NOP hints. */
455 {ARM_EXT_V6K, 0x0320f001, 0x0fffffff, "yield%c"},
456 {ARM_EXT_V6K, 0x0320f002, 0x0fffffff, "wfe%c"},
457 {ARM_EXT_V6K, 0x0320f003, 0x0fffffff, "wfi%c"},
458 {ARM_EXT_V6K, 0x0320f004, 0x0fffffff, "sev%c"},
459 {ARM_EXT_V6K, 0x0320f000, 0x0fffff00, "nop%c\t{%0-7d}"},
c19d1205 460
8f06b2d8
PB
461 /* ARM V6 instructions. */
462 {ARM_EXT_V6, 0xf1080000, 0xfffdfe3f, "cpsie\t%8'a%7'i%6'f"},
463 {ARM_EXT_V6, 0xf1080000, 0xfffdfe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"},
464 {ARM_EXT_V6, 0xf10C0000, 0xfffdfe3f, "cpsid\t%8'a%7'i%6'f"},
465 {ARM_EXT_V6, 0xf10C0000, 0xfffdfe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"},
466 {ARM_EXT_V6, 0xf1000000, 0xfff1fe20, "cps\t#%0-4d"},
467 {ARM_EXT_V6, 0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"},
468 {ARM_EXT_V6, 0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, LSL #%7-11d"},
469 {ARM_EXT_V6, 0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #32"},
470 {ARM_EXT_V6, 0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #%7-11d"},
471 {ARM_EXT_V6, 0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"},
472 {ARM_EXT_V6, 0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"},
473 {ARM_EXT_V6, 0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"},
474 {ARM_EXT_V6, 0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"},
475 {ARM_EXT_V6, 0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"},
476 {ARM_EXT_V6, 0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"},
477 {ARM_EXT_V6, 0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"},
478 {ARM_EXT_V6, 0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"},
479 {ARM_EXT_V6, 0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"},
480 {ARM_EXT_V6, 0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"},
481 {ARM_EXT_V6, 0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"},
482 {ARM_EXT_V6, 0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"},
483 {ARM_EXT_V6, 0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"},
484 {ARM_EXT_V6, 0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"},
485 {ARM_EXT_V6, 0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"},
486 {ARM_EXT_V6, 0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"},
487 {ARM_EXT_V6, 0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"},
488 {ARM_EXT_V6, 0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"},
489 {ARM_EXT_V6, 0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"},
490 {ARM_EXT_V6, 0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"},
491 {ARM_EXT_V6, 0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"},
492 {ARM_EXT_V6, 0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"},
493 {ARM_EXT_V6, 0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"},
494 {ARM_EXT_V6, 0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"},
495 {ARM_EXT_V6, 0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"},
496 {ARM_EXT_V6, 0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"},
497 {ARM_EXT_V6, 0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"},
498 {ARM_EXT_V6, 0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"},
499 {ARM_EXT_V6, 0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"},
500 {ARM_EXT_V6, 0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"},
501 {ARM_EXT_V6, 0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"},
502 {ARM_EXT_V6, 0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"},
503 {ARM_EXT_V6, 0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"},
504 {ARM_EXT_V6, 0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"},
505 {ARM_EXT_V6, 0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"},
506 {ARM_EXT_V6, 0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"},
507 {ARM_EXT_V6, 0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"},
508 {ARM_EXT_V6, 0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"},
509 {ARM_EXT_V6, 0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"},
510 {ARM_EXT_V6, 0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"},
511 {ARM_EXT_V6, 0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"},
512 {ARM_EXT_V6, 0x06bf0070, 0x0fff0ff0, "sxth%c %12-15r,%0-3r"},
513 {ARM_EXT_V6, 0x06bf0470, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #8"},
514 {ARM_EXT_V6, 0x06bf0870, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #16"},
515 {ARM_EXT_V6, 0x06bf0c70, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #24"},
516 {ARM_EXT_V6, 0x068f0070, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r"},
517 {ARM_EXT_V6, 0x068f0470, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #8"},
518 {ARM_EXT_V6, 0x068f0870, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #16"},
519 {ARM_EXT_V6, 0x068f0c70, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #24"},
520 {ARM_EXT_V6, 0x06af0070, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r"},
521 {ARM_EXT_V6, 0x06af0470, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #8"},
522 {ARM_EXT_V6, 0x06af0870, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #16"},
523 {ARM_EXT_V6, 0x06af0c70, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #24"},
524 {ARM_EXT_V6, 0x06ff0070, 0x0fff0ff0, "uxth%c %12-15r,%0-3r"},
525 {ARM_EXT_V6, 0x06ff0470, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #8"},
526 {ARM_EXT_V6, 0x06ff0870, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #16"},
527 {ARM_EXT_V6, 0x06ff0c70, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #24"},
528 {ARM_EXT_V6, 0x06cf0070, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r"},
529 {ARM_EXT_V6, 0x06cf0470, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #8"},
530 {ARM_EXT_V6, 0x06cf0870, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #16"},
531 {ARM_EXT_V6, 0x06cf0c70, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #24"},
532 {ARM_EXT_V6, 0x06ef0070, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r"},
533 {ARM_EXT_V6, 0x06ef0470, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #8"},
534 {ARM_EXT_V6, 0x06ef0870, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #16"},
535 {ARM_EXT_V6, 0x06ef0c70, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #24"},
536 {ARM_EXT_V6, 0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"},
537 {ARM_EXT_V6, 0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
538 {ARM_EXT_V6, 0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
539 {ARM_EXT_V6, 0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
540 {ARM_EXT_V6, 0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"},
541 {ARM_EXT_V6, 0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
542 {ARM_EXT_V6, 0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
543 {ARM_EXT_V6, 0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
544 {ARM_EXT_V6, 0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"},
545 {ARM_EXT_V6, 0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
546 {ARM_EXT_V6, 0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
547 {ARM_EXT_V6, 0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
548 {ARM_EXT_V6, 0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"},
549 {ARM_EXT_V6, 0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
550 {ARM_EXT_V6, 0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
551 {ARM_EXT_V6, 0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
552 {ARM_EXT_V6, 0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"},
553 {ARM_EXT_V6, 0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
554 {ARM_EXT_V6, 0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
555 {ARM_EXT_V6, 0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
556 {ARM_EXT_V6, 0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"},
557 {ARM_EXT_V6, 0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"},
558 {ARM_EXT_V6, 0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"},
559 {ARM_EXT_V6, 0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"},
f1022c90 560 {ARM_EXT_V6, 0x06800fb0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"},
8f06b2d8
PB
561 {ARM_EXT_V6, 0xf1010000, 0xfffffc00, "setend\t%9?ble"},
562 {ARM_EXT_V6, 0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"},
563 {ARM_EXT_V6, 0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"},
564 {ARM_EXT_V6, 0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
565 {ARM_EXT_V6, 0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
566 {ARM_EXT_V6, 0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
567 {ARM_EXT_V6, 0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
568 {ARM_EXT_V6, 0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"},
569 {ARM_EXT_V6, 0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
570 {ARM_EXT_V6, 0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
571 {ARM_EXT_V6, 0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t#%0-4d%21'!"},
572 {ARM_EXT_V6, 0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"},
573 {ARM_EXT_V6, 0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, LSL #%7-11d"},
574 {ARM_EXT_V6, 0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, ASR #%7-11d"},
575 {ARM_EXT_V6, 0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"},
576 {ARM_EXT_V6, 0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"},
577 {ARM_EXT_V6, 0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
578 {ARM_EXT_V6, 0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"},
579 {ARM_EXT_V6, 0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
580 {ARM_EXT_V6, 0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"},
581 {ARM_EXT_V6, 0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, LSL #%7-11d"},
582 {ARM_EXT_V6, 0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, ASR #%7-11d"},
583 {ARM_EXT_V6, 0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"},
c19d1205 584
8f06b2d8
PB
585 /* V5J instruction. */
586 {ARM_EXT_V5J, 0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
c19d1205 587
8f06b2d8
PB
588 /* V5 Instructions. */
589 {ARM_EXT_V5, 0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
590 {ARM_EXT_V5, 0xfa000000, 0xfe000000, "blx\t%B"},
591 {ARM_EXT_V5, 0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
592 {ARM_EXT_V5, 0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
c19d1205 593
8f06b2d8
PB
594 /* V5E "El Segundo" Instructions. */
595 {ARM_EXT_V5E, 0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
596 {ARM_EXT_V5E, 0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
597 {ARM_EXT_V5E, 0xf450f000, 0xfc70f000, "pld\t%a"},
598 {ARM_EXT_V5ExP, 0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
599 {ARM_EXT_V5ExP, 0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
600 {ARM_EXT_V5ExP, 0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
601 {ARM_EXT_V5ExP, 0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
c19d1205 602
8f06b2d8
PB
603 {ARM_EXT_V5ExP, 0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
604 {ARM_EXT_V5ExP, 0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
c19d1205 605
8f06b2d8
PB
606 {ARM_EXT_V5ExP, 0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
607 {ARM_EXT_V5ExP, 0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
608 {ARM_EXT_V5ExP, 0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
609 {ARM_EXT_V5ExP, 0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
c19d1205 610
8f06b2d8
PB
611 {ARM_EXT_V5ExP, 0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
612 {ARM_EXT_V5ExP, 0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
613 {ARM_EXT_V5ExP, 0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
614 {ARM_EXT_V5ExP, 0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
4a5329c6 615
8f06b2d8
PB
616 {ARM_EXT_V5ExP, 0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
617 {ARM_EXT_V5ExP, 0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
4a5329c6 618
8f06b2d8
PB
619 {ARM_EXT_V5ExP, 0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
620 {ARM_EXT_V5ExP, 0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
621 {ARM_EXT_V5ExP, 0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
622 {ARM_EXT_V5ExP, 0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
c19d1205 623
8f06b2d8
PB
624 /* ARM Instructions. */
625 {ARM_EXT_V1, 0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
626 {ARM_EXT_V1, 0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
627 {ARM_EXT_V1, 0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
628 {ARM_EXT_V1, 0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
629 {ARM_EXT_V1, 0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
630 {ARM_EXT_V1, 0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
631 {ARM_EXT_V1, 0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
632 {ARM_EXT_V1, 0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
633 {ARM_EXT_V1, 0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
634 {ARM_EXT_V1, 0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
635 {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
636 {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
637 {ARM_EXT_V1, 0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
638 {ARM_EXT_V1, 0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
639 {ARM_EXT_V1, 0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
640 {ARM_EXT_V1, 0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
641 {ARM_EXT_V1, 0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
642 {ARM_EXT_V1, 0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
643 {ARM_EXT_V1, 0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
644 {ARM_EXT_V1, 0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
645 {ARM_EXT_V1, 0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
646 {ARM_EXT_V1, 0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
647 {ARM_EXT_V1, 0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
648 {ARM_EXT_V1, 0x06000010, 0x0e000010, "undefined"},
649 {ARM_EXT_V1, 0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
650 {ARM_EXT_V1, 0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
651 {ARM_EXT_V1, 0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
652 {ARM_EXT_V1, 0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
653 {ARM_EXT_V1, 0x0f000000, 0x0f000000, "swi%c\t%0-23x"},
654
655 /* The rest. */
656 {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined instruction %0-31x"},
657 {0, 0x00000000, 0x00000000, 0}
658};
659
660/* print_insn_thumb16 recognizes the following format control codes:
661
662 %S print Thumb register (bits 3..5 as high number if bit 6 set)
663 %D print Thumb register (bits 0..2 as high number if bit 7 set)
664 %<bitfield>I print bitfield as a signed decimal
665 (top bit of range being the sign bit)
666 %N print Thumb register mask (with LR)
667 %O print Thumb register mask (with PC)
668 %M print Thumb register mask
669 %b print CZB's 6-bit unsigned branch destination
670 %s print Thumb right-shift immediate (6..10; 0 == 32).
671 %<bitfield>r print bitfield as an ARM register
672 %<bitfield>d print bitfield as a decimal
673 %<bitfield>H print (bitfield * 2) as a decimal
674 %<bitfield>W print (bitfield * 4) as a decimal
675 %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
676 %<bitfield>B print Thumb branch destination (signed displacement)
677 %<bitfield>c print bitfield as a condition code
678 %<bitnum>'c print specified char iff bit is one
679 %<bitnum>?ab print a if bit is one else print b. */
680
681static const struct opcode16 thumb_opcodes[] =
682{
683 /* Thumb instructions. */
684
685 /* ARM V6K no-argument instructions. */
686 {ARM_EXT_V6K, 0xbf00, 0xffff, "nop"},
687 {ARM_EXT_V6K, 0xbf10, 0xffff, "yield"},
688 {ARM_EXT_V6K, 0xbf20, 0xffff, "wfe"},
689 {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi"},
690 {ARM_EXT_V6K, 0xbf40, 0xffff, "sev"},
691 {ARM_EXT_V6K, 0xbf00, 0xff0f, "nop\t{%4-7d}"},
692
693 /* ARM V6T2 instructions. */
694 {ARM_EXT_V6T2, 0xb900, 0xfd00, "cbnz\t%0-2r, %b"},
695 {ARM_EXT_V6T2, 0xb100, 0xfd00, "cbz\t%0-2r, %b"},
696 {ARM_EXT_V6T2, 0xbf08, 0xff0f, "it\t%4-7c"},
697 {ARM_EXT_V6T2, 0xbf14, 0xff17, "it%3?te\t%4-7c"},
698 {ARM_EXT_V6T2, 0xbf04, 0xff17, "it%3?et\t%4-7c"},
699 {ARM_EXT_V6T2, 0xbf12, 0xff13, "it%3?te%2?te\t%4-7c"},
700 {ARM_EXT_V6T2, 0xbf02, 0xff13, "it%3?et%2?et\t%4-7c"},
701 {ARM_EXT_V6T2, 0xbf11, 0xff11, "it%3?te%2?te%1?te\t%4-7c"},
702 {ARM_EXT_V6T2, 0xbf01, 0xff11, "it%3?et%2?et%1?et\t%4-7c"},
703
704 /* ARM V6. */
705 {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f"},
706 {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f"},
707 {ARM_EXT_V6, 0x4600, 0xffc0, "mov\t%0-2r, %3-5r"},
708 {ARM_EXT_V6, 0xba00, 0xffc0, "rev\t%0-2r, %3-5r"},
709 {ARM_EXT_V6, 0xba40, 0xffc0, "rev16\t%0-2r, %3-5r"},
710 {ARM_EXT_V6, 0xbac0, 0xffc0, "revsh\t%0-2r, %3-5r"},
711 {ARM_EXT_V6, 0xb650, 0xfff7, "setend\t%3?ble"},
712 {ARM_EXT_V6, 0xb200, 0xffc0, "sxth\t%0-2r, %3-5r"},
713 {ARM_EXT_V6, 0xb240, 0xffc0, "sxtb\t%0-2r, %3-5r"},
714 {ARM_EXT_V6, 0xb280, 0xffc0, "uxth\t%0-2r, %3-5r"},
715 {ARM_EXT_V6, 0xb2c0, 0xffc0, "uxtb\t%0-2r, %3-5r"},
716
717 /* ARM V5 ISA extends Thumb. */
718 {ARM_EXT_V5T, 0xbe00, 0xff00, "bkpt\t%0-7x"},
719 /* This is BLX(2). BLX(1) is a 32-bit instruction. */
720 {ARM_EXT_V5T, 0x4780, 0xff87, "blx\t%3-6r"}, /* note: 4 bit register number. */
721 /* ARM V4T ISA (Thumb v1). */
722 {ARM_EXT_V4T, 0x46C0, 0xFFFF, "nop\t\t\t(mov r8, r8)"},
723 /* Format 4. */
724 {ARM_EXT_V4T, 0x4000, 0xFFC0, "ands\t%0-2r, %3-5r"},
725 {ARM_EXT_V4T, 0x4040, 0xFFC0, "eors\t%0-2r, %3-5r"},
726 {ARM_EXT_V4T, 0x4080, 0xFFC0, "lsls\t%0-2r, %3-5r"},
727 {ARM_EXT_V4T, 0x40C0, 0xFFC0, "lsrs\t%0-2r, %3-5r"},
728 {ARM_EXT_V4T, 0x4100, 0xFFC0, "asrs\t%0-2r, %3-5r"},
729 {ARM_EXT_V4T, 0x4140, 0xFFC0, "adcs\t%0-2r, %3-5r"},
730 {ARM_EXT_V4T, 0x4180, 0xFFC0, "sbcs\t%0-2r, %3-5r"},
731 {ARM_EXT_V4T, 0x41C0, 0xFFC0, "rors\t%0-2r, %3-5r"},
732 {ARM_EXT_V4T, 0x4200, 0xFFC0, "tst\t%0-2r, %3-5r"},
733 {ARM_EXT_V4T, 0x4240, 0xFFC0, "negs\t%0-2r, %3-5r"},
734 {ARM_EXT_V4T, 0x4280, 0xFFC0, "cmp\t%0-2r, %3-5r"},
735 {ARM_EXT_V4T, 0x42C0, 0xFFC0, "cmn\t%0-2r, %3-5r"},
736 {ARM_EXT_V4T, 0x4300, 0xFFC0, "orrs\t%0-2r, %3-5r"},
737 {ARM_EXT_V4T, 0x4340, 0xFFC0, "muls\t%0-2r, %3-5r"},
738 {ARM_EXT_V4T, 0x4380, 0xFFC0, "bics\t%0-2r, %3-5r"},
739 {ARM_EXT_V4T, 0x43C0, 0xFFC0, "mvns\t%0-2r, %3-5r"},
740 /* format 13 */
741 {ARM_EXT_V4T, 0xB000, 0xFF80, "add\tsp, #%0-6W"},
742 {ARM_EXT_V4T, 0xB080, 0xFF80, "sub\tsp, #%0-6W"},
743 /* format 5 */
744 {ARM_EXT_V4T, 0x4700, 0xFF80, "bx\t%S"},
745 {ARM_EXT_V4T, 0x4400, 0xFF00, "add\t%D, %S"},
746 {ARM_EXT_V4T, 0x4500, 0xFF00, "cmp\t%D, %S"},
747 {ARM_EXT_V4T, 0x4600, 0xFF00, "mov\t%D, %S"},
748 /* format 14 */
749 {ARM_EXT_V4T, 0xB400, 0xFE00, "push\t%N"},
750 {ARM_EXT_V4T, 0xBC00, 0xFE00, "pop\t%O"},
751 /* format 2 */
752 {ARM_EXT_V4T, 0x1800, 0xFE00, "adds\t%0-2r, %3-5r, %6-8r"},
753 {ARM_EXT_V4T, 0x1A00, 0xFE00, "subs\t%0-2r, %3-5r, %6-8r"},
754 {ARM_EXT_V4T, 0x1C00, 0xFE00, "adds\t%0-2r, %3-5r, #%6-8d"},
755 {ARM_EXT_V4T, 0x1E00, 0xFE00, "subs\t%0-2r, %3-5r, #%6-8d"},
756 /* format 8 */
757 {ARM_EXT_V4T, 0x5200, 0xFE00, "strh\t%0-2r, [%3-5r, %6-8r]"},
758 {ARM_EXT_V4T, 0x5A00, 0xFE00, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
759 {ARM_EXT_V4T, 0x5600, 0xF600, "ldrs%11?hb\t%0-2r, [%3-5r, %6-8r]"},
760 /* format 7 */
761 {ARM_EXT_V4T, 0x5000, 0xFA00, "str%10'b\t%0-2r, [%3-5r, %6-8r]"},
762 {ARM_EXT_V4T, 0x5800, 0xFA00, "ldr%10'b\t%0-2r, [%3-5r, %6-8r]"},
763 /* format 1 */
764 {ARM_EXT_V4T, 0x0000, 0xF800, "lsls\t%0-2r, %3-5r, #%6-10d"},
765 {ARM_EXT_V4T, 0x0800, 0xF800, "lsrs\t%0-2r, %3-5r, %s"},
766 {ARM_EXT_V4T, 0x1000, 0xF800, "asrs\t%0-2r, %3-5r, %s"},
767 /* format 3 */
768 {ARM_EXT_V4T, 0x2000, 0xF800, "movs\t%8-10r, #%0-7d"},
769 {ARM_EXT_V4T, 0x2800, 0xF800, "cmp\t%8-10r, #%0-7d"},
770 {ARM_EXT_V4T, 0x3000, 0xF800, "adds\t%8-10r, #%0-7d"},
771 {ARM_EXT_V4T, 0x3800, 0xF800, "subs\t%8-10r, #%0-7d"},
772 /* format 6 */
773 {ARM_EXT_V4T, 0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
774 /* format 9 */
775 {ARM_EXT_V4T, 0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
776 {ARM_EXT_V4T, 0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
777 {ARM_EXT_V4T, 0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
778 {ARM_EXT_V4T, 0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
779 /* format 10 */
780 {ARM_EXT_V4T, 0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
781 {ARM_EXT_V4T, 0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
782 /* format 11 */
783 {ARM_EXT_V4T, 0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
784 {ARM_EXT_V4T, 0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
785 /* format 12 */
786 {ARM_EXT_V4T, 0xA000, 0xF800, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
787 {ARM_EXT_V4T, 0xA800, 0xF800, "add\t%8-10r, sp, #%0-7W"},
788 /* format 15 */
789 {ARM_EXT_V4T, 0xC000, 0xF800, "stmia\t%8-10r!, %M"},
790 {ARM_EXT_V4T, 0xC800, 0xF800, "ldmia\t%8-10r!, %M"},
791 /* format 17 */
792 {ARM_EXT_V4T, 0xDF00, 0xFF00, "swi\t%0-7d"},
793 /* format 16 */
794 {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B"},
795 /* format 18 */
796 {ARM_EXT_V4T, 0xE000, 0xF800, "b.n\t%0-10B"},
797
798 /* The E800 .. FFFF range is unconditionally redirected to the
799 32-bit table, because even in pre-V6T2 ISAs, BL and BLX(1) pairs
800 are processed via that table. Thus, we can never encounter a
801 bare "second half of BL/BLX(1)" instruction here. */
802 {ARM_EXT_V1, 0x0000, 0x0000, "undefined"},
803 {0, 0, 0, 0}
804};
805
806/* Thumb32 opcodes use the same table structure as the ARM opcodes.
807 We adopt the convention that hw1 is the high 16 bits of .value and
808 .mask, hw2 the low 16 bits.
809
810 print_insn_thumb32 recognizes the following format control codes:
811
812 %% %
813
814 %I print a 12-bit immediate from hw1[10],hw2[14:12,7:0]
815 %M print a modified 12-bit immediate (same location)
816 %J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0]
817 %K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4]
818 %S print a possibly-shifted Rm
819
820 %a print the address of a plain load/store
821 %w print the width and signedness of a core load/store
822 %m print register mask for ldm/stm
823
824 %E print the lsb and width fields of a bfc/bfi instruction
825 %F print the lsb and width fields of a sbfx/ubfx instruction
826 %b print a conditional branch offset
827 %B print an unconditional branch offset
828 %s print the shift field of an SSAT instruction
829 %R print the rotation field of an SXT instruction
830
831 %<bitfield>d print bitfield in decimal
832 %<bitfield>W print bitfield*4 in decimal
833 %<bitfield>r print bitfield as an ARM register
834 %<bitfield>c print bitfield as a condition code
835
836 %<bitnum>'c print "c" iff bit is one
837 %<bitnum>`c print "c" iff bit is zero
838 %<bitnum>?ab print "a" if bit is one, else "b"
839
840 With one exception at the bottom (done because BL and BLX(1) need
841 to come dead last), this table was machine-sorted first in
842 decreasing order of number of bits set in the mask, then in
843 increasing numeric order of mask, then in increasing numeric order
844 of opcode. This order is not the clearest for a human reader, but
845 is guaranteed never to catch a special-case bit pattern with a more
846 general mask, which is important, because this instruction encoding
847 makes heavy use of special-case bit patterns. */
848static const struct opcode32 thumb32_opcodes[] =
849{
850 /* Instructions defined in the basic V6T2 set. */
851 {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop.w"},
852 {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield.w"},
853 {ARM_EXT_V6T2, 0xf3af8002, 0xffffffff, "wfe.w"},
854 {ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi.w"},
855 {ARM_EXT_V6T2, 0xf3af9004, 0xffffffff, "sev.w"},
856 {ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop.w\t{%0-7d}"},
857
858 {ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex"},
859 {ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f"},
860 {ARM_EXT_V6T2, 0xf3af8600, 0xffffff1f, "cpsid.w\t%7'a%6'i%5'f"},
861 {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj\t%16-19r"},
862 {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb\t%16-19r%21'!"},
863 {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia\t%16-19r%21'!"},
864 {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff0ff, "mrs\t%8-11r, %20?CSPSR"},
865 {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d"},
866 {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb\t[%16-19r, %0-3r]"},
867 {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh\t[%16-19r, %0-3r, lsl #1]"},
868 {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d"},
869 {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d"},
c19d1205
ZW
870 {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs\tpc, lr, #%0-7d"},
871 {ARM_EXT_V6T2, 0xf3808000, 0xffe0f0ff, "msr\t%20?CSPSR_%8'c%9'x%10's%11'f, %16-19r"},
872 {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex\t%12-15r, [%16-19r]"},
873 {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb\t%12-15r, [%16-19r]"},
874 {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb\t#%0-4d%21'!"},
875 {ARM_EXT_V6T2, 0xe980c000, 0xffd0ffe0, "srsia\t#%0-4d%21'!"},
876 {ARM_EXT_V6T2, 0xfa0ff080, 0xfffff0c0, "sxth.w\t%8-11r, %0-3r%R"},
877 {ARM_EXT_V6T2, 0xfa1ff080, 0xfffff0c0, "uxth.w\t%8-11r, %0-3r%R"},
878 {ARM_EXT_V6T2, 0xfa2ff080, 0xfffff0c0, "sxtb16\t%8-11r, %0-3r%R"},
879 {ARM_EXT_V6T2, 0xfa3ff080, 0xfffff0c0, "uxtb16\t%8-11r, %0-3r%R"},
880 {ARM_EXT_V6T2, 0xfa4ff080, 0xfffff0c0, "sxtb.w\t%8-11r, %0-3r%R"},
881 {ARM_EXT_V6T2, 0xfa5ff080, 0xfffff0c0, "uxtb.w\t%8-11r, %0-3r%R"},
882 {ARM_EXT_V6T2, 0xe8400000, 0xfff000ff, "strex\t%8-11r, %12-15r, [%16-19r]"},
883 {ARM_EXT_V6T2, 0xe8d0007f, 0xfff000ff, "ldrexd\t%12-15r, %8-11r, [%16-19r]"},
884 {ARM_EXT_V6T2, 0xfa80f000, 0xfff0f0f0, "sadd8\t%8-11r, %16-19r, %0-3r"},
885 {ARM_EXT_V6T2, 0xfa80f010, 0xfff0f0f0, "qadd8\t%8-11r, %16-19r, %0-3r"},
886 {ARM_EXT_V6T2, 0xfa80f020, 0xfff0f0f0, "shadd8\t%8-11r, %16-19r, %0-3r"},
887 {ARM_EXT_V6T2, 0xfa80f040, 0xfff0f0f0, "uadd8\t%8-11r, %16-19r, %0-3r"},
888 {ARM_EXT_V6T2, 0xfa80f050, 0xfff0f0f0, "uqadd8\t%8-11r, %16-19r, %0-3r"},
889 {ARM_EXT_V6T2, 0xfa80f060, 0xfff0f0f0, "uhadd8\t%8-11r, %16-19r, %0-3r"},
890 {ARM_EXT_V6T2, 0xfa80f080, 0xfff0f0f0, "qadd\t%8-11r, %0-3r, %16-19r"},
891 {ARM_EXT_V6T2, 0xfa80f090, 0xfff0f0f0, "qdadd\t%8-11r, %0-3r, %16-19r"},
892 {ARM_EXT_V6T2, 0xfa80f0a0, 0xfff0f0f0, "qsub\t%8-11r, %0-3r, %16-19r"},
893 {ARM_EXT_V6T2, 0xfa80f0b0, 0xfff0f0f0, "qdsub\t%8-11r, %0-3r, %16-19r"},
894 {ARM_EXT_V6T2, 0xfa90f000, 0xfff0f0f0, "sadd16\t%8-11r, %16-19r, %0-3r"},
895 {ARM_EXT_V6T2, 0xfa90f010, 0xfff0f0f0, "qadd16\t%8-11r, %16-19r, %0-3r"},
896 {ARM_EXT_V6T2, 0xfa90f020, 0xfff0f0f0, "shadd16\t%8-11r, %16-19r, %0-3r"},
897 {ARM_EXT_V6T2, 0xfa90f040, 0xfff0f0f0, "uadd16\t%8-11r, %16-19r, %0-3r"},
898 {ARM_EXT_V6T2, 0xfa90f050, 0xfff0f0f0, "uqadd16\t%8-11r, %16-19r, %0-3r"},
899 {ARM_EXT_V6T2, 0xfa90f060, 0xfff0f0f0, "uhadd16\t%8-11r, %16-19r, %0-3r"},
900 {ARM_EXT_V6T2, 0xfa90f080, 0xfff0f0f0, "rev.w\t%8-11r, %16-19r"},
901 {ARM_EXT_V6T2, 0xfa90f090, 0xfff0f0f0, "rev16.w\t%8-11r, %16-19r"},
902 {ARM_EXT_V6T2, 0xfa90f0a0, 0xfff0f0f0, "rbit\t%8-11r, %16-19r"},
903 {ARM_EXT_V6T2, 0xfa90f0b0, 0xfff0f0f0, "revsh.w\t%8-11r, %16-19r"},
904 {ARM_EXT_V6T2, 0xfaa0f000, 0xfff0f0f0, "saddsubx\t%8-11r, %16-19r, %0-3r"},
905 {ARM_EXT_V6T2, 0xfaa0f010, 0xfff0f0f0, "qaddsubx\t%8-11r, %16-19r, %0-3r"},
906 {ARM_EXT_V6T2, 0xfaa0f020, 0xfff0f0f0, "shaddsubx\t%8-11r, %16-19r, %0-3r"},
907 {ARM_EXT_V6T2, 0xfaa0f040, 0xfff0f0f0, "uaddsubx\t%8-11r, %16-19r, %0-3r"},
908 {ARM_EXT_V6T2, 0xfaa0f050, 0xfff0f0f0, "uqaddsubx\t%8-11r, %16-19r, %0-3r"},
909 {ARM_EXT_V6T2, 0xfaa0f060, 0xfff0f0f0, "uhaddsubx\t%8-11r, %16-19r, %0-3r"},
910 {ARM_EXT_V6T2, 0xfaa0f080, 0xfff0f0f0, "sel\t%8-11r, %16-19r, %0-3r"},
911 {ARM_EXT_V6T2, 0xfab0f080, 0xfff0f0f0, "clz\t%8-11r, %16-19r"},
912 {ARM_EXT_V6T2, 0xfac0f000, 0xfff0f0f0, "ssub8\t%8-11r, %16-19r, %0-3r"},
913 {ARM_EXT_V6T2, 0xfac0f010, 0xfff0f0f0, "qsub8\t%8-11r, %16-19r, %0-3r"},
914 {ARM_EXT_V6T2, 0xfac0f020, 0xfff0f0f0, "shsub8\t%8-11r, %16-19r, %0-3r"},
915 {ARM_EXT_V6T2, 0xfac0f040, 0xfff0f0f0, "usub8\t%8-11r, %16-19r, %0-3r"},
916 {ARM_EXT_V6T2, 0xfac0f050, 0xfff0f0f0, "uqsub8\t%8-11r, %16-19r, %0-3r"},
917 {ARM_EXT_V6T2, 0xfac0f060, 0xfff0f0f0, "uhsub8\t%8-11r, %16-19r, %0-3r"},
918 {ARM_EXT_V6T2, 0xfad0f000, 0xfff0f0f0, "ssub16\t%8-11r, %16-19r, %0-3r"},
919 {ARM_EXT_V6T2, 0xfad0f010, 0xfff0f0f0, "qsub16\t%8-11r, %16-19r, %0-3r"},
920 {ARM_EXT_V6T2, 0xfad0f020, 0xfff0f0f0, "shsub16\t%8-11r, %16-19r, %0-3r"},
921 {ARM_EXT_V6T2, 0xfad0f040, 0xfff0f0f0, "usub16\t%8-11r, %16-19r, %0-3r"},
922 {ARM_EXT_V6T2, 0xfad0f050, 0xfff0f0f0, "uqsub16\t%8-11r, %16-19r, %0-3r"},
923 {ARM_EXT_V6T2, 0xfad0f060, 0xfff0f0f0, "uhsub16\t%8-11r, %16-19r, %0-3r"},
924 {ARM_EXT_V6T2, 0xfae0f000, 0xfff0f0f0, "ssubaddx\t%8-11r, %16-19r, %0-3r"},
925 {ARM_EXT_V6T2, 0xfae0f010, 0xfff0f0f0, "qsubaddx\t%8-11r, %16-19r, %0-3r"},
926 {ARM_EXT_V6T2, 0xfae0f020, 0xfff0f0f0, "shsubaddx\t%8-11r, %16-19r, %0-3r"},
927 {ARM_EXT_V6T2, 0xfae0f040, 0xfff0f0f0, "usubaddx\t%8-11r, %16-19r, %0-3r"},
928 {ARM_EXT_V6T2, 0xfae0f050, 0xfff0f0f0, "uqsubaddx\t%8-11r, %16-19r, %0-3r"},
929 {ARM_EXT_V6T2, 0xfae0f060, 0xfff0f0f0, "uhsubaddx\t%8-11r, %16-19r, %0-3r"},
930 {ARM_EXT_V6T2, 0xfb00f000, 0xfff0f0f0, "mul.w\t%8-11r, %16-19r, %0-3r"},
931 {ARM_EXT_V6T2, 0xfb70f000, 0xfff0f0f0, "usad8\t%8-11r, %16-19r, %0-3r"},
932 {ARM_EXT_V6T2, 0xfa00f000, 0xffe0f0f0, "lsl%20's.w\t%8-11r, %16-19r, %0-3r"},
933 {ARM_EXT_V6T2, 0xfa20f000, 0xffe0f0f0, "lsr%20's.w\t%8-11r, %16-19r, %0-3r"},
934 {ARM_EXT_V6T2, 0xfa40f000, 0xffe0f0f0, "asr%20's.w\t%8-11r, %16-19r, %0-3r"},
935 {ARM_EXT_V6T2, 0xfa60f000, 0xffe0f0f0, "ror%20's.w\t%8-11r, %16-19r, %0-3r"},
936 {ARM_EXT_V6T2, 0xe8c00f40, 0xfff00fe0, "strex%4?hb\t%0-3r, %12-15r, [%16-19r]"},
937 {ARM_EXT_V6T2, 0xf3200000, 0xfff0f0e0, "ssat16\t%8-11r, #%0-4d, %16-19r"},
938 {ARM_EXT_V6T2, 0xf3a00000, 0xfff0f0e0, "usat16\t%8-11r, #%0-4d, %16-19r"},
939 {ARM_EXT_V6T2, 0xfb20f000, 0xfff0f0e0, "smuad%4'x\t%8-11r, %16-19r, %0-3r"},
940 {ARM_EXT_V6T2, 0xfb30f000, 0xfff0f0e0, "smulw%4?tb\t%8-11r, %16-19r, %0-3r"},
941 {ARM_EXT_V6T2, 0xfb40f000, 0xfff0f0e0, "smusd%4'x\t%8-11r, %16-19r, %0-3r"},
942 {ARM_EXT_V6T2, 0xfb50f000, 0xfff0f0e0, "smmul%4'r\t%8-11r, %16-19r, %0-3r"},
943 {ARM_EXT_V6T2, 0xfa00f080, 0xfff0f0c0, "sxtah\t%8-11r, %16-19r, %0-3r%R"},
944 {ARM_EXT_V6T2, 0xfa10f080, 0xfff0f0c0, "uxtah\t%8-11r, %16-19r, %0-3r%R"},
945 {ARM_EXT_V6T2, 0xfa20f080, 0xfff0f0c0, "sxtab16\t%8-11r, %16-19r, %0-3r%R"},
946 {ARM_EXT_V6T2, 0xfa30f080, 0xfff0f0c0, "uxtab16\t%8-11r, %16-19r, %0-3r%R"},
947 {ARM_EXT_V6T2, 0xfa40f080, 0xfff0f0c0, "sxtab\t%8-11r, %16-19r, %0-3r%R"},
948 {ARM_EXT_V6T2, 0xfa50f080, 0xfff0f0c0, "uxtab\t%8-11r, %16-19r, %0-3r%R"},
949 {ARM_EXT_V6T2, 0xfb10f000, 0xfff0f0c0, "smul%5?tb%4?tb\t%8-11r, %16-19r, %0-3r"},
950 {ARM_EXT_V6T2, 0xf36f0000, 0xffff8020, "bfc\t%8-11r, %E"},
951 {ARM_EXT_V6T2, 0xea100f00, 0xfff08f00, "tst.w\t%16-19r, %S"},
952 {ARM_EXT_V6T2, 0xea900f00, 0xfff08f00, "teq\t%16-19r, %S"},
953 {ARM_EXT_V6T2, 0xeb100f00, 0xfff08f00, "cmn.w\t%16-19r, %S"},
954 {ARM_EXT_V6T2, 0xebb00f00, 0xfff08f00, "cmp.w\t%16-19r, %S"},
955 {ARM_EXT_V6T2, 0xf0100f00, 0xfbf08f00, "tst.w\t%16-19r, %M"},
956 {ARM_EXT_V6T2, 0xf0900f00, 0xfbf08f00, "teq\t%16-19r, %M"},
957 {ARM_EXT_V6T2, 0xf1100f00, 0xfbf08f00, "cmn.w\t%16-19r, %M"},
958 {ARM_EXT_V6T2, 0xf1b00f00, 0xfbf08f00, "cmp.w\t%16-19r, %M"},
959 {ARM_EXT_V6T2, 0xea4f0000, 0xffef8000, "mov%20's.w\t%8-11r, %S"},
960 {ARM_EXT_V6T2, 0xea6f0000, 0xffef8000, "mvn%20's.w\t%8-11r, %S"},
961 {ARM_EXT_V6T2, 0xe8c00070, 0xfff000f0, "strexd\t%0-3r, %12-15r, %8-11r, [%16-19r]"},
962 {ARM_EXT_V6T2, 0xfb000000, 0xfff000f0, "mla\t%8-11r, %16-19r, %0-3r, %12-15r"},
963 {ARM_EXT_V6T2, 0xfb000010, 0xfff000f0, "mls\t%8-11r, %16-19r, %0-3r, %12-15r"},
964 {ARM_EXT_V6T2, 0xfb700000, 0xfff000f0, "usada8\t%8-11r, %16-19r, %0-3r, %12-15r"},
965 {ARM_EXT_V6T2, 0xfb800000, 0xfff000f0, "smull\t%12-15r, %8-11r, %16-19r, %0-3r"},
966 {ARM_EXT_V6T2, 0xfba00000, 0xfff000f0, "umull\t%12-15r, %8-11r, %16-19r, %0-3r"},
967 {ARM_EXT_V6T2, 0xfbc00000, 0xfff000f0, "smlal\t%12-15r, %8-11r, %16-19r, %0-3r"},
968 {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal\t%12-15r, %8-11r, %16-19r, %0-3r"},
969 {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal\t%12-15r, %8-11r, %16-19r, %0-3r"},
970 {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex\t%12-15r, [%16-19r, #%0-7W]"},
3eb17e6b 971 {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc\t%K"},
c19d1205
ZW
972 {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's.w\t%8-11r, %M"},
973 {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's.w\t%8-11r, %M"},
974 {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld\t%a"},
975 {ARM_EXT_V6T2, 0xfb200000, 0xfff000e0, "smlad%4'x\t%8-11r, %16-19r, %0-3r, %12-15r"},
976 {ARM_EXT_V6T2, 0xfb300000, 0xfff000e0, "smlaw%4?tb\t%8-11r, %16-19r, %0-3r, %12-15r"},
977 {ARM_EXT_V6T2, 0xfb400000, 0xfff000e0, "smlsd%4'x\t%8-11r, %16-19r, %0-3r, %12-15r"},
978 {ARM_EXT_V6T2, 0xfb500000, 0xfff000e0, "smmla%4'r\t%8-11r, %16-19r, %0-3r, %12-15r"},
979 {ARM_EXT_V6T2, 0xfb600000, 0xfff000e0, "smmls%4'r\t%8-11r, %16-19r, %0-3r, %12-15r"},
980 {ARM_EXT_V6T2, 0xfbc000c0, 0xfff000e0, "smlald%4'x\t%12-15r, %8-11r, %16-19r, %0-3r"},
981 {ARM_EXT_V6T2, 0xfbd000c0, 0xfff000e0, "smlsld%4'x\t%12-15r, %8-11r, %16-19r, %0-3r"},
982 {ARM_EXT_V6T2, 0xeac00000, 0xfff08030, "pkhbt\t%8-11r, %16-19r, %S"},
983 {ARM_EXT_V6T2, 0xeac00020, 0xfff08030, "pkhtb\t%8-11r, %16-19r, %S"},
984 {ARM_EXT_V6T2, 0xf3400000, 0xfff08020, "sbfx\t%8-11r, %16-19r, %F"},
985 {ARM_EXT_V6T2, 0xf3c00000, 0xfff08020, "ubfx\t%8-11r, %16-19r, %F"},
986 {ARM_EXT_V6T2, 0xf8000e00, 0xff900f00, "str%wt\t%12-15r, %a"},
987 {ARM_EXT_V6T2, 0xfb100000, 0xfff000c0, "smla%5?tb%4?tb\t%8-11r, %16-19r, %0-3r, %12-15r"},
988 {ARM_EXT_V6T2, 0xfbc00080, 0xfff000c0, "smlal%5?tb%4?tb\t%12-15r, %8-11r, %16-19r, %0-3r"},
989 {ARM_EXT_V6T2, 0xf3600000, 0xfff08020, "bfi\t%8-11r, %16-19r, %E"},
990 {ARM_EXT_V6T2, 0xf8100e00, 0xfe900f00, "ldr%wt\t%12-15r, %a"},
991 {ARM_EXT_V6T2, 0xf3000000, 0xffd08020, "ssat\t%8-11r, #%0-4d, %16-19r%s"},
992 {ARM_EXT_V6T2, 0xf3800000, 0xffd08020, "usat\t%8-11r, #%0-4d, %16-19r%s"},
c19d1205
ZW
993 {ARM_EXT_V6T2, 0xf2000000, 0xfbf08000, "addw\t%8-11r, %16-19r, %I"},
994 {ARM_EXT_V6T2, 0xf2400000, 0xfbf08000, "movw\t%8-11r, %J"},
995 {ARM_EXT_V6T2, 0xf2a00000, 0xfbf08000, "subw\t%8-11r, %16-19r, %I"},
996 {ARM_EXT_V6T2, 0xf2c00000, 0xfbf08000, "movt\t%8-11r, %J"},
997 {ARM_EXT_V6T2, 0xea000000, 0xffe08000, "and%20's.w\t%8-11r, %16-19r, %S"},
998 {ARM_EXT_V6T2, 0xea200000, 0xffe08000, "bic%20's.w\t%8-11r, %16-19r, %S"},
999 {ARM_EXT_V6T2, 0xea400000, 0xffe08000, "orr%20's.w\t%8-11r, %16-19r, %S"},
1000 {ARM_EXT_V6T2, 0xea600000, 0xffe08000, "orn%20's\t%8-11r, %16-19r, %S"},
1001 {ARM_EXT_V6T2, 0xea800000, 0xffe08000, "eor%20's.w\t%8-11r, %16-19r, %S"},
1002 {ARM_EXT_V6T2, 0xeb000000, 0xffe08000, "add%20's.w\t%8-11r, %16-19r, %S"},
1003 {ARM_EXT_V6T2, 0xeb400000, 0xffe08000, "adc%20's.w\t%8-11r, %16-19r, %S"},
1004 {ARM_EXT_V6T2, 0xeb600000, 0xffe08000, "sbc%20's.w\t%8-11r, %16-19r, %S"},
1005 {ARM_EXT_V6T2, 0xeba00000, 0xffe08000, "sub%20's.w\t%8-11r, %16-19r, %S"},
1006 {ARM_EXT_V6T2, 0xebc00000, 0xffe08000, "rsb%20's\t%8-11r, %16-19r, %S"},
1007 {ARM_EXT_V6T2, 0xe8400000, 0xfff00000, "strex\t%8-11r, %12-15r, [%16-19r, #%0-7W]"},
c19d1205
ZW
1008 {ARM_EXT_V6T2, 0xf0000000, 0xfbe08000, "and%20's.w\t%8-11r, %16-19r, %M"},
1009 {ARM_EXT_V6T2, 0xf0200000, 0xfbe08000, "bic%20's.w\t%8-11r, %16-19r, %M"},
1010 {ARM_EXT_V6T2, 0xf0400000, 0xfbe08000, "orr%20's.w\t%8-11r, %16-19r, %M"},
1011 {ARM_EXT_V6T2, 0xf0600000, 0xfbe08000, "orn%20's\t%8-11r, %16-19r, %M"},
1012 {ARM_EXT_V6T2, 0xf0800000, 0xfbe08000, "eor%20's.w\t%8-11r, %16-19r, %M"},
1013 {ARM_EXT_V6T2, 0xf1000000, 0xfbe08000, "add%20's.w\t%8-11r, %16-19r, %M"},
1014 {ARM_EXT_V6T2, 0xf1400000, 0xfbe08000, "adc%20's.w\t%8-11r, %16-19r, %M"},
1015 {ARM_EXT_V6T2, 0xf1600000, 0xfbe08000, "sbc%20's.w\t%8-11r, %16-19r, %M"},
1016 {ARM_EXT_V6T2, 0xf1a00000, 0xfbe08000, "sub%20's.w\t%8-11r, %16-19r, %M"},
1017 {ARM_EXT_V6T2, 0xf1c00000, 0xfbe08000, "rsb%20's\t%8-11r, %16-19r, %M"},
1018 {ARM_EXT_V6T2, 0xe8800000, 0xffd00000, "stmia.w\t%16-19r%21'!, %m"},
1019 {ARM_EXT_V6T2, 0xe8900000, 0xffd00000, "ldmia.w\t%16-19r%21'!, %m"},
1020 {ARM_EXT_V6T2, 0xe9000000, 0xffd00000, "stmdb\t%16-19r%21'!, %m"},
1021 {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb\t%16-19r%21'!, %m"},
1022 {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd\t%12-15r, %8-11r, [%16-19r]"},
1023 {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd\t%12-15r, %8-11r, [%16-19r]"},
1024 {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]"},
1025 {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]"},
c19d1205
ZW
1026 {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w.w\t%12-15r, %a"},
1027 {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w.w\t%12-15r, %a"},
c19d1205
ZW
1028
1029 /* Filter out Bcc with cond=E or F, which are used for other instructions. */
1030 {ARM_EXT_V6T2, 0xf3c08000, 0xfbc0d000, "undefined (bcc, cond=0xF)"},
1031 {ARM_EXT_V6T2, 0xf3808000, 0xfbc0d000, "undefined (bcc, cond=0xE)"},
1032 {ARM_EXT_V6T2, 0xf0008000, 0xf800d000, "b%22-25c.w\t%b"},
1033 {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b.w\t%B"},
1034
8f06b2d8
PB
1035 /* These have been 32-bit since the invention of Thumb. */
1036 {ARM_EXT_V4T, 0xf000c000, 0xf800d000, "blx\t%B"},
1037 {ARM_EXT_V4T, 0xf000d000, 0xf800d000, "bl\t%B"},
1038
1039 /* Fallback. */
1040 {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined"},
1041 {0, 0, 0, 0}
1042};
1043
1044static const char *const arm_conditional[] =
1045{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
1046 "hi", "ls", "ge", "lt", "gt", "le", "", "<und>"};
1047
1048static const char *const arm_fp_const[] =
1049{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
1050
1051static const char *const arm_shift[] =
1052{"lsl", "lsr", "asr", "ror"};
1053
1054typedef struct
1055{
1056 const char *name;
1057 const char *description;
1058 const char *reg_names[16];
1059}
1060arm_regname;
1061
1062static const arm_regname regnames[] =
1063{
1064 { "raw" , "Select raw register names",
1065 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
1066 { "gcc", "Select register names used by GCC",
1067 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
1068 { "std", "Select register names used in ARM's ISA documentation",
1069 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
1070 { "apcs", "Select register names used in the APCS",
1071 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
1072 { "atpcs", "Select register names used in the ATPCS",
1073 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
1074 { "special-atpcs", "Select special register names used in the ATPCS",
1075 { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }},
1076};
1077
1078static const char *const iwmmxt_wwnames[] =
1079{"b", "h", "w", "d"};
1080
1081static const char *const iwmmxt_wwssnames[] =
1082{"b", "bus", "b", "bss",
1083 "h", "hus", "h", "hss",
1084 "w", "wus", "w", "wss",
1085 "d", "dus", "d", "dss"
1086};
1087
1088static const char *const iwmmxt_regnames[] =
1089{ "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7",
1090 "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"
1091};
1092
1093static const char *const iwmmxt_cregnames[] =
1094{ "wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved",
1095 "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"
1096};
1097
1098/* Default to GCC register name set. */
1099static unsigned int regname_selected = 1;
1100
1101#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
1102#define arm_regnames regnames[regname_selected].reg_names
1103
1104static bfd_boolean force_thumb = FALSE;
1105
1106\f
1107/* Functions. */
1108int
1109get_arm_regname_num_options (void)
1110{
1111 return NUM_ARM_REGNAMES;
1112}
1113
1114int
1115set_arm_regname_option (int option)
1116{
1117 int old = regname_selected;
1118 regname_selected = option;
1119 return old;
1120}
1121
1122int
1123get_arm_regnames (int option, const char **setname, const char **setdescription,
1124 const char *const **register_names)
1125{
1126 *setname = regnames[option].name;
1127 *setdescription = regnames[option].description;
1128 *register_names = regnames[option].reg_names;
1129 return 16;
1130}
1131
1132static void
1133arm_decode_shift (long given, fprintf_ftype func, void *stream)
1134{
1135 func (stream, "%s", arm_regnames[given & 0xf]);
1136
1137 if ((given & 0xff0) != 0)
1138 {
1139 if ((given & 0x10) == 0)
1140 {
1141 int amount = (given & 0xf80) >> 7;
1142 int shift = (given & 0x60) >> 5;
1143
1144 if (amount == 0)
1145 {
1146 if (shift == 3)
1147 {
1148 func (stream, ", rrx");
1149 return;
1150 }
1151
1152 amount = 32;
1153 }
1154
1155 func (stream, ", %s #%d", arm_shift[shift], amount);
1156 }
1157 else
1158 func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
1159 arm_regnames[(given & 0xf00) >> 8]);
1160 }
1161}
1162
1163/* Print one coprocessor instruction on INFO->STREAM.
1164 Return TRUE if the instuction matched, FALSE if this is not a
1165 recognised coprocessor instruction. */
1166
1167static bfd_boolean
1168print_insn_coprocessor (struct disassemble_info *info, long given,
1169 bfd_boolean thumb)
1170{
1171 const struct opcode32 *insn;
1172 void *stream = info->stream;
1173 fprintf_ftype func = info->fprintf_func;
1174 unsigned long mask;
1175 unsigned long value;
1176
1177 for (insn = coprocessor_opcodes; insn->assembler; insn++)
1178 {
1179 if (insn->value == FIRST_IWMMXT_INSN
1180 && info->mach != bfd_mach_arm_XScale
1181 && info->mach != bfd_mach_arm_iWMMXt)
1182 insn = insn + IWMMXT_INSN_COUNT;
1183
1184 mask = insn->mask;
1185 value = insn->value;
1186 if (thumb)
1187 {
1188 /* The high 4 bits are 0xe for Arm conditional instructions, and
1189 0xe for arm unconditional instructions. The rest of the
1190 encoding is the same. */
1191 mask |= 0xf0000000;
1192 value |= 0xe0000000;
1193 }
1194 else
1195 {
1196 /* Only match unconditional instuctions against unconditional
1197 patterns. */
1198 if ((given & 0xf0000000) == 0xf0000000)
1199 mask |= 0xf0000000;
1200 }
1201 if ((given & mask) == value)
1202 {
1203 const char *c;
1204
1205 for (c = insn->assembler; *c; c++)
1206 {
1207 if (*c == '%')
1208 {
1209 switch (*++c)
1210 {
1211 case '%':
1212 func (stream, "%%");
1213 break;
1214
1215 case 'A':
1216 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
1217
1218 if ((given & (1 << 24)) != 0)
1219 {
1220 int offset = given & 0xff;
1221
1222 if (offset)
1223 func (stream, ", #%s%d]%s",
1224 ((given & 0x00800000) == 0 ? "-" : ""),
1225 offset * 4,
1226 ((given & 0x00200000) != 0 ? "!" : ""));
1227 else
1228 func (stream, "]");
1229 }
1230 else
1231 {
1232 int offset = given & 0xff;
1233
1234 func (stream, "]");
1235
1236 if (given & (1 << 21))
1237 {
1238 if (offset)
1239 func (stream, ", #%s%d",
1240 ((given & 0x00800000) == 0 ? "-" : ""),
1241 offset * 4);
1242 }
1243 else
1244 func (stream, ", {%d}", offset);
1245 }
1246 break;
1247
1248 case 'c':
1249 func (stream, "%s",
1250 arm_conditional [(given >> 28) & 0xf]);
1251 break;
1252
1253 case 'I':
1254 /* Print a Cirrus/DSP shift immediate. */
1255 /* Immediates are 7bit signed ints with bits 0..3 in
1256 bits 0..3 of opcode and bits 4..6 in bits 5..7
1257 of opcode. */
1258 {
1259 int imm;
1260
1261 imm = (given & 0xf) | ((given & 0xe0) >> 1);
1262
1263 /* Is ``imm'' a negative number? */
1264 if (imm & 0x40)
1265 imm |= (-1 << 7);
1266
1267 func (stream, "%d", imm);
1268 }
1269
1270 break;
1271
1272 case 'F':
1273 switch (given & 0x00408000)
1274 {
1275 case 0:
1276 func (stream, "4");
1277 break;
1278 case 0x8000:
1279 func (stream, "1");
1280 break;
1281 case 0x00400000:
1282 func (stream, "2");
1283 break;
1284 default:
1285 func (stream, "3");
1286 }
1287 break;
1288
1289 case 'P':
1290 switch (given & 0x00080080)
1291 {
1292 case 0:
1293 func (stream, "s");
1294 break;
1295 case 0x80:
1296 func (stream, "d");
1297 break;
1298 case 0x00080000:
1299 func (stream, "e");
1300 break;
1301 default:
1302 func (stream, _("<illegal precision>"));
1303 break;
1304 }
1305 break;
1306 case 'Q':
1307 switch (given & 0x00408000)
1308 {
1309 case 0:
1310 func (stream, "s");
1311 break;
1312 case 0x8000:
1313 func (stream, "d");
1314 break;
1315 case 0x00400000:
1316 func (stream, "e");
1317 break;
1318 default:
1319 func (stream, "p");
1320 break;
1321 }
1322 break;
1323 case 'R':
1324 switch (given & 0x60)
1325 {
1326 case 0:
1327 break;
1328 case 0x20:
1329 func (stream, "p");
1330 break;
1331 case 0x40:
1332 func (stream, "m");
1333 break;
1334 default:
1335 func (stream, "z");
1336 break;
1337 }
1338 break;
1339
1340 case '0': case '1': case '2': case '3': case '4':
1341 case '5': case '6': case '7': case '8': case '9':
1342 {
1343 int bitstart = *c++ - '0';
1344 int bitend = 0;
1345 while (*c >= '0' && *c <= '9')
1346 bitstart = (bitstart * 10) + *c++ - '0';
1347
1348 switch (*c)
1349 {
1350 case '-':
1351 c++;
1352
1353 while (*c >= '0' && *c <= '9')
1354 bitend = (bitend * 10) + *c++ - '0';
1355
1356 if (!bitend)
1357 abort ();
1358
1359 switch (*c)
1360 {
1361 case 'r':
1362 {
1363 long reg;
1364
1365 reg = given >> bitstart;
1366 reg &= (2 << (bitend - bitstart)) - 1;
1367
1368 func (stream, "%s", arm_regnames[reg]);
1369 }
1370 break;
1371 case 'd':
1372 {
1373 long reg;
1374
1375 reg = given >> bitstart;
1376 reg &= (2 << (bitend - bitstart)) - 1;
1377
1378 func (stream, "%ld", reg);
1379 }
1380 break;
1381 case 'f':
1382 {
1383 long reg;
1384
1385 reg = given >> bitstart;
1386 reg &= (2 << (bitend - bitstart)) - 1;
1387
1388 if (reg > 7)
1389 func (stream, "#%s",
1390 arm_fp_const[reg & 7]);
1391 else
1392 func (stream, "f%ld", reg);
1393 }
1394 break;
1395
1396 case 'w':
1397 {
1398 long reg;
1399
1400 if (bitstart != bitend)
1401 {
1402 reg = given >> bitstart;
1403 reg &= (2 << (bitend - bitstart)) - 1;
1404 if (bitend - bitstart == 1)
1405 func (stream, "%s", iwmmxt_wwnames[reg]);
1406 else
1407 func (stream, "%s", iwmmxt_wwssnames[reg]);
1408 }
1409 else
1410 {
1411 reg = (((given >> 8) & 0x1) |
1412 ((given >> 22) & 0x1));
1413 func (stream, "%s", iwmmxt_wwnames[reg]);
1414 }
1415 }
1416 break;
1417
1418 case 'g':
1419 {
1420 long reg;
1421 reg = given >> bitstart;
1422 reg &= (2 << (bitend - bitstart)) - 1;
1423 func (stream, "%s", iwmmxt_regnames[reg]);
1424 }
1425 break;
1426
1427 case 'G':
1428 {
1429 long reg;
1430 reg = given >> bitstart;
1431 reg &= (2 << (bitend - bitstart)) - 1;
1432 func (stream, "%s", iwmmxt_cregnames[reg]);
1433 }
1434 break;
1435
1436 default:
1437 abort ();
1438 }
1439 break;
1440
1441 case 'y':
1442 case 'z':
1443 {
1444 int single = *c == 'y';
1445 int regno;
1446
1447 switch (bitstart)
1448 {
1449 case 4: /* Sm pair */
1450 func (stream, "{");
1451 /* Fall through. */
1452 case 0: /* Sm, Dm */
1453 regno = given & 0x0000000f;
1454 if (single)
1455 {
1456 regno <<= 1;
1457 regno += (given >> 5) & 1;
1458 }
1459 break;
1460
1461 case 1: /* Sd, Dd */
1462 regno = (given >> 12) & 0x0000000f;
1463 if (single)
1464 {
1465 regno <<= 1;
1466 regno += (given >> 22) & 1;
1467 }
1468 break;
c19d1205 1469
8f06b2d8
PB
1470 case 2: /* Sn, Dn */
1471 regno = (given >> 16) & 0x0000000f;
1472 if (single)
1473 {
1474 regno <<= 1;
1475 regno += (given >> 7) & 1;
1476 }
1477 break;
252b5132 1478
8f06b2d8
PB
1479 case 3: /* List */
1480 func (stream, "{");
1481 regno = (given >> 12) & 0x0000000f;
1482 if (single)
1483 {
1484 regno <<= 1;
1485 regno += (given >> 22) & 1;
1486 }
1487 break;
6b5d3a4d 1488
6b5d3a4d 1489
8f06b2d8
PB
1490 default:
1491 abort ();
1492 }
dd92f639 1493
8f06b2d8 1494 func (stream, "%c%d", single ? 's' : 'd', regno);
e16bb312 1495
8f06b2d8
PB
1496 if (bitstart == 3)
1497 {
1498 int count = given & 0xff;
e16bb312 1499
8f06b2d8
PB
1500 if (single == 0)
1501 count >>= 1;
58efb6c0 1502
8f06b2d8
PB
1503 if (--count)
1504 {
1505 func (stream, "-%c%d",
1506 single ? 's' : 'd',
1507 regno + count);
1508 }
6b5d3a4d 1509
8f06b2d8
PB
1510 func (stream, "}");
1511 }
1512 else if (bitstart == 4)
1513 func (stream, ", %c%d}", single ? 's' : 'd',
1514 regno + 1);
6b5d3a4d 1515
8f06b2d8
PB
1516 break;
1517 }
58efb6c0 1518
8f06b2d8 1519 break;
252b5132 1520
8f06b2d8
PB
1521 case '`':
1522 c++;
1523 if ((given & (1 << bitstart)) == 0)
1524 func (stream, "%c", *c);
1525 break;
1526 case '\'':
1527 c++;
1528 if ((given & (1 << bitstart)) != 0)
1529 func (stream, "%c", *c);
1530 break;
1531 case '?':
1532 ++c;
1533 if ((given & (1 << bitstart)) != 0)
1534 func (stream, "%c", *c++);
1535 else
1536 func (stream, "%c", *++c);
1537 break;
1538 default:
1539 abort ();
1540 }
1541 break;
01c7f630 1542
8f06b2d8
PB
1543 case 'L':
1544 switch (given & 0x00400100)
1545 {
1546 case 0x00000000: func (stream, "b"); break;
1547 case 0x00400000: func (stream, "h"); break;
1548 case 0x00000100: func (stream, "w"); break;
1549 case 0x00400100: func (stream, "d"); break;
1550 default:
1551 break;
1552 }
1553 break;
a7f8487e 1554
8f06b2d8
PB
1555 case 'Z':
1556 {
1557 int value;
1558 /* given (20, 23) | given (0, 3) */
1559 value = ((given >> 16) & 0xf0) | (given & 0xf);
1560 func (stream, "%d", value);
1561 }
1562 break;
a7f8487e 1563
8f06b2d8
PB
1564 case 'l':
1565 /* This is like the 'A' operator, except that if
1566 the width field "M" is zero, then the offset is
1567 *not* multiplied by four. */
1568 {
1569 int offset = given & 0xff;
1570 int multiplier = (given & 0x00000100) ? 4 : 1;
a7f8487e 1571
8f06b2d8 1572 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
b34976b6 1573
8f06b2d8
PB
1574 if (offset)
1575 {
1576 if ((given & 0x01000000) != 0)
1577 func (stream, ", #%s%d]%s",
1578 ((given & 0x00800000) == 0 ? "-" : ""),
1579 offset * multiplier,
1580 ((given & 0x00200000) != 0 ? "!" : ""));
1581 else
1582 func (stream, "], #%s%d",
1583 ((given & 0x00800000) == 0 ? "-" : ""),
1584 offset * multiplier);
1585 }
1586 else
1587 func (stream, "]");
1588 }
1589 break;
b34976b6 1590
8f06b2d8
PB
1591 default:
1592 abort ();
1593 }
1594 }
252b5132 1595 }
8f06b2d8
PB
1596 else
1597 func (stream, "%c", *c);
252b5132 1598 }
8f06b2d8 1599 return TRUE;
252b5132 1600 }
252b5132 1601 }
8f06b2d8 1602 return FALSE;
252b5132
RH
1603}
1604
4a5329c6
ZW
1605/* Print one ARM instruction from PC on INFO->STREAM. */
1606
1607static void
1608print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given)
252b5132 1609{
6b5d3a4d 1610 const struct opcode32 *insn;
6a51a8a8 1611 void *stream = info->stream;
6b5d3a4d 1612 fprintf_ftype func = info->fprintf_func;
252b5132 1613
8f06b2d8
PB
1614 if (print_insn_coprocessor (info, given, FALSE))
1615 return;
1616
252b5132
RH
1617 for (insn = arm_opcodes; insn->assembler; insn++)
1618 {
e16bb312
NC
1619 if (insn->value == FIRST_IWMMXT_INSN
1620 && info->mach != bfd_mach_arm_XScale
1621 && info->mach != bfd_mach_arm_iWMMXt)
1622 insn = insn + IWMMXT_INSN_COUNT;
1623
0a003adc
ZW
1624 if ((given & insn->mask) == insn->value
1625 /* Special case: an instruction with all bits set in the condition field
1626 (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask,
1627 or by the catchall at the end of the table. */
1628 && ((given & 0xF0000000) != 0xF0000000
1629 || (insn->mask & 0xF0000000) == 0xF0000000
1630 || (insn->mask == 0 && insn->value == 0)))
252b5132 1631 {
6b5d3a4d 1632 const char *c;
b34976b6 1633
252b5132
RH
1634 for (c = insn->assembler; *c; c++)
1635 {
1636 if (*c == '%')
1637 {
1638 switch (*++c)
1639 {
1640 case '%':
1641 func (stream, "%%");
1642 break;
1643
1644 case 'a':
1645 if (((given & 0x000f0000) == 0x000f0000)
1646 && ((given & 0x02000000) == 0))
1647 {
1648 int offset = given & 0xfff;
b34976b6 1649
252b5132 1650 func (stream, "[pc");
b34976b6 1651
252b5132
RH
1652 if (given & 0x01000000)
1653 {
1654 if ((given & 0x00800000) == 0)
1655 offset = - offset;
b34976b6 1656
baf0cc5e 1657 /* Pre-indexed. */
40536497 1658 func (stream, ", #%d]", offset);
252b5132
RH
1659
1660 offset += pc + 8;
1661
58efb6c0
NC
1662 /* Cope with the possibility of write-back
1663 being used. Probably a very dangerous thing
1664 for the programmer to do, but who are we to
1665 argue ? */
252b5132
RH
1666 if (given & 0x00200000)
1667 func (stream, "!");
1668 }
1669 else
1670 {
58efb6c0 1671 /* Post indexed. */
40536497 1672 func (stream, "], #%d", offset);
252b5132 1673
baf0cc5e
NC
1674 /* ie ignore the offset. */
1675 offset = pc + 8;
252b5132 1676 }
b34976b6 1677
252b5132
RH
1678 func (stream, "\t; ");
1679 info->print_address_func (offset, info);
1680 }
1681 else
1682 {
b34976b6 1683 func (stream, "[%s",
252b5132
RH
1684 arm_regnames[(given >> 16) & 0xf]);
1685 if ((given & 0x01000000) != 0)
1686 {
1687 if ((given & 0x02000000) == 0)
1688 {
1689 int offset = given & 0xfff;
1690 if (offset)
8e6446ff 1691 func (stream, ", #%s%d",
252b5132
RH
1692 (((given & 0x00800000) == 0)
1693 ? "-" : ""), offset);
1694 }
1695 else
1696 {
1697 func (stream, ", %s",
1698 (((given & 0x00800000) == 0)
1699 ? "-" : ""));
1700 arm_decode_shift (given, func, stream);
1701 }
1702
b34976b6 1703 func (stream, "]%s",
252b5132
RH
1704 ((given & 0x00200000) != 0) ? "!" : "");
1705 }
1706 else
1707 {
1708 if ((given & 0x02000000) == 0)
1709 {
1710 int offset = given & 0xfff;
1711 if (offset)
8e6446ff 1712 func (stream, "], #%s%d",
252b5132
RH
1713 (((given & 0x00800000) == 0)
1714 ? "-" : ""), offset);
b34976b6 1715 else
252b5132
RH
1716 func (stream, "]");
1717 }
1718 else
1719 {
1720 func (stream, "], %s",
b34976b6 1721 (((given & 0x00800000) == 0)
252b5132
RH
1722 ? "-" : ""));
1723 arm_decode_shift (given, func, stream);
1724 }
1725 }
1726 }
1727 break;
1728
1729 case 's':
1730 if ((given & 0x004f0000) == 0x004f0000)
1731 {
58efb6c0 1732 /* PC relative with immediate offset. */
252b5132 1733 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
b34976b6 1734
252b5132
RH
1735 if ((given & 0x00800000) == 0)
1736 offset = -offset;
b34976b6 1737
40536497 1738 func (stream, "[pc, #%d]\t; ", offset);
6b5d3a4d 1739 info->print_address_func (offset + pc + 8, info);
252b5132
RH
1740 }
1741 else
1742 {
b34976b6 1743 func (stream, "[%s",
252b5132
RH
1744 arm_regnames[(given >> 16) & 0xf]);
1745 if ((given & 0x01000000) != 0)
1746 {
58efb6c0 1747 /* Pre-indexed. */
252b5132
RH
1748 if ((given & 0x00400000) == 0x00400000)
1749 {
58efb6c0 1750 /* Immediate. */
252b5132
RH
1751 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
1752 if (offset)
8e6446ff 1753 func (stream, ", #%s%d",
252b5132
RH
1754 (((given & 0x00800000) == 0)
1755 ? "-" : ""), offset);
1756 }
1757 else
1758 {
58efb6c0 1759 /* Register. */
252b5132
RH
1760 func (stream, ", %s%s",
1761 (((given & 0x00800000) == 0)
1762 ? "-" : ""),
1763 arm_regnames[given & 0xf]);
1764 }
1765
b34976b6 1766 func (stream, "]%s",
252b5132
RH
1767 ((given & 0x00200000) != 0) ? "!" : "");
1768 }
1769 else
1770 {
58efb6c0 1771 /* Post-indexed. */
252b5132
RH
1772 if ((given & 0x00400000) == 0x00400000)
1773 {
58efb6c0 1774 /* Immediate. */
252b5132
RH
1775 int offset = ((given & 0xf00) >> 4) | (given & 0xf);
1776 if (offset)
8e6446ff 1777 func (stream, "], #%s%d",
252b5132
RH
1778 (((given & 0x00800000) == 0)
1779 ? "-" : ""), offset);
b34976b6 1780 else
252b5132
RH
1781 func (stream, "]");
1782 }
1783 else
1784 {
58efb6c0 1785 /* Register. */
252b5132
RH
1786 func (stream, "], %s%s",
1787 (((given & 0x00800000) == 0)
1788 ? "-" : ""),
1789 arm_regnames[given & 0xf]);
1790 }
1791 }
1792 }
1793 break;
b34976b6 1794
252b5132 1795 case 'b':
6b5d3a4d
ZW
1796 {
1797 int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000);
1798 info->print_address_func (disp*4 + pc + 8, info);
1799 }
252b5132
RH
1800 break;
1801
1802 case 'c':
1803 func (stream, "%s",
1804 arm_conditional [(given >> 28) & 0xf]);
1805 break;
1806
1807 case 'm':
1808 {
1809 int started = 0;
1810 int reg;
1811
1812 func (stream, "{");
1813 for (reg = 0; reg < 16; reg++)
1814 if ((given & (1 << reg)) != 0)
1815 {
1816 if (started)
1817 func (stream, ", ");
1818 started = 1;
1819 func (stream, "%s", arm_regnames[reg]);
1820 }
1821 func (stream, "}");
1822 }
1823 break;
1824
1825 case 'o':
1826 if ((given & 0x02000000) != 0)
1827 {
1828 int rotate = (given & 0xf00) >> 7;
1829 int immed = (given & 0xff);
9f20bbfd
NC
1830 immed = (((immed << (32 - rotate))
1831 | (immed >> rotate)) & 0xffffffff);
1832 func (stream, "#%d\t; 0x%x", immed, immed);
252b5132
RH
1833 }
1834 else
1835 arm_decode_shift (given, func, stream);
1836 break;
1837
1838 case 'p':
1839 if ((given & 0x0000f000) == 0x0000f000)
1840 func (stream, "p");
1841 break;
1842
1843 case 't':
1844 if ((given & 0x01200000) == 0x00200000)
1845 func (stream, "t");
1846 break;
1847
252b5132
RH
1848 case 'A':
1849 func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
f02232aa
NC
1850
1851 if ((given & (1 << 24)) != 0)
252b5132
RH
1852 {
1853 int offset = given & 0xff;
f02232aa 1854
252b5132 1855 if (offset)
8e6446ff 1856 func (stream, ", #%s%d]%s",
252b5132
RH
1857 ((given & 0x00800000) == 0 ? "-" : ""),
1858 offset * 4,
1859 ((given & 0x00200000) != 0 ? "!" : ""));
1860 else
1861 func (stream, "]");
1862 }
1863 else
1864 {
1865 int offset = given & 0xff;
f02232aa
NC
1866
1867 func (stream, "]");
1868
1869 if (given & (1 << 21))
1870 {
1871 if (offset)
8e6446ff 1872 func (stream, ", #%s%d",
f02232aa
NC
1873 ((given & 0x00800000) == 0 ? "-" : ""),
1874 offset * 4);
1875 }
252b5132 1876 else
f02232aa 1877 func (stream, ", {%d}", offset);
252b5132
RH
1878 }
1879 break;
1880
077b8428
NC
1881 case 'B':
1882 /* Print ARM V5 BLX(1) address: pc+25 bits. */
1883 {
1884 bfd_vma address;
1885 bfd_vma offset = 0;
b34976b6 1886
077b8428
NC
1887 if (given & 0x00800000)
1888 /* Is signed, hi bits should be ones. */
1889 offset = (-1) ^ 0x00ffffff;
1890
1891 /* Offset is (SignExtend(offset field)<<2). */
1892 offset += given & 0x00ffffff;
1893 offset <<= 2;
1894 address = offset + pc + 8;
b34976b6 1895
8f06b2d8
PB
1896 if (given & 0x01000000)
1897 /* H bit allows addressing to 2-byte boundaries. */
1898 address += 2;
b1ee46c5 1899
8f06b2d8 1900 info->print_address_func (address, info);
b1ee46c5 1901 }
b1ee46c5
AH
1902 break;
1903
252b5132 1904 case 'C':
6eeeb4b4
AO
1905 func (stream, "_");
1906 if (given & 0x80000)
1907 func (stream, "f");
1908 if (given & 0x40000)
1909 func (stream, "s");
1910 if (given & 0x20000)
1911 func (stream, "x");
1912 if (given & 0x10000)
1913 func (stream, "c");
252b5132
RH
1914 break;
1915
b34976b6 1916 case '0': case '1': case '2': case '3': case '4':
252b5132
RH
1917 case '5': case '6': case '7': case '8': case '9':
1918 {
1919 int bitstart = *c++ - '0';
1920 int bitend = 0;
1921 while (*c >= '0' && *c <= '9')
1922 bitstart = (bitstart * 10) + *c++ - '0';
1923
1924 switch (*c)
1925 {
1926 case '-':
1927 c++;
b34976b6 1928
252b5132
RH
1929 while (*c >= '0' && *c <= '9')
1930 bitend = (bitend * 10) + *c++ - '0';
b34976b6 1931
252b5132
RH
1932 if (!bitend)
1933 abort ();
b34976b6 1934
252b5132
RH
1935 switch (*c)
1936 {
1937 case 'r':
1938 {
1939 long reg;
b34976b6 1940
252b5132
RH
1941 reg = given >> bitstart;
1942 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 1943
252b5132
RH
1944 func (stream, "%s", arm_regnames[reg]);
1945 }
1946 break;
1947 case 'd':
1948 {
1949 long reg;
b34976b6 1950
252b5132
RH
1951 reg = given >> bitstart;
1952 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 1953
0fd3a477 1954 func (stream, "%ld", reg);
252b5132
RH
1955 }
1956 break;
09d92015
MM
1957 case 'W':
1958 {
1959 long reg;
1960
1961 reg = given >> bitstart;
1962 reg &= (2 << (bitend - bitstart)) - 1;
1963
0fd3a477 1964 func (stream, "%ld", reg + 1);
09d92015
MM
1965 }
1966 break;
252b5132
RH
1967 case 'x':
1968 {
1969 long reg;
b34976b6 1970
252b5132
RH
1971 reg = given >> bitstart;
1972 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 1973
0fd3a477 1974 func (stream, "0x%08lx", reg);
b34976b6 1975
58efb6c0
NC
1976 /* Some SWI instructions have special
1977 meanings. */
5876e06d
NC
1978 if ((given & 0x0fffffff) == 0x0FF00000)
1979 func (stream, "\t; IMB");
1980 else if ((given & 0x0fffffff) == 0x0FF00001)
1981 func (stream, "\t; IMBRange");
252b5132
RH
1982 }
1983 break;
cfbd315c
DL
1984 case 'X':
1985 {
1986 long reg;
b34976b6 1987
cfbd315c
DL
1988 reg = given >> bitstart;
1989 reg &= (2 << (bitend - bitstart)) - 1;
b34976b6 1990
0fd3a477 1991 func (stream, "%01lx", reg & 0xf);
cfbd315c
DL
1992 }
1993 break;
252b5132
RH
1994 default:
1995 abort ();
1996 }
1997 break;
a660f11e 1998
252b5132
RH
1999 case '`':
2000 c++;
2001 if ((given & (1 << bitstart)) == 0)
2002 func (stream, "%c", *c);
2003 break;
2004 case '\'':
2005 c++;
2006 if ((given & (1 << bitstart)) != 0)
2007 func (stream, "%c", *c);
2008 break;
2009 case '?':
2010 ++c;
2011 if ((given & (1 << bitstart)) != 0)
2012 func (stream, "%c", *c++);
2013 else
2014 func (stream, "%c", *++c);
2015 break;
2016 default:
2017 abort ();
2018 }
2019 break;
2020
0dd132b6
NC
2021 case 'e':
2022 {
2023 int imm;
2024
2025 imm = (given & 0xf) | ((given & 0xfff00) >> 4);
2026 func (stream, "%d", imm);
2027 }
2028 break;
2029
0a003adc
ZW
2030 case 'E':
2031 /* LSB and WIDTH fields of BFI or BFC. The machine-
2032 language instruction encodes LSB and MSB. */
2033 {
2034 long msb = (given & 0x001f0000) >> 16;
2035 long lsb = (given & 0x00000f80) >> 7;
2036
2037 long width = msb - lsb + 1;
2038 if (width > 0)
2039 func (stream, "#%lu, #%lu", lsb, width);
2040 else
2041 func (stream, "(invalid: %lu:%lu)", lsb, msb);
2042 }
2043 break;
2044
2045 case 'V':
2046 /* 16-bit unsigned immediate from a MOVT or MOVW
2047 instruction, encoded in bits 0:11 and 15:19. */
2048 {
2049 long hi = (given & 0x000f0000) >> 4;
2050 long lo = (given & 0x00000fff);
2051 long imm16 = hi | lo;
2052 func (stream, "#%lu\t; 0x%lx", imm16, imm16);
2053 }
2054 break;
2055
252b5132
RH
2056 default:
2057 abort ();
2058 }
2059 }
2060 }
2061 else
2062 func (stream, "%c", *c);
2063 }
4a5329c6 2064 return;
252b5132
RH
2065 }
2066 }
2067 abort ();
2068}
2069
4a5329c6 2070/* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */
baf0cc5e 2071
4a5329c6
ZW
2072static void
2073print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given)
252b5132 2074{
6b5d3a4d 2075 const struct opcode16 *insn;
6a51a8a8
AM
2076 void *stream = info->stream;
2077 fprintf_ftype func = info->fprintf_func;
252b5132
RH
2078
2079 for (insn = thumb_opcodes; insn->assembler; insn++)
c19d1205
ZW
2080 if ((given & insn->mask) == insn->value)
2081 {
6b5d3a4d 2082 const char *c = insn->assembler;
c19d1205
ZW
2083 for (; *c; c++)
2084 {
2085 int domaskpc = 0;
2086 int domasklr = 0;
2087
2088 if (*c != '%')
2089 {
2090 func (stream, "%c", *c);
2091 continue;
2092 }
252b5132 2093
c19d1205
ZW
2094 switch (*++c)
2095 {
2096 case '%':
2097 func (stream, "%%");
2098 break;
b34976b6 2099
c19d1205
ZW
2100 case 'S':
2101 {
2102 long reg;
2103
2104 reg = (given >> 3) & 0x7;
2105 if (given & (1 << 6))
2106 reg += 8;
4f3c3dbb 2107
c19d1205
ZW
2108 func (stream, "%s", arm_regnames[reg]);
2109 }
2110 break;
baf0cc5e 2111
c19d1205 2112 case 'D':
4f3c3dbb 2113 {
c19d1205
ZW
2114 long reg;
2115
2116 reg = given & 0x7;
2117 if (given & (1 << 7))
2118 reg += 8;
2119
2120 func (stream, "%s", arm_regnames[reg]);
4f3c3dbb 2121 }
c19d1205
ZW
2122 break;
2123
2124 case 'N':
2125 if (given & (1 << 8))
2126 domasklr = 1;
2127 /* Fall through. */
2128 case 'O':
2129 if (*c == 'O' && (given & (1 << 8)))
2130 domaskpc = 1;
2131 /* Fall through. */
2132 case 'M':
2133 {
2134 int started = 0;
2135 int reg;
2136
2137 func (stream, "{");
2138
2139 /* It would be nice if we could spot
2140 ranges, and generate the rS-rE format: */
2141 for (reg = 0; (reg < 8); reg++)
2142 if ((given & (1 << reg)) != 0)
2143 {
2144 if (started)
2145 func (stream, ", ");
2146 started = 1;
2147 func (stream, "%s", arm_regnames[reg]);
2148 }
2149
2150 if (domasklr)
2151 {
2152 if (started)
2153 func (stream, ", ");
2154 started = 1;
2155 func (stream, arm_regnames[14] /* "lr" */);
2156 }
2157
2158 if (domaskpc)
2159 {
2160 if (started)
2161 func (stream, ", ");
2162 func (stream, arm_regnames[15] /* "pc" */);
2163 }
2164
2165 func (stream, "}");
2166 }
2167 break;
2168
2169 case 'b':
2170 /* Print ARM V6T2 CZB address: pc+4+6 bits. */
2171 {
2172 bfd_vma address = (pc + 4
2173 + ((given & 0x00f8) >> 2)
2174 + ((given & 0x0200) >> 3));
2175 info->print_address_func (address, info);
2176 }
2177 break;
2178
2179 case 's':
2180 /* Right shift immediate -- bits 6..10; 1-31 print
2181 as themselves, 0 prints as 32. */
2182 {
2183 long imm = (given & 0x07c0) >> 6;
2184 if (imm == 0)
2185 imm = 32;
0fd3a477 2186 func (stream, "#%ld", imm);
c19d1205
ZW
2187 }
2188 break;
2189
2190 case '0': case '1': case '2': case '3': case '4':
2191 case '5': case '6': case '7': case '8': case '9':
2192 {
2193 int bitstart = *c++ - '0';
2194 int bitend = 0;
2195
2196 while (*c >= '0' && *c <= '9')
2197 bitstart = (bitstart * 10) + *c++ - '0';
2198
2199 switch (*c)
2200 {
2201 case '-':
2202 {
2203 long reg;
2204
2205 c++;
2206 while (*c >= '0' && *c <= '9')
2207 bitend = (bitend * 10) + *c++ - '0';
2208 if (!bitend)
2209 abort ();
2210 reg = given >> bitstart;
2211 reg &= (2 << (bitend - bitstart)) - 1;
2212 switch (*c)
2213 {
2214 case 'r':
2215 func (stream, "%s", arm_regnames[reg]);
2216 break;
2217
2218 case 'd':
0fd3a477 2219 func (stream, "%ld", reg);
c19d1205
ZW
2220 break;
2221
2222 case 'H':
0fd3a477 2223 func (stream, "%ld", reg << 1);
c19d1205
ZW
2224 break;
2225
2226 case 'W':
0fd3a477 2227 func (stream, "%ld", reg << 2);
c19d1205
ZW
2228 break;
2229
2230 case 'a':
2231 /* PC-relative address -- the bottom two
2232 bits of the address are dropped
2233 before the calculation. */
2234 info->print_address_func
2235 (((pc + 4) & ~3) + (reg << 2), info);
2236 break;
2237
2238 case 'x':
0fd3a477 2239 func (stream, "0x%04lx", reg);
c19d1205
ZW
2240 break;
2241
c19d1205
ZW
2242 case 'B':
2243 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
6b5d3a4d 2244 info->print_address_func (reg * 2 + pc + 4, info);
c19d1205
ZW
2245 break;
2246
2247 case 'c':
2248 {
2249 /* Must print 0xE as 'al' to distinguish
2250 unconditional B from conditional BAL. */
2251 if (reg == 0xE)
2252 func (stream, "al");
2253 else
2254 func (stream, "%s", arm_conditional [reg]);
2255 }
2256 break;
2257
2258 default:
2259 abort ();
2260 }
2261 }
2262 break;
2263
2264 case '\'':
2265 c++;
2266 if ((given & (1 << bitstart)) != 0)
2267 func (stream, "%c", *c);
2268 break;
2269
2270 case '?':
2271 ++c;
2272 if ((given & (1 << bitstart)) != 0)
2273 func (stream, "%c", *c++);
2274 else
2275 func (stream, "%c", *++c);
2276 break;
2277
2278 default:
2279 abort ();
2280 }
2281 }
2282 break;
2283
2284 default:
2285 abort ();
2286 }
2287 }
4a5329c6 2288 return;
c19d1205
ZW
2289 }
2290
2291 /* No match. */
2292 abort ();
2293}
2294
4a5329c6
ZW
2295/* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */
2296
2297static void
2298print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
c19d1205 2299{
6b5d3a4d 2300 const struct opcode32 *insn;
c19d1205
ZW
2301 void *stream = info->stream;
2302 fprintf_ftype func = info->fprintf_func;
2303
8f06b2d8
PB
2304 if (print_insn_coprocessor (info, given, TRUE))
2305 return;
2306
c19d1205
ZW
2307 for (insn = thumb32_opcodes; insn->assembler; insn++)
2308 if ((given & insn->mask) == insn->value)
2309 {
6b5d3a4d 2310 const char *c = insn->assembler;
c19d1205
ZW
2311 for (; *c; c++)
2312 {
2313 if (*c != '%')
2314 {
2315 func (stream, "%c", *c);
2316 continue;
2317 }
2318
2319 switch (*++c)
2320 {
2321 case '%':
2322 func (stream, "%%");
2323 break;
2324
2325 case 'I':
2326 {
2327 unsigned int imm12 = 0;
2328 imm12 |= (given & 0x000000ffu);
2329 imm12 |= (given & 0x00007000u) >> 4;
92e90b6e 2330 imm12 |= (given & 0x04000000u) >> 15;
c19d1205
ZW
2331 func (stream, "#%u\t; 0x%x", imm12, imm12);
2332 }
2333 break;
2334
2335 case 'M':
2336 {
2337 unsigned int bits = 0, imm, imm8, mod;
2338 bits |= (given & 0x000000ffu);
2339 bits |= (given & 0x00007000u) >> 4;
2340 bits |= (given & 0x04000000u) >> 15;
2341 imm8 = (bits & 0x0ff);
2342 mod = (bits & 0xf00) >> 8;
2343 switch (mod)
2344 {
2345 case 0: imm = imm8; break;
2346 case 1: imm = ((imm8<<16) | imm8); break;
2347 case 2: imm = ((imm8<<24) | (imm8 << 8)); break;
2348 case 3: imm = ((imm8<<24) | (imm8 << 16) | (imm8 << 8) | imm8); break;
2349 default:
2350 mod = (bits & 0xf80) >> 7;
2351 imm8 = (bits & 0x07f) | 0x80;
2352 imm = (((imm8 << (32 - mod)) | (imm8 >> mod)) & 0xffffffff);
2353 }
2354 func (stream, "#%u\t; 0x%x", imm, imm);
2355 }
2356 break;
2357
2358 case 'J':
2359 {
2360 unsigned int imm = 0;
2361 imm |= (given & 0x000000ffu);
2362 imm |= (given & 0x00007000u) >> 4;
2363 imm |= (given & 0x04000000u) >> 15;
2364 imm |= (given & 0x000f0000u) >> 4;
2365 func (stream, "#%u\t; 0x%x", imm, imm);
2366 }
2367 break;
2368
2369 case 'K':
2370 {
2371 unsigned int imm = 0;
2372 imm |= (given & 0x000f0000u) >> 16;
2373 imm |= (given & 0x00000ff0u) >> 0;
2374 imm |= (given & 0x0000000fu) << 12;
2375 func (stream, "#%u\t; 0x%x", imm, imm);
2376 }
2377 break;
2378
2379 case 'S':
2380 {
2381 unsigned int reg = (given & 0x0000000fu);
2382 unsigned int stp = (given & 0x00000030u) >> 4;
2383 unsigned int imm = 0;
2384 imm |= (given & 0x000000c0u) >> 6;
2385 imm |= (given & 0x00007000u) >> 10;
2386
2387 func (stream, "%s", arm_regnames[reg]);
2388 switch (stp)
2389 {
2390 case 0:
2391 if (imm > 0)
2392 func (stream, ", lsl #%u", imm);
2393 break;
2394
2395 case 1:
2396 if (imm == 0)
2397 imm = 32;
2398 func (stream, ", lsr #%u", imm);
2399 break;
2400
2401 case 2:
2402 if (imm == 0)
2403 imm = 32;
2404 func (stream, ", asr #%u", imm);
2405 break;
2406
2407 case 3:
2408 if (imm == 0)
2409 func (stream, ", rrx");
2410 else
2411 func (stream, ", ror #%u", imm);
2412 }
2413 }
2414 break;
2415
2416 case 'a':
2417 {
2418 unsigned int Rn = (given & 0x000f0000) >> 16;
2419 unsigned int U = (given & 0x00800000) >> 23;
2420 unsigned int op = (given & 0x00000f00) >> 8;
2421 unsigned int i12 = (given & 0x00000fff);
2422 unsigned int i8 = (given & 0x000000ff);
2423 bfd_boolean writeback = FALSE, postind = FALSE;
2424 int offset = 0;
2425
2426 func (stream, "[%s", arm_regnames[Rn]);
2427 if (U) /* 12-bit positive immediate offset */
2428 offset = i12;
2429 else if (Rn == 15) /* 12-bit negative immediate offset */
2430 offset = -(int)i12;
2431 else if (op == 0x0) /* shifted register offset */
2432 {
2433 unsigned int Rm = (i8 & 0x0f);
2434 unsigned int sh = (i8 & 0x30) >> 4;
2435 func (stream, ", %s", arm_regnames[Rm]);
2436 if (sh)
2437 func (stream, ", lsl #%u", sh);
2438 func (stream, "]");
2439 break;
2440 }
2441 else switch (op)
2442 {
2443 case 0xE: /* 8-bit positive immediate offset */
2444 offset = i8;
2445 break;
2446
2447 case 0xC: /* 8-bit negative immediate offset */
2448 offset = -i8;
2449 break;
2450
e9f89963 2451 case 0xF: /* 8-bit + preindex with wb */
c19d1205
ZW
2452 offset = i8;
2453 writeback = TRUE;
2454 break;
2455
e9f89963 2456 case 0xD: /* 8-bit - preindex with wb */
c19d1205
ZW
2457 offset = -i8;
2458 writeback = TRUE;
2459 break;
2460
e9f89963 2461 case 0xB: /* 8-bit + postindex */
c19d1205
ZW
2462 offset = i8;
2463 postind = TRUE;
2464 break;
2465
e9f89963 2466 case 0x9: /* 8-bit - postindex */
c19d1205
ZW
2467 offset = -i8;
2468 postind = TRUE;
2469 break;
2470
2471 default:
2472 func (stream, ", <undefined>]");
2473 goto skip;
2474 }
2475
2476 if (postind)
2477 func (stream, "], #%d", offset);
2478 else
2479 {
2480 if (offset)
2481 func (stream, ", #%d", offset);
2482 func (stream, writeback ? "]!" : "]");
2483 }
2484
2485 if (Rn == 15)
2486 {
2487 func (stream, "\t; ");
2488 info->print_address_func (((pc + 4) & ~3) + offset, info);
2489 }
2490 }
2491 skip:
2492 break;
2493
2494 case 'A':
2495 {
2496 unsigned int P = (given & 0x01000000) >> 24;
2497 unsigned int U = (given & 0x00800000) >> 23;
2498 unsigned int W = (given & 0x00400000) >> 21;
2499 unsigned int Rn = (given & 0x000f0000) >> 16;
2500 unsigned int off = (given & 0x000000ff);
2501
2502 func (stream, "[%s", arm_regnames[Rn]);
2503 if (P)
2504 {
2505 if (off || !U)
2506 func (stream, ", #%c%u", U ? '+' : '-', off * 4);
2507 func (stream, "]");
2508 if (W)
2509 func (stream, "!");
2510 }
2511 else
2512 {
2513 func (stream, "], ");
2514 if (W)
2515 func (stream, "#%c%u", U ? '+' : '-', off * 4);
2516 else
2517 func (stream, "{%u}", off);
2518 }
2519 }
2520 break;
2521
2522 case 'w':
2523 {
2524 unsigned int Sbit = (given & 0x01000000) >> 24;
2525 unsigned int type = (given & 0x00600000) >> 21;
2526 switch (type)
2527 {
2528 case 0: func (stream, Sbit ? "sb" : "b"); break;
2529 case 1: func (stream, Sbit ? "sh" : "h"); break;
2530 case 2:
2531 if (Sbit)
2532 func (stream, "??");
2533 break;
2534 case 3:
2535 func (stream, "??");
2536 break;
2537 }
2538 }
2539 break;
2540
2541 case 'm':
2542 {
2543 int started = 0;
2544 int reg;
2545
2546 func (stream, "{");
2547 for (reg = 0; reg < 16; reg++)
2548 if ((given & (1 << reg)) != 0)
2549 {
2550 if (started)
2551 func (stream, ", ");
2552 started = 1;
2553 func (stream, "%s", arm_regnames[reg]);
2554 }
2555 func (stream, "}");
2556 }
2557 break;
2558
2559 case 'E':
2560 {
2561 unsigned int msb = (given & 0x0000001f);
2562 unsigned int lsb = 0;
2563 lsb |= (given & 0x000000c0u) >> 6;
2564 lsb |= (given & 0x00007000u) >> 10;
2565 func (stream, "#%u, #%u", lsb, msb - lsb + 1);
2566 }
2567 break;
2568
2569 case 'F':
2570 {
2571 unsigned int width = (given & 0x0000001f) + 1;
2572 unsigned int lsb = 0;
2573 lsb |= (given & 0x000000c0u) >> 6;
2574 lsb |= (given & 0x00007000u) >> 10;
2575 func (stream, "#%u, #%u", lsb, width);
2576 }
2577 break;
2578
2579 case 'b':
2580 {
2581 unsigned int S = (given & 0x04000000u) >> 26;
2582 unsigned int J1 = (given & 0x00002000u) >> 13;
2583 unsigned int J2 = (given & 0x00000800u) >> 11;
2584 int offset = 0;
2585
2586 offset |= !S << 20;
2587 offset |= J2 << 19;
2588 offset |= J1 << 18;
2589 offset |= (given & 0x003f0000) >> 4;
2590 offset |= (given & 0x000007ff) << 1;
2591 offset -= (1 << 20);
2592
2593 info->print_address_func (pc + 4 + offset, info);
2594 }
2595 break;
2596
2597 case 'B':
2598 {
2599 unsigned int S = (given & 0x04000000u) >> 26;
2600 unsigned int I1 = (given & 0x00002000u) >> 13;
2601 unsigned int I2 = (given & 0x00000800u) >> 11;
2602 int offset = 0;
2603
2604 offset |= !S << 24;
2605 offset |= !(I1 ^ S) << 23;
2606 offset |= !(I2 ^ S) << 22;
2607 offset |= (given & 0x03ff0000u) >> 4;
2608 offset |= (given & 0x000007ffu) << 1;
2609 offset -= (1 << 24);
36b0c57d 2610 offset += pc + 4;
c19d1205 2611
36b0c57d
PB
2612 /* BLX target addresses are always word aligned. */
2613 if ((given & 0x00001000u) == 0)
2614 offset &= ~2u;
2615
2616 info->print_address_func (offset, info);
c19d1205
ZW
2617 }
2618 break;
2619
2620 case 's':
2621 {
2622 unsigned int shift = 0;
2623 shift |= (given & 0x000000c0u) >> 6;
2624 shift |= (given & 0x00007000u) >> 10;
2625 if (given & 0x00200000u)
2626 func (stream, ", asr #%u", shift);
2627 else if (shift)
2628 func (stream, ", lsl #%u", shift);
2629 /* else print nothing - lsl #0 */
2630 }
2631 break;
2632
2633 case 'R':
2634 {
2635 unsigned int rot = (given & 0x00000030) >> 4;
2636 if (rot)
2637 func (stream, ", ror #%u", rot * 8);
2638 }
2639 break;
2640
2641 case '0': case '1': case '2': case '3': case '4':
2642 case '5': case '6': case '7': case '8': case '9':
2643 {
2644 int bitstart = *c++ - '0';
2645 int bitend = 0;
2646 unsigned int val;
2647 while (*c >= '0' && *c <= '9')
2648 bitstart = (bitstart * 10) + *c++ - '0';
2649
2650 if (*c == '-')
2651 {
2652 c++;
2653 while (*c >= '0' && *c <= '9')
2654 bitend = (bitend * 10) + *c++ - '0';
2655 if (!bitend)
2656 abort ();
2657
2658 val = given >> bitstart;
2659 val &= (2 << (bitend - bitstart)) - 1;
2660 }
2661 else
2662 val = (given >> bitstart) & 1;
2663
2664 switch (*c)
2665 {
2666 case 'd': func (stream, "%u", val); break;
2667 case 'W': func (stream, "%u", val * 4); break;
2668 case 'r': func (stream, "%s", arm_regnames[val]); break;
2669
2670 case 'c':
2671 if (val == 0xE)
2672 func (stream, "al");
2673 else
2674 func (stream, "%s", arm_conditional[val]);
2675 break;
2676
2677 case '\'':
2678 if (val)
2679 func (stream, "%c", c[1]);
2680 c++;
2681 break;
2682
2683 case '`':
2684 if (!val)
2685 func (stream, "%c", c[1]);
2686 c++;
2687 break;
2688
2689 case '?':
2690 func (stream, "%c", val ? c[1] : c[2]);
2691 c += 2;
2692 break;
2693
2694 default:
2695 abort ();
2696 }
2697 }
2698 break;
2699
2700 default:
2701 abort ();
2702 }
2703 }
4a5329c6 2704 return;
c19d1205 2705 }
252b5132 2706
58efb6c0 2707 /* No match. */
252b5132
RH
2708 abort ();
2709}
2710
22a398e1
NC
2711/* Disallow mapping symbols ($a, $b, $d, $t etc) from
2712 being displayed in symbol relative addresses. */
2713
2714bfd_boolean
2715arm_symbol_is_valid (asymbol * sym,
2716 struct disassemble_info * info ATTRIBUTE_UNUSED)
2717{
2718 const char * name;
2719
2720 if (sym == NULL)
2721 return FALSE;
2722
2723 name = bfd_asymbol_name (sym);
2724
2725 return (name && *name != '$');
2726}
2727
58efb6c0 2728/* Parse an individual disassembler option. */
baf0cc5e 2729
a3d9c82d 2730void
4a5329c6 2731parse_arm_disassembler_option (char *option)
dd92f639 2732{
01c7f630 2733 if (option == NULL)
dd92f639 2734 return;
b34976b6 2735
01c7f630 2736 if (strneq (option, "reg-names-", 10))
dd92f639 2737 {
58efb6c0 2738 int i;
b34976b6 2739
01c7f630 2740 option += 10;
58efb6c0
NC
2741
2742 for (i = NUM_ARM_REGNAMES; i--;)
31e0f3cd 2743 if (strneq (option, regnames[i].name, strlen (regnames[i].name)))
58efb6c0
NC
2744 {
2745 regname_selected = i;
2746 break;
2747 }
b34976b6 2748
58efb6c0 2749 if (i < 0)
31e0f3cd 2750 /* XXX - should break 'option' at following delimiter. */
58efb6c0 2751 fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
dd92f639 2752 }
31e0f3cd 2753 else if (strneq (option, "force-thumb", 11))
01c7f630 2754 force_thumb = 1;
31e0f3cd 2755 else if (strneq (option, "no-force-thumb", 14))
01c7f630 2756 force_thumb = 0;
dd92f639 2757 else
31e0f3cd 2758 /* XXX - should break 'option' at following delimiter. */
58efb6c0 2759 fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
b34976b6 2760
dd92f639
NC
2761 return;
2762}
2763
31e0f3cd
NC
2764/* Parse the string of disassembler options, spliting it at whitespaces
2765 or commas. (Whitespace separators supported for backwards compatibility). */
baf0cc5e 2766
01c7f630 2767static void
4a5329c6 2768parse_disassembler_options (char *options)
01c7f630 2769{
01c7f630
NC
2770 if (options == NULL)
2771 return;
2772
31e0f3cd 2773 while (*options)
01c7f630 2774 {
31e0f3cd
NC
2775 parse_arm_disassembler_option (options);
2776
2777 /* Skip forward to next seperator. */
2778 while ((*options) && (! ISSPACE (*options)) && (*options != ','))
2779 ++ options;
2780 /* Skip forward past seperators. */
2781 while (ISSPACE (*options) || (*options == ','))
2782 ++ options;
01c7f630 2783 }
01c7f630
NC
2784}
2785
58efb6c0
NC
2786/* NOTE: There are no checks in these routines that
2787 the relevant number of data bytes exist. */
baf0cc5e 2788
58efb6c0 2789static int
4a5329c6 2790print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
252b5132 2791{
c19d1205
ZW
2792 unsigned char b[4];
2793 long given;
2794 int status;
2795 int is_thumb;
4a5329c6
ZW
2796 int size;
2797 void (*printer) (bfd_vma, struct disassemble_info *, long);
58efb6c0 2798
dd92f639
NC
2799 if (info->disassembler_options)
2800 {
2801 parse_disassembler_options (info->disassembler_options);
b34976b6 2802
58efb6c0 2803 /* To avoid repeated parsing of these options, we remove them here. */
dd92f639
NC
2804 info->disassembler_options = NULL;
2805 }
b34976b6 2806
01c7f630 2807 is_thumb = force_thumb;
b34976b6 2808
01c7f630 2809 if (!is_thumb && info->symbols != NULL)
252b5132 2810 {
5876e06d
NC
2811 if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
2812 {
2f0ca46a 2813 coff_symbol_type * cs;
b34976b6 2814
5876e06d
NC
2815 cs = coffsymbol (*info->symbols);
2816 is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
2817 || cs->native->u.syment.n_sclass == C_THUMBSTAT
2818 || cs->native->u.syment.n_sclass == C_THUMBLABEL
2819 || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
2820 || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
2821 }
2822 else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
2823 {
2f0ca46a 2824 elf_symbol_type * es;
58efb6c0 2825 unsigned int type;
b34976b6 2826
5876e06d 2827 es = *(elf_symbol_type **)(info->symbols);
58efb6c0 2828 type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
b34976b6 2829
58efb6c0 2830 is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
5876e06d
NC
2831 }
2832 }
b34976b6 2833
58efb6c0 2834 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
c19d1205 2835 info->bytes_per_line = 4;
252b5132 2836
c19d1205 2837 if (!is_thumb)
252b5132 2838 {
c19d1205
ZW
2839 /* In ARM mode endianness is a straightforward issue: the instruction
2840 is four bytes long and is either ordered 0123 or 3210. */
2841 printer = print_insn_arm;
2842 info->bytes_per_chunk = 4;
4a5329c6 2843 size = 4;
c19d1205
ZW
2844
2845 status = info->read_memory_func (pc, (bfd_byte *)b, 4, info);
2846 if (little)
2847 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
2848 else
2849 given = (b[3]) | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
252b5132 2850 }
58efb6c0 2851 else
252b5132 2852 {
c19d1205
ZW
2853 /* In Thumb mode we have the additional wrinkle of two
2854 instruction lengths. Fortunately, the bits that determine
2855 the length of the current instruction are always to be found
2856 in the first two bytes. */
4a5329c6 2857 printer = print_insn_thumb16;
c19d1205 2858 info->bytes_per_chunk = 2;
4a5329c6
ZW
2859 size = 2;
2860
c19d1205 2861 status = info->read_memory_func (pc, (bfd_byte *)b, 2, info);
9a2ff3f5
AM
2862 if (little)
2863 given = (b[0]) | (b[1] << 8);
2864 else
2865 given = (b[1]) | (b[0] << 8);
2866
c19d1205 2867 if (!status)
252b5132 2868 {
c19d1205
ZW
2869 /* These bit patterns signal a four-byte Thumb
2870 instruction. */
2871 if ((given & 0xF800) == 0xF800
2872 || (given & 0xF800) == 0xF000
2873 || (given & 0xF800) == 0xE800)
252b5132 2874 {
c19d1205
ZW
2875 status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info);
2876 if (little)
2877 given = (b[0]) | (b[1] << 8) | (given << 16);
b7693d02 2878 else
c19d1205
ZW
2879 given = (b[1]) | (b[0] << 8) | (given << 16);
2880
2881 printer = print_insn_thumb32;
4a5329c6 2882 size = 4;
252b5132 2883 }
252b5132 2884 }
252b5132 2885 }
b34976b6 2886
c19d1205
ZW
2887 if (status)
2888 {
2889 info->memory_error_func (status, pc, info);
2890 return -1;
2891 }
6a56ec7e
NC
2892 if (info->flags & INSN_HAS_RELOC)
2893 /* If the instruction has a reloc associated with it, then
2894 the offset field in the instruction will actually be the
2895 addend for the reloc. (We are using REL type relocs).
2896 In such cases, we can ignore the pc when computing
2897 addresses, since the addend is not currently pc-relative. */
2898 pc = 0;
b34976b6 2899
4a5329c6
ZW
2900 printer (pc, info, given);
2901 return size;
252b5132
RH
2902}
2903
2904int
4a5329c6 2905print_insn_big_arm (bfd_vma pc, struct disassemble_info *info)
252b5132 2906{
b34976b6 2907 return print_insn (pc, info, FALSE);
58efb6c0 2908}
01c7f630 2909
58efb6c0 2910int
4a5329c6 2911print_insn_little_arm (bfd_vma pc, struct disassemble_info *info)
58efb6c0 2912{
b34976b6 2913 return print_insn (pc, info, TRUE);
58efb6c0 2914}
252b5132 2915
58efb6c0 2916void
4a5329c6 2917print_arm_disassembler_options (FILE *stream)
58efb6c0
NC
2918{
2919 int i;
252b5132 2920
58efb6c0
NC
2921 fprintf (stream, _("\n\
2922The following ARM specific disassembler options are supported for use with\n\
2923the -M switch:\n"));
b34976b6 2924
58efb6c0
NC
2925 for (i = NUM_ARM_REGNAMES; i--;)
2926 fprintf (stream, " reg-names-%s %*c%s\n",
2927 regnames[i].name,
d5b2f4d6 2928 (int)(14 - strlen (regnames[i].name)), ' ',
58efb6c0
NC
2929 regnames[i].description);
2930
2931 fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
2932 fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
252b5132 2933}
This page took 0.407115 seconds and 4 git commands to generate.