OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [opcodes/] [arm-dis.c] - Blame information for rev 298

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.