]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
Don't use wildcards in ChangeLog entries.
[thirdparty/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
ae6063d4 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
b99bd4ef
NC
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
22d9c8c5 6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
b99bd4ef
NC
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
b99bd4ef
NC
25#include <string.h>
26#define NO_RELOC 0
27#include "as.h"
3882b010 28#include "safe-ctype.h"
b99bd4ef
NC
29
30/* Need TARGET_CPU. */
31#include "config.h"
32#include "subsegs.h"
33#include "obstack.h"
34#include "symbols.h"
35#include "listing.h"
36
37#ifdef OBJ_ELF
38#include "elf/arm.h"
39#include "dwarf2dbg.h"
40#endif
41
03b1477f
RE
42/* XXX Set this to 1 after the next binutils release */
43#define WARN_DEPRECATED 0
44
b89dddec
RE
45/* The following bitmasks control CPU extensions: */
46#define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47#define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48#define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49#define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50#define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51#define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52#define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54#define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
ea6ef066 57#define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
09d92015 58#define ARM_EXT_V6 0x00001000 /* ARM V6. */
03b1477f
RE
59
60/* Co-processor space extensions. */
61#define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
62#define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
5a6c6817 63#define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
b89dddec
RE
64
65/* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
66 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
67 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
68 three more to cover cores prior to ARM6. Finally, there are cores which
69 implement further extensions in the co-processor space. */
70#define ARM_ARCH_V1 ARM_EXT_V1
71#define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
72#define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
73#define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
74#define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
75#define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
76#define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
77#define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
78#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
79#define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
80#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
81#define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
82#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
83#define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
84#define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
ea6ef066 85#define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
09d92015 86#define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
03b1477f 87
b89dddec 88/* Processors with specific extensions in the co-processor space. */
03b1477f 89#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
5a6c6817 90#define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
b99bd4ef
NC
91
92/* Some useful combinations: */
03b1477f
RE
93#define ARM_ANY 0x0000ffff /* Any basic core. */
94#define ARM_ALL 0x00ffffff /* Any core + co-processor */
95#define CPROC_ANY 0x00ff0000 /* Any co-processor */
96#define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97
b99bd4ef 98
bfae80f2
RE
99#define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
100#define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
101#define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
102#define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
103#define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
104#define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
33a392fb 105#define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
bfae80f2 106#define FPU_NONE 0
b99bd4ef 107
b89dddec
RE
108#define FPU_ARCH_FPE FPU_FPA_EXT_V1
109#define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
110
bfae80f2
RE
111#define FPU_ARCH_VFP FPU_VFP_EXT_NONE
112#define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
113#define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
114#define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
115
33a392fb
PB
116#define FPU_ARCH_MAVERICK FPU_MAVERICK
117
118enum arm_float_abi
119{
120 ARM_FLOAT_ABI_HARD,
121 ARM_FLOAT_ABI_SOFTFP,
122 ARM_FLOAT_ABI_SOFT
123};
124
b89dddec
RE
125/* Types of processor to assemble for. */
126#define ARM_1 ARM_ARCH_V1
127#define ARM_2 ARM_ARCH_V2
128#define ARM_3 ARM_ARCH_V2S
129#define ARM_250 ARM_ARCH_V2S
130#define ARM_6 ARM_ARCH_V3
131#define ARM_7 ARM_ARCH_V3
132#define ARM_8 ARM_ARCH_V4
133#define ARM_9 ARM_ARCH_V4T
134#define ARM_STRONG ARM_ARCH_V4
135#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
136
137#ifndef CPU_DEFAULT
138#if defined __XSCALE__
b89dddec 139#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
140#else
141#if defined __thumb__
b89dddec 142#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 143#else
03b1477f 144#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
145#endif
146#endif
147#endif
148
39c2da32
RE
149#ifdef TE_LINUX
150#define FPU_DEFAULT FPU_ARCH_FPA
151#endif
152
153#ifdef TE_NetBSD
154#ifdef OBJ_ELF
155#define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
156#else
157/* Legacy a.out format. */
158#define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
159#endif
160#endif
161
bfae80f2 162/* For backwards compatibility we default to the FPA. */
b99bd4ef 163#ifndef FPU_DEFAULT
b89dddec 164#define FPU_DEFAULT FPU_ARCH_FPA
b99bd4ef
NC
165#endif
166
167#define streq(a, b) (strcmp (a, b) == 0)
168#define skip_whitespace(str) while (*(str) == ' ') ++(str)
169
03b1477f 170static unsigned long cpu_variant;
b99bd4ef
NC
171static int target_oabi = 0;
172
b99bd4ef 173/* Flags stored in private area of BFD structure. */
b34976b6
AM
174static int uses_apcs_26 = FALSE;
175static int atpcs = FALSE;
176static int support_interwork = FALSE;
177static int uses_apcs_float = FALSE;
178static int pic_code = FALSE;
03b1477f
RE
179
180/* Variables that we set while parsing command-line options. Once all
181 options have been read we re-process these values to set the real
182 assembly flags. */
183static int legacy_cpu = -1;
184static int legacy_fpu = -1;
185
186static int mcpu_cpu_opt = -1;
187static int mcpu_fpu_opt = -1;
188static int march_cpu_opt = -1;
189static int march_fpu_opt = -1;
190static int mfpu_opt = -1;
33a392fb 191static int mfloat_abi_opt = -1;
b99bd4ef
NC
192
193/* This array holds the chars that always start a comment. If the
194 pre-processor is disabled, these aren't very useful. */
f57c81f6 195const char comment_chars[] = "@";
b99bd4ef
NC
196
197/* This array holds the chars that only start a comment at the beginning of
198 a line. If the line seems to have the form '# 123 filename'
199 .line and .file directives will appear in the pre-processed output. */
200/* Note that input_file.c hand checks for '#' at the beginning of the
201 first line of the input file. This is because the compiler outputs
202 #NO_APP at the beginning of its output. */
203/* Also note that comments like this one will always work. */
05d2d07e 204const char line_comment_chars[] = "#";
b99bd4ef 205
da89cce1 206const char line_separator_chars[] = ";";
b99bd4ef
NC
207
208/* Chars that can be used to separate mant
209 from exp in floating point numbers. */
05d2d07e 210const char EXP_CHARS[] = "eE";
b99bd4ef
NC
211
212/* Chars that mean this number is a floating point constant. */
213/* As in 0f12.456 */
214/* or 0d1.2345e12 */
215
05d2d07e 216const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
217
218/* Prefix characters that indicate the start of an immediate
219 value. */
220#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
221
222#ifdef OBJ_ELF
223/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
224symbolS * GOT_symbol;
225#endif
226
227/* Size of relocation record. */
05d2d07e 228const int md_reloc_size = 8;
b99bd4ef
NC
229
230/* 0: assemble for ARM,
231 1: assemble for Thumb,
232 2: assemble for Thumb even though target CPU does not support thumb
233 instructions. */
234static int thumb_mode = 0;
235
236typedef struct arm_fix
237{
238 int thumb_mode;
239} arm_fix_data;
240
241struct arm_it
242{
05d2d07e 243 const char * error;
b99bd4ef 244 unsigned long instruction;
b99bd4ef
NC
245 int size;
246 struct
247 {
248 bfd_reloc_code_real_type type;
249 expressionS exp;
250 int pc_rel;
251 } reloc;
252};
253
254struct arm_it inst;
255
256enum asm_shift_index
257{
258 SHIFT_LSL = 0,
259 SHIFT_LSR,
260 SHIFT_ASR,
261 SHIFT_ROR,
262 SHIFT_RRX
263};
264
265struct asm_shift_properties
266{
267 enum asm_shift_index index;
268 unsigned long bit_field;
269 unsigned int allows_0 : 1;
270 unsigned int allows_32 : 1;
271};
272
273static const struct asm_shift_properties shift_properties [] =
274{
275 { SHIFT_LSL, 0, 1, 0},
276 { SHIFT_LSR, 0x20, 0, 1},
277 { SHIFT_ASR, 0x40, 0, 1},
278 { SHIFT_ROR, 0x60, 0, 0},
279 { SHIFT_RRX, 0x60, 0, 0}
280};
281
282struct asm_shift_name
283{
284 const char * name;
285 const struct asm_shift_properties * properties;
286};
287
288static const struct asm_shift_name shift_names [] =
289{
290 { "asl", shift_properties + SHIFT_LSL },
291 { "lsl", shift_properties + SHIFT_LSL },
292 { "lsr", shift_properties + SHIFT_LSR },
293 { "asr", shift_properties + SHIFT_ASR },
294 { "ror", shift_properties + SHIFT_ROR },
295 { "rrx", shift_properties + SHIFT_RRX },
296 { "ASL", shift_properties + SHIFT_LSL },
297 { "LSL", shift_properties + SHIFT_LSL },
298 { "LSR", shift_properties + SHIFT_LSR },
299 { "ASR", shift_properties + SHIFT_ASR },
300 { "ROR", shift_properties + SHIFT_ROR },
301 { "RRX", shift_properties + SHIFT_RRX }
302};
303
09d92015 304/* Any kind of shift is accepted. */
b99bd4ef 305#define NO_SHIFT_RESTRICT 1
09d92015
MM
306/* The shift operand must be an immediate value, not a register. */
307#define SHIFT_IMMEDIATE 0
308/* The shift must be LSL or ASR and the operand must be an immediate. */
309#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
310/* The shift must be ASR and the operand must be an immediate. */
311#define SHIFT_ASR_IMMEDIATE 3
312/* The shift must be LSL and the operand must be an immediate. */
313#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
314
315#define NUM_FLOAT_VALS 8
316
05d2d07e 317const char * fp_const[] =
b99bd4ef
NC
318{
319 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
320};
321
322/* Number of littlenums required to hold an extended precision number. */
323#define MAX_LITTLENUMS 6
324
325LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
326
327#define FAIL (-1)
328#define SUCCESS (0)
329
bfae80f2
RE
330/* Whether a Co-processor load/store operation accepts write-back forms. */
331#define CP_WB_OK 1
332#define CP_NO_WB 0
333
b99bd4ef
NC
334#define SUFF_S 1
335#define SUFF_D 2
336#define SUFF_E 3
337#define SUFF_P 4
338
339#define CP_T_X 0x00008000
340#define CP_T_Y 0x00400000
341#define CP_T_Pre 0x01000000
342#define CP_T_UD 0x00800000
343#define CP_T_WB 0x00200000
344
345#define CONDS_BIT 0x00100000
346#define LOAD_BIT 0x00100000
b99bd4ef
NC
347
348#define DOUBLE_LOAD_FLAG 0x00000001
349
350struct asm_cond
351{
05d2d07e 352 const char * template;
b99bd4ef
NC
353 unsigned long value;
354};
355
b99bd4ef 356#define COND_ALWAYS 0xe0000000
90e4755a 357#define COND_MASK 0xf0000000
b99bd4ef 358
05d2d07e 359static const struct asm_cond conds[] =
b99bd4ef
NC
360{
361 {"eq", 0x00000000},
362 {"ne", 0x10000000},
363 {"cs", 0x20000000}, {"hs", 0x20000000},
364 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
365 {"mi", 0x40000000},
366 {"pl", 0x50000000},
367 {"vs", 0x60000000},
368 {"vc", 0x70000000},
369 {"hi", 0x80000000},
370 {"ls", 0x90000000},
371 {"ge", 0xa0000000},
372 {"lt", 0xb0000000},
373 {"gt", 0xc0000000},
374 {"le", 0xd0000000},
375 {"al", 0xe0000000},
376 {"nv", 0xf0000000}
377};
378
b99bd4ef
NC
379struct asm_psr
380{
b34976b6
AM
381 const char *template;
382 bfd_boolean cpsr;
b99bd4ef
NC
383 unsigned long field;
384};
385
2d2255b5 386/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
387#define SPSR_BIT (1 << 22)
388
389/* How many bits to shift the PSR_xxx bits up by. */
390#define PSR_SHIFT 16
391
392#define PSR_c (1 << 0)
393#define PSR_x (1 << 1)
394#define PSR_s (1 << 2)
395#define PSR_f (1 << 3)
396
05d2d07e 397static const struct asm_psr psrs[] =
b99bd4ef 398{
b34976b6
AM
399 {"CPSR", TRUE, PSR_c | PSR_f},
400 {"CPSR_all", TRUE, PSR_c | PSR_f},
401 {"SPSR", FALSE, PSR_c | PSR_f},
402 {"SPSR_all", FALSE, PSR_c | PSR_f},
403 {"CPSR_flg", TRUE, PSR_f},
404 {"CPSR_f", TRUE, PSR_f},
405 {"SPSR_flg", FALSE, PSR_f},
406 {"SPSR_f", FALSE, PSR_f},
407 {"CPSR_c", TRUE, PSR_c},
408 {"CPSR_ctl", TRUE, PSR_c},
409 {"SPSR_c", FALSE, PSR_c},
410 {"SPSR_ctl", FALSE, PSR_c},
411 {"CPSR_x", TRUE, PSR_x},
412 {"CPSR_s", TRUE, PSR_s},
413 {"SPSR_x", FALSE, PSR_x},
414 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 415 /* Combinations of flags. */
b34976b6
AM
416 {"CPSR_fs", TRUE, PSR_f | PSR_s},
417 {"CPSR_fx", TRUE, PSR_f | PSR_x},
418 {"CPSR_fc", TRUE, PSR_f | PSR_c},
419 {"CPSR_sf", TRUE, PSR_s | PSR_f},
420 {"CPSR_sx", TRUE, PSR_s | PSR_x},
421 {"CPSR_sc", TRUE, PSR_s | PSR_c},
422 {"CPSR_xf", TRUE, PSR_x | PSR_f},
423 {"CPSR_xs", TRUE, PSR_x | PSR_s},
424 {"CPSR_xc", TRUE, PSR_x | PSR_c},
425 {"CPSR_cf", TRUE, PSR_c | PSR_f},
426 {"CPSR_cs", TRUE, PSR_c | PSR_s},
427 {"CPSR_cx", TRUE, PSR_c | PSR_x},
428 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
429 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
430 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
431 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
432 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
433 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
434 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
435 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
436 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
437 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
438 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
439 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
440 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
441 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
442 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
443 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
444 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
445 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
446 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
447 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
448 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
449 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
450 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
451 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
452 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
453 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
454 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
455 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
456 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
457 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
458 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
459 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
460 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
461 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
462 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
463 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
464 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
465 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
466 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
467 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
468 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
469 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
470 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
471 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
472 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
473 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
474 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
475 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
476 {"SPSR_fs", FALSE, PSR_f | PSR_s},
477 {"SPSR_fx", FALSE, PSR_f | PSR_x},
478 {"SPSR_fc", FALSE, PSR_f | PSR_c},
479 {"SPSR_sf", FALSE, PSR_s | PSR_f},
480 {"SPSR_sx", FALSE, PSR_s | PSR_x},
481 {"SPSR_sc", FALSE, PSR_s | PSR_c},
482 {"SPSR_xf", FALSE, PSR_x | PSR_f},
483 {"SPSR_xs", FALSE, PSR_x | PSR_s},
484 {"SPSR_xc", FALSE, PSR_x | PSR_c},
485 {"SPSR_cf", FALSE, PSR_c | PSR_f},
486 {"SPSR_cs", FALSE, PSR_c | PSR_s},
487 {"SPSR_cx", FALSE, PSR_c | PSR_x},
488 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
489 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
490 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
491 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
492 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
493 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
494 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
495 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
496 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
497 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
498 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
499 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
500 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
501 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
502 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
503 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
504 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
505 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
506 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
507 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
508 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
509 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
510 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
511 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
512 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
513 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
514 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
515 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
516 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
517 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
518 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
519 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
520 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
521 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
522 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
523 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
524 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
525 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
526 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
527 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
528 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
529 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
530 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
531 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
532 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
533 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
534 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
535 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
536};
537
e16bb312
NC
538enum wreg_type
539 {
540 IWMMXT_REG_WR = 0,
541 IWMMXT_REG_WC = 1,
542 IWMMXT_REG_WR_OR_WC = 2,
543 IWMMXT_REG_WCG
544 };
545
546enum iwmmxt_insn_type
547{
548 check_rd,
549 check_wr,
550 check_wrwr,
551 check_wrwrwr,
552 check_wrwrwcg,
553 check_tbcst,
554 check_tmovmsk,
555 check_tmia,
556 check_tmcrr,
557 check_tmrrc,
558 check_tmcr,
559 check_tmrc,
560 check_tinsr,
561 check_textrc,
562 check_waligni,
563 check_textrm,
564 check_wshufh
565};
566
bfae80f2
RE
567enum vfp_dp_reg_pos
568{
569 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
570};
571
572enum vfp_sp_reg_pos
573{
574 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
575};
576
577enum vfp_ldstm_type
578{
579 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
580};
581
582/* VFP system registers. */
583struct vfp_reg
584{
585 const char *name;
586 unsigned long regno;
587};
588
cc8a6dd0 589static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
590{
591 {"fpsid", 0x00000000},
592 {"FPSID", 0x00000000},
593 {"fpscr", 0x00010000},
594 {"FPSCR", 0x00010000},
595 {"fpexc", 0x00080000},
596 {"FPEXC", 0x00080000}
597};
598
6c43fab6
RE
599/* Structure for a hash table entry for a register. */
600struct reg_entry
601{
602 const char * name;
603 int number;
0bbf2aa4 604 bfd_boolean builtin;
6c43fab6
RE
605};
606
e28cd48c 607/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
608#define REG_SP 13
609#define REG_LR 14
610#define REG_PC 15
611
e16bb312
NC
612#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
613#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
614#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
615
0bbf2aa4
NC
616/* These are the standard names. Users can add aliases with .req.
617 and delete them with .unreq. */
618
6c43fab6
RE
619/* Integer Register Numbers. */
620static const struct reg_entry rn_table[] =
621{
0bbf2aa4
NC
622 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
623 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
624 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
625 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 626 /* ATPCS Synonyms. */
0bbf2aa4
NC
627 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
628 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
629 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 630 /* Well-known aliases. */
0bbf2aa4
NC
631 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
632 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
633 {NULL, 0, TRUE}
6c43fab6
RE
634};
635
e16bb312
NC
636#define WR_PREFIX 0x200
637#define WC_PREFIX 0x400
638
639static const struct reg_entry iwmmxt_table[] =
640{
5a6c6817 641 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
642 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
643 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
644 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
645 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
646 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
647 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
648 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
649 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
650 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
651 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
652 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
653 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
654
655 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
656 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
657 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
658 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
659 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
660 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
661 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
662 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
663 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
664 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
665 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
666 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
667 {NULL, 0, TRUE}
e16bb312
NC
668};
669
6c43fab6
RE
670/* Co-processor Numbers. */
671static const struct reg_entry cp_table[] =
672{
0bbf2aa4
NC
673 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
674 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
675 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
676 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
677 {NULL, 0, TRUE}
6c43fab6
RE
678};
679
680/* Co-processor Register Numbers. */
681static const struct reg_entry cn_table[] =
682{
0bbf2aa4
NC
683 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
684 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
685 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
686 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 687 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
688 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
689 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
690 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
691 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
692 {NULL, 0, TRUE}
6c43fab6
RE
693};
694
695/* FPA Registers. */
696static const struct reg_entry fn_table[] =
697{
0bbf2aa4
NC
698 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
699 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
700 {NULL, 0, TRUE}
6c43fab6
RE
701};
702
bfae80f2
RE
703/* VFP SP Registers. */
704static const struct reg_entry sn_table[] =
705{
0bbf2aa4
NC
706 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
707 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
708 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
709 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
710 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
711 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
712 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
713 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
714 {NULL, 0, TRUE}
bfae80f2
RE
715};
716
717/* VFP DP Registers. */
718static const struct reg_entry dn_table[] =
719{
0bbf2aa4
NC
720 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
721 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
722 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
723 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
724 {NULL, 0, TRUE}
bfae80f2
RE
725};
726
63e63b07 727/* Maverick DSP coprocessor registers. */
6c43fab6
RE
728static const struct reg_entry mav_mvf_table[] =
729{
0bbf2aa4
NC
730 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
731 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
732 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
733 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
734 {NULL, 0, TRUE}
6c43fab6
RE
735};
736
737static const struct reg_entry mav_mvd_table[] =
738{
0bbf2aa4
NC
739 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
740 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
741 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
742 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
743 {NULL, 0, TRUE}
6c43fab6
RE
744};
745
746static const struct reg_entry mav_mvfx_table[] =
747{
0bbf2aa4
NC
748 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
749 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
750 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
751 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
752 {NULL, 0, TRUE}
6c43fab6
RE
753};
754
755static const struct reg_entry mav_mvdx_table[] =
756{
0bbf2aa4
NC
757 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
758 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
759 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
760 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
761 {NULL, 0, TRUE}
6c43fab6
RE
762};
763
764static const struct reg_entry mav_mvax_table[] =
765{
0bbf2aa4
NC
766 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
767 {NULL, 0, TRUE}
6c43fab6
RE
768};
769
770static const struct reg_entry mav_dspsc_table[] =
771{
0bbf2aa4
NC
772 {"dspsc", 0, TRUE},
773 {NULL, 0, TRUE}
6c43fab6
RE
774};
775
776struct reg_map
777{
778 const struct reg_entry *names;
779 int max_regno;
780 struct hash_control *htab;
781 const char *expected;
782};
783
784struct reg_map all_reg_maps[] =
785{
786 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
787 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
788 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 789 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
790 {sn_table, 31, NULL, N_("VFP single precision register expected")},
791 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
792 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
793 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
794 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 795 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
796 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
797 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 798 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
799};
800
801/* Enumeration matching entries in table above. */
802enum arm_reg_type
803{
804 REG_TYPE_RN = 0,
805#define REG_TYPE_FIRST REG_TYPE_RN
806 REG_TYPE_CP = 1,
807 REG_TYPE_CN = 2,
808 REG_TYPE_FN = 3,
bfae80f2
RE
809 REG_TYPE_SN = 4,
810 REG_TYPE_DN = 5,
811 REG_TYPE_MVF = 6,
812 REG_TYPE_MVD = 7,
813 REG_TYPE_MVFX = 8,
814 REG_TYPE_MVDX = 9,
815 REG_TYPE_MVAX = 10,
816 REG_TYPE_DSPSC = 11,
e16bb312 817 REG_TYPE_IWMMXT = 12,
bfae80f2 818
e16bb312 819 REG_TYPE_MAX = 13
6c43fab6 820};
404ff6b5 821
b99bd4ef
NC
822/* Functions called by parser. */
823/* ARM instructions. */
f2b7cb0a
RE
824static void do_arit PARAMS ((char *));
825static void do_cmp PARAMS ((char *));
826static void do_mov PARAMS ((char *));
827static void do_ldst PARAMS ((char *));
828static void do_ldstt PARAMS ((char *));
829static void do_ldmstm PARAMS ((char *));
830static void do_branch PARAMS ((char *));
831static void do_swi PARAMS ((char *));
c9b604bd 832
b99bd4ef 833/* Pseudo Op codes. */
f2b7cb0a
RE
834static void do_adr PARAMS ((char *));
835static void do_adrl PARAMS ((char *));
836static void do_empty PARAMS ((char *));
c9b604bd
RE
837
838/* ARM v2. */
f2b7cb0a
RE
839static void do_mul PARAMS ((char *));
840static void do_mla PARAMS ((char *));
c9b604bd
RE
841
842/* ARM v2S. */
f2b7cb0a 843static void do_swap PARAMS ((char *));
c9b604bd
RE
844
845/* ARM v3. */
f2b7cb0a
RE
846static void do_msr PARAMS ((char *));
847static void do_mrs PARAMS ((char *));
c9b604bd
RE
848
849/* ARM v3M. */
f2b7cb0a 850static void do_mull PARAMS ((char *));
b99bd4ef 851
90e4755a 852/* ARM v4. */
f2b7cb0a 853static void do_ldstv4 PARAMS ((char *));
90e4755a 854
c9b604bd 855/* ARM v4T. */
f2b7cb0a 856static void do_bx PARAMS ((char *));
b99bd4ef 857
ea6ef066 858/* ARM v5T. */
f2b7cb0a
RE
859static void do_blx PARAMS ((char *));
860static void do_bkpt PARAMS ((char *));
861static void do_clz PARAMS ((char *));
862static void do_lstc2 PARAMS ((char *));
863static void do_cdp2 PARAMS ((char *));
864static void do_co_reg2 PARAMS ((char *));
b99bd4ef 865
ea6ef066 866/* ARM v5TExP. */
f2b7cb0a
RE
867static void do_smla PARAMS ((char *));
868static void do_smlal PARAMS ((char *));
869static void do_smul PARAMS ((char *));
870static void do_qadd PARAMS ((char *));
c9b604bd 871
ea6ef066 872/* ARM v5TE. */
f2b7cb0a
RE
873static void do_pld PARAMS ((char *));
874static void do_ldrd PARAMS ((char *));
875static void do_co_reg2c PARAMS ((char *));
b99bd4ef 876
ea6ef066
RE
877/* ARM v5TEJ. */
878static void do_bxj PARAMS ((char *));
879
09d92015
MM
880/* ARM V6. */
881static void do_cps PARAMS ((char *));
882static void do_cpsi PARAMS ((char *));
883static void do_ldrex PARAMS ((char *));
884static void do_pkhbt PARAMS ((char *));
885static void do_pkhtb PARAMS ((char *));
886static void do_qadd16 PARAMS ((char *));
887static void do_rev PARAMS ((char *));
888static void do_rfe PARAMS ((char *));
889static void do_sxtah PARAMS ((char *));
890static void do_sxth PARAMS ((char *));
891static void do_setend PARAMS ((char *));
892static void do_smlad PARAMS ((char *));
893static void do_smlald PARAMS ((char *));
894static void do_smmul PARAMS ((char *));
895static void do_ssat PARAMS ((char *));
896static void do_usat PARAMS ((char *));
897static void do_srs PARAMS ((char *));
898static void do_ssat16 PARAMS ((char *));
899static void do_usat16 PARAMS ((char *));
900static void do_strex PARAMS ((char *));
901static void do_umaal PARAMS ((char *));
902
903static void do_cps_mode PARAMS ((char **));
904static void do_cps_flags PARAMS ((char **, int));
905static int do_endian_specifier PARAMS ((char *));
906static void do_pkh_core PARAMS ((char *, int));
907static void do_sat PARAMS ((char **, int));
908static void do_sat16 PARAMS ((char **, int));
909
b99bd4ef 910/* Coprocessor Instructions. */
f2b7cb0a
RE
911static void do_cdp PARAMS ((char *));
912static void do_lstc PARAMS ((char *));
913static void do_co_reg PARAMS ((char *));
c9b604bd
RE
914
915/* FPA instructions. */
f2b7cb0a
RE
916static void do_fpa_ctrl PARAMS ((char *));
917static void do_fpa_ldst PARAMS ((char *));
918static void do_fpa_ldmstm PARAMS ((char *));
919static void do_fpa_dyadic PARAMS ((char *));
920static void do_fpa_monadic PARAMS ((char *));
921static void do_fpa_cmp PARAMS ((char *));
922static void do_fpa_from_reg PARAMS ((char *));
923static void do_fpa_to_reg PARAMS ((char *));
c9b604bd 924
bfae80f2
RE
925/* VFP instructions. */
926static void do_vfp_sp_monadic PARAMS ((char *));
927static void do_vfp_dp_monadic PARAMS ((char *));
928static void do_vfp_sp_dyadic PARAMS ((char *));
929static void do_vfp_dp_dyadic PARAMS ((char *));
930static void do_vfp_reg_from_sp PARAMS ((char *));
931static void do_vfp_sp_from_reg PARAMS ((char *));
e45d0630
PB
932static void do_vfp_reg2_from_sp2 PARAMS ((char *));
933static void do_vfp_sp2_from_reg2 PARAMS ((char *));
bfae80f2
RE
934static void do_vfp_reg_from_dp PARAMS ((char *));
935static void do_vfp_reg2_from_dp PARAMS ((char *));
936static void do_vfp_dp_from_reg PARAMS ((char *));
937static void do_vfp_dp_from_reg2 PARAMS ((char *));
938static void do_vfp_reg_from_ctrl PARAMS ((char *));
939static void do_vfp_ctrl_from_reg PARAMS ((char *));
940static void do_vfp_sp_ldst PARAMS ((char *));
941static void do_vfp_dp_ldst PARAMS ((char *));
942static void do_vfp_sp_ldstmia PARAMS ((char *));
943static void do_vfp_sp_ldstmdb PARAMS ((char *));
944static void do_vfp_dp_ldstmia PARAMS ((char *));
945static void do_vfp_dp_ldstmdb PARAMS ((char *));
946static void do_vfp_xp_ldstmia PARAMS ((char *));
947static void do_vfp_xp_ldstmdb PARAMS ((char *));
948static void do_vfp_sp_compare_z PARAMS ((char *));
949static void do_vfp_dp_compare_z PARAMS ((char *));
950static void do_vfp_dp_sp_cvt PARAMS ((char *));
951static void do_vfp_sp_dp_cvt PARAMS ((char *));
952
c9b604bd 953/* XScale. */
63e63b07
RE
954static void do_xsc_mia PARAMS ((char *));
955static void do_xsc_mar PARAMS ((char *));
956static void do_xsc_mra PARAMS ((char *));
f2b7cb0a
RE
957
958/* Maverick. */
63e63b07 959static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
6c43fab6 960 enum arm_reg_type));
63e63b07
RE
961static void do_mav_binops_1a PARAMS ((char *));
962static void do_mav_binops_1b PARAMS ((char *));
963static void do_mav_binops_1c PARAMS ((char *));
964static void do_mav_binops_1d PARAMS ((char *));
965static void do_mav_binops_1e PARAMS ((char *));
966static void do_mav_binops_1f PARAMS ((char *));
967static void do_mav_binops_1g PARAMS ((char *));
968static void do_mav_binops_1h PARAMS ((char *));
969static void do_mav_binops_1i PARAMS ((char *));
970static void do_mav_binops_1j PARAMS ((char *));
971static void do_mav_binops_1k PARAMS ((char *));
972static void do_mav_binops_1l PARAMS ((char *));
973static void do_mav_binops_1m PARAMS ((char *));
974static void do_mav_binops_1n PARAMS ((char *));
975static void do_mav_binops_1o PARAMS ((char *));
976static void do_mav_binops_2a PARAMS ((char *));
977static void do_mav_binops_2b PARAMS ((char *));
978static void do_mav_binops_2c PARAMS ((char *));
979static void do_mav_binops_3a PARAMS ((char *));
980static void do_mav_binops_3b PARAMS ((char *));
981static void do_mav_binops_3c PARAMS ((char *));
982static void do_mav_binops_3d PARAMS ((char *));
cc8a6dd0 983static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
984 enum arm_reg_type,
985 enum arm_reg_type));
63e63b07
RE
986static void do_mav_triple_4a PARAMS ((char *));
987static void do_mav_triple_4b PARAMS ((char *));
988static void do_mav_triple_5a PARAMS ((char *));
989static void do_mav_triple_5b PARAMS ((char *));
990static void do_mav_triple_5c PARAMS ((char *));
991static void do_mav_triple_5d PARAMS ((char *));
992static void do_mav_triple_5e PARAMS ((char *));
993static void do_mav_triple_5f PARAMS ((char *));
994static void do_mav_triple_5g PARAMS ((char *));
995static void do_mav_triple_5h PARAMS ((char *));
cc8a6dd0 996static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
997 enum arm_reg_type,
998 enum arm_reg_type,
999 enum arm_reg_type));
63e63b07
RE
1000static void do_mav_quad_6a PARAMS ((char *));
1001static void do_mav_quad_6b PARAMS ((char *));
1002static void do_mav_dspsc_1 PARAMS ((char *));
1003static void do_mav_dspsc_2 PARAMS ((char *));
1004static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
6c43fab6 1005 enum arm_reg_type));
63e63b07
RE
1006static void do_mav_shift_1 PARAMS ((char *));
1007static void do_mav_shift_2 PARAMS ((char *));
1008static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1009static void do_mav_ldst_1 PARAMS ((char *));
1010static void do_mav_ldst_2 PARAMS ((char *));
1011static void do_mav_ldst_3 PARAMS ((char *));
1012static void do_mav_ldst_4 PARAMS ((char *));
1013
1014static int mav_reg_required_here PARAMS ((char **, int,
6c43fab6 1015 enum arm_reg_type));
63e63b07 1016static int mav_parse_offset PARAMS ((char **, int *));
404ff6b5 1017
90e4755a
RE
1018static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1019 int, int));
6c43fab6
RE
1020static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1021static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
05d2d07e 1022static const struct asm_psr * arm_psr_parse PARAMS ((char **));
90e4755a
RE
1023static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1024 fragS *));
b99bd4ef
NC
1025static int add_to_lit_pool PARAMS ((void));
1026static unsigned validate_immediate PARAMS ((unsigned));
90e4755a
RE
1027static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1028 unsigned int *));
b99bd4ef
NC
1029static int validate_offset_imm PARAMS ((unsigned int, int));
1030static void opcode_select PARAMS ((int));
1031static void end_of_line PARAMS ((char *));
1032static int reg_required_here PARAMS ((char **, int));
1033static int psr_required_here PARAMS ((char **));
1034static int co_proc_number PARAMS ((char **));
1035static int cp_opc_expr PARAMS ((char **, int, int));
1036static int cp_reg_required_here PARAMS ((char **, int));
1037static int fp_reg_required_here PARAMS ((char **, int));
bfae80f2
RE
1038static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1039static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1040static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1041static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1042static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1043static long vfp_dp_reg_list PARAMS ((char **));
1044static int vfp_psr_required_here PARAMS ((char **str));
1045static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
b99bd4ef 1046static int cp_address_offset PARAMS ((char **));
bfae80f2 1047static int cp_address_required_here PARAMS ((char **, int));
b99bd4ef
NC
1048static int my_get_float_expression PARAMS ((char **));
1049static int skip_past_comma PARAMS ((char **));
1050static int walk_no_bignums PARAMS ((symbolS *));
1051static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1052static int data_op2 PARAMS ((char **));
1053static int fp_op2 PARAMS ((char **));
1054static long reg_list PARAMS ((char **));
1055static void thumb_load_store PARAMS ((char *, int, int));
1056static int decode_shift PARAMS ((char **, int));
90e4755a
RE
1057static int ldst_extend PARAMS ((char **));
1058static int ldst_extend_v4 PARAMS ((char **));
b99bd4ef 1059static void thumb_add_sub PARAMS ((char *, int));
6c43fab6
RE
1060static void insert_reg PARAMS ((const struct reg_entry *,
1061 struct hash_control *));
b99bd4ef
NC
1062static void thumb_shift PARAMS ((char *, int));
1063static void thumb_mov_compare PARAMS ((char *, int));
f2b7cb0a 1064static void build_arm_ops_hsh PARAMS ((void));
b99bd4ef
NC
1065static void set_constant_flonums PARAMS ((void));
1066static valueT md_chars_to_number PARAMS ((char *, int));
6c43fab6
RE
1067static void build_reg_hsh PARAMS ((struct reg_map *));
1068static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1069static int create_register_alias PARAMS ((char *, char *));
f03698e6 1070static void output_inst PARAMS ((const char *));
2c20dfb2
NC
1071static int accum0_required_here PARAMS ((char **));
1072static int ld_mode_required_here PARAMS ((char **));
f2b7cb0a 1073static void do_branch25 PARAMS ((char *));
2c20dfb2 1074static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
1075#ifdef OBJ_ELF
1076static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1077#endif
1078
e16bb312
NC
1079static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1080static void do_iwmmxt_byte_addr PARAMS ((char *));
1081static void do_iwmmxt_tandc PARAMS ((char *));
1082static void do_iwmmxt_tbcst PARAMS ((char *));
1083static void do_iwmmxt_textrc PARAMS ((char *));
1084static void do_iwmmxt_textrm PARAMS ((char *));
1085static void do_iwmmxt_tinsr PARAMS ((char *));
1086static void do_iwmmxt_tmcr PARAMS ((char *));
1087static void do_iwmmxt_tmcrr PARAMS ((char *));
1088static void do_iwmmxt_tmia PARAMS ((char *));
1089static void do_iwmmxt_tmovmsk PARAMS ((char *));
1090static void do_iwmmxt_tmrc PARAMS ((char *));
1091static void do_iwmmxt_tmrrc PARAMS ((char *));
1092static void do_iwmmxt_torc PARAMS ((char *));
1093static void do_iwmmxt_waligni PARAMS ((char *));
1094static void do_iwmmxt_wmov PARAMS ((char *));
1095static void do_iwmmxt_word_addr PARAMS ((char *));
1096static void do_iwmmxt_wrwr PARAMS ((char *));
1097static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1098static void do_iwmmxt_wrwrwr PARAMS ((char *));
1099static void do_iwmmxt_wshufh PARAMS ((char *));
1100static void do_iwmmxt_wzero PARAMS ((char *));
1101static int cp_byte_address_offset PARAMS ((char **));
1102static int cp_byte_address_required_here PARAMS ((char **));
1103
b99bd4ef
NC
1104/* ARM instructions take 4bytes in the object file, Thumb instructions
1105 take 2: */
1106#define INSN_SIZE 4
1107
404ff6b5 1108/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 1109#define MAV_MODE1 0x100c
404ff6b5
AH
1110
1111/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 1112#define MAV_MODE2 0x0c10
404ff6b5
AH
1113
1114/* "INSN<cond> X,Y" where X:0, Y:bit16. */
63e63b07 1115#define MAV_MODE3 0x1000
404ff6b5
AH
1116
1117/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 1118#define MAV_MODE4 0x0c0010
404ff6b5
AH
1119
1120/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 1121#define MAV_MODE5 0x00100c
404ff6b5
AH
1122
1123/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 1124#define MAV_MODE6 0x00100c05
b99bd4ef
NC
1125
1126struct asm_opcode
1127{
1128 /* Basic string to match. */
05d2d07e 1129 const char * template;
b99bd4ef
NC
1130
1131 /* Basic instruction code. */
1132 unsigned long value;
1133
90e4755a
RE
1134 /* Offset into the template where the condition code (if any) will be.
1135 If zero, then the instruction is never conditional. */
1136 unsigned cond_offset;
b99bd4ef 1137
90e4755a
RE
1138 /* Which architecture variant provides this instruction. */
1139 unsigned long variant;
b99bd4ef
NC
1140
1141 /* Function to call to parse args. */
f2b7cb0a 1142 void (* parms) PARAMS ((char *));
b99bd4ef
NC
1143};
1144
05d2d07e 1145static const struct asm_opcode insns[] =
b99bd4ef 1146{
c9b604bd 1147 /* Core ARM Instructions. */
90e4755a
RE
1148 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1149 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1150 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1151 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1152 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1153 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1154 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1155 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1156 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1157 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1158 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1159 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1160 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1161 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1162 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1163 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1164 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1165 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1166 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1167 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1168
1169 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1170 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1171 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1172 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1173 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1174 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1175 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1176 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1177 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1178 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1179 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1181
1182 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1183 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1184 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1185 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1186
1187 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1188 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1189 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1190 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1191 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1192 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1193 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1194 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1195
1196 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1197 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1198 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1201 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1204
1205 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1206 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1207 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1209 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1213
1214 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
b99bd4ef 1215#ifdef TE_WINCE
c9b604bd 1216 /* XXX This is the wrong place to do this. Think multi-arch. */
90e4755a
RE
1217 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1218 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
b99bd4ef 1219#else
90e4755a
RE
1220 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1221 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
b99bd4ef
NC
1222#endif
1223
c9b604bd 1224 /* Pseudo ops. */
90e4755a
RE
1225 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1226 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1227 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
b99bd4ef 1228
c9b604bd 1229 /* ARM 2 multiplies. */
90e4755a
RE
1230 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1231 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1232 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1233 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 1234
67c1ffbe 1235 /* Generic coprocessor instructions. */
90e4755a
RE
1236 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1237 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1238 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1239 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1240 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1241 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1242 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
c9b604bd
RE
1243
1244 /* ARM 3 - swp instructions. */
90e4755a
RE
1245 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1246 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 1247
c9b604bd 1248 /* ARM 6 Status register instructions. */
90e4755a
RE
1249 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1250 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1251 /* ScottB: our code uses 0xe128f000 for msr.
c9b604bd 1252 NickC: but this is wrong because the bits 16 through 19 are
90e4755a 1253 handled by the PSR_xxx defines above. */
b99bd4ef 1254
f2b7cb0a 1255 /* ARM 7M long multiplies. */
90e4755a
RE
1256 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1257 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1258 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1259 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1260 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1261 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1262 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1263 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1264
1265 /* ARM Architecture 4. */
1266 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1267 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1268 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1269 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 1270
c9b604bd 1271 /* ARM Architecture 4T. */
cc8a6dd0 1272 /* Note: bx (and blx) are required on V5, even if the processor does
90e4755a
RE
1273 not support Thumb. */
1274 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1275
ea6ef066 1276 /* ARM Architecture 5T. */
90e4755a
RE
1277 /* Note: blx has 2 variants, so the .value is set dynamically.
1278 Only one of the variants has conditional execution. */
1279 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1280 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1281 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1282 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1283 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1284 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1285 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1286 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1287 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1288 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1289
ea6ef066 1290 /* ARM Architecture 5TExP. */
90e4755a
RE
1291 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1292 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1293 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1294 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1295
1296 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1297 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1298
1299 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1300 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1301 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1302 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1303
1304 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1305 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1306 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1307 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1308
1309 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1310 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1311
1312 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1313 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1314 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1315 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
c9b604bd 1316
ea6ef066 1317 /* ARM Architecture 5TE. */
90e4755a
RE
1318 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1319 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1320 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1321
1322 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1323 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
404ff6b5 1324
ea6ef066
RE
1325 /* ARM Architecture 5TEJ. */
1326 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1327
09d92015
MM
1328 /* ARM V6. */
1329 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1330 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1331 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1332 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1333 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1334 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1335 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1336 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1337 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1338 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1339 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1340 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1341 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1342 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1343 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1344 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1345 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1346 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1347 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1348 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1349 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1350 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1351 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1352 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1353 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1354 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1355 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1356 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1357 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1358 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1359 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1360 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1361 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1362 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1363 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1364 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1365 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1366 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1367 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1368 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1369 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1370 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1371 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1372 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1373 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1374 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1375 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1376 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1377 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1378 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1379 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1380 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1381 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1384 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1385 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1386 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1387 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1388 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1389 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1390 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1391 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1392 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1393 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1394 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1395 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1396 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1397 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1398 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1399 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1400 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1401 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1402 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1403 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1404 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1405 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1406 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1407 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1408 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1409 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1410 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1411 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1412 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1413 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1414 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1415 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1416 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1417 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1418 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1419 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1420 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1421 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1422 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1423 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1424 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1425 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1426 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1427 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1428
c9b604bd 1429 /* Core FPA instruction set (V1). */
90e4755a
RE
1430 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1431 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1432 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1433 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1434
1435 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1436 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1437 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1438 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1439
1440 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1442 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444
1445 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1446 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457
1458 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470
1471 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483
1484 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496
1497 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509
1510 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522
1523 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535
1536 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548
1549 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561
1562 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574
1575 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587
1588 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600
1601 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613
1614 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626
1627 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639
1640 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1642 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652
1653 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1654 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665
1666 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678
1679 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691
1692 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704
1705 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717
1718 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730
1731 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743
1744 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756
1757 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769
1770 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782
1783 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795
1796 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808
1809 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1811 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821
1822 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1823 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1824 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1825 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1826 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1827 not be an optional suffix, but part of the instruction. To be
1828 compatible, we accept either. */
1829 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1830 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1831
1832 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1833 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1834 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1835 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1836 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1837 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844
1845 /* The implementation of the FIX instruction is broken on some
1846 assemblers, in that it accepts a precision specifier as well as a
1847 rounding specifier, despite the fact that this is meaningless.
1848 To be more compatible, we accept it as well, though of course it
1849 does not set any bits. */
1850 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1851 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1852 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1853 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1854 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1855 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
c9b604bd
RE
1863
1864 /* Instructions that were new with the real FPA, call them V2. */
90e4755a
RE
1865 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1866 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1867 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1868 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1869 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1870 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
c9b604bd 1871
bfae80f2
RE
1872 /* VFP V1xD (single precision). */
1873 /* Moves and type conversions. */
1874 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1875 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1876 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1877 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1878 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1879 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1880 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1881 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1885 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1886
1887 /* Memory operations. */
1888 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1889 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1890 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1891 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1892 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1893 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1894 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1895 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1896 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1897 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1898 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1899 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1900 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1901 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1902 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1903 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1904 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1905 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1906
1907 /* Monadic operations. */
1908 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1909 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1910 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1911
1912 /* Dyadic operations. */
1913 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1914 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1915 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1916 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922
1923 /* Comparisons. */
1924 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1925 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1926 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1927 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1928
1929 /* VFP V1 (Double precision). */
1930 /* Moves and type conversions. */
1931 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1932 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1933 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1934 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1935 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1936 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1937 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1938 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1939 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1940 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1941 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1942 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1943 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1944
1945 /* Memory operations. */
1946 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1947 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1948 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1949 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1950 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1951 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1952 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1953 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1954 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1955 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1956
1957 /* Monadic operations. */
1958 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1959 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1960 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1961
1962 /* Dyadic operations. */
1963 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1964 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1965 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1966 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1967 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1968 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972
1973 /* Comparisons. */
1974 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1975 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1976 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1977 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1978
1979 /* VFP V2. */
e45d0630
PB
1980 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1981 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
bfae80f2
RE
1982 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1983 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1984
c9b604bd 1985 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
63e63b07
RE
1986 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1987 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1988 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1989 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1990 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1991 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1993 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1994
5a6c6817
NC
1995 /* Intel Wireless MMX technology instructions. */
1996 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1997 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1998 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1999 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2000 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2001 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2002 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2003 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2004 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2005 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2006 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2007 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2008 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2012 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2013 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2014 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2015 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2016 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2017 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2018 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2019 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2023 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2024 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2025 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2026 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2027 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2028 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2029 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2030 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2031 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2032 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2033 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2034 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2035 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2043 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2063 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2064 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2065 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2066 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2068 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2085 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2098 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2100 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2102 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2103 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2105 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2107 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2109 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2114 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2115 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2116 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2117 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2119 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2121 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2123 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2125 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2126 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2127 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2128 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2129 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2130 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2131 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2132 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2139 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2140 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2145 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2146 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2147 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2148 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2149 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2150 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2154 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2155 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2156 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2157 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2158
63e63b07
RE
2159 /* Cirrus Maverick instructions. */
2160 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2161 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2162 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2163 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2164 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2165 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2166 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2167 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2168 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2169 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2170 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2171 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2172 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2173 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2174 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2175 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2176 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2177 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2178 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2179 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2180 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2181 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2182 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2183 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2184 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2185 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2186 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2187 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2188 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2189 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2190 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2191 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2192 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2193 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2194 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2195 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2196 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2197 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2198 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2199 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2200 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2201 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2202 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2203 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2204 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2205 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2206 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2207 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2208 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2209 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2210 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2211 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2212 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2213 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2214 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2215 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2216 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2217 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2218 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2219 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2220 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2221 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2222 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2223 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2224 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2225 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2226 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2227 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2228 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2229 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2230 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2231 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2232 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2233 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2234 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2235 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
b99bd4ef
NC
2236};
2237
2238/* Defines for various bits that we will want to toggle. */
2239#define INST_IMMEDIATE 0x02000000
2240#define OFFSET_REG 0x02000000
2241#define HWOFFSET_IMM 0x00400000
2242#define SHIFT_BY_REG 0x00000010
2243#define PRE_INDEX 0x01000000
2244#define INDEX_UP 0x00800000
2245#define WRITE_BACK 0x00200000
2246#define LDM_TYPE_2_OR_3 0x00400000
2247
2248#define LITERAL_MASK 0xf000f000
b99bd4ef 2249#define OPCODE_MASK 0xfe1fffff
90e4755a
RE
2250#define V4_STR_BIT 0x00000020
2251
b99bd4ef
NC
2252#define DATA_OP_SHIFT 21
2253
2254/* Codes to distinguish the arithmetic instructions. */
2255#define OPCODE_AND 0
2256#define OPCODE_EOR 1
2257#define OPCODE_SUB 2
2258#define OPCODE_RSB 3
2259#define OPCODE_ADD 4
2260#define OPCODE_ADC 5
2261#define OPCODE_SBC 6
2262#define OPCODE_RSC 7
2263#define OPCODE_TST 8
2264#define OPCODE_TEQ 9
2265#define OPCODE_CMP 10
2266#define OPCODE_CMN 11
2267#define OPCODE_ORR 12
2268#define OPCODE_MOV 13
2269#define OPCODE_BIC 14
2270#define OPCODE_MVN 15
2271
c9b604bd 2272/* Thumb v1 (ARMv4T). */
b99bd4ef
NC
2273static void do_t_nop PARAMS ((char *));
2274static void do_t_arit PARAMS ((char *));
2275static void do_t_add PARAMS ((char *));
2276static void do_t_asr PARAMS ((char *));
2277static void do_t_branch9 PARAMS ((char *));
2278static void do_t_branch12 PARAMS ((char *));
2279static void do_t_branch23 PARAMS ((char *));
2280static void do_t_bx PARAMS ((char *));
2281static void do_t_compare PARAMS ((char *));
2282static void do_t_ldmstm PARAMS ((char *));
2283static void do_t_ldr PARAMS ((char *));
2284static void do_t_ldrb PARAMS ((char *));
2285static void do_t_ldrh PARAMS ((char *));
2286static void do_t_lds PARAMS ((char *));
2287static void do_t_lsl PARAMS ((char *));
2288static void do_t_lsr PARAMS ((char *));
2289static void do_t_mov PARAMS ((char *));
2290static void do_t_push_pop PARAMS ((char *));
2291static void do_t_str PARAMS ((char *));
2292static void do_t_strb PARAMS ((char *));
2293static void do_t_strh PARAMS ((char *));
2294static void do_t_sub PARAMS ((char *));
2295static void do_t_swi PARAMS ((char *));
2296static void do_t_adr PARAMS ((char *));
2297
c9b604bd
RE
2298/* Thumb v2 (ARMv5T). */
2299static void do_t_blx PARAMS ((char *));
2300static void do_t_bkpt PARAMS ((char *));
2301
09d92015
MM
2302/* ARM V6. */
2303static void do_t_cps PARAMS ((char *));
2304static void do_t_cpy PARAMS ((char *));
2305static void do_t_setend PARAMS ((char *));;
2306
b99bd4ef
NC
2307#define T_OPCODE_MUL 0x4340
2308#define T_OPCODE_TST 0x4200
2309#define T_OPCODE_CMN 0x42c0
2310#define T_OPCODE_NEG 0x4240
2311#define T_OPCODE_MVN 0x43c0
2312
2313#define T_OPCODE_ADD_R3 0x1800
2314#define T_OPCODE_SUB_R3 0x1a00
2315#define T_OPCODE_ADD_HI 0x4400
2316#define T_OPCODE_ADD_ST 0xb000
2317#define T_OPCODE_SUB_ST 0xb080
2318#define T_OPCODE_ADD_SP 0xa800
2319#define T_OPCODE_ADD_PC 0xa000
2320#define T_OPCODE_ADD_I8 0x3000
2321#define T_OPCODE_SUB_I8 0x3800
2322#define T_OPCODE_ADD_I3 0x1c00
2323#define T_OPCODE_SUB_I3 0x1e00
2324
2325#define T_OPCODE_ASR_R 0x4100
2326#define T_OPCODE_LSL_R 0x4080
2327#define T_OPCODE_LSR_R 0x40c0
2328#define T_OPCODE_ASR_I 0x1000
2329#define T_OPCODE_LSL_I 0x0000
2330#define T_OPCODE_LSR_I 0x0800
2331
2332#define T_OPCODE_MOV_I8 0x2000
2333#define T_OPCODE_CMP_I8 0x2800
2334#define T_OPCODE_CMP_LR 0x4280
2335#define T_OPCODE_MOV_HR 0x4600
2336#define T_OPCODE_CMP_HR 0x4500
2337
2338#define T_OPCODE_LDR_PC 0x4800
2339#define T_OPCODE_LDR_SP 0x9800
2340#define T_OPCODE_STR_SP 0x9000
2341#define T_OPCODE_LDR_IW 0x6800
2342#define T_OPCODE_STR_IW 0x6000
2343#define T_OPCODE_LDR_IH 0x8800
2344#define T_OPCODE_STR_IH 0x8000
2345#define T_OPCODE_LDR_IB 0x7800
2346#define T_OPCODE_STR_IB 0x7000
2347#define T_OPCODE_LDR_RW 0x5800
2348#define T_OPCODE_STR_RW 0x5000
2349#define T_OPCODE_LDR_RH 0x5a00
2350#define T_OPCODE_STR_RH 0x5200
2351#define T_OPCODE_LDR_RB 0x5c00
2352#define T_OPCODE_STR_RB 0x5400
2353
2354#define T_OPCODE_PUSH 0xb400
2355#define T_OPCODE_POP 0xbc00
2356
2357#define T_OPCODE_BRANCH 0xe7fe
2358
2359static int thumb_reg PARAMS ((char ** str, int hi_lo));
2360
2361#define THUMB_SIZE 2 /* Size of thumb instruction. */
2362#define THUMB_REG_LO 0x1
2363#define THUMB_REG_HI 0x2
2364#define THUMB_REG_ANY 0x3
2365
2366#define THUMB_H1 0x0080
2367#define THUMB_H2 0x0040
2368
2369#define THUMB_ASR 0
2370#define THUMB_LSL 1
2371#define THUMB_LSR 2
2372
2373#define THUMB_MOVE 0
2374#define THUMB_COMPARE 1
09d92015 2375#define THUMB_CPY 2
b99bd4ef
NC
2376
2377#define THUMB_LOAD 0
2378#define THUMB_STORE 1
2379
2380#define THUMB_PP_PC_LR 0x0100
2381
2382/* These three are used for immediate shifts, do not alter. */
2383#define THUMB_WORD 2
2384#define THUMB_HALFWORD 1
2385#define THUMB_BYTE 0
2386
2387struct thumb_opcode
2388{
2389 /* Basic string to match. */
05d2d07e 2390 const char * template;
b99bd4ef
NC
2391
2392 /* Basic instruction code. */
2393 unsigned long value;
2394
2395 int size;
2396
2397 /* Which CPU variants this exists for. */
90e4755a 2398 unsigned long variant;
b99bd4ef
NC
2399
2400 /* Function to call to parse args. */
2401 void (* parms) PARAMS ((char *));
2402};
2403
05d2d07e 2404static const struct thumb_opcode tinsns[] =
b99bd4ef 2405{
c9b604bd 2406 /* Thumb v1 (ARMv4T). */
b89dddec
RE
2407 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2408 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2409 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2410 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2411 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2412 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2413 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2414 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2431 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
b89dddec
RE
2432 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2433 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2434 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2435 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2436 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2437 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2438 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2439 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2440 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2441 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2442 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2443 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2444 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2445 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2446 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2447 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2448 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2449 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2450 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2451 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2452 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2453 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2454 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2455 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2456 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2457 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2458 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2459 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2460 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2461 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
b99bd4ef 2462 /* Pseudo ops: */
b89dddec
RE
2463 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2464 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
c9b604bd
RE
2465 /* Thumb v2 (ARMv5T). */
2466 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2467 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
09d92015
MM
2468
2469 /* ARM V6. */
2470 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2471 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2472 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2473 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2474 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2475 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2476 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2477 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2478 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2479 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2480 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
b99bd4ef
NC
2481};
2482
f03698e6 2483#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 2484#define BAD_PC _("r15 not allowed here")
f03698e6 2485#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
2486#define ERR_NO_ACCUM _("acc0 expected")
2487
2488static struct hash_control * arm_ops_hsh = NULL;
2489static struct hash_control * arm_tops_hsh = NULL;
2490static struct hash_control * arm_cond_hsh = NULL;
2491static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
2492static struct hash_control * arm_psr_hsh = NULL;
2493
2494/* This table describes all the machine specific pseudo-ops the assembler
2495 has to support. The fields are:
2496 pseudo-op name without dot
2497 function to call to execute this pseudo-op
2498 Integer arg to pass to the function. */
2499
2500static void s_req PARAMS ((int));
0bbf2aa4 2501static void s_unreq PARAMS ((int));
b99bd4ef
NC
2502static void s_align PARAMS ((int));
2503static void s_bss PARAMS ((int));
2504static void s_even PARAMS ((int));
2505static void s_ltorg PARAMS ((int));
2506static void s_arm PARAMS ((int));
2507static void s_thumb PARAMS ((int));
2508static void s_code PARAMS ((int));
2509static void s_force_thumb PARAMS ((int));
2510static void s_thumb_func PARAMS ((int));
2511static void s_thumb_set PARAMS ((int));
76feaaf3 2512#ifdef OBJ_ELF
b99bd4ef
NC
2513static void s_arm_elf_cons PARAMS ((int));
2514#endif
2515
2516static int my_get_expression PARAMS ((expressionS *, char **));
2517
05d2d07e 2518const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2519{
0bbf2aa4 2520 /* Never called because '.req' does not start a line. */
b99bd4ef 2521 { "req", s_req, 0 },
0bbf2aa4 2522 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2523 { "bss", s_bss, 0 },
2524 { "align", s_align, 0 },
2525 { "arm", s_arm, 0 },
2526 { "thumb", s_thumb, 0 },
2527 { "code", s_code, 0 },
2528 { "force_thumb", s_force_thumb, 0 },
2529 { "thumb_func", s_thumb_func, 0 },
2530 { "thumb_set", s_thumb_set, 0 },
2531 { "even", s_even, 0 },
2532 { "ltorg", s_ltorg, 0 },
2533 { "pool", s_ltorg, 0 },
76feaaf3 2534#ifdef OBJ_ELF
b99bd4ef
NC
2535 { "word", s_arm_elf_cons, 4 },
2536 { "long", s_arm_elf_cons, 4 },
b99bd4ef
NC
2537#else
2538 { "word", cons, 4},
2539#endif
2540 { "extend", float_cons, 'x' },
2541 { "ldouble", float_cons, 'x' },
2542 { "packed", float_cons, 'p' },
2543 { 0, 0, 0 }
2544};
2545
03b1477f
RE
2546/* Other internal functions. */
2547static int arm_parse_extension PARAMS ((char *, int *));
2548static int arm_parse_cpu PARAMS ((char *));
2549static int arm_parse_arch PARAMS ((char *));
2550static int arm_parse_fpu PARAMS ((char *));
33a392fb 2551static int arm_parse_float_abi PARAMS ((char *));
0bbf2aa4 2552#if 0 /* Suppressed - for now. */
5a6c6817
NC
2553#if defined OBJ_COFF || defined OBJ_ELF
2554static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2555#endif
0bbf2aa4 2556#endif
03b1477f 2557
b99bd4ef
NC
2558/* Stuff needed to resolve the label ambiguity
2559 As:
2560 ...
2561 label: <insn>
2562 may differ from:
2563 ...
2564 label:
2565 <insn>
2566*/
2567
2568symbolS * last_label_seen;
b34976b6 2569static int label_is_thumb_function_name = FALSE;
b99bd4ef 2570
3d0c9500 2571/* Literal Pool stuff. */
b99bd4ef
NC
2572
2573#define MAX_LITERAL_POOL_SIZE 1024
2574
3d0c9500
NC
2575/* Literal pool structure. Held on a per-section
2576 and per-sub-section basis. */
2577typedef struct literal_pool
b99bd4ef 2578{
3d0c9500
NC
2579 expressionS literals [MAX_LITERAL_POOL_SIZE];
2580 unsigned int next_free_entry;
2581 unsigned int id;
2582 symbolS * symbol;
2583 segT section;
2584 subsegT sub_section;
61b5f74b 2585 struct literal_pool * next;
3d0c9500 2586} literal_pool;
b99bd4ef 2587
3d0c9500
NC
2588/* Pointer to a linked list of literal pools. */
2589literal_pool * list_of_pools = NULL;
b99bd4ef 2590
3d0c9500
NC
2591static literal_pool * find_literal_pool PARAMS ((void));
2592static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2593
3d0c9500
NC
2594static literal_pool *
2595find_literal_pool ()
2596{
2597 literal_pool * pool;
2598
2599 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2600 {
2601 if (pool->section == now_seg
2602 && pool->sub_section == now_subseg)
2603 break;
2604 }
2605
2606 return pool;
2607}
b99bd4ef 2608
3d0c9500
NC
2609static literal_pool *
2610find_or_make_literal_pool ()
2611{
2612 /* Next literal pool ID number. */
2613 static unsigned int latest_pool_num = 1;
2614 literal_pool * pool;
2615
2616 pool = find_literal_pool ();
b99bd4ef 2617
3d0c9500
NC
2618 if (pool == NULL)
2619 {
2620 /* Create a new pool. */
2621 pool = (literal_pool *) xmalloc (sizeof (* pool));
2622 if (! pool)
2623 return NULL;
2624
2625 pool->next_free_entry = 0;
2626 pool->section = now_seg;
2627 pool->sub_section = now_subseg;
2628 pool->next = list_of_pools;
2629 pool->symbol = NULL;
2630
2631 /* Add it to the list. */
2632 list_of_pools = pool;
2633 }
2634
2635 /* New pools, and emptied pools, will have a NULL symbol. */
2636 if (pool->symbol == NULL)
2637 {
2638 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2639 (valueT) 0, &zero_address_frag);
2640 pool->id = latest_pool_num ++;
2641 }
2642
2643 /* Done. */
2644 return pool;
2645}
2646
2647/* Add the literal in the global 'inst'
2648 structure to the relevent literal pool. */
b99bd4ef
NC
2649static int
2650add_to_lit_pool ()
2651{
61b5f74b 2652 literal_pool * pool;
3d0c9500 2653 unsigned int entry;
b99bd4ef 2654
3d0c9500 2655 pool = find_or_make_literal_pool ();
b99bd4ef 2656
3d0c9500
NC
2657 /* Check if this literal value is already in the pool. */
2658 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2659 {
3d0c9500
NC
2660 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2661 && (inst.reloc.exp.X_op == O_constant)
2662 && (pool->literals[entry].X_add_number
b99bd4ef 2663 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2664 && (pool->literals[entry].X_unsigned
2665 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2666 break;
2667
3d0c9500
NC
2668 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2669 && (inst.reloc.exp.X_op == O_symbol)
2670 && (pool->literals[entry].X_add_number
b99bd4ef 2671 == inst.reloc.exp.X_add_number)
3d0c9500 2672 && (pool->literals[entry].X_add_symbol
b99bd4ef 2673 == inst.reloc.exp.X_add_symbol)
3d0c9500 2674 && (pool->literals[entry].X_op_symbol
b99bd4ef 2675 == inst.reloc.exp.X_op_symbol))
3d0c9500 2676 break;
b99bd4ef
NC
2677 }
2678
3d0c9500
NC
2679 /* Do we need to create a new entry? */
2680 if (entry == pool->next_free_entry)
b99bd4ef 2681 {
3d0c9500 2682 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2683 {
ed71e111 2684 inst.error = _("literal pool overflow");
b99bd4ef
NC
2685 return FAIL;
2686 }
2687
3d0c9500
NC
2688 pool->literals[entry] = inst.reloc.exp;
2689 pool->next_free_entry += 1;
b99bd4ef
NC
2690 }
2691
3d0c9500 2692 inst.reloc.exp.X_op = O_symbol;
08df2379 2693 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2694 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2695
2696 return SUCCESS;
2697}
2698
2699/* Can't use symbol_new here, so have to create a symbol and then at
2700 a later date assign it a value. Thats what these functions do. */
2701
2702static void
2703symbol_locate (symbolP, name, segment, valu, frag)
2704 symbolS * symbolP;
05d2d07e 2705 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2706 segT segment; /* Segment identifier (SEG_<something>). */
2707 valueT valu; /* Symbol value. */
2708 fragS * frag; /* Associated fragment. */
2709{
2710 unsigned int name_length;
2711 char * preserved_copy_of_name;
2712
2713 name_length = strlen (name) + 1; /* +1 for \0. */
2714 obstack_grow (&notes, name, name_length);
2715 preserved_copy_of_name = obstack_finish (&notes);
2716#ifdef STRIP_UNDERSCORE
2717 if (preserved_copy_of_name[0] == '_')
2718 preserved_copy_of_name++;
2719#endif
2720
2721#ifdef tc_canonicalize_symbol_name
2722 preserved_copy_of_name =
2723 tc_canonicalize_symbol_name (preserved_copy_of_name);
2724#endif
2725
2726 S_SET_NAME (symbolP, preserved_copy_of_name);
2727
2728 S_SET_SEGMENT (symbolP, segment);
2729 S_SET_VALUE (symbolP, valu);
c62e1cc3 2730 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2731
2732 symbol_set_frag (symbolP, frag);
2733
2734 /* Link to end of symbol chain. */
2735 {
2736 extern int symbol_table_frozen;
2737 if (symbol_table_frozen)
2738 abort ();
2739 }
2740
2741 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2742
2743 obj_symbol_new_hook (symbolP);
2744
2745#ifdef tc_symbol_new_hook
2746 tc_symbol_new_hook (symbolP);
2747#endif
2748
2749#ifdef DEBUG_SYMS
2750 verify_symbol_chain (symbol_rootP, symbol_lastP);
2751#endif /* DEBUG_SYMS */
2752}
2753
2754/* Check that an immediate is valid.
2755 If so, convert it to the right format. */
2756
2757static unsigned int
2758validate_immediate (val)
2759 unsigned int val;
2760{
2761 unsigned int a;
2762 unsigned int i;
2763
2764#define rotate_left(v, n) (v << n | v >> (32 - n))
2765
2766 for (i = 0; i < 32; i += 2)
2767 if ((a = rotate_left (val, i)) <= 0xff)
2768 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2769
2770 return FAIL;
2771}
2772
2d2255b5 2773/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2774 values, added together. We already know that this value cannot be
2775 computed by just one ARM instruction. */
2776
2777static unsigned int
2778validate_immediate_twopart (val, highpart)
2779 unsigned int val;
2780 unsigned int * highpart;
2781{
2782 unsigned int a;
2783 unsigned int i;
2784
2785 for (i = 0; i < 32; i += 2)
2786 if (((a = rotate_left (val, i)) & 0xff) != 0)
2787 {
2788 if (a & 0xff00)
2789 {
2790 if (a & ~ 0xffff)
2791 continue;
2792 * highpart = (a >> 8) | ((i + 24) << 7);
2793 }
2794 else if (a & 0xff0000)
2795 {
2796 if (a & 0xff000000)
2797 continue;
2798 * highpart = (a >> 16) | ((i + 16) << 7);
2799 }
2800 else
2801 {
2802 assert (a & 0xff000000);
2803 * highpart = (a >> 24) | ((i + 8) << 7);
2804 }
2805
2806 return (a & 0xff) | (i << 7);
2807 }
2808
2809 return FAIL;
2810}
2811
2812static int
2813validate_offset_imm (val, hwse)
2814 unsigned int val;
2815 int hwse;
2816{
2817 if ((hwse && val > 255) || val > 4095)
2818 return FAIL;
2819 return val;
2820}
2821
6057a28f
NC
2822\f
2823#ifdef OBJ_ELF
2824enum mstate
2825{
2826 MAP_DATA,
2827 MAP_ARM,
2828 MAP_THUMB
2829};
2830
2831/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2832 (This text is taken from version B-02 of the spec):
2833
2834 4.4.7 Mapping and tagging symbols
2835
2836 A section of an ARM ELF file can contain a mixture of ARM code,
2837 Thumb code, and data. There are inline transitions between code
2838 and data at literal pool boundaries. There can also be inline
2839 transitions between ARM code and Thumb code, for example in
2840 ARM-Thumb inter-working veneers. Linkers, machine-level
2841 debuggers, profiling tools, and disassembly tools need to map
2842 images accurately. For example, setting an ARM breakpoint on a
2843 Thumb location, or in a literal pool, can crash the program
2844 being debugged, ruining the debugging session.
2845
2846 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2847 tagged (see section 4.4.7.2 below) using local symbols (with
2848 binding STB_LOCAL). To assist consumers, mapping and tagging
2849 symbols should be collated first in the symbol table, before
2850 other symbols with binding STB_LOCAL.
2851
2852 To allow properly collated mapping and tagging symbols to be
2853 skipped by consumers that have no interest in them, the first
2854 such symbol should have the name $m and its st_value field equal
2855 to the total number of mapping and tagging symbols (including
2856 the $m) in the symbol table.
2857
2858 4.4.7.1 Mapping symbols
2859
2860 $a Labels the first byte of a sequence of ARM instructions.
2861 Its type is STT_FUNC.
2862
2863 $d Labels the first byte of a sequence of data items.
2864 Its type is STT_OBJECT.
2865
2866 $t Labels the first byte of a sequence of Thumb instructions.
2867 Its type is STT_FUNC.
2868
2869 This list of mapping symbols may be extended in the future.
2870
2871 Section-relative mapping symbols
2872
2873 Mapping symbols defined in a section define a sequence of
2874 half-open address intervals that cover the address range of the
2875 section. Each interval starts at the address defined by a
2876 mapping symbol, and continues up to, but not including, the
2877 address defined by the next (in address order) mapping symbol or
2878 the end of the section. A corollary is that there must be a
2879 mapping symbol defined at the beginning of each section.
2880 Consumers can ignore the size of a section-relative mapping
2881 symbol. Producers can set it to 0.
2882
2883 Absolute mapping symbols
2884
2885 Because of the need to crystallize a Thumb address with the
2886 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2887 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2888 or $t.
2889
2890 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2891 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2892 where [x, y) denotes the half-open address range from x,
2893 inclusive, to y, exclusive.
2894
2895 In the absence of a mapping symbol, a consumer can interpret a
2896 function symbol with an odd value as the Thumb code address
2897 obtained by clearing the least significant bit of the
2898 value. This interpretation is deprecated, and it may not work in
2899 the future.
2900
2901 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2902 the EABI (which is still under development), so they are not
2903 implemented here. */
2904
2905static void
2906mapping_state (enum mstate state)
2907{
2908 static enum mstate mapstate = MAP_DATA;
2909 symbolS * symbolP;
2910 const char * symname;
2911 int type;
2912
2913 if (mapstate == state)
2914 /* The mapping symbol has already been emitted.
2915 There is nothing else to do. */
2916 return;
2917
2918 mapstate = state;
2919
2920 switch (state)
2921 {
2922 case MAP_DATA:
2923 symname = "$d";
2924 type = BSF_OBJECT;
2925 break;
2926 case MAP_ARM:
2927 symname = "$a";
2928 type = BSF_FUNCTION;
2929 break;
2930 case MAP_THUMB:
2931 symname = "$t";
2932 type = BSF_FUNCTION;
2933 break;
2934 default:
2935 abort ();
2936 }
2937
2938 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2939 symbol_table_insert (symbolP);
2940 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2941
2942 switch (state)
2943 {
2944 case MAP_ARM:
2945 THUMB_SET_FUNC (symbolP, 0);
2946 ARM_SET_THUMB (symbolP, 0);
2947 ARM_SET_INTERWORK (symbolP, support_interwork);
2948 break;
2949
2950 case MAP_THUMB:
2951 THUMB_SET_FUNC (symbolP, 1);
2952 ARM_SET_THUMB (symbolP, 1);
2953 ARM_SET_INTERWORK (symbolP, support_interwork);
2954 break;
2955
2956 case MAP_DATA:
2957 default:
2958 return;
2959 }
2960}
2961
2962/* When we change sections we need to issue a new mapping symbol. */
2963
9ce887a1 2964void
6057a28f
NC
2965arm_elf_change_section (void)
2966{
2967 flagword flags;
2968
2969 if (!SEG_NORMAL (now_seg))
2970 return;
2971
2972 flags = bfd_get_section_flags (stdoutput, now_seg);
2973
2974 /* We can ignore sections that only contain debug info. */
2975 if ((flags & SEC_ALLOC) == 0)
2976 return;
2977
2978 if (flags & SEC_CODE)
2979 {
2980 if (thumb_mode)
2981 mapping_state (MAP_THUMB);
2982 else
2983 mapping_state (MAP_ARM);
2984 }
2985 else
2986 /* This section does not contain code. Therefore it must contain data. */
2987 mapping_state (MAP_DATA);
2988}
2989#else
2990#define mapping_state(a)
2991#endif /* OBJ_ELF */
2992\f
2993
b99bd4ef
NC
2994static void
2995s_req (a)
2996 int a ATTRIBUTE_UNUSED;
2997{
f03698e6 2998 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
2999}
3000
0bbf2aa4
NC
3001/* The .unreq directive deletes an alias which was previously defined
3002 by .req. For example:
3003
3004 my_alias .req r11
3005 .unreq my_alias */
3006
3007static void
3008s_unreq (int a ATTRIBUTE_UNUSED)
3009{
3010 char *name;
3011 char saved_char;
3012
3013 skip_whitespace (input_line_pointer);
3014 name = input_line_pointer;
3015
3016 while (*input_line_pointer != 0
3017 && *input_line_pointer != ' '
3018 && *input_line_pointer != '\n')
3019 ++input_line_pointer;
3020
3021 saved_char = *input_line_pointer;
3022 *input_line_pointer = 0;
3023
3024 if (*name)
3025 {
3026 enum arm_reg_type req_type = arm_reg_parse_any (name);
3027
3028 if (req_type != REG_TYPE_MAX)
3029 {
3030 char *temp_name = name;
3031 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3032
3033 if (req_no != FAIL)
3034 {
3035 struct reg_entry *req_entry;
3036
3037 /* Check to see if this alias is a builtin one. */
3038 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3039
3040 if (!req_entry)
3041 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3042 else if (req_entry->builtin)
67c1ffbe 3043 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
3044 points to a const data structure, so we only need to
3045 free up the memory used by the key in the hash table.
3046 Unfortunately we have not recorded this value, so this
3047 is a memory leak. */
3048 /* FIXME: Should we issue a warning message ? */
3049 ;
3050 else
3051 {
67c1ffbe 3052 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
3053 key and the value, but fortunately the key is the same
3054 as the value->name field. */
3055 free ((char *) req_entry->name);
3056 free (req_entry);
3057 }
3058 }
3059 else
3060 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3061 }
3062 else
3063 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3064 }
3065 else
3066 as_bad (_("invalid syntax for .unreq directive"));
3067
3068 *input_line_pointer = saved_char;
3069 demand_empty_rest_of_line ();
3070}
3071
b99bd4ef
NC
3072static void
3073s_bss (ignore)
3074 int ignore ATTRIBUTE_UNUSED;
3075{
3076 /* We don't support putting frags in the BSS segment, we fake it by
3077 marking in_bss, then looking at s_skip for clues. */
3078 subseg_set (bss_section, 0);
3079 demand_empty_rest_of_line ();
6057a28f 3080 mapping_state (MAP_DATA);
b99bd4ef
NC
3081}
3082
3083static void
3084s_even (ignore)
3085 int ignore ATTRIBUTE_UNUSED;
3086{
3087 /* Never make frag if expect extra pass. */
3088 if (!need_pass_2)
3089 frag_align (1, 0, 0);
3090
3091 record_alignment (now_seg, 1);
3092
3093 demand_empty_rest_of_line ();
3094}
3095
3096static void
3097s_ltorg (ignored)
3098 int ignored ATTRIBUTE_UNUSED;
3099{
3d0c9500
NC
3100 unsigned int entry;
3101 literal_pool * pool;
b99bd4ef
NC
3102 char sym_name[20];
3103
3d0c9500
NC
3104 pool = find_literal_pool ();
3105 if (pool == NULL
3106 || pool->symbol == NULL
3107 || pool->next_free_entry == 0)
b99bd4ef
NC
3108 return;
3109
3110 /* Align pool as you have word accesses.
3111 Only make a frag if we have to. */
3112 if (!need_pass_2)
3113 frag_align (2, 0, 0);
3114
3115 record_alignment (now_seg, 2);
3116
3d0c9500 3117 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3118
3d0c9500 3119 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3120 (valueT) frag_now_fix (), frag_now);
3d0c9500 3121 symbol_table_insert (pool->symbol);
b99bd4ef 3122
3d0c9500 3123 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3124
3125#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3126 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3127#endif
3128
3d0c9500 3129 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3130 /* First output the expression in the instruction to the pool. */
3d0c9500 3131 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3132
3d0c9500
NC
3133 /* Mark the pool as empty. */
3134 pool->next_free_entry = 0;
3135 pool->symbol = NULL;
b99bd4ef
NC
3136}
3137
3138/* Same as s_align_ptwo but align 0 => align 2. */
3139
3140static void
3141s_align (unused)
3142 int unused ATTRIBUTE_UNUSED;
3143{
3144 register int temp;
3145 register long temp_fill;
3146 long max_alignment = 15;
3147
3148 temp = get_absolute_expression ();
3149 if (temp > max_alignment)
f03698e6 3150 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3151 else if (temp < 0)
3152 {
f03698e6 3153 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3154 temp = 0;
3155 }
3156
3157 if (*input_line_pointer == ',')
3158 {
3159 input_line_pointer++;
3160 temp_fill = get_absolute_expression ();
3161 }
3162 else
3163 temp_fill = 0;
3164
3165 if (!temp)
3166 temp = 2;
3167
3168 /* Only make a frag if we HAVE to. */
3169 if (temp && !need_pass_2)
3170 frag_align (temp, (int) temp_fill, 0);
3171 demand_empty_rest_of_line ();
3172
3173 record_alignment (now_seg, temp);
3174}
3175
3176static void
3177s_force_thumb (ignore)
3178 int ignore ATTRIBUTE_UNUSED;
3179{
3180 /* If we are not already in thumb mode go into it, EVEN if
3181 the target processor does not support thumb instructions.
3182 This is used by gcc/config/arm/lib1funcs.asm for example
3183 to compile interworking support functions even if the
3184 target processor should not support interworking. */
3185 if (! thumb_mode)
3186 {
3187 thumb_mode = 2;
3188
3189 record_alignment (now_seg, 1);
3190 }
3191
3192 demand_empty_rest_of_line ();
3193}
3194
3195static void
3196s_thumb_func (ignore)
3197 int ignore ATTRIBUTE_UNUSED;
3198{
3199 if (! thumb_mode)
3200 opcode_select (16);
3201
3202 /* The following label is the name/address of the start of a Thumb function.
3203 We need to know this for the interworking support. */
b34976b6 3204 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3205
3206 demand_empty_rest_of_line ();
3207}
3208
3209/* Perform a .set directive, but also mark the alias as
3210 being a thumb function. */
3211
3212static void
3213s_thumb_set (equiv)
3214 int equiv;
3215{
3216 /* XXX the following is a duplicate of the code for s_set() in read.c
3217 We cannot just call that code as we need to get at the symbol that
3218 is created. */
3219 register char * name;
3220 register char delim;
3221 register char * end_name;
3222 register symbolS * symbolP;
3223
3224 /* Especial apologies for the random logic:
3225 This just grew, and could be parsed much more simply!
3226 Dean - in haste. */
3227 name = input_line_pointer;
3228 delim = get_symbol_end ();
3229 end_name = input_line_pointer;
3230 *end_name = delim;
3231
3232 SKIP_WHITESPACE ();
3233
3234 if (*input_line_pointer != ',')
3235 {
3236 *end_name = 0;
f03698e6 3237 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3238 *end_name = delim;
3239 ignore_rest_of_line ();
3240 return;
3241 }
3242
3243 input_line_pointer++;
3244 *end_name = 0;
3245
3246 if (name[0] == '.' && name[1] == '\0')
3247 {
3248 /* XXX - this should not happen to .thumb_set. */
3249 abort ();
3250 }
3251
3252 if ((symbolP = symbol_find (name)) == NULL
3253 && (symbolP = md_undefined_symbol (name)) == NULL)
3254 {
3255#ifndef NO_LISTING
3256 /* When doing symbol listings, play games with dummy fragments living
3257 outside the normal fragment chain to record the file and line info
3258 for this symbol. */
3259 if (listing & LISTING_SYMBOLS)
3260 {
3261 extern struct list_info_struct * listing_tail;
3262 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3263
3264 memset (dummy_frag, 0, sizeof (fragS));
3265 dummy_frag->fr_type = rs_fill;
3266 dummy_frag->line = listing_tail;
3267 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3268 dummy_frag->fr_symbol = symbolP;
3269 }
3270 else
3271#endif
3272 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3273
3274#ifdef OBJ_COFF
3275 /* "set" symbols are local unless otherwise specified. */
3276 SF_SET_LOCAL (symbolP);
3277#endif /* OBJ_COFF */
3278 } /* Make a new symbol. */
3279
3280 symbol_table_insert (symbolP);
3281
3282 * end_name = delim;
3283
3284 if (equiv
3285 && S_IS_DEFINED (symbolP)
3286 && S_GET_SEGMENT (symbolP) != reg_section)
3287 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3288
3289 pseudo_set (symbolP);
3290
3291 demand_empty_rest_of_line ();
3292
3293 /* XXX Now we come to the Thumb specific bit of code. */
3294
3295 THUMB_SET_FUNC (symbolP, 1);
3296 ARM_SET_THUMB (symbolP, 1);
3297#if defined OBJ_ELF || defined OBJ_COFF
3298 ARM_SET_INTERWORK (symbolP, support_interwork);
3299#endif
3300}
3301
b99bd4ef
NC
3302static void
3303opcode_select (width)
3304 int width;
3305{
3306 switch (width)
3307 {
3308 case 16:
3309 if (! thumb_mode)
3310 {
b89dddec 3311 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3312 as_bad (_("selected processor does not support THUMB opcodes"));
3313
3314 thumb_mode = 1;
3315 /* No need to force the alignment, since we will have been
3316 coming from ARM mode, which is word-aligned. */
3317 record_alignment (now_seg, 1);
3318 }
6057a28f 3319 mapping_state (MAP_THUMB);
b99bd4ef
NC
3320 break;
3321
3322 case 32:
3323 if (thumb_mode)
3324 {
03b1477f 3325 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3326 as_bad (_("selected processor does not support ARM opcodes"));
3327
3328 thumb_mode = 0;
3329
3330 if (!need_pass_2)
cc8a6dd0 3331 frag_align (2, 0, 0);
b99bd4ef 3332
cc8a6dd0 3333 record_alignment (now_seg, 1);
b99bd4ef 3334 }
6057a28f 3335 mapping_state (MAP_ARM);
b99bd4ef
NC
3336 break;
3337
3338 default:
3339 as_bad (_("invalid instruction size selected (%d)"), width);
3340 }
3341}
3342
3343static void
3344s_arm (ignore)
3345 int ignore ATTRIBUTE_UNUSED;
3346{
3347 opcode_select (32);
3348 demand_empty_rest_of_line ();
3349}
3350
3351static void
3352s_thumb (ignore)
3353 int ignore ATTRIBUTE_UNUSED;
3354{
3355 opcode_select (16);
3356 demand_empty_rest_of_line ();
3357}
3358
3359static void
3360s_code (unused)
3361 int unused ATTRIBUTE_UNUSED;
3362{
3363 register int temp;
3364
3365 temp = get_absolute_expression ();
3366 switch (temp)
3367 {
3368 case 16:
3369 case 32:
3370 opcode_select (temp);
3371 break;
3372
3373 default:
3374 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3375 }
3376}
3377
3378static void
3379end_of_line (str)
f03698e6 3380 char *str;
b99bd4ef
NC
3381{
3382 skip_whitespace (str);
3383
f03698e6
RE
3384 if (*str != '\0' && !inst.error)
3385 inst.error = _("garbage following instruction");
b99bd4ef
NC
3386}
3387
3388static int
3389skip_past_comma (str)
3390 char ** str;
3391{
3392 char * p = * str, c;
3393 int comma = 0;
3394
3395 while ((c = *p) == ' ' || c == ',')
3396 {
3397 p++;
3398 if (c == ',' && comma++)
3399 return FAIL;
3400 }
3401
3402 if (c == '\0')
3403 return FAIL;
3404
3405 *str = p;
3406 return comma ? SUCCESS : FAIL;
3407}
3408
3409/* A standard register must be given at this point.
3410 SHIFT is the place to put it in inst.instruction.
3411 Restores input start point on error.
3412 Returns the reg#, or FAIL. */
3413
3414static int
3415reg_required_here (str, shift)
3416 char ** str;
3417 int shift;
3418{
3419 static char buff [128]; /* XXX */
3420 int reg;
3421 char * start = * str;
3422
6c43fab6 3423 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3424 {
3425 if (shift >= 0)
3426 inst.instruction |= reg << shift;
3427 return reg;
3428 }
3429
3430 /* Restore the start point, we may have got a reg of the wrong class. */
3431 *str = start;
3432
3433 /* In the few cases where we might be able to accept something else
3434 this error can be overridden. */
f03698e6 3435 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3436 inst.error = buff;
3437
3438 return FAIL;
3439}
3440
5a6c6817 3441/* A Intel Wireless MMX technology register
e16bb312
NC
3442 must be given at this point.
3443 Shift is the place to put it in inst.instruction.
3444 Restores input start point on err.
3445 Returns the reg#, or FAIL. */
3446
3447static int
3448wreg_required_here (str, shift, reg_type)
3449 char ** str;
3450 int shift;
3451 enum wreg_type reg_type;
3452{
3453 static char buff [128];
3454 int reg;
3455 char * start = *str;
3456
3457 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3458 {
3459 if (wr_register (reg)
3460 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3461 {
3462 if (shift >= 0)
3463 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3464 return reg;
3465 }
3466 else if (wc_register (reg)
3467 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3468 {
3469 if (shift >= 0)
3470 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3471 return reg;
3472 }
3473 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3474 {
3475 if (shift >= 0)
3476 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3477 return reg;
3478 }
3479 }
3480
3481 /* Restore the start point, we may have got a reg of the wrong class. */
3482 *str = start;
3483
3484 /* In the few cases where we might be able to accept
3485 something else this error can be overridden. */
5a6c6817 3486 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3487 inst.error = buff;
3488
3489 return FAIL;
3490}
3491
05d2d07e 3492static const struct asm_psr *
b99bd4ef
NC
3493arm_psr_parse (ccp)
3494 register char ** ccp;
3495{
3496 char * start = * ccp;
3497 char c;
3498 char * p;
05d2d07e 3499 const struct asm_psr * psr;
b99bd4ef
NC
3500
3501 p = start;
3502
3503 /* Skip to the end of the next word in the input stream. */
3504 do
3505 {
3506 c = *p++;
3507 }
3882b010 3508 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3509
3510 /* Terminate the word. */
3511 *--p = 0;
3512
3513 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3514 feature for ease of use and backwards compatibility. */
3515 if (!strncmp (start, "cpsr", 4))
3516 strncpy (start, "CPSR", 4);
3517 else if (!strncmp (start, "spsr", 4))
3518 strncpy (start, "SPSR", 4);
3519
3520 /* Now locate the word in the psr hash table. */
05d2d07e 3521 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3522
3523 /* Restore the input stream. */
3524 *p = c;
3525
3526 /* If we found a valid match, advance the
3527 stream pointer past the end of the word. */
3528 *ccp = p;
3529
3530 return psr;
3531}
3532
3533/* Parse the input looking for a PSR flag. */
3534
3535static int
3536psr_required_here (str)
3537 char ** str;
3538{
3539 char * start = * str;
05d2d07e 3540 const struct asm_psr * psr;
b99bd4ef
NC
3541
3542 psr = arm_psr_parse (str);
3543
3544 if (psr)
3545 {
3546 /* If this is the SPSR that is being modified, set the R bit. */
3547 if (! psr->cpsr)
3548 inst.instruction |= SPSR_BIT;
3549
3550 /* Set the psr flags in the MSR instruction. */
3551 inst.instruction |= psr->field << PSR_SHIFT;
3552
3553 return SUCCESS;
3554 }
3555
3556 /* In the few cases where we might be able to accept
3557 something else this error can be overridden. */
3558 inst.error = _("flag for {c}psr instruction expected");
3559
3560 /* Restore the start point. */
3561 *str = start;
3562 return FAIL;
3563}
3564
3565static int
3566co_proc_number (str)
6c43fab6 3567 char **str;
b99bd4ef
NC
3568{
3569 int processor, pchar;
6c43fab6 3570 char *start;
b99bd4ef 3571
6c43fab6
RE
3572 skip_whitespace (*str);
3573 start = *str;
b99bd4ef
NC
3574
3575 /* The data sheet seems to imply that just a number on its own is valid
3576 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3577 accept either. */
6c43fab6
RE
3578 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3579 == FAIL)
b99bd4ef 3580 {
6c43fab6
RE
3581 *str = start;
3582
3583 pchar = *(*str)++;
3584 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3585 {
6c43fab6
RE
3586 processor = pchar - '0';
3587 if (**str >= '0' && **str <= '9')
b99bd4ef 3588 {
6c43fab6
RE
3589 processor = processor * 10 + *(*str)++ - '0';
3590 if (processor > 15)
3591 {
f03698e6 3592 inst.error = _("illegal co-processor number");
6c43fab6
RE
3593 return FAIL;
3594 }
b99bd4ef
NC
3595 }
3596 }
6c43fab6
RE
3597 else
3598 {
f03698e6 3599 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
3600 return FAIL;
3601 }
b99bd4ef
NC
3602 }
3603
3604 inst.instruction |= processor << 8;
3605 return SUCCESS;
3606}
3607
3608static int
3609cp_opc_expr (str, where, length)
3610 char ** str;
3611 int where;
3612 int length;
3613{
3614 expressionS expr;
3615
3616 skip_whitespace (* str);
3617
3618 memset (&expr, '\0', sizeof (expr));
3619
3620 if (my_get_expression (&expr, str))
3621 return FAIL;
3622 if (expr.X_op != O_constant)
3623 {
3624 inst.error = _("bad or missing expression");
3625 return FAIL;
3626 }
3627
3628 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3629 {
3630 inst.error = _("immediate co-processor expression too large");
3631 return FAIL;
3632 }
3633
3634 inst.instruction |= expr.X_add_number << where;
3635 return SUCCESS;
3636}
3637
3638static int
3639cp_reg_required_here (str, where)
3640 char ** str;
3641 int where;
3642{
3643 int reg;
3644 char * start = *str;
3645
6c43fab6 3646 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3647 {
b99bd4ef
NC
3648 inst.instruction |= reg << where;
3649 return reg;
3650 }
3651
3652 /* In the few cases where we might be able to accept something else
3653 this error can be overridden. */
f03698e6 3654 inst.error = _("co-processor register expected");
b99bd4ef
NC
3655
3656 /* Restore the start point. */
3657 *str = start;
3658 return FAIL;
3659}
3660
3661static int
3662fp_reg_required_here (str, where)
3663 char ** str;
3664 int where;
3665{
3666 int reg;
3667 char * start = * str;
3668
6c43fab6 3669 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3670 {
b99bd4ef
NC
3671 inst.instruction |= reg << where;
3672 return reg;
3673 }
3674
3675 /* In the few cases where we might be able to accept something else
3676 this error can be overridden. */
f03698e6 3677 inst.error = _("floating point register expected");
b99bd4ef
NC
3678
3679 /* Restore the start point. */
3680 *str = start;
3681 return FAIL;
3682}
3683
3684static int
3685cp_address_offset (str)
3686 char ** str;
3687{
3688 int offset;
3689
3690 skip_whitespace (* str);
3691
3692 if (! is_immediate_prefix (**str))
3693 {
3694 inst.error = _("immediate expression expected");
3695 return FAIL;
3696 }
3697
3698 (*str)++;
3699
3700 if (my_get_expression (& inst.reloc.exp, str))
3701 return FAIL;
3702
3703 if (inst.reloc.exp.X_op == O_constant)
3704 {
3705 offset = inst.reloc.exp.X_add_number;
3706
3707 if (offset & 3)
3708 {
3709 inst.error = _("co-processor address must be word aligned");
3710 return FAIL;
3711 }
3712
3713 if (offset > 1023 || offset < -1023)
3714 {
3715 inst.error = _("offset too large");
3716 return FAIL;
3717 }
3718
3719 if (offset >= 0)
3720 inst.instruction |= INDEX_UP;
3721 else
3722 offset = -offset;
3723
3724 inst.instruction |= offset >> 2;
3725 }
3726 else
3727 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3728
3729 return SUCCESS;
3730}
3731
3732static int
bfae80f2 3733cp_address_required_here (str, wb_ok)
b99bd4ef 3734 char ** str;
bfae80f2 3735 int wb_ok;
b99bd4ef
NC
3736{
3737 char * p = * str;
3738 int pre_inc = 0;
3739 int write_back = 0;
3740
3741 if (*p == '[')
3742 {
3743 int reg;
3744
3745 p++;
3746 skip_whitespace (p);
3747
3748 if ((reg = reg_required_here (& p, 16)) == FAIL)
3749 return FAIL;
3750
3751 skip_whitespace (p);
3752
3753 if (*p == ']')
3754 {
3755 p++;
3756
f02232aa
NC
3757 skip_whitespace (p);
3758
3759 if (*p == '\0')
b99bd4ef 3760 {
f02232aa
NC
3761 /* As an extension to the official ARM syntax we allow:
3762
3763 [Rn]
3764
3765 as a short hand for:
3766
3767 [Rn,#0] */
3768 inst.instruction |= PRE_INDEX | INDEX_UP;
3769 *str = p;
3770 return SUCCESS;
3771 }
3772
3773 if (skip_past_comma (& p) == FAIL)
3774 {
3775 inst.error = _("comma expected after closing square bracket");
3776 return FAIL;
3777 }
b99bd4ef 3778
f02232aa
NC
3779 skip_whitespace (p);
3780
3781 if (*p == '#')
3782 {
3783 if (wb_ok)
b99bd4ef 3784 {
f02232aa
NC
3785 /* [Rn], #expr */
3786 write_back = WRITE_BACK;
3787
3788 if (reg == REG_PC)
3789 {
3790 inst.error = _("pc may not be used in post-increment");
3791 return FAIL;
3792 }
3793
3794 if (cp_address_offset (& p) == FAIL)
3795 return FAIL;
b99bd4ef 3796 }
f02232aa
NC
3797 else
3798 pre_inc = PRE_INDEX | INDEX_UP;
3799 }
3800 else if (*p == '{')
3801 {
3802 int option;
b99bd4ef 3803
f02232aa
NC
3804 /* [Rn], {<expr>} */
3805 p++;
3806
3807 skip_whitespace (p);
3808
3809 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3810 return FAIL;
f02232aa
NC
3811
3812 if (inst.reloc.exp.X_op == O_constant)
3813 {
3814 option = inst.reloc.exp.X_add_number;
3815
3816 if (option > 255 || option < 0)
3817 {
3818 inst.error = _("'option' field too large");
3819 return FAIL;
3820 }
3821
3822 skip_whitespace (p);
3823
3824 if (*p != '}')
3825 {
3826 inst.error = _("'}' expected at end of 'option' field");
3827 return FAIL;
3828 }
3829 else
3830 {
3831 p++;
3832 inst.instruction |= option;
3833 inst.instruction |= INDEX_UP;
3834 }
3835 }
3836 else
3837 {
3838 inst.error = _("non-constant expressions for 'option' field not supported");
3839 return FAIL;
3840 }
b99bd4ef
NC
3841 }
3842 else
f02232aa
NC
3843 {
3844 inst.error = _("# or { expected after comma");
3845 return FAIL;
3846 }
b99bd4ef
NC
3847 }
3848 else
3849 {
3850 /* '['Rn, #expr']'[!] */
3851
3852 if (skip_past_comma (& p) == FAIL)
3853 {
3854 inst.error = _("pre-indexed expression expected");
3855 return FAIL;
3856 }
3857
3858 pre_inc = PRE_INDEX;
3859
3860 if (cp_address_offset (& p) == FAIL)
3861 return FAIL;
3862
3863 skip_whitespace (p);
3864
3865 if (*p++ != ']')
3866 {
3867 inst.error = _("missing ]");
3868 return FAIL;
3869 }
3870
3871 skip_whitespace (p);
3872
bfae80f2 3873 if (wb_ok && *p == '!')
b99bd4ef
NC
3874 {
3875 if (reg == REG_PC)
3876 {
3877 inst.error = _("pc may not be used with write-back");
3878 return FAIL;
3879 }
3880
3881 p++;
3882 write_back = WRITE_BACK;
3883 }
3884 }
3885 }
3886 else
3887 {
3888 if (my_get_expression (&inst.reloc.exp, &p))
3889 return FAIL;
3890
3891 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3892 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3893 inst.reloc.pc_rel = 1;
3894 inst.instruction |= (REG_PC << 16);
3895 pre_inc = PRE_INDEX;
3896 }
3897
3898 inst.instruction |= write_back | pre_inc;
3899 *str = p;
3900 return SUCCESS;
3901}
3902
e16bb312
NC
3903static int
3904cp_byte_address_offset (str)
3905 char ** str;
3906{
3907 int offset;
3908
3909 skip_whitespace (* str);
3910
3911 if (! is_immediate_prefix (**str))
3912 {
3913 inst.error = _("immediate expression expected");
3914 return FAIL;
3915 }
3916
3917 (*str)++;
3918
3919 if (my_get_expression (& inst.reloc.exp, str))
3920 return FAIL;
3921
3922 if (inst.reloc.exp.X_op == O_constant)
3923 {
3924 offset = inst.reloc.exp.X_add_number;
3925
3926 if (offset > 255 || offset < -255)
3927 {
3928 inst.error = _("offset too large");
3929 return FAIL;
3930 }
3931
3932 if (offset >= 0)
3933 inst.instruction |= INDEX_UP;
3934 else
3935 offset = -offset;
3936
3937 inst.instruction |= offset;
3938 }
3939 else
3940 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3941
3942 return SUCCESS;
3943}
3944
3945static int
3946cp_byte_address_required_here (str)
3947 char ** str;
3948{
3949 char * p = * str;
3950 int pre_inc = 0;
3951 int write_back = 0;
3952
3953 if (*p == '[')
3954 {
3955 int reg;
3956
3957 p++;
3958 skip_whitespace (p);
3959
3960 if ((reg = reg_required_here (& p, 16)) == FAIL)
3961 return FAIL;
3962
3963 skip_whitespace (p);
3964
3965 if (*p == ']')
3966 {
3967 p++;
3968
3969 if (skip_past_comma (& p) == SUCCESS)
3970 {
3971 /* [Rn], #expr */
3972 write_back = WRITE_BACK;
3973
3974 if (reg == REG_PC)
3975 {
3976 inst.error = _("pc may not be used in post-increment");
3977 return FAIL;
3978 }
3979
3980 if (cp_byte_address_offset (& p) == FAIL)
3981 return FAIL;
3982 }
3983 else
3984 pre_inc = PRE_INDEX | INDEX_UP;
3985 }
3986 else
3987 {
3988 /* '['Rn, #expr']'[!] */
3989
3990 if (skip_past_comma (& p) == FAIL)
3991 {
3992 inst.error = _("pre-indexed expression expected");
3993 return FAIL;
3994 }
3995
3996 pre_inc = PRE_INDEX;
3997
3998 if (cp_byte_address_offset (& p) == FAIL)
3999 return FAIL;
4000
4001 skip_whitespace (p);
4002
4003 if (*p++ != ']')
4004 {
4005 inst.error = _("missing ]");
4006 return FAIL;
4007 }
4008
4009 skip_whitespace (p);
4010
4011 if (*p == '!')
4012 {
4013 if (reg == REG_PC)
4014 {
4015 inst.error = _("pc may not be used with write-back");
4016 return FAIL;
4017 }
4018
4019 p++;
4020 write_back = WRITE_BACK;
4021 }
4022 }
4023 }
4024 else
4025 {
4026 if (my_get_expression (&inst.reloc.exp, &p))
4027 return FAIL;
4028
4029 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4030 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4031 inst.reloc.pc_rel = 1;
4032 inst.instruction |= (REG_PC << 16);
4033 pre_inc = PRE_INDEX;
4034 }
4035
4036 inst.instruction |= write_back | pre_inc;
4037 *str = p;
4038 return SUCCESS;
4039}
4040
b99bd4ef 4041static void
f2b7cb0a 4042do_empty (str)
b99bd4ef 4043 char * str;
b99bd4ef
NC
4044{
4045 /* Do nothing really. */
b99bd4ef 4046 end_of_line (str);
b99bd4ef
NC
4047}
4048
4049static void
f2b7cb0a 4050do_mrs (str)
b99bd4ef 4051 char *str;
b99bd4ef
NC
4052{
4053 int skip = 0;
4054
4055 /* Only one syntax. */
4056 skip_whitespace (str);
4057
4058 if (reg_required_here (&str, 12) == FAIL)
4059 {
4060 inst.error = BAD_ARGS;
4061 return;
4062 }
4063
4064 if (skip_past_comma (&str) == FAIL)
4065 {
4066 inst.error = _("comma expected after register name");
4067 return;
4068 }
4069
4070 skip_whitespace (str);
4071
4072 if ( strcmp (str, "CPSR") == 0
4073 || strcmp (str, "SPSR") == 0
2d2255b5 4074 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4075 || strcmp (str, "cpsr") == 0
4076 || strcmp (str, "spsr") == 0)
4077 skip = 4;
4078
2d2255b5 4079 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4080 else if ( strcmp (str, "cpsr_all") == 0
4081 || strcmp (str, "spsr_all") == 0)
4082 skip = 8;
4083 else
4084 {
f03698e6 4085 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4086 return;
4087 }
4088
4089 if (* str == 's' || * str == 'S')
4090 inst.instruction |= SPSR_BIT;
4091 str += skip;
4092
b99bd4ef
NC
4093 end_of_line (str);
4094}
4095
4096/* Two possible forms:
4097 "{C|S}PSR_<field>, Rm",
4098 "{C|S}PSR_f, #expression". */
4099
4100static void
f2b7cb0a 4101do_msr (str)
b99bd4ef 4102 char * str;
b99bd4ef
NC
4103{
4104 skip_whitespace (str);
4105
4106 if (psr_required_here (& str) == FAIL)
4107 return;
4108
4109 if (skip_past_comma (& str) == FAIL)
4110 {
4111 inst.error = _("comma missing after psr flags");
4112 return;
4113 }
4114
4115 skip_whitespace (str);
4116
4117 if (reg_required_here (& str, 0) != FAIL)
4118 {
4119 inst.error = NULL;
b99bd4ef
NC
4120 end_of_line (str);
4121 return;
4122 }
4123
4124 if (! is_immediate_prefix (* str))
4125 {
4126 inst.error =
4127 _("only a register or immediate value can follow a psr flag");
4128 return;
4129 }
4130
4131 str ++;
4132 inst.error = NULL;
4133
4134 if (my_get_expression (& inst.reloc.exp, & str))
4135 {
4136 inst.error =
4137 _("only a register or immediate value can follow a psr flag");
4138 return;
4139 }
4140
4141#if 0 /* The first edition of the ARM architecture manual stated that
4142 writing anything other than the flags with an immediate operation
4143 had UNPREDICTABLE effects. This constraint was removed in the
4144 second edition of the specification. */
4145 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4146 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4147 {
4148 inst.error = _("immediate value cannot be used to set this field");
4149 return;
4150 }
4151#endif
4152
f2b7cb0a 4153 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4154
4155 if (inst.reloc.exp.X_add_symbol)
4156 {
4157 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4158 inst.reloc.pc_rel = 0;
4159 }
4160 else
4161 {
4162 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4163
4164 if (value == (unsigned) FAIL)
4165 {
f03698e6 4166 inst.error = _("invalid constant");
b99bd4ef
NC
4167 return;
4168 }
4169
4170 inst.instruction |= value;
4171 }
4172
4173 inst.error = NULL;
b99bd4ef
NC
4174 end_of_line (str);
4175}
4176
4177/* Long Multiply Parser
4178 UMULL RdLo, RdHi, Rm, Rs
4179 SMULL RdLo, RdHi, Rm, Rs
4180 UMLAL RdLo, RdHi, Rm, Rs
4181 SMLAL RdLo, RdHi, Rm, Rs. */
4182
4183static void
f2b7cb0a 4184do_mull (str)
b99bd4ef 4185 char * str;
b99bd4ef
NC
4186{
4187 int rdlo, rdhi, rm, rs;
4188
4189 /* Only one format "rdlo, rdhi, rm, rs". */
4190 skip_whitespace (str);
4191
4192 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4193 {
4194 inst.error = BAD_ARGS;
4195 return;
4196 }
4197
4198 if (skip_past_comma (&str) == FAIL
4199 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4200 {
4201 inst.error = BAD_ARGS;
4202 return;
4203 }
4204
4205 if (skip_past_comma (&str) == FAIL
4206 || (rm = reg_required_here (&str, 0)) == FAIL)
4207 {
4208 inst.error = BAD_ARGS;
4209 return;
4210 }
4211
4212 /* rdhi, rdlo and rm must all be different. */
4213 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4214 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4215
4216 if (skip_past_comma (&str) == FAIL
4217 || (rs = reg_required_here (&str, 8)) == FAIL)
4218 {
4219 inst.error = BAD_ARGS;
4220 return;
4221 }
4222
4223 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4224 {
4225 inst.error = BAD_PC;
4226 return;
4227 }
4228
b99bd4ef 4229 end_of_line (str);
b99bd4ef
NC
4230}
4231
4232static void
f2b7cb0a 4233do_mul (str)
b99bd4ef 4234 char * str;
b99bd4ef
NC
4235{
4236 int rd, rm;
4237
4238 /* Only one format "rd, rm, rs". */
4239 skip_whitespace (str);
4240
4241 if ((rd = reg_required_here (&str, 16)) == FAIL)
4242 {
4243 inst.error = BAD_ARGS;
4244 return;
4245 }
4246
4247 if (rd == REG_PC)
4248 {
4249 inst.error = BAD_PC;
4250 return;
4251 }
4252
4253 if (skip_past_comma (&str) == FAIL
4254 || (rm = reg_required_here (&str, 0)) == FAIL)
4255 {
4256 inst.error = BAD_ARGS;
4257 return;
4258 }
4259
4260 if (rm == REG_PC)
4261 {
4262 inst.error = BAD_PC;
4263 return;
4264 }
4265
4266 if (rm == rd)
4267 as_tsktsk (_("rd and rm should be different in mul"));
4268
4269 if (skip_past_comma (&str) == FAIL
4270 || (rm = reg_required_here (&str, 8)) == FAIL)
4271 {
4272 inst.error = BAD_ARGS;
4273 return;
4274 }
4275
4276 if (rm == REG_PC)
4277 {
4278 inst.error = BAD_PC;
4279 return;
4280 }
4281
b99bd4ef 4282 end_of_line (str);
b99bd4ef
NC
4283}
4284
4285static void
f2b7cb0a 4286do_mla (str)
b99bd4ef 4287 char * str;
b99bd4ef
NC
4288{
4289 int rd, rm;
4290
4291 /* Only one format "rd, rm, rs, rn". */
4292 skip_whitespace (str);
4293
4294 if ((rd = reg_required_here (&str, 16)) == FAIL)
4295 {
4296 inst.error = BAD_ARGS;
4297 return;
4298 }
4299
4300 if (rd == REG_PC)
4301 {
4302 inst.error = BAD_PC;
4303 return;
4304 }
4305
4306 if (skip_past_comma (&str) == FAIL
4307 || (rm = reg_required_here (&str, 0)) == FAIL)
4308 {
4309 inst.error = BAD_ARGS;
4310 return;
4311 }
4312
4313 if (rm == REG_PC)
4314 {
4315 inst.error = BAD_PC;
4316 return;
4317 }
4318
4319 if (rm == rd)
4320 as_tsktsk (_("rd and rm should be different in mla"));
4321
4322 if (skip_past_comma (&str) == FAIL
4323 || (rd = reg_required_here (&str, 8)) == FAIL
4324 || skip_past_comma (&str) == FAIL
4325 || (rm = reg_required_here (&str, 12)) == FAIL)
4326 {
4327 inst.error = BAD_ARGS;
4328 return;
4329 }
4330
4331 if (rd == REG_PC || rm == REG_PC)
4332 {
4333 inst.error = BAD_PC;
4334 return;
4335 }
4336
b99bd4ef 4337 end_of_line (str);
b99bd4ef
NC
4338}
4339
4340/* Expects *str -> the characters "acc0", possibly with leading blanks.
4341 Advances *str to the next non-alphanumeric.
4342 Returns 0, or else FAIL (in which case sets inst.error).
4343
4344 (In a future XScale, there may be accumulators other than zero.
4345 At that time this routine and its callers can be upgraded to suit.) */
4346
4347static int
4348accum0_required_here (str)
4349 char ** str;
4350{
4351 static char buff [128]; /* Note the address is taken. Hence, static. */
4352 char * p = * str;
4353 char c;
4354 int result = 0; /* The accum number. */
4355
4356 skip_whitespace (p);
4357
4358 *str = p; /* Advance caller's string pointer too. */
4359 c = *p++;
3882b010 4360 while (ISALNUM (c))
b99bd4ef
NC
4361 c = *p++;
4362
4363 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4364
4365 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4366 {
4367 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4368 inst.error = buff;
4369 result = FAIL;
4370 }
4371
4372 *p = c; /* Unzap. */
4373 *str = p; /* Caller's string pointer to after match. */
4374 return result;
4375}
4376
4377/* Expects **str -> after a comma. May be leading blanks.
4378 Advances *str, recognizing a load mode, and setting inst.instruction.
4379 Returns rn, or else FAIL (in which case may set inst.error
4380 and not advance str)
4381
4382 Note: doesn't know Rd, so no err checks that require such knowledge. */
4383
4384static int
4385ld_mode_required_here (string)
4386 char ** string;
4387{
4388 char * str = * string;
4389 int rn;
4390 int pre_inc = 0;
4391
4392 skip_whitespace (str);
4393
4394 if (* str == '[')
4395 {
4396 str++;
4397
4398 skip_whitespace (str);
4399
4400 if ((rn = reg_required_here (& str, 16)) == FAIL)
4401 return FAIL;
4402
4403 skip_whitespace (str);
4404
4405 if (* str == ']')
4406 {
4407 str ++;
4408
4409 if (skip_past_comma (& str) == SUCCESS)
4410 {
4411 /* [Rn],... (post inc) */
90e4755a 4412 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4413 return FAIL;
4414 }
4415 else /* [Rn] */
4416 {
cc8a6dd0 4417 skip_whitespace (str);
b99bd4ef 4418
cc8a6dd0
KH
4419 if (* str == '!')
4420 {
4421 str ++;
4422 inst.instruction |= WRITE_BACK;
4423 }
b99bd4ef
NC
4424
4425 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4426 pre_inc = 1;
4427 }
4428 }
4429 else /* [Rn,...] */
4430 {
4431 if (skip_past_comma (& str) == FAIL)
4432 {
4433 inst.error = _("pre-indexed expression expected");
4434 return FAIL;
4435 }
4436
4437 pre_inc = 1;
4438
90e4755a 4439 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4440 return FAIL;
4441
4442 skip_whitespace (str);
4443
4444 if (* str ++ != ']')
4445 {
4446 inst.error = _("missing ]");
4447 return FAIL;
4448 }
4449
4450 skip_whitespace (str);
4451
4452 if (* str == '!')
4453 {
4454 str ++;
4455 inst.instruction |= WRITE_BACK;
4456 }
4457 }
4458 }
4459 else if (* str == '=') /* ldr's "r,=label" syntax */
4460 /* We should never reach here, because <text> = <expression> is
4461 caught gas/read.c read_a_source_file() as a .set operation. */
4462 return FAIL;
4463 else /* PC +- 8 bit immediate offset. */
4464 {
4465 if (my_get_expression (& inst.reloc.exp, & str))
4466 return FAIL;
4467
4468 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4469 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4470 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4471 inst.reloc.pc_rel = 1;
4472 inst.instruction |= (REG_PC << 16);
4473
4474 rn = REG_PC;
4475 pre_inc = 1;
4476 }
4477
4478 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4479 * string = str;
4480
4481 return rn;
4482}
4483
4484/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4485 SMLAxy{cond} Rd,Rm,Rs,Rn
4486 SMLAWy{cond} Rd,Rm,Rs,Rn
4487 Error if any register is R15. */
4488
4489static void
f2b7cb0a 4490do_smla (str)
b99bd4ef 4491 char * str;
b99bd4ef
NC
4492{
4493 int rd, rm, rs, rn;
4494
4495 skip_whitespace (str);
4496
4497 if ((rd = reg_required_here (& str, 16)) == FAIL
4498 || skip_past_comma (& str) == FAIL
4499 || (rm = reg_required_here (& str, 0)) == FAIL
4500 || skip_past_comma (& str) == FAIL
4501 || (rs = reg_required_here (& str, 8)) == FAIL
4502 || skip_past_comma (& str) == FAIL
4503 || (rn = reg_required_here (& str, 12)) == FAIL)
4504 inst.error = BAD_ARGS;
4505
4506 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4507 inst.error = BAD_PC;
4508
b99bd4ef
NC
4509 else
4510 end_of_line (str);
4511}
4512
4513/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4514 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4515 Error if any register is R15.
4516 Warning if Rdlo == Rdhi. */
4517
4518static void
f2b7cb0a 4519do_smlal (str)
b99bd4ef 4520 char * str;
b99bd4ef
NC
4521{
4522 int rdlo, rdhi, rm, rs;
4523
4524 skip_whitespace (str);
4525
4526 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4527 || skip_past_comma (& str) == FAIL
4528 || (rdhi = reg_required_here (& str, 16)) == FAIL
4529 || skip_past_comma (& str) == FAIL
4530 || (rm = reg_required_here (& str, 0)) == FAIL
4531 || skip_past_comma (& str) == FAIL
4532 || (rs = reg_required_here (& str, 8)) == FAIL)
4533 {
4534 inst.error = BAD_ARGS;
4535 return;
4536 }
4537
4538 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4539 {
4540 inst.error = BAD_PC;
4541 return;
4542 }
4543
4544 if (rdlo == rdhi)
4545 as_tsktsk (_("rdhi and rdlo must be different"));
4546
f2b7cb0a 4547 end_of_line (str);
b99bd4ef
NC
4548}
4549
4550/* ARM V5E (El Segundo) signed-multiply (argument parse)
4551 SMULxy{cond} Rd,Rm,Rs
4552 Error if any register is R15. */
4553
4554static void
f2b7cb0a 4555do_smul (str)
b99bd4ef 4556 char * str;
b99bd4ef
NC
4557{
4558 int rd, rm, rs;
4559
4560 skip_whitespace (str);
4561
4562 if ((rd = reg_required_here (& str, 16)) == FAIL
4563 || skip_past_comma (& str) == FAIL
4564 || (rm = reg_required_here (& str, 0)) == FAIL
4565 || skip_past_comma (& str) == FAIL
4566 || (rs = reg_required_here (& str, 8)) == FAIL)
4567 inst.error = BAD_ARGS;
4568
4569 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4570 inst.error = BAD_PC;
4571
b99bd4ef
NC
4572 else
4573 end_of_line (str);
4574}
4575
4576/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4577 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4578 Error if any register is R15. */
4579
4580static void
f2b7cb0a 4581do_qadd (str)
b99bd4ef 4582 char * str;
b99bd4ef
NC
4583{
4584 int rd, rm, rn;
4585
4586 skip_whitespace (str);
4587
4588 if ((rd = reg_required_here (& str, 12)) == FAIL
4589 || skip_past_comma (& str) == FAIL
4590 || (rm = reg_required_here (& str, 0)) == FAIL
4591 || skip_past_comma (& str) == FAIL
4592 || (rn = reg_required_here (& str, 16)) == FAIL)
4593 inst.error = BAD_ARGS;
4594
4595 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4596 inst.error = BAD_PC;
4597
b99bd4ef
NC
4598 else
4599 end_of_line (str);
4600}
4601
4602/* ARM V5E (el Segundo)
4603 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4604 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4605
4606 These are equivalent to the XScale instructions MAR and MRA,
4607 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4608
4609 Result unpredicatable if Rd or Rn is R15. */
4610
4611static void
f2b7cb0a 4612do_co_reg2c (str)
b99bd4ef 4613 char * str;
b99bd4ef
NC
4614{
4615 int rd, rn;
4616
4617 skip_whitespace (str);
4618
4619 if (co_proc_number (& str) == FAIL)
4620 {
4621 if (!inst.error)
4622 inst.error = BAD_ARGS;
4623 return;
4624 }
4625
4626 if (skip_past_comma (& str) == FAIL
4627 || cp_opc_expr (& str, 4, 4) == FAIL)
4628 {
4629 if (!inst.error)
4630 inst.error = BAD_ARGS;
4631 return;
4632 }
4633
4634 if (skip_past_comma (& str) == FAIL
4635 || (rd = reg_required_here (& str, 12)) == FAIL)
4636 {
4637 if (!inst.error)
4638 inst.error = BAD_ARGS;
4639 return;
4640 }
4641
4642 if (skip_past_comma (& str) == FAIL
4643 || (rn = reg_required_here (& str, 16)) == FAIL)
4644 {
4645 if (!inst.error)
4646 inst.error = BAD_ARGS;
4647 return;
4648 }
4649
09d92015
MM
4650 /* Unpredictable result if rd or rn is R15. */
4651 if (rd == REG_PC || rn == REG_PC)
4652 as_tsktsk
4653 (_("Warning: instruction unpredictable when using r15"));
4654
4655 if (skip_past_comma (& str) == FAIL
4656 || cp_reg_required_here (& str, 0) == FAIL)
4657 {
4658 if (!inst.error)
4659 inst.error = BAD_ARGS;
4660 return;
4661 }
4662
4663 end_of_line (str);
4664}
4665
4666/* ARM V5 count-leading-zeroes instruction (argument parse)
4667 CLZ{<cond>} <Rd>, <Rm>
4668 Condition defaults to COND_ALWAYS.
4669 Error if Rd or Rm are R15. */
4670
4671static void
4672do_clz (str)
4673 char * str;
4674{
4675 int rd, rm;
4676
4677 skip_whitespace (str);
4678
4679 if (((rd = reg_required_here (& str, 12)) == FAIL)
4680 || (skip_past_comma (& str) == FAIL)
4681 || ((rm = reg_required_here (& str, 0)) == FAIL))
4682 inst.error = BAD_ARGS;
4683
4684 else if (rd == REG_PC || rm == REG_PC )
4685 inst.error = BAD_PC;
4686
4687 else
4688 end_of_line (str);
4689}
4690
4691/* ARM V5 (argument parse)
4692 LDC2{L} <coproc>, <CRd>, <addressing mode>
4693 STC2{L} <coproc>, <CRd>, <addressing mode>
4694 Instruction is not conditional, and has 0xf in the condition field.
4695 Otherwise, it's the same as LDC/STC. */
4696
4697static void
4698do_lstc2 (str)
4699 char * str;
4700{
4701 skip_whitespace (str);
4702
4703 if (co_proc_number (& str) == FAIL)
4704 {
4705 if (!inst.error)
4706 inst.error = BAD_ARGS;
4707 }
4708 else if (skip_past_comma (& str) == FAIL
4709 || cp_reg_required_here (& str, 12) == FAIL)
4710 {
4711 if (!inst.error)
4712 inst.error = BAD_ARGS;
4713 }
4714 else if (skip_past_comma (& str) == FAIL
4715 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4716 {
4717 if (! inst.error)
4718 inst.error = BAD_ARGS;
4719 }
4720 else
4721 end_of_line (str);
4722}
4723
4724/* ARM V5 (argument parse)
4725 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4726 Instruction is not conditional, and has 0xf in the condition field.
4727 Otherwise, it's the same as CDP. */
4728
4729static void
4730do_cdp2 (str)
4731 char * str;
4732{
4733 skip_whitespace (str);
4734
4735 if (co_proc_number (& str) == FAIL)
4736 {
4737 if (!inst.error)
4738 inst.error = BAD_ARGS;
4739 return;
4740 }
4741
4742 if (skip_past_comma (& str) == FAIL
4743 || cp_opc_expr (& str, 20,4) == FAIL)
4744 {
4745 if (!inst.error)
4746 inst.error = BAD_ARGS;
4747 return;
4748 }
4749
4750 if (skip_past_comma (& str) == FAIL
4751 || cp_reg_required_here (& str, 12) == FAIL)
4752 {
4753 if (!inst.error)
4754 inst.error = BAD_ARGS;
4755 return;
4756 }
4757
4758 if (skip_past_comma (& str) == FAIL
4759 || cp_reg_required_here (& str, 16) == FAIL)
4760 {
4761 if (!inst.error)
4762 inst.error = BAD_ARGS;
4763 return;
4764 }
4765
4766 if (skip_past_comma (& str) == FAIL
4767 || cp_reg_required_here (& str, 0) == FAIL)
4768 {
4769 if (!inst.error)
4770 inst.error = BAD_ARGS;
4771 return;
4772 }
4773
4774 if (skip_past_comma (& str) == SUCCESS)
4775 {
4776 if (cp_opc_expr (& str, 5, 3) == FAIL)
4777 {
4778 if (!inst.error)
4779 inst.error = BAD_ARGS;
4780 return;
4781 }
4782 }
4783
4784 end_of_line (str);
4785}
4786
4787/* ARM V5 (argument parse)
4788 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4789 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4790 Instruction is not conditional, and has 0xf in the condition field.
4791 Otherwise, it's the same as MCR/MRC. */
4792
4793static void
4794do_co_reg2 (str)
4795 char * str;
4796{
4797 skip_whitespace (str);
4798
4799 if (co_proc_number (& str) == FAIL)
4800 {
4801 if (!inst.error)
4802 inst.error = BAD_ARGS;
4803 return;
4804 }
4805
4806 if (skip_past_comma (& str) == FAIL
4807 || cp_opc_expr (& str, 21, 3) == FAIL)
4808 {
4809 if (!inst.error)
4810 inst.error = BAD_ARGS;
4811 return;
4812 }
4813
4814 if (skip_past_comma (& str) == FAIL
4815 || reg_required_here (& str, 12) == FAIL)
4816 {
4817 if (!inst.error)
4818 inst.error = BAD_ARGS;
4819 return;
4820 }
4821
4822 if (skip_past_comma (& str) == FAIL
4823 || cp_reg_required_here (& str, 16) == FAIL)
4824 {
4825 if (!inst.error)
4826 inst.error = BAD_ARGS;
4827 return;
4828 }
4829
4830 if (skip_past_comma (& str) == FAIL
4831 || cp_reg_required_here (& str, 0) == FAIL)
4832 {
4833 if (!inst.error)
4834 inst.error = BAD_ARGS;
4835 return;
4836 }
4837
4838 if (skip_past_comma (& str) == SUCCESS)
4839 {
4840 if (cp_opc_expr (& str, 5, 3) == FAIL)
4841 {
4842 if (!inst.error)
4843 inst.error = BAD_ARGS;
4844 return;
4845 }
4846 }
4847
4848 end_of_line (str);
4849}
4850
4851/* ARM v5TEJ. Jump to Jazelle code. */
4852static void
4853do_bxj (str)
4854 char * str;
4855{
4856 int reg;
4857
4858 skip_whitespace (str);
4859
4860 if ((reg = reg_required_here (&str, 0)) == FAIL)
4861 {
4862 inst.error = BAD_ARGS;
4863 return;
4864 }
4865
4866 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4867 if (reg == REG_PC)
4868 as_tsktsk (_("use of r15 in bxj is not really useful"));
4869
4870 end_of_line (str);
4871}
4872
4873/* ARM V6 umaal (argument parse). */
4874
4875static void
4876do_umaal (str)
4877 char *str;
4878{
4879
4880 int rdlo, rdhi, rm, rs;
4881
4882 skip_whitespace (str);
4883 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4884 || skip_past_comma (& str) == FAIL
4885 || (rdhi = reg_required_here (& str, 16)) == FAIL
4886 || skip_past_comma (& str) == FAIL
4887 || (rm = reg_required_here (& str, 0)) == FAIL
4888 || skip_past_comma (& str) == FAIL
5533419b 4889 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4890 {
4891 inst.error = BAD_ARGS;
4892 return;
4893 }
4894
4895 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4896 {
4897 inst.error = BAD_PC;
4898 return;
4899 }
4900
4901 end_of_line (str);
4902}
4903
4904/* ARM V6 strex (argument parse). */
4905
4906static void
4907do_strex (str)
4908 char *str;
4909{
4910 int rd, rm, rn;
4911
4912 /* Parse Rd, Rm,. */
4913 skip_whitespace (str);
4914 if ((rd = reg_required_here (& str, 12)) == FAIL
4915 || skip_past_comma (& str) == FAIL
4916 || (rm = reg_required_here (& str, 0)) == FAIL
4917 || skip_past_comma (& str) == FAIL)
4918 {
4919 inst.error = BAD_ARGS;
4920 return;
4921 }
4922 if (rd == REG_PC || rm == REG_PC)
4923 {
4924 inst.error = BAD_PC;
4925 return;
4926 }
4927 if (rd == rm)
4928 {
4929 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4930 return;
4931 }
4932
4933 /* Skip past '['. */
4934 if ((strlen (str) >= 1)
4935 && strncmp (str, "[", 1) == 0)
4936 str+=1;
4937 skip_whitespace (str);
4938
4939 /* Parse Rn. */
4940 if ((rn = reg_required_here (& str, 16)) == FAIL)
4941 {
4942 inst.error = BAD_ARGS;
4943 return;
4944 }
4945 else if (rn == REG_PC)
4946 {
4947 inst.error = BAD_PC;
4948 return;
4949 }
4950 if (rd == rn)
4951 {
4952 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4953 return;
4954 }
4955 skip_whitespace (str);
4956
4957 /* Skip past ']'. */
4958 if ((strlen (str) >= 1)
4959 && strncmp (str, "]", 1) == 0)
4960 str+=1;
4961
4962 end_of_line (str);
4963}
4964
4965/* ARM V6 ssat (argument parse). */
4966
4967static void
4968do_ssat (str)
4969 char* str;
4970{
4971 do_sat (&str, /*bias=*/-1);
4972 end_of_line (str);
4973}
4974
4975/* ARM V6 usat (argument parse). */
4976
4977static void
4978do_usat (str)
4979 char* str;
4980{
4981 do_sat (&str, /*bias=*/0);
4982 end_of_line (str);
4983}
4984
4985static void
4986do_sat (str, bias)
4987 char **str;
4988 int bias;
4989{
4990 int rd, rm;
4991 expressionS expr;
4992
4993 skip_whitespace (*str);
4994
4995 /* Parse <Rd>, field. */
4996 if ((rd = reg_required_here (str, 12)) == FAIL
4997 || skip_past_comma (str) == FAIL)
4998 {
4999 inst.error = BAD_ARGS;
5000 return;
5001 }
5002 if (rd == REG_PC)
5003 {
5004 inst.error = BAD_PC;
5005 return;
5006 }
5007
5008 /* Parse #<immed>, field. */
5009 if (is_immediate_prefix (**str))
5010 (*str)++;
5011 else
5012 {
5013 inst.error = _("immediate expression expected");
5014 return;
5015 }
5016 if (my_get_expression (&expr, str))
5017 {
5018 inst.error = _("bad expression");
5019 return;
5020 }
5021 if (expr.X_op != O_constant)
5022 {
5023 inst.error = _("constant expression expected");
5024 return;
5025 }
5026 if (expr.X_add_number + bias < 0
5027 || expr.X_add_number + bias > 31)
5028 {
5029 inst.error = _("immediate value out of range");
5030 return;
5031 }
5032 inst.instruction |= (expr.X_add_number + bias) << 16;
5033 if (skip_past_comma (str) == FAIL)
5034 {
5035 inst.error = BAD_ARGS;
5036 return;
5037 }
5038
5039 /* Parse <Rm> field. */
5040 if ((rm = reg_required_here (str, 0)) == FAIL)
5041 {
5042 inst.error = BAD_ARGS;
5043 return;
5044 }
5045 if (rm == REG_PC)
5046 {
5047 inst.error = BAD_PC;
5048 return;
5049 }
5050
5051 if (skip_past_comma (str) == SUCCESS)
5052 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5053}
5054
5055/* ARM V6 ssat16 (argument parse). */
5056
5057static void
5058do_ssat16 (str)
5059 char *str;
5060{
5061 do_sat16 (&str, /*bias=*/-1);
5062 end_of_line (str);
5063}
5064
5065static void
5066do_usat16 (str)
5067 char *str;
5068{
5069 do_sat16 (&str, /*bias=*/0);
5070 end_of_line (str);
5071}
5072
5073static void
5074do_sat16 (str, bias)
5075 char **str;
5076 int bias;
5077{
5078 int rd, rm;
5079 expressionS expr;
5080
5081 skip_whitespace (*str);
5082
5083 /* Parse the <Rd> field. */
5084 if ((rd = reg_required_here (str, 12)) == FAIL
5085 || skip_past_comma (str) == FAIL)
5086 {
5087 inst.error = BAD_ARGS;
5088 return;
5089 }
5090 if (rd == REG_PC)
5091 {
5092 inst.error = BAD_PC;
5093 return;
5094 }
5095
5096 /* Parse #<immed>, field. */
5097 if (is_immediate_prefix (**str))
5098 (*str)++;
5099 else
5100 {
5101 inst.error = _("immediate expression expected");
5102 return;
5103 }
5104 if (my_get_expression (&expr, str))
5105 {
5106 inst.error = _("bad expression");
5107 return;
5108 }
5109 if (expr.X_op != O_constant)
5110 {
5111 inst.error = _("constant expression expected");
5112 return;
5113 }
5114 if (expr.X_add_number + bias < 0
5115 || expr.X_add_number + bias > 15)
5116 {
5117 inst.error = _("immediate value out of range");
5118 return;
5119 }
5120 inst.instruction |= (expr.X_add_number + bias) << 16;
5121 if (skip_past_comma (str) == FAIL)
5122 {
5123 inst.error = BAD_ARGS;
5124 return;
5125 }
5126
5127 /* Parse <Rm> field. */
5128 if ((rm = reg_required_here (str, 0)) == FAIL)
5129 {
5130 inst.error = BAD_ARGS;
5131 return;
5132 }
5133 if (rm == REG_PC)
5134 {
5135 inst.error = BAD_PC;
5136 return;
5137 }
5138}
5139
5140/* ARM V6 srs (argument parse). */
5141
5142static void
5143do_srs (str)
5144 char* str;
5145{
5146 char *exclam;
5147 skip_whitespace (str);
5148 exclam = strchr (str, '!');
5149 if (exclam)
5150 *exclam = '\0';
5151 do_cps_mode (&str);
5152 if (exclam)
5153 *exclam = '!';
5154 if (*str == '!')
5155 {
5156 inst.instruction |= WRITE_BACK;
5157 str++;
5158 }
5159 end_of_line (str);
5160}
5161
5162/* ARM V6 SMMUL (argument parse). */
5163
5164static void
5165do_smmul (str)
5166 char* str;
5167{
5168 int rd, rm, rs;
5169
5170 skip_whitespace (str);
5171 if ((rd = reg_required_here (&str, 16)) == FAIL
5172 || skip_past_comma (&str) == FAIL
5173 || (rm = reg_required_here (&str, 0)) == FAIL
5174 || skip_past_comma (&str) == FAIL
5175 || (rs = reg_required_here (&str, 8)) == FAIL)
5176 {
5177 inst.error = BAD_ARGS;
5178 return;
5179 }
5180
5181 if (rd == REG_PC
5182 || rm == REG_PC
5183 || rs == REG_PC)
5184 {
5185 inst.error = BAD_PC;
5186 return;
5187 }
5188
5189 end_of_line (str);
5190
5191}
5192
5193/* ARM V6 SMLALD (argument parse). */
5194
5195static void
5196do_smlald (str)
5197 char* str;
5198{
5199 int rdlo, rdhi, rm, rs;
5200 skip_whitespace (str);
5201 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5202 || skip_past_comma (&str) == FAIL
5203 || (rdhi = reg_required_here (&str, 16)) == FAIL
5204 || skip_past_comma (&str) == FAIL
5205 || (rm = reg_required_here (&str, 0)) == FAIL
5206 || skip_past_comma (&str) == FAIL
5207 || (rs = reg_required_here (&str, 8)) == FAIL)
5208 {
5209 inst.error = BAD_ARGS;
5210 return;
5211 }
5212
5213 if (rdlo == REG_PC
5214 || rdhi == REG_PC
5215 || rm == REG_PC
5216 || rs == REG_PC)
5217 {
5218 inst.error = BAD_PC;
5219 return;
5220 }
5221
5222 end_of_line (str);
5223}
5224
5225/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5226 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5227
5228static void
5229do_smlad (str)
5230 char *str;
5231{
5232 int rd, rm, rs, rn;
5233
5234 skip_whitespace (str);
5235 if ((rd = reg_required_here (&str, 16)) == FAIL
5236 || skip_past_comma (&str) == FAIL
5237 || (rm = reg_required_here (&str, 0)) == FAIL
5238 || skip_past_comma (&str) == FAIL
5239 || (rs = reg_required_here (&str, 8)) == FAIL
5240 || skip_past_comma (&str) == FAIL
5241 || (rn = reg_required_here (&str, 12)) == FAIL)
5242 {
5243 inst.error = BAD_ARGS;
5244 return;
5245 }
5246
5247 if (rd == REG_PC
5248 || rn == REG_PC
5249 || rs == REG_PC
5250 || rm == REG_PC)
5251 {
5252 inst.error = BAD_PC;
5253 return;
5254 }
5255
5256 end_of_line (str);
5257}
5258
5259/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5260 preserving the other bits.
5261
5262 setend <endian_specifier>, where <endian_specifier> is either
5263 BE or LE. */
5264
5265static void
5266do_setend (str)
5267 char *str;
5268{
5269 if (do_endian_specifier (str))
5270 inst.instruction |= 0x200;
5271}
5272
5273/* Returns true if the endian-specifier indicates big-endianness. */
5274
5275static int
5276do_endian_specifier (str)
5277 char *str;
5278{
5279 int big_endian = 0;
5280
5281 skip_whitespace (str);
5282 if (strlen (str) < 2)
5283 inst.error = _("missing endian specifier");
5284 else if (strncasecmp (str, "BE", 2) == 0)
5285 {
5286 str += 2;
5287 big_endian = 1;
5288 }
5289 else if (strncasecmp (str, "LE", 2) == 0)
5290 str += 2;
5291 else
5292 inst.error = _("valid endian specifiers are be or le");
5293
5294 end_of_line (str);
5295
5296 return big_endian;
5297}
5298
5299/* ARM V6 SXTH.
5300
5301 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5302 Condition defaults to COND_ALWAYS.
5303 Error if any register uses R15. */
5304
5305static void
5306do_sxth (str)
5307 char *str;
5308{
5309 int rd, rm;
5310 expressionS expr;
5311 int rotation_clear_mask = 0xfffff3ff;
5312 int rotation_eight_mask = 0x00000400;
5313 int rotation_sixteen_mask = 0x00000800;
5314 int rotation_twenty_four_mask = 0x00000c00;
5315
5316 skip_whitespace (str);
5317 if ((rd = reg_required_here (&str, 12)) == FAIL
5318 || skip_past_comma (&str) == FAIL
5319 || (rm = reg_required_here (&str, 0)) == FAIL)
5320 {
5321 inst.error = BAD_ARGS;
5322 return;
5323 }
5324
5325 else if (rd == REG_PC || rm == REG_PC)
5326 {
5327 inst.error = BAD_PC;
5328 return;
5329 }
5330
5331 /* Zero out the rotation field. */
5332 inst.instruction &= rotation_clear_mask;
5333
5334 /* Check for lack of optional rotation field. */
5335 if (skip_past_comma (&str) == FAIL)
5336 {
5337 end_of_line (str);
5338 return;
5339 }
5340
5341 /* Move past 'ROR'. */
5342 skip_whitespace (str);
5343 if (strncasecmp (str, "ROR", 3) == 0)
5344 str+=3;
5345 else
5346 {
5347 inst.error = _("missing rotation field after comma");
5348 return;
5349 }
5350
5351 /* Get the immediate constant. */
5352 skip_whitespace (str);
5353 if (is_immediate_prefix (* str))
5354 str++;
5355 else
5356 {
5357 inst.error = _("immediate expression expected");
5358 return;
5359 }
5360
5361 if (my_get_expression (&expr, &str))
5362 {
5363 inst.error = _("bad expression");
5364 return;
5365 }
5366
5367 if (expr.X_op != O_constant)
5368 {
5369 inst.error = _("constant expression expected");
5370 return;
5371 }
5372
5373 switch (expr.X_add_number)
5374 {
5375 case 0:
5376 /* Rotation field has already been zeroed. */
5377 break;
5378 case 8:
5379 inst.instruction |= rotation_eight_mask;
5380 break;
5381
5382 case 16:
5383 inst.instruction |= rotation_sixteen_mask;
5384 break;
5385
5386 case 24:
5387 inst.instruction |= rotation_twenty_four_mask;
5388 break;
5389
5390 default:
5391 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5392 break;
5393 }
5394
5395 end_of_line (str);
5396
5397}
5398
5399/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5400 extends it to 32-bits, and adds the result to a value in another
5401 register. You can specify a rotation by 0, 8, 16, or 24 bits
5402 before extracting the 16-bit value.
5403 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5404 Condition defaults to COND_ALWAYS.
5405 Error if any register uses R15. */
5406
5407static void
5408do_sxtah (str)
5409 char *str;
5410{
5411 int rd, rn, rm;
5412 expressionS expr;
5413 int rotation_clear_mask = 0xfffff3ff;
5414 int rotation_eight_mask = 0x00000400;
5415 int rotation_sixteen_mask = 0x00000800;
5416 int rotation_twenty_four_mask = 0x00000c00;
5417
5418 skip_whitespace (str);
5419 if ((rd = reg_required_here (&str, 12)) == FAIL
5420 || skip_past_comma (&str) == FAIL
5421 || (rn = reg_required_here (&str, 16)) == FAIL
5422 || skip_past_comma (&str) == FAIL
5423 || (rm = reg_required_here (&str, 0)) == FAIL)
5424 {
5425 inst.error = BAD_ARGS;
5426 return;
5427 }
5428
5429 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5430 {
5431 inst.error = BAD_PC;
5432 return;
5433 }
5434
5435 /* Zero out the rotation field. */
5436 inst.instruction &= rotation_clear_mask;
5437
5438 /* Check for lack of optional rotation field. */
5439 if (skip_past_comma (&str) == FAIL)
5440 {
5441 end_of_line (str);
5442 return;
5443 }
5444
5445 /* Move past 'ROR'. */
5446 skip_whitespace (str);
5447 if (strncasecmp (str, "ROR", 3) == 0)
5448 str+=3;
5449 else
5450 {
5451 inst.error = _("missing rotation field after comma");
5452 return;
5453 }
5454
5455 /* Get the immediate constant. */
5456 skip_whitespace (str);
5457 if (is_immediate_prefix (* str))
5458 str++;
5459 else
5460 {
5461 inst.error = _("immediate expression expected");
5462 return;
5463 }
5464
5465 if (my_get_expression (&expr, &str))
5466 {
5467 inst.error = _("bad expression");
5468 return;
5469 }
5470
5471 if (expr.X_op != O_constant)
5472 {
5473 inst.error = _("constant expression expected");
5474 return;
5475 }
5476
5477 switch (expr.X_add_number)
5478 {
5479 case 0:
5480 /* Rotation field has already been zeroed. */
5481 break;
5482
5483 case 8:
5484 inst.instruction |= rotation_eight_mask;
5485 break;
5486
5487 case 16:
5488 inst.instruction |= rotation_sixteen_mask;
5489 break;
5490
5491 case 24:
5492 inst.instruction |= rotation_twenty_four_mask;
5493 break;
5494
5495 default:
5496 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5497 break;
5498 }
5499
5500 end_of_line (str);
5501
5502}
5503
5504
5505/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5506 word at the specified address and the following word
5507 respectively.
5508 Unconditionally executed.
5509 Error if Rn is R15.
5510*/
5511
5512static void
5513do_rfe (str)
5514 char *str;
5515{
5516 int rn;
5517
5518 skip_whitespace (str);
5519
5520 if ((rn = reg_required_here (&str, 16)) == FAIL)
5521 return;
b99bd4ef 5522
09d92015 5523 if (rn == REG_PC)
b99bd4ef 5524 {
09d92015 5525 inst.error = BAD_PC;
b99bd4ef
NC
5526 return;
5527 }
5528
09d92015
MM
5529 skip_whitespace (str);
5530
5531 if (*str == '!')
5532 {
5533 inst.instruction |= WRITE_BACK;
5534 str++;
5535 }
b99bd4ef
NC
5536 end_of_line (str);
5537}
5538
09d92015
MM
5539/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5540 register (argument parse).
5541 REV{<cond>} Rd, Rm.
5542 Condition defaults to COND_ALWAYS.
5543 Error if Rd or Rm are R15. */
b99bd4ef
NC
5544
5545static void
09d92015
MM
5546do_rev (str)
5547 char* str;
b99bd4ef
NC
5548{
5549 int rd, rm;
5550
b99bd4ef
NC
5551 skip_whitespace (str);
5552
09d92015
MM
5553 if ((rd = reg_required_here (&str, 12)) == FAIL
5554 || skip_past_comma (&str) == FAIL
5555 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5556 inst.error = BAD_ARGS;
5557
09d92015 5558 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5559 inst.error = BAD_PC;
5560
5561 else
5562 end_of_line (str);
5563}
5564
09d92015
MM
5565/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5566 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5567 Condition defaults to COND_ALWAYS.
5568 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5569
5570static void
09d92015
MM
5571do_qadd16 (str)
5572 char* str;
b99bd4ef 5573{
09d92015
MM
5574 int rd, rm, rn;
5575
b99bd4ef
NC
5576 skip_whitespace (str);
5577
09d92015
MM
5578 if ((rd = reg_required_here (&str, 12)) == FAIL
5579 || skip_past_comma (&str) == FAIL
5580 || (rn = reg_required_here (&str, 16)) == FAIL
5581 || skip_past_comma (&str) == FAIL
5582 || (rm = reg_required_here (&str, 0)) == FAIL)
5583 inst.error = BAD_ARGS;
5584
5585 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5586 inst.error = BAD_PC;
5587
b99bd4ef
NC
5588 else
5589 end_of_line (str);
5590}
5591
09d92015
MM
5592/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5593 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5594 Condition defaults to COND_ALWAYS.
5595 Error if Rd, Rn or Rm are R15. */
5596
5597static void
5598do_pkhbt (str)
5599 char* str;
5600{
5601 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5602}
5603
5604/* ARM V6 PKHTB (Argument Parse). */
5605
5606static void
5607do_pkhtb (str)
5608 char* str;
5609{
5610 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5611}
b99bd4ef
NC
5612
5613static void
09d92015
MM
5614do_pkh_core (str, shift)
5615 char* str;
5616 int shift;
b99bd4ef 5617{
09d92015 5618 int rd, rn, rm;
b99bd4ef 5619
09d92015
MM
5620 skip_whitespace (str);
5621 if (((rd = reg_required_here (&str, 12)) == FAIL)
5622 || (skip_past_comma (&str) == FAIL)
5623 || ((rn = reg_required_here (&str, 16)) == FAIL)
5624 || (skip_past_comma (&str) == FAIL)
5625 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5626 {
09d92015 5627 inst.error = BAD_ARGS;
b99bd4ef
NC
5628 return;
5629 }
5630
09d92015 5631 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5632 {
09d92015 5633 inst.error = BAD_PC;
b99bd4ef
NC
5634 return;
5635 }
5636
09d92015
MM
5637 /* Check for optional shift immediate constant. */
5638 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5639 {
09d92015
MM
5640 if (shift == SHIFT_ASR_IMMEDIATE)
5641 {
5642 /* If the shift specifier is ommited, turn the instruction
5643 into pkhbt rd, rm, rn. First, switch the instruction
5644 code, and clear the rn and rm fields. */
5645 inst.instruction &= 0xfff0f010;
5646 /* Now, re-encode the registers. */
5647 inst.instruction |= (rm << 16) | rn;
5648 }
b99bd4ef
NC
5649 return;
5650 }
5651
09d92015
MM
5652 decode_shift (&str, shift);
5653}
5654
5655/* ARM V6 Load Register Exclusive instruction (argument parse).
5656 LDREX{<cond>} <Rd, [<Rn>]
5657 Condition defaults to COND_ALWAYS.
5658 Error if Rd or Rn are R15.
5659 See ARMARMv6 A4.1.27: LDREX. */
5660
5661
5662static void
5663do_ldrex (str)
5664 char * str;
5665{
5666 int rd, rn;
5667
5668 skip_whitespace (str);
5669
5670 /* Parse Rd. */
5671 if (((rd = reg_required_here (&str, 12)) == FAIL)
5672 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5673 {
09d92015 5674 inst.error = BAD_ARGS;
b99bd4ef
NC
5675 return;
5676 }
09d92015 5677 else if (rd == REG_PC)
b99bd4ef 5678 {
09d92015 5679 inst.error = BAD_PC;
b99bd4ef
NC
5680 return;
5681 }
09d92015 5682 skip_whitespace (str);
b99bd4ef 5683
09d92015
MM
5684 /* Skip past '['. */
5685 if ((strlen (str) >= 1)
5686 &&strncmp (str, "[", 1) == 0)
5687 str+=1;
5688 skip_whitespace (str);
5689
5690 /* Parse Rn. */
5691 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5692 {
09d92015
MM
5693 inst.error = BAD_ARGS;
5694 return;
b99bd4ef 5695 }
09d92015
MM
5696 else if (rn == REG_PC)
5697 {
5698 inst.error = BAD_PC;
5699 return;
5700 }
5701 skip_whitespace (str);
b99bd4ef 5702
09d92015
MM
5703 /* Skip past ']'. */
5704 if ((strlen (str) >= 1)
5705 && strncmp (str, "]", 1) == 0)
5706 str+=1;
5707
b99bd4ef
NC
5708 end_of_line (str);
5709}
5710
09d92015
MM
5711/* ARM V6 change processor state instruction (argument parse)
5712 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5713
5714static void
09d92015
MM
5715do_cps (str)
5716 char * str;
b99bd4ef 5717{
09d92015
MM
5718 do_cps_mode (&str);
5719 end_of_line (str);
5720}
b99bd4ef 5721
09d92015
MM
5722static void
5723do_cpsi (str)
5724 char * str;
5725{
5726 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5727
09d92015 5728 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5729 {
09d92015
MM
5730 skip_whitespace (str);
5731 do_cps_mode (&str);
b99bd4ef 5732 }
09d92015
MM
5733 end_of_line (str);
5734}
b99bd4ef 5735
09d92015
MM
5736static void
5737do_cps_mode (str)
5738 char **str;
5739{
5740 expressionS expr;
5741
5742 skip_whitespace (*str);
5743
5744 if (! is_immediate_prefix (**str))
b99bd4ef 5745 {
09d92015 5746 inst.error = _("immediate expression expected");
b99bd4ef
NC
5747 return;
5748 }
5749
09d92015
MM
5750 (*str)++; /* Strip off the immediate signifier. */
5751 if (my_get_expression (&expr, str))
b99bd4ef 5752 {
09d92015 5753 inst.error = _("bad expression");
b99bd4ef
NC
5754 return;
5755 }
5756
09d92015 5757 if (expr.X_op != O_constant)
b99bd4ef 5758 {
09d92015 5759 inst.error = _("constant expression expected");
b99bd4ef
NC
5760 return;
5761 }
09d92015
MM
5762
5763 /* The mode is a 5 bit field. Valid values are 0-31. */
5764 if (((unsigned) expr.X_add_number) > 31
5765 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5766 {
09d92015
MM
5767 inst.error = _("invalid constant");
5768 return;
b99bd4ef 5769 }
09d92015
MM
5770
5771 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5772}
5773
ea6ef066 5774static void
09d92015
MM
5775do_cps_flags (str, thumb_p)
5776 char **str;
5777 int thumb_p;
ea6ef066 5778{
09d92015
MM
5779 struct cps_flag {
5780 char character;
5781 unsigned long arm_value;
5782 unsigned long thumb_value;
5783 };
5784 static struct cps_flag flag_table[] = {
5785 {'a', 0x100, 0x4 },
5786 {'i', 0x080, 0x2 },
5787 {'f', 0x040, 0x1 }
5788 };
ea6ef066 5789
09d92015 5790 int saw_a_flag = 0;
ea6ef066 5791
09d92015
MM
5792 skip_whitespace (*str);
5793
5794 /* Get the a, f and i flags. */
5795 while (**str && **str != ',')
ea6ef066 5796 {
09d92015
MM
5797 struct cps_flag *p;
5798 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5799 for (p = flag_table; p < q; ++p)
5800 if (strncasecmp (*str, &p->character, 1) == 0)
5801 {
5802 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5803 saw_a_flag = 1;
5804 break;
5805 }
5806 if (p == q)
5807 {
5808 inst.error = _("unrecognized flag");
5809 return;
5810 }
5811 (*str)++;
ea6ef066 5812 }
09d92015
MM
5813 if (!saw_a_flag)
5814 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5815}
5816
b99bd4ef
NC
5817/* THUMB V5 breakpoint instruction (argument parse)
5818 BKPT <immed_8>. */
5819
5820static void
5821do_t_bkpt (str)
5822 char * str;
5823{
5824 expressionS expr;
5825 unsigned long number;
5826
5827 skip_whitespace (str);
5828
5829 /* Allow optional leading '#'. */
5830 if (is_immediate_prefix (*str))
5831 str ++;
5832
5833 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5834 if (my_get_expression (& expr, & str)
5835 || (expr.X_op != O_constant
5836 /* As a convenience we allow 'bkpt' without an operand. */
5837 && expr.X_op != O_absent))
b99bd4ef 5838 {
143c8e19 5839 inst.error = _("bad expression");
b99bd4ef
NC
5840 return;
5841 }
5842
5843 number = expr.X_add_number;
5844
5845 /* Check it fits an 8 bit unsigned. */
5846 if (number != (number & 0xff))
5847 {
5848 inst.error = _("immediate value out of range");
5849 return;
5850 }
5851
5852 inst.instruction |= number;
5853
5854 end_of_line (str);
5855}
5856
5857/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5858 Expects inst.instruction is set for BLX(1).
5859 Note: this is cloned from do_branch, and the reloc changed to be a
5860 new one that can cope with setting one extra bit (the H bit). */
5861
5862static void
f2b7cb0a 5863do_branch25 (str)
b99bd4ef 5864 char * str;
b99bd4ef
NC
5865{
5866 if (my_get_expression (& inst.reloc.exp, & str))
5867 return;
5868
5869#ifdef OBJ_ELF
5870 {
5871 char * save_in;
5872
5873 /* ScottB: February 5, 1998 */
5874 /* Check to see of PLT32 reloc required for the instruction. */
5875
5876 /* arm_parse_reloc() works on input_line_pointer.
5877 We actually want to parse the operands to the branch instruction
5878 passed in 'str'. Save the input pointer and restore it later. */
5879 save_in = input_line_pointer;
5880 input_line_pointer = str;
5881
5882 if (inst.reloc.exp.X_op == O_symbol
5883 && *str == '('
5884 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5885 {
5886 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5887 inst.reloc.pc_rel = 0;
5888 /* Modify str to point to after parsed operands, otherwise
5889 end_of_line() will complain about the (PLT) left in str. */
5890 str = input_line_pointer;
5891 }
5892 else
5893 {
5894 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5895 inst.reloc.pc_rel = 1;
5896 }
5897
5898 input_line_pointer = save_in;
5899 }
5900#else
5901 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5902 inst.reloc.pc_rel = 1;
5903#endif /* OBJ_ELF */
5904
5905 end_of_line (str);
5906}
5907
5908/* ARM V5 branch-link-exchange instruction (argument parse)
5909 BLX <target_addr> ie BLX(1)
5910 BLX{<condition>} <Rm> ie BLX(2)
5911 Unfortunately, there are two different opcodes for this mnemonic.
5912 So, the insns[].value is not used, and the code here zaps values
5913 into inst.instruction.
5914 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5915
5916static void
f2b7cb0a 5917do_blx (str)
b99bd4ef 5918 char * str;
b99bd4ef
NC
5919{
5920 char * mystr = str;
5921 int rm;
5922
b99bd4ef
NC
5923 skip_whitespace (mystr);
5924 rm = reg_required_here (& mystr, 0);
5925
5926 /* The above may set inst.error. Ignore his opinion. */
5927 inst.error = 0;
5928
5929 if (rm != FAIL)
5930 {
5931 /* Arg is a register.
5932 Use the condition code our caller put in inst.instruction.
5933 Pass ourselves off as a BX with a funny opcode. */
5934 inst.instruction |= 0x012fff30;
f2b7cb0a 5935 do_bx (str);
b99bd4ef
NC
5936 }
5937 else
5938 {
5939 /* This must be is BLX <target address>, no condition allowed. */
5940 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5941 {
5942 inst.error = BAD_COND;
b99bd4ef 5943 return;
cc8a6dd0 5944 }
b99bd4ef
NC
5945
5946 inst.instruction = 0xfafffffe;
5947
5948 /* Process like a B/BL, but with a different reloc.
5949 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5950 do_branch25 (str);
b99bd4ef
NC
5951 }
5952}
5953
5954/* ARM V5 Thumb BLX (argument parse)
5955 BLX <target_addr> which is BLX(1)
5956 BLX <Rm> which is BLX(2)
5957 Unfortunately, there are two different opcodes for this mnemonic.
5958 So, the tinsns[].value is not used, and the code here zaps values
5959 into inst.instruction. */
5960
5961static void
5962do_t_blx (str)
5963 char * str;
5964{
5965 char * mystr = str;
5966 int rm;
5967
5968 skip_whitespace (mystr);
5969 inst.instruction = 0x4780;
5970
5971 /* Note that this call is to the ARM register recognizer. BLX(2)
5972 uses the ARM register space, not the Thumb one, so a call to
5973 thumb_reg() would be wrong. */
5974 rm = reg_required_here (& mystr, 3);
5975 inst.error = 0;
5976
5977 if (rm != FAIL)
5978 {
5979 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5980 inst.size = 2;
5981 }
5982 else
5983 {
5984 /* No ARM register. This must be BLX(1). Change the .instruction. */
5985 inst.instruction = 0xf7ffeffe;
5986 inst.size = 4;
5987
5988 if (my_get_expression (& inst.reloc.exp, & mystr))
5989 return;
5990
5991 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5992 inst.reloc.pc_rel = 1;
5993 }
5994
5995 end_of_line (mystr);
5996}
5997
5998/* ARM V5 breakpoint instruction (argument parse)
5999 BKPT <16 bit unsigned immediate>
6000 Instruction is not conditional.
6001 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 6002 and it is an error if the caller tried to override that. */
b99bd4ef
NC
6003
6004static void
f2b7cb0a 6005do_bkpt (str)
b99bd4ef 6006 char * str;
b99bd4ef
NC
6007{
6008 expressionS expr;
6009 unsigned long number;
6010
6011 skip_whitespace (str);
6012
6013 /* Allow optional leading '#'. */
6014 if (is_immediate_prefix (* str))
6015 str++;
6016
6017 memset (& expr, '\0', sizeof (expr));
6018
143c8e19
NC
6019 if (my_get_expression (& expr, & str)
6020 || (expr.X_op != O_constant
6021 /* As a convenience we allow 'bkpt' without an operand. */
6022 && expr.X_op != O_absent))
b99bd4ef 6023 {
143c8e19 6024 inst.error = _("bad expression");
b99bd4ef
NC
6025 return;
6026 }
6027
6028 number = expr.X_add_number;
6029
6030 /* Check it fits a 16 bit unsigned. */
6031 if (number != (number & 0xffff))
6032 {
6033 inst.error = _("immediate value out of range");
6034 return;
6035 }
6036
6037 /* Top 12 of 16 bits to bits 19:8. */
6038 inst.instruction |= (number & 0xfff0) << 4;
6039
6040 /* Bottom 4 of 16 bits to bits 3:0. */
6041 inst.instruction |= number & 0xf;
6042
6043 end_of_line (str);
b99bd4ef
NC
6044}
6045
09d92015
MM
6046/* THUMB CPS instruction (argument parse). */
6047
6048static void
6049do_t_cps (str)
6050 char *str;
6051{
6052 do_cps_flags (&str, /*thumb_p=*/1);
6053 end_of_line (str);
6054}
6055
6056/* THUMB CPY instruction (argument parse). */
6057
6058static void
6059do_t_cpy (str)
6060 char *str;
6061{
6062 thumb_mov_compare (str, THUMB_CPY);
6063}
6064
6065/* THUMB SETEND instruction (argument parse). */
6066
6067static void
6068do_t_setend (str)
6069 char *str;
6070{
6071 if (do_endian_specifier (str))
6072 inst.instruction |= 0x8;
6073}
6074
e16bb312
NC
6075static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6076
6077/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6078
6079static unsigned long
6080check_iwmmxt_insn (str, insn_type, immediate_size)
6081 char * str;
6082 enum iwmmxt_insn_type insn_type;
6083 int immediate_size;
6084{
6085 int reg = 0;
6086 const char * inst_error;
6087 expressionS expr;
6088 unsigned long number;
6089
6090 inst_error = inst.error;
6091 if (!inst.error)
6092 inst.error = BAD_ARGS;
6093 skip_whitespace (str);
6094
6095 switch (insn_type)
6096 {
6097 case check_rd:
6098 if ((reg = reg_required_here (&str, 12)) == FAIL)
6099 return FAIL;
6100 break;
6101
6102 case check_wr:
6103 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6104 return FAIL;
6105 break;
6106
6107 case check_wrwr:
6108 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6109 || skip_past_comma (&str) == FAIL
6110 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6111 return FAIL;
6112 break;
6113
6114 case check_wrwrwr:
6115 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6116 || skip_past_comma (&str) == FAIL
6117 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6118 || skip_past_comma (&str) == FAIL
6119 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6120 return FAIL;
6121 break;
6122
6123 case check_wrwrwcg:
6124 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6125 || skip_past_comma (&str) == FAIL
6126 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6127 || skip_past_comma (&str) == FAIL
6128 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6129 return FAIL;
6130 break;
6131
6132 case check_tbcst:
6133 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6134 || skip_past_comma (&str) == FAIL
6135 || reg_required_here (&str, 12) == FAIL))
6136 return FAIL;
6137 break;
6138
6139 case check_tmovmsk:
6140 if ((reg_required_here (&str, 12) == FAIL
6141 || skip_past_comma (&str) == FAIL
6142 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6143 return FAIL;
6144 break;
6145
6146 case check_tmia:
6147 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6148 || skip_past_comma (&str) == FAIL
6149 || reg_required_here (&str, 0) == FAIL
6150 || skip_past_comma (&str) == FAIL
6151 || reg_required_here (&str, 12) == FAIL))
6152 return FAIL;
6153 break;
6154
6155 case check_tmcrr:
6156 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6157 || skip_past_comma (&str) == FAIL
6158 || reg_required_here (&str, 12) == FAIL
6159 || skip_past_comma (&str) == FAIL
6160 || reg_required_here (&str, 16) == FAIL))
6161 return FAIL;
6162 break;
6163
6164 case check_tmrrc:
6165 if ((reg_required_here (&str, 12) == FAIL
6166 || skip_past_comma (&str) == FAIL
6167 || reg_required_here (&str, 16) == FAIL
6168 || skip_past_comma (&str) == FAIL
6169 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6170 return FAIL;
6171 break;
6172
6173 case check_tmcr:
6174 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6175 || skip_past_comma (&str) == FAIL
6176 || reg_required_here (&str, 12) == FAIL))
6177 return FAIL;
6178 break;
6179
6180 case check_tmrc:
6181 if ((reg_required_here (&str, 12) == FAIL
6182 || skip_past_comma (&str) == FAIL
6183 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6184 return FAIL;
6185 break;
6186
6187 case check_tinsr:
6188 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6189 || skip_past_comma (&str) == FAIL
6190 || reg_required_here (&str, 12) == FAIL
6191 || skip_past_comma (&str) == FAIL))
6192 return FAIL;
6193 break;
6194
6195 case check_textrc:
6196 if ((reg_required_here (&str, 12) == FAIL
6197 || skip_past_comma (&str) == FAIL))
6198 return FAIL;
6199 break;
6200
6201 case check_waligni:
6202 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6203 || skip_past_comma (&str) == FAIL
6204 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6205 || skip_past_comma (&str) == FAIL
6206 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6207 || skip_past_comma (&str) == FAIL))
6208 return FAIL;
6209 break;
6210
6211 case check_textrm:
6212 if ((reg_required_here (&str, 12) == FAIL
6213 || skip_past_comma (&str) == FAIL
6214 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6215 || skip_past_comma (&str) == FAIL))
6216 return FAIL;
6217 break;
6218
6219 case check_wshufh:
6220 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6221 || skip_past_comma (&str) == FAIL
6222 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6223 || skip_past_comma (&str) == FAIL))
6224 return FAIL;
6225 break;
6226 }
6227
6228 if (immediate_size == 0)
6229 {
6230 end_of_line (str);
6231 inst.error = inst_error;
6232 return reg;
6233 }
6234 else
6235 {
6236 skip_whitespace (str);
6237
6238 /* Allow optional leading '#'. */
6239 if (is_immediate_prefix (* str))
6240 str++;
6241
6242 memset (& expr, '\0', sizeof (expr));
6243
6244 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6245 {
6246 inst.error = _("bad or missing expression");
6247 return FAIL;
6248 }
6249
6250 number = expr.X_add_number;
6251
6252 if (number != (number & immediate_size))
6253 {
6254 inst.error = _("immediate value out of range");
6255 return FAIL;
6256 }
6257 end_of_line (str);
6258 inst.error = inst_error;
6259 return number;
6260 }
6261}
6262
6263static void
6264do_iwmmxt_byte_addr (str)
6265 char * str;
6266{
6267 int op = (inst.instruction & 0x300) >> 8;
6268 int reg;
6269
6270 inst.instruction &= ~0x300;
6271 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6272
6273 skip_whitespace (str);
6274
6275 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6276 || skip_past_comma (& str) == FAIL
6277 || cp_byte_address_required_here (&str) == FAIL)
6278 {
6279 if (! inst.error)
6280 inst.error = BAD_ARGS;
6281 }
6282 else
6283 end_of_line (str);
6284
6285 if (wc_register (reg))
6286 {
ece01a63 6287 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6288 inst.instruction |= 0xf0000100;
6289 inst.instruction &= ~0x00400000;
6290 }
6291}
6292
6293static void
6294do_iwmmxt_tandc (str)
6295 char * str;
6296{
6297 int reg;
6298
6299 reg = check_iwmmxt_insn (str, check_rd, 0);
6300
6301 if (reg != REG_PC && !inst.error)
6302 inst.error = _("only r15 allowed here");
e16bb312
NC
6303}
6304
6305static void
6306do_iwmmxt_tbcst (str)
6307 char * str;
6308{
6309 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6310}
6311
6312static void
6313do_iwmmxt_textrc (str)
6314 char * str;
6315{
6316 unsigned long number;
6317
6318 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6319 return;
6320
6321 inst.instruction |= number & 0x7;
e16bb312
NC
6322}
6323
6324static void
6325do_iwmmxt_textrm (str)
6326 char * str;
6327{
6328 unsigned long number;
6329
6330 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6331 return;
6332
6333 inst.instruction |= number & 0x7;
6334}
6335
6336static void
6337do_iwmmxt_tinsr (str)
6338 char * str;
6339{
6340 unsigned long number;
6341
6342 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6343 return;
6344
6345 inst.instruction |= number & 0x7;
e16bb312
NC
6346}
6347
6348static void
6349do_iwmmxt_tmcr (str)
6350 char * str;
6351{
6352 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6353}
6354
6355static void
6356do_iwmmxt_tmcrr (str)
6357 char * str;
6358{
6359 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6360}
6361
6362static void
6363do_iwmmxt_tmia (str)
6364 char * str;
6365{
6366 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6367}
6368
6369static void
6370do_iwmmxt_tmovmsk (str)
6371 char * str;
6372{
6373 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6374}
6375
6376static void
6377do_iwmmxt_tmrc (str)
6378 char * str;
6379{
6380 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6381}
6382
6383static void
6384do_iwmmxt_tmrrc (str)
6385 char * str;
6386{
6387 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6388}
6389
6390static void
6391do_iwmmxt_torc (str)
6392 char * str;
6393{
6394 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6395}
6396
6397static void
6398do_iwmmxt_waligni (str)
6399 char * str;
6400{
6401 unsigned long number;
6402
6403 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6404 return;
6405
6406 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6407}
6408
6409static void
6410do_iwmmxt_wmov (str)
6411 char * str;
6412{
6413 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6414 return;
6415
6416 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6417}
6418
6419static void
6420do_iwmmxt_word_addr (str)
6421 char * str;
6422{
6423 int op = (inst.instruction & 0x300) >> 8;
6424 int reg;
6425
6426 inst.instruction &= ~0x300;
6427 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6428
6429 skip_whitespace (str);
6430
6431 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6432 || skip_past_comma (& str) == FAIL
6433 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6434 {
6435 if (! inst.error)
6436 inst.error = BAD_ARGS;
6437 }
6438 else
6439 end_of_line (str);
6440
6441 if (wc_register (reg))
6442 {
ece01a63
ILT
6443 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6444 as_bad (_("conditional execution not supported with control register"));
6445 if (op != 2)
6446 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6447 inst.instruction |= 0xf0000100;
6448 inst.instruction &= ~0x00400000;
6449 }
6450}
6451
6452static void
6453do_iwmmxt_wrwr (str)
6454 char * str;
6455{
6456 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6457}
6458
6459static void
6460do_iwmmxt_wrwrwcg (str)
6461 char * str;
6462{
6463 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6464}
6465
6466static void
6467do_iwmmxt_wrwrwr (str)
6468 char * str;
6469{
6470 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6471}
6472
6473static void
6474do_iwmmxt_wshufh (str)
6475 char * str;
6476{
6477 unsigned long number;
6478
6479 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6480 return;
6481
6482 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6483}
6484
6485static void
6486do_iwmmxt_wzero (str)
6487 char * str;
6488{
6489 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6490 return;
6491
6492 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6493}
6494
b99bd4ef
NC
6495/* Xscale multiply-accumulate (argument parse)
6496 MIAcc acc0,Rm,Rs
6497 MIAPHcc acc0,Rm,Rs
6498 MIAxycc acc0,Rm,Rs. */
6499
6500static void
63e63b07 6501do_xsc_mia (str)
b99bd4ef 6502 char * str;
b99bd4ef
NC
6503{
6504 int rs;
6505 int rm;
6506
f2b7cb0a 6507 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6508 inst.error = ERR_NO_ACCUM;
6509
6510 else if (skip_past_comma (& str) == FAIL
6511 || (rm = reg_required_here (& str, 0)) == FAIL)
6512 inst.error = BAD_ARGS;
6513
6514 else if (skip_past_comma (& str) == FAIL
6515 || (rs = reg_required_here (& str, 12)) == FAIL)
6516 inst.error = BAD_ARGS;
6517
6518 /* inst.instruction has now been zapped with both rm and rs. */
6519 else if (rm == REG_PC || rs == REG_PC)
6520 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6521
6522 else
6523 end_of_line (str);
6524}
6525
6526/* Xscale move-accumulator-register (argument parse)
6527
6528 MARcc acc0,RdLo,RdHi. */
6529
6530static void
63e63b07 6531do_xsc_mar (str)
b99bd4ef 6532 char * str;
b99bd4ef
NC
6533{
6534 int rdlo, rdhi;
6535
f2b7cb0a 6536 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6537 inst.error = ERR_NO_ACCUM;
6538
6539 else if (skip_past_comma (& str) == FAIL
6540 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6541 inst.error = BAD_ARGS;
6542
6543 else if (skip_past_comma (& str) == FAIL
6544 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6545 inst.error = BAD_ARGS;
6546
6547 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6548 else if (rdlo == REG_PC || rdhi == REG_PC)
6549 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6550
6551 else
6552 end_of_line (str);
6553}
6554
6555/* Xscale move-register-accumulator (argument parse)
6556
6557 MRAcc RdLo,RdHi,acc0. */
6558
6559static void
63e63b07 6560do_xsc_mra (str)
b99bd4ef 6561 char * str;
b99bd4ef
NC
6562{
6563 int rdlo;
6564 int rdhi;
6565
b99bd4ef
NC
6566 skip_whitespace (str);
6567
6568 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6569 inst.error = BAD_ARGS;
6570
6571 else if (skip_past_comma (& str) == FAIL
6572 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6573 inst.error = BAD_ARGS;
6574
6575 else if (skip_past_comma (& str) == FAIL
6576 || accum0_required_here (& str) == FAIL)
6577 inst.error = ERR_NO_ACCUM;
6578
6579 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6580 else if (rdlo == rdhi)
6581 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6582
6583 else if (rdlo == REG_PC || rdhi == REG_PC)
6584 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6585 else
6586 end_of_line (str);
6587}
6588
c9b604bd 6589/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6590
6591 PLD <addr_mode>
6592
6593 Syntactically, like LDR with B=1, W=0, L=1. */
6594
6595static void
f2b7cb0a 6596do_pld (str)
b99bd4ef 6597 char * str;
b99bd4ef
NC
6598{
6599 int rd;
6600
b99bd4ef
NC
6601 skip_whitespace (str);
6602
6603 if (* str != '[')
6604 {
6605 inst.error = _("'[' expected after PLD mnemonic");
6606 return;
6607 }
6608
90e4755a 6609 ++str;
b99bd4ef
NC
6610 skip_whitespace (str);
6611
6612 if ((rd = reg_required_here (& str, 16)) == FAIL)
6613 return;
6614
6615 skip_whitespace (str);
6616
90e4755a 6617 if (*str == ']')
b99bd4ef
NC
6618 {
6619 /* [Rn], ... ? */
90e4755a 6620 ++str;
b99bd4ef
NC
6621 skip_whitespace (str);
6622
90e4755a
RE
6623 /* Post-indexed addressing is not allowed with PLD. */
6624 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6625 {
90e4755a
RE
6626 inst.error
6627 = _("post-indexed expression used in preload instruction");
6628 return;
b99bd4ef 6629 }
90e4755a 6630 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6631 {
6632 inst.error = _("writeback used in preload instruction");
90e4755a 6633 ++str;
b99bd4ef
NC
6634 }
6635 else /* [Rn] */
6636 inst.instruction |= INDEX_UP | PRE_INDEX;
6637 }
6638 else /* [Rn, ...] */
6639 {
6640 if (skip_past_comma (& str) == FAIL)
6641 {
6642 inst.error = _("pre-indexed expression expected");
6643 return;
6644 }
6645
90e4755a 6646 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6647 return;
6648
6649 skip_whitespace (str);
6650
6651 if (* str != ']')
6652 {
6653 inst.error = _("missing ]");
6654 return;
6655 }
6656
6657 ++ str;
6658 skip_whitespace (str);
6659
6660 if (* str == '!') /* [Rn]! */
6661 {
6662 inst.error = _("writeback used in preload instruction");
6663 ++ str;
6664 }
6665
6666 inst.instruction |= PRE_INDEX;
6667 }
6668
6669 end_of_line (str);
6670}
6671
c9b604bd 6672/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6673 Mode is like LDRH.
6674
6675 LDRccD R, mode
6676 STRccD R, mode. */
6677
6678static void
f2b7cb0a 6679do_ldrd (str)
b99bd4ef 6680 char * str;
b99bd4ef
NC
6681{
6682 int rd;
6683 int rn;
6684
b99bd4ef
NC
6685 skip_whitespace (str);
6686
6687 if ((rd = reg_required_here (& str, 12)) == FAIL)
6688 {
6689 inst.error = BAD_ARGS;
6690 return;
6691 }
6692
6693 if (skip_past_comma (& str) == FAIL
6694 || (rn = ld_mode_required_here (& str)) == FAIL)
6695 {
6696 if (!inst.error)
cc8a6dd0 6697 inst.error = BAD_ARGS;
b99bd4ef
NC
6698 return;
6699 }
6700
6701 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6702 if (rd & 1) /* Unpredictable result if Rd is odd. */
6703 {
f03698e6 6704 inst.error = _("destination register must be even");
b99bd4ef
NC
6705 return;
6706 }
6707
90e4755a 6708 if (rd == REG_LR)
b99bd4ef 6709 {
f2b7cb0a 6710 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6711 return;
6712 }
6713
6714 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6715 && ((inst.instruction & WRITE_BACK)
6716 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6717 as_warn (_("pre/post-indexing used when modified address register is destination"));
6718
90e4755a
RE
6719 /* For an index-register load, the index register must not overlap the
6720 destination (even if not write-back). */
6721 if ((inst.instruction & V4_STR_BIT) == 0
6722 && (inst.instruction & HWOFFSET_IMM) == 0)
6723 {
6724 int rm = inst.instruction & 0x0000000f;
6725
6726 if (rm == rd || (rm == rd + 1))
6727 as_warn (_("ldrd destination registers must not overlap index register"));
6728 }
6729
b99bd4ef
NC
6730 end_of_line (str);
6731}
6732
6733/* Returns the index into fp_values of a floating point number,
6734 or -1 if not in the table. */
6735
6736static int
6737my_get_float_expression (str)
6738 char ** str;
6739{
6740 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6741 char * save_in;
6742 expressionS exp;
6743 int i;
6744 int j;
6745
6746 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6747
6748 /* Look for a raw floating point number. */
6749 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6750 && is_end_of_line[(unsigned char) *save_in])
6751 {
6752 for (i = 0; i < NUM_FLOAT_VALS; i++)
6753 {
6754 for (j = 0; j < MAX_LITTLENUMS; j++)
6755 {
6756 if (words[j] != fp_values[i][j])
6757 break;
6758 }
6759
6760 if (j == MAX_LITTLENUMS)
6761 {
6762 *str = save_in;
6763 return i;
6764 }
6765 }
6766 }
6767
6768 /* Try and parse a more complex expression, this will probably fail
6769 unless the code uses a floating point prefix (eg "0f"). */
6770 save_in = input_line_pointer;
6771 input_line_pointer = *str;
6772 if (expression (&exp) == absolute_section
6773 && exp.X_op == O_big
6774 && exp.X_add_number < 0)
6775 {
6776 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6777 Ditto for 15. */
6778 if (gen_to_words (words, 5, (long) 15) == 0)
6779 {
6780 for (i = 0; i < NUM_FLOAT_VALS; i++)
6781 {
6782 for (j = 0; j < MAX_LITTLENUMS; j++)
6783 {
6784 if (words[j] != fp_values[i][j])
6785 break;
6786 }
6787
6788 if (j == MAX_LITTLENUMS)
6789 {
6790 *str = input_line_pointer;
6791 input_line_pointer = save_in;
6792 return i;
6793 }
6794 }
6795 }
6796 }
6797
6798 *str = input_line_pointer;
6799 input_line_pointer = save_in;
6800 return -1;
6801}
6802
b34976b6 6803/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6804
6805static int
6806walk_no_bignums (sp)
6807 symbolS * sp;
6808{
6809 if (symbol_get_value_expression (sp)->X_op == O_big)
6810 return 1;
6811
6812 if (symbol_get_value_expression (sp)->X_add_symbol)
6813 {
6814 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6815 || (symbol_get_value_expression (sp)->X_op_symbol
6816 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6817 }
6818
6819 return 0;
6820}
6821
f03698e6
RE
6822static int in_my_get_expression = 0;
6823
b99bd4ef
NC
6824static int
6825my_get_expression (ep, str)
6826 expressionS * ep;
6827 char ** str;
6828{
6829 char * save_in;
6830 segT seg;
6831
6832 save_in = input_line_pointer;
6833 input_line_pointer = *str;
f03698e6 6834 in_my_get_expression = 1;
b99bd4ef 6835 seg = expression (ep);
f03698e6
RE
6836 in_my_get_expression = 0;
6837
6838 if (ep->X_op == O_illegal)
6839 {
6840 /* We found a bad expression in md_operand(). */
6841 *str = input_line_pointer;
6842 input_line_pointer = save_in;
6843 return 1;
6844 }
b99bd4ef
NC
6845
6846#ifdef OBJ_AOUT
6847 if (seg != absolute_section
6848 && seg != text_section
6849 && seg != data_section
6850 && seg != bss_section
6851 && seg != undefined_section)
6852 {
6853 inst.error = _("bad_segment");
6854 *str = input_line_pointer;
6855 input_line_pointer = save_in;
6856 return 1;
6857 }
6858#endif
6859
6860 /* Get rid of any bignums now, so that we don't generate an error for which
6861 we can't establish a line number later on. Big numbers are never valid
6862 in instructions, which is where this routine is always called. */
6863 if (ep->X_op == O_big
6864 || (ep->X_add_symbol
6865 && (walk_no_bignums (ep->X_add_symbol)
6866 || (ep->X_op_symbol
6867 && walk_no_bignums (ep->X_op_symbol)))))
6868 {
f03698e6 6869 inst.error = _("invalid constant");
b99bd4ef
NC
6870 *str = input_line_pointer;
6871 input_line_pointer = save_in;
6872 return 1;
6873 }
6874
6875 *str = input_line_pointer;
6876 input_line_pointer = save_in;
6877 return 0;
6878}
6879
cc8a6dd0 6880/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6881 instruction in the error message. */
6882void
ce058b6c 6883md_operand (expr)
f03698e6
RE
6884 expressionS *expr;
6885{
6886 if (in_my_get_expression)
6887 {
6888 expr->X_op = O_illegal;
6889 if (inst.error == NULL)
6890 inst.error = _("bad expression");
6891 }
6892}
6893
09d92015 6894/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6895
6896static int
09d92015 6897decode_shift (str, kind)
b99bd4ef 6898 char ** str;
09d92015 6899 int kind;
b99bd4ef
NC
6900{
6901 const struct asm_shift_name * shift;
6902 char * p;
6903 char c;
6904
6905 skip_whitespace (* str);
6906
3882b010 6907 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6908 ;
6909
6910 if (p == * str)
6911 {
f03698e6 6912 inst.error = _("shift expression expected");
b99bd4ef
NC
6913 return FAIL;
6914 }
6915
6916 c = * p;
6917 * p = '\0';
6918 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6919 * p = c;
6920
6921 if (shift == NULL)
6922 {
f03698e6 6923 inst.error = _("shift expression expected");
b99bd4ef
NC
6924 return FAIL;
6925 }
6926
6927 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6928
09d92015
MM
6929 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6930 && shift->properties->index != SHIFT_LSL
6931 && shift->properties->index != SHIFT_ASR)
6932 {
6933 inst.error = _("'LSL' or 'ASR' required");
6934 return FAIL;
6935 }
6936 else if (kind == SHIFT_LSL_IMMEDIATE
6937 && shift->properties->index != SHIFT_LSL)
6938 {
6939 inst.error = _("'LSL' required");
6940 return FAIL;
6941 }
6942 else if (kind == SHIFT_ASR_IMMEDIATE
6943 && shift->properties->index != SHIFT_ASR)
6944 {
6945 inst.error = _("'ASR' required");
6946 return FAIL;
6947 }
6948
b99bd4ef
NC
6949 if (shift->properties->index == SHIFT_RRX)
6950 {
6951 * str = p;
6952 inst.instruction |= shift->properties->bit_field;
6953 return SUCCESS;
6954 }
6955
6956 skip_whitespace (p);
6957
09d92015 6958 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6959 {
6960 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6961 * str = p;
6962 return SUCCESS;
6963 }
6964 else if (! is_immediate_prefix (* p))
6965 {
09d92015 6966 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6967 ? _("shift requires register or #expression")
6968 : _("shift requires #expression"));
6969 * str = p;
6970 return FAIL;
6971 }
6972
6973 inst.error = NULL;
6974 p ++;
6975
6976 if (my_get_expression (& inst.reloc.exp, & p))
6977 return FAIL;
6978
6979 /* Validate some simple #expressions. */
6980 if (inst.reloc.exp.X_op == O_constant)
6981 {
6982 unsigned num = inst.reloc.exp.X_add_number;
6983
6984 /* Reject operations greater than 32. */
6985 if (num > 32
6986 /* Reject a shift of 0 unless the mode allows it. */
6987 || (num == 0 && shift->properties->allows_0 == 0)
6988 /* Reject a shift of 32 unless the mode allows it. */
6989 || (num == 32 && shift->properties->allows_32 == 0)
6990 )
6991 {
6992 /* As a special case we allow a shift of zero for
6993 modes that do not support it to be recoded as an
6994 logical shift left of zero (ie nothing). We warn
6995 about this though. */
6996 if (num == 0)
6997 {
f03698e6 6998 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
6999 shift = & shift_names[0];
7000 assert (shift->properties->index == SHIFT_LSL);
7001 }
7002 else
7003 {
f03698e6 7004 inst.error = _("invalid immediate shift");
b99bd4ef
NC
7005 return FAIL;
7006 }
7007 }
7008
7009 /* Shifts of 32 are encoded as 0, for those shifts that
7010 support it. */
7011 if (num == 32)
7012 num = 0;
7013
7014 inst.instruction |= (num << 7) | shift->properties->bit_field;
7015 }
7016 else
7017 {
7018 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7019 inst.reloc.pc_rel = 0;
7020 inst.instruction |= shift->properties->bit_field;
7021 }
7022
7023 * str = p;
7024 return SUCCESS;
7025}
7026
7027/* Do those data_ops which can take a negative immediate constant
2d2255b5 7028 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
7029 MOV <-> MVN
7030 AND <-> BIC
7031 ADC <-> SBC
7032 by inverting the second operand, and
7033 ADD <-> SUB
7034 CMP <-> CMN
7035 by negating the second operand. */
7036
7037static int
7038negate_data_op (instruction, value)
7039 unsigned long * instruction;
7040 unsigned long value;
7041{
7042 int op, new_inst;
7043 unsigned long negated, inverted;
7044
7045 negated = validate_immediate (-value);
7046 inverted = validate_immediate (~value);
7047
7048 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7049 switch (op)
7050 {
7051 /* First negates. */
7052 case OPCODE_SUB: /* ADD <-> SUB */
7053 new_inst = OPCODE_ADD;
7054 value = negated;
7055 break;
7056
7057 case OPCODE_ADD:
7058 new_inst = OPCODE_SUB;
7059 value = negated;
7060 break;
7061
7062 case OPCODE_CMP: /* CMP <-> CMN */
7063 new_inst = OPCODE_CMN;
7064 value = negated;
7065 break;
7066
7067 case OPCODE_CMN:
7068 new_inst = OPCODE_CMP;
7069 value = negated;
7070 break;
7071
7072 /* Now Inverted ops. */
7073 case OPCODE_MOV: /* MOV <-> MVN */
7074 new_inst = OPCODE_MVN;
7075 value = inverted;
7076 break;
7077
7078 case OPCODE_MVN:
7079 new_inst = OPCODE_MOV;
7080 value = inverted;
7081 break;
7082
7083 case OPCODE_AND: /* AND <-> BIC */
7084 new_inst = OPCODE_BIC;
7085 value = inverted;
7086 break;
7087
7088 case OPCODE_BIC:
7089 new_inst = OPCODE_AND;
7090 value = inverted;
7091 break;
7092
7093 case OPCODE_ADC: /* ADC <-> SBC */
7094 new_inst = OPCODE_SBC;
7095 value = inverted;
7096 break;
7097
7098 case OPCODE_SBC:
7099 new_inst = OPCODE_ADC;
7100 value = inverted;
7101 break;
7102
7103 /* We cannot do anything. */
7104 default:
7105 return FAIL;
7106 }
7107
7108 if (value == (unsigned) FAIL)
7109 return FAIL;
7110
7111 *instruction &= OPCODE_MASK;
7112 *instruction |= new_inst << DATA_OP_SHIFT;
7113 return value;
7114}
7115
7116static int
7117data_op2 (str)
7118 char ** str;
7119{
7120 int value;
7121 expressionS expr;
7122
7123 skip_whitespace (* str);
7124
7125 if (reg_required_here (str, 0) != FAIL)
7126 {
7127 if (skip_past_comma (str) == SUCCESS)
7128 /* Shift operation on register. */
7129 return decode_shift (str, NO_SHIFT_RESTRICT);
7130
7131 return SUCCESS;
7132 }
7133 else
7134 {
7135 /* Immediate expression. */
7136 if (is_immediate_prefix (**str))
7137 {
7138 (*str)++;
7139 inst.error = NULL;
7140
7141 if (my_get_expression (&inst.reloc.exp, str))
7142 return FAIL;
7143
7144 if (inst.reloc.exp.X_add_symbol)
7145 {
7146 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7147 inst.reloc.pc_rel = 0;
7148 }
7149 else
7150 {
7151 if (skip_past_comma (str) == SUCCESS)
7152 {
7153 /* #x, y -- ie explicit rotation by Y. */
7154 if (my_get_expression (&expr, str))
7155 return FAIL;
7156
7157 if (expr.X_op != O_constant)
7158 {
f03698e6 7159 inst.error = _("constant expression expected");
b99bd4ef
NC
7160 return FAIL;
7161 }
7162
7163 /* Rotate must be a multiple of 2. */
7164 if (((unsigned) expr.X_add_number) > 30
7165 || (expr.X_add_number & 1) != 0
7166 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7167 {
f03698e6 7168 inst.error = _("invalid constant");
b99bd4ef
NC
7169 return FAIL;
7170 }
7171 inst.instruction |= INST_IMMEDIATE;
7172 inst.instruction |= inst.reloc.exp.X_add_number;
7173 inst.instruction |= expr.X_add_number << 7;
7174 return SUCCESS;
7175 }
7176
7177 /* Implicit rotation, select a suitable one. */
7178 value = validate_immediate (inst.reloc.exp.X_add_number);
7179
7180 if (value == FAIL)
7181 {
7182 /* Can't be done. Perhaps the code reads something like
7183 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7184 if ((value = negate_data_op (&inst.instruction,
7185 inst.reloc.exp.X_add_number))
7186 == FAIL)
7187 {
f03698e6 7188 inst.error = _("invalid constant");
b99bd4ef
NC
7189 return FAIL;
7190 }
7191 }
7192
7193 inst.instruction |= value;
7194 }
7195
7196 inst.instruction |= INST_IMMEDIATE;
7197 return SUCCESS;
7198 }
7199
7200 (*str)++;
f03698e6 7201 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7202 return FAIL;
7203 }
7204}
7205
7206static int
7207fp_op2 (str)
7208 char ** str;
7209{
7210 skip_whitespace (* str);
7211
7212 if (fp_reg_required_here (str, 0) != FAIL)
7213 return SUCCESS;
7214 else
7215 {
7216 /* Immediate expression. */
7217 if (*((*str)++) == '#')
7218 {
7219 int i;
7220
7221 inst.error = NULL;
7222
7223 skip_whitespace (* str);
7224
7225 /* First try and match exact strings, this is to guarantee
7226 that some formats will work even for cross assembly. */
7227
7228 for (i = 0; fp_const[i]; i++)
7229 {
7230 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7231 {
7232 char *start = *str;
7233
7234 *str += strlen (fp_const[i]);
7235 if (is_end_of_line[(unsigned char) **str])
7236 {
7237 inst.instruction |= i + 8;
7238 return SUCCESS;
7239 }
7240 *str = start;
7241 }
7242 }
7243
7244 /* Just because we didn't get a match doesn't mean that the
7245 constant isn't valid, just that it is in a format that we
7246 don't automatically recognize. Try parsing it with
7247 the standard expression routines. */
7248 if ((i = my_get_float_expression (str)) >= 0)
7249 {
7250 inst.instruction |= i + 8;
7251 return SUCCESS;
7252 }
7253
f03698e6 7254 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7255 return FAIL;
7256 }
7257 inst.error =
f03698e6 7258 _("floating point register or immediate expression expected");
b99bd4ef
NC
7259 return FAIL;
7260 }
7261}
7262
7263static void
f2b7cb0a 7264do_arit (str)
b99bd4ef 7265 char * str;
b99bd4ef
NC
7266{
7267 skip_whitespace (str);
7268
7269 if (reg_required_here (&str, 12) == FAIL
7270 || skip_past_comma (&str) == FAIL
7271 || reg_required_here (&str, 16) == FAIL
7272 || skip_past_comma (&str) == FAIL
7273 || data_op2 (&str) == FAIL)
7274 {
7275 if (!inst.error)
7276 inst.error = BAD_ARGS;
7277 return;
7278 }
7279
b99bd4ef 7280 end_of_line (str);
b99bd4ef
NC
7281}
7282
7283static void
f2b7cb0a 7284do_adr (str)
b99bd4ef 7285 char * str;
b99bd4ef 7286{
90e4755a
RE
7287 /* This is a pseudo-op of the form "adr rd, label" to be converted
7288 into a relative address of the form "add rd, pc, #label-.-8". */
7289 skip_whitespace (str);
7290
7291 if (reg_required_here (&str, 12) == FAIL
7292 || skip_past_comma (&str) == FAIL
7293 || my_get_expression (&inst.reloc.exp, &str))
7294 {
7295 if (!inst.error)
7296 inst.error = BAD_ARGS;
7297 return;
7298 }
7299
7300 /* Frag hacking will turn this into a sub instruction if the offset turns
7301 out to be negative. */
7302 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 7303#ifndef TE_WINCE
90e4755a 7304 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 7305#endif
90e4755a
RE
7306 inst.reloc.pc_rel = 1;
7307
7308 end_of_line (str);
7309}
7310
7311static void
f2b7cb0a 7312do_adrl (str)
90e4755a 7313 char * str;
90e4755a
RE
7314{
7315 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7316 into a relative address of the form:
7317 add rd, pc, #low(label-.-8)"
7318 add rd, rd, #high(label-.-8)" */
7319
7320 skip_whitespace (str);
7321
7322 if (reg_required_here (&str, 12) == FAIL
7323 || skip_past_comma (&str) == FAIL
7324 || my_get_expression (&inst.reloc.exp, &str))
7325 {
7326 if (!inst.error)
7327 inst.error = BAD_ARGS;
7328
7329 return;
7330 }
7331
7332 end_of_line (str);
7333 /* Frag hacking will turn this into a sub instruction if the offset turns
7334 out to be negative. */
7335 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
250355db 7336#ifndef TE_WINCE
90e4755a 7337 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 7338#endif
90e4755a
RE
7339 inst.reloc.pc_rel = 1;
7340 inst.size = INSN_SIZE * 2;
90e4755a
RE
7341}
7342
7343static void
f2b7cb0a 7344do_cmp (str)
90e4755a 7345 char * str;
90e4755a
RE
7346{
7347 skip_whitespace (str);
7348
7349 if (reg_required_here (&str, 16) == FAIL)
7350 {
7351 if (!inst.error)
7352 inst.error = BAD_ARGS;
7353 return;
7354 }
7355
7356 if (skip_past_comma (&str) == FAIL
7357 || data_op2 (&str) == FAIL)
7358 {
7359 if (!inst.error)
7360 inst.error = BAD_ARGS;
7361 return;
7362 }
7363
90e4755a 7364 end_of_line (str);
90e4755a
RE
7365}
7366
7367static void
f2b7cb0a 7368do_mov (str)
90e4755a 7369 char * str;
90e4755a
RE
7370{
7371 skip_whitespace (str);
7372
7373 if (reg_required_here (&str, 12) == FAIL)
7374 {
7375 if (!inst.error)
7376 inst.error = BAD_ARGS;
7377 return;
7378 }
7379
7380 if (skip_past_comma (&str) == FAIL
7381 || data_op2 (&str) == FAIL)
7382 {
7383 if (!inst.error)
7384 inst.error = BAD_ARGS;
7385 return;
7386 }
7387
90e4755a 7388 end_of_line (str);
90e4755a
RE
7389}
7390
7391static int
7392ldst_extend (str)
7393 char ** str;
7394{
7395 int add = INDEX_UP;
7396
7397 switch (**str)
7398 {
7399 case '#':
7400 case '$':
7401 (*str)++;
7402 if (my_get_expression (& inst.reloc.exp, str))
7403 return FAIL;
7404
7405 if (inst.reloc.exp.X_op == O_constant)
7406 {
7407 int value = inst.reloc.exp.X_add_number;
7408
7409 if (value < -4095 || value > 4095)
7410 {
7411 inst.error = _("address offset too large");
7412 return FAIL;
7413 }
7414
7415 if (value < 0)
7416 {
7417 value = -value;
7418 add = 0;
7419 }
7420
7421 inst.instruction |= add | value;
7422 }
7423 else
7424 {
7425 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7426 inst.reloc.pc_rel = 0;
7427 }
7428 return SUCCESS;
7429
7430 case '-':
7431 add = 0;
7432 /* Fall through. */
7433
7434 case '+':
7435 (*str)++;
7436 /* Fall through. */
7437
7438 default:
7439 if (reg_required_here (str, 0) == FAIL)
7440 return FAIL;
7441
7442 inst.instruction |= add | OFFSET_REG;
7443 if (skip_past_comma (str) == SUCCESS)
09d92015 7444 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7445
7446 return SUCCESS;
7447 }
7448}
7449
7450static void
f2b7cb0a 7451do_ldst (str)
90e4755a 7452 char * str;
90e4755a
RE
7453{
7454 int pre_inc = 0;
7455 int conflict_reg;
7456 int value;
7457
b99bd4ef
NC
7458 skip_whitespace (str);
7459
90e4755a
RE
7460 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7461 {
7462 if (!inst.error)
7463 inst.error = BAD_ARGS;
7464 return;
7465 }
7466
7467 if (skip_past_comma (&str) == FAIL)
7468 {
f03698e6 7469 inst.error = _("address expected");
90e4755a
RE
7470 return;
7471 }
7472
90e4755a
RE
7473 if (*str == '[')
7474 {
7475 int reg;
7476
7477 str++;
7478
7479 skip_whitespace (str);
7480
7481 if ((reg = reg_required_here (&str, 16)) == FAIL)
7482 return;
7483
7484 /* Conflicts can occur on stores as well as loads. */
7485 conflict_reg = (conflict_reg == reg);
7486
7487 skip_whitespace (str);
7488
7489 if (*str == ']')
7490 {
7491 str ++;
7492
7493 if (skip_past_comma (&str) == SUCCESS)
7494 {
7495 /* [Rn],... (post inc) */
7496 if (ldst_extend (&str) == FAIL)
7497 return;
7498 if (conflict_reg)
7499 as_warn (_("%s register same as write-back base"),
7500 ((inst.instruction & LOAD_BIT)
7501 ? _("destination") : _("source")));
7502 }
7503 else
7504 {
7505 /* [Rn] */
7506 skip_whitespace (str);
7507
7508 if (*str == '!')
7509 {
7510 if (conflict_reg)
7511 as_warn (_("%s register same as write-back base"),
7512 ((inst.instruction & LOAD_BIT)
7513 ? _("destination") : _("source")));
7514 str++;
7515 inst.instruction |= WRITE_BACK;
7516 }
7517
7518 inst.instruction |= INDEX_UP;
7519 pre_inc = 1;
7520 }
7521 }
7522 else
7523 {
7524 /* [Rn,...] */
7525 if (skip_past_comma (&str) == FAIL)
7526 {
7527 inst.error = _("pre-indexed expression expected");
7528 return;
7529 }
7530
7531 pre_inc = 1;
7532 if (ldst_extend (&str) == FAIL)
7533 return;
7534
7535 skip_whitespace (str);
7536
7537 if (*str++ != ']')
7538 {
7539 inst.error = _("missing ]");
7540 return;
7541 }
7542
7543 skip_whitespace (str);
7544
7545 if (*str == '!')
7546 {
7547 if (conflict_reg)
7548 as_warn (_("%s register same as write-back base"),
7549 ((inst.instruction & LOAD_BIT)
7550 ? _("destination") : _("source")));
7551 str++;
7552 inst.instruction |= WRITE_BACK;
7553 }
7554 }
7555 }
7556 else if (*str == '=')
7557 {
f03698e6
RE
7558 if ((inst.instruction & LOAD_BIT) == 0)
7559 {
7560 inst.error = _("invalid pseudo operation");
7561 return;
7562 }
7563
90e4755a
RE
7564 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7565 str++;
7566
7567 skip_whitespace (str);
7568
7569 if (my_get_expression (&inst.reloc.exp, &str))
7570 return;
7571
7572 if (inst.reloc.exp.X_op != O_constant
7573 && inst.reloc.exp.X_op != O_symbol)
7574 {
f03698e6 7575 inst.error = _("constant expression expected");
90e4755a
RE
7576 return;
7577 }
7578
e28cd48c 7579 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7580 {
e28cd48c
RE
7581 value = validate_immediate (inst.reloc.exp.X_add_number);
7582
7583 if (value != FAIL)
90e4755a 7584 {
e28cd48c
RE
7585 /* This can be done with a mov instruction. */
7586 inst.instruction &= LITERAL_MASK;
7587 inst.instruction |= (INST_IMMEDIATE
7588 | (OPCODE_MOV << DATA_OP_SHIFT));
7589 inst.instruction |= value & 0xfff;
7590 end_of_line (str);
90e4755a
RE
7591 return;
7592 }
b99bd4ef 7593
e28cd48c
RE
7594 value = validate_immediate (~inst.reloc.exp.X_add_number);
7595
7596 if (value != FAIL)
7597 {
7598 /* This can be done with a mvn instruction. */
7599 inst.instruction &= LITERAL_MASK;
7600 inst.instruction |= (INST_IMMEDIATE
7601 | (OPCODE_MVN << DATA_OP_SHIFT));
7602 inst.instruction |= value & 0xfff;
7603 end_of_line (str);
7604 return;
7605 }
90e4755a 7606 }
e28cd48c
RE
7607
7608 /* Insert into literal pool. */
7609 if (add_to_lit_pool () == FAIL)
7610 {
7611 if (!inst.error)
7612 inst.error = _("literal pool insertion failed");
7613 return;
7614 }
7615
7616 /* Change the instruction exp to point to the pool. */
7617 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7618 inst.reloc.pc_rel = 1;
7619 inst.instruction |= (REG_PC << 16);
7620 pre_inc = 1;
1cac9012
NC
7621 }
7622 else
7623 {
90e4755a
RE
7624 if (my_get_expression (&inst.reloc.exp, &str))
7625 return;
7626
7627 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7628#ifndef TE_WINCE
7629 /* PC rel adjust. */
7630 inst.reloc.exp.X_add_number -= 8;
7631#endif
1cac9012 7632 inst.reloc.pc_rel = 1;
90e4755a
RE
7633 inst.instruction |= (REG_PC << 16);
7634 pre_inc = 1;
b99bd4ef
NC
7635 }
7636
90e4755a 7637 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7638 end_of_line (str);
b99bd4ef
NC
7639}
7640
7641static void
f2b7cb0a 7642do_ldstt (str)
90e4755a 7643 char * str;
b99bd4ef 7644{
90e4755a
RE
7645 int conflict_reg;
7646
b99bd4ef
NC
7647 skip_whitespace (str);
7648
90e4755a 7649 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7650 {
7651 if (!inst.error)
7652 inst.error = BAD_ARGS;
7653 return;
7654 }
7655
90e4755a 7656 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7657 {
f03698e6 7658 inst.error = _("address expected");
b99bd4ef
NC
7659 return;
7660 }
7661
90e4755a
RE
7662 if (*str == '[')
7663 {
7664 int reg;
b99bd4ef 7665
90e4755a 7666 str++;
b99bd4ef 7667
90e4755a 7668 skip_whitespace (str);
b99bd4ef 7669
90e4755a
RE
7670 if ((reg = reg_required_here (&str, 16)) == FAIL)
7671 return;
b99bd4ef 7672
90e4755a
RE
7673 /* ldrt/strt always use post-indexed addressing, so if the base is
7674 the same as Rd, we warn. */
7675 if (conflict_reg == reg)
7676 as_warn (_("%s register same as write-back base"),
7677 ((inst.instruction & LOAD_BIT)
7678 ? _("destination") : _("source")));
7679
7680 skip_whitespace (str);
7681
7682 if (*str == ']')
7683 {
7684 str ++;
7685
7686 if (skip_past_comma (&str) == SUCCESS)
7687 {
7688 /* [Rn],... (post inc) */
7689 if (ldst_extend (&str) == FAIL)
7690 return;
7691 }
7692 else
7693 {
7694 /* [Rn] */
7695 skip_whitespace (str);
7696
7697 /* Skip a write-back '!'. */
7698 if (*str == '!')
7699 str++;
7700
7701 inst.instruction |= INDEX_UP;
7702 }
7703 }
7704 else
7705 {
7706 inst.error = _("post-indexed expression expected");
7707 return;
7708 }
7709 }
7710 else
b99bd4ef 7711 {
90e4755a 7712 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7713 return;
7714 }
7715
b99bd4ef 7716 end_of_line (str);
b99bd4ef
NC
7717}
7718
7719static int
90e4755a 7720ldst_extend_v4 (str)
b99bd4ef 7721 char ** str;
b99bd4ef
NC
7722{
7723 int add = INDEX_UP;
7724
7725 switch (**str)
7726 {
7727 case '#':
7728 case '$':
7729 (*str)++;
7730 if (my_get_expression (& inst.reloc.exp, str))
7731 return FAIL;
7732
7733 if (inst.reloc.exp.X_op == O_constant)
7734 {
7735 int value = inst.reloc.exp.X_add_number;
7736
90e4755a 7737 if (value < -255 || value > 255)
b99bd4ef
NC
7738 {
7739 inst.error = _("address offset too large");
7740 return FAIL;
7741 }
7742
7743 if (value < 0)
7744 {
7745 value = -value;
7746 add = 0;
7747 }
7748
7749 /* Halfword and signextension instructions have the
7750 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7751 inst.instruction |= (add | HWOFFSET_IMM
7752 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7753 }
7754 else
7755 {
90e4755a
RE
7756 inst.instruction |= HWOFFSET_IMM;
7757 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7758 inst.reloc.pc_rel = 0;
7759 }
7760 return SUCCESS;
7761
7762 case '-':
7763 add = 0;
7764 /* Fall through. */
7765
7766 case '+':
7767 (*str)++;
7768 /* Fall through. */
7769
7770 default:
7771 if (reg_required_here (str, 0) == FAIL)
7772 return FAIL;
7773
90e4755a 7774 inst.instruction |= add;
b99bd4ef
NC
7775 return SUCCESS;
7776 }
7777}
7778
90e4755a 7779/* Halfword and signed-byte load/store operations. */
b99bd4ef 7780static void
f2b7cb0a 7781do_ldstv4 (str)
b99bd4ef 7782 char * str;
b99bd4ef 7783{
b99bd4ef
NC
7784 int pre_inc = 0;
7785 int conflict_reg;
7786 int value;
7787
b99bd4ef
NC
7788 skip_whitespace (str);
7789
7790 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7791 {
7792 if (!inst.error)
7793 inst.error = BAD_ARGS;
7794 return;
7795 }
7796
7797 if (skip_past_comma (& str) == FAIL)
7798 {
f03698e6 7799 inst.error = _("address expected");
b99bd4ef
NC
7800 return;
7801 }
7802
7803 if (*str == '[')
7804 {
7805 int reg;
7806
7807 str++;
7808
7809 skip_whitespace (str);
7810
7811 if ((reg = reg_required_here (&str, 16)) == FAIL)
7812 return;
7813
7814 /* Conflicts can occur on stores as well as loads. */
7815 conflict_reg = (conflict_reg == reg);
7816
7817 skip_whitespace (str);
7818
7819 if (*str == ']')
7820 {
7821 str ++;
7822
7823 if (skip_past_comma (&str) == SUCCESS)
7824 {
7825 /* [Rn],... (post inc) */
90e4755a 7826 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7827 return;
7828 if (conflict_reg)
90e4755a
RE
7829 as_warn (_("%s register same as write-back base"),
7830 ((inst.instruction & LOAD_BIT)
7831 ? _("destination") : _("source")));
b99bd4ef
NC
7832 }
7833 else
7834 {
7835 /* [Rn] */
90e4755a 7836 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7837
7838 skip_whitespace (str);
7839
7840 if (*str == '!')
7841 {
7842 if (conflict_reg)
7843 as_warn (_("%s register same as write-back base"),
7844 ((inst.instruction & LOAD_BIT)
7845 ? _("destination") : _("source")));
7846 str++;
7847 inst.instruction |= WRITE_BACK;
7848 }
7849
90e4755a
RE
7850 inst.instruction |= INDEX_UP;
7851 pre_inc = 1;
b99bd4ef
NC
7852 }
7853 }
7854 else
7855 {
7856 /* [Rn,...] */
7857 if (skip_past_comma (&str) == FAIL)
7858 {
7859 inst.error = _("pre-indexed expression expected");
7860 return;
7861 }
7862
7863 pre_inc = 1;
90e4755a 7864 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7865 return;
7866
7867 skip_whitespace (str);
7868
7869 if (*str++ != ']')
7870 {
7871 inst.error = _("missing ]");
7872 return;
7873 }
7874
7875 skip_whitespace (str);
7876
7877 if (*str == '!')
7878 {
7879 if (conflict_reg)
7880 as_warn (_("%s register same as write-back base"),
7881 ((inst.instruction & LOAD_BIT)
7882 ? _("destination") : _("source")));
7883 str++;
7884 inst.instruction |= WRITE_BACK;
7885 }
7886 }
7887 }
7888 else if (*str == '=')
7889 {
f03698e6
RE
7890 if ((inst.instruction & LOAD_BIT) == 0)
7891 {
7892 inst.error = _("invalid pseudo operation");
7893 return;
7894 }
7895
90e4755a 7896 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7897 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7898 str++;
7899
7900 skip_whitespace (str);
7901
7902 if (my_get_expression (&inst.reloc.exp, &str))
7903 return;
7904
7905 if (inst.reloc.exp.X_op != O_constant
7906 && inst.reloc.exp.X_op != O_symbol)
7907 {
f03698e6 7908 inst.error = _("constant expression expected");
b99bd4ef
NC
7909 return;
7910 }
7911
d8273442 7912 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7913 {
d8273442
NC
7914 value = validate_immediate (inst.reloc.exp.X_add_number);
7915
7916 if (value != FAIL)
b99bd4ef 7917 {
d8273442
NC
7918 /* This can be done with a mov instruction. */
7919 inst.instruction &= LITERAL_MASK;
7920 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7921 inst.instruction |= value & 0xfff;
d8273442 7922 end_of_line (str);
b99bd4ef
NC
7923 return;
7924 }
cc8a6dd0 7925
d8273442 7926 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7927
d8273442 7928 if (value != FAIL)
b99bd4ef 7929 {
d8273442
NC
7930 /* This can be done with a mvn instruction. */
7931 inst.instruction &= LITERAL_MASK;
7932 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7933 inst.instruction |= value & 0xfff;
d8273442
NC
7934 end_of_line (str);
7935 return;
b99bd4ef 7936 }
b99bd4ef 7937 }
d8273442
NC
7938
7939 /* Insert into literal pool. */
7940 if (add_to_lit_pool () == FAIL)
7941 {
7942 if (!inst.error)
7943 inst.error = _("literal pool insertion failed");
7944 return;
7945 }
7946
7947 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7948 inst.instruction |= HWOFFSET_IMM;
7949 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7950 inst.reloc.pc_rel = 1;
7951 inst.instruction |= (REG_PC << 16);
7952 pre_inc = 1;
b99bd4ef
NC
7953 }
7954 else
7955 {
7956 if (my_get_expression (&inst.reloc.exp, &str))
7957 return;
7958
90e4755a
RE
7959 inst.instruction |= HWOFFSET_IMM;
7960 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7961#ifndef TE_WINCE
7962 /* PC rel adjust. */
7963 inst.reloc.exp.X_add_number -= 8;
7964#endif
7965 inst.reloc.pc_rel = 1;
7966 inst.instruction |= (REG_PC << 16);
7967 pre_inc = 1;
7968 }
7969
90e4755a 7970 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7971 end_of_line (str);
b99bd4ef
NC
7972}
7973
7974static long
7975reg_list (strp)
7976 char ** strp;
7977{
7978 char * str = * strp;
7979 long range = 0;
7980 int another_range;
7981
7982 /* We come back here if we get ranges concatenated by '+' or '|'. */
7983 do
7984 {
7985 another_range = 0;
7986
7987 if (*str == '{')
7988 {
7989 int in_range = 0;
7990 int cur_reg = -1;
7991
7992 str++;
7993 do
7994 {
7995 int reg;
7996
7997 skip_whitespace (str);
7998
7999 if ((reg = reg_required_here (& str, -1)) == FAIL)
8000 return FAIL;
8001
8002 if (in_range)
8003 {
8004 int i;
8005
8006 if (reg <= cur_reg)
8007 {
f03698e6 8008 inst.error = _("bad range in register list");
b99bd4ef
NC
8009 return FAIL;
8010 }
8011
8012 for (i = cur_reg + 1; i < reg; i++)
8013 {
8014 if (range & (1 << i))
8015 as_tsktsk
f03698e6 8016 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8017 i);
8018 else
8019 range |= 1 << i;
8020 }
8021 in_range = 0;
8022 }
8023
8024 if (range & (1 << reg))
f03698e6 8025 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8026 reg);
8027 else if (reg <= cur_reg)
f03698e6 8028 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
8029
8030 range |= 1 << reg;
8031 cur_reg = reg;
8032 }
8033 while (skip_past_comma (&str) != FAIL
8034 || (in_range = 1, *str++ == '-'));
8035 str--;
8036 skip_whitespace (str);
8037
8038 if (*str++ != '}')
8039 {
f03698e6 8040 inst.error = _("missing `}'");
b99bd4ef
NC
8041 return FAIL;
8042 }
8043 }
8044 else
8045 {
8046 expressionS expr;
8047
8048 if (my_get_expression (&expr, &str))
8049 return FAIL;
8050
8051 if (expr.X_op == O_constant)
8052 {
8053 if (expr.X_add_number
8054 != (expr.X_add_number & 0x0000ffff))
8055 {
8056 inst.error = _("invalid register mask");
8057 return FAIL;
8058 }
8059
8060 if ((range & expr.X_add_number) != 0)
8061 {
8062 int regno = range & expr.X_add_number;
8063
8064 regno &= -regno;
8065 regno = (1 << regno) - 1;
8066 as_tsktsk
f03698e6 8067 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8068 regno);
8069 }
8070
8071 range |= expr.X_add_number;
8072 }
8073 else
8074 {
8075 if (inst.reloc.type != 0)
8076 {
8077 inst.error = _("expression too complex");
8078 return FAIL;
8079 }
8080
8081 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8082 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8083 inst.reloc.pc_rel = 0;
8084 }
8085 }
8086
8087 skip_whitespace (str);
8088
8089 if (*str == '|' || *str == '+')
8090 {
8091 str++;
8092 another_range = 1;
8093 }
8094 }
8095 while (another_range);
8096
8097 *strp = str;
8098 return range;
8099}
8100
8101static void
f2b7cb0a 8102do_ldmstm (str)
b99bd4ef 8103 char * str;
b99bd4ef
NC
8104{
8105 int base_reg;
8106 long range;
8107
8108 skip_whitespace (str);
8109
8110 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8111 return;
8112
8113 if (base_reg == REG_PC)
8114 {
8115 inst.error = _("r15 not allowed as base register");
8116 return;
8117 }
8118
8119 skip_whitespace (str);
8120
8121 if (*str == '!')
8122 {
90e4755a 8123 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8124 str++;
8125 }
8126
8127 if (skip_past_comma (&str) == FAIL
8128 || (range = reg_list (&str)) == FAIL)
8129 {
8130 if (! inst.error)
8131 inst.error = BAD_ARGS;
8132 return;
8133 }
8134
8135 if (*str == '^')
8136 {
8137 str++;
90e4755a 8138 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8139 }
8140
6189168b
NC
8141 if (inst.instruction & WRITE_BACK)
8142 {
8143 /* Check for unpredictable uses of writeback. */
8144 if (inst.instruction & LOAD_BIT)
8145 {
8146 /* Not allowed in LDM type 2. */
8147 if ((inst.instruction & LDM_TYPE_2_OR_3)
8148 && ((range & (1 << REG_PC)) == 0))
8149 as_warn (_("writeback of base register is UNPREDICTABLE"));
8150 /* Only allowed if base reg not in list for other types. */
8151 else if (range & (1 << base_reg))
8152 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8153 }
8154 else /* STM. */
8155 {
8156 /* Not allowed for type 2. */
8157 if (inst.instruction & LDM_TYPE_2_OR_3)
8158 as_warn (_("writeback of base register is UNPREDICTABLE"));
8159 /* Only allowed if base reg not in list, or first in list. */
8160 else if ((range & (1 << base_reg))
8161 && (range & ((1 << base_reg) - 1)))
8162 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8163 }
8164 }
61b5f74b 8165
f2b7cb0a 8166 inst.instruction |= range;
b99bd4ef 8167 end_of_line (str);
b99bd4ef
NC
8168}
8169
8170static void
f2b7cb0a 8171do_swi (str)
b99bd4ef 8172 char * str;
b99bd4ef
NC
8173{
8174 skip_whitespace (str);
8175
8176 /* Allow optional leading '#'. */
8177 if (is_immediate_prefix (*str))
8178 str++;
8179
8180 if (my_get_expression (& inst.reloc.exp, & str))
8181 return;
8182
8183 inst.reloc.type = BFD_RELOC_ARM_SWI;
8184 inst.reloc.pc_rel = 0;
b99bd4ef 8185 end_of_line (str);
b99bd4ef
NC
8186}
8187
8188static void
f2b7cb0a 8189do_swap (str)
b99bd4ef 8190 char * str;
b99bd4ef
NC
8191{
8192 int reg;
8193
8194 skip_whitespace (str);
8195
8196 if ((reg = reg_required_here (&str, 12)) == FAIL)
8197 return;
8198
8199 if (reg == REG_PC)
8200 {
8201 inst.error = _("r15 not allowed in swap");
8202 return;
8203 }
8204
8205 if (skip_past_comma (&str) == FAIL
8206 || (reg = reg_required_here (&str, 0)) == FAIL)
8207 {
8208 if (!inst.error)
8209 inst.error = BAD_ARGS;
8210 return;
8211 }
8212
8213 if (reg == REG_PC)
8214 {
8215 inst.error = _("r15 not allowed in swap");
8216 return;
8217 }
8218
8219 if (skip_past_comma (&str) == FAIL
8220 || *str++ != '[')
8221 {
8222 inst.error = BAD_ARGS;
8223 return;
8224 }
8225
8226 skip_whitespace (str);
8227
8228 if ((reg = reg_required_here (&str, 16)) == FAIL)
8229 return;
8230
8231 if (reg == REG_PC)
8232 {
8233 inst.error = BAD_PC;
8234 return;
8235 }
8236
8237 skip_whitespace (str);
8238
8239 if (*str++ != ']')
8240 {
8241 inst.error = _("missing ]");
8242 return;
8243 }
8244
b99bd4ef 8245 end_of_line (str);
b99bd4ef
NC
8246}
8247
8248static void
f2b7cb0a 8249do_branch (str)
b99bd4ef 8250 char * str;
b99bd4ef
NC
8251{
8252 if (my_get_expression (&inst.reloc.exp, &str))
8253 return;
8254
8255#ifdef OBJ_ELF
8256 {
8257 char * save_in;
8258
8259 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8260 required for the instruction. */
8261
8262 /* arm_parse_reloc () works on input_line_pointer.
8263 We actually want to parse the operands to the branch instruction
8264 passed in 'str'. Save the input pointer and restore it later. */
8265 save_in = input_line_pointer;
8266 input_line_pointer = str;
8267 if (inst.reloc.exp.X_op == O_symbol
8268 && *str == '('
8269 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8270 {
8271 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8272 inst.reloc.pc_rel = 0;
8273 /* Modify str to point to after parsed operands, otherwise
8274 end_of_line() will complain about the (PLT) left in str. */
8275 str = input_line_pointer;
8276 }
8277 else
8278 {
8279 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8280 inst.reloc.pc_rel = 1;
8281 }
8282 input_line_pointer = save_in;
8283 }
8284#else
8285 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8286 inst.reloc.pc_rel = 1;
8287#endif /* OBJ_ELF */
8288
8289 end_of_line (str);
b99bd4ef
NC
8290}
8291
8292static void
f2b7cb0a 8293do_bx (str)
b99bd4ef 8294 char * str;
b99bd4ef
NC
8295{
8296 int reg;
8297
8298 skip_whitespace (str);
8299
8300 if ((reg = reg_required_here (&str, 0)) == FAIL)
8301 {
8302 inst.error = BAD_ARGS;
8303 return;
8304 }
8305
8306 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8307 if (reg == REG_PC)
f03698e6 8308 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8309
8310 end_of_line (str);
8311}
8312
8313static void
f2b7cb0a 8314do_cdp (str)
b99bd4ef 8315 char * str;
b99bd4ef
NC
8316{
8317 /* Co-processor data operation.
8318 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8319 skip_whitespace (str);
8320
8321 if (co_proc_number (&str) == FAIL)
8322 {
8323 if (!inst.error)
8324 inst.error = BAD_ARGS;
8325 return;
8326 }
8327
8328 if (skip_past_comma (&str) == FAIL
8329 || cp_opc_expr (&str, 20,4) == FAIL)
8330 {
8331 if (!inst.error)
8332 inst.error = BAD_ARGS;
8333 return;
8334 }
8335
8336 if (skip_past_comma (&str) == FAIL
8337 || cp_reg_required_here (&str, 12) == FAIL)
8338 {
8339 if (!inst.error)
8340 inst.error = BAD_ARGS;
8341 return;
8342 }
8343
8344 if (skip_past_comma (&str) == FAIL
8345 || cp_reg_required_here (&str, 16) == FAIL)
8346 {
8347 if (!inst.error)
8348 inst.error = BAD_ARGS;
8349 return;
8350 }
8351
8352 if (skip_past_comma (&str) == FAIL
8353 || cp_reg_required_here (&str, 0) == FAIL)
8354 {
8355 if (!inst.error)
8356 inst.error = BAD_ARGS;
8357 return;
8358 }
8359
8360 if (skip_past_comma (&str) == SUCCESS)
8361 {
8362 if (cp_opc_expr (&str, 5, 3) == FAIL)
8363 {
8364 if (!inst.error)
8365 inst.error = BAD_ARGS;
8366 return;
8367 }
8368 }
8369
8370 end_of_line (str);
b99bd4ef
NC
8371}
8372
8373static void
f2b7cb0a 8374do_lstc (str)
b99bd4ef 8375 char * str;
b99bd4ef
NC
8376{
8377 /* Co-processor register load/store.
8378 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8379
8380 skip_whitespace (str);
8381
8382 if (co_proc_number (&str) == FAIL)
8383 {
8384 if (!inst.error)
8385 inst.error = BAD_ARGS;
8386 return;
8387 }
8388
8389 if (skip_past_comma (&str) == FAIL
8390 || cp_reg_required_here (&str, 12) == FAIL)
8391 {
8392 if (!inst.error)
8393 inst.error = BAD_ARGS;
8394 return;
8395 }
8396
8397 if (skip_past_comma (&str) == FAIL
bfae80f2 8398 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8399 {
8400 if (! inst.error)
8401 inst.error = BAD_ARGS;
8402 return;
8403 }
8404
b99bd4ef 8405 end_of_line (str);
b99bd4ef
NC
8406}
8407
8408static void
f2b7cb0a 8409do_co_reg (str)
b99bd4ef 8410 char * str;
b99bd4ef
NC
8411{
8412 /* Co-processor register transfer.
8413 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8414
8415 skip_whitespace (str);
8416
8417 if (co_proc_number (&str) == FAIL)
8418 {
8419 if (!inst.error)
8420 inst.error = BAD_ARGS;
8421 return;
8422 }
8423
8424 if (skip_past_comma (&str) == FAIL
8425 || cp_opc_expr (&str, 21, 3) == FAIL)
8426 {
8427 if (!inst.error)
8428 inst.error = BAD_ARGS;
8429 return;
8430 }
8431
8432 if (skip_past_comma (&str) == FAIL
8433 || reg_required_here (&str, 12) == FAIL)
8434 {
8435 if (!inst.error)
8436 inst.error = BAD_ARGS;
8437 return;
8438 }
8439
8440 if (skip_past_comma (&str) == FAIL
8441 || cp_reg_required_here (&str, 16) == FAIL)
8442 {
8443 if (!inst.error)
8444 inst.error = BAD_ARGS;
8445 return;
8446 }
8447
8448 if (skip_past_comma (&str) == FAIL
8449 || cp_reg_required_here (&str, 0) == FAIL)
8450 {
8451 if (!inst.error)
8452 inst.error = BAD_ARGS;
8453 return;
8454 }
8455
8456 if (skip_past_comma (&str) == SUCCESS)
8457 {
8458 if (cp_opc_expr (&str, 5, 3) == FAIL)
8459 {
8460 if (!inst.error)
8461 inst.error = BAD_ARGS;
8462 return;
8463 }
8464 }
b99bd4ef
NC
8465
8466 end_of_line (str);
b99bd4ef
NC
8467}
8468
8469static void
f2b7cb0a 8470do_fpa_ctrl (str)
b99bd4ef 8471 char * str;
b99bd4ef
NC
8472{
8473 /* FP control registers.
8474 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8475
8476 skip_whitespace (str);
8477
8478 if (reg_required_here (&str, 12) == FAIL)
8479 {
8480 if (!inst.error)
8481 inst.error = BAD_ARGS;
8482 return;
8483 }
8484
8485 end_of_line (str);
b99bd4ef
NC
8486}
8487
8488static void
f2b7cb0a 8489do_fpa_ldst (str)
b99bd4ef 8490 char * str;
b99bd4ef
NC
8491{
8492 skip_whitespace (str);
8493
b99bd4ef
NC
8494 if (fp_reg_required_here (&str, 12) == FAIL)
8495 {
8496 if (!inst.error)
8497 inst.error = BAD_ARGS;
8498 return;
8499 }
8500
8501 if (skip_past_comma (&str) == FAIL
bfae80f2 8502 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8503 {
8504 if (!inst.error)
8505 inst.error = BAD_ARGS;
8506 return;
8507 }
8508
8509 end_of_line (str);
8510}
8511
8512static void
f2b7cb0a 8513do_fpa_ldmstm (str)
b99bd4ef 8514 char * str;
b99bd4ef
NC
8515{
8516 int num_regs;
8517
8518 skip_whitespace (str);
8519
8520 if (fp_reg_required_here (&str, 12) == FAIL)
8521 {
8522 if (! inst.error)
8523 inst.error = BAD_ARGS;
8524 return;
8525 }
8526
8527 /* Get Number of registers to transfer. */
8528 if (skip_past_comma (&str) == FAIL
8529 || my_get_expression (&inst.reloc.exp, &str))
8530 {
8531 if (! inst.error)
8532 inst.error = _("constant expression expected");
8533 return;
8534 }
8535
8536 if (inst.reloc.exp.X_op != O_constant)
8537 {
f03698e6 8538 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8539 return;
8540 }
8541
8542 num_regs = inst.reloc.exp.X_add_number;
8543
8544 if (num_regs < 1 || num_regs > 4)
8545 {
8546 inst.error = _("number of registers must be in the range [1:4]");
8547 return;
8548 }
8549
8550 switch (num_regs)
8551 {
8552 case 1:
8553 inst.instruction |= CP_T_X;
8554 break;
8555 case 2:
8556 inst.instruction |= CP_T_Y;
8557 break;
8558 case 3:
8559 inst.instruction |= CP_T_Y | CP_T_X;
8560 break;
8561 case 4:
8562 break;
8563 default:
8564 abort ();
8565 }
8566
e28cd48c 8567 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8568 {
8569 int reg;
8570 int write_back;
8571 int offset;
8572
8573 /* The instruction specified "ea" or "fd", so we can only accept
8574 [Rn]{!}. The instruction does not really support stacking or
8575 unstacking, so we have to emulate these by setting appropriate
8576 bits and offsets. */
8577 if (skip_past_comma (&str) == FAIL
8578 || *str != '[')
8579 {
8580 if (! inst.error)
8581 inst.error = BAD_ARGS;
8582 return;
8583 }
8584
8585 str++;
8586 skip_whitespace (str);
8587
8588 if ((reg = reg_required_here (&str, 16)) == FAIL)
8589 return;
8590
8591 skip_whitespace (str);
8592
8593 if (*str != ']')
8594 {
8595 inst.error = BAD_ARGS;
8596 return;
8597 }
8598
8599 str++;
8600 if (*str == '!')
8601 {
8602 write_back = 1;
8603 str++;
8604 if (reg == REG_PC)
8605 {
8606 inst.error =
f03698e6 8607 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8608 return;
8609 }
8610 }
8611 else
8612 write_back = 0;
8613
90e4755a 8614 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8615 {
8616 /* Pre-decrement. */
8617 offset = 3 * num_regs;
8618 if (write_back)
90e4755a 8619 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8620 }
8621 else
8622 {
8623 /* Post-increment. */
8624 if (write_back)
8625 {
90e4755a 8626 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8627 offset = 3 * num_regs;
8628 }
8629 else
8630 {
8631 /* No write-back, so convert this into a standard pre-increment
8632 instruction -- aesthetically more pleasing. */
90e4755a 8633 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8634 offset = 0;
8635 }
8636 }
8637
f2b7cb0a 8638 inst.instruction |= offset;
b99bd4ef
NC
8639 }
8640 else if (skip_past_comma (&str) == FAIL
bfae80f2 8641 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8642 {
8643 if (! inst.error)
8644 inst.error = BAD_ARGS;
8645 return;
8646 }
8647
8648 end_of_line (str);
8649}
8650
8651static void
f2b7cb0a 8652do_fpa_dyadic (str)
b99bd4ef 8653 char * str;
b99bd4ef
NC
8654{
8655 skip_whitespace (str);
8656
b99bd4ef
NC
8657 if (fp_reg_required_here (&str, 12) == FAIL)
8658 {
8659 if (! inst.error)
8660 inst.error = BAD_ARGS;
8661 return;
8662 }
8663
8664 if (skip_past_comma (&str) == FAIL
8665 || fp_reg_required_here (&str, 16) == FAIL)
8666 {
8667 if (! inst.error)
8668 inst.error = BAD_ARGS;
8669 return;
8670 }
8671
8672 if (skip_past_comma (&str) == FAIL
8673 || fp_op2 (&str) == FAIL)
8674 {
8675 if (! inst.error)
8676 inst.error = BAD_ARGS;
8677 return;
8678 }
8679
b99bd4ef 8680 end_of_line (str);
b99bd4ef
NC
8681}
8682
8683static void
f2b7cb0a 8684do_fpa_monadic (str)
b99bd4ef 8685 char * str;
b99bd4ef
NC
8686{
8687 skip_whitespace (str);
8688
b99bd4ef
NC
8689 if (fp_reg_required_here (&str, 12) == FAIL)
8690 {
8691 if (! inst.error)
8692 inst.error = BAD_ARGS;
8693 return;
8694 }
8695
8696 if (skip_past_comma (&str) == FAIL
8697 || fp_op2 (&str) == FAIL)
8698 {
8699 if (! inst.error)
8700 inst.error = BAD_ARGS;
8701 return;
8702 }
8703
b99bd4ef 8704 end_of_line (str);
b99bd4ef
NC
8705}
8706
8707static void
f2b7cb0a 8708do_fpa_cmp (str)
b99bd4ef 8709 char * str;
b99bd4ef
NC
8710{
8711 skip_whitespace (str);
8712
8713 if (fp_reg_required_here (&str, 16) == FAIL)
8714 {
8715 if (! inst.error)
8716 inst.error = BAD_ARGS;
8717 return;
8718 }
8719
8720 if (skip_past_comma (&str) == FAIL
8721 || fp_op2 (&str) == FAIL)
8722 {
8723 if (! inst.error)
8724 inst.error = BAD_ARGS;
8725 return;
8726 }
8727
b99bd4ef 8728 end_of_line (str);
b99bd4ef
NC
8729}
8730
8731static void
f2b7cb0a 8732do_fpa_from_reg (str)
b99bd4ef 8733 char * str;
b99bd4ef
NC
8734{
8735 skip_whitespace (str);
8736
b99bd4ef
NC
8737 if (fp_reg_required_here (&str, 16) == FAIL)
8738 {
8739 if (! inst.error)
8740 inst.error = BAD_ARGS;
8741 return;
8742 }
8743
8744 if (skip_past_comma (&str) == FAIL
8745 || reg_required_here (&str, 12) == FAIL)
8746 {
8747 if (! inst.error)
8748 inst.error = BAD_ARGS;
8749 return;
8750 }
8751
b99bd4ef 8752 end_of_line (str);
b99bd4ef
NC
8753}
8754
8755static void
f2b7cb0a 8756do_fpa_to_reg (str)
b99bd4ef 8757 char * str;
b99bd4ef
NC
8758{
8759 skip_whitespace (str);
8760
8761 if (reg_required_here (&str, 12) == FAIL)
8762 return;
8763
8764 if (skip_past_comma (&str) == FAIL
8765 || fp_reg_required_here (&str, 0) == FAIL)
8766 {
8767 if (! inst.error)
8768 inst.error = BAD_ARGS;
8769 return;
8770 }
8771
b99bd4ef 8772 end_of_line (str);
b99bd4ef
NC
8773}
8774
b99bd4ef 8775static int
bfae80f2
RE
8776vfp_sp_reg_required_here (str, pos)
8777 char **str;
8778 enum vfp_sp_reg_pos pos;
b99bd4ef 8779{
bfae80f2
RE
8780 int reg;
8781 char *start = *str;
b99bd4ef 8782
bfae80f2 8783 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8784 {
bfae80f2 8785 switch (pos)
b99bd4ef 8786 {
bfae80f2
RE
8787 case VFP_REG_Sd:
8788 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8789 break;
8790
8791 case VFP_REG_Sn:
8792 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8793 break;
8794
8795 case VFP_REG_Sm:
8796 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8797 break;
8798
8799 default:
8800 abort ();
b99bd4ef 8801 }
bfae80f2
RE
8802 return reg;
8803 }
b99bd4ef 8804
bfae80f2
RE
8805 /* In the few cases where we might be able to accept something else
8806 this error can be overridden. */
8807 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8808
8809 /* Restore the start point. */
8810 *str = start;
8811 return FAIL;
8812}
8813
8814static int
8815vfp_dp_reg_required_here (str, pos)
8816 char **str;
f201ccb3 8817 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8818{
8819 int reg;
8820 char *start = *str;
8821
8822 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8823 {
8824 switch (pos)
b99bd4ef 8825 {
bfae80f2
RE
8826 case VFP_REG_Dd:
8827 inst.instruction |= reg << 12;
8828 break;
b99bd4ef 8829
bfae80f2
RE
8830 case VFP_REG_Dn:
8831 inst.instruction |= reg << 16;
8832 break;
8833
8834 case VFP_REG_Dm:
8835 inst.instruction |= reg << 0;
8836 break;
8837
8838 default:
8839 abort ();
8840 }
8841 return reg;
b99bd4ef
NC
8842 }
8843
bfae80f2
RE
8844 /* In the few cases where we might be able to accept something else
8845 this error can be overridden. */
8846 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8847
bfae80f2
RE
8848 /* Restore the start point. */
8849 *str = start;
8850 return FAIL;
8851}
b99bd4ef
NC
8852
8853static void
bfae80f2
RE
8854do_vfp_sp_monadic (str)
8855 char *str;
b99bd4ef 8856{
b99bd4ef
NC
8857 skip_whitespace (str);
8858
bfae80f2
RE
8859 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8860 return;
8861
8862 if (skip_past_comma (&str) == FAIL
8863 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8864 {
8865 if (! inst.error)
8866 inst.error = BAD_ARGS;
8867 return;
8868 }
8869
bfae80f2 8870 end_of_line (str);
bfae80f2
RE
8871}
8872
8873static void
8874do_vfp_dp_monadic (str)
8875 char *str;
8876{
8877 skip_whitespace (str);
8878
8879 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8880 return;
8881
8882 if (skip_past_comma (&str) == FAIL
8883 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8884 {
bfae80f2
RE
8885 if (! inst.error)
8886 inst.error = BAD_ARGS;
8887 return;
b99bd4ef 8888 }
b99bd4ef 8889
bfae80f2 8890 end_of_line (str);
bfae80f2 8891}
b99bd4ef 8892
bfae80f2
RE
8893static void
8894do_vfp_sp_dyadic (str)
8895 char *str;
8896{
8897 skip_whitespace (str);
b99bd4ef 8898
bfae80f2
RE
8899 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8900 return;
b99bd4ef 8901
bfae80f2
RE
8902 if (skip_past_comma (&str) == FAIL
8903 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8904 || skip_past_comma (&str) == FAIL
8905 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8906 {
bfae80f2
RE
8907 if (! inst.error)
8908 inst.error = BAD_ARGS;
8909 return;
8910 }
b99bd4ef 8911
bfae80f2 8912 end_of_line (str);
bfae80f2 8913}
b99bd4ef 8914
bfae80f2
RE
8915static void
8916do_vfp_dp_dyadic (str)
8917 char *str;
8918{
8919 skip_whitespace (str);
b99bd4ef 8920
bfae80f2
RE
8921 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8922 return;
b99bd4ef 8923
bfae80f2
RE
8924 if (skip_past_comma (&str) == FAIL
8925 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8926 || skip_past_comma (&str) == FAIL
8927 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8928 {
8929 if (! inst.error)
8930 inst.error = BAD_ARGS;
8931 return;
8932 }
b99bd4ef 8933
bfae80f2 8934 end_of_line (str);
bfae80f2 8935}
b99bd4ef 8936
bfae80f2
RE
8937static void
8938do_vfp_reg_from_sp (str)
8939 char *str;
8940{
8941 skip_whitespace (str);
8942
8943 if (reg_required_here (&str, 12) == FAIL)
8944 return;
8945
8946 if (skip_past_comma (&str) == FAIL
8947 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8948 {
8949 if (! inst.error)
8950 inst.error = BAD_ARGS;
8951 return;
8952 }
8953
8954 end_of_line (str);
bfae80f2
RE
8955}
8956
8957static void
e45d0630 8958do_vfp_reg2_from_sp2 (str)
bfae80f2
RE
8959 char *str;
8960{
8961 skip_whitespace (str);
8962
e45d0630
PB
8963 if (reg_required_here (&str, 12) == FAIL
8964 || skip_past_comma (&str) == FAIL
bfae80f2
RE
8965 || reg_required_here (&str, 16) == FAIL
8966 || skip_past_comma (&str) == FAIL)
8967 {
8968 if (! inst.error)
8969 inst.error = BAD_ARGS;
8970 return;
8971 }
8972
8973 /* We require exactly two consecutive SP registers. */
8974 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8975 {
8976 if (! inst.error)
8977 inst.error = _("only two consecutive VFP SP registers allowed here");
8978 }
8979
8980 end_of_line (str);
bfae80f2
RE
8981}
8982
8983static void
8984do_vfp_sp_from_reg (str)
8985 char *str;
8986{
8987 skip_whitespace (str);
8988
8989 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8990 return;
8991
8992 if (skip_past_comma (&str) == FAIL
8993 || reg_required_here (&str, 12) == FAIL)
8994 {
8995 if (! inst.error)
8996 inst.error = BAD_ARGS;
8997 return;
8998 }
8999
9000 end_of_line (str);
bfae80f2
RE
9001}
9002
e45d0630
PB
9003static void
9004do_vfp_sp2_from_reg2 (str)
9005 char *str;
9006{
9007 skip_whitespace (str);
9008
9009 /* We require exactly two consecutive SP registers. */
9010 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9011 {
9012 if (! inst.error)
9013 inst.error = _("only two consecutive VFP SP registers allowed here");
9014 }
9015
9016 if (skip_past_comma (&str) == FAIL
9017 || reg_required_here (&str, 12) == FAIL
9018 || skip_past_comma (&str) == FAIL
9019 || reg_required_here (&str, 16) == FAIL)
9020 {
9021 if (! inst.error)
9022 inst.error = BAD_ARGS;
9023 return;
9024 }
9025
9026 end_of_line (str);
9027}
9028
bfae80f2
RE
9029static void
9030do_vfp_reg_from_dp (str)
9031 char *str;
9032{
9033 skip_whitespace (str);
9034
9035 if (reg_required_here (&str, 12) == FAIL)
9036 return;
9037
9038 if (skip_past_comma (&str) == FAIL
9039 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9040 {
9041 if (! inst.error)
9042 inst.error = BAD_ARGS;
9043 return;
9044 }
9045
9046 end_of_line (str);
bfae80f2
RE
9047}
9048
9049static void
9050do_vfp_reg2_from_dp (str)
9051 char *str;
9052{
9053 skip_whitespace (str);
9054
9055 if (reg_required_here (&str, 12) == FAIL)
9056 return;
9057
9058 if (skip_past_comma (&str) == FAIL
9059 || reg_required_here (&str, 16) == FAIL
9060 || skip_past_comma (&str) == FAIL
9061 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9062 {
9063 if (! inst.error)
9064 inst.error = BAD_ARGS;
9065 return;
9066 }
9067
9068 end_of_line (str);
bfae80f2
RE
9069}
9070
9071static void
9072do_vfp_dp_from_reg (str)
9073 char *str;
9074{
9075 skip_whitespace (str);
9076
9077 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9078 return;
9079
9080 if (skip_past_comma (&str) == FAIL
9081 || reg_required_here (&str, 12) == FAIL)
9082 {
9083 if (! inst.error)
9084 inst.error = BAD_ARGS;
9085 return;
9086 }
9087
9088 end_of_line (str);
bfae80f2
RE
9089}
9090
9091static void
9092do_vfp_dp_from_reg2 (str)
9093 char *str;
9094{
9095 skip_whitespace (str);
9096
9097 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9098 return;
9099
9100 if (skip_past_comma (&str) == FAIL
9101 || reg_required_here (&str, 12) == FAIL
9102 || skip_past_comma (&str) == FAIL
e45d0630 9103 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
9104 {
9105 if (! inst.error)
9106 inst.error = BAD_ARGS;
9107 return;
9108 }
9109
9110 end_of_line (str);
bfae80f2
RE
9111}
9112
9113static const struct vfp_reg *
9114vfp_psr_parse (str)
9115 char **str;
9116{
9117 char *start = *str;
9118 char c;
9119 char *p;
9120 const struct vfp_reg *vreg;
9121
9122 p = start;
9123
9124 /* Find the end of the current token. */
9125 do
9126 {
9127 c = *p++;
9128 }
9129 while (ISALPHA (c));
9130
9131 /* Mark it. */
9132 *--p = 0;
9133
cc8a6dd0 9134 for (vreg = vfp_regs + 0;
bfae80f2
RE
9135 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9136 vreg++)
9137 {
9138 if (strcmp (start, vreg->name) == 0)
9139 {
9140 *p = c;
9141 *str = p;
9142 return vreg;
9143 }
9144 }
9145
9146 *p = c;
9147 return NULL;
9148}
9149
9150static int
9151vfp_psr_required_here (str)
9152 char **str;
9153{
9154 char *start = *str;
9155 const struct vfp_reg *vreg;
9156
9157 vreg = vfp_psr_parse (str);
9158
9159 if (vreg)
9160 {
9161 inst.instruction |= vreg->regno;
9162 return SUCCESS;
9163 }
9164
9165 inst.error = _("VFP system register expected");
9166
9167 *str = start;
9168 return FAIL;
9169}
9170
9171static void
9172do_vfp_reg_from_ctrl (str)
9173 char *str;
9174{
9175 skip_whitespace (str);
9176
9177 if (reg_required_here (&str, 12) == FAIL)
9178 return;
9179
9180 if (skip_past_comma (&str) == FAIL
9181 || vfp_psr_required_here (&str) == FAIL)
9182 {
9183 if (! inst.error)
9184 inst.error = BAD_ARGS;
9185 return;
9186 }
9187
9188 end_of_line (str);
bfae80f2
RE
9189}
9190
9191static void
9192do_vfp_ctrl_from_reg (str)
9193 char *str;
9194{
9195 skip_whitespace (str);
9196
9197 if (vfp_psr_required_here (&str) == FAIL)
9198 return;
9199
9200 if (skip_past_comma (&str) == FAIL
9201 || reg_required_here (&str, 12) == FAIL)
9202 {
9203 if (! inst.error)
9204 inst.error = BAD_ARGS;
9205 return;
9206 }
9207
9208 end_of_line (str);
bfae80f2
RE
9209}
9210
9211static void
9212do_vfp_sp_ldst (str)
9213 char *str;
9214{
9215 skip_whitespace (str);
9216
9217 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9218 {
9219 if (!inst.error)
9220 inst.error = BAD_ARGS;
9221 return;
9222 }
9223
9224 if (skip_past_comma (&str) == FAIL
9225 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9226 {
9227 if (!inst.error)
9228 inst.error = BAD_ARGS;
9229 return;
9230 }
9231
9232 end_of_line (str);
bfae80f2
RE
9233}
9234
9235static void
9236do_vfp_dp_ldst (str)
9237 char *str;
9238{
9239 skip_whitespace (str);
9240
9241 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9242 {
9243 if (!inst.error)
9244 inst.error = BAD_ARGS;
9245 return;
9246 }
9247
9248 if (skip_past_comma (&str) == FAIL
9249 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9250 {
9251 if (!inst.error)
9252 inst.error = BAD_ARGS;
9253 return;
9254 }
9255
9256 end_of_line (str);
bfae80f2
RE
9257}
9258
9259/* Parse and encode a VFP SP register list, storing the initial
9260 register in position POS and returning the range as the result. If
9261 the string is invalid return FAIL (an invalid range). */
9262static long
9263vfp_sp_reg_list (str, pos)
9264 char **str;
9265 enum vfp_sp_reg_pos pos;
9266{
9267 long range = 0;
9268 int base_reg = 0;
9269 int new_base;
9270 long base_bits = 0;
9271 int count = 0;
9272 long tempinst;
9273 unsigned long mask = 0;
9274 int warned = 0;
9275
9276 if (**str != '{')
9277 return FAIL;
9278
9279 (*str)++;
9280 skip_whitespace (*str);
9281
9282 tempinst = inst.instruction;
9283
9284 do
9285 {
9286 inst.instruction = 0;
9287
9288 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9289 return FAIL;
9290
9291 if (count == 0 || base_reg > new_base)
9292 {
9293 base_reg = new_base;
9294 base_bits = inst.instruction;
9295 }
9296
9297 if (mask & (1 << new_base))
9298 {
9299 inst.error = _("invalid register list");
9300 return FAIL;
9301 }
9302
9303 if ((mask >> new_base) != 0 && ! warned)
9304 {
9305 as_tsktsk (_("register list not in ascending order"));
9306 warned = 1;
9307 }
9308
9309 mask |= 1 << new_base;
9310 count++;
9311
9312 skip_whitespace (*str);
9313
9314 if (**str == '-') /* We have the start of a range expression */
9315 {
9316 int high_range;
9317
9318 (*str)++;
9319
9320 if ((high_range
9321 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9322 == FAIL)
9323 {
9324 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9325 return FAIL;
9326 }
9327
9328 if (high_range <= new_base)
9329 {
9330 inst.error = _("register range not in ascending order");
9331 return FAIL;
9332 }
9333
9334 for (new_base++; new_base <= high_range; new_base++)
9335 {
9336 if (mask & (1 << new_base))
9337 {
9338 inst.error = _("invalid register list");
9339 return FAIL;
9340 }
9341
9342 mask |= 1 << new_base;
9343 count++;
9344 }
9345 }
9346 }
9347 while (skip_past_comma (str) != FAIL);
9348
9349 if (**str != '}')
9350 {
9351 inst.error = _("invalid register list");
9352 return FAIL;
9353 }
9354
9355 (*str)++;
9356
9357 range = count;
9358
9359 /* Sanity check -- should have raised a parse error above. */
9360 if (count == 0 || count > 32)
c62e1cc3 9361 abort ();
bfae80f2
RE
9362
9363 /* Final test -- the registers must be consecutive. */
9364 while (count--)
9365 {
9366 if ((mask & (1 << base_reg++)) == 0)
9367 {
9368 inst.error = _("non-contiguous register range");
9369 return FAIL;
9370 }
9371 }
9372
9373 inst.instruction = tempinst | base_bits;
9374 return range;
9375}
9376
9377static long
9378vfp_dp_reg_list (str)
9379 char **str;
9380{
9381 long range = 0;
9382 int base_reg = 0;
9383 int new_base;
9384 int count = 0;
9385 long tempinst;
9386 unsigned long mask = 0;
9387 int warned = 0;
9388
9389 if (**str != '{')
9390 return FAIL;
9391
9392 (*str)++;
9393 skip_whitespace (*str);
9394
9395 tempinst = inst.instruction;
9396
9397 do
9398 {
9399 inst.instruction = 0;
9400
9401 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9402 return FAIL;
9403
9404 if (count == 0 || base_reg > new_base)
9405 {
9406 base_reg = new_base;
9407 range = inst.instruction;
9408 }
9409
9410 if (mask & (1 << new_base))
9411 {
9412 inst.error = _("invalid register list");
9413 return FAIL;
9414 }
9415
9416 if ((mask >> new_base) != 0 && ! warned)
9417 {
9418 as_tsktsk (_("register list not in ascending order"));
9419 warned = 1;
9420 }
9421
9422 mask |= 1 << new_base;
9423 count++;
9424
9425 skip_whitespace (*str);
9426
9427 if (**str == '-') /* We have the start of a range expression */
9428 {
9429 int high_range;
9430
9431 (*str)++;
9432
9433 if ((high_range
9434 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9435 == FAIL)
9436 {
9437 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9438 return FAIL;
9439 }
9440
9441 if (high_range <= new_base)
9442 {
9443 inst.error = _("register range not in ascending order");
9444 return FAIL;
9445 }
9446
9447 for (new_base++; new_base <= high_range; new_base++)
9448 {
9449 if (mask & (1 << new_base))
9450 {
9451 inst.error = _("invalid register list");
9452 return FAIL;
9453 }
9454
9455 mask |= 1 << new_base;
9456 count++;
9457 }
9458 }
9459 }
9460 while (skip_past_comma (str) != FAIL);
9461
9462 if (**str != '}')
9463 {
9464 inst.error = _("invalid register list");
9465 return FAIL;
9466 }
9467
9468 (*str)++;
9469
9470 range |= 2 * count;
9471
9472 /* Sanity check -- should have raised a parse error above. */
9473 if (count == 0 || count > 16)
c62e1cc3 9474 abort ();
bfae80f2
RE
9475
9476 /* Final test -- the registers must be consecutive. */
9477 while (count--)
9478 {
9479 if ((mask & (1 << base_reg++)) == 0)
9480 {
9481 inst.error = _("non-contiguous register range");
9482 return FAIL;
9483 }
9484 }
9485
9486 inst.instruction = tempinst;
9487 return range;
9488}
9489
9490static void
c62e1cc3 9491vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9492 char *str;
9493 enum vfp_ldstm_type ldstm_type;
9494{
9495 long range;
9496
9497 skip_whitespace (str);
9498
9499 if (reg_required_here (&str, 16) == FAIL)
9500 return;
9501
9502 skip_whitespace (str);
9503
9504 if (*str == '!')
9505 {
9506 inst.instruction |= WRITE_BACK;
9507 str++;
9508 }
9509 else if (ldstm_type != VFP_LDSTMIA)
9510 {
9511 inst.error = _("this addressing mode requires base-register writeback");
9512 return;
9513 }
9514
9515 if (skip_past_comma (&str) == FAIL
9516 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9517 {
9518 if (!inst.error)
9519 inst.error = BAD_ARGS;
9520 return;
9521 }
9522
9523 inst.instruction |= range;
9524 end_of_line (str);
9525}
9526
9527static void
c62e1cc3 9528vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9529 char *str;
9530 enum vfp_ldstm_type ldstm_type;
9531{
9532 long range;
9533
9534 skip_whitespace (str);
9535
9536 if (reg_required_here (&str, 16) == FAIL)
9537 return;
9538
9539 skip_whitespace (str);
9540
9541 if (*str == '!')
9542 {
9543 inst.instruction |= WRITE_BACK;
9544 str++;
9545 }
9546 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9547 {
9548 inst.error = _("this addressing mode requires base-register writeback");
9549 return;
9550 }
9551
9552 if (skip_past_comma (&str) == FAIL
9553 || (range = vfp_dp_reg_list (&str)) == FAIL)
9554 {
9555 if (!inst.error)
9556 inst.error = BAD_ARGS;
9557 return;
9558 }
9559
9560 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9561 range += 1;
9562
9563 inst.instruction |= range;
9564 end_of_line (str);
9565}
9566
9567static void
9568do_vfp_sp_ldstmia (str)
9569 char *str;
9570{
9571 vfp_sp_ldstm (str, VFP_LDSTMIA);
9572}
9573
9574static void
9575do_vfp_sp_ldstmdb (str)
9576 char *str;
9577{
9578 vfp_sp_ldstm (str, VFP_LDSTMDB);
9579}
9580
9581static void
9582do_vfp_dp_ldstmia (str)
9583 char *str;
9584{
9585 vfp_dp_ldstm (str, VFP_LDSTMIA);
9586}
9587
9588static void
9589do_vfp_dp_ldstmdb (str)
9590 char *str;
9591{
9592 vfp_dp_ldstm (str, VFP_LDSTMDB);
9593}
9594
9595static void
9596do_vfp_xp_ldstmia (str)
9597 char *str;
9598{
9599 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9600}
9601
9602static void
9603do_vfp_xp_ldstmdb (str)
9604 char *str;
9605{
9606 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9607}
9608
9609static void
9610do_vfp_sp_compare_z (str)
9611 char *str;
9612{
9613 skip_whitespace (str);
9614
9615 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9616 {
9617 if (!inst.error)
9618 inst.error = BAD_ARGS;
9619 return;
9620 }
9621
9622 end_of_line (str);
bfae80f2
RE
9623}
9624
9625static void
9626do_vfp_dp_compare_z (str)
9627 char *str;
9628{
9629 skip_whitespace (str);
9630
9631 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9632 {
9633 if (!inst.error)
9634 inst.error = BAD_ARGS;
9635 return;
9636 }
9637
9638 end_of_line (str);
bfae80f2
RE
9639}
9640
9641static void
9642do_vfp_dp_sp_cvt (str)
9643 char *str;
9644{
9645 skip_whitespace (str);
9646
9647 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9648 return;
9649
9650 if (skip_past_comma (&str) == FAIL
9651 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9652 {
9653 if (! inst.error)
9654 inst.error = BAD_ARGS;
9655 return;
9656 }
9657
9658 end_of_line (str);
bfae80f2
RE
9659}
9660
9661static void
9662do_vfp_sp_dp_cvt (str)
9663 char *str;
9664{
9665 skip_whitespace (str);
9666
9667 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9668 return;
9669
9670 if (skip_past_comma (&str) == FAIL
9671 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9672 {
9673 if (! inst.error)
9674 inst.error = BAD_ARGS;
9675 return;
9676 }
9677
9678 end_of_line (str);
bfae80f2
RE
9679}
9680
9681/* Thumb specific routines. */
9682
9683/* Parse and validate that a register is of the right form, this saves
9684 repeated checking of this information in many similar cases.
9685 Unlike the 32-bit case we do not insert the register into the opcode
9686 here, since the position is often unknown until the full instruction
9687 has been parsed. */
9688
9689static int
9690thumb_reg (strp, hi_lo)
9691 char ** strp;
9692 int hi_lo;
9693{
9694 int reg;
9695
9696 if ((reg = reg_required_here (strp, -1)) == FAIL)
9697 return FAIL;
9698
9699 switch (hi_lo)
9700 {
9701 case THUMB_REG_LO:
9702 if (reg > 7)
9703 {
9704 inst.error = _("lo register required");
9705 return FAIL;
9706 }
9707 break;
9708
9709 case THUMB_REG_HI:
9710 if (reg < 8)
9711 {
9712 inst.error = _("hi register required");
9713 return FAIL;
9714 }
9715 break;
9716
9717 default:
9718 break;
9719 }
9720
9721 return reg;
9722}
9723
9724/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9725 was SUB. */
9726
9727static void
9728thumb_add_sub (str, subtract)
9729 char * str;
9730 int subtract;
9731{
9732 int Rd, Rs, Rn = FAIL;
9733
9734 skip_whitespace (str);
9735
9736 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9737 || skip_past_comma (&str) == FAIL)
9738 {
9739 if (! inst.error)
9740 inst.error = BAD_ARGS;
9741 return;
9742 }
9743
9744 if (is_immediate_prefix (*str))
9745 {
9746 Rs = Rd;
9747 str++;
9748 if (my_get_expression (&inst.reloc.exp, &str))
9749 return;
9750 }
9751 else
9752 {
9753 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9754 return;
9755
9756 if (skip_past_comma (&str) == FAIL)
9757 {
9758 /* Two operand format, shuffle the registers
9759 and pretend there are 3. */
9760 Rn = Rs;
9761 Rs = Rd;
9762 }
9763 else if (is_immediate_prefix (*str))
9764 {
9765 str++;
9766 if (my_get_expression (&inst.reloc.exp, &str))
9767 return;
9768 }
9769 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9770 return;
9771 }
9772
9773 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9774 for the latter case, EXPR contains the immediate that was found. */
9775 if (Rn != FAIL)
9776 {
9777 /* All register format. */
9778 if (Rd > 7 || Rs > 7 || Rn > 7)
9779 {
9780 if (Rs != Rd)
9781 {
9782 inst.error = _("dest and source1 must be the same register");
9783 return;
9784 }
9785
9786 /* Can't do this for SUB. */
9787 if (subtract)
9788 {
9789 inst.error = _("subtract valid only on lo regs");
9790 return;
9791 }
9792
9793 inst.instruction = (T_OPCODE_ADD_HI
9794 | (Rd > 7 ? THUMB_H1 : 0)
9795 | (Rn > 7 ? THUMB_H2 : 0));
9796 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9797 }
9798 else
9799 {
9800 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9801 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9802 }
9803 }
9804 else
9805 {
9806 /* Immediate expression, now things start to get nasty. */
9807
9808 /* First deal with HI regs, only very restricted cases allowed:
9809 Adjusting SP, and using PC or SP to get an address. */
9810 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9811 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9812 {
9813 inst.error = _("invalid Hi register with immediate");
9814 return;
9815 }
9816
9817 if (inst.reloc.exp.X_op != O_constant)
9818 {
9819 /* Value isn't known yet, all we can do is store all the fragments
9820 we know about in the instruction and let the reloc hacking
9821 work it all out. */
9822 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9823 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9824 }
9825 else
9826 {
9827 int offset = inst.reloc.exp.X_add_number;
9828
9829 if (subtract)
358b94bd 9830 offset = - offset;
bfae80f2
RE
9831
9832 if (offset < 0)
9833 {
358b94bd 9834 offset = - offset;
bfae80f2
RE
9835 subtract = 1;
9836
9837 /* Quick check, in case offset is MIN_INT. */
9838 if (offset < 0)
9839 {
9840 inst.error = _("immediate value out of range");
9841 return;
9842 }
9843 }
358b94bd
NC
9844 /* Note - you cannot convert a subtract of 0 into an
9845 add of 0 because the carry flag is set differently. */
9846 else if (offset > 0)
bfae80f2
RE
9847 subtract = 0;
9848
9849 if (Rd == REG_SP)
9850 {
9851 if (offset & ~0x1fc)
9852 {
9853 inst.error = _("invalid immediate value for stack adjust");
9854 return;
b99bd4ef
NC
9855 }
9856 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9857 inst.instruction |= offset >> 2;
9858 }
9859 else if (Rs == REG_PC || Rs == REG_SP)
9860 {
9861 if (subtract
9862 || (offset & ~0x3fc))
9863 {
9864 inst.error = _("invalid immediate for address calculation");
9865 return;
9866 }
9867 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9868 : T_OPCODE_ADD_SP);
9869 inst.instruction |= (Rd << 8) | (offset >> 2);
9870 }
9871 else if (Rs == Rd)
9872 {
9873 if (offset & ~0xff)
9874 {
9875 inst.error = _("immediate value out of range");
9876 return;
9877 }
9878 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9879 inst.instruction |= (Rd << 8) | offset;
9880 }
9881 else
9882 {
9883 if (offset & ~0x7)
9884 {
9885 inst.error = _("immediate value out of range");
9886 return;
9887 }
9888 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9889 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9890 }
9891 }
9892 }
9893
9894 end_of_line (str);
9895}
9896
9897static void
9898thumb_shift (str, shift)
9899 char * str;
9900 int shift;
9901{
9902 int Rd, Rs, Rn = FAIL;
9903
9904 skip_whitespace (str);
9905
9906 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9907 || skip_past_comma (&str) == FAIL)
9908 {
9909 if (! inst.error)
9910 inst.error = BAD_ARGS;
9911 return;
9912 }
9913
9914 if (is_immediate_prefix (*str))
9915 {
9916 /* Two operand immediate format, set Rs to Rd. */
9917 Rs = Rd;
9918 str ++;
9919 if (my_get_expression (&inst.reloc.exp, &str))
9920 return;
9921 }
9922 else
9923 {
9924 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9925 return;
9926
9927 if (skip_past_comma (&str) == FAIL)
9928 {
9929 /* Two operand format, shuffle the registers
9930 and pretend there are 3. */
9931 Rn = Rs;
9932 Rs = Rd;
9933 }
9934 else if (is_immediate_prefix (*str))
9935 {
9936 str++;
9937 if (my_get_expression (&inst.reloc.exp, &str))
9938 return;
9939 }
9940 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9941 return;
9942 }
9943
9944 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9945 for the latter case, EXPR contains the immediate that was found. */
9946
9947 if (Rn != FAIL)
9948 {
9949 if (Rs != Rd)
9950 {
9951 inst.error = _("source1 and dest must be same register");
9952 return;
9953 }
9954
9955 switch (shift)
9956 {
9957 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9958 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9959 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9960 }
9961
9962 inst.instruction |= Rd | (Rn << 3);
9963 }
9964 else
9965 {
9966 switch (shift)
9967 {
9968 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9969 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9970 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9971 }
9972
9973 if (inst.reloc.exp.X_op != O_constant)
9974 {
9975 /* Value isn't known yet, create a dummy reloc and let reloc
9976 hacking fix it up. */
9977 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9978 }
9979 else
9980 {
9981 unsigned shift_value = inst.reloc.exp.X_add_number;
9982
9983 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9984 {
f03698e6 9985 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9986 return;
9987 }
9988
9989 /* Shifts of zero are handled by converting to LSL. */
9990 if (shift_value == 0)
9991 inst.instruction = T_OPCODE_LSL_I;
9992
9993 /* Shifts of 32 are encoded as a shift of zero. */
9994 if (shift_value == 32)
9995 shift_value = 0;
9996
9997 inst.instruction |= shift_value << 6;
9998 }
9999
10000 inst.instruction |= Rd | (Rs << 3);
10001 }
10002
10003 end_of_line (str);
10004}
10005
10006static void
10007thumb_mov_compare (str, move)
10008 char * str;
10009 int move;
10010{
10011 int Rd, Rs = FAIL;
10012
10013 skip_whitespace (str);
10014
10015 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10016 || skip_past_comma (&str) == FAIL)
10017 {
10018 if (! inst.error)
10019 inst.error = BAD_ARGS;
10020 return;
10021 }
10022
09d92015 10023 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
10024 {
10025 str++;
10026 if (my_get_expression (&inst.reloc.exp, &str))
10027 return;
10028 }
10029 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10030 return;
10031
10032 if (Rs != FAIL)
10033 {
09d92015 10034 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
10035 {
10036 if (move == THUMB_MOVE)
10037 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10038 since a MOV instruction produces unpredictable results. */
10039 inst.instruction = T_OPCODE_ADD_I3;
10040 else
10041 inst.instruction = T_OPCODE_CMP_LR;
10042 inst.instruction |= Rd | (Rs << 3);
10043 }
10044 else
10045 {
10046 if (move == THUMB_MOVE)
10047 inst.instruction = T_OPCODE_MOV_HR;
09d92015 10048 else if (move != THUMB_CPY)
b99bd4ef
NC
10049 inst.instruction = T_OPCODE_CMP_HR;
10050
10051 if (Rd > 7)
10052 inst.instruction |= THUMB_H1;
10053
10054 if (Rs > 7)
10055 inst.instruction |= THUMB_H2;
10056
10057 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10058 }
10059 }
10060 else
10061 {
10062 if (Rd > 7)
10063 {
10064 inst.error = _("only lo regs allowed with immediate");
10065 return;
10066 }
10067
10068 if (move == THUMB_MOVE)
10069 inst.instruction = T_OPCODE_MOV_I8;
10070 else
10071 inst.instruction = T_OPCODE_CMP_I8;
10072
10073 inst.instruction |= Rd << 8;
10074
10075 if (inst.reloc.exp.X_op != O_constant)
10076 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10077 else
10078 {
10079 unsigned value = inst.reloc.exp.X_add_number;
10080
10081 if (value > 255)
10082 {
10083 inst.error = _("invalid immediate");
10084 return;
10085 }
10086
10087 inst.instruction |= value;
10088 }
10089 }
10090
10091 end_of_line (str);
10092}
10093
10094static void
10095thumb_load_store (str, load_store, size)
10096 char * str;
10097 int load_store;
10098 int size;
10099{
10100 int Rd, Rb, Ro = FAIL;
10101
10102 skip_whitespace (str);
10103
10104 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10105 || skip_past_comma (&str) == FAIL)
10106 {
10107 if (! inst.error)
10108 inst.error = BAD_ARGS;
10109 return;
10110 }
10111
10112 if (*str == '[')
10113 {
10114 str++;
10115 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10116 return;
10117
10118 if (skip_past_comma (&str) != FAIL)
10119 {
10120 if (is_immediate_prefix (*str))
10121 {
10122 str++;
10123 if (my_get_expression (&inst.reloc.exp, &str))
10124 return;
10125 }
10126 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10127 return;
10128 }
10129 else
10130 {
10131 inst.reloc.exp.X_op = O_constant;
10132 inst.reloc.exp.X_add_number = 0;
10133 }
10134
10135 if (*str != ']')
10136 {
10137 inst.error = _("expected ']'");
10138 return;
10139 }
10140 str++;
10141 }
10142 else if (*str == '=')
10143 {
f03698e6
RE
10144 if (load_store != THUMB_LOAD)
10145 {
10146 inst.error = _("invalid pseudo operation");
10147 return;
10148 }
10149
b99bd4ef
NC
10150 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10151 str++;
10152
10153 skip_whitespace (str);
10154
10155 if (my_get_expression (& inst.reloc.exp, & str))
10156 return;
10157
10158 end_of_line (str);
10159
10160 if ( inst.reloc.exp.X_op != O_constant
10161 && inst.reloc.exp.X_op != O_symbol)
10162 {
10163 inst.error = "Constant expression expected";
10164 return;
10165 }
10166
10167 if (inst.reloc.exp.X_op == O_constant
10168 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10169 {
10170 /* This can be done with a mov instruction. */
10171
10172 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10173 inst.instruction |= inst.reloc.exp.X_add_number;
10174 return;
10175 }
10176
10177 /* Insert into literal pool. */
10178 if (add_to_lit_pool () == FAIL)
10179 {
10180 if (!inst.error)
10181 inst.error = "literal pool insertion failed";
10182 return;
10183 }
10184
10185 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10186 inst.reloc.pc_rel = 1;
10187 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10188 /* Adjust ARM pipeline offset to Thumb. */
10189 inst.reloc.exp.X_add_number += 4;
10190
10191 return;
10192 }
10193 else
10194 {
10195 if (my_get_expression (&inst.reloc.exp, &str))
10196 return;
10197
10198 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10199 inst.reloc.pc_rel = 1;
10200 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10201 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10202 end_of_line (str);
10203 return;
10204 }
10205
10206 if (Rb == REG_PC || Rb == REG_SP)
10207 {
10208 if (size != THUMB_WORD)
10209 {
10210 inst.error = _("byte or halfword not valid for base register");
10211 return;
10212 }
10213 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10214 {
f03698e6 10215 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10216 return;
10217 }
10218 else if (Ro != FAIL)
10219 {
f03698e6 10220 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10221 return;
10222 }
10223
10224 if (Rb == REG_PC)
10225 inst.instruction = T_OPCODE_LDR_PC;
10226 else if (load_store == THUMB_LOAD)
10227 inst.instruction = T_OPCODE_LDR_SP;
10228 else
10229 inst.instruction = T_OPCODE_STR_SP;
10230
10231 inst.instruction |= Rd << 8;
10232 if (inst.reloc.exp.X_op == O_constant)
10233 {
10234 unsigned offset = inst.reloc.exp.X_add_number;
10235
10236 if (offset & ~0x3fc)
10237 {
10238 inst.error = _("invalid offset");
10239 return;
10240 }
10241
10242 inst.instruction |= offset >> 2;
10243 }
10244 else
10245 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10246 }
10247 else if (Rb > 7)
10248 {
10249 inst.error = _("invalid base register in load/store");
10250 return;
10251 }
10252 else if (Ro == FAIL)
10253 {
10254 /* Immediate offset. */
10255 if (size == THUMB_WORD)
10256 inst.instruction = (load_store == THUMB_LOAD
10257 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10258 else if (size == THUMB_HALFWORD)
10259 inst.instruction = (load_store == THUMB_LOAD
10260 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10261 else
10262 inst.instruction = (load_store == THUMB_LOAD
10263 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10264
10265 inst.instruction |= Rd | (Rb << 3);
10266
10267 if (inst.reloc.exp.X_op == O_constant)
10268 {
10269 unsigned offset = inst.reloc.exp.X_add_number;
10270
10271 if (offset & ~(0x1f << size))
10272 {
f03698e6 10273 inst.error = _("invalid offset");
b99bd4ef
NC
10274 return;
10275 }
10276 inst.instruction |= (offset >> size) << 6;
10277 }
10278 else
10279 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10280 }
10281 else
10282 {
10283 /* Register offset. */
10284 if (size == THUMB_WORD)
10285 inst.instruction = (load_store == THUMB_LOAD
10286 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10287 else if (size == THUMB_HALFWORD)
10288 inst.instruction = (load_store == THUMB_LOAD
10289 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10290 else
10291 inst.instruction = (load_store == THUMB_LOAD
10292 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10293
10294 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10295 }
10296
10297 end_of_line (str);
10298}
10299
404ff6b5
AH
10300/* A register must be given at this point.
10301
404ff6b5
AH
10302 Shift is the place to put it in inst.instruction.
10303
404ff6b5
AH
10304 Restores input start point on err.
10305 Returns the reg#, or FAIL. */
10306
10307static int
63e63b07 10308mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10309 char ** str;
10310 int shift;
6c43fab6 10311 enum arm_reg_type regtype;
404ff6b5 10312{
6c43fab6
RE
10313 int reg;
10314 char *start = *str;
404ff6b5 10315
6c43fab6 10316 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10317 {
404ff6b5
AH
10318 if (shift >= 0)
10319 inst.instruction |= reg << shift;
10320
6c43fab6 10321 return reg;
404ff6b5
AH
10322 }
10323
6c43fab6 10324 /* Restore the start point. */
404ff6b5 10325 *str = start;
cc8a6dd0 10326
404ff6b5
AH
10327 /* In the few cases where we might be able to accept something else
10328 this error can be overridden. */
6c43fab6 10329 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10330
404ff6b5
AH
10331 return FAIL;
10332}
10333
63e63b07 10334/* Cirrus Maverick Instructions. */
404ff6b5
AH
10335
10336/* Wrapper functions. */
10337
10338static void
63e63b07 10339do_mav_binops_1a (str)
6c43fab6
RE
10340 char * str;
10341{
63e63b07 10342 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10343}
10344
10345static void
63e63b07 10346do_mav_binops_1b (str)
6c43fab6
RE
10347 char * str;
10348{
63e63b07 10349 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10350}
10351
10352static void
63e63b07 10353do_mav_binops_1c (str)
404ff6b5 10354 char * str;
404ff6b5 10355{
63e63b07 10356 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10357}
10358
10359static void
63e63b07 10360do_mav_binops_1d (str)
404ff6b5 10361 char * str;
404ff6b5 10362{
63e63b07 10363 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10364}
10365
10366static void
63e63b07 10367do_mav_binops_1e (str)
404ff6b5 10368 char * str;
404ff6b5 10369{
63e63b07 10370 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10371}
10372
10373static void
63e63b07 10374do_mav_binops_1f (str)
404ff6b5 10375 char * str;
404ff6b5 10376{
63e63b07 10377 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10378}
10379
10380static void
63e63b07 10381do_mav_binops_1g (str)
404ff6b5 10382 char * str;
404ff6b5 10383{
63e63b07 10384 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10385}
10386
10387static void
63e63b07 10388do_mav_binops_1h (str)
404ff6b5 10389 char * str;
404ff6b5 10390{
63e63b07 10391 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10392}
10393
6c43fab6 10394static void
63e63b07 10395do_mav_binops_1i (str)
6c43fab6
RE
10396 char * str;
10397{
63e63b07 10398 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10399}
10400
10401static void
63e63b07 10402do_mav_binops_1j (str)
6c43fab6
RE
10403 char * str;
10404{
63e63b07 10405 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10406}
10407
10408static void
63e63b07 10409do_mav_binops_1k (str)
6c43fab6
RE
10410 char * str;
10411{
63e63b07 10412 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10413}
10414
10415static void
63e63b07 10416do_mav_binops_1l (str)
6c43fab6
RE
10417 char * str;
10418{
63e63b07 10419 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10420}
10421
10422static void
63e63b07 10423do_mav_binops_1m (str)
6c43fab6
RE
10424 char * str;
10425{
63e63b07 10426 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10427}
10428
10429static void
63e63b07 10430do_mav_binops_1n (str)
6c43fab6
RE
10431 char * str;
10432{
63e63b07 10433 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10434}
10435
10436static void
63e63b07 10437do_mav_binops_1o (str)
6c43fab6
RE
10438 char * str;
10439{
63e63b07 10440 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10441}
10442
10443static void
63e63b07 10444do_mav_binops_2a (str)
6c43fab6
RE
10445 char * str;
10446{
63e63b07 10447 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10448}
10449
10450static void
63e63b07 10451do_mav_binops_2b (str)
6c43fab6
RE
10452 char * str;
10453{
63e63b07 10454 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10455}
10456
10457static void
63e63b07 10458do_mav_binops_2c (str)
6c43fab6
RE
10459 char * str;
10460{
63e63b07 10461 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10462}
10463
10464static void
63e63b07 10465do_mav_binops_3a (str)
6c43fab6
RE
10466 char * str;
10467{
63e63b07 10468 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10469}
10470
10471static void
63e63b07 10472do_mav_binops_3b (str)
6c43fab6
RE
10473 char * str;
10474{
63e63b07 10475 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10476}
10477
10478static void
63e63b07 10479do_mav_binops_3c (str)
6c43fab6
RE
10480 char * str;
10481{
63e63b07 10482 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10483}
10484
10485static void
63e63b07 10486do_mav_binops_3d (str)
6c43fab6
RE
10487 char * str;
10488{
63e63b07 10489 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10490}
10491
10492static void
63e63b07 10493do_mav_triple_4a (str)
6c43fab6
RE
10494 char * str;
10495{
63e63b07 10496 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10497}
10498
10499static void
63e63b07 10500do_mav_triple_4b (str)
6c43fab6
RE
10501 char * str;
10502{
63e63b07 10503 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10504}
10505
10506static void
63e63b07 10507do_mav_triple_5a (str)
6c43fab6
RE
10508 char * str;
10509{
63e63b07 10510 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10511}
10512
10513static void
63e63b07 10514do_mav_triple_5b (str)
6c43fab6
RE
10515 char * str;
10516{
63e63b07 10517 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10518}
10519
10520static void
63e63b07 10521do_mav_triple_5c (str)
6c43fab6
RE
10522 char * str;
10523{
63e63b07 10524 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10525}
10526
10527static void
63e63b07 10528do_mav_triple_5d (str)
6c43fab6
RE
10529 char * str;
10530{
63e63b07 10531 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10532}
10533
10534static void
63e63b07 10535do_mav_triple_5e (str)
6c43fab6
RE
10536 char * str;
10537{
63e63b07 10538 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10539}
10540
10541static void
63e63b07 10542do_mav_triple_5f (str)
6c43fab6
RE
10543 char * str;
10544{
63e63b07 10545 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10546}
10547
10548static void
63e63b07 10549do_mav_triple_5g (str)
6c43fab6
RE
10550 char * str;
10551{
63e63b07 10552 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10553}
10554
10555static void
63e63b07 10556do_mav_triple_5h (str)
6c43fab6
RE
10557 char * str;
10558{
63e63b07 10559 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10560}
10561
10562static void
63e63b07 10563do_mav_quad_6a (str)
6c43fab6
RE
10564 char * str;
10565{
63e63b07 10566 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10567 REG_TYPE_MVFX);
10568}
10569
10570static void
63e63b07 10571do_mav_quad_6b (str)
6c43fab6
RE
10572 char * str;
10573{
63e63b07 10574 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10575 REG_TYPE_MVFX);
10576}
10577
cc8a6dd0 10578/* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
404ff6b5 10579static void
63e63b07 10580do_mav_dspsc_1 (str)
404ff6b5 10581 char * str;
404ff6b5 10582{
6c43fab6
RE
10583 skip_whitespace (str);
10584
10585 /* cfmvsc32. */
63e63b07 10586 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10587 || skip_past_comma (&str) == FAIL
63e63b07 10588 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
6c43fab6
RE
10589 {
10590 if (!inst.error)
10591 inst.error = BAD_ARGS;
10592
10593 return;
10594 }
10595
10596 end_of_line (str);
404ff6b5
AH
10597}
10598
6c43fab6 10599/* cfmv32sc<cond> MVFX[15:0],DSPSC. */
404ff6b5 10600static void
63e63b07 10601do_mav_dspsc_2 (str)
404ff6b5 10602 char * str;
404ff6b5 10603{
6c43fab6
RE
10604 skip_whitespace (str);
10605
10606 /* cfmv32sc. */
63e63b07 10607 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
6c43fab6 10608 || skip_past_comma (&str) == FAIL
63e63b07 10609 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10610 {
10611 if (!inst.error)
10612 inst.error = BAD_ARGS;
10613
10614 return;
10615 }
10616
10617 end_of_line (str);
404ff6b5
AH
10618}
10619
10620static void
63e63b07 10621do_mav_shift_1 (str)
404ff6b5 10622 char * str;
404ff6b5 10623{
63e63b07 10624 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10625}
10626
10627static void
63e63b07 10628do_mav_shift_2 (str)
404ff6b5 10629 char * str;
404ff6b5 10630{
63e63b07 10631 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10632}
10633
10634static void
63e63b07 10635do_mav_ldst_1 (str)
404ff6b5 10636 char * str;
404ff6b5 10637{
63e63b07 10638 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10639}
10640
10641static void
63e63b07 10642do_mav_ldst_2 (str)
404ff6b5 10643 char * str;
404ff6b5 10644{
63e63b07 10645 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10646}
10647
10648static void
63e63b07 10649do_mav_ldst_3 (str)
404ff6b5 10650 char * str;
404ff6b5 10651{
63e63b07 10652 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10653}
10654
10655static void
63e63b07 10656do_mav_ldst_4 (str)
404ff6b5 10657 char * str;
404ff6b5 10658{
63e63b07 10659 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10660}
10661
10662/* Isnsn like "foo X,Y". */
10663
10664static void
63e63b07 10665do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10666 char * str;
404ff6b5 10667 int mode;
6c43fab6
RE
10668 enum arm_reg_type reg0;
10669 enum arm_reg_type reg1;
404ff6b5 10670{
6c43fab6 10671 int shift0, shift1;
404ff6b5 10672
6c43fab6
RE
10673 shift0 = mode & 0xff;
10674 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10675
10676 skip_whitespace (str);
10677
63e63b07 10678 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10679 || skip_past_comma (&str) == FAIL
63e63b07 10680 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10681 {
10682 if (!inst.error)
10683 inst.error = BAD_ARGS;
10684 }
10685 else
10686 end_of_line (str);
404ff6b5
AH
10687}
10688
10689/* Isnsn like "foo X,Y,Z". */
10690
10691static void
63e63b07 10692do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10693 char * str;
404ff6b5 10694 int mode;
6c43fab6
RE
10695 enum arm_reg_type reg0;
10696 enum arm_reg_type reg1;
10697 enum arm_reg_type reg2;
404ff6b5 10698{
6c43fab6 10699 int shift0, shift1, shift2;
404ff6b5 10700
6c43fab6
RE
10701 shift0 = mode & 0xff;
10702 shift1 = (mode >> 8) & 0xff;
10703 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10704
10705 skip_whitespace (str);
10706
63e63b07 10707 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10708 || skip_past_comma (&str) == FAIL
63e63b07 10709 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10710 || skip_past_comma (&str) == FAIL
63e63b07 10711 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10712 {
10713 if (!inst.error)
10714 inst.error = BAD_ARGS;
10715 }
10716 else
10717 end_of_line (str);
404ff6b5
AH
10718}
10719
10720/* Isnsn like "foo W,X,Y,Z".
10721 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10722
10723static void
63e63b07 10724do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10725 char * str;
404ff6b5 10726 int mode;
6c43fab6
RE
10727 enum arm_reg_type reg0;
10728 enum arm_reg_type reg1;
10729 enum arm_reg_type reg2;
10730 enum arm_reg_type reg3;
404ff6b5 10731{
6c43fab6 10732 int shift0, shift1, shift2, shift3;
404ff6b5 10733
6c43fab6
RE
10734 shift0= mode & 0xff;
10735 shift1 = (mode >> 8) & 0xff;
10736 shift2 = (mode >> 16) & 0xff;
10737 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10738
10739 skip_whitespace (str);
10740
63e63b07 10741 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10742 || skip_past_comma (&str) == FAIL
63e63b07 10743 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10744 || skip_past_comma (&str) == FAIL
63e63b07 10745 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10746 || skip_past_comma (&str) == FAIL
63e63b07 10747 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10748 {
10749 if (!inst.error)
10750 inst.error = BAD_ARGS;
10751 }
10752 else
10753 end_of_line (str);
404ff6b5
AH
10754}
10755
63e63b07 10756/* Maverick shift immediate instructions.
404ff6b5
AH
10757 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10758 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10759
10760static void
63e63b07 10761do_mav_shift (str, reg0, reg1)
404ff6b5 10762 char * str;
6c43fab6
RE
10763 enum arm_reg_type reg0;
10764 enum arm_reg_type reg1;
404ff6b5
AH
10765{
10766 int error;
10767 int imm, neg = 0;
10768
10769 skip_whitespace (str);
10770
10771 error = 0;
10772
63e63b07 10773 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10774 || skip_past_comma (&str) == FAIL
63e63b07 10775 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10776 || skip_past_comma (&str) == FAIL)
10777 {
10778 if (!inst.error)
10779 inst.error = BAD_ARGS;
10780 return;
10781 }
10782
10783 /* Calculate the immediate operand.
10784 The operand is a 7bit signed number. */
10785 skip_whitespace (str);
10786
10787 if (*str == '#')
10788 ++str;
10789
8420dfca 10790 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10791 {
10792 inst.error = _("expecting immediate, 7bit operand");
10793 return;
10794 }
10795
10796 if (*str == '-')
10797 {
10798 neg = 1;
10799 ++str;
10800 }
10801
8420dfca 10802 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10803 imm = imm * 10 + *str - '0';
10804
10805 if (imm > 64)
10806 {
10807 inst.error = _("immediate out of range");
10808 return;
10809 }
10810
10811 /* Make negative imm's into 7bit signed numbers. */
10812 if (neg)
10813 {
10814 imm = -imm;
10815 imm &= 0x0000007f;
10816 }
10817
10818 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10819 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10820 Bit 4 should be 0. */
10821 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10822
10823 inst.instruction |= imm;
404ff6b5 10824 end_of_line (str);
404ff6b5
AH
10825}
10826
10827static int
63e63b07 10828mav_parse_offset (str, negative)
404ff6b5
AH
10829 char ** str;
10830 int *negative;
10831{
10832 char * p = *str;
10833 int offset;
10834
10835 *negative = 0;
10836
10837 skip_whitespace (p);
10838
10839 if (*p == '#')
10840 ++p;
10841
10842 if (*p == '-')
10843 {
10844 *negative = 1;
10845 ++p;
10846 }
10847
8420dfca 10848 if (!ISDIGIT (*p))
404ff6b5
AH
10849 {
10850 inst.error = _("offset expected");
10851 return 0;
10852 }
10853
8420dfca 10854 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10855 offset = offset * 10 + *p - '0';
10856
10857 if (offset > 0xff)
10858 {
10859 inst.error = _("offset out of range");
10860 return 0;
10861 }
10862
10863 *str = p;
10864
10865 return *negative ? -offset : offset;
10866}
10867
63e63b07 10868/* Maverick load/store instructions.
404ff6b5
AH
10869 <insn><cond> CRd,[Rn,<offset>]{!}.
10870 <insn><cond> CRd,[Rn],<offset>. */
10871
10872static void
63e63b07 10873do_mav_ldst (str, reg0)
404ff6b5 10874 char * str;
6c43fab6 10875 enum arm_reg_type reg0;
404ff6b5
AH
10876{
10877 int offset, negative;
404ff6b5
AH
10878
10879 skip_whitespace (str);
10880
63e63b07 10881 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10882 || skip_past_comma (&str) == FAIL
404ff6b5 10883 || *str++ != '['
6c43fab6 10884 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10885 goto fail_ldst;
10886
6c43fab6 10887 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10888 {
10889 /* You are here: "<offset>]{!}". */
10890 inst.instruction |= PRE_INDEX;
10891
63e63b07 10892 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10893
10894 if (inst.error)
10895 return;
10896
10897 if (*str++ != ']')
10898 {
10899 inst.error = _("missing ]");
10900 return;
10901 }
10902
10903 if (*str == '!')
10904 {
10905 inst.instruction |= WRITE_BACK;
10906 ++str;
10907 }
10908 }
10909 else
10910 {
10911 /* You are here: "], <offset>". */
10912 if (*str++ != ']')
10913 {
10914 inst.error = _("missing ]");
10915 return;
10916 }
10917
10918 if (skip_past_comma (&str) == FAIL
63e63b07 10919 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10920 goto fail_ldst;
10921
10922 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10923 }
10924
10925 if (negative)
10926 offset = -offset;
10927 else
2d2255b5 10928 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10929
10930 inst.instruction |= offset >> 2;
404ff6b5
AH
10931 end_of_line (str);
10932 return;
10933
10934fail_ldst:
10935 if (!inst.error)
10936 inst.error = BAD_ARGS;
404ff6b5
AH
10937}
10938
b99bd4ef
NC
10939static void
10940do_t_nop (str)
10941 char * str;
10942{
10943 /* Do nothing. */
10944 end_of_line (str);
b99bd4ef
NC
10945}
10946
10947/* Handle the Format 4 instructions that do not have equivalents in other
10948 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10949 BIC and MVN. */
10950
10951static void
10952do_t_arit (str)
10953 char * str;
10954{
10955 int Rd, Rs, Rn;
10956
10957 skip_whitespace (str);
10958
10959 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10960 || skip_past_comma (&str) == FAIL
10961 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10962 {
10963 inst.error = BAD_ARGS;
10964 return;
10965 }
10966
10967 if (skip_past_comma (&str) != FAIL)
10968 {
10969 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10970 (It isn't allowed for CMP either, but that isn't handled by this
10971 function.) */
10972 if (inst.instruction == T_OPCODE_TST
10973 || inst.instruction == T_OPCODE_CMN
10974 || inst.instruction == T_OPCODE_NEG
10975 || inst.instruction == T_OPCODE_MVN)
10976 {
10977 inst.error = BAD_ARGS;
10978 return;
10979 }
10980
10981 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10982 return;
10983
10984 if (Rs != Rd)
10985 {
10986 inst.error = _("dest and source1 must be the same register");
10987 return;
10988 }
10989 Rs = Rn;
10990 }
10991
10992 if (inst.instruction == T_OPCODE_MUL
10993 && Rs == Rd)
10994 as_tsktsk (_("Rs and Rd must be different in MUL"));
10995
10996 inst.instruction |= Rd | (Rs << 3);
10997 end_of_line (str);
10998}
10999
11000static void
11001do_t_add (str)
11002 char * str;
11003{
11004 thumb_add_sub (str, 0);
11005}
11006
11007static void
11008do_t_asr (str)
11009 char * str;
11010{
11011 thumb_shift (str, THUMB_ASR);
11012}
11013
11014static void
11015do_t_branch9 (str)
11016 char * str;
11017{
11018 if (my_get_expression (&inst.reloc.exp, &str))
11019 return;
11020 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11021 inst.reloc.pc_rel = 1;
11022 end_of_line (str);
11023}
11024
11025static void
11026do_t_branch12 (str)
11027 char * str;
11028{
11029 if (my_get_expression (&inst.reloc.exp, &str))
11030 return;
11031 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11032 inst.reloc.pc_rel = 1;
11033 end_of_line (str);
11034}
11035
11036/* Find the real, Thumb encoded start of a Thumb function. */
11037
11038static symbolS *
11039find_real_start (symbolP)
11040 symbolS * symbolP;
11041{
11042 char * real_start;
11043 const char * name = S_GET_NAME (symbolP);
11044 symbolS * new_target;
11045
2d2255b5 11046 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11047#define STUB_NAME ".real_start_of"
11048
11049 if (name == NULL)
11050 abort ();
11051
11052 /* Names that start with '.' are local labels, not function entry points.
11053 The compiler may generate BL instructions to these labels because it
11054 needs to perform a branch to a far away location. */
11055 if (name[0] == '.')
11056 return symbolP;
11057
11058 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11059 sprintf (real_start, "%s%s", STUB_NAME, name);
11060
11061 new_target = symbol_find (real_start);
11062
11063 if (new_target == NULL)
11064 {
11065 as_warn ("Failed to find real start of function: %s\n", name);
11066 new_target = symbolP;
11067 }
11068
11069 free (real_start);
11070
11071 return new_target;
11072}
11073
11074static void
11075do_t_branch23 (str)
11076 char * str;
11077{
11078 if (my_get_expression (& inst.reloc.exp, & str))
11079 return;
11080
11081 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11082 inst.reloc.pc_rel = 1;
11083 end_of_line (str);
11084
11085 /* If the destination of the branch is a defined symbol which does not have
11086 the THUMB_FUNC attribute, then we must be calling a function which has
11087 the (interfacearm) attribute. We look for the Thumb entry point to that
11088 function and change the branch to refer to that function instead. */
11089 if ( inst.reloc.exp.X_op == O_symbol
11090 && inst.reloc.exp.X_add_symbol != NULL
11091 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11092 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11093 inst.reloc.exp.X_add_symbol =
11094 find_real_start (inst.reloc.exp.X_add_symbol);
11095}
11096
11097static void
11098do_t_bx (str)
11099 char * str;
11100{
11101 int reg;
11102
11103 skip_whitespace (str);
11104
11105 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11106 return;
11107
11108 /* This sets THUMB_H2 from the top bit of reg. */
11109 inst.instruction |= reg << 3;
11110
11111 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11112 should cause the alignment to be checked once it is known. This is
11113 because BX PC only works if the instruction is word aligned. */
11114
11115 end_of_line (str);
11116}
11117
11118static void
11119do_t_compare (str)
11120 char * str;
11121{
11122 thumb_mov_compare (str, THUMB_COMPARE);
11123}
11124
11125static void
11126do_t_ldmstm (str)
11127 char * str;
11128{
11129 int Rb;
11130 long range;
11131
11132 skip_whitespace (str);
11133
11134 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11135 return;
11136
11137 if (*str != '!')
f03698e6 11138 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11139 else
11140 str++;
11141
11142 if (skip_past_comma (&str) == FAIL
11143 || (range = reg_list (&str)) == FAIL)
11144 {
11145 if (! inst.error)
11146 inst.error = BAD_ARGS;
11147 return;
11148 }
11149
11150 if (inst.reloc.type != BFD_RELOC_NONE)
11151 {
11152 /* This really doesn't seem worth it. */
11153 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11154 inst.error = _("expression too complex");
b99bd4ef
NC
11155 return;
11156 }
11157
11158 if (range & ~0xff)
11159 {
11160 inst.error = _("only lo-regs valid in load/store multiple");
11161 return;
11162 }
11163
11164 inst.instruction |= (Rb << 8) | range;
11165 end_of_line (str);
11166}
11167
11168static void
11169do_t_ldr (str)
11170 char * str;
11171{
11172 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11173}
11174
11175static void
11176do_t_ldrb (str)
11177 char * str;
11178{
11179 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11180}
11181
11182static void
11183do_t_ldrh (str)
11184 char * str;
11185{
11186 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11187}
11188
11189static void
11190do_t_lds (str)
11191 char * str;
11192{
11193 int Rd, Rb, Ro;
11194
11195 skip_whitespace (str);
11196
11197 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11198 || skip_past_comma (&str) == FAIL
11199 || *str++ != '['
11200 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11201 || skip_past_comma (&str) == FAIL
11202 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11203 || *str++ != ']')
11204 {
11205 if (! inst.error)
f03698e6 11206 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11207 return;
11208 }
11209
11210 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11211 end_of_line (str);
11212}
11213
11214static void
11215do_t_lsl (str)
11216 char * str;
11217{
11218 thumb_shift (str, THUMB_LSL);
11219}
11220
11221static void
11222do_t_lsr (str)
11223 char * str;
11224{
11225 thumb_shift (str, THUMB_LSR);
11226}
11227
11228static void
11229do_t_mov (str)
11230 char * str;
11231{
11232 thumb_mov_compare (str, THUMB_MOVE);
11233}
11234
11235static void
11236do_t_push_pop (str)
11237 char * str;
11238{
11239 long range;
11240
11241 skip_whitespace (str);
11242
11243 if ((range = reg_list (&str)) == FAIL)
11244 {
11245 if (! inst.error)
11246 inst.error = BAD_ARGS;
11247 return;
11248 }
11249
11250 if (inst.reloc.type != BFD_RELOC_NONE)
11251 {
11252 /* This really doesn't seem worth it. */
11253 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11254 inst.error = _("expression too complex");
b99bd4ef
NC
11255 return;
11256 }
11257
11258 if (range & ~0xff)
11259 {
11260 if ((inst.instruction == T_OPCODE_PUSH
11261 && (range & ~0xff) == 1 << REG_LR)
11262 || (inst.instruction == T_OPCODE_POP
11263 && (range & ~0xff) == 1 << REG_PC))
11264 {
11265 inst.instruction |= THUMB_PP_PC_LR;
11266 range &= 0xff;
11267 }
11268 else
11269 {
11270 inst.error = _("invalid register list to push/pop instruction");
11271 return;
11272 }
11273 }
11274
11275 inst.instruction |= range;
11276 end_of_line (str);
11277}
11278
11279static void
11280do_t_str (str)
11281 char * str;
11282{
11283 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11284}
11285
11286static void
11287do_t_strb (str)
11288 char * str;
11289{
11290 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11291}
11292
11293static void
11294do_t_strh (str)
11295 char * str;
11296{
11297 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11298}
11299
11300static void
11301do_t_sub (str)
11302 char * str;
11303{
11304 thumb_add_sub (str, 1);
11305}
11306
11307static void
11308do_t_swi (str)
11309 char * str;
11310{
11311 skip_whitespace (str);
11312
11313 if (my_get_expression (&inst.reloc.exp, &str))
11314 return;
11315
11316 inst.reloc.type = BFD_RELOC_ARM_SWI;
11317 end_of_line (str);
b99bd4ef
NC
11318}
11319
11320static void
11321do_t_adr (str)
11322 char * str;
11323{
11324 int reg;
11325
11326 /* This is a pseudo-op of the form "adr rd, label" to be converted
11327 into a relative address of the form "add rd, pc, #label-.-4". */
11328 skip_whitespace (str);
11329
11330 /* Store Rd in temporary location inside instruction. */
11331 if ((reg = reg_required_here (&str, 4)) == FAIL
11332 || (reg > 7) /* For Thumb reg must be r0..r7. */
11333 || skip_past_comma (&str) == FAIL
11334 || my_get_expression (&inst.reloc.exp, &str))
11335 {
11336 if (!inst.error)
11337 inst.error = BAD_ARGS;
11338 return;
11339 }
11340
11341 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11342 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11343 inst.reloc.pc_rel = 1;
11344 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11345
11346 end_of_line (str);
11347}
11348
11349static void
6c43fab6
RE
11350insert_reg (r, htab)
11351 const struct reg_entry *r;
11352 struct hash_control *htab;
b99bd4ef 11353{
6c43fab6 11354 int len = strlen (r->name) + 2;
b99bd4ef
NC
11355 char * buf = (char *) xmalloc (len);
11356 char * buf2 = (char *) xmalloc (len);
11357 int i = 0;
11358
11359#ifdef REGISTER_PREFIX
11360 buf[i++] = REGISTER_PREFIX;
11361#endif
11362
6c43fab6 11363 strcpy (buf + i, r->name);
b99bd4ef
NC
11364
11365 for (i = 0; buf[i]; i++)
3882b010 11366 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11367
11368 buf2[i] = '\0';
11369
6c43fab6
RE
11370 hash_insert (htab, buf, (PTR) r);
11371 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11372}
11373
11374static void
6c43fab6
RE
11375build_reg_hsh (map)
11376 struct reg_map *map;
11377{
11378 const struct reg_entry *r;
11379
11380 if ((map->htab = hash_new ()) == NULL)
f03698e6 11381 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11382
11383 for (r = map->names; r->name != NULL; r++)
11384 insert_reg (r, map->htab);
11385}
11386
11387static void
11388insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11389 char *str;
11390 int regnum;
6c43fab6 11391 struct hash_control *htab;
b99bd4ef 11392{
0bbf2aa4
NC
11393 const char *error;
11394 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11395 const char *name = xmalloc (strlen (str) + 1);
11396
11397 strcpy ((char *) name, str);
11398
b99bd4ef
NC
11399 new->name = name;
11400 new->number = regnum;
0bbf2aa4 11401 new->builtin = FALSE;
b99bd4ef 11402
0bbf2aa4
NC
11403 error = hash_insert (htab, name, (PTR) new);
11404 if (error)
11405 {
11406 as_bad (_("failed to create an alias for %s, reason: %s"),
11407 str, error);
11408 free ((char *) name);
11409 free (new);
11410 }
b99bd4ef
NC
11411}
11412
6c43fab6
RE
11413/* Look for the .req directive. This is of the form:
11414
0bbf2aa4 11415 new_register_name .req existing_register_name
6c43fab6
RE
11416
11417 If we find one, or if it looks sufficiently like one that we want to
11418 handle any error here, return non-zero. Otherwise return zero. */
11419static int
11420create_register_alias (newname, p)
11421 char *newname;
11422 char *p;
11423{
11424 char *q;
11425 char c;
11426
11427 q = p;
11428 skip_whitespace (q);
11429
11430 c = *p;
11431 *p = '\0';
11432
11433 if (*q && !strncmp (q, ".req ", 5))
11434 {
11435 char *copy_of_str;
11436 char *r;
11437
11438#ifdef IGNORE_OPCODE_CASE
11439 newname = original_case_string;
11440#endif
11441 copy_of_str = newname;
11442
11443 q += 4;
11444 skip_whitespace (q);
11445
11446 for (r = q; *r != '\0'; r++)
11447 if (*r == ' ')
11448 break;
11449
11450 if (r != q)
11451 {
11452 enum arm_reg_type new_type, old_type;
11453 int old_regno;
11454 char d = *r;
11455
11456 *r = '\0';
11457 old_type = arm_reg_parse_any (q);
11458 *r = d;
11459
11460 new_type = arm_reg_parse_any (newname);
11461
11462 if (new_type == REG_TYPE_MAX)
11463 {
11464 if (old_type != REG_TYPE_MAX)
11465 {
11466 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11467 insert_reg_alias (newname, old_regno,
11468 all_reg_maps[old_type].htab);
11469 }
11470 else
11471 as_warn (_("register '%s' does not exist\n"), q);
11472 }
11473 else if (old_type == REG_TYPE_MAX)
11474 {
11475 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11476 copy_of_str, q);
11477 }
11478 else
11479 {
11480 /* Do not warn about redefinitions to the same alias. */
11481 if (new_type != old_type
11482 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11483 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11484 as_warn (_("ignoring redefinition of register alias '%s'"),
11485 copy_of_str);
11486
11487 }
11488 }
11489 else
11490 as_warn (_("ignoring incomplete .req pseuso op"));
11491
11492 *p = c;
11493 return 1;
11494 }
0bbf2aa4 11495
6c43fab6
RE
11496 *p = c;
11497 return 0;
11498}
cc8a6dd0 11499
b99bd4ef
NC
11500static void
11501set_constant_flonums ()
11502{
11503 int i;
11504
11505 for (i = 0; i < NUM_FLOAT_VALS; i++)
11506 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11507 abort ();
11508}
11509
90e4755a
RE
11510/* Iterate over the base tables to create the instruction patterns. */
11511static void
11512build_arm_ops_hsh ()
11513{
11514 unsigned int i;
11515 unsigned int j;
11516 static struct obstack insn_obstack;
11517
11518 obstack_begin (&insn_obstack, 4000);
11519
11520 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11521 {
6c43fab6 11522 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11523
11524 if (insn->cond_offset != 0)
11525 {
11526 /* Insn supports conditional execution. Build the varaints
11527 and insert them in the hash table. */
11528 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11529 {
11530 unsigned len = strlen (insn->template);
11531 struct asm_opcode *new;
11532 char *template;
11533
11534 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11535 /* All condition codes are two characters. */
11536 template = obstack_alloc (&insn_obstack, len + 3);
11537
11538 strncpy (template, insn->template, insn->cond_offset);
11539 strcpy (template + insn->cond_offset, conds[j].template);
11540 if (len > insn->cond_offset)
11541 strcpy (template + insn->cond_offset + 2,
11542 insn->template + insn->cond_offset);
11543 new->template = template;
11544 new->cond_offset = 0;
11545 new->variant = insn->variant;
11546 new->parms = insn->parms;
11547 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11548
11549 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11550 }
11551 }
11552 /* Finally, insert the unconditional insn in the table directly;
11553 no need to build a copy. */
11554 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11555 }
11556}
11557
0bbf2aa4 11558#if 0 /* Suppressed - for now. */
5a6c6817
NC
11559#if defined OBJ_ELF || defined OBJ_COFF
11560
11561#ifdef OBJ_ELF
11562#define arm_Note Elf_External_Note
11563#else
11564typedef struct
11565{
11566 unsigned char namesz[4]; /* Size of entry's owner string. */
11567 unsigned char descsz[4]; /* Size of the note descriptor. */
11568 unsigned char type[4]; /* Interpretation of the descriptor. */
11569 char name[1]; /* Start of the name+desc data. */
11570} arm_Note;
11571#endif
11572
11573/* The description is kept to a fix sized in order to make updating
11574 it and merging it easier. */
11575#define ARM_NOTE_DESCRIPTION_LENGTH 8
11576
11577static void
11578arm_add_note (name, description, type)
11579 const char * name;
11580 const char * description;
11581 unsigned int type;
11582{
11583 arm_Note note ATTRIBUTE_UNUSED;
11584 char * p;
11585 unsigned int name_len;
11586
11587 name_len = (strlen (name) + 1 + 3) & ~3;
11588
11589 p = frag_more (sizeof (note.namesz));
11590 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11591
11592 p = frag_more (sizeof (note.descsz));
11593 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11594
11595 p = frag_more (sizeof (note.type));
11596 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11597
11598 p = frag_more (name_len);
11599 strcpy (p, name);
11600
11601 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11602 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11603 frag_align (2, 0, 0);
11604}
11605#endif
0bbf2aa4 11606#endif
5a6c6817 11607
b99bd4ef
NC
11608void
11609md_begin ()
11610{
11611 unsigned mach;
11612 unsigned int i;
11613
11614 if ( (arm_ops_hsh = hash_new ()) == NULL
11615 || (arm_tops_hsh = hash_new ()) == NULL
11616 || (arm_cond_hsh = hash_new ()) == NULL
11617 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11618 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11619 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11620
90e4755a 11621 build_arm_ops_hsh ();
b99bd4ef
NC
11622 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11623 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11624 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11625 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11626 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11627 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11628 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11629 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11630
6c43fab6
RE
11631 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11632 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11633
11634 set_constant_flonums ();
11635
03b1477f
RE
11636 /* Set the cpu variant based on the command-line options. We prefer
11637 -mcpu= over -march= if both are set (as for GCC); and we prefer
11638 -mfpu= over any other way of setting the floating point unit.
11639 Use of legacy options with new options are faulted. */
11640 if (legacy_cpu != -1)
11641 {
11642 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11643 as_bad (_("use of old and new-style options to set CPU type"));
11644
11645 mcpu_cpu_opt = legacy_cpu;
11646 }
11647 else if (mcpu_cpu_opt == -1)
11648 mcpu_cpu_opt = march_cpu_opt;
11649
11650 if (legacy_fpu != -1)
11651 {
11652 if (mfpu_opt != -1)
11653 as_bad (_("use of old and new-style options to set FPU type"));
11654
11655 mfpu_opt = legacy_fpu;
11656 }
11657 else if (mfpu_opt == -1)
11658 {
39c2da32
RE
11659#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11660 /* Some environments specify a default FPU. If they don't, infer it
11661 from the processor. */
03b1477f
RE
11662 if (mcpu_fpu_opt != -1)
11663 mfpu_opt = mcpu_fpu_opt;
11664 else
11665 mfpu_opt = march_fpu_opt;
39c2da32
RE
11666#else
11667 mfpu_opt = FPU_DEFAULT;
11668#endif
03b1477f
RE
11669 }
11670
11671 if (mfpu_opt == -1)
11672 {
11673 if (mcpu_cpu_opt == -1)
11674 mfpu_opt = FPU_DEFAULT;
11675 else if (mcpu_cpu_opt & ARM_EXT_V5)
11676 mfpu_opt = FPU_ARCH_VFP_V2;
11677 else
11678 mfpu_opt = FPU_ARCH_FPA;
11679 }
11680
11681 if (mcpu_cpu_opt == -1)
11682 mcpu_cpu_opt = CPU_DEFAULT;
11683
11684 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11685
b99bd4ef
NC
11686#if defined OBJ_COFF || defined OBJ_ELF
11687 {
11688 unsigned int flags = 0;
11689
11690 /* Set the flags in the private structure. */
11691 if (uses_apcs_26) flags |= F_APCS26;
11692 if (support_interwork) flags |= F_INTERWORK;
11693 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11694 if (pic_code) flags |= F_PIC;
bfae80f2 11695 if ((cpu_variant & FPU_ANY) == FPU_NONE
33a392fb
PB
11696 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11697 {
11698 flags |= F_SOFT_FLOAT;
11699 }
11700 switch (mfloat_abi_opt)
11701 {
11702 case ARM_FLOAT_ABI_SOFT:
11703 case ARM_FLOAT_ABI_SOFTFP:
11704 flags |= F_SOFT_FLOAT;
11705 break;
11706
11707 case ARM_FLOAT_ABI_HARD:
11708 if (flags & F_SOFT_FLOAT)
11709 as_bad (_("hard-float conflicts with specified fpu"));
11710 break;
11711 }
03b1477f
RE
11712 /* Using VFP conventions (even if soft-float). */
11713 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11714
fde78edd 11715#if defined OBJ_ELF
33a392fb 11716 if (cpu_variant & FPU_ARCH_MAVERICK)
fde78edd 11717 flags |= EF_ARM_MAVERICK_FLOAT;
fde78edd 11718#endif
b99bd4ef
NC
11719
11720 bfd_set_private_flags (stdoutput, flags);
11721
11722 /* We have run out flags in the COFF header to encode the
11723 status of ATPCS support, so instead we create a dummy,
11724 empty, debug section called .arm.atpcs. */
11725 if (atpcs)
11726 {
11727 asection * sec;
11728
11729 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11730
11731 if (sec != NULL)
11732 {
11733 bfd_set_section_flags
11734 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11735 bfd_set_section_size (stdoutput, sec, 0);
11736 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11737 }
11738 }
11739 }
11740#endif
11741
11742 /* Record the CPU type as well. */
11743 switch (cpu_variant & ARM_CPU_MASK)
11744 {
11745 case ARM_2:
11746 mach = bfd_mach_arm_2;
11747 break;
11748
11749 case ARM_3: /* Also ARM_250. */
11750 mach = bfd_mach_arm_2a;
11751 break;
11752
b89dddec
RE
11753 case ARM_6: /* Also ARM_7. */
11754 mach = bfd_mach_arm_3;
11755 break;
11756
b99bd4ef 11757 default:
5a6c6817 11758 mach = bfd_mach_arm_unknown;
b99bd4ef 11759 break;
b99bd4ef
NC
11760 }
11761
11762 /* Catch special cases. */
e16bb312
NC
11763 if (cpu_variant & ARM_CEXT_IWMMXT)
11764 mach = bfd_mach_arm_iWMMXt;
11765 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11766 mach = bfd_mach_arm_XScale;
fde78edd
NC
11767 else if (cpu_variant & ARM_CEXT_MAVERICK)
11768 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11769 else if (cpu_variant & ARM_EXT_V5E)
11770 mach = bfd_mach_arm_5TE;
11771 else if (cpu_variant & ARM_EXT_V5)
11772 {
b89dddec 11773 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11774 mach = bfd_mach_arm_5T;
11775 else
11776 mach = bfd_mach_arm_5;
11777 }
b89dddec 11778 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11779 {
b89dddec 11780 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11781 mach = bfd_mach_arm_4T;
11782 else
11783 mach = bfd_mach_arm_4;
11784 }
b89dddec 11785 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11786 mach = bfd_mach_arm_3M;
11787
5a6c6817 11788#if 0 /* Suppressed - for now. */
e16bb312 11789#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11790
11791 /* Create a .note section to fully identify this arm binary. */
11792
11793#define NOTE_ARCH_STRING "arch: "
11794
11795#if defined OBJ_COFF && ! defined NT_VERSION
11796#define NT_VERSION 1
11797#define NT_ARCH 2
11798#endif
11799
e16bb312 11800 {
e16bb312
NC
11801 segT current_seg = now_seg;
11802 subsegT current_subseg = now_subseg;
11803 asection * arm_arch;
5a6c6817
NC
11804 const char * arch_string;
11805
e16bb312
NC
11806 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11807
11808#ifdef OBJ_COFF
11809 bfd_set_section_flags (stdoutput, arm_arch,
11810 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11811 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11812#else
11813 bfd_set_section_flags (stdoutput, arm_arch,
11814 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11815#endif
11816 arm_arch->output_section = arm_arch;
11817 subseg_set (arm_arch, 0);
e16bb312 11818
5a6c6817
NC
11819 switch (mach)
11820 {
11821 default:
11822 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11823 case bfd_mach_arm_2: arch_string = "armv2"; break;
11824 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11825 case bfd_mach_arm_3: arch_string = "armv3"; break;
11826 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11827 case bfd_mach_arm_4: arch_string = "armv4"; break;
11828 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11829 case bfd_mach_arm_5: arch_string = "armv5"; break;
11830 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11831 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11832 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11833 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11834 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11835 }
11836
11837 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11838
11839 subseg_set (current_seg, current_subseg);
11840 }
11841#endif
5a6c6817
NC
11842#endif /* Suppressed code. */
11843
b99bd4ef
NC
11844 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11845}
11846
11847/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11848 for use in the a.out file, and stores them in the array pointed to by buf.
11849 This knows about the endian-ness of the target machine and does
11850 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11851 2 (short) and 4 (long) Floating numbers are put out as a series of
11852 LITTLENUMS (shorts, here at least). */
11853
11854void
11855md_number_to_chars (buf, val, n)
11856 char * buf;
11857 valueT val;
11858 int n;
11859{
11860 if (target_big_endian)
11861 number_to_chars_bigendian (buf, val, n);
11862 else
11863 number_to_chars_littleendian (buf, val, n);
11864}
11865
11866static valueT
11867md_chars_to_number (buf, n)
11868 char * buf;
11869 int n;
11870{
11871 valueT result = 0;
11872 unsigned char * where = (unsigned char *) buf;
11873
11874 if (target_big_endian)
11875 {
11876 while (n--)
11877 {
11878 result <<= 8;
11879 result |= (*where++ & 255);
11880 }
11881 }
11882 else
11883 {
11884 while (n--)
11885 {
11886 result <<= 8;
11887 result |= (where[n] & 255);
11888 }
11889 }
11890
11891 return result;
11892}
11893
11894/* Turn a string in input_line_pointer into a floating point constant
11895 of type TYPE, and store the appropriate bytes in *LITP. The number
11896 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11897 returned, or NULL on OK.
11898
11899 Note that fp constants aren't represent in the normal way on the ARM.
11900 In big endian mode, things are as expected. However, in little endian
11901 mode fp constants are big-endian word-wise, and little-endian byte-wise
11902 within the words. For example, (double) 1.1 in big endian mode is
11903 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11904 the byte sequence 99 99 f1 3f 9a 99 99 99.
11905
11906 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11907
11908char *
11909md_atof (type, litP, sizeP)
11910 char type;
11911 char * litP;
11912 int * sizeP;
11913{
11914 int prec;
11915 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11916 char *t;
11917 int i;
11918
11919 switch (type)
11920 {
11921 case 'f':
11922 case 'F':
11923 case 's':
11924 case 'S':
11925 prec = 2;
11926 break;
11927
11928 case 'd':
11929 case 'D':
11930 case 'r':
11931 case 'R':
11932 prec = 4;
11933 break;
11934
11935 case 'x':
11936 case 'X':
11937 prec = 6;
11938 break;
11939
11940 case 'p':
11941 case 'P':
11942 prec = 6;
11943 break;
11944
11945 default:
11946 *sizeP = 0;
f03698e6 11947 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11948 }
11949
11950 t = atof_ieee (input_line_pointer, type, words);
11951 if (t)
11952 input_line_pointer = t;
11953 *sizeP = prec * 2;
11954
11955 if (target_big_endian)
11956 {
11957 for (i = 0; i < prec; i++)
11958 {
11959 md_number_to_chars (litP, (valueT) words[i], 2);
11960 litP += 2;
11961 }
11962 }
11963 else
11964 {
bfae80f2
RE
11965 if (cpu_variant & FPU_ARCH_VFP)
11966 for (i = prec - 1; i >= 0; i--)
11967 {
11968 md_number_to_chars (litP, (valueT) words[i], 2);
11969 litP += 2;
11970 }
11971 else
11972 /* For a 4 byte float the order of elements in `words' is 1 0.
11973 For an 8 byte float the order is 1 0 3 2. */
11974 for (i = 0; i < prec; i += 2)
11975 {
11976 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11977 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11978 litP += 4;
11979 }
b99bd4ef
NC
11980 }
11981
11982 return 0;
11983}
11984
11985/* The knowledge of the PC's pipeline offset is built into the insns
11986 themselves. */
11987
11988long
11989md_pcrel_from (fixP)
11990 fixS * fixP;
11991{
11992 if (fixP->fx_addsy
11993 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11994 && fixP->fx_subsy == NULL)
11995 return 0;
11996
11997 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11998 {
11999 /* PC relative addressing on the Thumb is slightly odd
12000 as the bottom two bits of the PC are forced to zero
12001 for the calculation. */
12002 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12003 }
12004
12005#ifdef TE_WINCE
2d2255b5
KH
12006 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12007 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
12008 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12009#else
12010 return fixP->fx_where + fixP->fx_frag->fr_address;
12011#endif
12012}
12013
12014/* Round up a section size to the appropriate boundary. */
12015
12016valueT
12017md_section_align (segment, size)
12018 segT segment ATTRIBUTE_UNUSED;
12019 valueT size;
12020{
12021#ifdef OBJ_ELF
12022 return size;
12023#else
12024 /* Round all sects to multiple of 4. */
12025 return (size + 3) & ~3;
12026#endif
12027}
12028
12029/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12030 Otherwise we have no need to default values of symbols. */
12031
12032symbolS *
12033md_undefined_symbol (name)
12034 char * name ATTRIBUTE_UNUSED;
12035{
12036#ifdef OBJ_ELF
12037 if (name[0] == '_' && name[1] == 'G'
12038 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12039 {
12040 if (!GOT_symbol)
12041 {
12042 if (symbol_find (name))
12043 as_bad ("GOT already in the symbol table");
12044
12045 GOT_symbol = symbol_new (name, undefined_section,
12046 (valueT) 0, & zero_address_frag);
12047 }
12048
12049 return GOT_symbol;
12050 }
12051#endif
12052
12053 return 0;
12054}
12055
12056/* arm_reg_parse () := if it looks like a register, return its token and
12057 advance the pointer. */
12058
12059static int
6c43fab6 12060arm_reg_parse (ccp, htab)
b99bd4ef 12061 register char ** ccp;
6c43fab6 12062 struct hash_control *htab;
b99bd4ef
NC
12063{
12064 char * start = * ccp;
12065 char c;
12066 char * p;
12067 struct reg_entry * reg;
12068
12069#ifdef REGISTER_PREFIX
12070 if (*start != REGISTER_PREFIX)
12071 return FAIL;
12072 p = start + 1;
12073#else
12074 p = start;
12075#ifdef OPTIONAL_REGISTER_PREFIX
12076 if (*p == OPTIONAL_REGISTER_PREFIX)
12077 p++, start++;
12078#endif
12079#endif
3882b010 12080 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12081 return FAIL;
12082
12083 c = *p++;
3882b010 12084 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12085 c = *p++;
12086
12087 *--p = 0;
6c43fab6 12088 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12089 *p = c;
12090
12091 if (reg)
12092 {
12093 *ccp = p;
12094 return reg->number;
12095 }
12096
12097 return FAIL;
12098}
12099
6c43fab6
RE
12100/* Search for the following register name in each of the possible reg name
12101 tables. Return the classification if found, or REG_TYPE_MAX if not
12102 present. */
12103static enum arm_reg_type
12104arm_reg_parse_any (cp)
12105 char *cp;
12106{
12107 int i;
12108
12109 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12110 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12111 return (enum arm_reg_type) i;
12112
12113 return REG_TYPE_MAX;
12114}
12115
94f592af
NC
12116void
12117md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12118 fixS * fixP;
94f592af 12119 valueT * valP;
b99bd4ef
NC
12120 segT seg;
12121{
94f592af 12122 offsetT value = * valP;
b99bd4ef
NC
12123 offsetT newval;
12124 unsigned int newimm;
12125 unsigned long temp;
12126 int sign;
12127 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12128 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12129
12130 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12131
12132 /* Note whether this will delete the relocation. */
12133#if 0
12134 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12135 doesn't work fully.) */
12136 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12137 && !fixP->fx_pcrel)
12138#else
12139 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12140#endif
12141 fixP->fx_done = 1;
12142
12143 /* If this symbol is in a different section then we need to leave it for
12144 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12145 so we have to undo it's effects here. */
12146 if (fixP->fx_pcrel)
12147 {
12148 if (fixP->fx_addsy != NULL
12149 && S_IS_DEFINED (fixP->fx_addsy)
12150 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12151 {
12152 if (target_oabi
12153 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12154 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12155 ))
12156 value = 0;
12157 else
12158 value += md_pcrel_from (fixP);
12159 }
12160 }
12161
12162 /* Remember value for emit_reloc. */
12163 fixP->fx_addnumber = value;
12164
12165 switch (fixP->fx_r_type)
12166 {
12167 case BFD_RELOC_ARM_IMMEDIATE:
12168 newimm = validate_immediate (value);
12169 temp = md_chars_to_number (buf, INSN_SIZE);
12170
12171 /* If the instruction will fail, see if we can fix things up by
12172 changing the opcode. */
12173 if (newimm == (unsigned int) FAIL
12174 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12175 {
12176 as_bad_where (fixP->fx_file, fixP->fx_line,
12177 _("invalid constant (%lx) after fixup"),
12178 (unsigned long) value);
12179 break;
12180 }
12181
12182 newimm |= (temp & 0xfffff000);
12183 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
6189168b 12184 fixP->fx_done = 1;
b99bd4ef
NC
12185 break;
12186
12187 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12188 {
12189 unsigned int highpart = 0;
12190 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12191
b99bd4ef
NC
12192 newimm = validate_immediate (value);
12193 temp = md_chars_to_number (buf, INSN_SIZE);
12194
12195 /* If the instruction will fail, see if we can fix things up by
12196 changing the opcode. */
12197 if (newimm == (unsigned int) FAIL
12198 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12199 {
12200 /* No ? OK - try using two ADD instructions to generate
12201 the value. */
12202 newimm = validate_immediate_twopart (value, & highpart);
12203
12204 /* Yes - then make sure that the second instruction is
12205 also an add. */
12206 if (newimm != (unsigned int) FAIL)
12207 newinsn = temp;
12208 /* Still No ? Try using a negated value. */
12209 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12210 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12211 /* Otherwise - give up. */
12212 else
12213 {
12214 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12215 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12216 (long) value);
b99bd4ef
NC
12217 break;
12218 }
12219
12220 /* Replace the first operand in the 2nd instruction (which
12221 is the PC) with the destination register. We have
12222 already added in the PC in the first instruction and we
12223 do not want to do it again. */
12224 newinsn &= ~ 0xf0000;
12225 newinsn |= ((newinsn & 0x0f000) << 4);
12226 }
12227
12228 newimm |= (temp & 0xfffff000);
12229 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12230
12231 highpart |= (newinsn & 0xfffff000);
12232 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12233 }
12234 break;
12235
12236 case BFD_RELOC_ARM_OFFSET_IMM:
12237 sign = value >= 0;
12238
12239 if (value < 0)
12240 value = - value;
12241
12242 if (validate_offset_imm (value, 0) == FAIL)
12243 {
12244 as_bad_where (fixP->fx_file, fixP->fx_line,
12245 _("bad immediate value for offset (%ld)"),
12246 (long) value);
12247 break;
12248 }
12249
12250 newval = md_chars_to_number (buf, INSN_SIZE);
12251 newval &= 0xff7ff000;
12252 newval |= value | (sign ? INDEX_UP : 0);
12253 md_number_to_chars (buf, newval, INSN_SIZE);
12254 break;
12255
12256 case BFD_RELOC_ARM_OFFSET_IMM8:
12257 case BFD_RELOC_ARM_HWLITERAL:
12258 sign = value >= 0;
12259
12260 if (value < 0)
12261 value = - value;
12262
12263 if (validate_offset_imm (value, 1) == FAIL)
12264 {
12265 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12266 as_bad_where (fixP->fx_file, fixP->fx_line,
12267 _("invalid literal constant: pool needs to be closer"));
12268 else
12269 as_bad (_("bad immediate value for half-word offset (%ld)"),
12270 (long) value);
12271 break;
12272 }
12273
12274 newval = md_chars_to_number (buf, INSN_SIZE);
12275 newval &= 0xff7ff0f0;
12276 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12277 md_number_to_chars (buf, newval, INSN_SIZE);
12278 break;
12279
12280 case BFD_RELOC_ARM_LITERAL:
12281 sign = value >= 0;
12282
12283 if (value < 0)
12284 value = - value;
12285
12286 if (validate_offset_imm (value, 0) == FAIL)
12287 {
12288 as_bad_where (fixP->fx_file, fixP->fx_line,
12289 _("invalid literal constant: pool needs to be closer"));
12290 break;
12291 }
12292
12293 newval = md_chars_to_number (buf, INSN_SIZE);
12294 newval &= 0xff7ff000;
12295 newval |= value | (sign ? INDEX_UP : 0);
12296 md_number_to_chars (buf, newval, INSN_SIZE);
12297 break;
12298
12299 case BFD_RELOC_ARM_SHIFT_IMM:
12300 newval = md_chars_to_number (buf, INSN_SIZE);
12301 if (((unsigned long) value) > 32
12302 || (value == 32
12303 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12304 {
12305 as_bad_where (fixP->fx_file, fixP->fx_line,
12306 _("shift expression is too large"));
12307 break;
12308 }
12309
12310 if (value == 0)
12311 /* Shifts of zero must be done as lsl. */
12312 newval &= ~0x60;
12313 else if (value == 32)
12314 value = 0;
12315 newval &= 0xfffff07f;
12316 newval |= (value & 0x1f) << 7;
12317 md_number_to_chars (buf, newval, INSN_SIZE);
12318 break;
12319
12320 case BFD_RELOC_ARM_SWI:
12321 if (arm_data->thumb_mode)
12322 {
12323 if (((unsigned long) value) > 0xff)
12324 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12325 _("invalid swi expression"));
b99bd4ef
NC
12326 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12327 newval |= value;
12328 md_number_to_chars (buf, newval, THUMB_SIZE);
12329 }
12330 else
12331 {
12332 if (((unsigned long) value) > 0x00ffffff)
12333 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12334 _("invalid swi expression"));
b99bd4ef
NC
12335 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12336 newval |= value;
12337 md_number_to_chars (buf, newval, INSN_SIZE);
12338 }
12339 break;
12340
12341 case BFD_RELOC_ARM_MULTI:
12342 if (((unsigned long) value) > 0xffff)
12343 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12344 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12345 newval = value | md_chars_to_number (buf, INSN_SIZE);
12346 md_number_to_chars (buf, newval, INSN_SIZE);
12347 break;
12348
12349 case BFD_RELOC_ARM_PCREL_BRANCH:
12350 newval = md_chars_to_number (buf, INSN_SIZE);
12351
12352 /* Sign-extend a 24-bit number. */
12353#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12354
12355#ifdef OBJ_ELF
12356 if (! target_oabi)
12357 value = fixP->fx_offset;
12358#endif
12359
12360 /* We are going to store value (shifted right by two) in the
12361 instruction, in a 24 bit, signed field. Thus we need to check
12362 that none of the top 8 bits of the shifted value (top 7 bits of
12363 the unshifted, unsigned value) are set, or that they are all set. */
12364 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12365 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12366 {
12367#ifdef OBJ_ELF
12368 /* Normally we would be stuck at this point, since we cannot store
12369 the absolute address that is the destination of the branch in the
12370 24 bits of the branch instruction. If however, we happen to know
12371 that the destination of the branch is in the same section as the
2d2255b5 12372 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12373 ourselves and not have to bother the linker with it.
12374
12375 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12376 because I have not worked out how to do this for OBJ_COFF or
12377 target_oabi. */
12378 if (! target_oabi
12379 && fixP->fx_addsy != NULL
12380 && S_IS_DEFINED (fixP->fx_addsy)
12381 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12382 {
12383 /* Get pc relative value to go into the branch. */
94f592af 12384 value = * valP;
b99bd4ef
NC
12385
12386 /* Permit a backward branch provided that enough bits
12387 are set. Allow a forwards branch, provided that
12388 enough bits are clear. */
12389 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12390 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12391 fixP->fx_done = 1;
12392 }
12393
12394 if (! fixP->fx_done)
12395#endif
12396 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12397 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12398 }
12399
12400 value >>= 2;
12401 value += SEXT24 (newval);
12402
12403 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12404 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12405 as_bad_where (fixP->fx_file, fixP->fx_line,
12406 _("out of range branch"));
12407
12408 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12409 md_number_to_chars (buf, newval, INSN_SIZE);
12410 break;
12411
12412 case BFD_RELOC_ARM_PCREL_BLX:
12413 {
12414 offsetT hbit;
12415 newval = md_chars_to_number (buf, INSN_SIZE);
12416
12417#ifdef OBJ_ELF
12418 if (! target_oabi)
12419 value = fixP->fx_offset;
12420#endif
12421 hbit = (value >> 1) & 1;
12422 value = (value >> 2) & 0x00ffffff;
12423 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12424 newval = value | (newval & 0xfe000000) | (hbit << 24);
12425 md_number_to_chars (buf, newval, INSN_SIZE);
12426 }
12427 break;
12428
12429 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12430 newval = md_chars_to_number (buf, THUMB_SIZE);
12431 {
12432 addressT diff = (newval & 0xff) << 1;
12433 if (diff & 0x100)
12434 diff |= ~0xff;
12435
12436 value += diff;
12437 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12438 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12439 _("branch out of range"));
b99bd4ef
NC
12440 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12441 }
12442 md_number_to_chars (buf, newval, THUMB_SIZE);
12443 break;
12444
12445 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12446 newval = md_chars_to_number (buf, THUMB_SIZE);
12447 {
12448 addressT diff = (newval & 0x7ff) << 1;
12449 if (diff & 0x800)
12450 diff |= ~0x7ff;
12451
12452 value += diff;
12453 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12454 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12455 _("branch out of range"));
b99bd4ef
NC
12456 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12457 }
12458 md_number_to_chars (buf, newval, THUMB_SIZE);
12459 break;
12460
12461 case BFD_RELOC_THUMB_PCREL_BLX:
12462 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12463 {
12464 offsetT newval2;
12465 addressT diff;
12466
12467 newval = md_chars_to_number (buf, THUMB_SIZE);
12468 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12469 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12470 if (diff & 0x400000)
12471 diff |= ~0x3fffff;
12472#ifdef OBJ_ELF
12473 value = fixP->fx_offset;
12474#endif
12475 value += diff;
c62e1cc3 12476
b99bd4ef
NC
12477 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12478 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12479 _("branch with link out of range"));
b99bd4ef
NC
12480
12481 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12482 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12483 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12484 /* For a BLX instruction, make sure that the relocation is rounded up
12485 to a word boundary. This follows the semantics of the instruction
12486 which specifies that bit 1 of the target address will come from bit
12487 1 of the base address. */
12488 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12489 md_number_to_chars (buf, newval, THUMB_SIZE);
12490 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12491 }
12492 break;
12493
12494 case BFD_RELOC_8:
12495 if (fixP->fx_done || fixP->fx_pcrel)
12496 md_number_to_chars (buf, value, 1);
12497#ifdef OBJ_ELF
12498 else if (!target_oabi)
12499 {
12500 value = fixP->fx_offset;
12501 md_number_to_chars (buf, value, 1);
12502 }
12503#endif
12504 break;
12505
12506 case BFD_RELOC_16:
12507 if (fixP->fx_done || fixP->fx_pcrel)
12508 md_number_to_chars (buf, value, 2);
12509#ifdef OBJ_ELF
12510 else if (!target_oabi)
12511 {
12512 value = fixP->fx_offset;
12513 md_number_to_chars (buf, value, 2);
12514 }
12515#endif
12516 break;
12517
12518#ifdef OBJ_ELF
12519 case BFD_RELOC_ARM_GOT32:
12520 case BFD_RELOC_ARM_GOTOFF:
12521 md_number_to_chars (buf, 0, 4);
12522 break;
12523#endif
12524
12525 case BFD_RELOC_RVA:
12526 case BFD_RELOC_32:
12527 if (fixP->fx_done || fixP->fx_pcrel)
12528 md_number_to_chars (buf, value, 4);
12529#ifdef OBJ_ELF
12530 else if (!target_oabi)
12531 {
12532 value = fixP->fx_offset;
12533 md_number_to_chars (buf, value, 4);
12534 }
12535#endif
12536 break;
12537
12538#ifdef OBJ_ELF
12539 case BFD_RELOC_ARM_PLT32:
12540 /* It appears the instruction is fully prepared at this point. */
12541 break;
12542#endif
12543
b99bd4ef
NC
12544 case BFD_RELOC_ARM_CP_OFF_IMM:
12545 sign = value >= 0;
12546 if (value < -1023 || value > 1023 || (value & 3))
12547 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12548 _("illegal value for co-processor offset"));
b99bd4ef
NC
12549 if (value < 0)
12550 value = -value;
12551 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12552 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12553 md_number_to_chars (buf, newval, INSN_SIZE);
12554 break;
12555
e16bb312
NC
12556 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12557 sign = value >= 0;
12558 if (value < -255 || value > 255)
12559 as_bad_where (fixP->fx_file, fixP->fx_line,
12560 _("Illegal value for co-processor offset"));
12561 if (value < 0)
12562 value = -value;
12563 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12564 newval |= value | (sign ? INDEX_UP : 0);
12565 md_number_to_chars (buf, newval , INSN_SIZE);
12566 break;
12567
b99bd4ef
NC
12568 case BFD_RELOC_ARM_THUMB_OFFSET:
12569 newval = md_chars_to_number (buf, THUMB_SIZE);
12570 /* Exactly what ranges, and where the offset is inserted depends
12571 on the type of instruction, we can establish this from the
12572 top 4 bits. */
12573 switch (newval >> 12)
12574 {
12575 case 4: /* PC load. */
12576 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12577 forced to zero for these loads, so we will need to round
12578 up the offset if the instruction address is not word
12579 aligned (since the final address produced must be, and
12580 we can only describe word-aligned immediate offsets). */
12581
12582 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12583 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12584 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12585 (unsigned int) (fixP->fx_frag->fr_address
12586 + fixP->fx_where + value));
12587
12588 if ((value + 2) & ~0x3fe)
12589 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12590 _("invalid offset, value too big (0x%08lX)"),
12591 (long) value);
b99bd4ef
NC
12592
12593 /* Round up, since pc will be rounded down. */
12594 newval |= (value + 2) >> 2;
12595 break;
12596
12597 case 9: /* SP load/store. */
12598 if (value & ~0x3fc)
12599 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12600 _("invalid offset, value too big (0x%08lX)"),
12601 (long) value);
b99bd4ef
NC
12602 newval |= value >> 2;
12603 break;
12604
12605 case 6: /* Word load/store. */
12606 if (value & ~0x7c)
12607 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12608 _("invalid offset, value too big (0x%08lX)"),
12609 (long) value);
b99bd4ef
NC
12610 newval |= value << 4; /* 6 - 2. */
12611 break;
12612
12613 case 7: /* Byte load/store. */
12614 if (value & ~0x1f)
12615 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12616 _("invalid offset, value too big (0x%08lX)"),
12617 (long) value);
b99bd4ef
NC
12618 newval |= value << 6;
12619 break;
12620
12621 case 8: /* Halfword load/store. */
12622 if (value & ~0x3e)
12623 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12624 _("invalid offset, value too big (0x%08lX)"),
12625 (long) value);
b99bd4ef
NC
12626 newval |= value << 5; /* 6 - 1. */
12627 break;
12628
12629 default:
12630 as_bad_where (fixP->fx_file, fixP->fx_line,
12631 "Unable to process relocation for thumb opcode: %lx",
12632 (unsigned long) newval);
12633 break;
12634 }
12635 md_number_to_chars (buf, newval, THUMB_SIZE);
12636 break;
12637
12638 case BFD_RELOC_ARM_THUMB_ADD:
12639 /* This is a complicated relocation, since we use it for all of
12640 the following immediate relocations:
12641
12642 3bit ADD/SUB
12643 8bit ADD/SUB
12644 9bit ADD/SUB SP word-aligned
12645 10bit ADD PC/SP word-aligned
12646
12647 The type of instruction being processed is encoded in the
12648 instruction field:
12649
12650 0x8000 SUB
12651 0x00F0 Rd
12652 0x000F Rs
12653 */
12654 newval = md_chars_to_number (buf, THUMB_SIZE);
12655 {
12656 int rd = (newval >> 4) & 0xf;
12657 int rs = newval & 0xf;
12658 int subtract = newval & 0x8000;
12659
12660 if (rd == REG_SP)
12661 {
12662 if (value & ~0x1fc)
12663 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12664 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12665 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12666 newval |= value >> 2;
12667 }
12668 else if (rs == REG_PC || rs == REG_SP)
12669 {
12670 if (subtract ||
12671 value & ~0x3fc)
12672 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12673 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12674 (unsigned long) value);
12675 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12676 newval |= rd << 8;
12677 newval |= value >> 2;
12678 }
12679 else if (rs == rd)
12680 {
12681 if (value & ~0xff)
12682 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12683 _("invalid 8bit immediate"));
b99bd4ef
NC
12684 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12685 newval |= (rd << 8) | value;
12686 }
12687 else
12688 {
12689 if (value & ~0x7)
12690 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12691 _("invalid 3bit immediate"));
b99bd4ef
NC
12692 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12693 newval |= rd | (rs << 3) | (value << 6);
12694 }
12695 }
12696 md_number_to_chars (buf, newval, THUMB_SIZE);
12697 break;
12698
12699 case BFD_RELOC_ARM_THUMB_IMM:
12700 newval = md_chars_to_number (buf, THUMB_SIZE);
12701 switch (newval >> 11)
12702 {
12703 case 0x04: /* 8bit immediate MOV. */
12704 case 0x05: /* 8bit immediate CMP. */
12705 if (value < 0 || value > 255)
12706 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12707 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12708 (long) value);
12709 newval |= value;
12710 break;
12711
12712 default:
12713 abort ();
12714 }
12715 md_number_to_chars (buf, newval, THUMB_SIZE);
12716 break;
12717
12718 case BFD_RELOC_ARM_THUMB_SHIFT:
12719 /* 5bit shift value (0..31). */
12720 if (value < 0 || value > 31)
12721 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12722 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12723 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12724 newval |= value << 6;
12725 md_number_to_chars (buf, newval, THUMB_SIZE);
12726 break;
12727
12728 case BFD_RELOC_VTABLE_INHERIT:
12729 case BFD_RELOC_VTABLE_ENTRY:
12730 fixP->fx_done = 0;
94f592af 12731 return;
b99bd4ef
NC
12732
12733 case BFD_RELOC_NONE:
12734 default:
12735 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12736 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12737 }
b99bd4ef
NC
12738}
12739
12740/* Translate internal representation of relocation info to BFD target
12741 format. */
12742
12743arelent *
12744tc_gen_reloc (section, fixp)
12745 asection * section ATTRIBUTE_UNUSED;
12746 fixS * fixp;
12747{
12748 arelent * reloc;
12749 bfd_reloc_code_real_type code;
12750
12751 reloc = (arelent *) xmalloc (sizeof (arelent));
12752
12753 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12754 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12755 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12756
12757 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12758#ifndef OBJ_ELF
12759 if (fixp->fx_pcrel == 0)
12760 reloc->addend = fixp->fx_offset;
12761 else
12762 reloc->addend = fixp->fx_offset = reloc->address;
12763#else /* OBJ_ELF */
12764 reloc->addend = fixp->fx_offset;
12765#endif
12766
12767 switch (fixp->fx_r_type)
12768 {
12769 case BFD_RELOC_8:
12770 if (fixp->fx_pcrel)
12771 {
12772 code = BFD_RELOC_8_PCREL;
12773 break;
12774 }
12775
12776 case BFD_RELOC_16:
12777 if (fixp->fx_pcrel)
12778 {
12779 code = BFD_RELOC_16_PCREL;
12780 break;
12781 }
12782
12783 case BFD_RELOC_32:
12784 if (fixp->fx_pcrel)
12785 {
12786 code = BFD_RELOC_32_PCREL;
12787 break;
12788 }
12789
12790 case BFD_RELOC_ARM_PCREL_BRANCH:
12791 case BFD_RELOC_ARM_PCREL_BLX:
12792 case BFD_RELOC_RVA:
12793 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12794 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12795 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12796 case BFD_RELOC_THUMB_PCREL_BLX:
12797 case BFD_RELOC_VTABLE_ENTRY:
12798 case BFD_RELOC_VTABLE_INHERIT:
12799 code = fixp->fx_r_type;
12800 break;
12801
12802 case BFD_RELOC_ARM_LITERAL:
12803 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12804 /* If this is called then the a literal has
12805 been referenced across a section boundary. */
b99bd4ef 12806 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12807 _("literal referenced across section boundary"));
b99bd4ef
NC
12808 return NULL;
12809
12810#ifdef OBJ_ELF
12811 case BFD_RELOC_ARM_GOT32:
12812 case BFD_RELOC_ARM_GOTOFF:
12813 case BFD_RELOC_ARM_PLT32:
12814 code = fixp->fx_r_type;
12815 break;
12816#endif
12817
12818 case BFD_RELOC_ARM_IMMEDIATE:
12819 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12820 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12821 return NULL;
12822
12823 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12824 as_bad_where (fixp->fx_file, fixp->fx_line,
12825 _("ADRL used for a symbol not defined in the same file"));
12826 return NULL;
12827
12828 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12829 if (fixp->fx_addsy != NULL
12830 && !S_IS_DEFINED (fixp->fx_addsy)
12831 && S_IS_LOCAL (fixp->fx_addsy))
12832 {
12833 as_bad_where (fixp->fx_file, fixp->fx_line,
12834 _("undefined local label `%s'"),
12835 S_GET_NAME (fixp->fx_addsy));
12836 return NULL;
12837 }
12838
b99bd4ef 12839 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12840 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12841 return NULL;
12842
12843 default:
12844 {
12845 char * type;
12846
12847 switch (fixp->fx_r_type)
12848 {
b99bd4ef
NC
12849 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12850 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12851 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12852 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12853 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12854 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12855 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12856 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12857 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12858 default: type = _("<unknown>"); break;
12859 }
12860 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12861 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12862 type);
12863 return NULL;
12864 }
12865 }
12866
12867#ifdef OBJ_ELF
8df7094c 12868 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12869 && GOT_symbol
12870 && fixp->fx_addsy == GOT_symbol)
12871 {
12872 code = BFD_RELOC_ARM_GOTPC;
12873 reloc->addend = fixp->fx_offset = reloc->address;
12874 }
12875#endif
12876
12877 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12878
12879 if (reloc->howto == NULL)
12880 {
12881 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12882 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12883 bfd_get_reloc_code_name (code));
12884 return NULL;
12885 }
12886
12887 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12888 vtable entry to be used in the relocation's section offset. */
12889 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12890 reloc->address = fixp->fx_offset;
12891
12892 return reloc;
12893}
12894
12895int
12896md_estimate_size_before_relax (fragP, segtype)
12897 fragS * fragP ATTRIBUTE_UNUSED;
12898 segT segtype ATTRIBUTE_UNUSED;
12899{
12900 as_fatal (_("md_estimate_size_before_relax\n"));
12901 return 1;
12902}
12903
12904static void
f03698e6
RE
12905output_inst (str)
12906 const char *str;
b99bd4ef
NC
12907{
12908 char * to = NULL;
12909
12910 if (inst.error)
12911 {
f03698e6 12912 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12913 return;
12914 }
12915
12916 to = frag_more (inst.size);
12917
12918 if (thumb_mode && (inst.size > THUMB_SIZE))
12919 {
12920 assert (inst.size == (2 * THUMB_SIZE));
12921 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12922 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12923 }
12924 else if (inst.size > INSN_SIZE)
12925 {
12926 assert (inst.size == (2 * INSN_SIZE));
12927 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12928 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12929 }
12930 else
12931 md_number_to_chars (to, inst.instruction, inst.size);
12932
12933 if (inst.reloc.type != BFD_RELOC_NONE)
12934 fix_new_arm (frag_now, to - frag_now->fr_literal,
12935 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12936 inst.reloc.type);
12937
12938#ifdef OBJ_ELF
12939 dwarf2_emit_insn (inst.size);
12940#endif
12941}
12942
12943void
12944md_assemble (str)
12945 char * str;
12946{
6c43fab6
RE
12947 char c;
12948 char *p;
12949 char *start;
b99bd4ef
NC
12950
12951 /* Align the instruction.
12952 This may not be the right thing to do but ... */
12953#if 0
12954 arm_align (2, 0);
12955#endif
b99bd4ef
NC
12956
12957 /* Align the previous label if needed. */
12958 if (last_label_seen != NULL)
12959 {
12960 symbol_set_frag (last_label_seen, frag_now);
12961 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12962 S_SET_SEGMENT (last_label_seen, now_seg);
12963 }
12964
12965 memset (&inst, '\0', sizeof (inst));
12966 inst.reloc.type = BFD_RELOC_NONE;
12967
12968 skip_whitespace (str);
12969
12970 /* Scan up to the end of the op-code, which must end in white space or
12971 end of string. */
12972 for (start = p = str; *p != '\0'; p++)
12973 if (*p == ' ')
12974 break;
12975
12976 if (p == str)
12977 {
f03698e6 12978 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12979 return;
12980 }
12981
12982 if (thumb_mode)
12983 {
05d2d07e 12984 const struct thumb_opcode * opcode;
b99bd4ef
NC
12985
12986 c = *p;
12987 *p = '\0';
05d2d07e 12988 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12989 *p = c;
12990
12991 if (opcode)
12992 {
12993 /* Check that this instruction is supported for this CPU. */
90e4755a 12994 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12995 {
f03698e6 12996 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12997 return;
12998 }
12999
6057a28f 13000 mapping_state (MAP_THUMB);
b99bd4ef
NC
13001 inst.instruction = opcode->value;
13002 inst.size = opcode->size;
13003 (*opcode->parms) (p);
f03698e6 13004 output_inst (str);
b99bd4ef
NC
13005 return;
13006 }
13007 }
13008 else
13009 {
05d2d07e 13010 const struct asm_opcode * opcode;
b99bd4ef 13011
90e4755a
RE
13012 c = *p;
13013 *p = '\0';
6c43fab6 13014 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 13015 *p = c;
b99bd4ef 13016
90e4755a 13017 if (opcode)
b99bd4ef 13018 {
90e4755a
RE
13019 /* Check that this instruction is supported for this CPU. */
13020 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 13021 {
f03698e6 13022 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13023 return;
13024 }
13025
6057a28f 13026 mapping_state (MAP_ARM);
90e4755a
RE
13027 inst.instruction = opcode->value;
13028 inst.size = INSN_SIZE;
f2b7cb0a 13029 (*opcode->parms) (p);
f03698e6 13030 output_inst (str);
90e4755a 13031 return;
b99bd4ef
NC
13032 }
13033 }
13034
13035 /* It wasn't an instruction, but it might be a register alias of the form
13036 alias .req reg. */
6c43fab6
RE
13037 if (create_register_alias (str, p))
13038 return;
b99bd4ef 13039
b99bd4ef
NC
13040 as_bad (_("bad instruction `%s'"), start);
13041}
13042
13043/* md_parse_option
13044 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 13045 See if it's a processor-specific option.
03b1477f
RE
13046
13047 This routine is somewhat complicated by the need for backwards
13048 compatibility (since older releases of gcc can't be changed).
13049 The new options try to make the interface as compatible as
13050 possible with GCC.
13051
13052 New options (supported) are:
13053
13054 -mcpu=<cpu name> Assemble for selected processor
13055 -march=<architecture name> Assemble for selected architecture
13056 -mfpu=<fpu architecture> Assemble for selected FPU.
13057 -EB/-mbig-endian Big-endian
13058 -EL/-mlittle-endian Little-endian
13059 -k Generate PIC code
13060 -mthumb Start in Thumb mode
13061 -mthumb-interwork Code supports ARM/Thumb interworking
13062
3d0c9500 13063 For now we will also provide support for:
03b1477f
RE
13064
13065 -mapcs-32 32-bit Program counter
13066 -mapcs-26 26-bit Program counter
13067 -macps-float Floats passed in FP registers
13068 -mapcs-reentrant Reentrant code
13069 -matpcs
13070 (sometime these will probably be replaced with -mapcs=<list of options>
13071 and -matpcs=<list of options>)
13072
13073 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13074 Cpu variants, the arm part is optional:
13075 -m[arm]1 Currently not supported.
13076 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13077 -m[arm]3 Arm 3 processor
13078 -m[arm]6[xx], Arm 6 processors
13079 -m[arm]7[xx][t][[d]m] Arm 7 processors
13080 -m[arm]8[10] Arm 8 processors
13081 -m[arm]9[20][tdmi] Arm 9 processors
13082 -mstrongarm[110[0]] StrongARM processors
13083 -mxscale XScale processors
13084 -m[arm]v[2345[t[e]]] Arm architectures
13085 -mall All (except the ARM1)
13086 FP variants:
13087 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13088 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13089 -mvfpxd VFP Single precision
13090 -mvfp All VFP
b99bd4ef 13091 -mno-fpu Disable all floating point instructions
b99bd4ef 13092
03b1477f
RE
13093 The following CPU names are recognized:
13094 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13095 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13096 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13097 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13098 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13099 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13100 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13101
13102 */
13103
5a38dc70 13104const char * md_shortopts = "m:k";
03b1477f 13105
b99bd4ef
NC
13106#ifdef ARM_BI_ENDIAN
13107#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13108#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13109#else
21f0f23a
RE
13110#if TARGET_BYTES_BIG_ENDIAN
13111#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13112#else
13113#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13114#endif
ce058b6c 13115#endif
03b1477f
RE
13116
13117struct option md_longopts[] =
13118{
13119#ifdef OPTION_EB
13120 {"EB", no_argument, NULL, OPTION_EB},
13121#endif
13122#ifdef OPTION_EL
13123 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13124#endif
13125 {NULL, no_argument, NULL, 0}
13126};
13127
13128size_t md_longopts_size = sizeof (md_longopts);
13129
03b1477f 13130struct arm_option_table
b99bd4ef 13131{
03b1477f
RE
13132 char *option; /* Option name to match. */
13133 char *help; /* Help information. */
13134 int *var; /* Variable to change. */
13135 int value; /* What to change it to. */
13136 char *deprecated; /* If non-null, print this message. */
13137};
b99bd4ef 13138
cc8a6dd0 13139struct arm_option_table arm_opts[] =
03b1477f
RE
13140{
13141 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13142 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13143 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13144 &support_interwork, 1, NULL},
13145 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13146 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13147 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13148 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13149 1, NULL},
13150 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13151 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13152 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13153 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13154 NULL},
13155
13156 /* These are recognized by the assembler, but have no affect on code. */
13157 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13158 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13159
13160 /* DON'T add any new processors to this list -- we want the whole list
13161 to go away... Add them to the processors table instead. */
13162 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13163 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13164 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13165 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13166 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13167 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13168 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13169 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13170 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13171 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13172 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13173 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13174 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13175 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13176 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13177 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13178 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13179 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13180 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13181 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13182 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13183 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13184 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13185 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13186 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13187 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13188 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13189 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13190 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13191 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13192 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13193 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13194 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13195 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13196 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13197 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13198 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13199 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13200 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13201 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13202 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13203 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13204 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13205 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13206 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13207 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13208 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13209 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13210 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13211 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13212 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13213 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13214 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13215 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13216 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13217 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13218 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13219 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13220 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13221 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13222 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13223 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13224 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13225 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13226 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13227 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13228 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13229 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13230 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13231 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13232 N_("use -mcpu=strongarm110")},
13233 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13234 N_("use -mcpu=strongarm1100")},
13235 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13236 N_("use -mcpu=strongarm1110")},
13237 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13238 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13239 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13240
13241 /* Architecture variants -- don't add any more to this list either. */
13242 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13243 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13244 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13245 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13246 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13247 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13248 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13249 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13250 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13251 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13252 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13253 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13254 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13255 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13256 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13257 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13258 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13259 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13260
13261 /* Floating point variants -- don't add any more to this list either. */
13262 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13263 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13264 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13265 {"mno-fpu", NULL, &legacy_fpu, 0,
13266 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13267
13268 {NULL, NULL, NULL, 0, NULL}
13269};
21f0f23a 13270
03b1477f
RE
13271struct arm_cpu_option_table
13272{
13273 char *name;
13274 int value;
13275 /* For some CPUs we assume an FPU unless the user explicitly sets
13276 -mfpu=... */
13277 int default_fpu;
13278};
13279
13280/* This list should, at a minimum, contain all the cpu names
13281 recognized by GCC. */
13282static struct arm_cpu_option_table arm_cpus[] =
13283{
13284 {"all", ARM_ANY, FPU_ARCH_FPA},
13285 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13286 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13287 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13288 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13289 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13290 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13291 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13292 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13293 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13294 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13295 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13296 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13297 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13298 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13299 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13300 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13301 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13302 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13303 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13305 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13307 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13308 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13309 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13310 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13312 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13313 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13314 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13315 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13316 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13317 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13318 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13319 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13320 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13321 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13322 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13323 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13324 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13325 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13326 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13327 /* For V5 or later processors we default to using VFP; but the user
13328 should really set the FPU type explicitly. */
13329 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13330 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13331 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13332 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13333 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13334 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13335 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13336 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13337 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13338 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13339 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13340 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13341 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 13342 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015
MM
13343 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13344 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13345 /* ??? XSCALE is really an architecture. */
13346 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13347 /* ??? iwmmxt is not a processor. */
e16bb312 13348 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13349 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13350 /* Maverick */
33a392fb 13351 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13352 {NULL, 0, 0}
13353};
cc8a6dd0 13354
03b1477f
RE
13355struct arm_arch_option_table
13356{
13357 char *name;
13358 int value;
13359 int default_fpu;
13360};
13361
13362/* This list should, at a minimum, contain all the architecture names
13363 recognized by GCC. */
13364static struct arm_arch_option_table arm_archs[] =
13365{
13366 {"all", ARM_ANY, FPU_ARCH_FPA},
13367 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13368 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13369 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13370 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13371 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13372 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13373 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13374 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13375 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13376 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13377 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13378 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13379 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13380 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13381 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13382 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13383 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13384 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13385 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13386 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13387 {NULL, 0, 0}
13388};
13389
13390/* ISA extensions in the co-processor space. */
13391struct arm_arch_extension_table
13392{
13393 char *name;
13394 int value;
13395};
13396
13397static struct arm_arch_extension_table arm_extensions[] =
13398{
13399 {"maverick", ARM_CEXT_MAVERICK},
13400 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13401 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13402 {NULL, 0}
13403};
b99bd4ef 13404
03b1477f
RE
13405struct arm_fpu_option_table
13406{
13407 char *name;
13408 int value;
13409};
13410
13411/* This list should, at a minimum, contain all the fpu names
13412 recognized by GCC. */
13413static struct arm_fpu_option_table arm_fpus[] =
13414{
13415 {"softfpa", FPU_NONE},
13416 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13417 {"fpe2", FPU_ARCH_FPE},
13418 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13419 {"fpa", FPU_ARCH_FPA},
13420 {"fpa10", FPU_ARCH_FPA},
13421 {"fpa11", FPU_ARCH_FPA},
13422 {"arm7500fe", FPU_ARCH_FPA},
13423 {"softvfp", FPU_ARCH_VFP},
13424 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13425 {"vfp", FPU_ARCH_VFP_V2},
13426 {"vfp9", FPU_ARCH_VFP_V2},
13427 {"vfp10", FPU_ARCH_VFP_V2},
13428 {"vfp10-r0", FPU_ARCH_VFP_V1},
13429 {"vfpxd", FPU_ARCH_VFP_V1xD},
13430 {"arm1020t", FPU_ARCH_VFP_V1},
13431 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13432 {"arm1136jfs", FPU_ARCH_VFP_V2},
33a392fb
PB
13433 {"maverick", FPU_ARCH_MAVERICK},
13434 {NULL, 0}
13435};
13436
13437struct arm_float_abi_option_table
13438{
13439 char *name;
13440 int value;
13441};
13442
13443static struct arm_float_abi_option_table arm_float_abis[] =
13444{
13445 {"hard", ARM_FLOAT_ABI_HARD},
13446 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13447 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13448 {NULL, 0}
13449};
13450
13451struct arm_long_option_table
13452{
13453 char *option; /* Substring to match. */
13454 char *help; /* Help information. */
13455 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13456 char *deprecated; /* If non-null, print this message. */
13457};
13458
13459static int
13460arm_parse_extension (str, opt_p)
13461 char *str;
13462 int *opt_p;
13463{
13464 while (str != NULL && *str != 0)
13465 {
13466 struct arm_arch_extension_table *opt;
13467 char *ext;
13468 int optlen;
13469
13470 if (*str != '+')
b99bd4ef 13471 {
03b1477f
RE
13472 as_bad (_("invalid architectural extension"));
13473 return 0;
13474 }
b99bd4ef 13475
03b1477f
RE
13476 str++;
13477 ext = strchr (str, '+');
b99bd4ef 13478
03b1477f
RE
13479 if (ext != NULL)
13480 optlen = ext - str;
13481 else
13482 optlen = strlen (str);
b99bd4ef 13483
03b1477f
RE
13484 if (optlen == 0)
13485 {
13486 as_bad (_("missing architectural extension"));
13487 return 0;
13488 }
b99bd4ef 13489
03b1477f
RE
13490 for (opt = arm_extensions; opt->name != NULL; opt++)
13491 if (strncmp (opt->name, str, optlen) == 0)
13492 {
13493 *opt_p |= opt->value;
13494 break;
13495 }
bfae80f2 13496
03b1477f
RE
13497 if (opt->name == NULL)
13498 {
13499 as_bad (_("unknown architectural extnsion `%s'"), str);
13500 return 0;
13501 }
b99bd4ef 13502
03b1477f
RE
13503 str = ext;
13504 };
b99bd4ef 13505
03b1477f
RE
13506 return 1;
13507}
b99bd4ef 13508
03b1477f
RE
13509static int
13510arm_parse_cpu (str)
13511 char *str;
13512{
13513 struct arm_cpu_option_table *opt;
13514 char *ext = strchr (str, '+');
13515 int optlen;
b99bd4ef 13516
03b1477f
RE
13517 if (ext != NULL)
13518 optlen = ext - str;
13519 else
13520 optlen = strlen (str);
b99bd4ef 13521
03b1477f
RE
13522 if (optlen == 0)
13523 {
13524 as_bad (_("missing cpu name `%s'"), str);
13525 return 0;
13526 }
b99bd4ef 13527
03b1477f
RE
13528 for (opt = arm_cpus; opt->name != NULL; opt++)
13529 if (strncmp (opt->name, str, optlen) == 0)
13530 {
13531 mcpu_cpu_opt = opt->value;
13532 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13533
03b1477f
RE
13534 if (ext != NULL)
13535 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13536
03b1477f
RE
13537 return 1;
13538 }
b99bd4ef 13539
03b1477f
RE
13540 as_bad (_("unknown cpu `%s'"), str);
13541 return 0;
13542}
b99bd4ef 13543
03b1477f
RE
13544static int
13545arm_parse_arch (str)
13546 char *str;
13547{
13548 struct arm_arch_option_table *opt;
13549 char *ext = strchr (str, '+');
13550 int optlen;
b99bd4ef 13551
03b1477f
RE
13552 if (ext != NULL)
13553 optlen = ext - str;
13554 else
13555 optlen = strlen (str);
b99bd4ef 13556
03b1477f
RE
13557 if (optlen == 0)
13558 {
13559 as_bad (_("missing architecture name `%s'"), str);
13560 return 0;
13561 }
b99bd4ef 13562
b99bd4ef 13563
03b1477f
RE
13564 for (opt = arm_archs; opt->name != NULL; opt++)
13565 if (strcmp (opt->name, str) == 0)
13566 {
13567 march_cpu_opt = opt->value;
13568 march_fpu_opt = opt->default_fpu;
b99bd4ef 13569
03b1477f
RE
13570 if (ext != NULL)
13571 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13572
03b1477f
RE
13573 return 1;
13574 }
b99bd4ef 13575
03b1477f
RE
13576 as_bad (_("unknown architecture `%s'\n"), str);
13577 return 0;
13578}
13579
13580static int
13581arm_parse_fpu (str)
13582 char *str;
13583{
13584 struct arm_fpu_option_table *opt;
b99bd4ef 13585
03b1477f
RE
13586 for (opt = arm_fpus; opt->name != NULL; opt++)
13587 if (strcmp (opt->name, str) == 0)
13588 {
13589 mfpu_opt = opt->value;
13590 return 1;
13591 }
b99bd4ef 13592
03b1477f
RE
13593 as_bad (_("unknown floating point format `%s'\n"), str);
13594 return 0;
13595}
b99bd4ef 13596
33a392fb
PB
13597static int
13598arm_parse_float_abi (str)
13599 char * str;
13600{
13601 struct arm_float_abi_option_table *opt;
13602
13603 for (opt = arm_float_abis; opt->name != NULL; opt++)
13604 if (strcmp (opt->name, str) == 0)
13605 {
13606 mfloat_abi_opt = opt->value;
13607 return 1;
13608 }
13609
13610 as_bad (_("unknown floating point abi `%s'\n"), str);
13611 return 0;
13612}
13613
03b1477f
RE
13614struct arm_long_option_table arm_long_opts[] =
13615{
13616 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13617 arm_parse_cpu, NULL},
13618 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13619 arm_parse_arch, NULL},
13620 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13621 arm_parse_fpu, NULL},
33a392fb
PB
13622 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13623 arm_parse_float_abi, NULL},
03b1477f
RE
13624 {NULL, NULL, 0, NULL}
13625};
b99bd4ef 13626
03b1477f
RE
13627int
13628md_parse_option (c, arg)
13629 int c;
13630 char * arg;
13631{
13632 struct arm_option_table *opt;
13633 struct arm_long_option_table *lopt;
b99bd4ef 13634
03b1477f
RE
13635 switch (c)
13636 {
13637#ifdef OPTION_EB
13638 case OPTION_EB:
13639 target_big_endian = 1;
b99bd4ef 13640 break;
03b1477f 13641#endif
b99bd4ef 13642
03b1477f
RE
13643#ifdef OPTION_EL
13644 case OPTION_EL:
13645 target_big_endian = 0;
b99bd4ef
NC
13646 break;
13647#endif
13648
03b1477f 13649 case 'a':
cc8a6dd0 13650 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13651 ones. */
13652 return 0;
13653
b99bd4ef 13654 default:
03b1477f
RE
13655 for (opt = arm_opts; opt->option != NULL; opt++)
13656 {
13657 if (c == opt->option[0]
13658 && ((arg == NULL && opt->option[1] == 0)
13659 || strcmp (arg, opt->option + 1) == 0))
13660 {
13661#if WARN_DEPRECATED
13662 /* If the option is deprecated, tell the user. */
13663 if (opt->deprecated != NULL)
13664 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13665 arg ? arg : "", _(opt->deprecated));
13666#endif
13667
13668 if (opt->var != NULL)
13669 *opt->var = opt->value;
13670
13671 return 1;
13672 }
13673 }
13674
13675 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13676 {
cc8a6dd0 13677 /* These options are expected to have an argument. */
03b1477f
RE
13678 if (c == lopt->option[0]
13679 && arg != NULL
cc8a6dd0 13680 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13681 strlen (lopt->option + 1)) == 0)
13682 {
13683#if WARN_DEPRECATED
13684 /* If the option is deprecated, tell the user. */
13685 if (lopt->deprecated != NULL)
13686 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13687 _(lopt->deprecated));
13688#endif
13689
13690 /* Call the sup-option parser. */
13691 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13692 }
13693 }
13694
13695 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
13696 return 0;
13697 }
13698
13699 return 1;
13700}
13701
13702void
13703md_show_usage (fp)
13704 FILE * fp;
13705{
03b1477f
RE
13706 struct arm_option_table *opt;
13707 struct arm_long_option_table *lopt;
13708
13709 fprintf (fp, _(" ARM-specific assembler options:\n"));
13710
13711 for (opt = arm_opts; opt->option != NULL; opt++)
13712 if (opt->help != NULL)
13713 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13714
13715 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13716 if (lopt->help != NULL)
13717 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13718
13719#ifdef OPTION_EB
b99bd4ef 13720 fprintf (fp, _("\
03b1477f 13721 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13722#endif
03b1477f
RE
13723
13724#ifdef OPTION_EL
b99bd4ef 13725 fprintf (fp, _("\
03b1477f 13726 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13727#endif
13728}
13729
13730/* We need to be able to fix up arbitrary expressions in some statements.
13731 This is so that we can handle symbols that are an arbitrary distance from
13732 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13733 which returns part of an address in a form which will be valid for
13734 a data instruction. We do this by pushing the expression into a symbol
13735 in the expr_section, and creating a fix for that. */
13736
13737static void
13738fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13739 fragS * frag;
13740 int where;
13741 short int size;
13742 expressionS * exp;
13743 int pc_rel;
13744 int reloc;
13745{
13746 fixS * new_fix;
13747 arm_fix_data * arm_data;
13748
13749 switch (exp->X_op)
13750 {
13751 case O_constant:
13752 case O_symbol:
13753 case O_add:
13754 case O_subtract:
13755 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13756 break;
13757
13758 default:
13759 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13760 pc_rel, reloc);
13761 break;
13762 }
13763
13764 /* Mark whether the fix is to a THUMB instruction, or an ARM
13765 instruction. */
13766 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13767 new_fix->tc_fix_data = (PTR) arm_data;
13768 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13769}
13770
13771/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13772
13773void
13774cons_fix_new_arm (frag, where, size, exp)
13775 fragS * frag;
13776 int where;
13777 int size;
13778 expressionS * exp;
13779{
13780 bfd_reloc_code_real_type type;
13781 int pcrel = 0;
13782
13783 /* Pick a reloc.
13784 FIXME: @@ Should look at CPU word size. */
13785 switch (size)
13786 {
13787 case 1:
13788 type = BFD_RELOC_8;
13789 break;
13790 case 2:
13791 type = BFD_RELOC_16;
13792 break;
13793 case 4:
13794 default:
13795 type = BFD_RELOC_32;
13796 break;
13797 case 8:
13798 type = BFD_RELOC_64;
13799 break;
13800 }
13801
13802 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13803}
13804
13805/* A good place to do this, although this was probably not intended
13806 for this kind of use. We need to dump the literal pool before
13807 references are made to a null symbol pointer. */
13808
13809void
13810arm_cleanup ()
13811{
3d0c9500 13812 literal_pool * pool;
b99bd4ef 13813
3d0c9500
NC
13814 for (pool = list_of_pools; pool; pool = pool->next)
13815 {
13816 /* Put it at the end of the relevent section. */
13817 subseg_set (pool->section, pool->sub_section);
13818 s_ltorg (0);
13819 }
b99bd4ef
NC
13820}
13821
13822void
13823arm_start_line_hook ()
13824{
13825 last_label_seen = NULL;
13826}
13827
13828void
13829arm_frob_label (sym)
13830 symbolS * sym;
13831{
13832 last_label_seen = sym;
13833
13834 ARM_SET_THUMB (sym, thumb_mode);
13835
13836#if defined OBJ_COFF || defined OBJ_ELF
13837 ARM_SET_INTERWORK (sym, support_interwork);
13838#endif
13839
13840 /* Note - do not allow local symbols (.Lxxx) to be labeled
13841 as Thumb functions. This is because these labels, whilst
13842 they exist inside Thumb code, are not the entry points for
13843 possible ARM->Thumb calls. Also, these labels can be used
13844 as part of a computed goto or switch statement. eg gcc
13845 can generate code that looks like this:
13846
13847 ldr r2, [pc, .Laaa]
13848 lsl r3, r3, #2
13849 ldr r2, [r3, r2]
13850 mov pc, r2
cc8a6dd0 13851
b99bd4ef
NC
13852 .Lbbb: .word .Lxxx
13853 .Lccc: .word .Lyyy
13854 ..etc...
13855 .Laaa: .word Lbbb
13856
13857 The first instruction loads the address of the jump table.
13858 The second instruction converts a table index into a byte offset.
13859 The third instruction gets the jump address out of the table.
13860 The fourth instruction performs the jump.
cc8a6dd0 13861
b99bd4ef
NC
13862 If the address stored at .Laaa is that of a symbol which has the
13863 Thumb_Func bit set, then the linker will arrange for this address
13864 to have the bottom bit set, which in turn would mean that the
13865 address computation performed by the third instruction would end
13866 up with the bottom bit set. Since the ARM is capable of unaligned
13867 word loads, the instruction would then load the incorrect address
13868 out of the jump table, and chaos would ensue. */
13869 if (label_is_thumb_function_name
13870 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13871 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13872 {
13873 /* When the address of a Thumb function is taken the bottom
13874 bit of that address should be set. This will allow
13875 interworking between Arm and Thumb functions to work
13876 correctly. */
13877
13878 THUMB_SET_FUNC (sym, 1);
13879
b34976b6 13880 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13881 }
13882}
13883
13884/* Adjust the symbol table. This marks Thumb symbols as distinct from
13885 ARM ones. */
13886
13887void
13888arm_adjust_symtab ()
13889{
13890#ifdef OBJ_COFF
13891 symbolS * sym;
13892
13893 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13894 {
13895 if (ARM_IS_THUMB (sym))
13896 {
13897 if (THUMB_IS_FUNC (sym))
13898 {
13899 /* Mark the symbol as a Thumb function. */
13900 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13901 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13902 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13903
13904 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13905 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13906 else
13907 as_bad (_("%s: unexpected function type: %d"),
13908 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13909 }
cc8a6dd0 13910 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13911 {
13912 case C_EXT:
13913 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13914 break;
13915 case C_STAT:
13916 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13917 break;
13918 case C_LABEL:
13919 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13920 break;
13921 default:
13922 /* Do nothing. */
13923 break;
13924 }
13925 }
13926
13927 if (ARM_IS_INTERWORK (sym))
13928 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13929 }
13930#endif
13931#ifdef OBJ_ELF
13932 symbolS * sym;
13933 char bind;
13934
13935 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13936 {
13937 if (ARM_IS_THUMB (sym))
13938 {
13939 elf_symbol_type * elf_sym;
13940
13941 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13942 bind = ELF_ST_BIND (elf_sym);
13943
13944 /* If it's a .thumb_func, declare it as so,
13945 otherwise tag label as .code 16. */
13946 if (THUMB_IS_FUNC (sym))
13947 elf_sym->internal_elf_sym.st_info =
13948 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13949 else
13950 elf_sym->internal_elf_sym.st_info =
13951 ELF_ST_INFO (bind, STT_ARM_16BIT);
13952 }
13953 }
13954#endif
13955}
13956
13957int
13958arm_data_in_code ()
13959{
13960 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13961 {
13962 *input_line_pointer = '/';
13963 input_line_pointer += 5;
13964 *input_line_pointer = 0;
13965 return 1;
13966 }
13967
13968 return 0;
13969}
13970
13971char *
13972arm_canonicalize_symbol_name (name)
13973 char * name;
13974{
13975 int len;
13976
13977 if (thumb_mode && (len = strlen (name)) > 5
13978 && streq (name + len - 5, "/data"))
13979 *(name + len - 5) = 0;
13980
13981 return name;
13982}
13983
bfc866a6 13984#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13985void
b99bd4ef
NC
13986arm_validate_fix (fixP)
13987 fixS * fixP;
13988{
13989 /* If the destination of the branch is a defined symbol which does not have
13990 the THUMB_FUNC attribute, then we must be calling a function which has
13991 the (interfacearm) attribute. We look for the Thumb entry point to that
13992 function and change the branch to refer to that function instead. */
13993 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13994 && fixP->fx_addsy != NULL
13995 && S_IS_DEFINED (fixP->fx_addsy)
13996 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13997 {
13998 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13999 }
b99bd4ef 14000}
bfc866a6 14001#endif
b99bd4ef 14002
114424c6
AM
14003int
14004arm_force_relocation (fixp)
14005 struct fix * fixp;
14006{
14007#if defined (OBJ_COFF) && defined (TE_PE)
14008 if (fixp->fx_r_type == BFD_RELOC_RVA)
14009 return 1;
14010#endif
14011#ifdef OBJ_ELF
ae6063d4 14012 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
14013 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14014 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14015 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14016 return 1;
14017#endif
14018
14019 /* Resolve these relocations even if the symbol is extern or weak. */
14020 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 14021 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
14022 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14023 return 0;
14024
ae6063d4 14025 return generic_force_reloc (fixp);
114424c6
AM
14026}
14027
b99bd4ef
NC
14028#ifdef OBJ_COFF
14029/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14030 local labels from being added to the output symbol table when they
14031 are used with the ADRL pseudo op. The ADRL relocation should always
14032 be resolved before the binbary is emitted, so it is safe to say that
14033 it is adjustable. */
14034
b34976b6 14035bfd_boolean
b99bd4ef
NC
14036arm_fix_adjustable (fixP)
14037 fixS * fixP;
14038{
14039 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14040 return 1;
14041 return 0;
14042}
14043#endif
114424c6 14044
b99bd4ef
NC
14045#ifdef OBJ_ELF
14046/* Relocations against Thumb function names must be left unadjusted,
14047 so that the linker can use this information to correctly set the
14048 bottom bit of their addresses. The MIPS version of this function
14049 also prevents relocations that are mips-16 specific, but I do not
14050 know why it does this.
14051
14052 FIXME:
14053 There is one other problem that ought to be addressed here, but
14054 which currently is not: Taking the address of a label (rather
14055 than a function) and then later jumping to that address. Such
14056 addresses also ought to have their bottom bit set (assuming that
14057 they reside in Thumb code), but at the moment they will not. */
14058
b34976b6 14059bfd_boolean
b99bd4ef
NC
14060arm_fix_adjustable (fixP)
14061 fixS * fixP;
14062{
14063 if (fixP->fx_addsy == NULL)
14064 return 1;
14065
b99bd4ef
NC
14066 if (THUMB_IS_FUNC (fixP->fx_addsy)
14067 && fixP->fx_subsy == NULL)
14068 return 0;
14069
14070 /* We need the symbol name for the VTABLE entries. */
14071 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14072 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14073 return 0;
14074
a161fe53
AM
14075 /* Don't allow symbols to be discarded on GOT related relocs. */
14076 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14077 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14078 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14079 return 0;
14080
b99bd4ef
NC
14081 return 1;
14082}
14083
14084const char *
14085elf32_arm_target_format ()
14086{
14087 if (target_big_endian)
14088 {
14089 if (target_oabi)
14090 return "elf32-bigarm-oabi";
14091 else
14092 return "elf32-bigarm";
14093 }
14094 else
14095 {
14096 if (target_oabi)
14097 return "elf32-littlearm-oabi";
14098 else
14099 return "elf32-littlearm";
14100 }
14101}
14102
14103void
14104armelf_frob_symbol (symp, puntp)
14105 symbolS * symp;
14106 int * puntp;
14107{
14108 elf_frob_symbol (symp, puntp);
14109}
14110
b99bd4ef
NC
14111static bfd_reloc_code_real_type
14112arm_parse_reloc ()
14113{
14114 char id [16];
14115 char * ip;
14116 unsigned int i;
14117 static struct
14118 {
14119 char * str;
14120 int len;
14121 bfd_reloc_code_real_type reloc;
14122 }
14123 reloc_map[] =
14124 {
14125#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14126 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14127 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14128 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14129 branch instructions generated by GCC for PLT relocs. */
14130 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14131 { NULL, 0, BFD_RELOC_UNUSED }
14132#undef MAP
14133 };
14134
14135 for (i = 0, ip = input_line_pointer;
3882b010 14136 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14137 i++, ip++)
3882b010 14138 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14139
14140 for (i = 0; reloc_map[i].str; i++)
14141 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14142 break;
14143
14144 input_line_pointer += reloc_map[i].len;
14145
14146 return reloc_map[i].reloc;
14147}
14148
14149static void
14150s_arm_elf_cons (nbytes)
14151 int nbytes;
14152{
14153 expressionS exp;
14154
14155#ifdef md_flush_pending_output
14156 md_flush_pending_output ();
14157#endif
14158
14159 if (is_it_end_of_statement ())
14160 {
14161 demand_empty_rest_of_line ();
14162 return;
14163 }
14164
14165#ifdef md_cons_align
14166 md_cons_align (nbytes);
14167#endif
14168
6057a28f 14169 mapping_state (MAP_DATA);
b99bd4ef
NC
14170 do
14171 {
14172 bfd_reloc_code_real_type reloc;
14173
14174 expression (& exp);
14175
14176 if (exp.X_op == O_symbol
14177 && * input_line_pointer == '('
14178 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14179 {
14180 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14181 int size = bfd_get_reloc_size (howto);
14182
14183 if (size > nbytes)
14184 as_bad ("%s relocations do not fit in %d bytes",
14185 howto->name, nbytes);
14186 else
14187 {
14188 register char *p = frag_more ((int) nbytes);
14189 int offset = nbytes - size;
14190
14191 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14192 &exp, 0, reloc);
14193 }
14194 }
14195 else
14196 emit_expr (&exp, (unsigned int) nbytes);
14197 }
14198 while (*input_line_pointer++ == ',');
14199
14200 /* Put terminator back into stream. */
14201 input_line_pointer --;
14202 demand_empty_rest_of_line ();
14203}
14204
14205#endif /* OBJ_ELF */
14206
14207/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14208 of an rs_align_code fragment. */
14209
14210void
14211arm_handle_align (fragP)
14212 fragS *fragP;
14213{
14214 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14215 static char const thumb_noop[2] = { 0xc0, 0x46 };
14216 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14217 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14218
14219 int bytes, fix, noop_size;
14220 char * p;
14221 const char * noop;
cc8a6dd0 14222
b99bd4ef
NC
14223 if (fragP->fr_type != rs_align_code)
14224 return;
14225
14226 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14227 p = fragP->fr_literal + fragP->fr_fix;
14228 fix = 0;
cc8a6dd0 14229
b99bd4ef
NC
14230 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14231 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14232
b99bd4ef
NC
14233 if (fragP->tc_frag_data)
14234 {
14235 if (target_big_endian)
14236 noop = thumb_bigend_noop;
14237 else
14238 noop = thumb_noop;
14239 noop_size = sizeof (thumb_noop);
14240 }
14241 else
14242 {
14243 if (target_big_endian)
14244 noop = arm_bigend_noop;
14245 else
14246 noop = arm_noop;
14247 noop_size = sizeof (arm_noop);
14248 }
cc8a6dd0 14249
b99bd4ef
NC
14250 if (bytes & (noop_size - 1))
14251 {
14252 fix = bytes & (noop_size - 1);
14253 memset (p, 0, fix);
14254 p += fix;
14255 bytes -= fix;
14256 }
14257
14258 while (bytes >= noop_size)
14259 {
14260 memcpy (p, noop, noop_size);
14261 p += noop_size;
14262 bytes -= noop_size;
14263 fix += noop_size;
14264 }
cc8a6dd0 14265
b99bd4ef
NC
14266 fragP->fr_fix += fix;
14267 fragP->fr_var = noop_size;
14268}
14269
14270/* Called from md_do_align. Used to create an alignment
14271 frag in a code section. */
14272
14273void
14274arm_frag_align_code (n, max)
14275 int n;
14276 int max;
14277{
14278 char * p;
14279
2d2255b5 14280 /* We assume that there will never be a requirement
b99bd4ef
NC
14281 to support alignments greater than 32 bytes. */
14282 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14283 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14284
b99bd4ef
NC
14285 p = frag_var (rs_align_code,
14286 MAX_MEM_FOR_RS_ALIGN_CODE,
14287 1,
14288 (relax_substateT) max,
14289 (symbolS *) NULL,
14290 (offsetT) n,
14291 (char *) NULL);
14292 *p = 0;
14293
14294}
14295
14296/* Perform target specific initialisation of a frag. */
14297
14298void
14299arm_init_frag (fragP)
14300 fragS *fragP;
14301{
14302 /* Record whether this frag is in an ARM or a THUMB area. */
14303 fragP->tc_frag_data = thumb_mode;
14304}