]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
daily update
[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)
34920d91
NC
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
b99bd4ef
NC
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
b99bd4ef
NC
27#include <string.h>
28#define NO_RELOC 0
29#include "as.h"
3882b010 30#include "safe-ctype.h"
b99bd4ef
NC
31
32/* Need TARGET_CPU. */
33#include "config.h"
34#include "subsegs.h"
35#include "obstack.h"
36#include "symbols.h"
37#include "listing.h"
38
39#ifdef OBJ_ELF
40#include "elf/arm.h"
41#include "dwarf2dbg.h"
42#endif
43
03b1477f
RE
44/* XXX Set this to 1 after the next binutils release */
45#define WARN_DEPRECATED 0
46
b89dddec
RE
47/* The following bitmasks control CPU extensions: */
48#define ARM_EXT_V1 0x00000001 /* All processors (core set). */
49#define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
50#define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
51#define ARM_EXT_V3 0x00000008 /* MSR MRS. */
52#define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
53#define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
54#define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
55#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
56#define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
57#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
58#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
ea6ef066 59#define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
09d92015 60#define ARM_EXT_V6 0x00001000 /* ARM V6. */
03b1477f
RE
61
62/* Co-processor space extensions. */
63#define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
64#define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
5a6c6817 65#define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
b89dddec
RE
66
67/* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
68 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
69 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
70 three more to cover cores prior to ARM6. Finally, there are cores which
71 implement further extensions in the co-processor space. */
72#define ARM_ARCH_V1 ARM_EXT_V1
73#define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
74#define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
75#define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
76#define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
77#define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
78#define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
79#define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
80#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
81#define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
82#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
83#define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
84#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
85#define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
86#define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
ea6ef066 87#define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
09d92015 88#define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
03b1477f 89
b89dddec 90/* Processors with specific extensions in the co-processor space. */
03b1477f 91#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
5a6c6817 92#define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
b99bd4ef
NC
93
94/* Some useful combinations: */
03b1477f
RE
95#define ARM_ANY 0x0000ffff /* Any basic core. */
96#define ARM_ALL 0x00ffffff /* Any core + co-processor */
97#define CPROC_ANY 0x00ff0000 /* Any co-processor */
98#define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
99
b99bd4ef 100
bfae80f2
RE
101#define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
102#define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
103#define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
104#define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
105#define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
106#define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
33a392fb 107#define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
bfae80f2 108#define FPU_NONE 0
b99bd4ef 109
b89dddec
RE
110#define FPU_ARCH_FPE FPU_FPA_EXT_V1
111#define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
112
bfae80f2
RE
113#define FPU_ARCH_VFP FPU_VFP_EXT_NONE
114#define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
115#define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
116#define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
117
33a392fb
PB
118#define FPU_ARCH_MAVERICK FPU_MAVERICK
119
120enum arm_float_abi
121{
122 ARM_FLOAT_ABI_HARD,
123 ARM_FLOAT_ABI_SOFTFP,
124 ARM_FLOAT_ABI_SOFT
125};
126
b89dddec
RE
127/* Types of processor to assemble for. */
128#define ARM_1 ARM_ARCH_V1
129#define ARM_2 ARM_ARCH_V2
130#define ARM_3 ARM_ARCH_V2S
131#define ARM_250 ARM_ARCH_V2S
132#define ARM_6 ARM_ARCH_V3
133#define ARM_7 ARM_ARCH_V3
134#define ARM_8 ARM_ARCH_V4
135#define ARM_9 ARM_ARCH_V4T
136#define ARM_STRONG ARM_ARCH_V4
137#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
138
139#ifndef CPU_DEFAULT
140#if defined __XSCALE__
b89dddec 141#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
142#else
143#if defined __thumb__
b89dddec 144#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 145#else
03b1477f 146#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
147#endif
148#endif
149#endif
150
39c2da32
RE
151#ifdef TE_LINUX
152#define FPU_DEFAULT FPU_ARCH_FPA
153#endif
154
155#ifdef TE_NetBSD
156#ifdef OBJ_ELF
157#define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
158#else
159/* Legacy a.out format. */
160#define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
161#endif
162#endif
163
bfae80f2 164/* For backwards compatibility we default to the FPA. */
b99bd4ef 165#ifndef FPU_DEFAULT
b89dddec 166#define FPU_DEFAULT FPU_ARCH_FPA
b99bd4ef
NC
167#endif
168
169#define streq(a, b) (strcmp (a, b) == 0)
170#define skip_whitespace(str) while (*(str) == ' ') ++(str)
171
03b1477f 172static unsigned long cpu_variant;
b99bd4ef
NC
173static int target_oabi = 0;
174
b99bd4ef 175/* Flags stored in private area of BFD structure. */
b34976b6
AM
176static int uses_apcs_26 = FALSE;
177static int atpcs = FALSE;
178static int support_interwork = FALSE;
179static int uses_apcs_float = FALSE;
180static int pic_code = FALSE;
03b1477f
RE
181
182/* Variables that we set while parsing command-line options. Once all
183 options have been read we re-process these values to set the real
184 assembly flags. */
185static int legacy_cpu = -1;
186static int legacy_fpu = -1;
187
188static int mcpu_cpu_opt = -1;
189static int mcpu_fpu_opt = -1;
190static int march_cpu_opt = -1;
191static int march_fpu_opt = -1;
192static int mfpu_opt = -1;
33a392fb 193static int mfloat_abi_opt = -1;
b99bd4ef
NC
194
195/* This array holds the chars that always start a comment. If the
196 pre-processor is disabled, these aren't very useful. */
f57c81f6 197const char comment_chars[] = "@";
b99bd4ef
NC
198
199/* This array holds the chars that only start a comment at the beginning of
200 a line. If the line seems to have the form '# 123 filename'
201 .line and .file directives will appear in the pre-processed output. */
202/* Note that input_file.c hand checks for '#' at the beginning of the
203 first line of the input file. This is because the compiler outputs
204 #NO_APP at the beginning of its output. */
205/* Also note that comments like this one will always work. */
05d2d07e 206const char line_comment_chars[] = "#";
b99bd4ef 207
da89cce1 208const char line_separator_chars[] = ";";
b99bd4ef
NC
209
210/* Chars that can be used to separate mant
211 from exp in floating point numbers. */
05d2d07e 212const char EXP_CHARS[] = "eE";
b99bd4ef
NC
213
214/* Chars that mean this number is a floating point constant. */
215/* As in 0f12.456 */
216/* or 0d1.2345e12 */
217
05d2d07e 218const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
219
220/* Prefix characters that indicate the start of an immediate
221 value. */
222#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
223
224#ifdef OBJ_ELF
225/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
226symbolS * GOT_symbol;
227#endif
228
229/* Size of relocation record. */
05d2d07e 230const int md_reloc_size = 8;
b99bd4ef
NC
231
232/* 0: assemble for ARM,
233 1: assemble for Thumb,
234 2: assemble for Thumb even though target CPU does not support thumb
235 instructions. */
236static int thumb_mode = 0;
237
238typedef struct arm_fix
239{
240 int thumb_mode;
241} arm_fix_data;
242
243struct arm_it
244{
05d2d07e 245 const char * error;
b99bd4ef 246 unsigned long instruction;
b99bd4ef
NC
247 int size;
248 struct
249 {
250 bfd_reloc_code_real_type type;
251 expressionS exp;
252 int pc_rel;
253 } reloc;
254};
255
256struct arm_it inst;
257
258enum asm_shift_index
259{
260 SHIFT_LSL = 0,
261 SHIFT_LSR,
262 SHIFT_ASR,
263 SHIFT_ROR,
264 SHIFT_RRX
265};
266
267struct asm_shift_properties
268{
269 enum asm_shift_index index;
270 unsigned long bit_field;
271 unsigned int allows_0 : 1;
272 unsigned int allows_32 : 1;
273};
274
275static const struct asm_shift_properties shift_properties [] =
276{
277 { SHIFT_LSL, 0, 1, 0},
278 { SHIFT_LSR, 0x20, 0, 1},
279 { SHIFT_ASR, 0x40, 0, 1},
280 { SHIFT_ROR, 0x60, 0, 0},
281 { SHIFT_RRX, 0x60, 0, 0}
282};
283
284struct asm_shift_name
285{
286 const char * name;
287 const struct asm_shift_properties * properties;
288};
289
290static const struct asm_shift_name shift_names [] =
291{
292 { "asl", shift_properties + SHIFT_LSL },
293 { "lsl", shift_properties + SHIFT_LSL },
294 { "lsr", shift_properties + SHIFT_LSR },
295 { "asr", shift_properties + SHIFT_ASR },
296 { "ror", shift_properties + SHIFT_ROR },
297 { "rrx", shift_properties + SHIFT_RRX },
298 { "ASL", shift_properties + SHIFT_LSL },
299 { "LSL", shift_properties + SHIFT_LSL },
300 { "LSR", shift_properties + SHIFT_LSR },
301 { "ASR", shift_properties + SHIFT_ASR },
302 { "ROR", shift_properties + SHIFT_ROR },
303 { "RRX", shift_properties + SHIFT_RRX }
304};
305
09d92015 306/* Any kind of shift is accepted. */
b99bd4ef 307#define NO_SHIFT_RESTRICT 1
09d92015
MM
308/* The shift operand must be an immediate value, not a register. */
309#define SHIFT_IMMEDIATE 0
310/* The shift must be LSL or ASR and the operand must be an immediate. */
311#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
312/* The shift must be ASR and the operand must be an immediate. */
313#define SHIFT_ASR_IMMEDIATE 3
314/* The shift must be LSL and the operand must be an immediate. */
315#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
316
317#define NUM_FLOAT_VALS 8
318
05d2d07e 319const char * fp_const[] =
b99bd4ef
NC
320{
321 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
322};
323
324/* Number of littlenums required to hold an extended precision number. */
325#define MAX_LITTLENUMS 6
326
327LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
328
329#define FAIL (-1)
330#define SUCCESS (0)
331
bfae80f2
RE
332/* Whether a Co-processor load/store operation accepts write-back forms. */
333#define CP_WB_OK 1
334#define CP_NO_WB 0
335
b99bd4ef
NC
336#define SUFF_S 1
337#define SUFF_D 2
338#define SUFF_E 3
339#define SUFF_P 4
340
341#define CP_T_X 0x00008000
342#define CP_T_Y 0x00400000
343#define CP_T_Pre 0x01000000
344#define CP_T_UD 0x00800000
345#define CP_T_WB 0x00200000
346
347#define CONDS_BIT 0x00100000
348#define LOAD_BIT 0x00100000
b99bd4ef
NC
349
350#define DOUBLE_LOAD_FLAG 0x00000001
351
352struct asm_cond
353{
05d2d07e 354 const char * template;
b99bd4ef
NC
355 unsigned long value;
356};
357
b99bd4ef 358#define COND_ALWAYS 0xe0000000
90e4755a 359#define COND_MASK 0xf0000000
b99bd4ef 360
05d2d07e 361static const struct asm_cond conds[] =
b99bd4ef
NC
362{
363 {"eq", 0x00000000},
364 {"ne", 0x10000000},
365 {"cs", 0x20000000}, {"hs", 0x20000000},
366 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
367 {"mi", 0x40000000},
368 {"pl", 0x50000000},
369 {"vs", 0x60000000},
370 {"vc", 0x70000000},
371 {"hi", 0x80000000},
372 {"ls", 0x90000000},
373 {"ge", 0xa0000000},
374 {"lt", 0xb0000000},
375 {"gt", 0xc0000000},
376 {"le", 0xd0000000},
377 {"al", 0xe0000000},
378 {"nv", 0xf0000000}
379};
380
b99bd4ef
NC
381struct asm_psr
382{
b34976b6
AM
383 const char *template;
384 bfd_boolean cpsr;
b99bd4ef
NC
385 unsigned long field;
386};
387
2d2255b5 388/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
389#define SPSR_BIT (1 << 22)
390
391/* How many bits to shift the PSR_xxx bits up by. */
392#define PSR_SHIFT 16
393
394#define PSR_c (1 << 0)
395#define PSR_x (1 << 1)
396#define PSR_s (1 << 2)
397#define PSR_f (1 << 3)
398
05d2d07e 399static const struct asm_psr psrs[] =
b99bd4ef 400{
b34976b6
AM
401 {"CPSR", TRUE, PSR_c | PSR_f},
402 {"CPSR_all", TRUE, PSR_c | PSR_f},
403 {"SPSR", FALSE, PSR_c | PSR_f},
404 {"SPSR_all", FALSE, PSR_c | PSR_f},
405 {"CPSR_flg", TRUE, PSR_f},
406 {"CPSR_f", TRUE, PSR_f},
407 {"SPSR_flg", FALSE, PSR_f},
408 {"SPSR_f", FALSE, PSR_f},
409 {"CPSR_c", TRUE, PSR_c},
410 {"CPSR_ctl", TRUE, PSR_c},
411 {"SPSR_c", FALSE, PSR_c},
412 {"SPSR_ctl", FALSE, PSR_c},
413 {"CPSR_x", TRUE, PSR_x},
414 {"CPSR_s", TRUE, PSR_s},
415 {"SPSR_x", FALSE, PSR_x},
416 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 417 /* Combinations of flags. */
b34976b6
AM
418 {"CPSR_fs", TRUE, PSR_f | PSR_s},
419 {"CPSR_fx", TRUE, PSR_f | PSR_x},
420 {"CPSR_fc", TRUE, PSR_f | PSR_c},
421 {"CPSR_sf", TRUE, PSR_s | PSR_f},
422 {"CPSR_sx", TRUE, PSR_s | PSR_x},
423 {"CPSR_sc", TRUE, PSR_s | PSR_c},
424 {"CPSR_xf", TRUE, PSR_x | PSR_f},
425 {"CPSR_xs", TRUE, PSR_x | PSR_s},
426 {"CPSR_xc", TRUE, PSR_x | PSR_c},
427 {"CPSR_cf", TRUE, PSR_c | PSR_f},
428 {"CPSR_cs", TRUE, PSR_c | PSR_s},
429 {"CPSR_cx", TRUE, PSR_c | PSR_x},
430 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
431 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
432 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
433 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
434 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
435 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
436 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
437 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
438 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
439 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
440 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
441 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
442 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
443 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
444 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
445 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
446 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
447 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
448 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
449 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
450 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
451 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
452 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
453 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
454 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
455 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
456 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
457 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
458 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
459 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
460 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
461 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
462 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
463 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
464 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
465 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
466 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
467 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
468 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
469 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
470 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
471 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
472 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
473 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
474 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
475 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
476 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
477 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
478 {"SPSR_fs", FALSE, PSR_f | PSR_s},
479 {"SPSR_fx", FALSE, PSR_f | PSR_x},
480 {"SPSR_fc", FALSE, PSR_f | PSR_c},
481 {"SPSR_sf", FALSE, PSR_s | PSR_f},
482 {"SPSR_sx", FALSE, PSR_s | PSR_x},
483 {"SPSR_sc", FALSE, PSR_s | PSR_c},
484 {"SPSR_xf", FALSE, PSR_x | PSR_f},
485 {"SPSR_xs", FALSE, PSR_x | PSR_s},
486 {"SPSR_xc", FALSE, PSR_x | PSR_c},
487 {"SPSR_cf", FALSE, PSR_c | PSR_f},
488 {"SPSR_cs", FALSE, PSR_c | PSR_s},
489 {"SPSR_cx", FALSE, PSR_c | PSR_x},
490 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
491 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
492 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
493 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
494 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
495 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
496 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
497 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
498 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
499 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
500 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
501 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
502 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
503 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
504 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
505 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
506 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
507 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
508 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
509 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
510 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
511 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
512 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
513 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
514 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
515 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
516 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
517 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
518 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
519 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
520 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
521 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
522 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
523 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
524 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
525 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
526 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
527 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
528 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
529 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
530 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
531 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
532 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
533 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
534 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
535 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
536 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
537 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
538};
539
e16bb312
NC
540enum wreg_type
541 {
542 IWMMXT_REG_WR = 0,
543 IWMMXT_REG_WC = 1,
544 IWMMXT_REG_WR_OR_WC = 2,
545 IWMMXT_REG_WCG
546 };
547
548enum iwmmxt_insn_type
549{
550 check_rd,
551 check_wr,
552 check_wrwr,
553 check_wrwrwr,
554 check_wrwrwcg,
555 check_tbcst,
556 check_tmovmsk,
557 check_tmia,
558 check_tmcrr,
559 check_tmrrc,
560 check_tmcr,
561 check_tmrc,
562 check_tinsr,
563 check_textrc,
564 check_waligni,
565 check_textrm,
566 check_wshufh
567};
568
bfae80f2
RE
569enum vfp_dp_reg_pos
570{
571 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
572};
573
574enum vfp_sp_reg_pos
575{
576 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
577};
578
579enum vfp_ldstm_type
580{
581 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
582};
583
584/* VFP system registers. */
585struct vfp_reg
586{
587 const char *name;
588 unsigned long regno;
589};
590
cc8a6dd0 591static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
592{
593 {"fpsid", 0x00000000},
594 {"FPSID", 0x00000000},
595 {"fpscr", 0x00010000},
596 {"FPSCR", 0x00010000},
597 {"fpexc", 0x00080000},
598 {"FPEXC", 0x00080000}
599};
600
6c43fab6
RE
601/* Structure for a hash table entry for a register. */
602struct reg_entry
603{
604 const char * name;
605 int number;
0bbf2aa4 606 bfd_boolean builtin;
6c43fab6
RE
607};
608
e28cd48c 609/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
610#define REG_SP 13
611#define REG_LR 14
612#define REG_PC 15
613
e16bb312
NC
614#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
615#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
616#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
617
0bbf2aa4
NC
618/* These are the standard names. Users can add aliases with .req.
619 and delete them with .unreq. */
620
6c43fab6
RE
621/* Integer Register Numbers. */
622static const struct reg_entry rn_table[] =
623{
0bbf2aa4
NC
624 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
625 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
626 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
627 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 628 /* ATPCS Synonyms. */
0bbf2aa4
NC
629 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
630 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
631 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 632 /* Well-known aliases. */
0bbf2aa4
NC
633 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
634 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
635 {NULL, 0, TRUE}
6c43fab6
RE
636};
637
e16bb312
NC
638#define WR_PREFIX 0x200
639#define WC_PREFIX 0x400
640
641static const struct reg_entry iwmmxt_table[] =
642{
5a6c6817 643 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
644 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
645 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
646 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
647 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
648 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
649 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
650 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
651 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
652 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
653 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
654 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
655 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
656
657 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
658 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
659 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
660 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
661 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
662 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
663 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
664 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
665 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
666 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
667 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
668 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
669 {NULL, 0, TRUE}
e16bb312
NC
670};
671
6c43fab6
RE
672/* Co-processor Numbers. */
673static const struct reg_entry cp_table[] =
674{
0bbf2aa4
NC
675 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
676 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
677 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
678 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
679 {NULL, 0, TRUE}
6c43fab6
RE
680};
681
682/* Co-processor Register Numbers. */
683static const struct reg_entry cn_table[] =
684{
0bbf2aa4
NC
685 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
686 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
687 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
688 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 689 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
690 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
691 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
692 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
693 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
694 {NULL, 0, TRUE}
6c43fab6
RE
695};
696
697/* FPA Registers. */
698static const struct reg_entry fn_table[] =
699{
0bbf2aa4
NC
700 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
701 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
702 {NULL, 0, TRUE}
6c43fab6
RE
703};
704
bfae80f2
RE
705/* VFP SP Registers. */
706static const struct reg_entry sn_table[] =
707{
0bbf2aa4
NC
708 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
709 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
710 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
711 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
712 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
713 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
714 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
715 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
716 {NULL, 0, TRUE}
bfae80f2
RE
717};
718
719/* VFP DP Registers. */
720static const struct reg_entry dn_table[] =
721{
0bbf2aa4
NC
722 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
723 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
724 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
725 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
726 {NULL, 0, TRUE}
bfae80f2
RE
727};
728
63e63b07 729/* Maverick DSP coprocessor registers. */
6c43fab6
RE
730static const struct reg_entry mav_mvf_table[] =
731{
0bbf2aa4
NC
732 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
733 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
734 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
735 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
736 {NULL, 0, TRUE}
6c43fab6
RE
737};
738
739static const struct reg_entry mav_mvd_table[] =
740{
0bbf2aa4
NC
741 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
742 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
743 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
744 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
745 {NULL, 0, TRUE}
6c43fab6
RE
746};
747
748static const struct reg_entry mav_mvfx_table[] =
749{
0bbf2aa4
NC
750 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
751 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
752 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
753 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
754 {NULL, 0, TRUE}
6c43fab6
RE
755};
756
757static const struct reg_entry mav_mvdx_table[] =
758{
0bbf2aa4
NC
759 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
760 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
761 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
762 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
763 {NULL, 0, TRUE}
6c43fab6
RE
764};
765
766static const struct reg_entry mav_mvax_table[] =
767{
0bbf2aa4
NC
768 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
769 {NULL, 0, TRUE}
6c43fab6
RE
770};
771
772static const struct reg_entry mav_dspsc_table[] =
773{
0bbf2aa4
NC
774 {"dspsc", 0, TRUE},
775 {NULL, 0, TRUE}
6c43fab6
RE
776};
777
778struct reg_map
779{
780 const struct reg_entry *names;
781 int max_regno;
782 struct hash_control *htab;
783 const char *expected;
784};
785
786struct reg_map all_reg_maps[] =
787{
788 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
789 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
790 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 791 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
792 {sn_table, 31, NULL, N_("VFP single precision register expected")},
793 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
794 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
795 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
796 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 797 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
798 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
799 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 800 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
801};
802
803/* Enumeration matching entries in table above. */
804enum arm_reg_type
805{
806 REG_TYPE_RN = 0,
807#define REG_TYPE_FIRST REG_TYPE_RN
808 REG_TYPE_CP = 1,
809 REG_TYPE_CN = 2,
810 REG_TYPE_FN = 3,
bfae80f2
RE
811 REG_TYPE_SN = 4,
812 REG_TYPE_DN = 5,
813 REG_TYPE_MVF = 6,
814 REG_TYPE_MVD = 7,
815 REG_TYPE_MVFX = 8,
816 REG_TYPE_MVDX = 9,
817 REG_TYPE_MVAX = 10,
818 REG_TYPE_DSPSC = 11,
e16bb312 819 REG_TYPE_IWMMXT = 12,
bfae80f2 820
e16bb312 821 REG_TYPE_MAX = 13
6c43fab6 822};
404ff6b5 823
b99bd4ef
NC
824/* Functions called by parser. */
825/* ARM instructions. */
f2b7cb0a
RE
826static void do_arit PARAMS ((char *));
827static void do_cmp PARAMS ((char *));
828static void do_mov PARAMS ((char *));
829static void do_ldst PARAMS ((char *));
830static void do_ldstt PARAMS ((char *));
831static void do_ldmstm PARAMS ((char *));
832static void do_branch PARAMS ((char *));
833static void do_swi PARAMS ((char *));
c9b604bd 834
b99bd4ef 835/* Pseudo Op codes. */
f2b7cb0a
RE
836static void do_adr PARAMS ((char *));
837static void do_adrl PARAMS ((char *));
838static void do_empty PARAMS ((char *));
c9b604bd
RE
839
840/* ARM v2. */
f2b7cb0a
RE
841static void do_mul PARAMS ((char *));
842static void do_mla PARAMS ((char *));
c9b604bd
RE
843
844/* ARM v2S. */
f2b7cb0a 845static void do_swap PARAMS ((char *));
c9b604bd
RE
846
847/* ARM v3. */
f2b7cb0a
RE
848static void do_msr PARAMS ((char *));
849static void do_mrs PARAMS ((char *));
c9b604bd
RE
850
851/* ARM v3M. */
f2b7cb0a 852static void do_mull PARAMS ((char *));
b99bd4ef 853
90e4755a 854/* ARM v4. */
f2b7cb0a 855static void do_ldstv4 PARAMS ((char *));
90e4755a 856
c9b604bd 857/* ARM v4T. */
f2b7cb0a 858static void do_bx PARAMS ((char *));
b99bd4ef 859
ea6ef066 860/* ARM v5T. */
f2b7cb0a
RE
861static void do_blx PARAMS ((char *));
862static void do_bkpt PARAMS ((char *));
863static void do_clz PARAMS ((char *));
864static void do_lstc2 PARAMS ((char *));
865static void do_cdp2 PARAMS ((char *));
866static void do_co_reg2 PARAMS ((char *));
b99bd4ef 867
ea6ef066 868/* ARM v5TExP. */
f2b7cb0a
RE
869static void do_smla PARAMS ((char *));
870static void do_smlal PARAMS ((char *));
871static void do_smul PARAMS ((char *));
872static void do_qadd PARAMS ((char *));
c9b604bd 873
ea6ef066 874/* ARM v5TE. */
f2b7cb0a
RE
875static void do_pld PARAMS ((char *));
876static void do_ldrd PARAMS ((char *));
877static void do_co_reg2c PARAMS ((char *));
b99bd4ef 878
ea6ef066
RE
879/* ARM v5TEJ. */
880static void do_bxj PARAMS ((char *));
881
09d92015
MM
882/* ARM V6. */
883static void do_cps PARAMS ((char *));
884static void do_cpsi PARAMS ((char *));
885static void do_ldrex PARAMS ((char *));
886static void do_pkhbt PARAMS ((char *));
887static void do_pkhtb PARAMS ((char *));
888static void do_qadd16 PARAMS ((char *));
889static void do_rev PARAMS ((char *));
890static void do_rfe PARAMS ((char *));
891static void do_sxtah PARAMS ((char *));
892static void do_sxth PARAMS ((char *));
893static void do_setend PARAMS ((char *));
894static void do_smlad PARAMS ((char *));
895static void do_smlald PARAMS ((char *));
896static void do_smmul PARAMS ((char *));
897static void do_ssat PARAMS ((char *));
898static void do_usat PARAMS ((char *));
899static void do_srs PARAMS ((char *));
900static void do_ssat16 PARAMS ((char *));
901static void do_usat16 PARAMS ((char *));
902static void do_strex PARAMS ((char *));
903static void do_umaal PARAMS ((char *));
904
905static void do_cps_mode PARAMS ((char **));
906static void do_cps_flags PARAMS ((char **, int));
907static int do_endian_specifier PARAMS ((char *));
908static void do_pkh_core PARAMS ((char *, int));
909static void do_sat PARAMS ((char **, int));
910static void do_sat16 PARAMS ((char **, int));
911
b99bd4ef 912/* Coprocessor Instructions. */
f2b7cb0a
RE
913static void do_cdp PARAMS ((char *));
914static void do_lstc PARAMS ((char *));
915static void do_co_reg PARAMS ((char *));
c9b604bd
RE
916
917/* FPA instructions. */
f2b7cb0a
RE
918static void do_fpa_ctrl PARAMS ((char *));
919static void do_fpa_ldst PARAMS ((char *));
920static void do_fpa_ldmstm PARAMS ((char *));
921static void do_fpa_dyadic PARAMS ((char *));
922static void do_fpa_monadic PARAMS ((char *));
923static void do_fpa_cmp PARAMS ((char *));
924static void do_fpa_from_reg PARAMS ((char *));
925static void do_fpa_to_reg PARAMS ((char *));
c9b604bd 926
bfae80f2
RE
927/* VFP instructions. */
928static void do_vfp_sp_monadic PARAMS ((char *));
929static void do_vfp_dp_monadic PARAMS ((char *));
930static void do_vfp_sp_dyadic PARAMS ((char *));
931static void do_vfp_dp_dyadic PARAMS ((char *));
932static void do_vfp_reg_from_sp PARAMS ((char *));
933static void do_vfp_sp_from_reg PARAMS ((char *));
e45d0630
PB
934static void do_vfp_reg2_from_sp2 PARAMS ((char *));
935static void do_vfp_sp2_from_reg2 PARAMS ((char *));
bfae80f2
RE
936static void do_vfp_reg_from_dp PARAMS ((char *));
937static void do_vfp_reg2_from_dp PARAMS ((char *));
938static void do_vfp_dp_from_reg PARAMS ((char *));
939static void do_vfp_dp_from_reg2 PARAMS ((char *));
940static void do_vfp_reg_from_ctrl PARAMS ((char *));
941static void do_vfp_ctrl_from_reg PARAMS ((char *));
942static void do_vfp_sp_ldst PARAMS ((char *));
943static void do_vfp_dp_ldst PARAMS ((char *));
944static void do_vfp_sp_ldstmia PARAMS ((char *));
945static void do_vfp_sp_ldstmdb PARAMS ((char *));
946static void do_vfp_dp_ldstmia PARAMS ((char *));
947static void do_vfp_dp_ldstmdb PARAMS ((char *));
948static void do_vfp_xp_ldstmia PARAMS ((char *));
949static void do_vfp_xp_ldstmdb PARAMS ((char *));
950static void do_vfp_sp_compare_z PARAMS ((char *));
951static void do_vfp_dp_compare_z PARAMS ((char *));
952static void do_vfp_dp_sp_cvt PARAMS ((char *));
953static void do_vfp_sp_dp_cvt PARAMS ((char *));
954
c9b604bd 955/* XScale. */
63e63b07
RE
956static void do_xsc_mia PARAMS ((char *));
957static void do_xsc_mar PARAMS ((char *));
958static void do_xsc_mra PARAMS ((char *));
f2b7cb0a
RE
959
960/* Maverick. */
63e63b07 961static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
6c43fab6 962 enum arm_reg_type));
63e63b07
RE
963static void do_mav_binops_1a PARAMS ((char *));
964static void do_mav_binops_1b PARAMS ((char *));
965static void do_mav_binops_1c PARAMS ((char *));
966static void do_mav_binops_1d PARAMS ((char *));
967static void do_mav_binops_1e PARAMS ((char *));
968static void do_mav_binops_1f PARAMS ((char *));
969static void do_mav_binops_1g PARAMS ((char *));
970static void do_mav_binops_1h PARAMS ((char *));
971static void do_mav_binops_1i PARAMS ((char *));
972static void do_mav_binops_1j PARAMS ((char *));
973static void do_mav_binops_1k PARAMS ((char *));
974static void do_mav_binops_1l PARAMS ((char *));
975static void do_mav_binops_1m PARAMS ((char *));
976static void do_mav_binops_1n PARAMS ((char *));
977static void do_mav_binops_1o PARAMS ((char *));
978static void do_mav_binops_2a PARAMS ((char *));
979static void do_mav_binops_2b PARAMS ((char *));
980static void do_mav_binops_2c PARAMS ((char *));
981static void do_mav_binops_3a PARAMS ((char *));
982static void do_mav_binops_3b PARAMS ((char *));
983static void do_mav_binops_3c PARAMS ((char *));
984static void do_mav_binops_3d PARAMS ((char *));
cc8a6dd0 985static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
986 enum arm_reg_type,
987 enum arm_reg_type));
63e63b07
RE
988static void do_mav_triple_4a PARAMS ((char *));
989static void do_mav_triple_4b PARAMS ((char *));
990static void do_mav_triple_5a PARAMS ((char *));
991static void do_mav_triple_5b PARAMS ((char *));
992static void do_mav_triple_5c PARAMS ((char *));
993static void do_mav_triple_5d PARAMS ((char *));
994static void do_mav_triple_5e PARAMS ((char *));
995static void do_mav_triple_5f PARAMS ((char *));
996static void do_mav_triple_5g PARAMS ((char *));
997static void do_mav_triple_5h PARAMS ((char *));
cc8a6dd0 998static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
999 enum arm_reg_type,
1000 enum arm_reg_type,
1001 enum arm_reg_type));
63e63b07
RE
1002static void do_mav_quad_6a PARAMS ((char *));
1003static void do_mav_quad_6b PARAMS ((char *));
1004static void do_mav_dspsc_1 PARAMS ((char *));
1005static void do_mav_dspsc_2 PARAMS ((char *));
1006static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
6c43fab6 1007 enum arm_reg_type));
63e63b07
RE
1008static void do_mav_shift_1 PARAMS ((char *));
1009static void do_mav_shift_2 PARAMS ((char *));
1010static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1011static void do_mav_ldst_1 PARAMS ((char *));
1012static void do_mav_ldst_2 PARAMS ((char *));
1013static void do_mav_ldst_3 PARAMS ((char *));
1014static void do_mav_ldst_4 PARAMS ((char *));
1015
1016static int mav_reg_required_here PARAMS ((char **, int,
6c43fab6 1017 enum arm_reg_type));
63e63b07 1018static int mav_parse_offset PARAMS ((char **, int *));
404ff6b5 1019
90e4755a
RE
1020static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1021 int, int));
6c43fab6
RE
1022static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1023static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
05d2d07e 1024static const struct asm_psr * arm_psr_parse PARAMS ((char **));
90e4755a
RE
1025static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1026 fragS *));
b99bd4ef
NC
1027static int add_to_lit_pool PARAMS ((void));
1028static unsigned validate_immediate PARAMS ((unsigned));
90e4755a
RE
1029static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1030 unsigned int *));
b99bd4ef
NC
1031static int validate_offset_imm PARAMS ((unsigned int, int));
1032static void opcode_select PARAMS ((int));
1033static void end_of_line PARAMS ((char *));
1034static int reg_required_here PARAMS ((char **, int));
1035static int psr_required_here PARAMS ((char **));
1036static int co_proc_number PARAMS ((char **));
1037static int cp_opc_expr PARAMS ((char **, int, int));
1038static int cp_reg_required_here PARAMS ((char **, int));
1039static int fp_reg_required_here PARAMS ((char **, int));
bfae80f2
RE
1040static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1041static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1042static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1043static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1044static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1045static long vfp_dp_reg_list PARAMS ((char **));
1046static int vfp_psr_required_here PARAMS ((char **str));
1047static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
b99bd4ef 1048static int cp_address_offset PARAMS ((char **));
bfae80f2 1049static int cp_address_required_here PARAMS ((char **, int));
b99bd4ef
NC
1050static int my_get_float_expression PARAMS ((char **));
1051static int skip_past_comma PARAMS ((char **));
1052static int walk_no_bignums PARAMS ((symbolS *));
1053static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1054static int data_op2 PARAMS ((char **));
1055static int fp_op2 PARAMS ((char **));
1056static long reg_list PARAMS ((char **));
1057static void thumb_load_store PARAMS ((char *, int, int));
1058static int decode_shift PARAMS ((char **, int));
90e4755a
RE
1059static int ldst_extend PARAMS ((char **));
1060static int ldst_extend_v4 PARAMS ((char **));
b99bd4ef 1061static void thumb_add_sub PARAMS ((char *, int));
6c43fab6
RE
1062static void insert_reg PARAMS ((const struct reg_entry *,
1063 struct hash_control *));
b99bd4ef
NC
1064static void thumb_shift PARAMS ((char *, int));
1065static void thumb_mov_compare PARAMS ((char *, int));
f2b7cb0a 1066static void build_arm_ops_hsh PARAMS ((void));
b99bd4ef
NC
1067static void set_constant_flonums PARAMS ((void));
1068static valueT md_chars_to_number PARAMS ((char *, int));
6c43fab6
RE
1069static void build_reg_hsh PARAMS ((struct reg_map *));
1070static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1071static int create_register_alias PARAMS ((char *, char *));
f03698e6 1072static void output_inst PARAMS ((const char *));
2c20dfb2
NC
1073static int accum0_required_here PARAMS ((char **));
1074static int ld_mode_required_here PARAMS ((char **));
f2b7cb0a 1075static void do_branch25 PARAMS ((char *));
2c20dfb2 1076static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
1077#ifdef OBJ_ELF
1078static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1079#endif
1080
e16bb312
NC
1081static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1082static void do_iwmmxt_byte_addr PARAMS ((char *));
1083static void do_iwmmxt_tandc PARAMS ((char *));
1084static void do_iwmmxt_tbcst PARAMS ((char *));
1085static void do_iwmmxt_textrc PARAMS ((char *));
1086static void do_iwmmxt_textrm PARAMS ((char *));
1087static void do_iwmmxt_tinsr PARAMS ((char *));
1088static void do_iwmmxt_tmcr PARAMS ((char *));
1089static void do_iwmmxt_tmcrr PARAMS ((char *));
1090static void do_iwmmxt_tmia PARAMS ((char *));
1091static void do_iwmmxt_tmovmsk PARAMS ((char *));
1092static void do_iwmmxt_tmrc PARAMS ((char *));
1093static void do_iwmmxt_tmrrc PARAMS ((char *));
1094static void do_iwmmxt_torc PARAMS ((char *));
1095static void do_iwmmxt_waligni PARAMS ((char *));
1096static void do_iwmmxt_wmov PARAMS ((char *));
1097static void do_iwmmxt_word_addr PARAMS ((char *));
1098static void do_iwmmxt_wrwr PARAMS ((char *));
1099static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1100static void do_iwmmxt_wrwrwr PARAMS ((char *));
1101static void do_iwmmxt_wshufh PARAMS ((char *));
1102static void do_iwmmxt_wzero PARAMS ((char *));
1103static int cp_byte_address_offset PARAMS ((char **));
1104static int cp_byte_address_required_here PARAMS ((char **));
1105
b99bd4ef
NC
1106/* ARM instructions take 4bytes in the object file, Thumb instructions
1107 take 2: */
1108#define INSN_SIZE 4
1109
404ff6b5 1110/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 1111#define MAV_MODE1 0x100c
404ff6b5
AH
1112
1113/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 1114#define MAV_MODE2 0x0c10
404ff6b5 1115
34920d91
NC
1116/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1117#define MAV_MODE3 0x100c
404ff6b5
AH
1118
1119/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 1120#define MAV_MODE4 0x0c0010
404ff6b5
AH
1121
1122/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 1123#define MAV_MODE5 0x00100c
404ff6b5
AH
1124
1125/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 1126#define MAV_MODE6 0x00100c05
b99bd4ef
NC
1127
1128struct asm_opcode
1129{
1130 /* Basic string to match. */
05d2d07e 1131 const char * template;
b99bd4ef
NC
1132
1133 /* Basic instruction code. */
1134 unsigned long value;
1135
90e4755a
RE
1136 /* Offset into the template where the condition code (if any) will be.
1137 If zero, then the instruction is never conditional. */
1138 unsigned cond_offset;
b99bd4ef 1139
90e4755a
RE
1140 /* Which architecture variant provides this instruction. */
1141 unsigned long variant;
b99bd4ef
NC
1142
1143 /* Function to call to parse args. */
f2b7cb0a 1144 void (* parms) PARAMS ((char *));
b99bd4ef
NC
1145};
1146
05d2d07e 1147static const struct asm_opcode insns[] =
b99bd4ef 1148{
c9b604bd 1149 /* Core ARM Instructions. */
90e4755a
RE
1150 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1151 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1152 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1153 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1154 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1155 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1156 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1157 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1158 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1159 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1160 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1161 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1162 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1163 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1164 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1165 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1166 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1167 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1168 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1169 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1170
1171 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1172 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1173 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1174 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1175 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1176 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1177 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1178 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1179 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1183
1184 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1185 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1186 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1187 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1188
1189 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1190 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1191 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1192 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1193 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1194 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1195 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1196 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1197
1198 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1201 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1206
1207 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1209 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1215
1216 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
b99bd4ef 1217#ifdef TE_WINCE
c9b604bd 1218 /* XXX This is the wrong place to do this. Think multi-arch. */
90e4755a
RE
1219 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1220 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
b99bd4ef 1221#else
90e4755a
RE
1222 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1223 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
b99bd4ef
NC
1224#endif
1225
c9b604bd 1226 /* Pseudo ops. */
90e4755a
RE
1227 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1228 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1229 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
b99bd4ef 1230
c9b604bd 1231 /* ARM 2 multiplies. */
90e4755a
RE
1232 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1233 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1234 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1235 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 1236
67c1ffbe 1237 /* Generic coprocessor instructions. */
90e4755a
RE
1238 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1239 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1240 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1241 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1242 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1243 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1244 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
c9b604bd
RE
1245
1246 /* ARM 3 - swp instructions. */
90e4755a
RE
1247 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1248 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 1249
c9b604bd 1250 /* ARM 6 Status register instructions. */
90e4755a
RE
1251 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1252 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1253 /* ScottB: our code uses 0xe128f000 for msr.
c9b604bd 1254 NickC: but this is wrong because the bits 16 through 19 are
90e4755a 1255 handled by the PSR_xxx defines above. */
b99bd4ef 1256
f2b7cb0a 1257 /* ARM 7M long multiplies. */
90e4755a
RE
1258 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1259 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1260 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1261 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1262 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1263 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1264 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1265 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1266
1267 /* ARM Architecture 4. */
1268 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1269 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1270 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1271 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 1272
c9b604bd 1273 /* ARM Architecture 4T. */
cc8a6dd0 1274 /* Note: bx (and blx) are required on V5, even if the processor does
90e4755a
RE
1275 not support Thumb. */
1276 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1277
ea6ef066 1278 /* ARM Architecture 5T. */
90e4755a
RE
1279 /* Note: blx has 2 variants, so the .value is set dynamically.
1280 Only one of the variants has conditional execution. */
1281 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1282 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1283 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1284 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1285 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1286 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1287 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1288 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1289 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1290 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1291
ea6ef066 1292 /* ARM Architecture 5TExP. */
90e4755a
RE
1293 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1294 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1295 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1296 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1297
1298 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1299 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1300
1301 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1302 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1303 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1304 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1305
1306 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1307 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1308 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1309 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1310
1311 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1312 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1313
1314 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1315 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1316 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1317 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
c9b604bd 1318
ea6ef066 1319 /* ARM Architecture 5TE. */
90e4755a
RE
1320 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1321 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1322 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1323
1324 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1325 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
404ff6b5 1326
ea6ef066
RE
1327 /* ARM Architecture 5TEJ. */
1328 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1329
09d92015
MM
1330 /* ARM V6. */
1331 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1332 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1333 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1334 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1335 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1336 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1337 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1338 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1339 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1340 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1341 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1342 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1343 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1344 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1345 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1346 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1347 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1348 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1349 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1350 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1351 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1352 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1353 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1354 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1355 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1356 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1357 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1358 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1359 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1360 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1361 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1362 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1363 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1364 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1365 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1366 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1367 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1368 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1369 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1370 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1371 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1372 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1373 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1374 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1375 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1376 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1377 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1378 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1379 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1380 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1381 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1386 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1387 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1388 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1389 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1390 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1391 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1392 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1393 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1394 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1395 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1396 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1397 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1398 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1399 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1400 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1401 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1402 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1403 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1404 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1405 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1406 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1407 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1408 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1409 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1410 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1411 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1412 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1413 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1414 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1415 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1416 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1417 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1418 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1419 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1420 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1421 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1422 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1423 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1424 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1425 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1426 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1427 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1428 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1429 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1430
c9b604bd 1431 /* Core FPA instruction set (V1). */
90e4755a
RE
1432 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1433 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1434 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1435 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436
1437 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1438 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1439 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1440 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441
1442 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1445 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446
1447 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459
1460 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472
1473 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485
1486 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498
1499 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511
1512 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524
1525 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537
1538 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550
1551 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563
1564 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576
1577 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589
1590 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602
1603 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615
1616 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628
1629 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641
1642 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654
1655 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667
1668 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680
1681 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693
1694 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706
1707 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719
1720 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732
1733 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745
1746 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758
1759 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771
1772 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784
1785 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797
1798 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810
1811 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823
1824 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1825 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1826 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1827 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1829 not be an optional suffix, but part of the instruction. To be
1830 compatible, we accept either. */
1831 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1832 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1833
1834 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1835 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1836 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1837 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846
1847 /* The implementation of the FIX instruction is broken on some
1848 assemblers, in that it accepts a precision specifier as well as a
1849 rounding specifier, despite the fact that this is meaningless.
1850 To be more compatible, we accept it as well, though of course it
1851 does not set any bits. */
1852 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1853 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1854 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1855 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
c9b604bd
RE
1865
1866 /* Instructions that were new with the real FPA, call them V2. */
90e4755a
RE
1867 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1868 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1869 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1870 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
c9b604bd 1873
bfae80f2
RE
1874 /* VFP V1xD (single precision). */
1875 /* Moves and type conversions. */
1876 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1877 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1878 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1879 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1880 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1881 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1887 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1888
1889 /* Memory operations. */
1890 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1891 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1892 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1893 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1894 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1895 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1896 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1897 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1898 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1899 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1900 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1901 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1902 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1903 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1904 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1905 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1906 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1907 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1908
1909 /* Monadic operations. */
1910 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1911 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1912 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913
1914 /* Dyadic operations. */
1915 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1916 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924
1925 /* Comparisons. */
1926 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1927 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1928 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1929 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1930
1931 /* VFP V1 (Double precision). */
1932 /* Moves and type conversions. */
1933 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1934 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1935 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1936 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1937 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1938 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1939 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1940 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1941 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1942 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1943 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1944 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1945 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946
1947 /* Memory operations. */
1948 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1949 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1950 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1951 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1952 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1953 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1954 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1955 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1956 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1957 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1958
1959 /* Monadic operations. */
1960 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1961 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1962 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1963
1964 /* Dyadic operations. */
1965 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1966 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1967 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1968 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974
1975 /* Comparisons. */
1976 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1977 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1978 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1979 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1980
1981 /* VFP V2. */
e45d0630
PB
1982 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1983 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
bfae80f2
RE
1984 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1985 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1986
c9b604bd 1987 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
63e63b07
RE
1988 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1989 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1990 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1991 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1995 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1996
5a6c6817
NC
1997 /* Intel Wireless MMX technology instructions. */
1998 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1999 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2000 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2001 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2002 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2003 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2004 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2005 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2006 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2007 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2008 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2014 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2015 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2016 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2017 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2018 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2019 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2025 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2026 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2027 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2028 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2029 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2030 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2031 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2032 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2033 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2034 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2035 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2045 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2065 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2066 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2067 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2068 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2087 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2100 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2102 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2103 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2104 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2105 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2107 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2109 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2114 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2115 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2116 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2117 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2119 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2121 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2123 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2125 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2126 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2127 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2128 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2129 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2130 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2131 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2132 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2147 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2148 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2149 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2150 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2156 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2157 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2158 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2160
63e63b07
RE
2161 /* Cirrus Maverick instructions. */
2162 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2163 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2164 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2165 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2166 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2167 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2168 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2169 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2170 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2171 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2172 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2173 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2174 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2175 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2176 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2177 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2178 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2179 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
34920d91
NC
2180 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2181 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2182 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2183 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2184 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2185 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2186 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2187 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2188 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2189 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2190 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2191 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
63e63b07
RE
2192 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2193 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2194 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2195 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2196 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2197 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2198 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2199 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2200 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2201 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2202 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2203 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2204 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2205 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2206 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2207 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2208 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2209 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2210 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2211 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2212 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2213 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2214 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2215 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2216 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2217 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2218 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2219 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2220 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2221 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2222 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2223 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2224 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2225 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2226 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2227 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2228 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2229 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2230 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2231 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2232 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2233 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2235 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2236 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2237 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
b99bd4ef
NC
2238};
2239
2240/* Defines for various bits that we will want to toggle. */
2241#define INST_IMMEDIATE 0x02000000
2242#define OFFSET_REG 0x02000000
2243#define HWOFFSET_IMM 0x00400000
2244#define SHIFT_BY_REG 0x00000010
2245#define PRE_INDEX 0x01000000
2246#define INDEX_UP 0x00800000
2247#define WRITE_BACK 0x00200000
2248#define LDM_TYPE_2_OR_3 0x00400000
2249
2250#define LITERAL_MASK 0xf000f000
b99bd4ef 2251#define OPCODE_MASK 0xfe1fffff
90e4755a
RE
2252#define V4_STR_BIT 0x00000020
2253
b99bd4ef
NC
2254#define DATA_OP_SHIFT 21
2255
2256/* Codes to distinguish the arithmetic instructions. */
2257#define OPCODE_AND 0
2258#define OPCODE_EOR 1
2259#define OPCODE_SUB 2
2260#define OPCODE_RSB 3
2261#define OPCODE_ADD 4
2262#define OPCODE_ADC 5
2263#define OPCODE_SBC 6
2264#define OPCODE_RSC 7
2265#define OPCODE_TST 8
2266#define OPCODE_TEQ 9
2267#define OPCODE_CMP 10
2268#define OPCODE_CMN 11
2269#define OPCODE_ORR 12
2270#define OPCODE_MOV 13
2271#define OPCODE_BIC 14
2272#define OPCODE_MVN 15
2273
c9b604bd 2274/* Thumb v1 (ARMv4T). */
b99bd4ef
NC
2275static void do_t_nop PARAMS ((char *));
2276static void do_t_arit PARAMS ((char *));
2277static void do_t_add PARAMS ((char *));
2278static void do_t_asr PARAMS ((char *));
2279static void do_t_branch9 PARAMS ((char *));
2280static void do_t_branch12 PARAMS ((char *));
2281static void do_t_branch23 PARAMS ((char *));
2282static void do_t_bx PARAMS ((char *));
2283static void do_t_compare PARAMS ((char *));
2284static void do_t_ldmstm PARAMS ((char *));
2285static void do_t_ldr PARAMS ((char *));
2286static void do_t_ldrb PARAMS ((char *));
2287static void do_t_ldrh PARAMS ((char *));
2288static void do_t_lds PARAMS ((char *));
2289static void do_t_lsl PARAMS ((char *));
2290static void do_t_lsr PARAMS ((char *));
2291static void do_t_mov PARAMS ((char *));
2292static void do_t_push_pop PARAMS ((char *));
2293static void do_t_str PARAMS ((char *));
2294static void do_t_strb PARAMS ((char *));
2295static void do_t_strh PARAMS ((char *));
2296static void do_t_sub PARAMS ((char *));
2297static void do_t_swi PARAMS ((char *));
2298static void do_t_adr PARAMS ((char *));
2299
c9b604bd
RE
2300/* Thumb v2 (ARMv5T). */
2301static void do_t_blx PARAMS ((char *));
2302static void do_t_bkpt PARAMS ((char *));
2303
09d92015
MM
2304/* ARM V6. */
2305static void do_t_cps PARAMS ((char *));
2306static void do_t_cpy PARAMS ((char *));
2307static void do_t_setend PARAMS ((char *));;
2308
b99bd4ef
NC
2309#define T_OPCODE_MUL 0x4340
2310#define T_OPCODE_TST 0x4200
2311#define T_OPCODE_CMN 0x42c0
2312#define T_OPCODE_NEG 0x4240
2313#define T_OPCODE_MVN 0x43c0
2314
2315#define T_OPCODE_ADD_R3 0x1800
2316#define T_OPCODE_SUB_R3 0x1a00
2317#define T_OPCODE_ADD_HI 0x4400
2318#define T_OPCODE_ADD_ST 0xb000
2319#define T_OPCODE_SUB_ST 0xb080
2320#define T_OPCODE_ADD_SP 0xa800
2321#define T_OPCODE_ADD_PC 0xa000
2322#define T_OPCODE_ADD_I8 0x3000
2323#define T_OPCODE_SUB_I8 0x3800
2324#define T_OPCODE_ADD_I3 0x1c00
2325#define T_OPCODE_SUB_I3 0x1e00
2326
2327#define T_OPCODE_ASR_R 0x4100
2328#define T_OPCODE_LSL_R 0x4080
2329#define T_OPCODE_LSR_R 0x40c0
2330#define T_OPCODE_ASR_I 0x1000
2331#define T_OPCODE_LSL_I 0x0000
2332#define T_OPCODE_LSR_I 0x0800
2333
2334#define T_OPCODE_MOV_I8 0x2000
2335#define T_OPCODE_CMP_I8 0x2800
2336#define T_OPCODE_CMP_LR 0x4280
2337#define T_OPCODE_MOV_HR 0x4600
2338#define T_OPCODE_CMP_HR 0x4500
2339
2340#define T_OPCODE_LDR_PC 0x4800
2341#define T_OPCODE_LDR_SP 0x9800
2342#define T_OPCODE_STR_SP 0x9000
2343#define T_OPCODE_LDR_IW 0x6800
2344#define T_OPCODE_STR_IW 0x6000
2345#define T_OPCODE_LDR_IH 0x8800
2346#define T_OPCODE_STR_IH 0x8000
2347#define T_OPCODE_LDR_IB 0x7800
2348#define T_OPCODE_STR_IB 0x7000
2349#define T_OPCODE_LDR_RW 0x5800
2350#define T_OPCODE_STR_RW 0x5000
2351#define T_OPCODE_LDR_RH 0x5a00
2352#define T_OPCODE_STR_RH 0x5200
2353#define T_OPCODE_LDR_RB 0x5c00
2354#define T_OPCODE_STR_RB 0x5400
2355
2356#define T_OPCODE_PUSH 0xb400
2357#define T_OPCODE_POP 0xbc00
2358
2359#define T_OPCODE_BRANCH 0xe7fe
2360
2361static int thumb_reg PARAMS ((char ** str, int hi_lo));
2362
2363#define THUMB_SIZE 2 /* Size of thumb instruction. */
2364#define THUMB_REG_LO 0x1
2365#define THUMB_REG_HI 0x2
2366#define THUMB_REG_ANY 0x3
2367
2368#define THUMB_H1 0x0080
2369#define THUMB_H2 0x0040
2370
2371#define THUMB_ASR 0
2372#define THUMB_LSL 1
2373#define THUMB_LSR 2
2374
2375#define THUMB_MOVE 0
2376#define THUMB_COMPARE 1
09d92015 2377#define THUMB_CPY 2
b99bd4ef
NC
2378
2379#define THUMB_LOAD 0
2380#define THUMB_STORE 1
2381
2382#define THUMB_PP_PC_LR 0x0100
2383
2384/* These three are used for immediate shifts, do not alter. */
2385#define THUMB_WORD 2
2386#define THUMB_HALFWORD 1
2387#define THUMB_BYTE 0
2388
2389struct thumb_opcode
2390{
2391 /* Basic string to match. */
05d2d07e 2392 const char * template;
b99bd4ef
NC
2393
2394 /* Basic instruction code. */
2395 unsigned long value;
2396
2397 int size;
2398
2399 /* Which CPU variants this exists for. */
90e4755a 2400 unsigned long variant;
b99bd4ef
NC
2401
2402 /* Function to call to parse args. */
2403 void (* parms) PARAMS ((char *));
2404};
2405
05d2d07e 2406static const struct thumb_opcode tinsns[] =
b99bd4ef 2407{
c9b604bd 2408 /* Thumb v1 (ARMv4T). */
b89dddec
RE
2409 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2410 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2411 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2412 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2413 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2414 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2433 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
b89dddec
RE
2434 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2435 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2436 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2437 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2438 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2439 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2440 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2441 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2442 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2443 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2444 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2445 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2446 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2447 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2448 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2449 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2450 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2451 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2452 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2453 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2454 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2455 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2456 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2457 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2458 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2459 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2460 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2461 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2462 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2463 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
b99bd4ef 2464 /* Pseudo ops: */
b89dddec
RE
2465 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2466 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
c9b604bd
RE
2467 /* Thumb v2 (ARMv5T). */
2468 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2469 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
09d92015
MM
2470
2471 /* ARM V6. */
2472 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2473 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2474 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2475 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2476 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2477 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2478 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2479 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2480 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2481 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2482 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
b99bd4ef
NC
2483};
2484
f03698e6 2485#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 2486#define BAD_PC _("r15 not allowed here")
f03698e6 2487#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
2488#define ERR_NO_ACCUM _("acc0 expected")
2489
2490static struct hash_control * arm_ops_hsh = NULL;
2491static struct hash_control * arm_tops_hsh = NULL;
2492static struct hash_control * arm_cond_hsh = NULL;
2493static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
2494static struct hash_control * arm_psr_hsh = NULL;
2495
2496/* This table describes all the machine specific pseudo-ops the assembler
2497 has to support. The fields are:
2498 pseudo-op name without dot
2499 function to call to execute this pseudo-op
2500 Integer arg to pass to the function. */
2501
2502static void s_req PARAMS ((int));
0bbf2aa4 2503static void s_unreq PARAMS ((int));
b99bd4ef
NC
2504static void s_align PARAMS ((int));
2505static void s_bss PARAMS ((int));
2506static void s_even PARAMS ((int));
2507static void s_ltorg PARAMS ((int));
2508static void s_arm PARAMS ((int));
2509static void s_thumb PARAMS ((int));
2510static void s_code PARAMS ((int));
2511static void s_force_thumb PARAMS ((int));
2512static void s_thumb_func PARAMS ((int));
2513static void s_thumb_set PARAMS ((int));
76feaaf3 2514#ifdef OBJ_ELF
b99bd4ef
NC
2515static void s_arm_elf_cons PARAMS ((int));
2516#endif
2517
2518static int my_get_expression PARAMS ((expressionS *, char **));
2519
05d2d07e 2520const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2521{
0bbf2aa4 2522 /* Never called because '.req' does not start a line. */
b99bd4ef 2523 { "req", s_req, 0 },
0bbf2aa4 2524 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2525 { "bss", s_bss, 0 },
2526 { "align", s_align, 0 },
2527 { "arm", s_arm, 0 },
2528 { "thumb", s_thumb, 0 },
2529 { "code", s_code, 0 },
2530 { "force_thumb", s_force_thumb, 0 },
2531 { "thumb_func", s_thumb_func, 0 },
2532 { "thumb_set", s_thumb_set, 0 },
2533 { "even", s_even, 0 },
2534 { "ltorg", s_ltorg, 0 },
2535 { "pool", s_ltorg, 0 },
76feaaf3 2536#ifdef OBJ_ELF
b99bd4ef
NC
2537 { "word", s_arm_elf_cons, 4 },
2538 { "long", s_arm_elf_cons, 4 },
b99bd4ef
NC
2539#else
2540 { "word", cons, 4},
2541#endif
2542 { "extend", float_cons, 'x' },
2543 { "ldouble", float_cons, 'x' },
2544 { "packed", float_cons, 'p' },
2545 { 0, 0, 0 }
2546};
2547
03b1477f
RE
2548/* Other internal functions. */
2549static int arm_parse_extension PARAMS ((char *, int *));
2550static int arm_parse_cpu PARAMS ((char *));
2551static int arm_parse_arch PARAMS ((char *));
2552static int arm_parse_fpu PARAMS ((char *));
33a392fb 2553static int arm_parse_float_abi PARAMS ((char *));
0bbf2aa4 2554#if 0 /* Suppressed - for now. */
5a6c6817
NC
2555#if defined OBJ_COFF || defined OBJ_ELF
2556static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2557#endif
0bbf2aa4 2558#endif
03b1477f 2559
b99bd4ef
NC
2560/* Stuff needed to resolve the label ambiguity
2561 As:
2562 ...
2563 label: <insn>
2564 may differ from:
2565 ...
2566 label:
2567 <insn>
2568*/
2569
2570symbolS * last_label_seen;
b34976b6 2571static int label_is_thumb_function_name = FALSE;
b99bd4ef 2572
3d0c9500 2573/* Literal Pool stuff. */
b99bd4ef
NC
2574
2575#define MAX_LITERAL_POOL_SIZE 1024
2576
3d0c9500
NC
2577/* Literal pool structure. Held on a per-section
2578 and per-sub-section basis. */
2579typedef struct literal_pool
b99bd4ef 2580{
3d0c9500
NC
2581 expressionS literals [MAX_LITERAL_POOL_SIZE];
2582 unsigned int next_free_entry;
2583 unsigned int id;
2584 symbolS * symbol;
2585 segT section;
2586 subsegT sub_section;
61b5f74b 2587 struct literal_pool * next;
3d0c9500 2588} literal_pool;
b99bd4ef 2589
3d0c9500
NC
2590/* Pointer to a linked list of literal pools. */
2591literal_pool * list_of_pools = NULL;
b99bd4ef 2592
3d0c9500
NC
2593static literal_pool * find_literal_pool PARAMS ((void));
2594static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2595
3d0c9500
NC
2596static literal_pool *
2597find_literal_pool ()
2598{
2599 literal_pool * pool;
2600
2601 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2602 {
2603 if (pool->section == now_seg
2604 && pool->sub_section == now_subseg)
2605 break;
2606 }
2607
2608 return pool;
2609}
b99bd4ef 2610
3d0c9500
NC
2611static literal_pool *
2612find_or_make_literal_pool ()
2613{
2614 /* Next literal pool ID number. */
2615 static unsigned int latest_pool_num = 1;
2616 literal_pool * pool;
2617
2618 pool = find_literal_pool ();
b99bd4ef 2619
3d0c9500
NC
2620 if (pool == NULL)
2621 {
2622 /* Create a new pool. */
2623 pool = (literal_pool *) xmalloc (sizeof (* pool));
2624 if (! pool)
2625 return NULL;
2626
2627 pool->next_free_entry = 0;
2628 pool->section = now_seg;
2629 pool->sub_section = now_subseg;
2630 pool->next = list_of_pools;
2631 pool->symbol = NULL;
2632
2633 /* Add it to the list. */
2634 list_of_pools = pool;
2635 }
2636
2637 /* New pools, and emptied pools, will have a NULL symbol. */
2638 if (pool->symbol == NULL)
2639 {
2640 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2641 (valueT) 0, &zero_address_frag);
2642 pool->id = latest_pool_num ++;
2643 }
2644
2645 /* Done. */
2646 return pool;
2647}
2648
2649/* Add the literal in the global 'inst'
2650 structure to the relevent literal pool. */
b99bd4ef
NC
2651static int
2652add_to_lit_pool ()
2653{
61b5f74b 2654 literal_pool * pool;
3d0c9500 2655 unsigned int entry;
b99bd4ef 2656
3d0c9500 2657 pool = find_or_make_literal_pool ();
b99bd4ef 2658
3d0c9500
NC
2659 /* Check if this literal value is already in the pool. */
2660 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2661 {
3d0c9500
NC
2662 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2663 && (inst.reloc.exp.X_op == O_constant)
2664 && (pool->literals[entry].X_add_number
b99bd4ef 2665 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2666 && (pool->literals[entry].X_unsigned
2667 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2668 break;
2669
3d0c9500
NC
2670 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2671 && (inst.reloc.exp.X_op == O_symbol)
2672 && (pool->literals[entry].X_add_number
b99bd4ef 2673 == inst.reloc.exp.X_add_number)
3d0c9500 2674 && (pool->literals[entry].X_add_symbol
b99bd4ef 2675 == inst.reloc.exp.X_add_symbol)
3d0c9500 2676 && (pool->literals[entry].X_op_symbol
b99bd4ef 2677 == inst.reloc.exp.X_op_symbol))
3d0c9500 2678 break;
b99bd4ef
NC
2679 }
2680
3d0c9500
NC
2681 /* Do we need to create a new entry? */
2682 if (entry == pool->next_free_entry)
b99bd4ef 2683 {
3d0c9500 2684 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2685 {
ed71e111 2686 inst.error = _("literal pool overflow");
b99bd4ef
NC
2687 return FAIL;
2688 }
2689
3d0c9500
NC
2690 pool->literals[entry] = inst.reloc.exp;
2691 pool->next_free_entry += 1;
b99bd4ef
NC
2692 }
2693
3d0c9500 2694 inst.reloc.exp.X_op = O_symbol;
08df2379 2695 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2696 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2697
2698 return SUCCESS;
2699}
2700
2701/* Can't use symbol_new here, so have to create a symbol and then at
2702 a later date assign it a value. Thats what these functions do. */
2703
2704static void
2705symbol_locate (symbolP, name, segment, valu, frag)
2706 symbolS * symbolP;
05d2d07e 2707 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2708 segT segment; /* Segment identifier (SEG_<something>). */
2709 valueT valu; /* Symbol value. */
2710 fragS * frag; /* Associated fragment. */
2711{
2712 unsigned int name_length;
2713 char * preserved_copy_of_name;
2714
2715 name_length = strlen (name) + 1; /* +1 for \0. */
2716 obstack_grow (&notes, name, name_length);
2717 preserved_copy_of_name = obstack_finish (&notes);
2718#ifdef STRIP_UNDERSCORE
2719 if (preserved_copy_of_name[0] == '_')
2720 preserved_copy_of_name++;
2721#endif
2722
2723#ifdef tc_canonicalize_symbol_name
2724 preserved_copy_of_name =
2725 tc_canonicalize_symbol_name (preserved_copy_of_name);
2726#endif
2727
2728 S_SET_NAME (symbolP, preserved_copy_of_name);
2729
2730 S_SET_SEGMENT (symbolP, segment);
2731 S_SET_VALUE (symbolP, valu);
c62e1cc3 2732 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2733
2734 symbol_set_frag (symbolP, frag);
2735
2736 /* Link to end of symbol chain. */
2737 {
2738 extern int symbol_table_frozen;
2739 if (symbol_table_frozen)
2740 abort ();
2741 }
2742
2743 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2744
2745 obj_symbol_new_hook (symbolP);
2746
2747#ifdef tc_symbol_new_hook
2748 tc_symbol_new_hook (symbolP);
2749#endif
2750
2751#ifdef DEBUG_SYMS
2752 verify_symbol_chain (symbol_rootP, symbol_lastP);
2753#endif /* DEBUG_SYMS */
2754}
2755
2756/* Check that an immediate is valid.
2757 If so, convert it to the right format. */
2758
2759static unsigned int
2760validate_immediate (val)
2761 unsigned int val;
2762{
2763 unsigned int a;
2764 unsigned int i;
2765
2766#define rotate_left(v, n) (v << n | v >> (32 - n))
2767
2768 for (i = 0; i < 32; i += 2)
2769 if ((a = rotate_left (val, i)) <= 0xff)
2770 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2771
2772 return FAIL;
2773}
2774
2d2255b5 2775/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2776 values, added together. We already know that this value cannot be
2777 computed by just one ARM instruction. */
2778
2779static unsigned int
2780validate_immediate_twopart (val, highpart)
2781 unsigned int val;
2782 unsigned int * highpart;
2783{
2784 unsigned int a;
2785 unsigned int i;
2786
2787 for (i = 0; i < 32; i += 2)
2788 if (((a = rotate_left (val, i)) & 0xff) != 0)
2789 {
2790 if (a & 0xff00)
2791 {
2792 if (a & ~ 0xffff)
2793 continue;
2794 * highpart = (a >> 8) | ((i + 24) << 7);
2795 }
2796 else if (a & 0xff0000)
2797 {
2798 if (a & 0xff000000)
2799 continue;
2800 * highpart = (a >> 16) | ((i + 16) << 7);
2801 }
2802 else
2803 {
2804 assert (a & 0xff000000);
2805 * highpart = (a >> 24) | ((i + 8) << 7);
2806 }
2807
2808 return (a & 0xff) | (i << 7);
2809 }
2810
2811 return FAIL;
2812}
2813
2814static int
2815validate_offset_imm (val, hwse)
2816 unsigned int val;
2817 int hwse;
2818{
2819 if ((hwse && val > 255) || val > 4095)
2820 return FAIL;
2821 return val;
2822}
2823
6057a28f
NC
2824\f
2825#ifdef OBJ_ELF
2826enum mstate
2827{
2828 MAP_DATA,
2829 MAP_ARM,
2830 MAP_THUMB
2831};
2832
2833/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2834 (This text is taken from version B-02 of the spec):
2835
2836 4.4.7 Mapping and tagging symbols
2837
2838 A section of an ARM ELF file can contain a mixture of ARM code,
2839 Thumb code, and data. There are inline transitions between code
2840 and data at literal pool boundaries. There can also be inline
2841 transitions between ARM code and Thumb code, for example in
2842 ARM-Thumb inter-working veneers. Linkers, machine-level
2843 debuggers, profiling tools, and disassembly tools need to map
2844 images accurately. For example, setting an ARM breakpoint on a
2845 Thumb location, or in a literal pool, can crash the program
2846 being debugged, ruining the debugging session.
2847
2848 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2849 tagged (see section 4.4.7.2 below) using local symbols (with
2850 binding STB_LOCAL). To assist consumers, mapping and tagging
2851 symbols should be collated first in the symbol table, before
2852 other symbols with binding STB_LOCAL.
2853
2854 To allow properly collated mapping and tagging symbols to be
2855 skipped by consumers that have no interest in them, the first
2856 such symbol should have the name $m and its st_value field equal
2857 to the total number of mapping and tagging symbols (including
2858 the $m) in the symbol table.
2859
2860 4.4.7.1 Mapping symbols
2861
2862 $a Labels the first byte of a sequence of ARM instructions.
2863 Its type is STT_FUNC.
2864
2865 $d Labels the first byte of a sequence of data items.
2866 Its type is STT_OBJECT.
2867
2868 $t Labels the first byte of a sequence of Thumb instructions.
2869 Its type is STT_FUNC.
2870
2871 This list of mapping symbols may be extended in the future.
2872
2873 Section-relative mapping symbols
2874
2875 Mapping symbols defined in a section define a sequence of
2876 half-open address intervals that cover the address range of the
2877 section. Each interval starts at the address defined by a
2878 mapping symbol, and continues up to, but not including, the
2879 address defined by the next (in address order) mapping symbol or
2880 the end of the section. A corollary is that there must be a
2881 mapping symbol defined at the beginning of each section.
2882 Consumers can ignore the size of a section-relative mapping
2883 symbol. Producers can set it to 0.
2884
2885 Absolute mapping symbols
2886
2887 Because of the need to crystallize a Thumb address with the
2888 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2889 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2890 or $t.
2891
2892 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2893 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2894 where [x, y) denotes the half-open address range from x,
2895 inclusive, to y, exclusive.
2896
2897 In the absence of a mapping symbol, a consumer can interpret a
2898 function symbol with an odd value as the Thumb code address
2899 obtained by clearing the least significant bit of the
2900 value. This interpretation is deprecated, and it may not work in
2901 the future.
2902
2903 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2904 the EABI (which is still under development), so they are not
2905 implemented here. */
2906
2907static void
2908mapping_state (enum mstate state)
2909{
2910 static enum mstate mapstate = MAP_DATA;
2911 symbolS * symbolP;
2912 const char * symname;
2913 int type;
2914
2915 if (mapstate == state)
2916 /* The mapping symbol has already been emitted.
2917 There is nothing else to do. */
2918 return;
2919
2920 mapstate = state;
2921
2922 switch (state)
2923 {
2924 case MAP_DATA:
2925 symname = "$d";
2926 type = BSF_OBJECT;
2927 break;
2928 case MAP_ARM:
2929 symname = "$a";
2930 type = BSF_FUNCTION;
2931 break;
2932 case MAP_THUMB:
2933 symname = "$t";
2934 type = BSF_FUNCTION;
2935 break;
2936 default:
2937 abort ();
2938 }
2939
2940 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2941 symbol_table_insert (symbolP);
2942 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2943
2944 switch (state)
2945 {
2946 case MAP_ARM:
2947 THUMB_SET_FUNC (symbolP, 0);
2948 ARM_SET_THUMB (symbolP, 0);
2949 ARM_SET_INTERWORK (symbolP, support_interwork);
2950 break;
2951
2952 case MAP_THUMB:
2953 THUMB_SET_FUNC (symbolP, 1);
2954 ARM_SET_THUMB (symbolP, 1);
2955 ARM_SET_INTERWORK (symbolP, support_interwork);
2956 break;
2957
2958 case MAP_DATA:
2959 default:
2960 return;
2961 }
2962}
2963
2964/* When we change sections we need to issue a new mapping symbol. */
2965
9ce887a1 2966void
6057a28f
NC
2967arm_elf_change_section (void)
2968{
2969 flagword flags;
2970
2971 if (!SEG_NORMAL (now_seg))
2972 return;
2973
2974 flags = bfd_get_section_flags (stdoutput, now_seg);
2975
2976 /* We can ignore sections that only contain debug info. */
2977 if ((flags & SEC_ALLOC) == 0)
2978 return;
2979
2980 if (flags & SEC_CODE)
2981 {
2982 if (thumb_mode)
2983 mapping_state (MAP_THUMB);
2984 else
2985 mapping_state (MAP_ARM);
2986 }
2987 else
2988 /* This section does not contain code. Therefore it must contain data. */
2989 mapping_state (MAP_DATA);
2990}
2991#else
2992#define mapping_state(a)
2993#endif /* OBJ_ELF */
2994\f
2995
b99bd4ef
NC
2996static void
2997s_req (a)
2998 int a ATTRIBUTE_UNUSED;
2999{
f03698e6 3000 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
3001}
3002
0bbf2aa4
NC
3003/* The .unreq directive deletes an alias which was previously defined
3004 by .req. For example:
3005
3006 my_alias .req r11
3007 .unreq my_alias */
3008
3009static void
3010s_unreq (int a ATTRIBUTE_UNUSED)
3011{
3012 char *name;
3013 char saved_char;
3014
3015 skip_whitespace (input_line_pointer);
3016 name = input_line_pointer;
3017
3018 while (*input_line_pointer != 0
3019 && *input_line_pointer != ' '
3020 && *input_line_pointer != '\n')
3021 ++input_line_pointer;
3022
3023 saved_char = *input_line_pointer;
3024 *input_line_pointer = 0;
3025
3026 if (*name)
3027 {
3028 enum arm_reg_type req_type = arm_reg_parse_any (name);
3029
3030 if (req_type != REG_TYPE_MAX)
3031 {
3032 char *temp_name = name;
3033 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3034
3035 if (req_no != FAIL)
3036 {
3037 struct reg_entry *req_entry;
3038
3039 /* Check to see if this alias is a builtin one. */
3040 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3041
3042 if (!req_entry)
3043 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3044 else if (req_entry->builtin)
67c1ffbe 3045 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
3046 points to a const data structure, so we only need to
3047 free up the memory used by the key in the hash table.
3048 Unfortunately we have not recorded this value, so this
3049 is a memory leak. */
3050 /* FIXME: Should we issue a warning message ? */
3051 ;
3052 else
3053 {
67c1ffbe 3054 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
3055 key and the value, but fortunately the key is the same
3056 as the value->name field. */
3057 free ((char *) req_entry->name);
3058 free (req_entry);
3059 }
3060 }
3061 else
3062 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3063 }
3064 else
3065 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3066 }
3067 else
3068 as_bad (_("invalid syntax for .unreq directive"));
3069
3070 *input_line_pointer = saved_char;
3071 demand_empty_rest_of_line ();
3072}
3073
b99bd4ef
NC
3074static void
3075s_bss (ignore)
3076 int ignore ATTRIBUTE_UNUSED;
3077{
3078 /* We don't support putting frags in the BSS segment, we fake it by
3079 marking in_bss, then looking at s_skip for clues. */
3080 subseg_set (bss_section, 0);
3081 demand_empty_rest_of_line ();
6057a28f 3082 mapping_state (MAP_DATA);
b99bd4ef
NC
3083}
3084
3085static void
3086s_even (ignore)
3087 int ignore ATTRIBUTE_UNUSED;
3088{
3089 /* Never make frag if expect extra pass. */
3090 if (!need_pass_2)
3091 frag_align (1, 0, 0);
3092
3093 record_alignment (now_seg, 1);
3094
3095 demand_empty_rest_of_line ();
3096}
3097
3098static void
3099s_ltorg (ignored)
3100 int ignored ATTRIBUTE_UNUSED;
3101{
3d0c9500
NC
3102 unsigned int entry;
3103 literal_pool * pool;
b99bd4ef
NC
3104 char sym_name[20];
3105
3d0c9500
NC
3106 pool = find_literal_pool ();
3107 if (pool == NULL
3108 || pool->symbol == NULL
3109 || pool->next_free_entry == 0)
b99bd4ef
NC
3110 return;
3111
3112 /* Align pool as you have word accesses.
3113 Only make a frag if we have to. */
3114 if (!need_pass_2)
3115 frag_align (2, 0, 0);
3116
3117 record_alignment (now_seg, 2);
3118
3d0c9500 3119 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3120
3d0c9500 3121 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3122 (valueT) frag_now_fix (), frag_now);
3d0c9500 3123 symbol_table_insert (pool->symbol);
b99bd4ef 3124
3d0c9500 3125 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3126
3127#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3128 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3129#endif
3130
3d0c9500 3131 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3132 /* First output the expression in the instruction to the pool. */
3d0c9500 3133 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3134
3d0c9500
NC
3135 /* Mark the pool as empty. */
3136 pool->next_free_entry = 0;
3137 pool->symbol = NULL;
b99bd4ef
NC
3138}
3139
3140/* Same as s_align_ptwo but align 0 => align 2. */
3141
3142static void
3143s_align (unused)
3144 int unused ATTRIBUTE_UNUSED;
3145{
3146 register int temp;
3147 register long temp_fill;
3148 long max_alignment = 15;
3149
3150 temp = get_absolute_expression ();
3151 if (temp > max_alignment)
f03698e6 3152 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3153 else if (temp < 0)
3154 {
f03698e6 3155 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3156 temp = 0;
3157 }
3158
3159 if (*input_line_pointer == ',')
3160 {
3161 input_line_pointer++;
3162 temp_fill = get_absolute_expression ();
3163 }
3164 else
3165 temp_fill = 0;
3166
3167 if (!temp)
3168 temp = 2;
3169
3170 /* Only make a frag if we HAVE to. */
3171 if (temp && !need_pass_2)
3172 frag_align (temp, (int) temp_fill, 0);
3173 demand_empty_rest_of_line ();
3174
3175 record_alignment (now_seg, temp);
3176}
3177
3178static void
3179s_force_thumb (ignore)
3180 int ignore ATTRIBUTE_UNUSED;
3181{
3182 /* If we are not already in thumb mode go into it, EVEN if
3183 the target processor does not support thumb instructions.
3184 This is used by gcc/config/arm/lib1funcs.asm for example
3185 to compile interworking support functions even if the
3186 target processor should not support interworking. */
3187 if (! thumb_mode)
3188 {
3189 thumb_mode = 2;
3190
3191 record_alignment (now_seg, 1);
3192 }
3193
3194 demand_empty_rest_of_line ();
3195}
3196
3197static void
3198s_thumb_func (ignore)
3199 int ignore ATTRIBUTE_UNUSED;
3200{
3201 if (! thumb_mode)
3202 opcode_select (16);
3203
3204 /* The following label is the name/address of the start of a Thumb function.
3205 We need to know this for the interworking support. */
b34976b6 3206 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3207
3208 demand_empty_rest_of_line ();
3209}
3210
3211/* Perform a .set directive, but also mark the alias as
3212 being a thumb function. */
3213
3214static void
3215s_thumb_set (equiv)
3216 int equiv;
3217{
3218 /* XXX the following is a duplicate of the code for s_set() in read.c
3219 We cannot just call that code as we need to get at the symbol that
3220 is created. */
3221 register char * name;
3222 register char delim;
3223 register char * end_name;
3224 register symbolS * symbolP;
3225
3226 /* Especial apologies for the random logic:
3227 This just grew, and could be parsed much more simply!
3228 Dean - in haste. */
3229 name = input_line_pointer;
3230 delim = get_symbol_end ();
3231 end_name = input_line_pointer;
3232 *end_name = delim;
3233
3234 SKIP_WHITESPACE ();
3235
3236 if (*input_line_pointer != ',')
3237 {
3238 *end_name = 0;
f03698e6 3239 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3240 *end_name = delim;
3241 ignore_rest_of_line ();
3242 return;
3243 }
3244
3245 input_line_pointer++;
3246 *end_name = 0;
3247
3248 if (name[0] == '.' && name[1] == '\0')
3249 {
3250 /* XXX - this should not happen to .thumb_set. */
3251 abort ();
3252 }
3253
3254 if ((symbolP = symbol_find (name)) == NULL
3255 && (symbolP = md_undefined_symbol (name)) == NULL)
3256 {
3257#ifndef NO_LISTING
3258 /* When doing symbol listings, play games with dummy fragments living
3259 outside the normal fragment chain to record the file and line info
3260 for this symbol. */
3261 if (listing & LISTING_SYMBOLS)
3262 {
3263 extern struct list_info_struct * listing_tail;
3264 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3265
3266 memset (dummy_frag, 0, sizeof (fragS));
3267 dummy_frag->fr_type = rs_fill;
3268 dummy_frag->line = listing_tail;
3269 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3270 dummy_frag->fr_symbol = symbolP;
3271 }
3272 else
3273#endif
3274 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3275
3276#ifdef OBJ_COFF
3277 /* "set" symbols are local unless otherwise specified. */
3278 SF_SET_LOCAL (symbolP);
3279#endif /* OBJ_COFF */
3280 } /* Make a new symbol. */
3281
3282 symbol_table_insert (symbolP);
3283
3284 * end_name = delim;
3285
3286 if (equiv
3287 && S_IS_DEFINED (symbolP)
3288 && S_GET_SEGMENT (symbolP) != reg_section)
3289 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3290
3291 pseudo_set (symbolP);
3292
3293 demand_empty_rest_of_line ();
3294
3295 /* XXX Now we come to the Thumb specific bit of code. */
3296
3297 THUMB_SET_FUNC (symbolP, 1);
3298 ARM_SET_THUMB (symbolP, 1);
3299#if defined OBJ_ELF || defined OBJ_COFF
3300 ARM_SET_INTERWORK (symbolP, support_interwork);
3301#endif
3302}
3303
b99bd4ef
NC
3304static void
3305opcode_select (width)
3306 int width;
3307{
3308 switch (width)
3309 {
3310 case 16:
3311 if (! thumb_mode)
3312 {
b89dddec 3313 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3314 as_bad (_("selected processor does not support THUMB opcodes"));
3315
3316 thumb_mode = 1;
3317 /* No need to force the alignment, since we will have been
3318 coming from ARM mode, which is word-aligned. */
3319 record_alignment (now_seg, 1);
3320 }
6057a28f 3321 mapping_state (MAP_THUMB);
b99bd4ef
NC
3322 break;
3323
3324 case 32:
3325 if (thumb_mode)
3326 {
03b1477f 3327 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3328 as_bad (_("selected processor does not support ARM opcodes"));
3329
3330 thumb_mode = 0;
3331
3332 if (!need_pass_2)
cc8a6dd0 3333 frag_align (2, 0, 0);
b99bd4ef 3334
cc8a6dd0 3335 record_alignment (now_seg, 1);
b99bd4ef 3336 }
6057a28f 3337 mapping_state (MAP_ARM);
b99bd4ef
NC
3338 break;
3339
3340 default:
3341 as_bad (_("invalid instruction size selected (%d)"), width);
3342 }
3343}
3344
3345static void
3346s_arm (ignore)
3347 int ignore ATTRIBUTE_UNUSED;
3348{
3349 opcode_select (32);
3350 demand_empty_rest_of_line ();
3351}
3352
3353static void
3354s_thumb (ignore)
3355 int ignore ATTRIBUTE_UNUSED;
3356{
3357 opcode_select (16);
3358 demand_empty_rest_of_line ();
3359}
3360
3361static void
3362s_code (unused)
3363 int unused ATTRIBUTE_UNUSED;
3364{
3365 register int temp;
3366
3367 temp = get_absolute_expression ();
3368 switch (temp)
3369 {
3370 case 16:
3371 case 32:
3372 opcode_select (temp);
3373 break;
3374
3375 default:
3376 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3377 }
3378}
3379
3380static void
3381end_of_line (str)
f03698e6 3382 char *str;
b99bd4ef
NC
3383{
3384 skip_whitespace (str);
3385
f03698e6
RE
3386 if (*str != '\0' && !inst.error)
3387 inst.error = _("garbage following instruction");
b99bd4ef
NC
3388}
3389
3390static int
3391skip_past_comma (str)
3392 char ** str;
3393{
3394 char * p = * str, c;
3395 int comma = 0;
3396
3397 while ((c = *p) == ' ' || c == ',')
3398 {
3399 p++;
3400 if (c == ',' && comma++)
3401 return FAIL;
3402 }
3403
3404 if (c == '\0')
3405 return FAIL;
3406
3407 *str = p;
3408 return comma ? SUCCESS : FAIL;
3409}
3410
3411/* A standard register must be given at this point.
3412 SHIFT is the place to put it in inst.instruction.
3413 Restores input start point on error.
3414 Returns the reg#, or FAIL. */
3415
3416static int
3417reg_required_here (str, shift)
3418 char ** str;
3419 int shift;
3420{
3421 static char buff [128]; /* XXX */
3422 int reg;
3423 char * start = * str;
3424
6c43fab6 3425 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3426 {
3427 if (shift >= 0)
3428 inst.instruction |= reg << shift;
3429 return reg;
3430 }
3431
3432 /* Restore the start point, we may have got a reg of the wrong class. */
3433 *str = start;
3434
3435 /* In the few cases where we might be able to accept something else
3436 this error can be overridden. */
f03698e6 3437 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3438 inst.error = buff;
3439
3440 return FAIL;
3441}
3442
5a6c6817 3443/* A Intel Wireless MMX technology register
e16bb312
NC
3444 must be given at this point.
3445 Shift is the place to put it in inst.instruction.
3446 Restores input start point on err.
3447 Returns the reg#, or FAIL. */
3448
3449static int
3450wreg_required_here (str, shift, reg_type)
3451 char ** str;
3452 int shift;
3453 enum wreg_type reg_type;
3454{
3455 static char buff [128];
3456 int reg;
3457 char * start = *str;
3458
3459 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3460 {
3461 if (wr_register (reg)
3462 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3463 {
3464 if (shift >= 0)
3465 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3466 return reg;
3467 }
3468 else if (wc_register (reg)
3469 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3470 {
3471 if (shift >= 0)
3472 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3473 return reg;
3474 }
3475 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3476 {
3477 if (shift >= 0)
3478 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3479 return reg;
3480 }
3481 }
3482
3483 /* Restore the start point, we may have got a reg of the wrong class. */
3484 *str = start;
3485
3486 /* In the few cases where we might be able to accept
3487 something else this error can be overridden. */
5a6c6817 3488 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3489 inst.error = buff;
3490
3491 return FAIL;
3492}
3493
05d2d07e 3494static const struct asm_psr *
b99bd4ef
NC
3495arm_psr_parse (ccp)
3496 register char ** ccp;
3497{
3498 char * start = * ccp;
3499 char c;
3500 char * p;
05d2d07e 3501 const struct asm_psr * psr;
b99bd4ef
NC
3502
3503 p = start;
3504
3505 /* Skip to the end of the next word in the input stream. */
3506 do
3507 {
3508 c = *p++;
3509 }
3882b010 3510 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3511
3512 /* Terminate the word. */
3513 *--p = 0;
3514
3515 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3516 feature for ease of use and backwards compatibility. */
3517 if (!strncmp (start, "cpsr", 4))
3518 strncpy (start, "CPSR", 4);
3519 else if (!strncmp (start, "spsr", 4))
3520 strncpy (start, "SPSR", 4);
3521
3522 /* Now locate the word in the psr hash table. */
05d2d07e 3523 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3524
3525 /* Restore the input stream. */
3526 *p = c;
3527
3528 /* If we found a valid match, advance the
3529 stream pointer past the end of the word. */
3530 *ccp = p;
3531
3532 return psr;
3533}
3534
3535/* Parse the input looking for a PSR flag. */
3536
3537static int
3538psr_required_here (str)
3539 char ** str;
3540{
3541 char * start = * str;
05d2d07e 3542 const struct asm_psr * psr;
b99bd4ef
NC
3543
3544 psr = arm_psr_parse (str);
3545
3546 if (psr)
3547 {
3548 /* If this is the SPSR that is being modified, set the R bit. */
3549 if (! psr->cpsr)
3550 inst.instruction |= SPSR_BIT;
3551
3552 /* Set the psr flags in the MSR instruction. */
3553 inst.instruction |= psr->field << PSR_SHIFT;
3554
3555 return SUCCESS;
3556 }
3557
3558 /* In the few cases where we might be able to accept
3559 something else this error can be overridden. */
3560 inst.error = _("flag for {c}psr instruction expected");
3561
3562 /* Restore the start point. */
3563 *str = start;
3564 return FAIL;
3565}
3566
3567static int
3568co_proc_number (str)
6c43fab6 3569 char **str;
b99bd4ef
NC
3570{
3571 int processor, pchar;
6c43fab6 3572 char *start;
b99bd4ef 3573
6c43fab6
RE
3574 skip_whitespace (*str);
3575 start = *str;
b99bd4ef
NC
3576
3577 /* The data sheet seems to imply that just a number on its own is valid
3578 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3579 accept either. */
6c43fab6
RE
3580 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3581 == FAIL)
b99bd4ef 3582 {
6c43fab6
RE
3583 *str = start;
3584
3585 pchar = *(*str)++;
3586 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3587 {
6c43fab6
RE
3588 processor = pchar - '0';
3589 if (**str >= '0' && **str <= '9')
b99bd4ef 3590 {
6c43fab6
RE
3591 processor = processor * 10 + *(*str)++ - '0';
3592 if (processor > 15)
3593 {
f03698e6 3594 inst.error = _("illegal co-processor number");
6c43fab6
RE
3595 return FAIL;
3596 }
b99bd4ef
NC
3597 }
3598 }
6c43fab6
RE
3599 else
3600 {
f03698e6 3601 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
3602 return FAIL;
3603 }
b99bd4ef
NC
3604 }
3605
3606 inst.instruction |= processor << 8;
3607 return SUCCESS;
3608}
3609
3610static int
3611cp_opc_expr (str, where, length)
3612 char ** str;
3613 int where;
3614 int length;
3615{
3616 expressionS expr;
3617
3618 skip_whitespace (* str);
3619
3620 memset (&expr, '\0', sizeof (expr));
3621
3622 if (my_get_expression (&expr, str))
3623 return FAIL;
3624 if (expr.X_op != O_constant)
3625 {
3626 inst.error = _("bad or missing expression");
3627 return FAIL;
3628 }
3629
3630 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3631 {
3632 inst.error = _("immediate co-processor expression too large");
3633 return FAIL;
3634 }
3635
3636 inst.instruction |= expr.X_add_number << where;
3637 return SUCCESS;
3638}
3639
3640static int
3641cp_reg_required_here (str, where)
3642 char ** str;
3643 int where;
3644{
3645 int reg;
3646 char * start = *str;
3647
6c43fab6 3648 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3649 {
b99bd4ef
NC
3650 inst.instruction |= reg << where;
3651 return reg;
3652 }
3653
3654 /* In the few cases where we might be able to accept something else
3655 this error can be overridden. */
f03698e6 3656 inst.error = _("co-processor register expected");
b99bd4ef
NC
3657
3658 /* Restore the start point. */
3659 *str = start;
3660 return FAIL;
3661}
3662
3663static int
3664fp_reg_required_here (str, where)
3665 char ** str;
3666 int where;
3667{
3668 int reg;
3669 char * start = * str;
3670
6c43fab6 3671 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3672 {
b99bd4ef
NC
3673 inst.instruction |= reg << where;
3674 return reg;
3675 }
3676
3677 /* In the few cases where we might be able to accept something else
3678 this error can be overridden. */
f03698e6 3679 inst.error = _("floating point register expected");
b99bd4ef
NC
3680
3681 /* Restore the start point. */
3682 *str = start;
3683 return FAIL;
3684}
3685
3686static int
3687cp_address_offset (str)
3688 char ** str;
3689{
3690 int offset;
3691
3692 skip_whitespace (* str);
3693
3694 if (! is_immediate_prefix (**str))
3695 {
3696 inst.error = _("immediate expression expected");
3697 return FAIL;
3698 }
3699
3700 (*str)++;
3701
3702 if (my_get_expression (& inst.reloc.exp, str))
3703 return FAIL;
3704
3705 if (inst.reloc.exp.X_op == O_constant)
3706 {
3707 offset = inst.reloc.exp.X_add_number;
3708
3709 if (offset & 3)
3710 {
3711 inst.error = _("co-processor address must be word aligned");
3712 return FAIL;
3713 }
3714
3715 if (offset > 1023 || offset < -1023)
3716 {
3717 inst.error = _("offset too large");
3718 return FAIL;
3719 }
3720
3721 if (offset >= 0)
3722 inst.instruction |= INDEX_UP;
3723 else
3724 offset = -offset;
3725
3726 inst.instruction |= offset >> 2;
3727 }
3728 else
3729 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3730
3731 return SUCCESS;
3732}
3733
3734static int
bfae80f2 3735cp_address_required_here (str, wb_ok)
b99bd4ef 3736 char ** str;
bfae80f2 3737 int wb_ok;
b99bd4ef
NC
3738{
3739 char * p = * str;
3740 int pre_inc = 0;
3741 int write_back = 0;
3742
3743 if (*p == '[')
3744 {
3745 int reg;
3746
3747 p++;
3748 skip_whitespace (p);
3749
3750 if ((reg = reg_required_here (& p, 16)) == FAIL)
3751 return FAIL;
3752
3753 skip_whitespace (p);
3754
3755 if (*p == ']')
3756 {
3757 p++;
3758
f02232aa
NC
3759 skip_whitespace (p);
3760
3761 if (*p == '\0')
b99bd4ef 3762 {
f02232aa
NC
3763 /* As an extension to the official ARM syntax we allow:
3764
3765 [Rn]
3766
3767 as a short hand for:
3768
3769 [Rn,#0] */
3770 inst.instruction |= PRE_INDEX | INDEX_UP;
3771 *str = p;
3772 return SUCCESS;
3773 }
3774
3775 if (skip_past_comma (& p) == FAIL)
3776 {
3777 inst.error = _("comma expected after closing square bracket");
3778 return FAIL;
3779 }
b99bd4ef 3780
f02232aa
NC
3781 skip_whitespace (p);
3782
3783 if (*p == '#')
3784 {
3785 if (wb_ok)
b99bd4ef 3786 {
f02232aa
NC
3787 /* [Rn], #expr */
3788 write_back = WRITE_BACK;
3789
3790 if (reg == REG_PC)
3791 {
3792 inst.error = _("pc may not be used in post-increment");
3793 return FAIL;
3794 }
3795
3796 if (cp_address_offset (& p) == FAIL)
3797 return FAIL;
b99bd4ef 3798 }
f02232aa
NC
3799 else
3800 pre_inc = PRE_INDEX | INDEX_UP;
3801 }
3802 else if (*p == '{')
3803 {
3804 int option;
b99bd4ef 3805
f02232aa
NC
3806 /* [Rn], {<expr>} */
3807 p++;
3808
3809 skip_whitespace (p);
3810
3811 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3812 return FAIL;
f02232aa
NC
3813
3814 if (inst.reloc.exp.X_op == O_constant)
3815 {
3816 option = inst.reloc.exp.X_add_number;
3817
3818 if (option > 255 || option < 0)
3819 {
3820 inst.error = _("'option' field too large");
3821 return FAIL;
3822 }
3823
3824 skip_whitespace (p);
3825
3826 if (*p != '}')
3827 {
3828 inst.error = _("'}' expected at end of 'option' field");
3829 return FAIL;
3830 }
3831 else
3832 {
3833 p++;
3834 inst.instruction |= option;
3835 inst.instruction |= INDEX_UP;
3836 }
3837 }
3838 else
3839 {
3840 inst.error = _("non-constant expressions for 'option' field not supported");
3841 return FAIL;
3842 }
b99bd4ef
NC
3843 }
3844 else
f02232aa
NC
3845 {
3846 inst.error = _("# or { expected after comma");
3847 return FAIL;
3848 }
b99bd4ef
NC
3849 }
3850 else
3851 {
3852 /* '['Rn, #expr']'[!] */
3853
3854 if (skip_past_comma (& p) == FAIL)
3855 {
3856 inst.error = _("pre-indexed expression expected");
3857 return FAIL;
3858 }
3859
3860 pre_inc = PRE_INDEX;
3861
3862 if (cp_address_offset (& p) == FAIL)
3863 return FAIL;
3864
3865 skip_whitespace (p);
3866
3867 if (*p++ != ']')
3868 {
3869 inst.error = _("missing ]");
3870 return FAIL;
3871 }
3872
3873 skip_whitespace (p);
3874
bfae80f2 3875 if (wb_ok && *p == '!')
b99bd4ef
NC
3876 {
3877 if (reg == REG_PC)
3878 {
3879 inst.error = _("pc may not be used with write-back");
3880 return FAIL;
3881 }
3882
3883 p++;
3884 write_back = WRITE_BACK;
3885 }
3886 }
3887 }
3888 else
3889 {
3890 if (my_get_expression (&inst.reloc.exp, &p))
3891 return FAIL;
3892
3893 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3894 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3895 inst.reloc.pc_rel = 1;
3896 inst.instruction |= (REG_PC << 16);
3897 pre_inc = PRE_INDEX;
3898 }
3899
3900 inst.instruction |= write_back | pre_inc;
3901 *str = p;
3902 return SUCCESS;
3903}
3904
e16bb312
NC
3905static int
3906cp_byte_address_offset (str)
3907 char ** str;
3908{
3909 int offset;
3910
3911 skip_whitespace (* str);
3912
3913 if (! is_immediate_prefix (**str))
3914 {
3915 inst.error = _("immediate expression expected");
3916 return FAIL;
3917 }
3918
3919 (*str)++;
3920
3921 if (my_get_expression (& inst.reloc.exp, str))
3922 return FAIL;
3923
3924 if (inst.reloc.exp.X_op == O_constant)
3925 {
3926 offset = inst.reloc.exp.X_add_number;
3927
3928 if (offset > 255 || offset < -255)
3929 {
3930 inst.error = _("offset too large");
3931 return FAIL;
3932 }
3933
3934 if (offset >= 0)
3935 inst.instruction |= INDEX_UP;
3936 else
3937 offset = -offset;
3938
3939 inst.instruction |= offset;
3940 }
3941 else
3942 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3943
3944 return SUCCESS;
3945}
3946
3947static int
3948cp_byte_address_required_here (str)
3949 char ** str;
3950{
3951 char * p = * str;
3952 int pre_inc = 0;
3953 int write_back = 0;
3954
3955 if (*p == '[')
3956 {
3957 int reg;
3958
3959 p++;
3960 skip_whitespace (p);
3961
3962 if ((reg = reg_required_here (& p, 16)) == FAIL)
3963 return FAIL;
3964
3965 skip_whitespace (p);
3966
3967 if (*p == ']')
3968 {
3969 p++;
3970
3971 if (skip_past_comma (& p) == SUCCESS)
3972 {
3973 /* [Rn], #expr */
3974 write_back = WRITE_BACK;
3975
3976 if (reg == REG_PC)
3977 {
3978 inst.error = _("pc may not be used in post-increment");
3979 return FAIL;
3980 }
3981
3982 if (cp_byte_address_offset (& p) == FAIL)
3983 return FAIL;
3984 }
3985 else
3986 pre_inc = PRE_INDEX | INDEX_UP;
3987 }
3988 else
3989 {
3990 /* '['Rn, #expr']'[!] */
3991
3992 if (skip_past_comma (& p) == FAIL)
3993 {
3994 inst.error = _("pre-indexed expression expected");
3995 return FAIL;
3996 }
3997
3998 pre_inc = PRE_INDEX;
3999
4000 if (cp_byte_address_offset (& p) == FAIL)
4001 return FAIL;
4002
4003 skip_whitespace (p);
4004
4005 if (*p++ != ']')
4006 {
4007 inst.error = _("missing ]");
4008 return FAIL;
4009 }
4010
4011 skip_whitespace (p);
4012
4013 if (*p == '!')
4014 {
4015 if (reg == REG_PC)
4016 {
4017 inst.error = _("pc may not be used with write-back");
4018 return FAIL;
4019 }
4020
4021 p++;
4022 write_back = WRITE_BACK;
4023 }
4024 }
4025 }
4026 else
4027 {
4028 if (my_get_expression (&inst.reloc.exp, &p))
4029 return FAIL;
4030
4031 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4032 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4033 inst.reloc.pc_rel = 1;
4034 inst.instruction |= (REG_PC << 16);
4035 pre_inc = PRE_INDEX;
4036 }
4037
4038 inst.instruction |= write_back | pre_inc;
4039 *str = p;
4040 return SUCCESS;
4041}
4042
b99bd4ef 4043static void
f2b7cb0a 4044do_empty (str)
b99bd4ef 4045 char * str;
b99bd4ef
NC
4046{
4047 /* Do nothing really. */
b99bd4ef 4048 end_of_line (str);
b99bd4ef
NC
4049}
4050
4051static void
f2b7cb0a 4052do_mrs (str)
b99bd4ef 4053 char *str;
b99bd4ef
NC
4054{
4055 int skip = 0;
4056
4057 /* Only one syntax. */
4058 skip_whitespace (str);
4059
4060 if (reg_required_here (&str, 12) == FAIL)
4061 {
4062 inst.error = BAD_ARGS;
4063 return;
4064 }
4065
4066 if (skip_past_comma (&str) == FAIL)
4067 {
4068 inst.error = _("comma expected after register name");
4069 return;
4070 }
4071
4072 skip_whitespace (str);
4073
4074 if ( strcmp (str, "CPSR") == 0
4075 || strcmp (str, "SPSR") == 0
2d2255b5 4076 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4077 || strcmp (str, "cpsr") == 0
4078 || strcmp (str, "spsr") == 0)
4079 skip = 4;
4080
2d2255b5 4081 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4082 else if ( strcmp (str, "cpsr_all") == 0
4083 || strcmp (str, "spsr_all") == 0)
4084 skip = 8;
4085 else
4086 {
f03698e6 4087 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4088 return;
4089 }
4090
4091 if (* str == 's' || * str == 'S')
4092 inst.instruction |= SPSR_BIT;
4093 str += skip;
4094
b99bd4ef
NC
4095 end_of_line (str);
4096}
4097
4098/* Two possible forms:
4099 "{C|S}PSR_<field>, Rm",
4100 "{C|S}PSR_f, #expression". */
4101
4102static void
f2b7cb0a 4103do_msr (str)
b99bd4ef 4104 char * str;
b99bd4ef
NC
4105{
4106 skip_whitespace (str);
4107
4108 if (psr_required_here (& str) == FAIL)
4109 return;
4110
4111 if (skip_past_comma (& str) == FAIL)
4112 {
4113 inst.error = _("comma missing after psr flags");
4114 return;
4115 }
4116
4117 skip_whitespace (str);
4118
4119 if (reg_required_here (& str, 0) != FAIL)
4120 {
4121 inst.error = NULL;
b99bd4ef
NC
4122 end_of_line (str);
4123 return;
4124 }
4125
4126 if (! is_immediate_prefix (* str))
4127 {
4128 inst.error =
4129 _("only a register or immediate value can follow a psr flag");
4130 return;
4131 }
4132
4133 str ++;
4134 inst.error = NULL;
4135
4136 if (my_get_expression (& inst.reloc.exp, & str))
4137 {
4138 inst.error =
4139 _("only a register or immediate value can follow a psr flag");
4140 return;
4141 }
4142
4143#if 0 /* The first edition of the ARM architecture manual stated that
4144 writing anything other than the flags with an immediate operation
4145 had UNPREDICTABLE effects. This constraint was removed in the
4146 second edition of the specification. */
4147 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4148 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4149 {
4150 inst.error = _("immediate value cannot be used to set this field");
4151 return;
4152 }
4153#endif
4154
f2b7cb0a 4155 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4156
4157 if (inst.reloc.exp.X_add_symbol)
4158 {
4159 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4160 inst.reloc.pc_rel = 0;
4161 }
4162 else
4163 {
4164 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4165
4166 if (value == (unsigned) FAIL)
4167 {
f03698e6 4168 inst.error = _("invalid constant");
b99bd4ef
NC
4169 return;
4170 }
4171
4172 inst.instruction |= value;
4173 }
4174
4175 inst.error = NULL;
b99bd4ef
NC
4176 end_of_line (str);
4177}
4178
4179/* Long Multiply Parser
4180 UMULL RdLo, RdHi, Rm, Rs
4181 SMULL RdLo, RdHi, Rm, Rs
4182 UMLAL RdLo, RdHi, Rm, Rs
4183 SMLAL RdLo, RdHi, Rm, Rs. */
4184
4185static void
f2b7cb0a 4186do_mull (str)
b99bd4ef 4187 char * str;
b99bd4ef
NC
4188{
4189 int rdlo, rdhi, rm, rs;
4190
4191 /* Only one format "rdlo, rdhi, rm, rs". */
4192 skip_whitespace (str);
4193
4194 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4195 {
4196 inst.error = BAD_ARGS;
4197 return;
4198 }
4199
4200 if (skip_past_comma (&str) == FAIL
4201 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4202 {
4203 inst.error = BAD_ARGS;
4204 return;
4205 }
4206
4207 if (skip_past_comma (&str) == FAIL
4208 || (rm = reg_required_here (&str, 0)) == FAIL)
4209 {
4210 inst.error = BAD_ARGS;
4211 return;
4212 }
4213
4214 /* rdhi, rdlo and rm must all be different. */
4215 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4216 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4217
4218 if (skip_past_comma (&str) == FAIL
4219 || (rs = reg_required_here (&str, 8)) == FAIL)
4220 {
4221 inst.error = BAD_ARGS;
4222 return;
4223 }
4224
4225 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4226 {
4227 inst.error = BAD_PC;
4228 return;
4229 }
4230
b99bd4ef 4231 end_of_line (str);
b99bd4ef
NC
4232}
4233
4234static void
f2b7cb0a 4235do_mul (str)
b99bd4ef 4236 char * str;
b99bd4ef
NC
4237{
4238 int rd, rm;
4239
4240 /* Only one format "rd, rm, rs". */
4241 skip_whitespace (str);
4242
4243 if ((rd = reg_required_here (&str, 16)) == FAIL)
4244 {
4245 inst.error = BAD_ARGS;
4246 return;
4247 }
4248
4249 if (rd == REG_PC)
4250 {
4251 inst.error = BAD_PC;
4252 return;
4253 }
4254
4255 if (skip_past_comma (&str) == FAIL
4256 || (rm = reg_required_here (&str, 0)) == FAIL)
4257 {
4258 inst.error = BAD_ARGS;
4259 return;
4260 }
4261
4262 if (rm == REG_PC)
4263 {
4264 inst.error = BAD_PC;
4265 return;
4266 }
4267
4268 if (rm == rd)
4269 as_tsktsk (_("rd and rm should be different in mul"));
4270
4271 if (skip_past_comma (&str) == FAIL
4272 || (rm = reg_required_here (&str, 8)) == FAIL)
4273 {
4274 inst.error = BAD_ARGS;
4275 return;
4276 }
4277
4278 if (rm == REG_PC)
4279 {
4280 inst.error = BAD_PC;
4281 return;
4282 }
4283
b99bd4ef 4284 end_of_line (str);
b99bd4ef
NC
4285}
4286
4287static void
f2b7cb0a 4288do_mla (str)
b99bd4ef 4289 char * str;
b99bd4ef
NC
4290{
4291 int rd, rm;
4292
4293 /* Only one format "rd, rm, rs, rn". */
4294 skip_whitespace (str);
4295
4296 if ((rd = reg_required_here (&str, 16)) == FAIL)
4297 {
4298 inst.error = BAD_ARGS;
4299 return;
4300 }
4301
4302 if (rd == REG_PC)
4303 {
4304 inst.error = BAD_PC;
4305 return;
4306 }
4307
4308 if (skip_past_comma (&str) == FAIL
4309 || (rm = reg_required_here (&str, 0)) == FAIL)
4310 {
4311 inst.error = BAD_ARGS;
4312 return;
4313 }
4314
4315 if (rm == REG_PC)
4316 {
4317 inst.error = BAD_PC;
4318 return;
4319 }
4320
4321 if (rm == rd)
4322 as_tsktsk (_("rd and rm should be different in mla"));
4323
4324 if (skip_past_comma (&str) == FAIL
4325 || (rd = reg_required_here (&str, 8)) == FAIL
4326 || skip_past_comma (&str) == FAIL
4327 || (rm = reg_required_here (&str, 12)) == FAIL)
4328 {
4329 inst.error = BAD_ARGS;
4330 return;
4331 }
4332
4333 if (rd == REG_PC || rm == REG_PC)
4334 {
4335 inst.error = BAD_PC;
4336 return;
4337 }
4338
b99bd4ef 4339 end_of_line (str);
b99bd4ef
NC
4340}
4341
4342/* Expects *str -> the characters "acc0", possibly with leading blanks.
4343 Advances *str to the next non-alphanumeric.
4344 Returns 0, or else FAIL (in which case sets inst.error).
4345
4346 (In a future XScale, there may be accumulators other than zero.
4347 At that time this routine and its callers can be upgraded to suit.) */
4348
4349static int
4350accum0_required_here (str)
4351 char ** str;
4352{
4353 static char buff [128]; /* Note the address is taken. Hence, static. */
4354 char * p = * str;
4355 char c;
4356 int result = 0; /* The accum number. */
4357
4358 skip_whitespace (p);
4359
4360 *str = p; /* Advance caller's string pointer too. */
4361 c = *p++;
3882b010 4362 while (ISALNUM (c))
b99bd4ef
NC
4363 c = *p++;
4364
4365 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4366
4367 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4368 {
4369 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4370 inst.error = buff;
4371 result = FAIL;
4372 }
4373
4374 *p = c; /* Unzap. */
4375 *str = p; /* Caller's string pointer to after match. */
4376 return result;
4377}
4378
4379/* Expects **str -> after a comma. May be leading blanks.
4380 Advances *str, recognizing a load mode, and setting inst.instruction.
4381 Returns rn, or else FAIL (in which case may set inst.error
4382 and not advance str)
4383
4384 Note: doesn't know Rd, so no err checks that require such knowledge. */
4385
4386static int
4387ld_mode_required_here (string)
4388 char ** string;
4389{
4390 char * str = * string;
4391 int rn;
4392 int pre_inc = 0;
4393
4394 skip_whitespace (str);
4395
4396 if (* str == '[')
4397 {
4398 str++;
4399
4400 skip_whitespace (str);
4401
4402 if ((rn = reg_required_here (& str, 16)) == FAIL)
4403 return FAIL;
4404
4405 skip_whitespace (str);
4406
4407 if (* str == ']')
4408 {
4409 str ++;
4410
4411 if (skip_past_comma (& str) == SUCCESS)
4412 {
4413 /* [Rn],... (post inc) */
90e4755a 4414 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4415 return FAIL;
4416 }
4417 else /* [Rn] */
4418 {
cc8a6dd0 4419 skip_whitespace (str);
b99bd4ef 4420
cc8a6dd0
KH
4421 if (* str == '!')
4422 {
4423 str ++;
4424 inst.instruction |= WRITE_BACK;
4425 }
b99bd4ef
NC
4426
4427 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4428 pre_inc = 1;
4429 }
4430 }
4431 else /* [Rn,...] */
4432 {
4433 if (skip_past_comma (& str) == FAIL)
4434 {
4435 inst.error = _("pre-indexed expression expected");
4436 return FAIL;
4437 }
4438
4439 pre_inc = 1;
4440
90e4755a 4441 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4442 return FAIL;
4443
4444 skip_whitespace (str);
4445
4446 if (* str ++ != ']')
4447 {
4448 inst.error = _("missing ]");
4449 return FAIL;
4450 }
4451
4452 skip_whitespace (str);
4453
4454 if (* str == '!')
4455 {
4456 str ++;
4457 inst.instruction |= WRITE_BACK;
4458 }
4459 }
4460 }
4461 else if (* str == '=') /* ldr's "r,=label" syntax */
4462 /* We should never reach here, because <text> = <expression> is
4463 caught gas/read.c read_a_source_file() as a .set operation. */
4464 return FAIL;
4465 else /* PC +- 8 bit immediate offset. */
4466 {
4467 if (my_get_expression (& inst.reloc.exp, & str))
4468 return FAIL;
4469
4470 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4471 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4472 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4473 inst.reloc.pc_rel = 1;
4474 inst.instruction |= (REG_PC << 16);
4475
4476 rn = REG_PC;
4477 pre_inc = 1;
4478 }
4479
4480 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4481 * string = str;
4482
4483 return rn;
4484}
4485
4486/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4487 SMLAxy{cond} Rd,Rm,Rs,Rn
4488 SMLAWy{cond} Rd,Rm,Rs,Rn
4489 Error if any register is R15. */
4490
4491static void
f2b7cb0a 4492do_smla (str)
b99bd4ef 4493 char * str;
b99bd4ef
NC
4494{
4495 int rd, rm, rs, rn;
4496
4497 skip_whitespace (str);
4498
4499 if ((rd = reg_required_here (& str, 16)) == FAIL
4500 || skip_past_comma (& str) == FAIL
4501 || (rm = reg_required_here (& str, 0)) == FAIL
4502 || skip_past_comma (& str) == FAIL
4503 || (rs = reg_required_here (& str, 8)) == FAIL
4504 || skip_past_comma (& str) == FAIL
4505 || (rn = reg_required_here (& str, 12)) == FAIL)
4506 inst.error = BAD_ARGS;
4507
4508 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4509 inst.error = BAD_PC;
4510
b99bd4ef
NC
4511 else
4512 end_of_line (str);
4513}
4514
4515/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4516 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4517 Error if any register is R15.
4518 Warning if Rdlo == Rdhi. */
4519
4520static void
f2b7cb0a 4521do_smlal (str)
b99bd4ef 4522 char * str;
b99bd4ef
NC
4523{
4524 int rdlo, rdhi, rm, rs;
4525
4526 skip_whitespace (str);
4527
4528 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4529 || skip_past_comma (& str) == FAIL
4530 || (rdhi = reg_required_here (& str, 16)) == FAIL
4531 || skip_past_comma (& str) == FAIL
4532 || (rm = reg_required_here (& str, 0)) == FAIL
4533 || skip_past_comma (& str) == FAIL
4534 || (rs = reg_required_here (& str, 8)) == FAIL)
4535 {
4536 inst.error = BAD_ARGS;
4537 return;
4538 }
4539
4540 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4541 {
4542 inst.error = BAD_PC;
4543 return;
4544 }
4545
4546 if (rdlo == rdhi)
4547 as_tsktsk (_("rdhi and rdlo must be different"));
4548
f2b7cb0a 4549 end_of_line (str);
b99bd4ef
NC
4550}
4551
4552/* ARM V5E (El Segundo) signed-multiply (argument parse)
4553 SMULxy{cond} Rd,Rm,Rs
4554 Error if any register is R15. */
4555
4556static void
f2b7cb0a 4557do_smul (str)
b99bd4ef 4558 char * str;
b99bd4ef
NC
4559{
4560 int rd, rm, rs;
4561
4562 skip_whitespace (str);
4563
4564 if ((rd = reg_required_here (& str, 16)) == FAIL
4565 || skip_past_comma (& str) == FAIL
4566 || (rm = reg_required_here (& str, 0)) == FAIL
4567 || skip_past_comma (& str) == FAIL
4568 || (rs = reg_required_here (& str, 8)) == FAIL)
4569 inst.error = BAD_ARGS;
4570
4571 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4572 inst.error = BAD_PC;
4573
b99bd4ef
NC
4574 else
4575 end_of_line (str);
4576}
4577
4578/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4579 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4580 Error if any register is R15. */
4581
4582static void
f2b7cb0a 4583do_qadd (str)
b99bd4ef 4584 char * str;
b99bd4ef
NC
4585{
4586 int rd, rm, rn;
4587
4588 skip_whitespace (str);
4589
4590 if ((rd = reg_required_here (& str, 12)) == FAIL
4591 || skip_past_comma (& str) == FAIL
4592 || (rm = reg_required_here (& str, 0)) == FAIL
4593 || skip_past_comma (& str) == FAIL
4594 || (rn = reg_required_here (& str, 16)) == FAIL)
4595 inst.error = BAD_ARGS;
4596
4597 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4598 inst.error = BAD_PC;
4599
b99bd4ef
NC
4600 else
4601 end_of_line (str);
4602}
4603
4604/* ARM V5E (el Segundo)
4605 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4606 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4607
4608 These are equivalent to the XScale instructions MAR and MRA,
4609 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4610
4611 Result unpredicatable if Rd or Rn is R15. */
4612
4613static void
f2b7cb0a 4614do_co_reg2c (str)
b99bd4ef 4615 char * str;
b99bd4ef
NC
4616{
4617 int rd, rn;
4618
4619 skip_whitespace (str);
4620
4621 if (co_proc_number (& str) == FAIL)
4622 {
4623 if (!inst.error)
4624 inst.error = BAD_ARGS;
4625 return;
4626 }
4627
4628 if (skip_past_comma (& str) == FAIL
4629 || cp_opc_expr (& str, 4, 4) == FAIL)
4630 {
4631 if (!inst.error)
4632 inst.error = BAD_ARGS;
4633 return;
4634 }
4635
4636 if (skip_past_comma (& str) == FAIL
4637 || (rd = reg_required_here (& str, 12)) == FAIL)
4638 {
4639 if (!inst.error)
4640 inst.error = BAD_ARGS;
4641 return;
4642 }
4643
4644 if (skip_past_comma (& str) == FAIL
4645 || (rn = reg_required_here (& str, 16)) == FAIL)
4646 {
4647 if (!inst.error)
4648 inst.error = BAD_ARGS;
4649 return;
4650 }
4651
09d92015
MM
4652 /* Unpredictable result if rd or rn is R15. */
4653 if (rd == REG_PC || rn == REG_PC)
4654 as_tsktsk
4655 (_("Warning: instruction unpredictable when using r15"));
4656
4657 if (skip_past_comma (& str) == FAIL
4658 || cp_reg_required_here (& str, 0) == FAIL)
4659 {
4660 if (!inst.error)
4661 inst.error = BAD_ARGS;
4662 return;
4663 }
4664
4665 end_of_line (str);
4666}
4667
4668/* ARM V5 count-leading-zeroes instruction (argument parse)
4669 CLZ{<cond>} <Rd>, <Rm>
4670 Condition defaults to COND_ALWAYS.
4671 Error if Rd or Rm are R15. */
4672
4673static void
4674do_clz (str)
4675 char * str;
4676{
4677 int rd, rm;
4678
4679 skip_whitespace (str);
4680
4681 if (((rd = reg_required_here (& str, 12)) == FAIL)
4682 || (skip_past_comma (& str) == FAIL)
4683 || ((rm = reg_required_here (& str, 0)) == FAIL))
4684 inst.error = BAD_ARGS;
4685
4686 else if (rd == REG_PC || rm == REG_PC )
4687 inst.error = BAD_PC;
4688
4689 else
4690 end_of_line (str);
4691}
4692
4693/* ARM V5 (argument parse)
4694 LDC2{L} <coproc>, <CRd>, <addressing mode>
4695 STC2{L} <coproc>, <CRd>, <addressing mode>
4696 Instruction is not conditional, and has 0xf in the condition field.
4697 Otherwise, it's the same as LDC/STC. */
4698
4699static void
4700do_lstc2 (str)
4701 char * str;
4702{
4703 skip_whitespace (str);
4704
4705 if (co_proc_number (& str) == FAIL)
4706 {
4707 if (!inst.error)
4708 inst.error = BAD_ARGS;
4709 }
4710 else if (skip_past_comma (& str) == FAIL
4711 || cp_reg_required_here (& str, 12) == FAIL)
4712 {
4713 if (!inst.error)
4714 inst.error = BAD_ARGS;
4715 }
4716 else if (skip_past_comma (& str) == FAIL
4717 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4718 {
4719 if (! inst.error)
4720 inst.error = BAD_ARGS;
4721 }
4722 else
4723 end_of_line (str);
4724}
4725
4726/* ARM V5 (argument parse)
4727 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4728 Instruction is not conditional, and has 0xf in the condition field.
4729 Otherwise, it's the same as CDP. */
4730
4731static void
4732do_cdp2 (str)
4733 char * str;
4734{
4735 skip_whitespace (str);
4736
4737 if (co_proc_number (& str) == FAIL)
4738 {
4739 if (!inst.error)
4740 inst.error = BAD_ARGS;
4741 return;
4742 }
4743
4744 if (skip_past_comma (& str) == FAIL
4745 || cp_opc_expr (& str, 20,4) == FAIL)
4746 {
4747 if (!inst.error)
4748 inst.error = BAD_ARGS;
4749 return;
4750 }
4751
4752 if (skip_past_comma (& str) == FAIL
4753 || cp_reg_required_here (& str, 12) == FAIL)
4754 {
4755 if (!inst.error)
4756 inst.error = BAD_ARGS;
4757 return;
4758 }
4759
4760 if (skip_past_comma (& str) == FAIL
4761 || cp_reg_required_here (& str, 16) == FAIL)
4762 {
4763 if (!inst.error)
4764 inst.error = BAD_ARGS;
4765 return;
4766 }
4767
4768 if (skip_past_comma (& str) == FAIL
4769 || cp_reg_required_here (& str, 0) == FAIL)
4770 {
4771 if (!inst.error)
4772 inst.error = BAD_ARGS;
4773 return;
4774 }
4775
4776 if (skip_past_comma (& str) == SUCCESS)
4777 {
4778 if (cp_opc_expr (& str, 5, 3) == FAIL)
4779 {
4780 if (!inst.error)
4781 inst.error = BAD_ARGS;
4782 return;
4783 }
4784 }
4785
4786 end_of_line (str);
4787}
4788
4789/* ARM V5 (argument parse)
4790 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4791 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4792 Instruction is not conditional, and has 0xf in the condition field.
4793 Otherwise, it's the same as MCR/MRC. */
4794
4795static void
4796do_co_reg2 (str)
4797 char * str;
4798{
4799 skip_whitespace (str);
4800
4801 if (co_proc_number (& str) == FAIL)
4802 {
4803 if (!inst.error)
4804 inst.error = BAD_ARGS;
4805 return;
4806 }
4807
4808 if (skip_past_comma (& str) == FAIL
4809 || cp_opc_expr (& str, 21, 3) == FAIL)
4810 {
4811 if (!inst.error)
4812 inst.error = BAD_ARGS;
4813 return;
4814 }
4815
4816 if (skip_past_comma (& str) == FAIL
4817 || reg_required_here (& str, 12) == FAIL)
4818 {
4819 if (!inst.error)
4820 inst.error = BAD_ARGS;
4821 return;
4822 }
4823
4824 if (skip_past_comma (& str) == FAIL
4825 || cp_reg_required_here (& str, 16) == FAIL)
4826 {
4827 if (!inst.error)
4828 inst.error = BAD_ARGS;
4829 return;
4830 }
4831
4832 if (skip_past_comma (& str) == FAIL
4833 || cp_reg_required_here (& str, 0) == FAIL)
4834 {
4835 if (!inst.error)
4836 inst.error = BAD_ARGS;
4837 return;
4838 }
4839
4840 if (skip_past_comma (& str) == SUCCESS)
4841 {
4842 if (cp_opc_expr (& str, 5, 3) == FAIL)
4843 {
4844 if (!inst.error)
4845 inst.error = BAD_ARGS;
4846 return;
4847 }
4848 }
4849
4850 end_of_line (str);
4851}
4852
4853/* ARM v5TEJ. Jump to Jazelle code. */
4854static void
4855do_bxj (str)
4856 char * str;
4857{
4858 int reg;
4859
4860 skip_whitespace (str);
4861
4862 if ((reg = reg_required_here (&str, 0)) == FAIL)
4863 {
4864 inst.error = BAD_ARGS;
4865 return;
4866 }
4867
4868 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4869 if (reg == REG_PC)
4870 as_tsktsk (_("use of r15 in bxj is not really useful"));
4871
4872 end_of_line (str);
4873}
4874
4875/* ARM V6 umaal (argument parse). */
4876
4877static void
4878do_umaal (str)
4879 char *str;
4880{
4881
4882 int rdlo, rdhi, rm, rs;
4883
4884 skip_whitespace (str);
4885 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4886 || skip_past_comma (& str) == FAIL
4887 || (rdhi = reg_required_here (& str, 16)) == FAIL
4888 || skip_past_comma (& str) == FAIL
4889 || (rm = reg_required_here (& str, 0)) == FAIL
4890 || skip_past_comma (& str) == FAIL
5533419b 4891 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4892 {
4893 inst.error = BAD_ARGS;
4894 return;
4895 }
4896
4897 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4898 {
4899 inst.error = BAD_PC;
4900 return;
4901 }
4902
4903 end_of_line (str);
4904}
4905
4906/* ARM V6 strex (argument parse). */
4907
4908static void
4909do_strex (str)
4910 char *str;
4911{
4912 int rd, rm, rn;
4913
4914 /* Parse Rd, Rm,. */
4915 skip_whitespace (str);
4916 if ((rd = reg_required_here (& str, 12)) == FAIL
4917 || skip_past_comma (& str) == FAIL
4918 || (rm = reg_required_here (& str, 0)) == FAIL
4919 || skip_past_comma (& str) == FAIL)
4920 {
4921 inst.error = BAD_ARGS;
4922 return;
4923 }
4924 if (rd == REG_PC || rm == REG_PC)
4925 {
4926 inst.error = BAD_PC;
4927 return;
4928 }
4929 if (rd == rm)
4930 {
4931 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4932 return;
4933 }
4934
4935 /* Skip past '['. */
4936 if ((strlen (str) >= 1)
4937 && strncmp (str, "[", 1) == 0)
4938 str+=1;
4939 skip_whitespace (str);
4940
4941 /* Parse Rn. */
4942 if ((rn = reg_required_here (& str, 16)) == FAIL)
4943 {
4944 inst.error = BAD_ARGS;
4945 return;
4946 }
4947 else if (rn == REG_PC)
4948 {
4949 inst.error = BAD_PC;
4950 return;
4951 }
4952 if (rd == rn)
4953 {
4954 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4955 return;
4956 }
4957 skip_whitespace (str);
4958
4959 /* Skip past ']'. */
4960 if ((strlen (str) >= 1)
4961 && strncmp (str, "]", 1) == 0)
4962 str+=1;
4963
4964 end_of_line (str);
4965}
4966
4967/* ARM V6 ssat (argument parse). */
4968
4969static void
4970do_ssat (str)
4971 char* str;
4972{
4973 do_sat (&str, /*bias=*/-1);
4974 end_of_line (str);
4975}
4976
4977/* ARM V6 usat (argument parse). */
4978
4979static void
4980do_usat (str)
4981 char* str;
4982{
4983 do_sat (&str, /*bias=*/0);
4984 end_of_line (str);
4985}
4986
4987static void
4988do_sat (str, bias)
4989 char **str;
4990 int bias;
4991{
4992 int rd, rm;
4993 expressionS expr;
4994
4995 skip_whitespace (*str);
4996
4997 /* Parse <Rd>, field. */
4998 if ((rd = reg_required_here (str, 12)) == FAIL
4999 || skip_past_comma (str) == FAIL)
5000 {
5001 inst.error = BAD_ARGS;
5002 return;
5003 }
5004 if (rd == REG_PC)
5005 {
5006 inst.error = BAD_PC;
5007 return;
5008 }
5009
5010 /* Parse #<immed>, field. */
5011 if (is_immediate_prefix (**str))
5012 (*str)++;
5013 else
5014 {
5015 inst.error = _("immediate expression expected");
5016 return;
5017 }
5018 if (my_get_expression (&expr, str))
5019 {
5020 inst.error = _("bad expression");
5021 return;
5022 }
5023 if (expr.X_op != O_constant)
5024 {
5025 inst.error = _("constant expression expected");
5026 return;
5027 }
5028 if (expr.X_add_number + bias < 0
5029 || expr.X_add_number + bias > 31)
5030 {
5031 inst.error = _("immediate value out of range");
5032 return;
5033 }
5034 inst.instruction |= (expr.X_add_number + bias) << 16;
5035 if (skip_past_comma (str) == FAIL)
5036 {
5037 inst.error = BAD_ARGS;
5038 return;
5039 }
5040
5041 /* Parse <Rm> field. */
5042 if ((rm = reg_required_here (str, 0)) == FAIL)
5043 {
5044 inst.error = BAD_ARGS;
5045 return;
5046 }
5047 if (rm == REG_PC)
5048 {
5049 inst.error = BAD_PC;
5050 return;
5051 }
5052
5053 if (skip_past_comma (str) == SUCCESS)
5054 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5055}
5056
5057/* ARM V6 ssat16 (argument parse). */
5058
5059static void
5060do_ssat16 (str)
5061 char *str;
5062{
5063 do_sat16 (&str, /*bias=*/-1);
5064 end_of_line (str);
5065}
5066
5067static void
5068do_usat16 (str)
5069 char *str;
5070{
5071 do_sat16 (&str, /*bias=*/0);
5072 end_of_line (str);
5073}
5074
5075static void
5076do_sat16 (str, bias)
5077 char **str;
5078 int bias;
5079{
5080 int rd, rm;
5081 expressionS expr;
5082
5083 skip_whitespace (*str);
5084
5085 /* Parse the <Rd> field. */
5086 if ((rd = reg_required_here (str, 12)) == FAIL
5087 || skip_past_comma (str) == FAIL)
5088 {
5089 inst.error = BAD_ARGS;
5090 return;
5091 }
5092 if (rd == REG_PC)
5093 {
5094 inst.error = BAD_PC;
5095 return;
5096 }
5097
5098 /* Parse #<immed>, field. */
5099 if (is_immediate_prefix (**str))
5100 (*str)++;
5101 else
5102 {
5103 inst.error = _("immediate expression expected");
5104 return;
5105 }
5106 if (my_get_expression (&expr, str))
5107 {
5108 inst.error = _("bad expression");
5109 return;
5110 }
5111 if (expr.X_op != O_constant)
5112 {
5113 inst.error = _("constant expression expected");
5114 return;
5115 }
5116 if (expr.X_add_number + bias < 0
5117 || expr.X_add_number + bias > 15)
5118 {
5119 inst.error = _("immediate value out of range");
5120 return;
5121 }
5122 inst.instruction |= (expr.X_add_number + bias) << 16;
5123 if (skip_past_comma (str) == FAIL)
5124 {
5125 inst.error = BAD_ARGS;
5126 return;
5127 }
5128
5129 /* Parse <Rm> field. */
5130 if ((rm = reg_required_here (str, 0)) == FAIL)
5131 {
5132 inst.error = BAD_ARGS;
5133 return;
5134 }
5135 if (rm == REG_PC)
5136 {
5137 inst.error = BAD_PC;
5138 return;
5139 }
5140}
5141
5142/* ARM V6 srs (argument parse). */
5143
5144static void
5145do_srs (str)
5146 char* str;
5147{
5148 char *exclam;
5149 skip_whitespace (str);
5150 exclam = strchr (str, '!');
5151 if (exclam)
5152 *exclam = '\0';
5153 do_cps_mode (&str);
5154 if (exclam)
5155 *exclam = '!';
5156 if (*str == '!')
5157 {
5158 inst.instruction |= WRITE_BACK;
5159 str++;
5160 }
5161 end_of_line (str);
5162}
5163
5164/* ARM V6 SMMUL (argument parse). */
5165
5166static void
5167do_smmul (str)
5168 char* str;
5169{
5170 int rd, rm, rs;
5171
5172 skip_whitespace (str);
5173 if ((rd = reg_required_here (&str, 16)) == FAIL
5174 || skip_past_comma (&str) == FAIL
5175 || (rm = reg_required_here (&str, 0)) == FAIL
5176 || skip_past_comma (&str) == FAIL
5177 || (rs = reg_required_here (&str, 8)) == FAIL)
5178 {
5179 inst.error = BAD_ARGS;
5180 return;
5181 }
5182
5183 if (rd == REG_PC
5184 || rm == REG_PC
5185 || rs == REG_PC)
5186 {
5187 inst.error = BAD_PC;
5188 return;
5189 }
5190
5191 end_of_line (str);
5192
5193}
5194
5195/* ARM V6 SMLALD (argument parse). */
5196
5197static void
5198do_smlald (str)
5199 char* str;
5200{
5201 int rdlo, rdhi, rm, rs;
5202 skip_whitespace (str);
5203 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5204 || skip_past_comma (&str) == FAIL
5205 || (rdhi = reg_required_here (&str, 16)) == FAIL
5206 || skip_past_comma (&str) == FAIL
5207 || (rm = reg_required_here (&str, 0)) == FAIL
5208 || skip_past_comma (&str) == FAIL
5209 || (rs = reg_required_here (&str, 8)) == FAIL)
5210 {
5211 inst.error = BAD_ARGS;
5212 return;
5213 }
5214
5215 if (rdlo == REG_PC
5216 || rdhi == REG_PC
5217 || rm == REG_PC
5218 || rs == REG_PC)
5219 {
5220 inst.error = BAD_PC;
5221 return;
5222 }
5223
5224 end_of_line (str);
5225}
5226
5227/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5228 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5229
5230static void
5231do_smlad (str)
5232 char *str;
5233{
5234 int rd, rm, rs, rn;
5235
5236 skip_whitespace (str);
5237 if ((rd = reg_required_here (&str, 16)) == FAIL
5238 || skip_past_comma (&str) == FAIL
5239 || (rm = reg_required_here (&str, 0)) == FAIL
5240 || skip_past_comma (&str) == FAIL
5241 || (rs = reg_required_here (&str, 8)) == FAIL
5242 || skip_past_comma (&str) == FAIL
5243 || (rn = reg_required_here (&str, 12)) == FAIL)
5244 {
5245 inst.error = BAD_ARGS;
5246 return;
5247 }
5248
5249 if (rd == REG_PC
5250 || rn == REG_PC
5251 || rs == REG_PC
5252 || rm == REG_PC)
5253 {
5254 inst.error = BAD_PC;
5255 return;
5256 }
5257
5258 end_of_line (str);
5259}
5260
5261/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5262 preserving the other bits.
5263
5264 setend <endian_specifier>, where <endian_specifier> is either
5265 BE or LE. */
5266
5267static void
5268do_setend (str)
5269 char *str;
5270{
5271 if (do_endian_specifier (str))
5272 inst.instruction |= 0x200;
5273}
5274
5275/* Returns true if the endian-specifier indicates big-endianness. */
5276
5277static int
5278do_endian_specifier (str)
5279 char *str;
5280{
5281 int big_endian = 0;
5282
5283 skip_whitespace (str);
5284 if (strlen (str) < 2)
5285 inst.error = _("missing endian specifier");
5286 else if (strncasecmp (str, "BE", 2) == 0)
5287 {
5288 str += 2;
5289 big_endian = 1;
5290 }
5291 else if (strncasecmp (str, "LE", 2) == 0)
5292 str += 2;
5293 else
5294 inst.error = _("valid endian specifiers are be or le");
5295
5296 end_of_line (str);
5297
5298 return big_endian;
5299}
5300
5301/* ARM V6 SXTH.
5302
5303 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5304 Condition defaults to COND_ALWAYS.
5305 Error if any register uses R15. */
5306
5307static void
5308do_sxth (str)
5309 char *str;
5310{
5311 int rd, rm;
5312 expressionS expr;
5313 int rotation_clear_mask = 0xfffff3ff;
5314 int rotation_eight_mask = 0x00000400;
5315 int rotation_sixteen_mask = 0x00000800;
5316 int rotation_twenty_four_mask = 0x00000c00;
5317
5318 skip_whitespace (str);
5319 if ((rd = reg_required_here (&str, 12)) == FAIL
5320 || skip_past_comma (&str) == FAIL
5321 || (rm = reg_required_here (&str, 0)) == FAIL)
5322 {
5323 inst.error = BAD_ARGS;
5324 return;
5325 }
5326
5327 else if (rd == REG_PC || rm == REG_PC)
5328 {
5329 inst.error = BAD_PC;
5330 return;
5331 }
5332
5333 /* Zero out the rotation field. */
5334 inst.instruction &= rotation_clear_mask;
5335
5336 /* Check for lack of optional rotation field. */
5337 if (skip_past_comma (&str) == FAIL)
5338 {
5339 end_of_line (str);
5340 return;
5341 }
5342
5343 /* Move past 'ROR'. */
5344 skip_whitespace (str);
5345 if (strncasecmp (str, "ROR", 3) == 0)
5346 str+=3;
5347 else
5348 {
5349 inst.error = _("missing rotation field after comma");
5350 return;
5351 }
5352
5353 /* Get the immediate constant. */
5354 skip_whitespace (str);
5355 if (is_immediate_prefix (* str))
5356 str++;
5357 else
5358 {
5359 inst.error = _("immediate expression expected");
5360 return;
5361 }
5362
5363 if (my_get_expression (&expr, &str))
5364 {
5365 inst.error = _("bad expression");
5366 return;
5367 }
5368
5369 if (expr.X_op != O_constant)
5370 {
5371 inst.error = _("constant expression expected");
5372 return;
5373 }
5374
5375 switch (expr.X_add_number)
5376 {
5377 case 0:
5378 /* Rotation field has already been zeroed. */
5379 break;
5380 case 8:
5381 inst.instruction |= rotation_eight_mask;
5382 break;
5383
5384 case 16:
5385 inst.instruction |= rotation_sixteen_mask;
5386 break;
5387
5388 case 24:
5389 inst.instruction |= rotation_twenty_four_mask;
5390 break;
5391
5392 default:
5393 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5394 break;
5395 }
5396
5397 end_of_line (str);
5398
5399}
5400
5401/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5402 extends it to 32-bits, and adds the result to a value in another
5403 register. You can specify a rotation by 0, 8, 16, or 24 bits
5404 before extracting the 16-bit value.
5405 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5406 Condition defaults to COND_ALWAYS.
5407 Error if any register uses R15. */
5408
5409static void
5410do_sxtah (str)
5411 char *str;
5412{
5413 int rd, rn, rm;
5414 expressionS expr;
5415 int rotation_clear_mask = 0xfffff3ff;
5416 int rotation_eight_mask = 0x00000400;
5417 int rotation_sixteen_mask = 0x00000800;
5418 int rotation_twenty_four_mask = 0x00000c00;
5419
5420 skip_whitespace (str);
5421 if ((rd = reg_required_here (&str, 12)) == FAIL
5422 || skip_past_comma (&str) == FAIL
5423 || (rn = reg_required_here (&str, 16)) == FAIL
5424 || skip_past_comma (&str) == FAIL
5425 || (rm = reg_required_here (&str, 0)) == FAIL)
5426 {
5427 inst.error = BAD_ARGS;
5428 return;
5429 }
5430
5431 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5432 {
5433 inst.error = BAD_PC;
5434 return;
5435 }
5436
5437 /* Zero out the rotation field. */
5438 inst.instruction &= rotation_clear_mask;
5439
5440 /* Check for lack of optional rotation field. */
5441 if (skip_past_comma (&str) == FAIL)
5442 {
5443 end_of_line (str);
5444 return;
5445 }
5446
5447 /* Move past 'ROR'. */
5448 skip_whitespace (str);
5449 if (strncasecmp (str, "ROR", 3) == 0)
5450 str+=3;
5451 else
5452 {
5453 inst.error = _("missing rotation field after comma");
5454 return;
5455 }
5456
5457 /* Get the immediate constant. */
5458 skip_whitespace (str);
5459 if (is_immediate_prefix (* str))
5460 str++;
5461 else
5462 {
5463 inst.error = _("immediate expression expected");
5464 return;
5465 }
5466
5467 if (my_get_expression (&expr, &str))
5468 {
5469 inst.error = _("bad expression");
5470 return;
5471 }
5472
5473 if (expr.X_op != O_constant)
5474 {
5475 inst.error = _("constant expression expected");
5476 return;
5477 }
5478
5479 switch (expr.X_add_number)
5480 {
5481 case 0:
5482 /* Rotation field has already been zeroed. */
5483 break;
5484
5485 case 8:
5486 inst.instruction |= rotation_eight_mask;
5487 break;
5488
5489 case 16:
5490 inst.instruction |= rotation_sixteen_mask;
5491 break;
5492
5493 case 24:
5494 inst.instruction |= rotation_twenty_four_mask;
5495 break;
5496
5497 default:
5498 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5499 break;
5500 }
5501
5502 end_of_line (str);
5503
5504}
5505
5506
5507/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5508 word at the specified address and the following word
5509 respectively.
5510 Unconditionally executed.
5511 Error if Rn is R15.
5512*/
5513
5514static void
5515do_rfe (str)
5516 char *str;
5517{
5518 int rn;
5519
5520 skip_whitespace (str);
5521
5522 if ((rn = reg_required_here (&str, 16)) == FAIL)
5523 return;
b99bd4ef 5524
09d92015 5525 if (rn == REG_PC)
b99bd4ef 5526 {
09d92015 5527 inst.error = BAD_PC;
b99bd4ef
NC
5528 return;
5529 }
5530
09d92015
MM
5531 skip_whitespace (str);
5532
5533 if (*str == '!')
5534 {
5535 inst.instruction |= WRITE_BACK;
5536 str++;
5537 }
b99bd4ef
NC
5538 end_of_line (str);
5539}
5540
09d92015
MM
5541/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5542 register (argument parse).
5543 REV{<cond>} Rd, Rm.
5544 Condition defaults to COND_ALWAYS.
5545 Error if Rd or Rm are R15. */
b99bd4ef
NC
5546
5547static void
09d92015
MM
5548do_rev (str)
5549 char* str;
b99bd4ef
NC
5550{
5551 int rd, rm;
5552
b99bd4ef
NC
5553 skip_whitespace (str);
5554
09d92015
MM
5555 if ((rd = reg_required_here (&str, 12)) == FAIL
5556 || skip_past_comma (&str) == FAIL
5557 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5558 inst.error = BAD_ARGS;
5559
09d92015 5560 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5561 inst.error = BAD_PC;
5562
5563 else
5564 end_of_line (str);
5565}
5566
09d92015
MM
5567/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5568 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5569 Condition defaults to COND_ALWAYS.
5570 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5571
5572static void
09d92015
MM
5573do_qadd16 (str)
5574 char* str;
b99bd4ef 5575{
09d92015
MM
5576 int rd, rm, rn;
5577
b99bd4ef
NC
5578 skip_whitespace (str);
5579
09d92015
MM
5580 if ((rd = reg_required_here (&str, 12)) == FAIL
5581 || skip_past_comma (&str) == FAIL
5582 || (rn = reg_required_here (&str, 16)) == FAIL
5583 || skip_past_comma (&str) == FAIL
5584 || (rm = reg_required_here (&str, 0)) == FAIL)
5585 inst.error = BAD_ARGS;
5586
5587 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5588 inst.error = BAD_PC;
5589
b99bd4ef
NC
5590 else
5591 end_of_line (str);
5592}
5593
09d92015
MM
5594/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5595 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5596 Condition defaults to COND_ALWAYS.
5597 Error if Rd, Rn or Rm are R15. */
5598
5599static void
5600do_pkhbt (str)
5601 char* str;
5602{
5603 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5604}
5605
5606/* ARM V6 PKHTB (Argument Parse). */
5607
5608static void
5609do_pkhtb (str)
5610 char* str;
5611{
5612 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5613}
b99bd4ef
NC
5614
5615static void
09d92015
MM
5616do_pkh_core (str, shift)
5617 char* str;
5618 int shift;
b99bd4ef 5619{
09d92015 5620 int rd, rn, rm;
b99bd4ef 5621
09d92015
MM
5622 skip_whitespace (str);
5623 if (((rd = reg_required_here (&str, 12)) == FAIL)
5624 || (skip_past_comma (&str) == FAIL)
5625 || ((rn = reg_required_here (&str, 16)) == FAIL)
5626 || (skip_past_comma (&str) == FAIL)
5627 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5628 {
09d92015 5629 inst.error = BAD_ARGS;
b99bd4ef
NC
5630 return;
5631 }
5632
09d92015 5633 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5634 {
09d92015 5635 inst.error = BAD_PC;
b99bd4ef
NC
5636 return;
5637 }
5638
09d92015
MM
5639 /* Check for optional shift immediate constant. */
5640 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5641 {
09d92015
MM
5642 if (shift == SHIFT_ASR_IMMEDIATE)
5643 {
5644 /* If the shift specifier is ommited, turn the instruction
5645 into pkhbt rd, rm, rn. First, switch the instruction
5646 code, and clear the rn and rm fields. */
5647 inst.instruction &= 0xfff0f010;
5648 /* Now, re-encode the registers. */
5649 inst.instruction |= (rm << 16) | rn;
5650 }
b99bd4ef
NC
5651 return;
5652 }
5653
09d92015
MM
5654 decode_shift (&str, shift);
5655}
5656
5657/* ARM V6 Load Register Exclusive instruction (argument parse).
5658 LDREX{<cond>} <Rd, [<Rn>]
5659 Condition defaults to COND_ALWAYS.
5660 Error if Rd or Rn are R15.
5661 See ARMARMv6 A4.1.27: LDREX. */
5662
5663
5664static void
5665do_ldrex (str)
5666 char * str;
5667{
5668 int rd, rn;
5669
5670 skip_whitespace (str);
5671
5672 /* Parse Rd. */
5673 if (((rd = reg_required_here (&str, 12)) == FAIL)
5674 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5675 {
09d92015 5676 inst.error = BAD_ARGS;
b99bd4ef
NC
5677 return;
5678 }
09d92015 5679 else if (rd == REG_PC)
b99bd4ef 5680 {
09d92015 5681 inst.error = BAD_PC;
b99bd4ef
NC
5682 return;
5683 }
09d92015 5684 skip_whitespace (str);
b99bd4ef 5685
09d92015
MM
5686 /* Skip past '['. */
5687 if ((strlen (str) >= 1)
5688 &&strncmp (str, "[", 1) == 0)
5689 str+=1;
5690 skip_whitespace (str);
5691
5692 /* Parse Rn. */
5693 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5694 {
09d92015
MM
5695 inst.error = BAD_ARGS;
5696 return;
b99bd4ef 5697 }
09d92015
MM
5698 else if (rn == REG_PC)
5699 {
5700 inst.error = BAD_PC;
5701 return;
5702 }
5703 skip_whitespace (str);
b99bd4ef 5704
09d92015
MM
5705 /* Skip past ']'. */
5706 if ((strlen (str) >= 1)
5707 && strncmp (str, "]", 1) == 0)
5708 str+=1;
5709
b99bd4ef
NC
5710 end_of_line (str);
5711}
5712
09d92015
MM
5713/* ARM V6 change processor state instruction (argument parse)
5714 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5715
5716static void
09d92015
MM
5717do_cps (str)
5718 char * str;
b99bd4ef 5719{
09d92015
MM
5720 do_cps_mode (&str);
5721 end_of_line (str);
5722}
b99bd4ef 5723
09d92015
MM
5724static void
5725do_cpsi (str)
5726 char * str;
5727{
5728 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5729
09d92015 5730 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5731 {
09d92015
MM
5732 skip_whitespace (str);
5733 do_cps_mode (&str);
b99bd4ef 5734 }
09d92015
MM
5735 end_of_line (str);
5736}
b99bd4ef 5737
09d92015
MM
5738static void
5739do_cps_mode (str)
5740 char **str;
5741{
5742 expressionS expr;
5743
5744 skip_whitespace (*str);
5745
5746 if (! is_immediate_prefix (**str))
b99bd4ef 5747 {
09d92015 5748 inst.error = _("immediate expression expected");
b99bd4ef
NC
5749 return;
5750 }
5751
09d92015
MM
5752 (*str)++; /* Strip off the immediate signifier. */
5753 if (my_get_expression (&expr, str))
b99bd4ef 5754 {
09d92015 5755 inst.error = _("bad expression");
b99bd4ef
NC
5756 return;
5757 }
5758
09d92015 5759 if (expr.X_op != O_constant)
b99bd4ef 5760 {
09d92015 5761 inst.error = _("constant expression expected");
b99bd4ef
NC
5762 return;
5763 }
09d92015
MM
5764
5765 /* The mode is a 5 bit field. Valid values are 0-31. */
5766 if (((unsigned) expr.X_add_number) > 31
5767 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5768 {
09d92015
MM
5769 inst.error = _("invalid constant");
5770 return;
b99bd4ef 5771 }
09d92015
MM
5772
5773 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5774}
5775
ea6ef066 5776static void
09d92015
MM
5777do_cps_flags (str, thumb_p)
5778 char **str;
5779 int thumb_p;
ea6ef066 5780{
09d92015
MM
5781 struct cps_flag {
5782 char character;
5783 unsigned long arm_value;
5784 unsigned long thumb_value;
5785 };
5786 static struct cps_flag flag_table[] = {
5787 {'a', 0x100, 0x4 },
5788 {'i', 0x080, 0x2 },
5789 {'f', 0x040, 0x1 }
5790 };
ea6ef066 5791
09d92015 5792 int saw_a_flag = 0;
ea6ef066 5793
09d92015
MM
5794 skip_whitespace (*str);
5795
5796 /* Get the a, f and i flags. */
5797 while (**str && **str != ',')
ea6ef066 5798 {
09d92015
MM
5799 struct cps_flag *p;
5800 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5801 for (p = flag_table; p < q; ++p)
5802 if (strncasecmp (*str, &p->character, 1) == 0)
5803 {
5804 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5805 saw_a_flag = 1;
5806 break;
5807 }
5808 if (p == q)
5809 {
5810 inst.error = _("unrecognized flag");
5811 return;
5812 }
5813 (*str)++;
ea6ef066 5814 }
09d92015
MM
5815 if (!saw_a_flag)
5816 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5817}
5818
b99bd4ef
NC
5819/* THUMB V5 breakpoint instruction (argument parse)
5820 BKPT <immed_8>. */
5821
5822static void
5823do_t_bkpt (str)
5824 char * str;
5825{
5826 expressionS expr;
5827 unsigned long number;
5828
5829 skip_whitespace (str);
5830
5831 /* Allow optional leading '#'. */
5832 if (is_immediate_prefix (*str))
5833 str ++;
5834
5835 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5836 if (my_get_expression (& expr, & str)
5837 || (expr.X_op != O_constant
5838 /* As a convenience we allow 'bkpt' without an operand. */
5839 && expr.X_op != O_absent))
b99bd4ef 5840 {
143c8e19 5841 inst.error = _("bad expression");
b99bd4ef
NC
5842 return;
5843 }
5844
5845 number = expr.X_add_number;
5846
5847 /* Check it fits an 8 bit unsigned. */
5848 if (number != (number & 0xff))
5849 {
5850 inst.error = _("immediate value out of range");
5851 return;
5852 }
5853
5854 inst.instruction |= number;
5855
5856 end_of_line (str);
5857}
5858
5859/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5860 Expects inst.instruction is set for BLX(1).
5861 Note: this is cloned from do_branch, and the reloc changed to be a
5862 new one that can cope with setting one extra bit (the H bit). */
5863
5864static void
f2b7cb0a 5865do_branch25 (str)
b99bd4ef 5866 char * str;
b99bd4ef
NC
5867{
5868 if (my_get_expression (& inst.reloc.exp, & str))
5869 return;
5870
5871#ifdef OBJ_ELF
5872 {
5873 char * save_in;
5874
5875 /* ScottB: February 5, 1998 */
5876 /* Check to see of PLT32 reloc required for the instruction. */
5877
5878 /* arm_parse_reloc() works on input_line_pointer.
5879 We actually want to parse the operands to the branch instruction
5880 passed in 'str'. Save the input pointer and restore it later. */
5881 save_in = input_line_pointer;
5882 input_line_pointer = str;
5883
5884 if (inst.reloc.exp.X_op == O_symbol
5885 && *str == '('
5886 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5887 {
5888 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5889 inst.reloc.pc_rel = 0;
5890 /* Modify str to point to after parsed operands, otherwise
5891 end_of_line() will complain about the (PLT) left in str. */
5892 str = input_line_pointer;
5893 }
5894 else
5895 {
5896 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5897 inst.reloc.pc_rel = 1;
5898 }
5899
5900 input_line_pointer = save_in;
5901 }
5902#else
5903 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5904 inst.reloc.pc_rel = 1;
5905#endif /* OBJ_ELF */
5906
5907 end_of_line (str);
5908}
5909
5910/* ARM V5 branch-link-exchange instruction (argument parse)
5911 BLX <target_addr> ie BLX(1)
5912 BLX{<condition>} <Rm> ie BLX(2)
5913 Unfortunately, there are two different opcodes for this mnemonic.
5914 So, the insns[].value is not used, and the code here zaps values
5915 into inst.instruction.
5916 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5917
5918static void
f2b7cb0a 5919do_blx (str)
b99bd4ef 5920 char * str;
b99bd4ef
NC
5921{
5922 char * mystr = str;
5923 int rm;
5924
b99bd4ef
NC
5925 skip_whitespace (mystr);
5926 rm = reg_required_here (& mystr, 0);
5927
5928 /* The above may set inst.error. Ignore his opinion. */
5929 inst.error = 0;
5930
5931 if (rm != FAIL)
5932 {
5933 /* Arg is a register.
5934 Use the condition code our caller put in inst.instruction.
5935 Pass ourselves off as a BX with a funny opcode. */
5936 inst.instruction |= 0x012fff30;
f2b7cb0a 5937 do_bx (str);
b99bd4ef
NC
5938 }
5939 else
5940 {
5941 /* This must be is BLX <target address>, no condition allowed. */
5942 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5943 {
5944 inst.error = BAD_COND;
b99bd4ef 5945 return;
cc8a6dd0 5946 }
b99bd4ef
NC
5947
5948 inst.instruction = 0xfafffffe;
5949
5950 /* Process like a B/BL, but with a different reloc.
5951 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5952 do_branch25 (str);
b99bd4ef
NC
5953 }
5954}
5955
5956/* ARM V5 Thumb BLX (argument parse)
5957 BLX <target_addr> which is BLX(1)
5958 BLX <Rm> which is BLX(2)
5959 Unfortunately, there are two different opcodes for this mnemonic.
5960 So, the tinsns[].value is not used, and the code here zaps values
5961 into inst.instruction. */
5962
5963static void
5964do_t_blx (str)
5965 char * str;
5966{
5967 char * mystr = str;
5968 int rm;
5969
5970 skip_whitespace (mystr);
5971 inst.instruction = 0x4780;
5972
5973 /* Note that this call is to the ARM register recognizer. BLX(2)
5974 uses the ARM register space, not the Thumb one, so a call to
5975 thumb_reg() would be wrong. */
5976 rm = reg_required_here (& mystr, 3);
5977 inst.error = 0;
5978
5979 if (rm != FAIL)
5980 {
5981 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5982 inst.size = 2;
5983 }
5984 else
5985 {
5986 /* No ARM register. This must be BLX(1). Change the .instruction. */
5987 inst.instruction = 0xf7ffeffe;
5988 inst.size = 4;
5989
5990 if (my_get_expression (& inst.reloc.exp, & mystr))
5991 return;
5992
5993 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5994 inst.reloc.pc_rel = 1;
5995 }
5996
5997 end_of_line (mystr);
5998}
5999
6000/* ARM V5 breakpoint instruction (argument parse)
6001 BKPT <16 bit unsigned immediate>
6002 Instruction is not conditional.
6003 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 6004 and it is an error if the caller tried to override that. */
b99bd4ef
NC
6005
6006static void
f2b7cb0a 6007do_bkpt (str)
b99bd4ef 6008 char * str;
b99bd4ef
NC
6009{
6010 expressionS expr;
6011 unsigned long number;
6012
6013 skip_whitespace (str);
6014
6015 /* Allow optional leading '#'. */
6016 if (is_immediate_prefix (* str))
6017 str++;
6018
6019 memset (& expr, '\0', sizeof (expr));
6020
143c8e19
NC
6021 if (my_get_expression (& expr, & str)
6022 || (expr.X_op != O_constant
6023 /* As a convenience we allow 'bkpt' without an operand. */
6024 && expr.X_op != O_absent))
b99bd4ef 6025 {
143c8e19 6026 inst.error = _("bad expression");
b99bd4ef
NC
6027 return;
6028 }
6029
6030 number = expr.X_add_number;
6031
6032 /* Check it fits a 16 bit unsigned. */
6033 if (number != (number & 0xffff))
6034 {
6035 inst.error = _("immediate value out of range");
6036 return;
6037 }
6038
6039 /* Top 12 of 16 bits to bits 19:8. */
6040 inst.instruction |= (number & 0xfff0) << 4;
6041
6042 /* Bottom 4 of 16 bits to bits 3:0. */
6043 inst.instruction |= number & 0xf;
6044
6045 end_of_line (str);
b99bd4ef
NC
6046}
6047
09d92015
MM
6048/* THUMB CPS instruction (argument parse). */
6049
6050static void
6051do_t_cps (str)
6052 char *str;
6053{
6054 do_cps_flags (&str, /*thumb_p=*/1);
6055 end_of_line (str);
6056}
6057
6058/* THUMB CPY instruction (argument parse). */
6059
6060static void
6061do_t_cpy (str)
6062 char *str;
6063{
6064 thumb_mov_compare (str, THUMB_CPY);
6065}
6066
6067/* THUMB SETEND instruction (argument parse). */
6068
6069static void
6070do_t_setend (str)
6071 char *str;
6072{
6073 if (do_endian_specifier (str))
6074 inst.instruction |= 0x8;
6075}
6076
e16bb312
NC
6077static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6078
6079/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6080
6081static unsigned long
6082check_iwmmxt_insn (str, insn_type, immediate_size)
6083 char * str;
6084 enum iwmmxt_insn_type insn_type;
6085 int immediate_size;
6086{
6087 int reg = 0;
6088 const char * inst_error;
6089 expressionS expr;
6090 unsigned long number;
6091
6092 inst_error = inst.error;
6093 if (!inst.error)
6094 inst.error = BAD_ARGS;
6095 skip_whitespace (str);
6096
6097 switch (insn_type)
6098 {
6099 case check_rd:
6100 if ((reg = reg_required_here (&str, 12)) == FAIL)
6101 return FAIL;
6102 break;
6103
6104 case check_wr:
6105 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6106 return FAIL;
6107 break;
6108
6109 case check_wrwr:
6110 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6111 || skip_past_comma (&str) == FAIL
6112 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6113 return FAIL;
6114 break;
6115
6116 case check_wrwrwr:
6117 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6118 || skip_past_comma (&str) == FAIL
6119 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6120 || skip_past_comma (&str) == FAIL
6121 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6122 return FAIL;
6123 break;
6124
6125 case check_wrwrwcg:
6126 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6127 || skip_past_comma (&str) == FAIL
6128 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6129 || skip_past_comma (&str) == FAIL
6130 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6131 return FAIL;
6132 break;
6133
6134 case check_tbcst:
6135 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6136 || skip_past_comma (&str) == FAIL
6137 || reg_required_here (&str, 12) == FAIL))
6138 return FAIL;
6139 break;
6140
6141 case check_tmovmsk:
6142 if ((reg_required_here (&str, 12) == FAIL
6143 || skip_past_comma (&str) == FAIL
6144 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6145 return FAIL;
6146 break;
6147
6148 case check_tmia:
6149 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6150 || skip_past_comma (&str) == FAIL
6151 || reg_required_here (&str, 0) == FAIL
6152 || skip_past_comma (&str) == FAIL
6153 || reg_required_here (&str, 12) == FAIL))
6154 return FAIL;
6155 break;
6156
6157 case check_tmcrr:
6158 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6159 || skip_past_comma (&str) == FAIL
6160 || reg_required_here (&str, 12) == FAIL
6161 || skip_past_comma (&str) == FAIL
6162 || reg_required_here (&str, 16) == FAIL))
6163 return FAIL;
6164 break;
6165
6166 case check_tmrrc:
6167 if ((reg_required_here (&str, 12) == FAIL
6168 || skip_past_comma (&str) == FAIL
6169 || reg_required_here (&str, 16) == FAIL
6170 || skip_past_comma (&str) == FAIL
6171 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6172 return FAIL;
6173 break;
6174
6175 case check_tmcr:
6176 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6177 || skip_past_comma (&str) == FAIL
6178 || reg_required_here (&str, 12) == FAIL))
6179 return FAIL;
6180 break;
6181
6182 case check_tmrc:
6183 if ((reg_required_here (&str, 12) == FAIL
6184 || skip_past_comma (&str) == FAIL
6185 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6186 return FAIL;
6187 break;
6188
6189 case check_tinsr:
6190 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6191 || skip_past_comma (&str) == FAIL
6192 || reg_required_here (&str, 12) == FAIL
6193 || skip_past_comma (&str) == FAIL))
6194 return FAIL;
6195 break;
6196
6197 case check_textrc:
6198 if ((reg_required_here (&str, 12) == FAIL
6199 || skip_past_comma (&str) == FAIL))
6200 return FAIL;
6201 break;
6202
6203 case check_waligni:
6204 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6205 || skip_past_comma (&str) == FAIL
6206 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6207 || skip_past_comma (&str) == FAIL
6208 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6209 || skip_past_comma (&str) == FAIL))
6210 return FAIL;
6211 break;
6212
6213 case check_textrm:
6214 if ((reg_required_here (&str, 12) == FAIL
6215 || skip_past_comma (&str) == FAIL
6216 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6217 || skip_past_comma (&str) == FAIL))
6218 return FAIL;
6219 break;
6220
6221 case check_wshufh:
6222 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6223 || skip_past_comma (&str) == FAIL
6224 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6225 || skip_past_comma (&str) == FAIL))
6226 return FAIL;
6227 break;
6228 }
6229
6230 if (immediate_size == 0)
6231 {
6232 end_of_line (str);
6233 inst.error = inst_error;
6234 return reg;
6235 }
6236 else
6237 {
6238 skip_whitespace (str);
6239
6240 /* Allow optional leading '#'. */
6241 if (is_immediate_prefix (* str))
6242 str++;
6243
6244 memset (& expr, '\0', sizeof (expr));
6245
6246 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6247 {
6248 inst.error = _("bad or missing expression");
6249 return FAIL;
6250 }
6251
6252 number = expr.X_add_number;
6253
6254 if (number != (number & immediate_size))
6255 {
6256 inst.error = _("immediate value out of range");
6257 return FAIL;
6258 }
6259 end_of_line (str);
6260 inst.error = inst_error;
6261 return number;
6262 }
6263}
6264
6265static void
6266do_iwmmxt_byte_addr (str)
6267 char * str;
6268{
6269 int op = (inst.instruction & 0x300) >> 8;
6270 int reg;
6271
6272 inst.instruction &= ~0x300;
6273 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6274
6275 skip_whitespace (str);
6276
6277 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6278 || skip_past_comma (& str) == FAIL
6279 || cp_byte_address_required_here (&str) == FAIL)
6280 {
6281 if (! inst.error)
6282 inst.error = BAD_ARGS;
6283 }
6284 else
6285 end_of_line (str);
6286
6287 if (wc_register (reg))
6288 {
ece01a63 6289 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6290 inst.instruction |= 0xf0000100;
6291 inst.instruction &= ~0x00400000;
6292 }
6293}
6294
6295static void
6296do_iwmmxt_tandc (str)
6297 char * str;
6298{
6299 int reg;
6300
6301 reg = check_iwmmxt_insn (str, check_rd, 0);
6302
6303 if (reg != REG_PC && !inst.error)
6304 inst.error = _("only r15 allowed here");
e16bb312
NC
6305}
6306
6307static void
6308do_iwmmxt_tbcst (str)
6309 char * str;
6310{
6311 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6312}
6313
6314static void
6315do_iwmmxt_textrc (str)
6316 char * str;
6317{
6318 unsigned long number;
6319
6320 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6321 return;
6322
6323 inst.instruction |= number & 0x7;
e16bb312
NC
6324}
6325
6326static void
6327do_iwmmxt_textrm (str)
6328 char * str;
6329{
6330 unsigned long number;
6331
6332 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6333 return;
6334
6335 inst.instruction |= number & 0x7;
6336}
6337
6338static void
6339do_iwmmxt_tinsr (str)
6340 char * str;
6341{
6342 unsigned long number;
6343
6344 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6345 return;
6346
6347 inst.instruction |= number & 0x7;
e16bb312
NC
6348}
6349
6350static void
6351do_iwmmxt_tmcr (str)
6352 char * str;
6353{
6354 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6355}
6356
6357static void
6358do_iwmmxt_tmcrr (str)
6359 char * str;
6360{
6361 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6362}
6363
6364static void
6365do_iwmmxt_tmia (str)
6366 char * str;
6367{
6368 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6369}
6370
6371static void
6372do_iwmmxt_tmovmsk (str)
6373 char * str;
6374{
6375 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6376}
6377
6378static void
6379do_iwmmxt_tmrc (str)
6380 char * str;
6381{
6382 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6383}
6384
6385static void
6386do_iwmmxt_tmrrc (str)
6387 char * str;
6388{
6389 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6390}
6391
6392static void
6393do_iwmmxt_torc (str)
6394 char * str;
6395{
6396 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6397}
6398
6399static void
6400do_iwmmxt_waligni (str)
6401 char * str;
6402{
6403 unsigned long number;
6404
6405 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6406 return;
6407
6408 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6409}
6410
6411static void
6412do_iwmmxt_wmov (str)
6413 char * str;
6414{
6415 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6416 return;
6417
6418 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6419}
6420
6421static void
6422do_iwmmxt_word_addr (str)
6423 char * str;
6424{
6425 int op = (inst.instruction & 0x300) >> 8;
6426 int reg;
6427
6428 inst.instruction &= ~0x300;
6429 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6430
6431 skip_whitespace (str);
6432
6433 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6434 || skip_past_comma (& str) == FAIL
6435 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6436 {
6437 if (! inst.error)
6438 inst.error = BAD_ARGS;
6439 }
6440 else
6441 end_of_line (str);
6442
6443 if (wc_register (reg))
6444 {
ece01a63
ILT
6445 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6446 as_bad (_("conditional execution not supported with control register"));
6447 if (op != 2)
6448 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6449 inst.instruction |= 0xf0000100;
6450 inst.instruction &= ~0x00400000;
6451 }
6452}
6453
6454static void
6455do_iwmmxt_wrwr (str)
6456 char * str;
6457{
6458 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6459}
6460
6461static void
6462do_iwmmxt_wrwrwcg (str)
6463 char * str;
6464{
6465 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6466}
6467
6468static void
6469do_iwmmxt_wrwrwr (str)
6470 char * str;
6471{
6472 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6473}
6474
6475static void
6476do_iwmmxt_wshufh (str)
6477 char * str;
6478{
6479 unsigned long number;
6480
6481 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6482 return;
6483
6484 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6485}
6486
6487static void
6488do_iwmmxt_wzero (str)
6489 char * str;
6490{
6491 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6492 return;
6493
6494 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6495}
6496
b99bd4ef
NC
6497/* Xscale multiply-accumulate (argument parse)
6498 MIAcc acc0,Rm,Rs
6499 MIAPHcc acc0,Rm,Rs
6500 MIAxycc acc0,Rm,Rs. */
6501
6502static void
63e63b07 6503do_xsc_mia (str)
b99bd4ef 6504 char * str;
b99bd4ef
NC
6505{
6506 int rs;
6507 int rm;
6508
f2b7cb0a 6509 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6510 inst.error = ERR_NO_ACCUM;
6511
6512 else if (skip_past_comma (& str) == FAIL
6513 || (rm = reg_required_here (& str, 0)) == FAIL)
6514 inst.error = BAD_ARGS;
6515
6516 else if (skip_past_comma (& str) == FAIL
6517 || (rs = reg_required_here (& str, 12)) == FAIL)
6518 inst.error = BAD_ARGS;
6519
6520 /* inst.instruction has now been zapped with both rm and rs. */
6521 else if (rm == REG_PC || rs == REG_PC)
6522 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6523
6524 else
6525 end_of_line (str);
6526}
6527
6528/* Xscale move-accumulator-register (argument parse)
6529
6530 MARcc acc0,RdLo,RdHi. */
6531
6532static void
63e63b07 6533do_xsc_mar (str)
b99bd4ef 6534 char * str;
b99bd4ef
NC
6535{
6536 int rdlo, rdhi;
6537
f2b7cb0a 6538 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6539 inst.error = ERR_NO_ACCUM;
6540
6541 else if (skip_past_comma (& str) == FAIL
6542 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6543 inst.error = BAD_ARGS;
6544
6545 else if (skip_past_comma (& str) == FAIL
6546 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6547 inst.error = BAD_ARGS;
6548
6549 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6550 else if (rdlo == REG_PC || rdhi == REG_PC)
6551 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6552
6553 else
6554 end_of_line (str);
6555}
6556
6557/* Xscale move-register-accumulator (argument parse)
6558
6559 MRAcc RdLo,RdHi,acc0. */
6560
6561static void
63e63b07 6562do_xsc_mra (str)
b99bd4ef 6563 char * str;
b99bd4ef
NC
6564{
6565 int rdlo;
6566 int rdhi;
6567
b99bd4ef
NC
6568 skip_whitespace (str);
6569
6570 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6571 inst.error = BAD_ARGS;
6572
6573 else if (skip_past_comma (& str) == FAIL
6574 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6575 inst.error = BAD_ARGS;
6576
6577 else if (skip_past_comma (& str) == FAIL
6578 || accum0_required_here (& str) == FAIL)
6579 inst.error = ERR_NO_ACCUM;
6580
6581 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6582 else if (rdlo == rdhi)
6583 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6584
6585 else if (rdlo == REG_PC || rdhi == REG_PC)
6586 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6587 else
6588 end_of_line (str);
6589}
6590
c9b604bd 6591/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6592
6593 PLD <addr_mode>
6594
6595 Syntactically, like LDR with B=1, W=0, L=1. */
6596
6597static void
f2b7cb0a 6598do_pld (str)
b99bd4ef 6599 char * str;
b99bd4ef
NC
6600{
6601 int rd;
6602
b99bd4ef
NC
6603 skip_whitespace (str);
6604
6605 if (* str != '[')
6606 {
6607 inst.error = _("'[' expected after PLD mnemonic");
6608 return;
6609 }
6610
90e4755a 6611 ++str;
b99bd4ef
NC
6612 skip_whitespace (str);
6613
6614 if ((rd = reg_required_here (& str, 16)) == FAIL)
6615 return;
6616
6617 skip_whitespace (str);
6618
90e4755a 6619 if (*str == ']')
b99bd4ef
NC
6620 {
6621 /* [Rn], ... ? */
90e4755a 6622 ++str;
b99bd4ef
NC
6623 skip_whitespace (str);
6624
90e4755a
RE
6625 /* Post-indexed addressing is not allowed with PLD. */
6626 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6627 {
90e4755a
RE
6628 inst.error
6629 = _("post-indexed expression used in preload instruction");
6630 return;
b99bd4ef 6631 }
90e4755a 6632 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6633 {
6634 inst.error = _("writeback used in preload instruction");
90e4755a 6635 ++str;
b99bd4ef
NC
6636 }
6637 else /* [Rn] */
6638 inst.instruction |= INDEX_UP | PRE_INDEX;
6639 }
6640 else /* [Rn, ...] */
6641 {
6642 if (skip_past_comma (& str) == FAIL)
6643 {
6644 inst.error = _("pre-indexed expression expected");
6645 return;
6646 }
6647
90e4755a 6648 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6649 return;
6650
6651 skip_whitespace (str);
6652
6653 if (* str != ']')
6654 {
6655 inst.error = _("missing ]");
6656 return;
6657 }
6658
6659 ++ str;
6660 skip_whitespace (str);
6661
6662 if (* str == '!') /* [Rn]! */
6663 {
6664 inst.error = _("writeback used in preload instruction");
6665 ++ str;
6666 }
6667
6668 inst.instruction |= PRE_INDEX;
6669 }
6670
6671 end_of_line (str);
6672}
6673
c9b604bd 6674/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6675 Mode is like LDRH.
6676
6677 LDRccD R, mode
6678 STRccD R, mode. */
6679
6680static void
f2b7cb0a 6681do_ldrd (str)
b99bd4ef 6682 char * str;
b99bd4ef
NC
6683{
6684 int rd;
6685 int rn;
6686
b99bd4ef
NC
6687 skip_whitespace (str);
6688
6689 if ((rd = reg_required_here (& str, 12)) == FAIL)
6690 {
6691 inst.error = BAD_ARGS;
6692 return;
6693 }
6694
6695 if (skip_past_comma (& str) == FAIL
6696 || (rn = ld_mode_required_here (& str)) == FAIL)
6697 {
6698 if (!inst.error)
cc8a6dd0 6699 inst.error = BAD_ARGS;
b99bd4ef
NC
6700 return;
6701 }
6702
6703 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6704 if (rd & 1) /* Unpredictable result if Rd is odd. */
6705 {
f03698e6 6706 inst.error = _("destination register must be even");
b99bd4ef
NC
6707 return;
6708 }
6709
90e4755a 6710 if (rd == REG_LR)
b99bd4ef 6711 {
f2b7cb0a 6712 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6713 return;
6714 }
6715
6716 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6717 && ((inst.instruction & WRITE_BACK)
6718 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6719 as_warn (_("pre/post-indexing used when modified address register is destination"));
6720
90e4755a
RE
6721 /* For an index-register load, the index register must not overlap the
6722 destination (even if not write-back). */
6723 if ((inst.instruction & V4_STR_BIT) == 0
6724 && (inst.instruction & HWOFFSET_IMM) == 0)
6725 {
6726 int rm = inst.instruction & 0x0000000f;
6727
6728 if (rm == rd || (rm == rd + 1))
6729 as_warn (_("ldrd destination registers must not overlap index register"));
6730 }
6731
b99bd4ef
NC
6732 end_of_line (str);
6733}
6734
6735/* Returns the index into fp_values of a floating point number,
6736 or -1 if not in the table. */
6737
6738static int
6739my_get_float_expression (str)
6740 char ** str;
6741{
6742 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6743 char * save_in;
6744 expressionS exp;
6745 int i;
6746 int j;
6747
6748 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6749
6750 /* Look for a raw floating point number. */
6751 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6752 && is_end_of_line[(unsigned char) *save_in])
6753 {
6754 for (i = 0; i < NUM_FLOAT_VALS; i++)
6755 {
6756 for (j = 0; j < MAX_LITTLENUMS; j++)
6757 {
6758 if (words[j] != fp_values[i][j])
6759 break;
6760 }
6761
6762 if (j == MAX_LITTLENUMS)
6763 {
6764 *str = save_in;
6765 return i;
6766 }
6767 }
6768 }
6769
6770 /* Try and parse a more complex expression, this will probably fail
6771 unless the code uses a floating point prefix (eg "0f"). */
6772 save_in = input_line_pointer;
6773 input_line_pointer = *str;
6774 if (expression (&exp) == absolute_section
6775 && exp.X_op == O_big
6776 && exp.X_add_number < 0)
6777 {
6778 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6779 Ditto for 15. */
6780 if (gen_to_words (words, 5, (long) 15) == 0)
6781 {
6782 for (i = 0; i < NUM_FLOAT_VALS; i++)
6783 {
6784 for (j = 0; j < MAX_LITTLENUMS; j++)
6785 {
6786 if (words[j] != fp_values[i][j])
6787 break;
6788 }
6789
6790 if (j == MAX_LITTLENUMS)
6791 {
6792 *str = input_line_pointer;
6793 input_line_pointer = save_in;
6794 return i;
6795 }
6796 }
6797 }
6798 }
6799
6800 *str = input_line_pointer;
6801 input_line_pointer = save_in;
6802 return -1;
6803}
6804
b34976b6 6805/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6806
6807static int
6808walk_no_bignums (sp)
6809 symbolS * sp;
6810{
6811 if (symbol_get_value_expression (sp)->X_op == O_big)
6812 return 1;
6813
6814 if (symbol_get_value_expression (sp)->X_add_symbol)
6815 {
6816 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6817 || (symbol_get_value_expression (sp)->X_op_symbol
6818 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6819 }
6820
6821 return 0;
6822}
6823
f03698e6
RE
6824static int in_my_get_expression = 0;
6825
b99bd4ef
NC
6826static int
6827my_get_expression (ep, str)
6828 expressionS * ep;
6829 char ** str;
6830{
6831 char * save_in;
6832 segT seg;
6833
6834 save_in = input_line_pointer;
6835 input_line_pointer = *str;
f03698e6 6836 in_my_get_expression = 1;
b99bd4ef 6837 seg = expression (ep);
f03698e6
RE
6838 in_my_get_expression = 0;
6839
6840 if (ep->X_op == O_illegal)
6841 {
6842 /* We found a bad expression in md_operand(). */
6843 *str = input_line_pointer;
6844 input_line_pointer = save_in;
6845 return 1;
6846 }
b99bd4ef
NC
6847
6848#ifdef OBJ_AOUT
6849 if (seg != absolute_section
6850 && seg != text_section
6851 && seg != data_section
6852 && seg != bss_section
6853 && seg != undefined_section)
6854 {
6855 inst.error = _("bad_segment");
6856 *str = input_line_pointer;
6857 input_line_pointer = save_in;
6858 return 1;
6859 }
6860#endif
6861
6862 /* Get rid of any bignums now, so that we don't generate an error for which
6863 we can't establish a line number later on. Big numbers are never valid
6864 in instructions, which is where this routine is always called. */
6865 if (ep->X_op == O_big
6866 || (ep->X_add_symbol
6867 && (walk_no_bignums (ep->X_add_symbol)
6868 || (ep->X_op_symbol
6869 && walk_no_bignums (ep->X_op_symbol)))))
6870 {
f03698e6 6871 inst.error = _("invalid constant");
b99bd4ef
NC
6872 *str = input_line_pointer;
6873 input_line_pointer = save_in;
6874 return 1;
6875 }
6876
6877 *str = input_line_pointer;
6878 input_line_pointer = save_in;
6879 return 0;
6880}
6881
cc8a6dd0 6882/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6883 instruction in the error message. */
6884void
ce058b6c 6885md_operand (expr)
f03698e6
RE
6886 expressionS *expr;
6887{
6888 if (in_my_get_expression)
6889 {
6890 expr->X_op = O_illegal;
6891 if (inst.error == NULL)
6892 inst.error = _("bad expression");
6893 }
6894}
6895
09d92015 6896/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6897
6898static int
09d92015 6899decode_shift (str, kind)
b99bd4ef 6900 char ** str;
09d92015 6901 int kind;
b99bd4ef
NC
6902{
6903 const struct asm_shift_name * shift;
6904 char * p;
6905 char c;
6906
6907 skip_whitespace (* str);
6908
3882b010 6909 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6910 ;
6911
6912 if (p == * str)
6913 {
f03698e6 6914 inst.error = _("shift expression expected");
b99bd4ef
NC
6915 return FAIL;
6916 }
6917
6918 c = * p;
6919 * p = '\0';
6920 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6921 * p = c;
6922
6923 if (shift == NULL)
6924 {
f03698e6 6925 inst.error = _("shift expression expected");
b99bd4ef
NC
6926 return FAIL;
6927 }
6928
6929 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6930
09d92015
MM
6931 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6932 && shift->properties->index != SHIFT_LSL
6933 && shift->properties->index != SHIFT_ASR)
6934 {
6935 inst.error = _("'LSL' or 'ASR' required");
6936 return FAIL;
6937 }
6938 else if (kind == SHIFT_LSL_IMMEDIATE
6939 && shift->properties->index != SHIFT_LSL)
6940 {
6941 inst.error = _("'LSL' required");
6942 return FAIL;
6943 }
6944 else if (kind == SHIFT_ASR_IMMEDIATE
6945 && shift->properties->index != SHIFT_ASR)
6946 {
6947 inst.error = _("'ASR' required");
6948 return FAIL;
6949 }
6950
b99bd4ef
NC
6951 if (shift->properties->index == SHIFT_RRX)
6952 {
6953 * str = p;
6954 inst.instruction |= shift->properties->bit_field;
6955 return SUCCESS;
6956 }
6957
6958 skip_whitespace (p);
6959
09d92015 6960 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6961 {
6962 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6963 * str = p;
6964 return SUCCESS;
6965 }
6966 else if (! is_immediate_prefix (* p))
6967 {
09d92015 6968 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6969 ? _("shift requires register or #expression")
6970 : _("shift requires #expression"));
6971 * str = p;
6972 return FAIL;
6973 }
6974
6975 inst.error = NULL;
6976 p ++;
6977
6978 if (my_get_expression (& inst.reloc.exp, & p))
6979 return FAIL;
6980
6981 /* Validate some simple #expressions. */
6982 if (inst.reloc.exp.X_op == O_constant)
6983 {
6984 unsigned num = inst.reloc.exp.X_add_number;
6985
6986 /* Reject operations greater than 32. */
6987 if (num > 32
6988 /* Reject a shift of 0 unless the mode allows it. */
6989 || (num == 0 && shift->properties->allows_0 == 0)
6990 /* Reject a shift of 32 unless the mode allows it. */
6991 || (num == 32 && shift->properties->allows_32 == 0)
6992 )
6993 {
6994 /* As a special case we allow a shift of zero for
6995 modes that do not support it to be recoded as an
6996 logical shift left of zero (ie nothing). We warn
6997 about this though. */
6998 if (num == 0)
6999 {
f03698e6 7000 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
7001 shift = & shift_names[0];
7002 assert (shift->properties->index == SHIFT_LSL);
7003 }
7004 else
7005 {
f03698e6 7006 inst.error = _("invalid immediate shift");
b99bd4ef
NC
7007 return FAIL;
7008 }
7009 }
7010
7011 /* Shifts of 32 are encoded as 0, for those shifts that
7012 support it. */
7013 if (num == 32)
7014 num = 0;
7015
7016 inst.instruction |= (num << 7) | shift->properties->bit_field;
7017 }
7018 else
7019 {
7020 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7021 inst.reloc.pc_rel = 0;
7022 inst.instruction |= shift->properties->bit_field;
7023 }
7024
7025 * str = p;
7026 return SUCCESS;
7027}
7028
7029/* Do those data_ops which can take a negative immediate constant
2d2255b5 7030 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
7031 MOV <-> MVN
7032 AND <-> BIC
7033 ADC <-> SBC
7034 by inverting the second operand, and
7035 ADD <-> SUB
7036 CMP <-> CMN
7037 by negating the second operand. */
7038
7039static int
7040negate_data_op (instruction, value)
7041 unsigned long * instruction;
7042 unsigned long value;
7043{
7044 int op, new_inst;
7045 unsigned long negated, inverted;
7046
7047 negated = validate_immediate (-value);
7048 inverted = validate_immediate (~value);
7049
7050 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7051 switch (op)
7052 {
7053 /* First negates. */
7054 case OPCODE_SUB: /* ADD <-> SUB */
7055 new_inst = OPCODE_ADD;
7056 value = negated;
7057 break;
7058
7059 case OPCODE_ADD:
7060 new_inst = OPCODE_SUB;
7061 value = negated;
7062 break;
7063
7064 case OPCODE_CMP: /* CMP <-> CMN */
7065 new_inst = OPCODE_CMN;
7066 value = negated;
7067 break;
7068
7069 case OPCODE_CMN:
7070 new_inst = OPCODE_CMP;
7071 value = negated;
7072 break;
7073
7074 /* Now Inverted ops. */
7075 case OPCODE_MOV: /* MOV <-> MVN */
7076 new_inst = OPCODE_MVN;
7077 value = inverted;
7078 break;
7079
7080 case OPCODE_MVN:
7081 new_inst = OPCODE_MOV;
7082 value = inverted;
7083 break;
7084
7085 case OPCODE_AND: /* AND <-> BIC */
7086 new_inst = OPCODE_BIC;
7087 value = inverted;
7088 break;
7089
7090 case OPCODE_BIC:
7091 new_inst = OPCODE_AND;
7092 value = inverted;
7093 break;
7094
7095 case OPCODE_ADC: /* ADC <-> SBC */
7096 new_inst = OPCODE_SBC;
7097 value = inverted;
7098 break;
7099
7100 case OPCODE_SBC:
7101 new_inst = OPCODE_ADC;
7102 value = inverted;
7103 break;
7104
7105 /* We cannot do anything. */
7106 default:
7107 return FAIL;
7108 }
7109
7110 if (value == (unsigned) FAIL)
7111 return FAIL;
7112
7113 *instruction &= OPCODE_MASK;
7114 *instruction |= new_inst << DATA_OP_SHIFT;
7115 return value;
7116}
7117
7118static int
7119data_op2 (str)
7120 char ** str;
7121{
7122 int value;
7123 expressionS expr;
7124
7125 skip_whitespace (* str);
7126
7127 if (reg_required_here (str, 0) != FAIL)
7128 {
7129 if (skip_past_comma (str) == SUCCESS)
7130 /* Shift operation on register. */
7131 return decode_shift (str, NO_SHIFT_RESTRICT);
7132
7133 return SUCCESS;
7134 }
7135 else
7136 {
7137 /* Immediate expression. */
7138 if (is_immediate_prefix (**str))
7139 {
7140 (*str)++;
7141 inst.error = NULL;
7142
7143 if (my_get_expression (&inst.reloc.exp, str))
7144 return FAIL;
7145
7146 if (inst.reloc.exp.X_add_symbol)
7147 {
7148 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7149 inst.reloc.pc_rel = 0;
7150 }
7151 else
7152 {
7153 if (skip_past_comma (str) == SUCCESS)
7154 {
7155 /* #x, y -- ie explicit rotation by Y. */
7156 if (my_get_expression (&expr, str))
7157 return FAIL;
7158
7159 if (expr.X_op != O_constant)
7160 {
f03698e6 7161 inst.error = _("constant expression expected");
b99bd4ef
NC
7162 return FAIL;
7163 }
7164
7165 /* Rotate must be a multiple of 2. */
7166 if (((unsigned) expr.X_add_number) > 30
7167 || (expr.X_add_number & 1) != 0
7168 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7169 {
f03698e6 7170 inst.error = _("invalid constant");
b99bd4ef
NC
7171 return FAIL;
7172 }
7173 inst.instruction |= INST_IMMEDIATE;
7174 inst.instruction |= inst.reloc.exp.X_add_number;
7175 inst.instruction |= expr.X_add_number << 7;
7176 return SUCCESS;
7177 }
7178
7179 /* Implicit rotation, select a suitable one. */
7180 value = validate_immediate (inst.reloc.exp.X_add_number);
7181
7182 if (value == FAIL)
7183 {
7184 /* Can't be done. Perhaps the code reads something like
7185 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7186 if ((value = negate_data_op (&inst.instruction,
7187 inst.reloc.exp.X_add_number))
7188 == FAIL)
7189 {
f03698e6 7190 inst.error = _("invalid constant");
b99bd4ef
NC
7191 return FAIL;
7192 }
7193 }
7194
7195 inst.instruction |= value;
7196 }
7197
7198 inst.instruction |= INST_IMMEDIATE;
7199 return SUCCESS;
7200 }
7201
7202 (*str)++;
f03698e6 7203 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7204 return FAIL;
7205 }
7206}
7207
7208static int
7209fp_op2 (str)
7210 char ** str;
7211{
7212 skip_whitespace (* str);
7213
7214 if (fp_reg_required_here (str, 0) != FAIL)
7215 return SUCCESS;
7216 else
7217 {
7218 /* Immediate expression. */
7219 if (*((*str)++) == '#')
7220 {
7221 int i;
7222
7223 inst.error = NULL;
7224
7225 skip_whitespace (* str);
7226
7227 /* First try and match exact strings, this is to guarantee
7228 that some formats will work even for cross assembly. */
7229
7230 for (i = 0; fp_const[i]; i++)
7231 {
7232 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7233 {
7234 char *start = *str;
7235
7236 *str += strlen (fp_const[i]);
7237 if (is_end_of_line[(unsigned char) **str])
7238 {
7239 inst.instruction |= i + 8;
7240 return SUCCESS;
7241 }
7242 *str = start;
7243 }
7244 }
7245
7246 /* Just because we didn't get a match doesn't mean that the
7247 constant isn't valid, just that it is in a format that we
7248 don't automatically recognize. Try parsing it with
7249 the standard expression routines. */
7250 if ((i = my_get_float_expression (str)) >= 0)
7251 {
7252 inst.instruction |= i + 8;
7253 return SUCCESS;
7254 }
7255
f03698e6 7256 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7257 return FAIL;
7258 }
7259 inst.error =
f03698e6 7260 _("floating point register or immediate expression expected");
b99bd4ef
NC
7261 return FAIL;
7262 }
7263}
7264
7265static void
f2b7cb0a 7266do_arit (str)
b99bd4ef 7267 char * str;
b99bd4ef
NC
7268{
7269 skip_whitespace (str);
7270
7271 if (reg_required_here (&str, 12) == FAIL
7272 || skip_past_comma (&str) == FAIL
7273 || reg_required_here (&str, 16) == FAIL
7274 || skip_past_comma (&str) == FAIL
7275 || data_op2 (&str) == FAIL)
7276 {
7277 if (!inst.error)
7278 inst.error = BAD_ARGS;
7279 return;
7280 }
7281
b99bd4ef 7282 end_of_line (str);
b99bd4ef
NC
7283}
7284
7285static void
f2b7cb0a 7286do_adr (str)
b99bd4ef 7287 char * str;
b99bd4ef 7288{
90e4755a
RE
7289 /* This is a pseudo-op of the form "adr rd, label" to be converted
7290 into a relative address of the form "add rd, pc, #label-.-8". */
7291 skip_whitespace (str);
7292
7293 if (reg_required_here (&str, 12) == FAIL
7294 || skip_past_comma (&str) == FAIL
7295 || my_get_expression (&inst.reloc.exp, &str))
7296 {
7297 if (!inst.error)
7298 inst.error = BAD_ARGS;
7299 return;
7300 }
7301
7302 /* Frag hacking will turn this into a sub instruction if the offset turns
7303 out to be negative. */
7304 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 7305#ifndef TE_WINCE
90e4755a 7306 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 7307#endif
90e4755a
RE
7308 inst.reloc.pc_rel = 1;
7309
7310 end_of_line (str);
7311}
7312
7313static void
f2b7cb0a 7314do_adrl (str)
90e4755a 7315 char * str;
90e4755a
RE
7316{
7317 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7318 into a relative address of the form:
7319 add rd, pc, #low(label-.-8)"
7320 add rd, rd, #high(label-.-8)" */
7321
7322 skip_whitespace (str);
7323
7324 if (reg_required_here (&str, 12) == FAIL
7325 || skip_past_comma (&str) == FAIL
7326 || my_get_expression (&inst.reloc.exp, &str))
7327 {
7328 if (!inst.error)
7329 inst.error = BAD_ARGS;
7330
7331 return;
7332 }
7333
7334 end_of_line (str);
7335 /* Frag hacking will turn this into a sub instruction if the offset turns
7336 out to be negative. */
7337 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
250355db 7338#ifndef TE_WINCE
90e4755a 7339 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 7340#endif
90e4755a
RE
7341 inst.reloc.pc_rel = 1;
7342 inst.size = INSN_SIZE * 2;
90e4755a
RE
7343}
7344
7345static void
f2b7cb0a 7346do_cmp (str)
90e4755a 7347 char * str;
90e4755a
RE
7348{
7349 skip_whitespace (str);
7350
7351 if (reg_required_here (&str, 16) == FAIL)
7352 {
7353 if (!inst.error)
7354 inst.error = BAD_ARGS;
7355 return;
7356 }
7357
7358 if (skip_past_comma (&str) == FAIL
7359 || data_op2 (&str) == FAIL)
7360 {
7361 if (!inst.error)
7362 inst.error = BAD_ARGS;
7363 return;
7364 }
7365
90e4755a 7366 end_of_line (str);
90e4755a
RE
7367}
7368
7369static void
f2b7cb0a 7370do_mov (str)
90e4755a 7371 char * str;
90e4755a
RE
7372{
7373 skip_whitespace (str);
7374
7375 if (reg_required_here (&str, 12) == FAIL)
7376 {
7377 if (!inst.error)
7378 inst.error = BAD_ARGS;
7379 return;
7380 }
7381
7382 if (skip_past_comma (&str) == FAIL
7383 || data_op2 (&str) == FAIL)
7384 {
7385 if (!inst.error)
7386 inst.error = BAD_ARGS;
7387 return;
7388 }
7389
90e4755a 7390 end_of_line (str);
90e4755a
RE
7391}
7392
7393static int
7394ldst_extend (str)
7395 char ** str;
7396{
7397 int add = INDEX_UP;
7398
7399 switch (**str)
7400 {
7401 case '#':
7402 case '$':
7403 (*str)++;
7404 if (my_get_expression (& inst.reloc.exp, str))
7405 return FAIL;
7406
7407 if (inst.reloc.exp.X_op == O_constant)
7408 {
7409 int value = inst.reloc.exp.X_add_number;
7410
7411 if (value < -4095 || value > 4095)
7412 {
7413 inst.error = _("address offset too large");
7414 return FAIL;
7415 }
7416
7417 if (value < 0)
7418 {
7419 value = -value;
7420 add = 0;
7421 }
7422
7423 inst.instruction |= add | value;
7424 }
7425 else
7426 {
7427 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7428 inst.reloc.pc_rel = 0;
7429 }
7430 return SUCCESS;
7431
7432 case '-':
7433 add = 0;
7434 /* Fall through. */
7435
7436 case '+':
7437 (*str)++;
7438 /* Fall through. */
7439
7440 default:
7441 if (reg_required_here (str, 0) == FAIL)
7442 return FAIL;
7443
7444 inst.instruction |= add | OFFSET_REG;
7445 if (skip_past_comma (str) == SUCCESS)
09d92015 7446 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7447
7448 return SUCCESS;
7449 }
7450}
7451
7452static void
f2b7cb0a 7453do_ldst (str)
90e4755a 7454 char * str;
90e4755a
RE
7455{
7456 int pre_inc = 0;
7457 int conflict_reg;
7458 int value;
7459
b99bd4ef
NC
7460 skip_whitespace (str);
7461
90e4755a
RE
7462 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7463 {
7464 if (!inst.error)
7465 inst.error = BAD_ARGS;
7466 return;
7467 }
7468
7469 if (skip_past_comma (&str) == FAIL)
7470 {
f03698e6 7471 inst.error = _("address expected");
90e4755a
RE
7472 return;
7473 }
7474
90e4755a
RE
7475 if (*str == '[')
7476 {
7477 int reg;
7478
7479 str++;
7480
7481 skip_whitespace (str);
7482
7483 if ((reg = reg_required_here (&str, 16)) == FAIL)
7484 return;
7485
7486 /* Conflicts can occur on stores as well as loads. */
7487 conflict_reg = (conflict_reg == reg);
7488
7489 skip_whitespace (str);
7490
7491 if (*str == ']')
7492 {
7493 str ++;
7494
7495 if (skip_past_comma (&str) == SUCCESS)
7496 {
7497 /* [Rn],... (post inc) */
7498 if (ldst_extend (&str) == FAIL)
7499 return;
7500 if (conflict_reg)
7501 as_warn (_("%s register same as write-back base"),
7502 ((inst.instruction & LOAD_BIT)
7503 ? _("destination") : _("source")));
7504 }
7505 else
7506 {
7507 /* [Rn] */
7508 skip_whitespace (str);
7509
7510 if (*str == '!')
7511 {
7512 if (conflict_reg)
7513 as_warn (_("%s register same as write-back base"),
7514 ((inst.instruction & LOAD_BIT)
7515 ? _("destination") : _("source")));
7516 str++;
7517 inst.instruction |= WRITE_BACK;
7518 }
7519
7520 inst.instruction |= INDEX_UP;
7521 pre_inc = 1;
7522 }
7523 }
7524 else
7525 {
7526 /* [Rn,...] */
7527 if (skip_past_comma (&str) == FAIL)
7528 {
7529 inst.error = _("pre-indexed expression expected");
7530 return;
7531 }
7532
7533 pre_inc = 1;
7534 if (ldst_extend (&str) == FAIL)
7535 return;
7536
7537 skip_whitespace (str);
7538
7539 if (*str++ != ']')
7540 {
7541 inst.error = _("missing ]");
7542 return;
7543 }
7544
7545 skip_whitespace (str);
7546
7547 if (*str == '!')
7548 {
7549 if (conflict_reg)
7550 as_warn (_("%s register same as write-back base"),
7551 ((inst.instruction & LOAD_BIT)
7552 ? _("destination") : _("source")));
7553 str++;
7554 inst.instruction |= WRITE_BACK;
7555 }
7556 }
7557 }
7558 else if (*str == '=')
7559 {
f03698e6
RE
7560 if ((inst.instruction & LOAD_BIT) == 0)
7561 {
7562 inst.error = _("invalid pseudo operation");
7563 return;
7564 }
7565
90e4755a
RE
7566 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7567 str++;
7568
7569 skip_whitespace (str);
7570
7571 if (my_get_expression (&inst.reloc.exp, &str))
7572 return;
7573
7574 if (inst.reloc.exp.X_op != O_constant
7575 && inst.reloc.exp.X_op != O_symbol)
7576 {
f03698e6 7577 inst.error = _("constant expression expected");
90e4755a
RE
7578 return;
7579 }
7580
e28cd48c 7581 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7582 {
e28cd48c
RE
7583 value = validate_immediate (inst.reloc.exp.X_add_number);
7584
7585 if (value != FAIL)
90e4755a 7586 {
e28cd48c
RE
7587 /* This can be done with a mov instruction. */
7588 inst.instruction &= LITERAL_MASK;
7589 inst.instruction |= (INST_IMMEDIATE
7590 | (OPCODE_MOV << DATA_OP_SHIFT));
7591 inst.instruction |= value & 0xfff;
7592 end_of_line (str);
90e4755a
RE
7593 return;
7594 }
b99bd4ef 7595
e28cd48c
RE
7596 value = validate_immediate (~inst.reloc.exp.X_add_number);
7597
7598 if (value != FAIL)
7599 {
7600 /* This can be done with a mvn instruction. */
7601 inst.instruction &= LITERAL_MASK;
7602 inst.instruction |= (INST_IMMEDIATE
7603 | (OPCODE_MVN << DATA_OP_SHIFT));
7604 inst.instruction |= value & 0xfff;
7605 end_of_line (str);
7606 return;
7607 }
90e4755a 7608 }
e28cd48c
RE
7609
7610 /* Insert into literal pool. */
7611 if (add_to_lit_pool () == FAIL)
7612 {
7613 if (!inst.error)
7614 inst.error = _("literal pool insertion failed");
7615 return;
7616 }
7617
7618 /* Change the instruction exp to point to the pool. */
7619 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7620 inst.reloc.pc_rel = 1;
7621 inst.instruction |= (REG_PC << 16);
7622 pre_inc = 1;
1cac9012
NC
7623 }
7624 else
7625 {
90e4755a
RE
7626 if (my_get_expression (&inst.reloc.exp, &str))
7627 return;
7628
7629 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7630#ifndef TE_WINCE
7631 /* PC rel adjust. */
7632 inst.reloc.exp.X_add_number -= 8;
7633#endif
1cac9012 7634 inst.reloc.pc_rel = 1;
90e4755a
RE
7635 inst.instruction |= (REG_PC << 16);
7636 pre_inc = 1;
b99bd4ef
NC
7637 }
7638
90e4755a 7639 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7640 end_of_line (str);
b99bd4ef
NC
7641}
7642
7643static void
f2b7cb0a 7644do_ldstt (str)
90e4755a 7645 char * str;
b99bd4ef 7646{
90e4755a
RE
7647 int conflict_reg;
7648
b99bd4ef
NC
7649 skip_whitespace (str);
7650
90e4755a 7651 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7652 {
7653 if (!inst.error)
7654 inst.error = BAD_ARGS;
7655 return;
7656 }
7657
90e4755a 7658 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7659 {
f03698e6 7660 inst.error = _("address expected");
b99bd4ef
NC
7661 return;
7662 }
7663
90e4755a
RE
7664 if (*str == '[')
7665 {
7666 int reg;
b99bd4ef 7667
90e4755a 7668 str++;
b99bd4ef 7669
90e4755a 7670 skip_whitespace (str);
b99bd4ef 7671
90e4755a
RE
7672 if ((reg = reg_required_here (&str, 16)) == FAIL)
7673 return;
b99bd4ef 7674
90e4755a
RE
7675 /* ldrt/strt always use post-indexed addressing, so if the base is
7676 the same as Rd, we warn. */
7677 if (conflict_reg == reg)
7678 as_warn (_("%s register same as write-back base"),
7679 ((inst.instruction & LOAD_BIT)
7680 ? _("destination") : _("source")));
7681
7682 skip_whitespace (str);
7683
7684 if (*str == ']')
7685 {
7686 str ++;
7687
7688 if (skip_past_comma (&str) == SUCCESS)
7689 {
7690 /* [Rn],... (post inc) */
7691 if (ldst_extend (&str) == FAIL)
7692 return;
7693 }
7694 else
7695 {
7696 /* [Rn] */
7697 skip_whitespace (str);
7698
7699 /* Skip a write-back '!'. */
7700 if (*str == '!')
7701 str++;
7702
7703 inst.instruction |= INDEX_UP;
7704 }
7705 }
7706 else
7707 {
7708 inst.error = _("post-indexed expression expected");
7709 return;
7710 }
7711 }
7712 else
b99bd4ef 7713 {
90e4755a 7714 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7715 return;
7716 }
7717
b99bd4ef 7718 end_of_line (str);
b99bd4ef
NC
7719}
7720
7721static int
90e4755a 7722ldst_extend_v4 (str)
b99bd4ef 7723 char ** str;
b99bd4ef
NC
7724{
7725 int add = INDEX_UP;
7726
7727 switch (**str)
7728 {
7729 case '#':
7730 case '$':
7731 (*str)++;
7732 if (my_get_expression (& inst.reloc.exp, str))
7733 return FAIL;
7734
7735 if (inst.reloc.exp.X_op == O_constant)
7736 {
7737 int value = inst.reloc.exp.X_add_number;
7738
90e4755a 7739 if (value < -255 || value > 255)
b99bd4ef
NC
7740 {
7741 inst.error = _("address offset too large");
7742 return FAIL;
7743 }
7744
7745 if (value < 0)
7746 {
7747 value = -value;
7748 add = 0;
7749 }
7750
7751 /* Halfword and signextension instructions have the
7752 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7753 inst.instruction |= (add | HWOFFSET_IMM
7754 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7755 }
7756 else
7757 {
90e4755a
RE
7758 inst.instruction |= HWOFFSET_IMM;
7759 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7760 inst.reloc.pc_rel = 0;
7761 }
7762 return SUCCESS;
7763
7764 case '-':
7765 add = 0;
7766 /* Fall through. */
7767
7768 case '+':
7769 (*str)++;
7770 /* Fall through. */
7771
7772 default:
7773 if (reg_required_here (str, 0) == FAIL)
7774 return FAIL;
7775
90e4755a 7776 inst.instruction |= add;
b99bd4ef
NC
7777 return SUCCESS;
7778 }
7779}
7780
90e4755a 7781/* Halfword and signed-byte load/store operations. */
b99bd4ef 7782static void
f2b7cb0a 7783do_ldstv4 (str)
b99bd4ef 7784 char * str;
b99bd4ef 7785{
b99bd4ef
NC
7786 int pre_inc = 0;
7787 int conflict_reg;
7788 int value;
7789
b99bd4ef
NC
7790 skip_whitespace (str);
7791
7792 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7793 {
7794 if (!inst.error)
7795 inst.error = BAD_ARGS;
7796 return;
7797 }
7798
7799 if (skip_past_comma (& str) == FAIL)
7800 {
f03698e6 7801 inst.error = _("address expected");
b99bd4ef
NC
7802 return;
7803 }
7804
7805 if (*str == '[')
7806 {
7807 int reg;
7808
7809 str++;
7810
7811 skip_whitespace (str);
7812
7813 if ((reg = reg_required_here (&str, 16)) == FAIL)
7814 return;
7815
7816 /* Conflicts can occur on stores as well as loads. */
7817 conflict_reg = (conflict_reg == reg);
7818
7819 skip_whitespace (str);
7820
7821 if (*str == ']')
7822 {
7823 str ++;
7824
7825 if (skip_past_comma (&str) == SUCCESS)
7826 {
7827 /* [Rn],... (post inc) */
90e4755a 7828 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7829 return;
7830 if (conflict_reg)
90e4755a
RE
7831 as_warn (_("%s register same as write-back base"),
7832 ((inst.instruction & LOAD_BIT)
7833 ? _("destination") : _("source")));
b99bd4ef
NC
7834 }
7835 else
7836 {
7837 /* [Rn] */
90e4755a 7838 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7839
7840 skip_whitespace (str);
7841
7842 if (*str == '!')
7843 {
7844 if (conflict_reg)
7845 as_warn (_("%s register same as write-back base"),
7846 ((inst.instruction & LOAD_BIT)
7847 ? _("destination") : _("source")));
7848 str++;
7849 inst.instruction |= WRITE_BACK;
7850 }
7851
90e4755a
RE
7852 inst.instruction |= INDEX_UP;
7853 pre_inc = 1;
b99bd4ef
NC
7854 }
7855 }
7856 else
7857 {
7858 /* [Rn,...] */
7859 if (skip_past_comma (&str) == FAIL)
7860 {
7861 inst.error = _("pre-indexed expression expected");
7862 return;
7863 }
7864
7865 pre_inc = 1;
90e4755a 7866 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7867 return;
7868
7869 skip_whitespace (str);
7870
7871 if (*str++ != ']')
7872 {
7873 inst.error = _("missing ]");
7874 return;
7875 }
7876
7877 skip_whitespace (str);
7878
7879 if (*str == '!')
7880 {
7881 if (conflict_reg)
7882 as_warn (_("%s register same as write-back base"),
7883 ((inst.instruction & LOAD_BIT)
7884 ? _("destination") : _("source")));
7885 str++;
7886 inst.instruction |= WRITE_BACK;
7887 }
7888 }
7889 }
7890 else if (*str == '=')
7891 {
f03698e6
RE
7892 if ((inst.instruction & LOAD_BIT) == 0)
7893 {
7894 inst.error = _("invalid pseudo operation");
7895 return;
7896 }
7897
90e4755a 7898 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7899 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7900 str++;
7901
7902 skip_whitespace (str);
7903
7904 if (my_get_expression (&inst.reloc.exp, &str))
7905 return;
7906
7907 if (inst.reloc.exp.X_op != O_constant
7908 && inst.reloc.exp.X_op != O_symbol)
7909 {
f03698e6 7910 inst.error = _("constant expression expected");
b99bd4ef
NC
7911 return;
7912 }
7913
d8273442 7914 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7915 {
d8273442
NC
7916 value = validate_immediate (inst.reloc.exp.X_add_number);
7917
7918 if (value != FAIL)
b99bd4ef 7919 {
d8273442
NC
7920 /* This can be done with a mov instruction. */
7921 inst.instruction &= LITERAL_MASK;
7922 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7923 inst.instruction |= value & 0xfff;
d8273442 7924 end_of_line (str);
b99bd4ef
NC
7925 return;
7926 }
cc8a6dd0 7927
d8273442 7928 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7929
d8273442 7930 if (value != FAIL)
b99bd4ef 7931 {
d8273442
NC
7932 /* This can be done with a mvn instruction. */
7933 inst.instruction &= LITERAL_MASK;
7934 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7935 inst.instruction |= value & 0xfff;
d8273442
NC
7936 end_of_line (str);
7937 return;
b99bd4ef 7938 }
b99bd4ef 7939 }
d8273442
NC
7940
7941 /* Insert into literal pool. */
7942 if (add_to_lit_pool () == FAIL)
7943 {
7944 if (!inst.error)
7945 inst.error = _("literal pool insertion failed");
7946 return;
7947 }
7948
7949 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7950 inst.instruction |= HWOFFSET_IMM;
7951 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7952 inst.reloc.pc_rel = 1;
7953 inst.instruction |= (REG_PC << 16);
7954 pre_inc = 1;
b99bd4ef
NC
7955 }
7956 else
7957 {
7958 if (my_get_expression (&inst.reloc.exp, &str))
7959 return;
7960
90e4755a
RE
7961 inst.instruction |= HWOFFSET_IMM;
7962 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7963#ifndef TE_WINCE
7964 /* PC rel adjust. */
7965 inst.reloc.exp.X_add_number -= 8;
7966#endif
7967 inst.reloc.pc_rel = 1;
7968 inst.instruction |= (REG_PC << 16);
7969 pre_inc = 1;
7970 }
7971
90e4755a 7972 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7973 end_of_line (str);
b99bd4ef
NC
7974}
7975
7976static long
7977reg_list (strp)
7978 char ** strp;
7979{
7980 char * str = * strp;
7981 long range = 0;
7982 int another_range;
7983
7984 /* We come back here if we get ranges concatenated by '+' or '|'. */
7985 do
7986 {
7987 another_range = 0;
7988
7989 if (*str == '{')
7990 {
7991 int in_range = 0;
7992 int cur_reg = -1;
7993
7994 str++;
7995 do
7996 {
7997 int reg;
7998
7999 skip_whitespace (str);
8000
8001 if ((reg = reg_required_here (& str, -1)) == FAIL)
8002 return FAIL;
8003
8004 if (in_range)
8005 {
8006 int i;
8007
8008 if (reg <= cur_reg)
8009 {
f03698e6 8010 inst.error = _("bad range in register list");
b99bd4ef
NC
8011 return FAIL;
8012 }
8013
8014 for (i = cur_reg + 1; i < reg; i++)
8015 {
8016 if (range & (1 << i))
8017 as_tsktsk
f03698e6 8018 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8019 i);
8020 else
8021 range |= 1 << i;
8022 }
8023 in_range = 0;
8024 }
8025
8026 if (range & (1 << reg))
f03698e6 8027 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8028 reg);
8029 else if (reg <= cur_reg)
f03698e6 8030 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
8031
8032 range |= 1 << reg;
8033 cur_reg = reg;
8034 }
8035 while (skip_past_comma (&str) != FAIL
8036 || (in_range = 1, *str++ == '-'));
8037 str--;
8038 skip_whitespace (str);
8039
8040 if (*str++ != '}')
8041 {
f03698e6 8042 inst.error = _("missing `}'");
b99bd4ef
NC
8043 return FAIL;
8044 }
8045 }
8046 else
8047 {
8048 expressionS expr;
8049
8050 if (my_get_expression (&expr, &str))
8051 return FAIL;
8052
8053 if (expr.X_op == O_constant)
8054 {
8055 if (expr.X_add_number
8056 != (expr.X_add_number & 0x0000ffff))
8057 {
8058 inst.error = _("invalid register mask");
8059 return FAIL;
8060 }
8061
8062 if ((range & expr.X_add_number) != 0)
8063 {
8064 int regno = range & expr.X_add_number;
8065
8066 regno &= -regno;
8067 regno = (1 << regno) - 1;
8068 as_tsktsk
f03698e6 8069 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8070 regno);
8071 }
8072
8073 range |= expr.X_add_number;
8074 }
8075 else
8076 {
8077 if (inst.reloc.type != 0)
8078 {
8079 inst.error = _("expression too complex");
8080 return FAIL;
8081 }
8082
8083 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8084 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8085 inst.reloc.pc_rel = 0;
8086 }
8087 }
8088
8089 skip_whitespace (str);
8090
8091 if (*str == '|' || *str == '+')
8092 {
8093 str++;
8094 another_range = 1;
8095 }
8096 }
8097 while (another_range);
8098
8099 *strp = str;
8100 return range;
8101}
8102
8103static void
f2b7cb0a 8104do_ldmstm (str)
b99bd4ef 8105 char * str;
b99bd4ef
NC
8106{
8107 int base_reg;
8108 long range;
8109
8110 skip_whitespace (str);
8111
8112 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8113 return;
8114
8115 if (base_reg == REG_PC)
8116 {
8117 inst.error = _("r15 not allowed as base register");
8118 return;
8119 }
8120
8121 skip_whitespace (str);
8122
8123 if (*str == '!')
8124 {
90e4755a 8125 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8126 str++;
8127 }
8128
8129 if (skip_past_comma (&str) == FAIL
8130 || (range = reg_list (&str)) == FAIL)
8131 {
8132 if (! inst.error)
8133 inst.error = BAD_ARGS;
8134 return;
8135 }
8136
8137 if (*str == '^')
8138 {
8139 str++;
90e4755a 8140 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8141 }
8142
6189168b
NC
8143 if (inst.instruction & WRITE_BACK)
8144 {
8145 /* Check for unpredictable uses of writeback. */
8146 if (inst.instruction & LOAD_BIT)
8147 {
8148 /* Not allowed in LDM type 2. */
8149 if ((inst.instruction & LDM_TYPE_2_OR_3)
8150 && ((range & (1 << REG_PC)) == 0))
8151 as_warn (_("writeback of base register is UNPREDICTABLE"));
8152 /* Only allowed if base reg not in list for other types. */
8153 else if (range & (1 << base_reg))
8154 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8155 }
8156 else /* STM. */
8157 {
8158 /* Not allowed for type 2. */
8159 if (inst.instruction & LDM_TYPE_2_OR_3)
8160 as_warn (_("writeback of base register is UNPREDICTABLE"));
8161 /* Only allowed if base reg not in list, or first in list. */
8162 else if ((range & (1 << base_reg))
8163 && (range & ((1 << base_reg) - 1)))
8164 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8165 }
8166 }
61b5f74b 8167
f2b7cb0a 8168 inst.instruction |= range;
b99bd4ef 8169 end_of_line (str);
b99bd4ef
NC
8170}
8171
8172static void
f2b7cb0a 8173do_swi (str)
b99bd4ef 8174 char * str;
b99bd4ef
NC
8175{
8176 skip_whitespace (str);
8177
8178 /* Allow optional leading '#'. */
8179 if (is_immediate_prefix (*str))
8180 str++;
8181
8182 if (my_get_expression (& inst.reloc.exp, & str))
8183 return;
8184
8185 inst.reloc.type = BFD_RELOC_ARM_SWI;
8186 inst.reloc.pc_rel = 0;
b99bd4ef 8187 end_of_line (str);
b99bd4ef
NC
8188}
8189
8190static void
f2b7cb0a 8191do_swap (str)
b99bd4ef 8192 char * str;
b99bd4ef
NC
8193{
8194 int reg;
8195
8196 skip_whitespace (str);
8197
8198 if ((reg = reg_required_here (&str, 12)) == FAIL)
8199 return;
8200
8201 if (reg == REG_PC)
8202 {
8203 inst.error = _("r15 not allowed in swap");
8204 return;
8205 }
8206
8207 if (skip_past_comma (&str) == FAIL
8208 || (reg = reg_required_here (&str, 0)) == FAIL)
8209 {
8210 if (!inst.error)
8211 inst.error = BAD_ARGS;
8212 return;
8213 }
8214
8215 if (reg == REG_PC)
8216 {
8217 inst.error = _("r15 not allowed in swap");
8218 return;
8219 }
8220
8221 if (skip_past_comma (&str) == FAIL
8222 || *str++ != '[')
8223 {
8224 inst.error = BAD_ARGS;
8225 return;
8226 }
8227
8228 skip_whitespace (str);
8229
8230 if ((reg = reg_required_here (&str, 16)) == FAIL)
8231 return;
8232
8233 if (reg == REG_PC)
8234 {
8235 inst.error = BAD_PC;
8236 return;
8237 }
8238
8239 skip_whitespace (str);
8240
8241 if (*str++ != ']')
8242 {
8243 inst.error = _("missing ]");
8244 return;
8245 }
8246
b99bd4ef 8247 end_of_line (str);
b99bd4ef
NC
8248}
8249
8250static void
f2b7cb0a 8251do_branch (str)
b99bd4ef 8252 char * str;
b99bd4ef
NC
8253{
8254 if (my_get_expression (&inst.reloc.exp, &str))
8255 return;
8256
8257#ifdef OBJ_ELF
8258 {
8259 char * save_in;
8260
8261 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8262 required for the instruction. */
8263
8264 /* arm_parse_reloc () works on input_line_pointer.
8265 We actually want to parse the operands to the branch instruction
8266 passed in 'str'. Save the input pointer and restore it later. */
8267 save_in = input_line_pointer;
8268 input_line_pointer = str;
8269 if (inst.reloc.exp.X_op == O_symbol
8270 && *str == '('
8271 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8272 {
8273 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8274 inst.reloc.pc_rel = 0;
8275 /* Modify str to point to after parsed operands, otherwise
8276 end_of_line() will complain about the (PLT) left in str. */
8277 str = input_line_pointer;
8278 }
8279 else
8280 {
8281 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8282 inst.reloc.pc_rel = 1;
8283 }
8284 input_line_pointer = save_in;
8285 }
8286#else
8287 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8288 inst.reloc.pc_rel = 1;
8289#endif /* OBJ_ELF */
8290
8291 end_of_line (str);
b99bd4ef
NC
8292}
8293
8294static void
f2b7cb0a 8295do_bx (str)
b99bd4ef 8296 char * str;
b99bd4ef
NC
8297{
8298 int reg;
8299
8300 skip_whitespace (str);
8301
8302 if ((reg = reg_required_here (&str, 0)) == FAIL)
8303 {
8304 inst.error = BAD_ARGS;
8305 return;
8306 }
8307
8308 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8309 if (reg == REG_PC)
f03698e6 8310 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8311
8312 end_of_line (str);
8313}
8314
8315static void
f2b7cb0a 8316do_cdp (str)
b99bd4ef 8317 char * str;
b99bd4ef
NC
8318{
8319 /* Co-processor data operation.
8320 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8321 skip_whitespace (str);
8322
8323 if (co_proc_number (&str) == FAIL)
8324 {
8325 if (!inst.error)
8326 inst.error = BAD_ARGS;
8327 return;
8328 }
8329
8330 if (skip_past_comma (&str) == FAIL
8331 || cp_opc_expr (&str, 20,4) == FAIL)
8332 {
8333 if (!inst.error)
8334 inst.error = BAD_ARGS;
8335 return;
8336 }
8337
8338 if (skip_past_comma (&str) == FAIL
8339 || cp_reg_required_here (&str, 12) == FAIL)
8340 {
8341 if (!inst.error)
8342 inst.error = BAD_ARGS;
8343 return;
8344 }
8345
8346 if (skip_past_comma (&str) == FAIL
8347 || cp_reg_required_here (&str, 16) == FAIL)
8348 {
8349 if (!inst.error)
8350 inst.error = BAD_ARGS;
8351 return;
8352 }
8353
8354 if (skip_past_comma (&str) == FAIL
8355 || cp_reg_required_here (&str, 0) == FAIL)
8356 {
8357 if (!inst.error)
8358 inst.error = BAD_ARGS;
8359 return;
8360 }
8361
8362 if (skip_past_comma (&str) == SUCCESS)
8363 {
8364 if (cp_opc_expr (&str, 5, 3) == FAIL)
8365 {
8366 if (!inst.error)
8367 inst.error = BAD_ARGS;
8368 return;
8369 }
8370 }
8371
8372 end_of_line (str);
b99bd4ef
NC
8373}
8374
8375static void
f2b7cb0a 8376do_lstc (str)
b99bd4ef 8377 char * str;
b99bd4ef
NC
8378{
8379 /* Co-processor register load/store.
8380 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8381
8382 skip_whitespace (str);
8383
8384 if (co_proc_number (&str) == FAIL)
8385 {
8386 if (!inst.error)
8387 inst.error = BAD_ARGS;
8388 return;
8389 }
8390
8391 if (skip_past_comma (&str) == FAIL
8392 || cp_reg_required_here (&str, 12) == FAIL)
8393 {
8394 if (!inst.error)
8395 inst.error = BAD_ARGS;
8396 return;
8397 }
8398
8399 if (skip_past_comma (&str) == FAIL
bfae80f2 8400 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8401 {
8402 if (! inst.error)
8403 inst.error = BAD_ARGS;
8404 return;
8405 }
8406
b99bd4ef 8407 end_of_line (str);
b99bd4ef
NC
8408}
8409
8410static void
f2b7cb0a 8411do_co_reg (str)
b99bd4ef 8412 char * str;
b99bd4ef
NC
8413{
8414 /* Co-processor register transfer.
8415 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8416
8417 skip_whitespace (str);
8418
8419 if (co_proc_number (&str) == FAIL)
8420 {
8421 if (!inst.error)
8422 inst.error = BAD_ARGS;
8423 return;
8424 }
8425
8426 if (skip_past_comma (&str) == FAIL
8427 || cp_opc_expr (&str, 21, 3) == FAIL)
8428 {
8429 if (!inst.error)
8430 inst.error = BAD_ARGS;
8431 return;
8432 }
8433
8434 if (skip_past_comma (&str) == FAIL
8435 || reg_required_here (&str, 12) == FAIL)
8436 {
8437 if (!inst.error)
8438 inst.error = BAD_ARGS;
8439 return;
8440 }
8441
8442 if (skip_past_comma (&str) == FAIL
8443 || cp_reg_required_here (&str, 16) == FAIL)
8444 {
8445 if (!inst.error)
8446 inst.error = BAD_ARGS;
8447 return;
8448 }
8449
8450 if (skip_past_comma (&str) == FAIL
8451 || cp_reg_required_here (&str, 0) == FAIL)
8452 {
8453 if (!inst.error)
8454 inst.error = BAD_ARGS;
8455 return;
8456 }
8457
8458 if (skip_past_comma (&str) == SUCCESS)
8459 {
8460 if (cp_opc_expr (&str, 5, 3) == FAIL)
8461 {
8462 if (!inst.error)
8463 inst.error = BAD_ARGS;
8464 return;
8465 }
8466 }
b99bd4ef
NC
8467
8468 end_of_line (str);
b99bd4ef
NC
8469}
8470
8471static void
f2b7cb0a 8472do_fpa_ctrl (str)
b99bd4ef 8473 char * str;
b99bd4ef
NC
8474{
8475 /* FP control registers.
8476 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8477
8478 skip_whitespace (str);
8479
8480 if (reg_required_here (&str, 12) == FAIL)
8481 {
8482 if (!inst.error)
8483 inst.error = BAD_ARGS;
8484 return;
8485 }
8486
8487 end_of_line (str);
b99bd4ef
NC
8488}
8489
8490static void
f2b7cb0a 8491do_fpa_ldst (str)
b99bd4ef 8492 char * str;
b99bd4ef
NC
8493{
8494 skip_whitespace (str);
8495
b99bd4ef
NC
8496 if (fp_reg_required_here (&str, 12) == FAIL)
8497 {
8498 if (!inst.error)
8499 inst.error = BAD_ARGS;
8500 return;
8501 }
8502
8503 if (skip_past_comma (&str) == FAIL
bfae80f2 8504 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8505 {
8506 if (!inst.error)
8507 inst.error = BAD_ARGS;
8508 return;
8509 }
8510
8511 end_of_line (str);
8512}
8513
8514static void
f2b7cb0a 8515do_fpa_ldmstm (str)
b99bd4ef 8516 char * str;
b99bd4ef
NC
8517{
8518 int num_regs;
8519
8520 skip_whitespace (str);
8521
8522 if (fp_reg_required_here (&str, 12) == FAIL)
8523 {
8524 if (! inst.error)
8525 inst.error = BAD_ARGS;
8526 return;
8527 }
8528
8529 /* Get Number of registers to transfer. */
8530 if (skip_past_comma (&str) == FAIL
8531 || my_get_expression (&inst.reloc.exp, &str))
8532 {
8533 if (! inst.error)
8534 inst.error = _("constant expression expected");
8535 return;
8536 }
8537
8538 if (inst.reloc.exp.X_op != O_constant)
8539 {
f03698e6 8540 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8541 return;
8542 }
8543
8544 num_regs = inst.reloc.exp.X_add_number;
8545
8546 if (num_regs < 1 || num_regs > 4)
8547 {
8548 inst.error = _("number of registers must be in the range [1:4]");
8549 return;
8550 }
8551
8552 switch (num_regs)
8553 {
8554 case 1:
8555 inst.instruction |= CP_T_X;
8556 break;
8557 case 2:
8558 inst.instruction |= CP_T_Y;
8559 break;
8560 case 3:
8561 inst.instruction |= CP_T_Y | CP_T_X;
8562 break;
8563 case 4:
8564 break;
8565 default:
8566 abort ();
8567 }
8568
e28cd48c 8569 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8570 {
8571 int reg;
8572 int write_back;
8573 int offset;
8574
8575 /* The instruction specified "ea" or "fd", so we can only accept
8576 [Rn]{!}. The instruction does not really support stacking or
8577 unstacking, so we have to emulate these by setting appropriate
8578 bits and offsets. */
8579 if (skip_past_comma (&str) == FAIL
8580 || *str != '[')
8581 {
8582 if (! inst.error)
8583 inst.error = BAD_ARGS;
8584 return;
8585 }
8586
8587 str++;
8588 skip_whitespace (str);
8589
8590 if ((reg = reg_required_here (&str, 16)) == FAIL)
8591 return;
8592
8593 skip_whitespace (str);
8594
8595 if (*str != ']')
8596 {
8597 inst.error = BAD_ARGS;
8598 return;
8599 }
8600
8601 str++;
8602 if (*str == '!')
8603 {
8604 write_back = 1;
8605 str++;
8606 if (reg == REG_PC)
8607 {
8608 inst.error =
f03698e6 8609 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8610 return;
8611 }
8612 }
8613 else
8614 write_back = 0;
8615
90e4755a 8616 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8617 {
8618 /* Pre-decrement. */
8619 offset = 3 * num_regs;
8620 if (write_back)
90e4755a 8621 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8622 }
8623 else
8624 {
8625 /* Post-increment. */
8626 if (write_back)
8627 {
90e4755a 8628 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8629 offset = 3 * num_regs;
8630 }
8631 else
8632 {
8633 /* No write-back, so convert this into a standard pre-increment
8634 instruction -- aesthetically more pleasing. */
90e4755a 8635 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8636 offset = 0;
8637 }
8638 }
8639
f2b7cb0a 8640 inst.instruction |= offset;
b99bd4ef
NC
8641 }
8642 else if (skip_past_comma (&str) == FAIL
bfae80f2 8643 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8644 {
8645 if (! inst.error)
8646 inst.error = BAD_ARGS;
8647 return;
8648 }
8649
8650 end_of_line (str);
8651}
8652
8653static void
f2b7cb0a 8654do_fpa_dyadic (str)
b99bd4ef 8655 char * str;
b99bd4ef
NC
8656{
8657 skip_whitespace (str);
8658
b99bd4ef
NC
8659 if (fp_reg_required_here (&str, 12) == FAIL)
8660 {
8661 if (! inst.error)
8662 inst.error = BAD_ARGS;
8663 return;
8664 }
8665
8666 if (skip_past_comma (&str) == FAIL
8667 || fp_reg_required_here (&str, 16) == FAIL)
8668 {
8669 if (! inst.error)
8670 inst.error = BAD_ARGS;
8671 return;
8672 }
8673
8674 if (skip_past_comma (&str) == FAIL
8675 || fp_op2 (&str) == FAIL)
8676 {
8677 if (! inst.error)
8678 inst.error = BAD_ARGS;
8679 return;
8680 }
8681
b99bd4ef 8682 end_of_line (str);
b99bd4ef
NC
8683}
8684
8685static void
f2b7cb0a 8686do_fpa_monadic (str)
b99bd4ef 8687 char * str;
b99bd4ef
NC
8688{
8689 skip_whitespace (str);
8690
b99bd4ef
NC
8691 if (fp_reg_required_here (&str, 12) == FAIL)
8692 {
8693 if (! inst.error)
8694 inst.error = BAD_ARGS;
8695 return;
8696 }
8697
8698 if (skip_past_comma (&str) == FAIL
8699 || fp_op2 (&str) == FAIL)
8700 {
8701 if (! inst.error)
8702 inst.error = BAD_ARGS;
8703 return;
8704 }
8705
b99bd4ef 8706 end_of_line (str);
b99bd4ef
NC
8707}
8708
8709static void
f2b7cb0a 8710do_fpa_cmp (str)
b99bd4ef 8711 char * str;
b99bd4ef
NC
8712{
8713 skip_whitespace (str);
8714
8715 if (fp_reg_required_here (&str, 16) == FAIL)
8716 {
8717 if (! inst.error)
8718 inst.error = BAD_ARGS;
8719 return;
8720 }
8721
8722 if (skip_past_comma (&str) == FAIL
8723 || fp_op2 (&str) == FAIL)
8724 {
8725 if (! inst.error)
8726 inst.error = BAD_ARGS;
8727 return;
8728 }
8729
b99bd4ef 8730 end_of_line (str);
b99bd4ef
NC
8731}
8732
8733static void
f2b7cb0a 8734do_fpa_from_reg (str)
b99bd4ef 8735 char * str;
b99bd4ef
NC
8736{
8737 skip_whitespace (str);
8738
b99bd4ef
NC
8739 if (fp_reg_required_here (&str, 16) == FAIL)
8740 {
8741 if (! inst.error)
8742 inst.error = BAD_ARGS;
8743 return;
8744 }
8745
8746 if (skip_past_comma (&str) == FAIL
8747 || reg_required_here (&str, 12) == FAIL)
8748 {
8749 if (! inst.error)
8750 inst.error = BAD_ARGS;
8751 return;
8752 }
8753
b99bd4ef 8754 end_of_line (str);
b99bd4ef
NC
8755}
8756
8757static void
f2b7cb0a 8758do_fpa_to_reg (str)
b99bd4ef 8759 char * str;
b99bd4ef
NC
8760{
8761 skip_whitespace (str);
8762
8763 if (reg_required_here (&str, 12) == FAIL)
8764 return;
8765
8766 if (skip_past_comma (&str) == FAIL
8767 || fp_reg_required_here (&str, 0) == FAIL)
8768 {
8769 if (! inst.error)
8770 inst.error = BAD_ARGS;
8771 return;
8772 }
8773
b99bd4ef 8774 end_of_line (str);
b99bd4ef
NC
8775}
8776
b99bd4ef 8777static int
bfae80f2
RE
8778vfp_sp_reg_required_here (str, pos)
8779 char **str;
8780 enum vfp_sp_reg_pos pos;
b99bd4ef 8781{
bfae80f2
RE
8782 int reg;
8783 char *start = *str;
b99bd4ef 8784
bfae80f2 8785 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8786 {
bfae80f2 8787 switch (pos)
b99bd4ef 8788 {
bfae80f2
RE
8789 case VFP_REG_Sd:
8790 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8791 break;
8792
8793 case VFP_REG_Sn:
8794 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8795 break;
8796
8797 case VFP_REG_Sm:
8798 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8799 break;
8800
8801 default:
8802 abort ();
b99bd4ef 8803 }
bfae80f2
RE
8804 return reg;
8805 }
b99bd4ef 8806
bfae80f2
RE
8807 /* In the few cases where we might be able to accept something else
8808 this error can be overridden. */
8809 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8810
8811 /* Restore the start point. */
8812 *str = start;
8813 return FAIL;
8814}
8815
8816static int
8817vfp_dp_reg_required_here (str, pos)
8818 char **str;
f201ccb3 8819 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8820{
8821 int reg;
8822 char *start = *str;
8823
8824 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8825 {
8826 switch (pos)
b99bd4ef 8827 {
bfae80f2
RE
8828 case VFP_REG_Dd:
8829 inst.instruction |= reg << 12;
8830 break;
b99bd4ef 8831
bfae80f2
RE
8832 case VFP_REG_Dn:
8833 inst.instruction |= reg << 16;
8834 break;
8835
8836 case VFP_REG_Dm:
8837 inst.instruction |= reg << 0;
8838 break;
8839
8840 default:
8841 abort ();
8842 }
8843 return reg;
b99bd4ef
NC
8844 }
8845
bfae80f2
RE
8846 /* In the few cases where we might be able to accept something else
8847 this error can be overridden. */
8848 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8849
bfae80f2
RE
8850 /* Restore the start point. */
8851 *str = start;
8852 return FAIL;
8853}
b99bd4ef
NC
8854
8855static void
bfae80f2
RE
8856do_vfp_sp_monadic (str)
8857 char *str;
b99bd4ef 8858{
b99bd4ef
NC
8859 skip_whitespace (str);
8860
bfae80f2
RE
8861 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8862 return;
8863
8864 if (skip_past_comma (&str) == FAIL
8865 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8866 {
8867 if (! inst.error)
8868 inst.error = BAD_ARGS;
8869 return;
8870 }
8871
bfae80f2 8872 end_of_line (str);
bfae80f2
RE
8873}
8874
8875static void
8876do_vfp_dp_monadic (str)
8877 char *str;
8878{
8879 skip_whitespace (str);
8880
8881 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8882 return;
8883
8884 if (skip_past_comma (&str) == FAIL
8885 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8886 {
bfae80f2
RE
8887 if (! inst.error)
8888 inst.error = BAD_ARGS;
8889 return;
b99bd4ef 8890 }
b99bd4ef 8891
bfae80f2 8892 end_of_line (str);
bfae80f2 8893}
b99bd4ef 8894
bfae80f2
RE
8895static void
8896do_vfp_sp_dyadic (str)
8897 char *str;
8898{
8899 skip_whitespace (str);
b99bd4ef 8900
bfae80f2
RE
8901 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8902 return;
b99bd4ef 8903
bfae80f2
RE
8904 if (skip_past_comma (&str) == FAIL
8905 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8906 || skip_past_comma (&str) == FAIL
8907 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8908 {
bfae80f2
RE
8909 if (! inst.error)
8910 inst.error = BAD_ARGS;
8911 return;
8912 }
b99bd4ef 8913
bfae80f2 8914 end_of_line (str);
bfae80f2 8915}
b99bd4ef 8916
bfae80f2
RE
8917static void
8918do_vfp_dp_dyadic (str)
8919 char *str;
8920{
8921 skip_whitespace (str);
b99bd4ef 8922
bfae80f2
RE
8923 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8924 return;
b99bd4ef 8925
bfae80f2
RE
8926 if (skip_past_comma (&str) == FAIL
8927 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8928 || skip_past_comma (&str) == FAIL
8929 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8930 {
8931 if (! inst.error)
8932 inst.error = BAD_ARGS;
8933 return;
8934 }
b99bd4ef 8935
bfae80f2 8936 end_of_line (str);
bfae80f2 8937}
b99bd4ef 8938
bfae80f2
RE
8939static void
8940do_vfp_reg_from_sp (str)
8941 char *str;
8942{
8943 skip_whitespace (str);
8944
8945 if (reg_required_here (&str, 12) == FAIL)
8946 return;
8947
8948 if (skip_past_comma (&str) == FAIL
8949 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8950 {
8951 if (! inst.error)
8952 inst.error = BAD_ARGS;
8953 return;
8954 }
8955
8956 end_of_line (str);
bfae80f2
RE
8957}
8958
8959static void
e45d0630 8960do_vfp_reg2_from_sp2 (str)
bfae80f2
RE
8961 char *str;
8962{
8963 skip_whitespace (str);
8964
e45d0630
PB
8965 if (reg_required_here (&str, 12) == FAIL
8966 || skip_past_comma (&str) == FAIL
bfae80f2
RE
8967 || reg_required_here (&str, 16) == FAIL
8968 || skip_past_comma (&str) == FAIL)
8969 {
8970 if (! inst.error)
8971 inst.error = BAD_ARGS;
8972 return;
8973 }
8974
8975 /* We require exactly two consecutive SP registers. */
8976 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8977 {
8978 if (! inst.error)
8979 inst.error = _("only two consecutive VFP SP registers allowed here");
8980 }
8981
8982 end_of_line (str);
bfae80f2
RE
8983}
8984
8985static void
8986do_vfp_sp_from_reg (str)
8987 char *str;
8988{
8989 skip_whitespace (str);
8990
8991 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8992 return;
8993
8994 if (skip_past_comma (&str) == FAIL
8995 || reg_required_here (&str, 12) == FAIL)
8996 {
8997 if (! inst.error)
8998 inst.error = BAD_ARGS;
8999 return;
9000 }
9001
9002 end_of_line (str);
bfae80f2
RE
9003}
9004
e45d0630
PB
9005static void
9006do_vfp_sp2_from_reg2 (str)
9007 char *str;
9008{
9009 skip_whitespace (str);
9010
9011 /* We require exactly two consecutive SP registers. */
9012 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9013 {
9014 if (! inst.error)
9015 inst.error = _("only two consecutive VFP SP registers allowed here");
9016 }
9017
9018 if (skip_past_comma (&str) == FAIL
9019 || reg_required_here (&str, 12) == FAIL
9020 || skip_past_comma (&str) == FAIL
9021 || reg_required_here (&str, 16) == FAIL)
9022 {
9023 if (! inst.error)
9024 inst.error = BAD_ARGS;
9025 return;
9026 }
9027
9028 end_of_line (str);
9029}
9030
bfae80f2
RE
9031static void
9032do_vfp_reg_from_dp (str)
9033 char *str;
9034{
9035 skip_whitespace (str);
9036
9037 if (reg_required_here (&str, 12) == FAIL)
9038 return;
9039
9040 if (skip_past_comma (&str) == FAIL
9041 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9042 {
9043 if (! inst.error)
9044 inst.error = BAD_ARGS;
9045 return;
9046 }
9047
9048 end_of_line (str);
bfae80f2
RE
9049}
9050
9051static void
9052do_vfp_reg2_from_dp (str)
9053 char *str;
9054{
9055 skip_whitespace (str);
9056
9057 if (reg_required_here (&str, 12) == FAIL)
9058 return;
9059
9060 if (skip_past_comma (&str) == FAIL
9061 || reg_required_here (&str, 16) == FAIL
9062 || skip_past_comma (&str) == FAIL
9063 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9064 {
9065 if (! inst.error)
9066 inst.error = BAD_ARGS;
9067 return;
9068 }
9069
9070 end_of_line (str);
bfae80f2
RE
9071}
9072
9073static void
9074do_vfp_dp_from_reg (str)
9075 char *str;
9076{
9077 skip_whitespace (str);
9078
9079 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9080 return;
9081
9082 if (skip_past_comma (&str) == FAIL
9083 || reg_required_here (&str, 12) == FAIL)
9084 {
9085 if (! inst.error)
9086 inst.error = BAD_ARGS;
9087 return;
9088 }
9089
9090 end_of_line (str);
bfae80f2
RE
9091}
9092
9093static void
9094do_vfp_dp_from_reg2 (str)
9095 char *str;
9096{
9097 skip_whitespace (str);
9098
9099 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9100 return;
9101
9102 if (skip_past_comma (&str) == FAIL
9103 || reg_required_here (&str, 12) == FAIL
9104 || skip_past_comma (&str) == FAIL
e45d0630 9105 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
9106 {
9107 if (! inst.error)
9108 inst.error = BAD_ARGS;
9109 return;
9110 }
9111
9112 end_of_line (str);
bfae80f2
RE
9113}
9114
9115static const struct vfp_reg *
9116vfp_psr_parse (str)
9117 char **str;
9118{
9119 char *start = *str;
9120 char c;
9121 char *p;
9122 const struct vfp_reg *vreg;
9123
9124 p = start;
9125
9126 /* Find the end of the current token. */
9127 do
9128 {
9129 c = *p++;
9130 }
9131 while (ISALPHA (c));
9132
9133 /* Mark it. */
9134 *--p = 0;
9135
cc8a6dd0 9136 for (vreg = vfp_regs + 0;
bfae80f2
RE
9137 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9138 vreg++)
9139 {
9140 if (strcmp (start, vreg->name) == 0)
9141 {
9142 *p = c;
9143 *str = p;
9144 return vreg;
9145 }
9146 }
9147
9148 *p = c;
9149 return NULL;
9150}
9151
9152static int
9153vfp_psr_required_here (str)
9154 char **str;
9155{
9156 char *start = *str;
9157 const struct vfp_reg *vreg;
9158
9159 vreg = vfp_psr_parse (str);
9160
9161 if (vreg)
9162 {
9163 inst.instruction |= vreg->regno;
9164 return SUCCESS;
9165 }
9166
9167 inst.error = _("VFP system register expected");
9168
9169 *str = start;
9170 return FAIL;
9171}
9172
9173static void
9174do_vfp_reg_from_ctrl (str)
9175 char *str;
9176{
9177 skip_whitespace (str);
9178
9179 if (reg_required_here (&str, 12) == FAIL)
9180 return;
9181
9182 if (skip_past_comma (&str) == FAIL
9183 || vfp_psr_required_here (&str) == FAIL)
9184 {
9185 if (! inst.error)
9186 inst.error = BAD_ARGS;
9187 return;
9188 }
9189
9190 end_of_line (str);
bfae80f2
RE
9191}
9192
9193static void
9194do_vfp_ctrl_from_reg (str)
9195 char *str;
9196{
9197 skip_whitespace (str);
9198
9199 if (vfp_psr_required_here (&str) == FAIL)
9200 return;
9201
9202 if (skip_past_comma (&str) == FAIL
9203 || reg_required_here (&str, 12) == FAIL)
9204 {
9205 if (! inst.error)
9206 inst.error = BAD_ARGS;
9207 return;
9208 }
9209
9210 end_of_line (str);
bfae80f2
RE
9211}
9212
9213static void
9214do_vfp_sp_ldst (str)
9215 char *str;
9216{
9217 skip_whitespace (str);
9218
9219 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9220 {
9221 if (!inst.error)
9222 inst.error = BAD_ARGS;
9223 return;
9224 }
9225
9226 if (skip_past_comma (&str) == FAIL
9227 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9228 {
9229 if (!inst.error)
9230 inst.error = BAD_ARGS;
9231 return;
9232 }
9233
9234 end_of_line (str);
bfae80f2
RE
9235}
9236
9237static void
9238do_vfp_dp_ldst (str)
9239 char *str;
9240{
9241 skip_whitespace (str);
9242
9243 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9244 {
9245 if (!inst.error)
9246 inst.error = BAD_ARGS;
9247 return;
9248 }
9249
9250 if (skip_past_comma (&str) == FAIL
9251 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9252 {
9253 if (!inst.error)
9254 inst.error = BAD_ARGS;
9255 return;
9256 }
9257
9258 end_of_line (str);
bfae80f2
RE
9259}
9260
9261/* Parse and encode a VFP SP register list, storing the initial
9262 register in position POS and returning the range as the result. If
9263 the string is invalid return FAIL (an invalid range). */
9264static long
9265vfp_sp_reg_list (str, pos)
9266 char **str;
9267 enum vfp_sp_reg_pos pos;
9268{
9269 long range = 0;
9270 int base_reg = 0;
9271 int new_base;
9272 long base_bits = 0;
9273 int count = 0;
9274 long tempinst;
9275 unsigned long mask = 0;
9276 int warned = 0;
9277
9278 if (**str != '{')
9279 return FAIL;
9280
9281 (*str)++;
9282 skip_whitespace (*str);
9283
9284 tempinst = inst.instruction;
9285
9286 do
9287 {
9288 inst.instruction = 0;
9289
9290 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9291 return FAIL;
9292
9293 if (count == 0 || base_reg > new_base)
9294 {
9295 base_reg = new_base;
9296 base_bits = inst.instruction;
9297 }
9298
9299 if (mask & (1 << new_base))
9300 {
9301 inst.error = _("invalid register list");
9302 return FAIL;
9303 }
9304
9305 if ((mask >> new_base) != 0 && ! warned)
9306 {
9307 as_tsktsk (_("register list not in ascending order"));
9308 warned = 1;
9309 }
9310
9311 mask |= 1 << new_base;
9312 count++;
9313
9314 skip_whitespace (*str);
9315
9316 if (**str == '-') /* We have the start of a range expression */
9317 {
9318 int high_range;
9319
9320 (*str)++;
9321
9322 if ((high_range
9323 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9324 == FAIL)
9325 {
9326 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9327 return FAIL;
9328 }
9329
9330 if (high_range <= new_base)
9331 {
9332 inst.error = _("register range not in ascending order");
9333 return FAIL;
9334 }
9335
9336 for (new_base++; new_base <= high_range; new_base++)
9337 {
9338 if (mask & (1 << new_base))
9339 {
9340 inst.error = _("invalid register list");
9341 return FAIL;
9342 }
9343
9344 mask |= 1 << new_base;
9345 count++;
9346 }
9347 }
9348 }
9349 while (skip_past_comma (str) != FAIL);
9350
9351 if (**str != '}')
9352 {
9353 inst.error = _("invalid register list");
9354 return FAIL;
9355 }
9356
9357 (*str)++;
9358
9359 range = count;
9360
9361 /* Sanity check -- should have raised a parse error above. */
9362 if (count == 0 || count > 32)
c62e1cc3 9363 abort ();
bfae80f2
RE
9364
9365 /* Final test -- the registers must be consecutive. */
9366 while (count--)
9367 {
9368 if ((mask & (1 << base_reg++)) == 0)
9369 {
9370 inst.error = _("non-contiguous register range");
9371 return FAIL;
9372 }
9373 }
9374
9375 inst.instruction = tempinst | base_bits;
9376 return range;
9377}
9378
9379static long
9380vfp_dp_reg_list (str)
9381 char **str;
9382{
9383 long range = 0;
9384 int base_reg = 0;
9385 int new_base;
9386 int count = 0;
9387 long tempinst;
9388 unsigned long mask = 0;
9389 int warned = 0;
9390
9391 if (**str != '{')
9392 return FAIL;
9393
9394 (*str)++;
9395 skip_whitespace (*str);
9396
9397 tempinst = inst.instruction;
9398
9399 do
9400 {
9401 inst.instruction = 0;
9402
9403 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9404 return FAIL;
9405
9406 if (count == 0 || base_reg > new_base)
9407 {
9408 base_reg = new_base;
9409 range = inst.instruction;
9410 }
9411
9412 if (mask & (1 << new_base))
9413 {
9414 inst.error = _("invalid register list");
9415 return FAIL;
9416 }
9417
9418 if ((mask >> new_base) != 0 && ! warned)
9419 {
9420 as_tsktsk (_("register list not in ascending order"));
9421 warned = 1;
9422 }
9423
9424 mask |= 1 << new_base;
9425 count++;
9426
9427 skip_whitespace (*str);
9428
9429 if (**str == '-') /* We have the start of a range expression */
9430 {
9431 int high_range;
9432
9433 (*str)++;
9434
9435 if ((high_range
9436 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9437 == FAIL)
9438 {
9439 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9440 return FAIL;
9441 }
9442
9443 if (high_range <= new_base)
9444 {
9445 inst.error = _("register range not in ascending order");
9446 return FAIL;
9447 }
9448
9449 for (new_base++; new_base <= high_range; new_base++)
9450 {
9451 if (mask & (1 << new_base))
9452 {
9453 inst.error = _("invalid register list");
9454 return FAIL;
9455 }
9456
9457 mask |= 1 << new_base;
9458 count++;
9459 }
9460 }
9461 }
9462 while (skip_past_comma (str) != FAIL);
9463
9464 if (**str != '}')
9465 {
9466 inst.error = _("invalid register list");
9467 return FAIL;
9468 }
9469
9470 (*str)++;
9471
9472 range |= 2 * count;
9473
9474 /* Sanity check -- should have raised a parse error above. */
9475 if (count == 0 || count > 16)
c62e1cc3 9476 abort ();
bfae80f2
RE
9477
9478 /* Final test -- the registers must be consecutive. */
9479 while (count--)
9480 {
9481 if ((mask & (1 << base_reg++)) == 0)
9482 {
9483 inst.error = _("non-contiguous register range");
9484 return FAIL;
9485 }
9486 }
9487
9488 inst.instruction = tempinst;
9489 return range;
9490}
9491
9492static void
c62e1cc3 9493vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9494 char *str;
9495 enum vfp_ldstm_type ldstm_type;
9496{
9497 long range;
9498
9499 skip_whitespace (str);
9500
9501 if (reg_required_here (&str, 16) == FAIL)
9502 return;
9503
9504 skip_whitespace (str);
9505
9506 if (*str == '!')
9507 {
9508 inst.instruction |= WRITE_BACK;
9509 str++;
9510 }
9511 else if (ldstm_type != VFP_LDSTMIA)
9512 {
9513 inst.error = _("this addressing mode requires base-register writeback");
9514 return;
9515 }
9516
9517 if (skip_past_comma (&str) == FAIL
9518 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9519 {
9520 if (!inst.error)
9521 inst.error = BAD_ARGS;
9522 return;
9523 }
9524
9525 inst.instruction |= range;
9526 end_of_line (str);
9527}
9528
9529static void
c62e1cc3 9530vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9531 char *str;
9532 enum vfp_ldstm_type ldstm_type;
9533{
9534 long range;
9535
9536 skip_whitespace (str);
9537
9538 if (reg_required_here (&str, 16) == FAIL)
9539 return;
9540
9541 skip_whitespace (str);
9542
9543 if (*str == '!')
9544 {
9545 inst.instruction |= WRITE_BACK;
9546 str++;
9547 }
9548 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9549 {
9550 inst.error = _("this addressing mode requires base-register writeback");
9551 return;
9552 }
9553
9554 if (skip_past_comma (&str) == FAIL
9555 || (range = vfp_dp_reg_list (&str)) == FAIL)
9556 {
9557 if (!inst.error)
9558 inst.error = BAD_ARGS;
9559 return;
9560 }
9561
9562 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9563 range += 1;
9564
9565 inst.instruction |= range;
9566 end_of_line (str);
9567}
9568
9569static void
9570do_vfp_sp_ldstmia (str)
9571 char *str;
9572{
9573 vfp_sp_ldstm (str, VFP_LDSTMIA);
9574}
9575
9576static void
9577do_vfp_sp_ldstmdb (str)
9578 char *str;
9579{
9580 vfp_sp_ldstm (str, VFP_LDSTMDB);
9581}
9582
9583static void
9584do_vfp_dp_ldstmia (str)
9585 char *str;
9586{
9587 vfp_dp_ldstm (str, VFP_LDSTMIA);
9588}
9589
9590static void
9591do_vfp_dp_ldstmdb (str)
9592 char *str;
9593{
9594 vfp_dp_ldstm (str, VFP_LDSTMDB);
9595}
9596
9597static void
9598do_vfp_xp_ldstmia (str)
9599 char *str;
9600{
9601 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9602}
9603
9604static void
9605do_vfp_xp_ldstmdb (str)
9606 char *str;
9607{
9608 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9609}
9610
9611static void
9612do_vfp_sp_compare_z (str)
9613 char *str;
9614{
9615 skip_whitespace (str);
9616
9617 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9618 {
9619 if (!inst.error)
9620 inst.error = BAD_ARGS;
9621 return;
9622 }
9623
9624 end_of_line (str);
bfae80f2
RE
9625}
9626
9627static void
9628do_vfp_dp_compare_z (str)
9629 char *str;
9630{
9631 skip_whitespace (str);
9632
9633 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9634 {
9635 if (!inst.error)
9636 inst.error = BAD_ARGS;
9637 return;
9638 }
9639
9640 end_of_line (str);
bfae80f2
RE
9641}
9642
9643static void
9644do_vfp_dp_sp_cvt (str)
9645 char *str;
9646{
9647 skip_whitespace (str);
9648
9649 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9650 return;
9651
9652 if (skip_past_comma (&str) == FAIL
9653 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9654 {
9655 if (! inst.error)
9656 inst.error = BAD_ARGS;
9657 return;
9658 }
9659
9660 end_of_line (str);
bfae80f2
RE
9661}
9662
9663static void
9664do_vfp_sp_dp_cvt (str)
9665 char *str;
9666{
9667 skip_whitespace (str);
9668
9669 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9670 return;
9671
9672 if (skip_past_comma (&str) == FAIL
9673 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9674 {
9675 if (! inst.error)
9676 inst.error = BAD_ARGS;
9677 return;
9678 }
9679
9680 end_of_line (str);
bfae80f2
RE
9681}
9682
9683/* Thumb specific routines. */
9684
9685/* Parse and validate that a register is of the right form, this saves
9686 repeated checking of this information in many similar cases.
9687 Unlike the 32-bit case we do not insert the register into the opcode
9688 here, since the position is often unknown until the full instruction
9689 has been parsed. */
9690
9691static int
9692thumb_reg (strp, hi_lo)
9693 char ** strp;
9694 int hi_lo;
9695{
9696 int reg;
9697
9698 if ((reg = reg_required_here (strp, -1)) == FAIL)
9699 return FAIL;
9700
9701 switch (hi_lo)
9702 {
9703 case THUMB_REG_LO:
9704 if (reg > 7)
9705 {
9706 inst.error = _("lo register required");
9707 return FAIL;
9708 }
9709 break;
9710
9711 case THUMB_REG_HI:
9712 if (reg < 8)
9713 {
9714 inst.error = _("hi register required");
9715 return FAIL;
9716 }
9717 break;
9718
9719 default:
9720 break;
9721 }
9722
9723 return reg;
9724}
9725
9726/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9727 was SUB. */
9728
9729static void
9730thumb_add_sub (str, subtract)
9731 char * str;
9732 int subtract;
9733{
9734 int Rd, Rs, Rn = FAIL;
9735
9736 skip_whitespace (str);
9737
9738 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9739 || skip_past_comma (&str) == FAIL)
9740 {
9741 if (! inst.error)
9742 inst.error = BAD_ARGS;
9743 return;
9744 }
9745
9746 if (is_immediate_prefix (*str))
9747 {
9748 Rs = Rd;
9749 str++;
9750 if (my_get_expression (&inst.reloc.exp, &str))
9751 return;
9752 }
9753 else
9754 {
9755 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9756 return;
9757
9758 if (skip_past_comma (&str) == FAIL)
9759 {
9760 /* Two operand format, shuffle the registers
9761 and pretend there are 3. */
9762 Rn = Rs;
9763 Rs = Rd;
9764 }
9765 else if (is_immediate_prefix (*str))
9766 {
9767 str++;
9768 if (my_get_expression (&inst.reloc.exp, &str))
9769 return;
9770 }
9771 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9772 return;
9773 }
9774
9775 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9776 for the latter case, EXPR contains the immediate that was found. */
9777 if (Rn != FAIL)
9778 {
9779 /* All register format. */
9780 if (Rd > 7 || Rs > 7 || Rn > 7)
9781 {
9782 if (Rs != Rd)
9783 {
9784 inst.error = _("dest and source1 must be the same register");
9785 return;
9786 }
9787
9788 /* Can't do this for SUB. */
9789 if (subtract)
9790 {
9791 inst.error = _("subtract valid only on lo regs");
9792 return;
9793 }
9794
9795 inst.instruction = (T_OPCODE_ADD_HI
9796 | (Rd > 7 ? THUMB_H1 : 0)
9797 | (Rn > 7 ? THUMB_H2 : 0));
9798 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9799 }
9800 else
9801 {
9802 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9803 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9804 }
9805 }
9806 else
9807 {
9808 /* Immediate expression, now things start to get nasty. */
9809
9810 /* First deal with HI regs, only very restricted cases allowed:
9811 Adjusting SP, and using PC or SP to get an address. */
9812 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9813 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9814 {
9815 inst.error = _("invalid Hi register with immediate");
9816 return;
9817 }
9818
9819 if (inst.reloc.exp.X_op != O_constant)
9820 {
9821 /* Value isn't known yet, all we can do is store all the fragments
9822 we know about in the instruction and let the reloc hacking
9823 work it all out. */
9824 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9825 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9826 }
9827 else
9828 {
9829 int offset = inst.reloc.exp.X_add_number;
9830
9831 if (subtract)
358b94bd 9832 offset = - offset;
bfae80f2
RE
9833
9834 if (offset < 0)
9835 {
358b94bd 9836 offset = - offset;
bfae80f2
RE
9837 subtract = 1;
9838
9839 /* Quick check, in case offset is MIN_INT. */
9840 if (offset < 0)
9841 {
9842 inst.error = _("immediate value out of range");
9843 return;
9844 }
9845 }
358b94bd
NC
9846 /* Note - you cannot convert a subtract of 0 into an
9847 add of 0 because the carry flag is set differently. */
9848 else if (offset > 0)
bfae80f2
RE
9849 subtract = 0;
9850
9851 if (Rd == REG_SP)
9852 {
9853 if (offset & ~0x1fc)
9854 {
9855 inst.error = _("invalid immediate value for stack adjust");
9856 return;
b99bd4ef
NC
9857 }
9858 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9859 inst.instruction |= offset >> 2;
9860 }
9861 else if (Rs == REG_PC || Rs == REG_SP)
9862 {
9863 if (subtract
9864 || (offset & ~0x3fc))
9865 {
9866 inst.error = _("invalid immediate for address calculation");
9867 return;
9868 }
9869 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9870 : T_OPCODE_ADD_SP);
9871 inst.instruction |= (Rd << 8) | (offset >> 2);
9872 }
9873 else if (Rs == Rd)
9874 {
9875 if (offset & ~0xff)
9876 {
9877 inst.error = _("immediate value out of range");
9878 return;
9879 }
9880 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9881 inst.instruction |= (Rd << 8) | offset;
9882 }
9883 else
9884 {
9885 if (offset & ~0x7)
9886 {
9887 inst.error = _("immediate value out of range");
9888 return;
9889 }
9890 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9891 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9892 }
9893 }
9894 }
9895
9896 end_of_line (str);
9897}
9898
9899static void
9900thumb_shift (str, shift)
9901 char * str;
9902 int shift;
9903{
9904 int Rd, Rs, Rn = FAIL;
9905
9906 skip_whitespace (str);
9907
9908 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9909 || skip_past_comma (&str) == FAIL)
9910 {
9911 if (! inst.error)
9912 inst.error = BAD_ARGS;
9913 return;
9914 }
9915
9916 if (is_immediate_prefix (*str))
9917 {
9918 /* Two operand immediate format, set Rs to Rd. */
9919 Rs = Rd;
9920 str ++;
9921 if (my_get_expression (&inst.reloc.exp, &str))
9922 return;
9923 }
9924 else
9925 {
9926 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9927 return;
9928
9929 if (skip_past_comma (&str) == FAIL)
9930 {
9931 /* Two operand format, shuffle the registers
9932 and pretend there are 3. */
9933 Rn = Rs;
9934 Rs = Rd;
9935 }
9936 else if (is_immediate_prefix (*str))
9937 {
9938 str++;
9939 if (my_get_expression (&inst.reloc.exp, &str))
9940 return;
9941 }
9942 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9943 return;
9944 }
9945
9946 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9947 for the latter case, EXPR contains the immediate that was found. */
9948
9949 if (Rn != FAIL)
9950 {
9951 if (Rs != Rd)
9952 {
9953 inst.error = _("source1 and dest must be same register");
9954 return;
9955 }
9956
9957 switch (shift)
9958 {
9959 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9960 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9961 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9962 }
9963
9964 inst.instruction |= Rd | (Rn << 3);
9965 }
9966 else
9967 {
9968 switch (shift)
9969 {
9970 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9971 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9972 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9973 }
9974
9975 if (inst.reloc.exp.X_op != O_constant)
9976 {
9977 /* Value isn't known yet, create a dummy reloc and let reloc
9978 hacking fix it up. */
9979 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9980 }
9981 else
9982 {
9983 unsigned shift_value = inst.reloc.exp.X_add_number;
9984
9985 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9986 {
f03698e6 9987 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9988 return;
9989 }
9990
9991 /* Shifts of zero are handled by converting to LSL. */
9992 if (shift_value == 0)
9993 inst.instruction = T_OPCODE_LSL_I;
9994
9995 /* Shifts of 32 are encoded as a shift of zero. */
9996 if (shift_value == 32)
9997 shift_value = 0;
9998
9999 inst.instruction |= shift_value << 6;
10000 }
10001
10002 inst.instruction |= Rd | (Rs << 3);
10003 }
10004
10005 end_of_line (str);
10006}
10007
10008static void
10009thumb_mov_compare (str, move)
10010 char * str;
10011 int move;
10012{
10013 int Rd, Rs = FAIL;
10014
10015 skip_whitespace (str);
10016
10017 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10018 || skip_past_comma (&str) == FAIL)
10019 {
10020 if (! inst.error)
10021 inst.error = BAD_ARGS;
10022 return;
10023 }
10024
09d92015 10025 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
10026 {
10027 str++;
10028 if (my_get_expression (&inst.reloc.exp, &str))
10029 return;
10030 }
10031 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10032 return;
10033
10034 if (Rs != FAIL)
10035 {
09d92015 10036 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
10037 {
10038 if (move == THUMB_MOVE)
10039 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10040 since a MOV instruction produces unpredictable results. */
10041 inst.instruction = T_OPCODE_ADD_I3;
10042 else
10043 inst.instruction = T_OPCODE_CMP_LR;
10044 inst.instruction |= Rd | (Rs << 3);
10045 }
10046 else
10047 {
10048 if (move == THUMB_MOVE)
10049 inst.instruction = T_OPCODE_MOV_HR;
09d92015 10050 else if (move != THUMB_CPY)
b99bd4ef
NC
10051 inst.instruction = T_OPCODE_CMP_HR;
10052
10053 if (Rd > 7)
10054 inst.instruction |= THUMB_H1;
10055
10056 if (Rs > 7)
10057 inst.instruction |= THUMB_H2;
10058
10059 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10060 }
10061 }
10062 else
10063 {
10064 if (Rd > 7)
10065 {
10066 inst.error = _("only lo regs allowed with immediate");
10067 return;
10068 }
10069
10070 if (move == THUMB_MOVE)
10071 inst.instruction = T_OPCODE_MOV_I8;
10072 else
10073 inst.instruction = T_OPCODE_CMP_I8;
10074
10075 inst.instruction |= Rd << 8;
10076
10077 if (inst.reloc.exp.X_op != O_constant)
10078 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10079 else
10080 {
10081 unsigned value = inst.reloc.exp.X_add_number;
10082
10083 if (value > 255)
10084 {
10085 inst.error = _("invalid immediate");
10086 return;
10087 }
10088
10089 inst.instruction |= value;
10090 }
10091 }
10092
10093 end_of_line (str);
10094}
10095
10096static void
10097thumb_load_store (str, load_store, size)
10098 char * str;
10099 int load_store;
10100 int size;
10101{
10102 int Rd, Rb, Ro = FAIL;
10103
10104 skip_whitespace (str);
10105
10106 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10107 || skip_past_comma (&str) == FAIL)
10108 {
10109 if (! inst.error)
10110 inst.error = BAD_ARGS;
10111 return;
10112 }
10113
10114 if (*str == '[')
10115 {
10116 str++;
10117 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10118 return;
10119
10120 if (skip_past_comma (&str) != FAIL)
10121 {
10122 if (is_immediate_prefix (*str))
10123 {
10124 str++;
10125 if (my_get_expression (&inst.reloc.exp, &str))
10126 return;
10127 }
10128 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10129 return;
10130 }
10131 else
10132 {
10133 inst.reloc.exp.X_op = O_constant;
10134 inst.reloc.exp.X_add_number = 0;
10135 }
10136
10137 if (*str != ']')
10138 {
10139 inst.error = _("expected ']'");
10140 return;
10141 }
10142 str++;
10143 }
10144 else if (*str == '=')
10145 {
f03698e6
RE
10146 if (load_store != THUMB_LOAD)
10147 {
10148 inst.error = _("invalid pseudo operation");
10149 return;
10150 }
10151
b99bd4ef
NC
10152 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10153 str++;
10154
10155 skip_whitespace (str);
10156
10157 if (my_get_expression (& inst.reloc.exp, & str))
10158 return;
10159
10160 end_of_line (str);
10161
10162 if ( inst.reloc.exp.X_op != O_constant
10163 && inst.reloc.exp.X_op != O_symbol)
10164 {
10165 inst.error = "Constant expression expected";
10166 return;
10167 }
10168
10169 if (inst.reloc.exp.X_op == O_constant
10170 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10171 {
10172 /* This can be done with a mov instruction. */
10173
10174 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10175 inst.instruction |= inst.reloc.exp.X_add_number;
10176 return;
10177 }
10178
10179 /* Insert into literal pool. */
10180 if (add_to_lit_pool () == FAIL)
10181 {
10182 if (!inst.error)
10183 inst.error = "literal pool insertion failed";
10184 return;
10185 }
10186
10187 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10188 inst.reloc.pc_rel = 1;
10189 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10190 /* Adjust ARM pipeline offset to Thumb. */
10191 inst.reloc.exp.X_add_number += 4;
10192
10193 return;
10194 }
10195 else
10196 {
10197 if (my_get_expression (&inst.reloc.exp, &str))
10198 return;
10199
10200 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10201 inst.reloc.pc_rel = 1;
10202 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10203 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10204 end_of_line (str);
10205 return;
10206 }
10207
10208 if (Rb == REG_PC || Rb == REG_SP)
10209 {
10210 if (size != THUMB_WORD)
10211 {
10212 inst.error = _("byte or halfword not valid for base register");
10213 return;
10214 }
10215 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10216 {
f03698e6 10217 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10218 return;
10219 }
10220 else if (Ro != FAIL)
10221 {
f03698e6 10222 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10223 return;
10224 }
10225
10226 if (Rb == REG_PC)
10227 inst.instruction = T_OPCODE_LDR_PC;
10228 else if (load_store == THUMB_LOAD)
10229 inst.instruction = T_OPCODE_LDR_SP;
10230 else
10231 inst.instruction = T_OPCODE_STR_SP;
10232
10233 inst.instruction |= Rd << 8;
10234 if (inst.reloc.exp.X_op == O_constant)
10235 {
10236 unsigned offset = inst.reloc.exp.X_add_number;
10237
10238 if (offset & ~0x3fc)
10239 {
10240 inst.error = _("invalid offset");
10241 return;
10242 }
10243
10244 inst.instruction |= offset >> 2;
10245 }
10246 else
10247 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10248 }
10249 else if (Rb > 7)
10250 {
10251 inst.error = _("invalid base register in load/store");
10252 return;
10253 }
10254 else if (Ro == FAIL)
10255 {
10256 /* Immediate offset. */
10257 if (size == THUMB_WORD)
10258 inst.instruction = (load_store == THUMB_LOAD
10259 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10260 else if (size == THUMB_HALFWORD)
10261 inst.instruction = (load_store == THUMB_LOAD
10262 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10263 else
10264 inst.instruction = (load_store == THUMB_LOAD
10265 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10266
10267 inst.instruction |= Rd | (Rb << 3);
10268
10269 if (inst.reloc.exp.X_op == O_constant)
10270 {
10271 unsigned offset = inst.reloc.exp.X_add_number;
10272
10273 if (offset & ~(0x1f << size))
10274 {
f03698e6 10275 inst.error = _("invalid offset");
b99bd4ef
NC
10276 return;
10277 }
10278 inst.instruction |= (offset >> size) << 6;
10279 }
10280 else
10281 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10282 }
10283 else
10284 {
10285 /* Register offset. */
10286 if (size == THUMB_WORD)
10287 inst.instruction = (load_store == THUMB_LOAD
10288 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10289 else if (size == THUMB_HALFWORD)
10290 inst.instruction = (load_store == THUMB_LOAD
10291 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10292 else
10293 inst.instruction = (load_store == THUMB_LOAD
10294 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10295
10296 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10297 }
10298
10299 end_of_line (str);
10300}
10301
404ff6b5
AH
10302/* A register must be given at this point.
10303
404ff6b5
AH
10304 Shift is the place to put it in inst.instruction.
10305
404ff6b5
AH
10306 Restores input start point on err.
10307 Returns the reg#, or FAIL. */
10308
10309static int
63e63b07 10310mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10311 char ** str;
10312 int shift;
6c43fab6 10313 enum arm_reg_type regtype;
404ff6b5 10314{
6c43fab6
RE
10315 int reg;
10316 char *start = *str;
404ff6b5 10317
6c43fab6 10318 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10319 {
404ff6b5
AH
10320 if (shift >= 0)
10321 inst.instruction |= reg << shift;
10322
6c43fab6 10323 return reg;
404ff6b5
AH
10324 }
10325
6c43fab6 10326 /* Restore the start point. */
404ff6b5 10327 *str = start;
cc8a6dd0 10328
404ff6b5
AH
10329 /* In the few cases where we might be able to accept something else
10330 this error can be overridden. */
6c43fab6 10331 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10332
404ff6b5
AH
10333 return FAIL;
10334}
10335
63e63b07 10336/* Cirrus Maverick Instructions. */
404ff6b5
AH
10337
10338/* Wrapper functions. */
10339
10340static void
63e63b07 10341do_mav_binops_1a (str)
6c43fab6
RE
10342 char * str;
10343{
63e63b07 10344 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10345}
10346
10347static void
63e63b07 10348do_mav_binops_1b (str)
6c43fab6
RE
10349 char * str;
10350{
63e63b07 10351 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10352}
10353
10354static void
63e63b07 10355do_mav_binops_1c (str)
404ff6b5 10356 char * str;
404ff6b5 10357{
63e63b07 10358 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10359}
10360
10361static void
63e63b07 10362do_mav_binops_1d (str)
404ff6b5 10363 char * str;
404ff6b5 10364{
63e63b07 10365 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10366}
10367
10368static void
63e63b07 10369do_mav_binops_1e (str)
404ff6b5 10370 char * str;
404ff6b5 10371{
63e63b07 10372 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10373}
10374
10375static void
63e63b07 10376do_mav_binops_1f (str)
404ff6b5 10377 char * str;
404ff6b5 10378{
63e63b07 10379 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10380}
10381
10382static void
63e63b07 10383do_mav_binops_1g (str)
404ff6b5 10384 char * str;
404ff6b5 10385{
63e63b07 10386 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10387}
10388
10389static void
63e63b07 10390do_mav_binops_1h (str)
404ff6b5 10391 char * str;
404ff6b5 10392{
63e63b07 10393 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10394}
10395
6c43fab6 10396static void
63e63b07 10397do_mav_binops_1i (str)
6c43fab6
RE
10398 char * str;
10399{
63e63b07 10400 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10401}
10402
10403static void
63e63b07 10404do_mav_binops_1j (str)
6c43fab6
RE
10405 char * str;
10406{
63e63b07 10407 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10408}
10409
10410static void
63e63b07 10411do_mav_binops_1k (str)
6c43fab6
RE
10412 char * str;
10413{
63e63b07 10414 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10415}
10416
10417static void
63e63b07 10418do_mav_binops_1l (str)
6c43fab6
RE
10419 char * str;
10420{
63e63b07 10421 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10422}
10423
10424static void
63e63b07 10425do_mav_binops_1m (str)
6c43fab6
RE
10426 char * str;
10427{
63e63b07 10428 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10429}
10430
10431static void
63e63b07 10432do_mav_binops_1n (str)
6c43fab6
RE
10433 char * str;
10434{
63e63b07 10435 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10436}
10437
10438static void
63e63b07 10439do_mav_binops_1o (str)
6c43fab6
RE
10440 char * str;
10441{
63e63b07 10442 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10443}
10444
10445static void
63e63b07 10446do_mav_binops_2a (str)
6c43fab6
RE
10447 char * str;
10448{
63e63b07 10449 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10450}
10451
10452static void
63e63b07 10453do_mav_binops_2b (str)
6c43fab6
RE
10454 char * str;
10455{
63e63b07 10456 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10457}
10458
10459static void
63e63b07 10460do_mav_binops_2c (str)
6c43fab6
RE
10461 char * str;
10462{
63e63b07 10463 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10464}
10465
10466static void
63e63b07 10467do_mav_binops_3a (str)
6c43fab6
RE
10468 char * str;
10469{
63e63b07 10470 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10471}
10472
10473static void
63e63b07 10474do_mav_binops_3b (str)
6c43fab6
RE
10475 char * str;
10476{
63e63b07 10477 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10478}
10479
10480static void
63e63b07 10481do_mav_binops_3c (str)
6c43fab6
RE
10482 char * str;
10483{
63e63b07 10484 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10485}
10486
10487static void
63e63b07 10488do_mav_binops_3d (str)
6c43fab6
RE
10489 char * str;
10490{
63e63b07 10491 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10492}
10493
10494static void
63e63b07 10495do_mav_triple_4a (str)
6c43fab6
RE
10496 char * str;
10497{
63e63b07 10498 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10499}
10500
10501static void
63e63b07 10502do_mav_triple_4b (str)
6c43fab6
RE
10503 char * str;
10504{
63e63b07 10505 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10506}
10507
10508static void
63e63b07 10509do_mav_triple_5a (str)
6c43fab6
RE
10510 char * str;
10511{
63e63b07 10512 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10513}
10514
10515static void
63e63b07 10516do_mav_triple_5b (str)
6c43fab6
RE
10517 char * str;
10518{
63e63b07 10519 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10520}
10521
10522static void
63e63b07 10523do_mav_triple_5c (str)
6c43fab6
RE
10524 char * str;
10525{
63e63b07 10526 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10527}
10528
10529static void
63e63b07 10530do_mav_triple_5d (str)
6c43fab6
RE
10531 char * str;
10532{
63e63b07 10533 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10534}
10535
10536static void
63e63b07 10537do_mav_triple_5e (str)
6c43fab6
RE
10538 char * str;
10539{
63e63b07 10540 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10541}
10542
10543static void
63e63b07 10544do_mav_triple_5f (str)
6c43fab6
RE
10545 char * str;
10546{
63e63b07 10547 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10548}
10549
10550static void
63e63b07 10551do_mav_triple_5g (str)
6c43fab6
RE
10552 char * str;
10553{
63e63b07 10554 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10555}
10556
10557static void
63e63b07 10558do_mav_triple_5h (str)
6c43fab6
RE
10559 char * str;
10560{
63e63b07 10561 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10562}
10563
10564static void
63e63b07 10565do_mav_quad_6a (str)
6c43fab6
RE
10566 char * str;
10567{
63e63b07 10568 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10569 REG_TYPE_MVFX);
10570}
10571
10572static void
63e63b07 10573do_mav_quad_6b (str)
6c43fab6
RE
10574 char * str;
10575{
63e63b07 10576 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10577 REG_TYPE_MVFX);
10578}
10579
34920d91 10580/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
404ff6b5 10581static void
63e63b07 10582do_mav_dspsc_1 (str)
404ff6b5 10583 char * str;
404ff6b5 10584{
6c43fab6
RE
10585 skip_whitespace (str);
10586
10587 /* cfmvsc32. */
63e63b07 10588 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10589 || skip_past_comma (&str) == FAIL
34920d91 10590 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
6c43fab6
RE
10591 {
10592 if (!inst.error)
10593 inst.error = BAD_ARGS;
10594
10595 return;
10596 }
10597
10598 end_of_line (str);
404ff6b5
AH
10599}
10600
34920d91 10601/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
404ff6b5 10602static void
63e63b07 10603do_mav_dspsc_2 (str)
404ff6b5 10604 char * str;
404ff6b5 10605{
6c43fab6
RE
10606 skip_whitespace (str);
10607
10608 /* cfmv32sc. */
34920d91 10609 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
6c43fab6 10610 || skip_past_comma (&str) == FAIL
63e63b07 10611 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10612 {
10613 if (!inst.error)
10614 inst.error = BAD_ARGS;
10615
10616 return;
10617 }
10618
10619 end_of_line (str);
404ff6b5
AH
10620}
10621
10622static void
63e63b07 10623do_mav_shift_1 (str)
404ff6b5 10624 char * str;
404ff6b5 10625{
63e63b07 10626 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10627}
10628
10629static void
63e63b07 10630do_mav_shift_2 (str)
404ff6b5 10631 char * str;
404ff6b5 10632{
63e63b07 10633 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10634}
10635
10636static void
63e63b07 10637do_mav_ldst_1 (str)
404ff6b5 10638 char * str;
404ff6b5 10639{
63e63b07 10640 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10641}
10642
10643static void
63e63b07 10644do_mav_ldst_2 (str)
404ff6b5 10645 char * str;
404ff6b5 10646{
63e63b07 10647 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10648}
10649
10650static void
63e63b07 10651do_mav_ldst_3 (str)
404ff6b5 10652 char * str;
404ff6b5 10653{
63e63b07 10654 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10655}
10656
10657static void
63e63b07 10658do_mav_ldst_4 (str)
404ff6b5 10659 char * str;
404ff6b5 10660{
63e63b07 10661 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10662}
10663
10664/* Isnsn like "foo X,Y". */
10665
10666static void
63e63b07 10667do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10668 char * str;
404ff6b5 10669 int mode;
6c43fab6
RE
10670 enum arm_reg_type reg0;
10671 enum arm_reg_type reg1;
404ff6b5 10672{
6c43fab6 10673 int shift0, shift1;
404ff6b5 10674
6c43fab6
RE
10675 shift0 = mode & 0xff;
10676 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10677
10678 skip_whitespace (str);
10679
63e63b07 10680 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10681 || skip_past_comma (&str) == FAIL
63e63b07 10682 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10683 {
10684 if (!inst.error)
10685 inst.error = BAD_ARGS;
10686 }
10687 else
10688 end_of_line (str);
404ff6b5
AH
10689}
10690
10691/* Isnsn like "foo X,Y,Z". */
10692
10693static void
63e63b07 10694do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10695 char * str;
404ff6b5 10696 int mode;
6c43fab6
RE
10697 enum arm_reg_type reg0;
10698 enum arm_reg_type reg1;
10699 enum arm_reg_type reg2;
404ff6b5 10700{
6c43fab6 10701 int shift0, shift1, shift2;
404ff6b5 10702
6c43fab6
RE
10703 shift0 = mode & 0xff;
10704 shift1 = (mode >> 8) & 0xff;
10705 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10706
10707 skip_whitespace (str);
10708
63e63b07 10709 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10710 || skip_past_comma (&str) == FAIL
63e63b07 10711 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10712 || skip_past_comma (&str) == FAIL
63e63b07 10713 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10714 {
10715 if (!inst.error)
10716 inst.error = BAD_ARGS;
10717 }
10718 else
10719 end_of_line (str);
404ff6b5
AH
10720}
10721
10722/* Isnsn like "foo W,X,Y,Z".
10723 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10724
10725static void
63e63b07 10726do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10727 char * str;
404ff6b5 10728 int mode;
6c43fab6
RE
10729 enum arm_reg_type reg0;
10730 enum arm_reg_type reg1;
10731 enum arm_reg_type reg2;
10732 enum arm_reg_type reg3;
404ff6b5 10733{
6c43fab6 10734 int shift0, shift1, shift2, shift3;
404ff6b5 10735
6c43fab6
RE
10736 shift0= mode & 0xff;
10737 shift1 = (mode >> 8) & 0xff;
10738 shift2 = (mode >> 16) & 0xff;
10739 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10740
10741 skip_whitespace (str);
10742
63e63b07 10743 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10744 || skip_past_comma (&str) == FAIL
63e63b07 10745 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10746 || skip_past_comma (&str) == FAIL
63e63b07 10747 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10748 || skip_past_comma (&str) == FAIL
63e63b07 10749 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10750 {
10751 if (!inst.error)
10752 inst.error = BAD_ARGS;
10753 }
10754 else
10755 end_of_line (str);
404ff6b5
AH
10756}
10757
63e63b07 10758/* Maverick shift immediate instructions.
404ff6b5
AH
10759 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10760 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10761
10762static void
63e63b07 10763do_mav_shift (str, reg0, reg1)
404ff6b5 10764 char * str;
6c43fab6
RE
10765 enum arm_reg_type reg0;
10766 enum arm_reg_type reg1;
404ff6b5
AH
10767{
10768 int error;
10769 int imm, neg = 0;
10770
10771 skip_whitespace (str);
10772
10773 error = 0;
10774
63e63b07 10775 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10776 || skip_past_comma (&str) == FAIL
63e63b07 10777 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10778 || skip_past_comma (&str) == FAIL)
10779 {
10780 if (!inst.error)
10781 inst.error = BAD_ARGS;
10782 return;
10783 }
10784
10785 /* Calculate the immediate operand.
10786 The operand is a 7bit signed number. */
10787 skip_whitespace (str);
10788
10789 if (*str == '#')
10790 ++str;
10791
8420dfca 10792 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10793 {
10794 inst.error = _("expecting immediate, 7bit operand");
10795 return;
10796 }
10797
10798 if (*str == '-')
10799 {
10800 neg = 1;
10801 ++str;
10802 }
10803
8420dfca 10804 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10805 imm = imm * 10 + *str - '0';
10806
10807 if (imm > 64)
10808 {
10809 inst.error = _("immediate out of range");
10810 return;
10811 }
10812
10813 /* Make negative imm's into 7bit signed numbers. */
10814 if (neg)
10815 {
10816 imm = -imm;
10817 imm &= 0x0000007f;
10818 }
10819
10820 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10821 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10822 Bit 4 should be 0. */
10823 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10824
10825 inst.instruction |= imm;
404ff6b5 10826 end_of_line (str);
404ff6b5
AH
10827}
10828
10829static int
63e63b07 10830mav_parse_offset (str, negative)
404ff6b5
AH
10831 char ** str;
10832 int *negative;
10833{
10834 char * p = *str;
10835 int offset;
10836
10837 *negative = 0;
10838
10839 skip_whitespace (p);
10840
10841 if (*p == '#')
10842 ++p;
10843
10844 if (*p == '-')
10845 {
10846 *negative = 1;
10847 ++p;
10848 }
10849
8420dfca 10850 if (!ISDIGIT (*p))
404ff6b5
AH
10851 {
10852 inst.error = _("offset expected");
10853 return 0;
10854 }
10855
8420dfca 10856 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10857 offset = offset * 10 + *p - '0';
10858
10859 if (offset > 0xff)
10860 {
10861 inst.error = _("offset out of range");
10862 return 0;
10863 }
10864
10865 *str = p;
10866
10867 return *negative ? -offset : offset;
10868}
10869
63e63b07 10870/* Maverick load/store instructions.
404ff6b5
AH
10871 <insn><cond> CRd,[Rn,<offset>]{!}.
10872 <insn><cond> CRd,[Rn],<offset>. */
10873
10874static void
63e63b07 10875do_mav_ldst (str, reg0)
404ff6b5 10876 char * str;
6c43fab6 10877 enum arm_reg_type reg0;
404ff6b5
AH
10878{
10879 int offset, negative;
404ff6b5
AH
10880
10881 skip_whitespace (str);
10882
63e63b07 10883 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10884 || skip_past_comma (&str) == FAIL
404ff6b5 10885 || *str++ != '['
6c43fab6 10886 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10887 goto fail_ldst;
10888
6c43fab6 10889 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10890 {
10891 /* You are here: "<offset>]{!}". */
10892 inst.instruction |= PRE_INDEX;
10893
63e63b07 10894 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10895
10896 if (inst.error)
10897 return;
10898
10899 if (*str++ != ']')
10900 {
10901 inst.error = _("missing ]");
10902 return;
10903 }
10904
10905 if (*str == '!')
10906 {
10907 inst.instruction |= WRITE_BACK;
10908 ++str;
10909 }
10910 }
10911 else
10912 {
10913 /* You are here: "], <offset>". */
10914 if (*str++ != ']')
10915 {
10916 inst.error = _("missing ]");
10917 return;
10918 }
10919
10920 if (skip_past_comma (&str) == FAIL
63e63b07 10921 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10922 goto fail_ldst;
10923
10924 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10925 }
10926
10927 if (negative)
10928 offset = -offset;
10929 else
2d2255b5 10930 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10931
10932 inst.instruction |= offset >> 2;
404ff6b5
AH
10933 end_of_line (str);
10934 return;
10935
10936fail_ldst:
10937 if (!inst.error)
10938 inst.error = BAD_ARGS;
404ff6b5
AH
10939}
10940
b99bd4ef
NC
10941static void
10942do_t_nop (str)
10943 char * str;
10944{
10945 /* Do nothing. */
10946 end_of_line (str);
b99bd4ef
NC
10947}
10948
10949/* Handle the Format 4 instructions that do not have equivalents in other
10950 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10951 BIC and MVN. */
10952
10953static void
10954do_t_arit (str)
10955 char * str;
10956{
10957 int Rd, Rs, Rn;
10958
10959 skip_whitespace (str);
10960
10961 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10962 || skip_past_comma (&str) == FAIL
10963 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10964 {
10965 inst.error = BAD_ARGS;
10966 return;
10967 }
10968
10969 if (skip_past_comma (&str) != FAIL)
10970 {
10971 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10972 (It isn't allowed for CMP either, but that isn't handled by this
10973 function.) */
10974 if (inst.instruction == T_OPCODE_TST
10975 || inst.instruction == T_OPCODE_CMN
10976 || inst.instruction == T_OPCODE_NEG
10977 || inst.instruction == T_OPCODE_MVN)
10978 {
10979 inst.error = BAD_ARGS;
10980 return;
10981 }
10982
10983 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10984 return;
10985
10986 if (Rs != Rd)
10987 {
10988 inst.error = _("dest and source1 must be the same register");
10989 return;
10990 }
10991 Rs = Rn;
10992 }
10993
10994 if (inst.instruction == T_OPCODE_MUL
10995 && Rs == Rd)
10996 as_tsktsk (_("Rs and Rd must be different in MUL"));
10997
10998 inst.instruction |= Rd | (Rs << 3);
10999 end_of_line (str);
11000}
11001
11002static void
11003do_t_add (str)
11004 char * str;
11005{
11006 thumb_add_sub (str, 0);
11007}
11008
11009static void
11010do_t_asr (str)
11011 char * str;
11012{
11013 thumb_shift (str, THUMB_ASR);
11014}
11015
11016static void
11017do_t_branch9 (str)
11018 char * str;
11019{
11020 if (my_get_expression (&inst.reloc.exp, &str))
11021 return;
11022 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11023 inst.reloc.pc_rel = 1;
11024 end_of_line (str);
11025}
11026
11027static void
11028do_t_branch12 (str)
11029 char * str;
11030{
11031 if (my_get_expression (&inst.reloc.exp, &str))
11032 return;
11033 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11034 inst.reloc.pc_rel = 1;
11035 end_of_line (str);
11036}
11037
11038/* Find the real, Thumb encoded start of a Thumb function. */
11039
11040static symbolS *
11041find_real_start (symbolP)
11042 symbolS * symbolP;
11043{
11044 char * real_start;
11045 const char * name = S_GET_NAME (symbolP);
11046 symbolS * new_target;
11047
2d2255b5 11048 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11049#define STUB_NAME ".real_start_of"
11050
11051 if (name == NULL)
11052 abort ();
11053
11054 /* Names that start with '.' are local labels, not function entry points.
11055 The compiler may generate BL instructions to these labels because it
11056 needs to perform a branch to a far away location. */
11057 if (name[0] == '.')
11058 return symbolP;
11059
11060 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11061 sprintf (real_start, "%s%s", STUB_NAME, name);
11062
11063 new_target = symbol_find (real_start);
11064
11065 if (new_target == NULL)
11066 {
11067 as_warn ("Failed to find real start of function: %s\n", name);
11068 new_target = symbolP;
11069 }
11070
11071 free (real_start);
11072
11073 return new_target;
11074}
11075
11076static void
11077do_t_branch23 (str)
11078 char * str;
11079{
11080 if (my_get_expression (& inst.reloc.exp, & str))
11081 return;
11082
11083 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11084 inst.reloc.pc_rel = 1;
11085 end_of_line (str);
11086
11087 /* If the destination of the branch is a defined symbol which does not have
11088 the THUMB_FUNC attribute, then we must be calling a function which has
11089 the (interfacearm) attribute. We look for the Thumb entry point to that
11090 function and change the branch to refer to that function instead. */
11091 if ( inst.reloc.exp.X_op == O_symbol
11092 && inst.reloc.exp.X_add_symbol != NULL
11093 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11094 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11095 inst.reloc.exp.X_add_symbol =
11096 find_real_start (inst.reloc.exp.X_add_symbol);
11097}
11098
11099static void
11100do_t_bx (str)
11101 char * str;
11102{
11103 int reg;
11104
11105 skip_whitespace (str);
11106
11107 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11108 return;
11109
11110 /* This sets THUMB_H2 from the top bit of reg. */
11111 inst.instruction |= reg << 3;
11112
11113 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11114 should cause the alignment to be checked once it is known. This is
11115 because BX PC only works if the instruction is word aligned. */
11116
11117 end_of_line (str);
11118}
11119
11120static void
11121do_t_compare (str)
11122 char * str;
11123{
11124 thumb_mov_compare (str, THUMB_COMPARE);
11125}
11126
11127static void
11128do_t_ldmstm (str)
11129 char * str;
11130{
11131 int Rb;
11132 long range;
11133
11134 skip_whitespace (str);
11135
11136 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11137 return;
11138
11139 if (*str != '!')
f03698e6 11140 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11141 else
11142 str++;
11143
11144 if (skip_past_comma (&str) == FAIL
11145 || (range = reg_list (&str)) == FAIL)
11146 {
11147 if (! inst.error)
11148 inst.error = BAD_ARGS;
11149 return;
11150 }
11151
11152 if (inst.reloc.type != BFD_RELOC_NONE)
11153 {
11154 /* This really doesn't seem worth it. */
11155 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11156 inst.error = _("expression too complex");
b99bd4ef
NC
11157 return;
11158 }
11159
11160 if (range & ~0xff)
11161 {
11162 inst.error = _("only lo-regs valid in load/store multiple");
11163 return;
11164 }
11165
11166 inst.instruction |= (Rb << 8) | range;
11167 end_of_line (str);
11168}
11169
11170static void
11171do_t_ldr (str)
11172 char * str;
11173{
11174 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11175}
11176
11177static void
11178do_t_ldrb (str)
11179 char * str;
11180{
11181 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11182}
11183
11184static void
11185do_t_ldrh (str)
11186 char * str;
11187{
11188 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11189}
11190
11191static void
11192do_t_lds (str)
11193 char * str;
11194{
11195 int Rd, Rb, Ro;
11196
11197 skip_whitespace (str);
11198
11199 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11200 || skip_past_comma (&str) == FAIL
11201 || *str++ != '['
11202 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11203 || skip_past_comma (&str) == FAIL
11204 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11205 || *str++ != ']')
11206 {
11207 if (! inst.error)
f03698e6 11208 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11209 return;
11210 }
11211
11212 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11213 end_of_line (str);
11214}
11215
11216static void
11217do_t_lsl (str)
11218 char * str;
11219{
11220 thumb_shift (str, THUMB_LSL);
11221}
11222
11223static void
11224do_t_lsr (str)
11225 char * str;
11226{
11227 thumb_shift (str, THUMB_LSR);
11228}
11229
11230static void
11231do_t_mov (str)
11232 char * str;
11233{
11234 thumb_mov_compare (str, THUMB_MOVE);
11235}
11236
11237static void
11238do_t_push_pop (str)
11239 char * str;
11240{
11241 long range;
11242
11243 skip_whitespace (str);
11244
11245 if ((range = reg_list (&str)) == FAIL)
11246 {
11247 if (! inst.error)
11248 inst.error = BAD_ARGS;
11249 return;
11250 }
11251
11252 if (inst.reloc.type != BFD_RELOC_NONE)
11253 {
11254 /* This really doesn't seem worth it. */
11255 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11256 inst.error = _("expression too complex");
b99bd4ef
NC
11257 return;
11258 }
11259
11260 if (range & ~0xff)
11261 {
11262 if ((inst.instruction == T_OPCODE_PUSH
11263 && (range & ~0xff) == 1 << REG_LR)
11264 || (inst.instruction == T_OPCODE_POP
11265 && (range & ~0xff) == 1 << REG_PC))
11266 {
11267 inst.instruction |= THUMB_PP_PC_LR;
11268 range &= 0xff;
11269 }
11270 else
11271 {
11272 inst.error = _("invalid register list to push/pop instruction");
11273 return;
11274 }
11275 }
11276
11277 inst.instruction |= range;
11278 end_of_line (str);
11279}
11280
11281static void
11282do_t_str (str)
11283 char * str;
11284{
11285 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11286}
11287
11288static void
11289do_t_strb (str)
11290 char * str;
11291{
11292 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11293}
11294
11295static void
11296do_t_strh (str)
11297 char * str;
11298{
11299 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11300}
11301
11302static void
11303do_t_sub (str)
11304 char * str;
11305{
11306 thumb_add_sub (str, 1);
11307}
11308
11309static void
11310do_t_swi (str)
11311 char * str;
11312{
11313 skip_whitespace (str);
11314
11315 if (my_get_expression (&inst.reloc.exp, &str))
11316 return;
11317
11318 inst.reloc.type = BFD_RELOC_ARM_SWI;
11319 end_of_line (str);
b99bd4ef
NC
11320}
11321
11322static void
11323do_t_adr (str)
11324 char * str;
11325{
11326 int reg;
11327
11328 /* This is a pseudo-op of the form "adr rd, label" to be converted
11329 into a relative address of the form "add rd, pc, #label-.-4". */
11330 skip_whitespace (str);
11331
11332 /* Store Rd in temporary location inside instruction. */
11333 if ((reg = reg_required_here (&str, 4)) == FAIL
11334 || (reg > 7) /* For Thumb reg must be r0..r7. */
11335 || skip_past_comma (&str) == FAIL
11336 || my_get_expression (&inst.reloc.exp, &str))
11337 {
11338 if (!inst.error)
11339 inst.error = BAD_ARGS;
11340 return;
11341 }
11342
11343 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11344 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11345 inst.reloc.pc_rel = 1;
11346 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11347
11348 end_of_line (str);
11349}
11350
11351static void
6c43fab6
RE
11352insert_reg (r, htab)
11353 const struct reg_entry *r;
11354 struct hash_control *htab;
b99bd4ef 11355{
6c43fab6 11356 int len = strlen (r->name) + 2;
b99bd4ef
NC
11357 char * buf = (char *) xmalloc (len);
11358 char * buf2 = (char *) xmalloc (len);
11359 int i = 0;
11360
11361#ifdef REGISTER_PREFIX
11362 buf[i++] = REGISTER_PREFIX;
11363#endif
11364
6c43fab6 11365 strcpy (buf + i, r->name);
b99bd4ef
NC
11366
11367 for (i = 0; buf[i]; i++)
3882b010 11368 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11369
11370 buf2[i] = '\0';
11371
6c43fab6
RE
11372 hash_insert (htab, buf, (PTR) r);
11373 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11374}
11375
11376static void
6c43fab6
RE
11377build_reg_hsh (map)
11378 struct reg_map *map;
11379{
11380 const struct reg_entry *r;
11381
11382 if ((map->htab = hash_new ()) == NULL)
f03698e6 11383 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11384
11385 for (r = map->names; r->name != NULL; r++)
11386 insert_reg (r, map->htab);
11387}
11388
11389static void
11390insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11391 char *str;
11392 int regnum;
6c43fab6 11393 struct hash_control *htab;
b99bd4ef 11394{
0bbf2aa4
NC
11395 const char *error;
11396 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11397 const char *name = xmalloc (strlen (str) + 1);
11398
11399 strcpy ((char *) name, str);
11400
b99bd4ef
NC
11401 new->name = name;
11402 new->number = regnum;
0bbf2aa4 11403 new->builtin = FALSE;
b99bd4ef 11404
0bbf2aa4
NC
11405 error = hash_insert (htab, name, (PTR) new);
11406 if (error)
11407 {
11408 as_bad (_("failed to create an alias for %s, reason: %s"),
11409 str, error);
11410 free ((char *) name);
11411 free (new);
11412 }
b99bd4ef
NC
11413}
11414
6c43fab6
RE
11415/* Look for the .req directive. This is of the form:
11416
0bbf2aa4 11417 new_register_name .req existing_register_name
6c43fab6
RE
11418
11419 If we find one, or if it looks sufficiently like one that we want to
11420 handle any error here, return non-zero. Otherwise return zero. */
11421static int
11422create_register_alias (newname, p)
11423 char *newname;
11424 char *p;
11425{
11426 char *q;
11427 char c;
11428
11429 q = p;
11430 skip_whitespace (q);
11431
11432 c = *p;
11433 *p = '\0';
11434
11435 if (*q && !strncmp (q, ".req ", 5))
11436 {
11437 char *copy_of_str;
11438 char *r;
11439
11440#ifdef IGNORE_OPCODE_CASE
11441 newname = original_case_string;
11442#endif
11443 copy_of_str = newname;
11444
11445 q += 4;
11446 skip_whitespace (q);
11447
11448 for (r = q; *r != '\0'; r++)
11449 if (*r == ' ')
11450 break;
11451
11452 if (r != q)
11453 {
11454 enum arm_reg_type new_type, old_type;
11455 int old_regno;
11456 char d = *r;
11457
11458 *r = '\0';
11459 old_type = arm_reg_parse_any (q);
11460 *r = d;
11461
11462 new_type = arm_reg_parse_any (newname);
11463
11464 if (new_type == REG_TYPE_MAX)
11465 {
11466 if (old_type != REG_TYPE_MAX)
11467 {
11468 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11469 insert_reg_alias (newname, old_regno,
11470 all_reg_maps[old_type].htab);
11471 }
11472 else
11473 as_warn (_("register '%s' does not exist\n"), q);
11474 }
11475 else if (old_type == REG_TYPE_MAX)
11476 {
11477 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11478 copy_of_str, q);
11479 }
11480 else
11481 {
11482 /* Do not warn about redefinitions to the same alias. */
11483 if (new_type != old_type
11484 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11485 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11486 as_warn (_("ignoring redefinition of register alias '%s'"),
11487 copy_of_str);
11488
11489 }
11490 }
11491 else
11492 as_warn (_("ignoring incomplete .req pseuso op"));
11493
11494 *p = c;
11495 return 1;
11496 }
0bbf2aa4 11497
6c43fab6
RE
11498 *p = c;
11499 return 0;
11500}
cc8a6dd0 11501
b99bd4ef
NC
11502static void
11503set_constant_flonums ()
11504{
11505 int i;
11506
11507 for (i = 0; i < NUM_FLOAT_VALS; i++)
11508 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11509 abort ();
11510}
11511
90e4755a
RE
11512/* Iterate over the base tables to create the instruction patterns. */
11513static void
11514build_arm_ops_hsh ()
11515{
11516 unsigned int i;
11517 unsigned int j;
11518 static struct obstack insn_obstack;
11519
11520 obstack_begin (&insn_obstack, 4000);
11521
11522 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11523 {
6c43fab6 11524 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11525
11526 if (insn->cond_offset != 0)
11527 {
11528 /* Insn supports conditional execution. Build the varaints
11529 and insert them in the hash table. */
11530 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11531 {
11532 unsigned len = strlen (insn->template);
11533 struct asm_opcode *new;
11534 char *template;
11535
11536 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11537 /* All condition codes are two characters. */
11538 template = obstack_alloc (&insn_obstack, len + 3);
11539
11540 strncpy (template, insn->template, insn->cond_offset);
11541 strcpy (template + insn->cond_offset, conds[j].template);
11542 if (len > insn->cond_offset)
11543 strcpy (template + insn->cond_offset + 2,
11544 insn->template + insn->cond_offset);
11545 new->template = template;
11546 new->cond_offset = 0;
11547 new->variant = insn->variant;
11548 new->parms = insn->parms;
11549 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11550
11551 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11552 }
11553 }
11554 /* Finally, insert the unconditional insn in the table directly;
11555 no need to build a copy. */
11556 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11557 }
11558}
11559
0bbf2aa4 11560#if 0 /* Suppressed - for now. */
5a6c6817
NC
11561#if defined OBJ_ELF || defined OBJ_COFF
11562
11563#ifdef OBJ_ELF
11564#define arm_Note Elf_External_Note
11565#else
11566typedef struct
11567{
11568 unsigned char namesz[4]; /* Size of entry's owner string. */
11569 unsigned char descsz[4]; /* Size of the note descriptor. */
11570 unsigned char type[4]; /* Interpretation of the descriptor. */
11571 char name[1]; /* Start of the name+desc data. */
11572} arm_Note;
11573#endif
11574
11575/* The description is kept to a fix sized in order to make updating
11576 it and merging it easier. */
11577#define ARM_NOTE_DESCRIPTION_LENGTH 8
11578
11579static void
11580arm_add_note (name, description, type)
11581 const char * name;
11582 const char * description;
11583 unsigned int type;
11584{
11585 arm_Note note ATTRIBUTE_UNUSED;
11586 char * p;
11587 unsigned int name_len;
11588
11589 name_len = (strlen (name) + 1 + 3) & ~3;
11590
11591 p = frag_more (sizeof (note.namesz));
11592 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11593
11594 p = frag_more (sizeof (note.descsz));
11595 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11596
11597 p = frag_more (sizeof (note.type));
11598 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11599
11600 p = frag_more (name_len);
11601 strcpy (p, name);
11602
11603 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11604 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11605 frag_align (2, 0, 0);
11606}
11607#endif
0bbf2aa4 11608#endif
5a6c6817 11609
b99bd4ef
NC
11610void
11611md_begin ()
11612{
11613 unsigned mach;
11614 unsigned int i;
11615
11616 if ( (arm_ops_hsh = hash_new ()) == NULL
11617 || (arm_tops_hsh = hash_new ()) == NULL
11618 || (arm_cond_hsh = hash_new ()) == NULL
11619 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11620 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11621 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11622
90e4755a 11623 build_arm_ops_hsh ();
b99bd4ef
NC
11624 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11625 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11626 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11627 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11628 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11629 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11630 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11631 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11632
6c43fab6
RE
11633 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11634 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11635
11636 set_constant_flonums ();
11637
03b1477f
RE
11638 /* Set the cpu variant based on the command-line options. We prefer
11639 -mcpu= over -march= if both are set (as for GCC); and we prefer
11640 -mfpu= over any other way of setting the floating point unit.
11641 Use of legacy options with new options are faulted. */
11642 if (legacy_cpu != -1)
11643 {
11644 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11645 as_bad (_("use of old and new-style options to set CPU type"));
11646
11647 mcpu_cpu_opt = legacy_cpu;
11648 }
11649 else if (mcpu_cpu_opt == -1)
11650 mcpu_cpu_opt = march_cpu_opt;
11651
11652 if (legacy_fpu != -1)
11653 {
11654 if (mfpu_opt != -1)
11655 as_bad (_("use of old and new-style options to set FPU type"));
11656
11657 mfpu_opt = legacy_fpu;
11658 }
11659 else if (mfpu_opt == -1)
11660 {
39c2da32
RE
11661#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11662 /* Some environments specify a default FPU. If they don't, infer it
11663 from the processor. */
03b1477f
RE
11664 if (mcpu_fpu_opt != -1)
11665 mfpu_opt = mcpu_fpu_opt;
11666 else
11667 mfpu_opt = march_fpu_opt;
39c2da32
RE
11668#else
11669 mfpu_opt = FPU_DEFAULT;
11670#endif
03b1477f
RE
11671 }
11672
11673 if (mfpu_opt == -1)
11674 {
11675 if (mcpu_cpu_opt == -1)
11676 mfpu_opt = FPU_DEFAULT;
11677 else if (mcpu_cpu_opt & ARM_EXT_V5)
11678 mfpu_opt = FPU_ARCH_VFP_V2;
11679 else
11680 mfpu_opt = FPU_ARCH_FPA;
11681 }
11682
11683 if (mcpu_cpu_opt == -1)
11684 mcpu_cpu_opt = CPU_DEFAULT;
11685
11686 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11687
b99bd4ef
NC
11688#if defined OBJ_COFF || defined OBJ_ELF
11689 {
11690 unsigned int flags = 0;
11691
11692 /* Set the flags in the private structure. */
11693 if (uses_apcs_26) flags |= F_APCS26;
11694 if (support_interwork) flags |= F_INTERWORK;
11695 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11696 if (pic_code) flags |= F_PIC;
bfae80f2 11697 if ((cpu_variant & FPU_ANY) == FPU_NONE
33a392fb
PB
11698 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11699 {
11700 flags |= F_SOFT_FLOAT;
11701 }
11702 switch (mfloat_abi_opt)
11703 {
11704 case ARM_FLOAT_ABI_SOFT:
11705 case ARM_FLOAT_ABI_SOFTFP:
11706 flags |= F_SOFT_FLOAT;
11707 break;
11708
11709 case ARM_FLOAT_ABI_HARD:
11710 if (flags & F_SOFT_FLOAT)
11711 as_bad (_("hard-float conflicts with specified fpu"));
11712 break;
11713 }
03b1477f
RE
11714 /* Using VFP conventions (even if soft-float). */
11715 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11716
fde78edd 11717#if defined OBJ_ELF
33a392fb 11718 if (cpu_variant & FPU_ARCH_MAVERICK)
fde78edd 11719 flags |= EF_ARM_MAVERICK_FLOAT;
fde78edd 11720#endif
b99bd4ef
NC
11721
11722 bfd_set_private_flags (stdoutput, flags);
11723
11724 /* We have run out flags in the COFF header to encode the
11725 status of ATPCS support, so instead we create a dummy,
11726 empty, debug section called .arm.atpcs. */
11727 if (atpcs)
11728 {
11729 asection * sec;
11730
11731 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11732
11733 if (sec != NULL)
11734 {
11735 bfd_set_section_flags
11736 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11737 bfd_set_section_size (stdoutput, sec, 0);
11738 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11739 }
11740 }
11741 }
11742#endif
11743
11744 /* Record the CPU type as well. */
11745 switch (cpu_variant & ARM_CPU_MASK)
11746 {
11747 case ARM_2:
11748 mach = bfd_mach_arm_2;
11749 break;
11750
11751 case ARM_3: /* Also ARM_250. */
11752 mach = bfd_mach_arm_2a;
11753 break;
11754
b89dddec
RE
11755 case ARM_6: /* Also ARM_7. */
11756 mach = bfd_mach_arm_3;
11757 break;
11758
b99bd4ef 11759 default:
5a6c6817 11760 mach = bfd_mach_arm_unknown;
b99bd4ef 11761 break;
b99bd4ef
NC
11762 }
11763
11764 /* Catch special cases. */
e16bb312
NC
11765 if (cpu_variant & ARM_CEXT_IWMMXT)
11766 mach = bfd_mach_arm_iWMMXt;
11767 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11768 mach = bfd_mach_arm_XScale;
fde78edd
NC
11769 else if (cpu_variant & ARM_CEXT_MAVERICK)
11770 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11771 else if (cpu_variant & ARM_EXT_V5E)
11772 mach = bfd_mach_arm_5TE;
11773 else if (cpu_variant & ARM_EXT_V5)
11774 {
b89dddec 11775 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11776 mach = bfd_mach_arm_5T;
11777 else
11778 mach = bfd_mach_arm_5;
11779 }
b89dddec 11780 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11781 {
b89dddec 11782 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11783 mach = bfd_mach_arm_4T;
11784 else
11785 mach = bfd_mach_arm_4;
11786 }
b89dddec 11787 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11788 mach = bfd_mach_arm_3M;
11789
5a6c6817 11790#if 0 /* Suppressed - for now. */
e16bb312 11791#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11792
11793 /* Create a .note section to fully identify this arm binary. */
11794
11795#define NOTE_ARCH_STRING "arch: "
11796
11797#if defined OBJ_COFF && ! defined NT_VERSION
11798#define NT_VERSION 1
11799#define NT_ARCH 2
11800#endif
11801
e16bb312 11802 {
e16bb312
NC
11803 segT current_seg = now_seg;
11804 subsegT current_subseg = now_subseg;
11805 asection * arm_arch;
5a6c6817
NC
11806 const char * arch_string;
11807
e16bb312
NC
11808 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11809
11810#ifdef OBJ_COFF
11811 bfd_set_section_flags (stdoutput, arm_arch,
11812 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11813 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11814#else
11815 bfd_set_section_flags (stdoutput, arm_arch,
11816 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11817#endif
11818 arm_arch->output_section = arm_arch;
11819 subseg_set (arm_arch, 0);
e16bb312 11820
5a6c6817
NC
11821 switch (mach)
11822 {
11823 default:
11824 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11825 case bfd_mach_arm_2: arch_string = "armv2"; break;
11826 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11827 case bfd_mach_arm_3: arch_string = "armv3"; break;
11828 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11829 case bfd_mach_arm_4: arch_string = "armv4"; break;
11830 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11831 case bfd_mach_arm_5: arch_string = "armv5"; break;
11832 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11833 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11834 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11835 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11836 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11837 }
11838
11839 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11840
11841 subseg_set (current_seg, current_subseg);
11842 }
11843#endif
5a6c6817
NC
11844#endif /* Suppressed code. */
11845
b99bd4ef
NC
11846 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11847}
11848
11849/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11850 for use in the a.out file, and stores them in the array pointed to by buf.
11851 This knows about the endian-ness of the target machine and does
11852 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11853 2 (short) and 4 (long) Floating numbers are put out as a series of
11854 LITTLENUMS (shorts, here at least). */
11855
11856void
11857md_number_to_chars (buf, val, n)
11858 char * buf;
11859 valueT val;
11860 int n;
11861{
11862 if (target_big_endian)
11863 number_to_chars_bigendian (buf, val, n);
11864 else
11865 number_to_chars_littleendian (buf, val, n);
11866}
11867
11868static valueT
11869md_chars_to_number (buf, n)
11870 char * buf;
11871 int n;
11872{
11873 valueT result = 0;
11874 unsigned char * where = (unsigned char *) buf;
11875
11876 if (target_big_endian)
11877 {
11878 while (n--)
11879 {
11880 result <<= 8;
11881 result |= (*where++ & 255);
11882 }
11883 }
11884 else
11885 {
11886 while (n--)
11887 {
11888 result <<= 8;
11889 result |= (where[n] & 255);
11890 }
11891 }
11892
11893 return result;
11894}
11895
11896/* Turn a string in input_line_pointer into a floating point constant
11897 of type TYPE, and store the appropriate bytes in *LITP. The number
11898 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11899 returned, or NULL on OK.
11900
11901 Note that fp constants aren't represent in the normal way on the ARM.
11902 In big endian mode, things are as expected. However, in little endian
11903 mode fp constants are big-endian word-wise, and little-endian byte-wise
11904 within the words. For example, (double) 1.1 in big endian mode is
11905 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11906 the byte sequence 99 99 f1 3f 9a 99 99 99.
11907
11908 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11909
11910char *
11911md_atof (type, litP, sizeP)
11912 char type;
11913 char * litP;
11914 int * sizeP;
11915{
11916 int prec;
11917 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11918 char *t;
11919 int i;
11920
11921 switch (type)
11922 {
11923 case 'f':
11924 case 'F':
11925 case 's':
11926 case 'S':
11927 prec = 2;
11928 break;
11929
11930 case 'd':
11931 case 'D':
11932 case 'r':
11933 case 'R':
11934 prec = 4;
11935 break;
11936
11937 case 'x':
11938 case 'X':
11939 prec = 6;
11940 break;
11941
11942 case 'p':
11943 case 'P':
11944 prec = 6;
11945 break;
11946
11947 default:
11948 *sizeP = 0;
f03698e6 11949 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11950 }
11951
11952 t = atof_ieee (input_line_pointer, type, words);
11953 if (t)
11954 input_line_pointer = t;
11955 *sizeP = prec * 2;
11956
11957 if (target_big_endian)
11958 {
11959 for (i = 0; i < prec; i++)
11960 {
11961 md_number_to_chars (litP, (valueT) words[i], 2);
11962 litP += 2;
11963 }
11964 }
11965 else
11966 {
bfae80f2
RE
11967 if (cpu_variant & FPU_ARCH_VFP)
11968 for (i = prec - 1; i >= 0; i--)
11969 {
11970 md_number_to_chars (litP, (valueT) words[i], 2);
11971 litP += 2;
11972 }
11973 else
11974 /* For a 4 byte float the order of elements in `words' is 1 0.
11975 For an 8 byte float the order is 1 0 3 2. */
11976 for (i = 0; i < prec; i += 2)
11977 {
11978 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11979 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11980 litP += 4;
11981 }
b99bd4ef
NC
11982 }
11983
11984 return 0;
11985}
11986
11987/* The knowledge of the PC's pipeline offset is built into the insns
11988 themselves. */
11989
11990long
11991md_pcrel_from (fixP)
11992 fixS * fixP;
11993{
11994 if (fixP->fx_addsy
11995 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11996 && fixP->fx_subsy == NULL)
11997 return 0;
11998
11999 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12000 {
12001 /* PC relative addressing on the Thumb is slightly odd
12002 as the bottom two bits of the PC are forced to zero
12003 for the calculation. */
12004 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12005 }
12006
12007#ifdef TE_WINCE
2d2255b5
KH
12008 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12009 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
12010 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12011#else
12012 return fixP->fx_where + fixP->fx_frag->fr_address;
12013#endif
12014}
12015
12016/* Round up a section size to the appropriate boundary. */
12017
12018valueT
12019md_section_align (segment, size)
12020 segT segment ATTRIBUTE_UNUSED;
12021 valueT size;
12022{
12023#ifdef OBJ_ELF
12024 return size;
12025#else
12026 /* Round all sects to multiple of 4. */
12027 return (size + 3) & ~3;
12028#endif
12029}
12030
12031/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12032 Otherwise we have no need to default values of symbols. */
12033
12034symbolS *
12035md_undefined_symbol (name)
12036 char * name ATTRIBUTE_UNUSED;
12037{
12038#ifdef OBJ_ELF
12039 if (name[0] == '_' && name[1] == 'G'
12040 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12041 {
12042 if (!GOT_symbol)
12043 {
12044 if (symbol_find (name))
12045 as_bad ("GOT already in the symbol table");
12046
12047 GOT_symbol = symbol_new (name, undefined_section,
12048 (valueT) 0, & zero_address_frag);
12049 }
12050
12051 return GOT_symbol;
12052 }
12053#endif
12054
12055 return 0;
12056}
12057
12058/* arm_reg_parse () := if it looks like a register, return its token and
12059 advance the pointer. */
12060
12061static int
6c43fab6 12062arm_reg_parse (ccp, htab)
b99bd4ef 12063 register char ** ccp;
6c43fab6 12064 struct hash_control *htab;
b99bd4ef
NC
12065{
12066 char * start = * ccp;
12067 char c;
12068 char * p;
12069 struct reg_entry * reg;
12070
12071#ifdef REGISTER_PREFIX
12072 if (*start != REGISTER_PREFIX)
12073 return FAIL;
12074 p = start + 1;
12075#else
12076 p = start;
12077#ifdef OPTIONAL_REGISTER_PREFIX
12078 if (*p == OPTIONAL_REGISTER_PREFIX)
12079 p++, start++;
12080#endif
12081#endif
3882b010 12082 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12083 return FAIL;
12084
12085 c = *p++;
3882b010 12086 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12087 c = *p++;
12088
12089 *--p = 0;
6c43fab6 12090 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12091 *p = c;
12092
12093 if (reg)
12094 {
12095 *ccp = p;
12096 return reg->number;
12097 }
12098
12099 return FAIL;
12100}
12101
6c43fab6
RE
12102/* Search for the following register name in each of the possible reg name
12103 tables. Return the classification if found, or REG_TYPE_MAX if not
12104 present. */
12105static enum arm_reg_type
12106arm_reg_parse_any (cp)
12107 char *cp;
12108{
12109 int i;
12110
12111 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12112 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12113 return (enum arm_reg_type) i;
12114
12115 return REG_TYPE_MAX;
12116}
12117
94f592af
NC
12118void
12119md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12120 fixS * fixP;
94f592af 12121 valueT * valP;
b99bd4ef
NC
12122 segT seg;
12123{
94f592af 12124 offsetT value = * valP;
b99bd4ef
NC
12125 offsetT newval;
12126 unsigned int newimm;
12127 unsigned long temp;
12128 int sign;
12129 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12130 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12131
12132 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12133
12134 /* Note whether this will delete the relocation. */
12135#if 0
12136 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12137 doesn't work fully.) */
12138 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12139 && !fixP->fx_pcrel)
12140#else
12141 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12142#endif
12143 fixP->fx_done = 1;
12144
12145 /* If this symbol is in a different section then we need to leave it for
12146 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12147 so we have to undo it's effects here. */
12148 if (fixP->fx_pcrel)
12149 {
12150 if (fixP->fx_addsy != NULL
12151 && S_IS_DEFINED (fixP->fx_addsy)
12152 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12153 {
12154 if (target_oabi
12155 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12156 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12157 ))
12158 value = 0;
12159 else
12160 value += md_pcrel_from (fixP);
12161 }
12162 }
12163
12164 /* Remember value for emit_reloc. */
12165 fixP->fx_addnumber = value;
12166
12167 switch (fixP->fx_r_type)
12168 {
12169 case BFD_RELOC_ARM_IMMEDIATE:
12170 newimm = validate_immediate (value);
12171 temp = md_chars_to_number (buf, INSN_SIZE);
12172
12173 /* If the instruction will fail, see if we can fix things up by
12174 changing the opcode. */
12175 if (newimm == (unsigned int) FAIL
12176 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12177 {
12178 as_bad_where (fixP->fx_file, fixP->fx_line,
12179 _("invalid constant (%lx) after fixup"),
12180 (unsigned long) value);
12181 break;
12182 }
12183
12184 newimm |= (temp & 0xfffff000);
12185 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
6189168b 12186 fixP->fx_done = 1;
b99bd4ef
NC
12187 break;
12188
12189 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12190 {
12191 unsigned int highpart = 0;
12192 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12193
b99bd4ef
NC
12194 newimm = validate_immediate (value);
12195 temp = md_chars_to_number (buf, INSN_SIZE);
12196
12197 /* If the instruction will fail, see if we can fix things up by
12198 changing the opcode. */
12199 if (newimm == (unsigned int) FAIL
12200 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12201 {
12202 /* No ? OK - try using two ADD instructions to generate
12203 the value. */
12204 newimm = validate_immediate_twopart (value, & highpart);
12205
12206 /* Yes - then make sure that the second instruction is
12207 also an add. */
12208 if (newimm != (unsigned int) FAIL)
12209 newinsn = temp;
12210 /* Still No ? Try using a negated value. */
12211 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12212 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12213 /* Otherwise - give up. */
12214 else
12215 {
12216 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12217 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12218 (long) value);
b99bd4ef
NC
12219 break;
12220 }
12221
12222 /* Replace the first operand in the 2nd instruction (which
12223 is the PC) with the destination register. We have
12224 already added in the PC in the first instruction and we
12225 do not want to do it again. */
12226 newinsn &= ~ 0xf0000;
12227 newinsn |= ((newinsn & 0x0f000) << 4);
12228 }
12229
12230 newimm |= (temp & 0xfffff000);
12231 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12232
12233 highpart |= (newinsn & 0xfffff000);
12234 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12235 }
12236 break;
12237
12238 case BFD_RELOC_ARM_OFFSET_IMM:
12239 sign = value >= 0;
12240
12241 if (value < 0)
12242 value = - value;
12243
12244 if (validate_offset_imm (value, 0) == FAIL)
12245 {
12246 as_bad_where (fixP->fx_file, fixP->fx_line,
12247 _("bad immediate value for offset (%ld)"),
12248 (long) value);
12249 break;
12250 }
12251
12252 newval = md_chars_to_number (buf, INSN_SIZE);
12253 newval &= 0xff7ff000;
12254 newval |= value | (sign ? INDEX_UP : 0);
12255 md_number_to_chars (buf, newval, INSN_SIZE);
12256 break;
12257
12258 case BFD_RELOC_ARM_OFFSET_IMM8:
12259 case BFD_RELOC_ARM_HWLITERAL:
12260 sign = value >= 0;
12261
12262 if (value < 0)
12263 value = - value;
12264
12265 if (validate_offset_imm (value, 1) == FAIL)
12266 {
12267 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12268 as_bad_where (fixP->fx_file, fixP->fx_line,
12269 _("invalid literal constant: pool needs to be closer"));
12270 else
12271 as_bad (_("bad immediate value for half-word offset (%ld)"),
12272 (long) value);
12273 break;
12274 }
12275
12276 newval = md_chars_to_number (buf, INSN_SIZE);
12277 newval &= 0xff7ff0f0;
12278 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12279 md_number_to_chars (buf, newval, INSN_SIZE);
12280 break;
12281
12282 case BFD_RELOC_ARM_LITERAL:
12283 sign = value >= 0;
12284
12285 if (value < 0)
12286 value = - value;
12287
12288 if (validate_offset_imm (value, 0) == FAIL)
12289 {
12290 as_bad_where (fixP->fx_file, fixP->fx_line,
12291 _("invalid literal constant: pool needs to be closer"));
12292 break;
12293 }
12294
12295 newval = md_chars_to_number (buf, INSN_SIZE);
12296 newval &= 0xff7ff000;
12297 newval |= value | (sign ? INDEX_UP : 0);
12298 md_number_to_chars (buf, newval, INSN_SIZE);
12299 break;
12300
12301 case BFD_RELOC_ARM_SHIFT_IMM:
12302 newval = md_chars_to_number (buf, INSN_SIZE);
12303 if (((unsigned long) value) > 32
12304 || (value == 32
12305 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12306 {
12307 as_bad_where (fixP->fx_file, fixP->fx_line,
12308 _("shift expression is too large"));
12309 break;
12310 }
12311
12312 if (value == 0)
12313 /* Shifts of zero must be done as lsl. */
12314 newval &= ~0x60;
12315 else if (value == 32)
12316 value = 0;
12317 newval &= 0xfffff07f;
12318 newval |= (value & 0x1f) << 7;
12319 md_number_to_chars (buf, newval, INSN_SIZE);
12320 break;
12321
12322 case BFD_RELOC_ARM_SWI:
12323 if (arm_data->thumb_mode)
12324 {
12325 if (((unsigned long) value) > 0xff)
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12327 _("invalid swi expression"));
b99bd4ef
NC
12328 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12329 newval |= value;
12330 md_number_to_chars (buf, newval, THUMB_SIZE);
12331 }
12332 else
12333 {
12334 if (((unsigned long) value) > 0x00ffffff)
12335 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12336 _("invalid swi expression"));
b99bd4ef
NC
12337 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12338 newval |= value;
12339 md_number_to_chars (buf, newval, INSN_SIZE);
12340 }
12341 break;
12342
12343 case BFD_RELOC_ARM_MULTI:
12344 if (((unsigned long) value) > 0xffff)
12345 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12346 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12347 newval = value | md_chars_to_number (buf, INSN_SIZE);
12348 md_number_to_chars (buf, newval, INSN_SIZE);
12349 break;
12350
12351 case BFD_RELOC_ARM_PCREL_BRANCH:
12352 newval = md_chars_to_number (buf, INSN_SIZE);
12353
12354 /* Sign-extend a 24-bit number. */
12355#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12356
12357#ifdef OBJ_ELF
12358 if (! target_oabi)
12359 value = fixP->fx_offset;
12360#endif
12361
12362 /* We are going to store value (shifted right by two) in the
12363 instruction, in a 24 bit, signed field. Thus we need to check
12364 that none of the top 8 bits of the shifted value (top 7 bits of
12365 the unshifted, unsigned value) are set, or that they are all set. */
12366 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12367 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12368 {
12369#ifdef OBJ_ELF
12370 /* Normally we would be stuck at this point, since we cannot store
12371 the absolute address that is the destination of the branch in the
12372 24 bits of the branch instruction. If however, we happen to know
12373 that the destination of the branch is in the same section as the
2d2255b5 12374 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12375 ourselves and not have to bother the linker with it.
12376
12377 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12378 because I have not worked out how to do this for OBJ_COFF or
12379 target_oabi. */
12380 if (! target_oabi
12381 && fixP->fx_addsy != NULL
12382 && S_IS_DEFINED (fixP->fx_addsy)
12383 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12384 {
12385 /* Get pc relative value to go into the branch. */
94f592af 12386 value = * valP;
b99bd4ef
NC
12387
12388 /* Permit a backward branch provided that enough bits
12389 are set. Allow a forwards branch, provided that
12390 enough bits are clear. */
12391 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12392 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12393 fixP->fx_done = 1;
12394 }
12395
12396 if (! fixP->fx_done)
12397#endif
12398 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12399 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12400 }
12401
12402 value >>= 2;
12403 value += SEXT24 (newval);
12404
12405 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12406 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12407 as_bad_where (fixP->fx_file, fixP->fx_line,
12408 _("out of range branch"));
12409
12410 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12411 md_number_to_chars (buf, newval, INSN_SIZE);
12412 break;
12413
12414 case BFD_RELOC_ARM_PCREL_BLX:
12415 {
12416 offsetT hbit;
12417 newval = md_chars_to_number (buf, INSN_SIZE);
12418
12419#ifdef OBJ_ELF
12420 if (! target_oabi)
12421 value = fixP->fx_offset;
12422#endif
12423 hbit = (value >> 1) & 1;
12424 value = (value >> 2) & 0x00ffffff;
12425 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12426 newval = value | (newval & 0xfe000000) | (hbit << 24);
12427 md_number_to_chars (buf, newval, INSN_SIZE);
12428 }
12429 break;
12430
12431 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12432 newval = md_chars_to_number (buf, THUMB_SIZE);
12433 {
12434 addressT diff = (newval & 0xff) << 1;
12435 if (diff & 0x100)
12436 diff |= ~0xff;
12437
12438 value += diff;
12439 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12440 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12441 _("branch out of range"));
b99bd4ef
NC
12442 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12443 }
12444 md_number_to_chars (buf, newval, THUMB_SIZE);
12445 break;
12446
12447 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12448 newval = md_chars_to_number (buf, THUMB_SIZE);
12449 {
12450 addressT diff = (newval & 0x7ff) << 1;
12451 if (diff & 0x800)
12452 diff |= ~0x7ff;
12453
12454 value += diff;
12455 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12456 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12457 _("branch out of range"));
b99bd4ef
NC
12458 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12459 }
12460 md_number_to_chars (buf, newval, THUMB_SIZE);
12461 break;
12462
12463 case BFD_RELOC_THUMB_PCREL_BLX:
12464 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12465 {
12466 offsetT newval2;
12467 addressT diff;
12468
12469 newval = md_chars_to_number (buf, THUMB_SIZE);
12470 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12471 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12472 if (diff & 0x400000)
12473 diff |= ~0x3fffff;
12474#ifdef OBJ_ELF
12475 value = fixP->fx_offset;
12476#endif
12477 value += diff;
c62e1cc3 12478
b99bd4ef
NC
12479 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12480 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12481 _("branch with link out of range"));
b99bd4ef
NC
12482
12483 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12484 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12485 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12486 /* For a BLX instruction, make sure that the relocation is rounded up
12487 to a word boundary. This follows the semantics of the instruction
12488 which specifies that bit 1 of the target address will come from bit
12489 1 of the base address. */
12490 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12491 md_number_to_chars (buf, newval, THUMB_SIZE);
12492 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12493 }
12494 break;
12495
12496 case BFD_RELOC_8:
12497 if (fixP->fx_done || fixP->fx_pcrel)
12498 md_number_to_chars (buf, value, 1);
12499#ifdef OBJ_ELF
12500 else if (!target_oabi)
12501 {
12502 value = fixP->fx_offset;
12503 md_number_to_chars (buf, value, 1);
12504 }
12505#endif
12506 break;
12507
12508 case BFD_RELOC_16:
12509 if (fixP->fx_done || fixP->fx_pcrel)
12510 md_number_to_chars (buf, value, 2);
12511#ifdef OBJ_ELF
12512 else if (!target_oabi)
12513 {
12514 value = fixP->fx_offset;
12515 md_number_to_chars (buf, value, 2);
12516 }
12517#endif
12518 break;
12519
12520#ifdef OBJ_ELF
12521 case BFD_RELOC_ARM_GOT32:
12522 case BFD_RELOC_ARM_GOTOFF:
12523 md_number_to_chars (buf, 0, 4);
12524 break;
12525#endif
12526
12527 case BFD_RELOC_RVA:
12528 case BFD_RELOC_32:
12529 if (fixP->fx_done || fixP->fx_pcrel)
12530 md_number_to_chars (buf, value, 4);
12531#ifdef OBJ_ELF
12532 else if (!target_oabi)
12533 {
12534 value = fixP->fx_offset;
12535 md_number_to_chars (buf, value, 4);
12536 }
12537#endif
12538 break;
12539
12540#ifdef OBJ_ELF
12541 case BFD_RELOC_ARM_PLT32:
12542 /* It appears the instruction is fully prepared at this point. */
12543 break;
12544#endif
12545
b99bd4ef
NC
12546 case BFD_RELOC_ARM_CP_OFF_IMM:
12547 sign = value >= 0;
12548 if (value < -1023 || value > 1023 || (value & 3))
12549 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12550 _("illegal value for co-processor offset"));
b99bd4ef
NC
12551 if (value < 0)
12552 value = -value;
12553 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12554 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12555 md_number_to_chars (buf, newval, INSN_SIZE);
12556 break;
12557
e16bb312
NC
12558 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12559 sign = value >= 0;
12560 if (value < -255 || value > 255)
12561 as_bad_where (fixP->fx_file, fixP->fx_line,
12562 _("Illegal value for co-processor offset"));
12563 if (value < 0)
12564 value = -value;
12565 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12566 newval |= value | (sign ? INDEX_UP : 0);
12567 md_number_to_chars (buf, newval , INSN_SIZE);
12568 break;
12569
b99bd4ef
NC
12570 case BFD_RELOC_ARM_THUMB_OFFSET:
12571 newval = md_chars_to_number (buf, THUMB_SIZE);
12572 /* Exactly what ranges, and where the offset is inserted depends
12573 on the type of instruction, we can establish this from the
12574 top 4 bits. */
12575 switch (newval >> 12)
12576 {
12577 case 4: /* PC load. */
12578 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12579 forced to zero for these loads, so we will need to round
12580 up the offset if the instruction address is not word
12581 aligned (since the final address produced must be, and
12582 we can only describe word-aligned immediate offsets). */
12583
12584 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12585 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12586 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12587 (unsigned int) (fixP->fx_frag->fr_address
12588 + fixP->fx_where + value));
12589
12590 if ((value + 2) & ~0x3fe)
12591 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12592 _("invalid offset, value too big (0x%08lX)"),
12593 (long) value);
b99bd4ef
NC
12594
12595 /* Round up, since pc will be rounded down. */
12596 newval |= (value + 2) >> 2;
12597 break;
12598
12599 case 9: /* SP load/store. */
12600 if (value & ~0x3fc)
12601 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12602 _("invalid offset, value too big (0x%08lX)"),
12603 (long) value);
b99bd4ef
NC
12604 newval |= value >> 2;
12605 break;
12606
12607 case 6: /* Word load/store. */
12608 if (value & ~0x7c)
12609 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12610 _("invalid offset, value too big (0x%08lX)"),
12611 (long) value);
b99bd4ef
NC
12612 newval |= value << 4; /* 6 - 2. */
12613 break;
12614
12615 case 7: /* Byte load/store. */
12616 if (value & ~0x1f)
12617 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12618 _("invalid offset, value too big (0x%08lX)"),
12619 (long) value);
b99bd4ef
NC
12620 newval |= value << 6;
12621 break;
12622
12623 case 8: /* Halfword load/store. */
12624 if (value & ~0x3e)
12625 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12626 _("invalid offset, value too big (0x%08lX)"),
12627 (long) value);
b99bd4ef
NC
12628 newval |= value << 5; /* 6 - 1. */
12629 break;
12630
12631 default:
12632 as_bad_where (fixP->fx_file, fixP->fx_line,
12633 "Unable to process relocation for thumb opcode: %lx",
12634 (unsigned long) newval);
12635 break;
12636 }
12637 md_number_to_chars (buf, newval, THUMB_SIZE);
12638 break;
12639
12640 case BFD_RELOC_ARM_THUMB_ADD:
12641 /* This is a complicated relocation, since we use it for all of
12642 the following immediate relocations:
12643
12644 3bit ADD/SUB
12645 8bit ADD/SUB
12646 9bit ADD/SUB SP word-aligned
12647 10bit ADD PC/SP word-aligned
12648
12649 The type of instruction being processed is encoded in the
12650 instruction field:
12651
12652 0x8000 SUB
12653 0x00F0 Rd
12654 0x000F Rs
12655 */
12656 newval = md_chars_to_number (buf, THUMB_SIZE);
12657 {
12658 int rd = (newval >> 4) & 0xf;
12659 int rs = newval & 0xf;
12660 int subtract = newval & 0x8000;
12661
12662 if (rd == REG_SP)
12663 {
12664 if (value & ~0x1fc)
12665 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12666 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12667 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12668 newval |= value >> 2;
12669 }
12670 else if (rs == REG_PC || rs == REG_SP)
12671 {
12672 if (subtract ||
12673 value & ~0x3fc)
12674 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12675 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12676 (unsigned long) value);
12677 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12678 newval |= rd << 8;
12679 newval |= value >> 2;
12680 }
12681 else if (rs == rd)
12682 {
12683 if (value & ~0xff)
12684 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12685 _("invalid 8bit immediate"));
b99bd4ef
NC
12686 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12687 newval |= (rd << 8) | value;
12688 }
12689 else
12690 {
12691 if (value & ~0x7)
12692 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12693 _("invalid 3bit immediate"));
b99bd4ef
NC
12694 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12695 newval |= rd | (rs << 3) | (value << 6);
12696 }
12697 }
12698 md_number_to_chars (buf, newval, THUMB_SIZE);
12699 break;
12700
12701 case BFD_RELOC_ARM_THUMB_IMM:
12702 newval = md_chars_to_number (buf, THUMB_SIZE);
12703 switch (newval >> 11)
12704 {
12705 case 0x04: /* 8bit immediate MOV. */
12706 case 0x05: /* 8bit immediate CMP. */
12707 if (value < 0 || value > 255)
12708 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12709 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12710 (long) value);
12711 newval |= value;
12712 break;
12713
12714 default:
12715 abort ();
12716 }
12717 md_number_to_chars (buf, newval, THUMB_SIZE);
12718 break;
12719
12720 case BFD_RELOC_ARM_THUMB_SHIFT:
12721 /* 5bit shift value (0..31). */
12722 if (value < 0 || value > 31)
12723 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12724 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12725 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12726 newval |= value << 6;
12727 md_number_to_chars (buf, newval, THUMB_SIZE);
12728 break;
12729
12730 case BFD_RELOC_VTABLE_INHERIT:
12731 case BFD_RELOC_VTABLE_ENTRY:
12732 fixP->fx_done = 0;
94f592af 12733 return;
b99bd4ef
NC
12734
12735 case BFD_RELOC_NONE:
12736 default:
12737 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12738 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12739 }
b99bd4ef
NC
12740}
12741
12742/* Translate internal representation of relocation info to BFD target
12743 format. */
12744
12745arelent *
12746tc_gen_reloc (section, fixp)
12747 asection * section ATTRIBUTE_UNUSED;
12748 fixS * fixp;
12749{
12750 arelent * reloc;
12751 bfd_reloc_code_real_type code;
12752
12753 reloc = (arelent *) xmalloc (sizeof (arelent));
12754
12755 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12756 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12757 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12758
12759 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12760#ifndef OBJ_ELF
12761 if (fixp->fx_pcrel == 0)
12762 reloc->addend = fixp->fx_offset;
12763 else
12764 reloc->addend = fixp->fx_offset = reloc->address;
12765#else /* OBJ_ELF */
12766 reloc->addend = fixp->fx_offset;
12767#endif
12768
12769 switch (fixp->fx_r_type)
12770 {
12771 case BFD_RELOC_8:
12772 if (fixp->fx_pcrel)
12773 {
12774 code = BFD_RELOC_8_PCREL;
12775 break;
12776 }
12777
12778 case BFD_RELOC_16:
12779 if (fixp->fx_pcrel)
12780 {
12781 code = BFD_RELOC_16_PCREL;
12782 break;
12783 }
12784
12785 case BFD_RELOC_32:
12786 if (fixp->fx_pcrel)
12787 {
12788 code = BFD_RELOC_32_PCREL;
12789 break;
12790 }
12791
12792 case BFD_RELOC_ARM_PCREL_BRANCH:
12793 case BFD_RELOC_ARM_PCREL_BLX:
12794 case BFD_RELOC_RVA:
12795 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12796 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12797 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12798 case BFD_RELOC_THUMB_PCREL_BLX:
12799 case BFD_RELOC_VTABLE_ENTRY:
12800 case BFD_RELOC_VTABLE_INHERIT:
12801 code = fixp->fx_r_type;
12802 break;
12803
12804 case BFD_RELOC_ARM_LITERAL:
12805 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12806 /* If this is called then the a literal has
12807 been referenced across a section boundary. */
b99bd4ef 12808 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12809 _("literal referenced across section boundary"));
b99bd4ef
NC
12810 return NULL;
12811
12812#ifdef OBJ_ELF
12813 case BFD_RELOC_ARM_GOT32:
12814 case BFD_RELOC_ARM_GOTOFF:
12815 case BFD_RELOC_ARM_PLT32:
12816 code = fixp->fx_r_type;
12817 break;
12818#endif
12819
12820 case BFD_RELOC_ARM_IMMEDIATE:
12821 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12822 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12823 return NULL;
12824
12825 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12826 as_bad_where (fixp->fx_file, fixp->fx_line,
12827 _("ADRL used for a symbol not defined in the same file"));
12828 return NULL;
12829
12830 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12831 if (fixp->fx_addsy != NULL
12832 && !S_IS_DEFINED (fixp->fx_addsy)
12833 && S_IS_LOCAL (fixp->fx_addsy))
12834 {
12835 as_bad_where (fixp->fx_file, fixp->fx_line,
12836 _("undefined local label `%s'"),
12837 S_GET_NAME (fixp->fx_addsy));
12838 return NULL;
12839 }
12840
b99bd4ef 12841 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12842 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12843 return NULL;
12844
12845 default:
12846 {
12847 char * type;
12848
12849 switch (fixp->fx_r_type)
12850 {
b99bd4ef
NC
12851 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12852 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12853 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12854 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12855 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12856 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12857 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12858 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12859 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12860 default: type = _("<unknown>"); break;
12861 }
12862 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12863 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12864 type);
12865 return NULL;
12866 }
12867 }
12868
12869#ifdef OBJ_ELF
8df7094c 12870 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12871 && GOT_symbol
12872 && fixp->fx_addsy == GOT_symbol)
12873 {
12874 code = BFD_RELOC_ARM_GOTPC;
12875 reloc->addend = fixp->fx_offset = reloc->address;
12876 }
12877#endif
12878
12879 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12880
12881 if (reloc->howto == NULL)
12882 {
12883 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12884 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12885 bfd_get_reloc_code_name (code));
12886 return NULL;
12887 }
12888
12889 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12890 vtable entry to be used in the relocation's section offset. */
12891 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12892 reloc->address = fixp->fx_offset;
12893
12894 return reloc;
12895}
12896
12897int
12898md_estimate_size_before_relax (fragP, segtype)
12899 fragS * fragP ATTRIBUTE_UNUSED;
12900 segT segtype ATTRIBUTE_UNUSED;
12901{
12902 as_fatal (_("md_estimate_size_before_relax\n"));
12903 return 1;
12904}
12905
12906static void
f03698e6
RE
12907output_inst (str)
12908 const char *str;
b99bd4ef
NC
12909{
12910 char * to = NULL;
12911
12912 if (inst.error)
12913 {
f03698e6 12914 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12915 return;
12916 }
12917
12918 to = frag_more (inst.size);
12919
12920 if (thumb_mode && (inst.size > THUMB_SIZE))
12921 {
12922 assert (inst.size == (2 * THUMB_SIZE));
12923 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12924 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12925 }
12926 else if (inst.size > INSN_SIZE)
12927 {
12928 assert (inst.size == (2 * INSN_SIZE));
12929 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12930 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12931 }
12932 else
12933 md_number_to_chars (to, inst.instruction, inst.size);
12934
12935 if (inst.reloc.type != BFD_RELOC_NONE)
12936 fix_new_arm (frag_now, to - frag_now->fr_literal,
12937 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12938 inst.reloc.type);
12939
12940#ifdef OBJ_ELF
12941 dwarf2_emit_insn (inst.size);
12942#endif
12943}
12944
12945void
12946md_assemble (str)
12947 char * str;
12948{
6c43fab6
RE
12949 char c;
12950 char *p;
12951 char *start;
b99bd4ef
NC
12952
12953 /* Align the instruction.
12954 This may not be the right thing to do but ... */
12955#if 0
12956 arm_align (2, 0);
12957#endif
b99bd4ef
NC
12958
12959 /* Align the previous label if needed. */
12960 if (last_label_seen != NULL)
12961 {
12962 symbol_set_frag (last_label_seen, frag_now);
12963 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12964 S_SET_SEGMENT (last_label_seen, now_seg);
12965 }
12966
12967 memset (&inst, '\0', sizeof (inst));
12968 inst.reloc.type = BFD_RELOC_NONE;
12969
12970 skip_whitespace (str);
12971
12972 /* Scan up to the end of the op-code, which must end in white space or
12973 end of string. */
12974 for (start = p = str; *p != '\0'; p++)
12975 if (*p == ' ')
12976 break;
12977
12978 if (p == str)
12979 {
f03698e6 12980 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12981 return;
12982 }
12983
12984 if (thumb_mode)
12985 {
05d2d07e 12986 const struct thumb_opcode * opcode;
b99bd4ef
NC
12987
12988 c = *p;
12989 *p = '\0';
05d2d07e 12990 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12991 *p = c;
12992
12993 if (opcode)
12994 {
12995 /* Check that this instruction is supported for this CPU. */
90e4755a 12996 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12997 {
f03698e6 12998 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12999 return;
13000 }
13001
6057a28f 13002 mapping_state (MAP_THUMB);
b99bd4ef
NC
13003 inst.instruction = opcode->value;
13004 inst.size = opcode->size;
13005 (*opcode->parms) (p);
f03698e6 13006 output_inst (str);
b99bd4ef
NC
13007 return;
13008 }
13009 }
13010 else
13011 {
05d2d07e 13012 const struct asm_opcode * opcode;
b99bd4ef 13013
90e4755a
RE
13014 c = *p;
13015 *p = '\0';
6c43fab6 13016 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 13017 *p = c;
b99bd4ef 13018
90e4755a 13019 if (opcode)
b99bd4ef 13020 {
90e4755a
RE
13021 /* Check that this instruction is supported for this CPU. */
13022 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 13023 {
f03698e6 13024 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13025 return;
13026 }
13027
6057a28f 13028 mapping_state (MAP_ARM);
90e4755a
RE
13029 inst.instruction = opcode->value;
13030 inst.size = INSN_SIZE;
f2b7cb0a 13031 (*opcode->parms) (p);
f03698e6 13032 output_inst (str);
90e4755a 13033 return;
b99bd4ef
NC
13034 }
13035 }
13036
13037 /* It wasn't an instruction, but it might be a register alias of the form
13038 alias .req reg. */
6c43fab6
RE
13039 if (create_register_alias (str, p))
13040 return;
b99bd4ef 13041
b99bd4ef
NC
13042 as_bad (_("bad instruction `%s'"), start);
13043}
13044
13045/* md_parse_option
13046 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 13047 See if it's a processor-specific option.
03b1477f
RE
13048
13049 This routine is somewhat complicated by the need for backwards
13050 compatibility (since older releases of gcc can't be changed).
13051 The new options try to make the interface as compatible as
13052 possible with GCC.
13053
13054 New options (supported) are:
13055
13056 -mcpu=<cpu name> Assemble for selected processor
13057 -march=<architecture name> Assemble for selected architecture
13058 -mfpu=<fpu architecture> Assemble for selected FPU.
13059 -EB/-mbig-endian Big-endian
13060 -EL/-mlittle-endian Little-endian
13061 -k Generate PIC code
13062 -mthumb Start in Thumb mode
13063 -mthumb-interwork Code supports ARM/Thumb interworking
13064
3d0c9500 13065 For now we will also provide support for:
03b1477f
RE
13066
13067 -mapcs-32 32-bit Program counter
13068 -mapcs-26 26-bit Program counter
13069 -macps-float Floats passed in FP registers
13070 -mapcs-reentrant Reentrant code
13071 -matpcs
13072 (sometime these will probably be replaced with -mapcs=<list of options>
13073 and -matpcs=<list of options>)
13074
13075 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13076 Cpu variants, the arm part is optional:
13077 -m[arm]1 Currently not supported.
13078 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13079 -m[arm]3 Arm 3 processor
13080 -m[arm]6[xx], Arm 6 processors
13081 -m[arm]7[xx][t][[d]m] Arm 7 processors
13082 -m[arm]8[10] Arm 8 processors
13083 -m[arm]9[20][tdmi] Arm 9 processors
13084 -mstrongarm[110[0]] StrongARM processors
13085 -mxscale XScale processors
13086 -m[arm]v[2345[t[e]]] Arm architectures
13087 -mall All (except the ARM1)
13088 FP variants:
13089 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13090 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13091 -mvfpxd VFP Single precision
13092 -mvfp All VFP
b99bd4ef 13093 -mno-fpu Disable all floating point instructions
b99bd4ef 13094
03b1477f
RE
13095 The following CPU names are recognized:
13096 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13097 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13098 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13099 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13100 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13101 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13102 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13103
13104 */
13105
5a38dc70 13106const char * md_shortopts = "m:k";
03b1477f 13107
b99bd4ef
NC
13108#ifdef ARM_BI_ENDIAN
13109#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13110#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13111#else
21f0f23a
RE
13112#if TARGET_BYTES_BIG_ENDIAN
13113#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13114#else
13115#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13116#endif
ce058b6c 13117#endif
03b1477f
RE
13118
13119struct option md_longopts[] =
13120{
13121#ifdef OPTION_EB
13122 {"EB", no_argument, NULL, OPTION_EB},
13123#endif
13124#ifdef OPTION_EL
13125 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13126#endif
13127 {NULL, no_argument, NULL, 0}
13128};
13129
13130size_t md_longopts_size = sizeof (md_longopts);
13131
03b1477f 13132struct arm_option_table
b99bd4ef 13133{
03b1477f
RE
13134 char *option; /* Option name to match. */
13135 char *help; /* Help information. */
13136 int *var; /* Variable to change. */
13137 int value; /* What to change it to. */
13138 char *deprecated; /* If non-null, print this message. */
13139};
b99bd4ef 13140
cc8a6dd0 13141struct arm_option_table arm_opts[] =
03b1477f
RE
13142{
13143 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13144 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13145 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13146 &support_interwork, 1, NULL},
13147 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13148 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13149 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13150 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13151 1, NULL},
13152 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13153 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13154 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13155 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13156 NULL},
13157
13158 /* These are recognized by the assembler, but have no affect on code. */
13159 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13160 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13161
13162 /* DON'T add any new processors to this list -- we want the whole list
13163 to go away... Add them to the processors table instead. */
13164 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13165 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13166 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13167 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13168 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13169 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13170 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13171 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13172 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13173 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13174 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13175 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13176 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13177 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13178 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13179 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13180 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13181 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13182 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13183 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13184 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13185 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13186 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13187 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13188 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13189 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13190 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13191 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13192 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13193 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13194 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13195 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13196 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13197 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13198 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13199 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13200 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13201 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13202 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13203 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13204 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13205 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13206 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13207 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13208 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13209 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13210 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13211 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13212 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13213 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13214 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13215 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13216 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13217 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13218 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13219 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13220 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13221 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13222 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13223 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13224 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13225 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13226 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13227 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13228 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13229 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13230 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13231 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13232 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13233 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13234 N_("use -mcpu=strongarm110")},
13235 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13236 N_("use -mcpu=strongarm1100")},
13237 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13238 N_("use -mcpu=strongarm1110")},
13239 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13240 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13241 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13242
13243 /* Architecture variants -- don't add any more to this list either. */
13244 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13245 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13246 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13247 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13248 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13249 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13250 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13251 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13252 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13253 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13254 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13255 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13256 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13257 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13258 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13259 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13260 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13261 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13262
13263 /* Floating point variants -- don't add any more to this list either. */
13264 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13265 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13266 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13267 {"mno-fpu", NULL, &legacy_fpu, 0,
13268 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13269
13270 {NULL, NULL, NULL, 0, NULL}
13271};
21f0f23a 13272
03b1477f
RE
13273struct arm_cpu_option_table
13274{
13275 char *name;
13276 int value;
13277 /* For some CPUs we assume an FPU unless the user explicitly sets
13278 -mfpu=... */
13279 int default_fpu;
13280};
13281
13282/* This list should, at a minimum, contain all the cpu names
13283 recognized by GCC. */
13284static struct arm_cpu_option_table arm_cpus[] =
13285{
13286 {"all", ARM_ANY, FPU_ARCH_FPA},
13287 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13288 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13289 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13290 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13291 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13292 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13293 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13294 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13295 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13296 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13297 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13298 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13299 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13300 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13301 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13302 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13303 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13305 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13307 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13308 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13309 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13310 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13312 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13314 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13315 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13316 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13317 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13318 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13319 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13320 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13321 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13322 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13323 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13324 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13325 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13326 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13327 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13328 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13329 /* For V5 or later processors we default to using VFP; but the user
13330 should really set the FPU type explicitly. */
13331 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13332 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13333 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13334 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13335 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13336 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13337 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13338 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13339 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13340 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13341 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13342 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13343 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 13344 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015
MM
13345 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13346 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13347 /* ??? XSCALE is really an architecture. */
13348 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13349 /* ??? iwmmxt is not a processor. */
e16bb312 13350 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13351 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13352 /* Maverick */
33a392fb 13353 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13354 {NULL, 0, 0}
13355};
cc8a6dd0 13356
03b1477f
RE
13357struct arm_arch_option_table
13358{
13359 char *name;
13360 int value;
13361 int default_fpu;
13362};
13363
13364/* This list should, at a minimum, contain all the architecture names
13365 recognized by GCC. */
13366static struct arm_arch_option_table arm_archs[] =
13367{
13368 {"all", ARM_ANY, FPU_ARCH_FPA},
13369 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13370 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13371 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13372 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13373 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13374 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13375 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13376 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13377 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13378 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13379 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13380 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13381 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13382 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13383 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13384 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13385 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13386 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13387 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13388 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13389 {NULL, 0, 0}
13390};
13391
13392/* ISA extensions in the co-processor space. */
13393struct arm_arch_extension_table
13394{
13395 char *name;
13396 int value;
13397};
13398
13399static struct arm_arch_extension_table arm_extensions[] =
13400{
13401 {"maverick", ARM_CEXT_MAVERICK},
13402 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13403 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13404 {NULL, 0}
13405};
b99bd4ef 13406
03b1477f
RE
13407struct arm_fpu_option_table
13408{
13409 char *name;
13410 int value;
13411};
13412
13413/* This list should, at a minimum, contain all the fpu names
13414 recognized by GCC. */
13415static struct arm_fpu_option_table arm_fpus[] =
13416{
13417 {"softfpa", FPU_NONE},
13418 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13419 {"fpe2", FPU_ARCH_FPE},
13420 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13421 {"fpa", FPU_ARCH_FPA},
13422 {"fpa10", FPU_ARCH_FPA},
13423 {"fpa11", FPU_ARCH_FPA},
13424 {"arm7500fe", FPU_ARCH_FPA},
13425 {"softvfp", FPU_ARCH_VFP},
13426 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13427 {"vfp", FPU_ARCH_VFP_V2},
13428 {"vfp9", FPU_ARCH_VFP_V2},
13429 {"vfp10", FPU_ARCH_VFP_V2},
13430 {"vfp10-r0", FPU_ARCH_VFP_V1},
13431 {"vfpxd", FPU_ARCH_VFP_V1xD},
13432 {"arm1020t", FPU_ARCH_VFP_V1},
13433 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13434 {"arm1136jfs", FPU_ARCH_VFP_V2},
33a392fb
PB
13435 {"maverick", FPU_ARCH_MAVERICK},
13436 {NULL, 0}
13437};
13438
13439struct arm_float_abi_option_table
13440{
13441 char *name;
13442 int value;
13443};
13444
13445static struct arm_float_abi_option_table arm_float_abis[] =
13446{
13447 {"hard", ARM_FLOAT_ABI_HARD},
13448 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13449 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13450 {NULL, 0}
13451};
13452
13453struct arm_long_option_table
13454{
13455 char *option; /* Substring to match. */
13456 char *help; /* Help information. */
13457 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13458 char *deprecated; /* If non-null, print this message. */
13459};
13460
13461static int
13462arm_parse_extension (str, opt_p)
13463 char *str;
13464 int *opt_p;
13465{
13466 while (str != NULL && *str != 0)
13467 {
13468 struct arm_arch_extension_table *opt;
13469 char *ext;
13470 int optlen;
13471
13472 if (*str != '+')
b99bd4ef 13473 {
03b1477f
RE
13474 as_bad (_("invalid architectural extension"));
13475 return 0;
13476 }
b99bd4ef 13477
03b1477f
RE
13478 str++;
13479 ext = strchr (str, '+');
b99bd4ef 13480
03b1477f
RE
13481 if (ext != NULL)
13482 optlen = ext - str;
13483 else
13484 optlen = strlen (str);
b99bd4ef 13485
03b1477f
RE
13486 if (optlen == 0)
13487 {
13488 as_bad (_("missing architectural extension"));
13489 return 0;
13490 }
b99bd4ef 13491
03b1477f
RE
13492 for (opt = arm_extensions; opt->name != NULL; opt++)
13493 if (strncmp (opt->name, str, optlen) == 0)
13494 {
13495 *opt_p |= opt->value;
13496 break;
13497 }
bfae80f2 13498
03b1477f
RE
13499 if (opt->name == NULL)
13500 {
13501 as_bad (_("unknown architectural extnsion `%s'"), str);
13502 return 0;
13503 }
b99bd4ef 13504
03b1477f
RE
13505 str = ext;
13506 };
b99bd4ef 13507
03b1477f
RE
13508 return 1;
13509}
b99bd4ef 13510
03b1477f
RE
13511static int
13512arm_parse_cpu (str)
13513 char *str;
13514{
13515 struct arm_cpu_option_table *opt;
13516 char *ext = strchr (str, '+');
13517 int optlen;
b99bd4ef 13518
03b1477f
RE
13519 if (ext != NULL)
13520 optlen = ext - str;
13521 else
13522 optlen = strlen (str);
b99bd4ef 13523
03b1477f
RE
13524 if (optlen == 0)
13525 {
13526 as_bad (_("missing cpu name `%s'"), str);
13527 return 0;
13528 }
b99bd4ef 13529
03b1477f
RE
13530 for (opt = arm_cpus; opt->name != NULL; opt++)
13531 if (strncmp (opt->name, str, optlen) == 0)
13532 {
13533 mcpu_cpu_opt = opt->value;
13534 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13535
03b1477f
RE
13536 if (ext != NULL)
13537 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13538
03b1477f
RE
13539 return 1;
13540 }
b99bd4ef 13541
03b1477f
RE
13542 as_bad (_("unknown cpu `%s'"), str);
13543 return 0;
13544}
b99bd4ef 13545
03b1477f
RE
13546static int
13547arm_parse_arch (str)
13548 char *str;
13549{
13550 struct arm_arch_option_table *opt;
13551 char *ext = strchr (str, '+');
13552 int optlen;
b99bd4ef 13553
03b1477f
RE
13554 if (ext != NULL)
13555 optlen = ext - str;
13556 else
13557 optlen = strlen (str);
b99bd4ef 13558
03b1477f
RE
13559 if (optlen == 0)
13560 {
13561 as_bad (_("missing architecture name `%s'"), str);
13562 return 0;
13563 }
b99bd4ef 13564
b99bd4ef 13565
03b1477f
RE
13566 for (opt = arm_archs; opt->name != NULL; opt++)
13567 if (strcmp (opt->name, str) == 0)
13568 {
13569 march_cpu_opt = opt->value;
13570 march_fpu_opt = opt->default_fpu;
b99bd4ef 13571
03b1477f
RE
13572 if (ext != NULL)
13573 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13574
03b1477f
RE
13575 return 1;
13576 }
b99bd4ef 13577
03b1477f
RE
13578 as_bad (_("unknown architecture `%s'\n"), str);
13579 return 0;
13580}
13581
13582static int
13583arm_parse_fpu (str)
13584 char *str;
13585{
13586 struct arm_fpu_option_table *opt;
b99bd4ef 13587
03b1477f
RE
13588 for (opt = arm_fpus; opt->name != NULL; opt++)
13589 if (strcmp (opt->name, str) == 0)
13590 {
13591 mfpu_opt = opt->value;
13592 return 1;
13593 }
b99bd4ef 13594
03b1477f
RE
13595 as_bad (_("unknown floating point format `%s'\n"), str);
13596 return 0;
13597}
b99bd4ef 13598
33a392fb
PB
13599static int
13600arm_parse_float_abi (str)
13601 char * str;
13602{
13603 struct arm_float_abi_option_table *opt;
13604
13605 for (opt = arm_float_abis; opt->name != NULL; opt++)
13606 if (strcmp (opt->name, str) == 0)
13607 {
13608 mfloat_abi_opt = opt->value;
13609 return 1;
13610 }
13611
13612 as_bad (_("unknown floating point abi `%s'\n"), str);
13613 return 0;
13614}
13615
03b1477f
RE
13616struct arm_long_option_table arm_long_opts[] =
13617{
13618 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13619 arm_parse_cpu, NULL},
13620 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13621 arm_parse_arch, NULL},
13622 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13623 arm_parse_fpu, NULL},
33a392fb
PB
13624 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13625 arm_parse_float_abi, NULL},
03b1477f
RE
13626 {NULL, NULL, 0, NULL}
13627};
b99bd4ef 13628
03b1477f
RE
13629int
13630md_parse_option (c, arg)
13631 int c;
13632 char * arg;
13633{
13634 struct arm_option_table *opt;
13635 struct arm_long_option_table *lopt;
b99bd4ef 13636
03b1477f
RE
13637 switch (c)
13638 {
13639#ifdef OPTION_EB
13640 case OPTION_EB:
13641 target_big_endian = 1;
b99bd4ef 13642 break;
03b1477f 13643#endif
b99bd4ef 13644
03b1477f
RE
13645#ifdef OPTION_EL
13646 case OPTION_EL:
13647 target_big_endian = 0;
b99bd4ef
NC
13648 break;
13649#endif
13650
03b1477f 13651 case 'a':
cc8a6dd0 13652 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13653 ones. */
13654 return 0;
13655
b99bd4ef 13656 default:
03b1477f
RE
13657 for (opt = arm_opts; opt->option != NULL; opt++)
13658 {
13659 if (c == opt->option[0]
13660 && ((arg == NULL && opt->option[1] == 0)
13661 || strcmp (arg, opt->option + 1) == 0))
13662 {
13663#if WARN_DEPRECATED
13664 /* If the option is deprecated, tell the user. */
13665 if (opt->deprecated != NULL)
13666 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13667 arg ? arg : "", _(opt->deprecated));
13668#endif
13669
13670 if (opt->var != NULL)
13671 *opt->var = opt->value;
13672
13673 return 1;
13674 }
13675 }
13676
13677 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13678 {
cc8a6dd0 13679 /* These options are expected to have an argument. */
03b1477f
RE
13680 if (c == lopt->option[0]
13681 && arg != NULL
cc8a6dd0 13682 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13683 strlen (lopt->option + 1)) == 0)
13684 {
13685#if WARN_DEPRECATED
13686 /* If the option is deprecated, tell the user. */
13687 if (lopt->deprecated != NULL)
13688 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13689 _(lopt->deprecated));
13690#endif
13691
13692 /* Call the sup-option parser. */
13693 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13694 }
13695 }
13696
13697 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
13698 return 0;
13699 }
13700
13701 return 1;
13702}
13703
13704void
13705md_show_usage (fp)
13706 FILE * fp;
13707{
03b1477f
RE
13708 struct arm_option_table *opt;
13709 struct arm_long_option_table *lopt;
13710
13711 fprintf (fp, _(" ARM-specific assembler options:\n"));
13712
13713 for (opt = arm_opts; opt->option != NULL; opt++)
13714 if (opt->help != NULL)
13715 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13716
13717 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13718 if (lopt->help != NULL)
13719 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13720
13721#ifdef OPTION_EB
b99bd4ef 13722 fprintf (fp, _("\
03b1477f 13723 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13724#endif
03b1477f
RE
13725
13726#ifdef OPTION_EL
b99bd4ef 13727 fprintf (fp, _("\
03b1477f 13728 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13729#endif
13730}
13731
13732/* We need to be able to fix up arbitrary expressions in some statements.
13733 This is so that we can handle symbols that are an arbitrary distance from
13734 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13735 which returns part of an address in a form which will be valid for
13736 a data instruction. We do this by pushing the expression into a symbol
13737 in the expr_section, and creating a fix for that. */
13738
13739static void
13740fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13741 fragS * frag;
13742 int where;
13743 short int size;
13744 expressionS * exp;
13745 int pc_rel;
13746 int reloc;
13747{
13748 fixS * new_fix;
13749 arm_fix_data * arm_data;
13750
13751 switch (exp->X_op)
13752 {
13753 case O_constant:
13754 case O_symbol:
13755 case O_add:
13756 case O_subtract:
13757 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13758 break;
13759
13760 default:
13761 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13762 pc_rel, reloc);
13763 break;
13764 }
13765
13766 /* Mark whether the fix is to a THUMB instruction, or an ARM
13767 instruction. */
13768 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13769 new_fix->tc_fix_data = (PTR) arm_data;
13770 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13771}
13772
13773/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13774
13775void
13776cons_fix_new_arm (frag, where, size, exp)
13777 fragS * frag;
13778 int where;
13779 int size;
13780 expressionS * exp;
13781{
13782 bfd_reloc_code_real_type type;
13783 int pcrel = 0;
13784
13785 /* Pick a reloc.
13786 FIXME: @@ Should look at CPU word size. */
13787 switch (size)
13788 {
13789 case 1:
13790 type = BFD_RELOC_8;
13791 break;
13792 case 2:
13793 type = BFD_RELOC_16;
13794 break;
13795 case 4:
13796 default:
13797 type = BFD_RELOC_32;
13798 break;
13799 case 8:
13800 type = BFD_RELOC_64;
13801 break;
13802 }
13803
13804 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13805}
13806
13807/* A good place to do this, although this was probably not intended
13808 for this kind of use. We need to dump the literal pool before
13809 references are made to a null symbol pointer. */
13810
13811void
13812arm_cleanup ()
13813{
3d0c9500 13814 literal_pool * pool;
b99bd4ef 13815
3d0c9500
NC
13816 for (pool = list_of_pools; pool; pool = pool->next)
13817 {
13818 /* Put it at the end of the relevent section. */
13819 subseg_set (pool->section, pool->sub_section);
13820 s_ltorg (0);
13821 }
b99bd4ef
NC
13822}
13823
13824void
13825arm_start_line_hook ()
13826{
13827 last_label_seen = NULL;
13828}
13829
13830void
13831arm_frob_label (sym)
13832 symbolS * sym;
13833{
13834 last_label_seen = sym;
13835
13836 ARM_SET_THUMB (sym, thumb_mode);
13837
13838#if defined OBJ_COFF || defined OBJ_ELF
13839 ARM_SET_INTERWORK (sym, support_interwork);
13840#endif
13841
13842 /* Note - do not allow local symbols (.Lxxx) to be labeled
13843 as Thumb functions. This is because these labels, whilst
13844 they exist inside Thumb code, are not the entry points for
13845 possible ARM->Thumb calls. Also, these labels can be used
13846 as part of a computed goto or switch statement. eg gcc
13847 can generate code that looks like this:
13848
13849 ldr r2, [pc, .Laaa]
13850 lsl r3, r3, #2
13851 ldr r2, [r3, r2]
13852 mov pc, r2
cc8a6dd0 13853
b99bd4ef
NC
13854 .Lbbb: .word .Lxxx
13855 .Lccc: .word .Lyyy
13856 ..etc...
13857 .Laaa: .word Lbbb
13858
13859 The first instruction loads the address of the jump table.
13860 The second instruction converts a table index into a byte offset.
13861 The third instruction gets the jump address out of the table.
13862 The fourth instruction performs the jump.
cc8a6dd0 13863
b99bd4ef
NC
13864 If the address stored at .Laaa is that of a symbol which has the
13865 Thumb_Func bit set, then the linker will arrange for this address
13866 to have the bottom bit set, which in turn would mean that the
13867 address computation performed by the third instruction would end
13868 up with the bottom bit set. Since the ARM is capable of unaligned
13869 word loads, the instruction would then load the incorrect address
13870 out of the jump table, and chaos would ensue. */
13871 if (label_is_thumb_function_name
13872 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13873 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13874 {
13875 /* When the address of a Thumb function is taken the bottom
13876 bit of that address should be set. This will allow
13877 interworking between Arm and Thumb functions to work
13878 correctly. */
13879
13880 THUMB_SET_FUNC (sym, 1);
13881
b34976b6 13882 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13883 }
13884}
13885
13886/* Adjust the symbol table. This marks Thumb symbols as distinct from
13887 ARM ones. */
13888
13889void
13890arm_adjust_symtab ()
13891{
13892#ifdef OBJ_COFF
13893 symbolS * sym;
13894
13895 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13896 {
13897 if (ARM_IS_THUMB (sym))
13898 {
13899 if (THUMB_IS_FUNC (sym))
13900 {
13901 /* Mark the symbol as a Thumb function. */
13902 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13903 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13904 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13905
13906 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13907 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13908 else
13909 as_bad (_("%s: unexpected function type: %d"),
13910 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13911 }
cc8a6dd0 13912 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13913 {
13914 case C_EXT:
13915 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13916 break;
13917 case C_STAT:
13918 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13919 break;
13920 case C_LABEL:
13921 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13922 break;
13923 default:
13924 /* Do nothing. */
13925 break;
13926 }
13927 }
13928
13929 if (ARM_IS_INTERWORK (sym))
13930 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13931 }
13932#endif
13933#ifdef OBJ_ELF
13934 symbolS * sym;
13935 char bind;
13936
13937 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13938 {
13939 if (ARM_IS_THUMB (sym))
13940 {
13941 elf_symbol_type * elf_sym;
13942
13943 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13944 bind = ELF_ST_BIND (elf_sym);
13945
13946 /* If it's a .thumb_func, declare it as so,
13947 otherwise tag label as .code 16. */
13948 if (THUMB_IS_FUNC (sym))
13949 elf_sym->internal_elf_sym.st_info =
13950 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13951 else
13952 elf_sym->internal_elf_sym.st_info =
13953 ELF_ST_INFO (bind, STT_ARM_16BIT);
13954 }
13955 }
13956#endif
13957}
13958
13959int
13960arm_data_in_code ()
13961{
13962 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13963 {
13964 *input_line_pointer = '/';
13965 input_line_pointer += 5;
13966 *input_line_pointer = 0;
13967 return 1;
13968 }
13969
13970 return 0;
13971}
13972
13973char *
13974arm_canonicalize_symbol_name (name)
13975 char * name;
13976{
13977 int len;
13978
13979 if (thumb_mode && (len = strlen (name)) > 5
13980 && streq (name + len - 5, "/data"))
13981 *(name + len - 5) = 0;
13982
13983 return name;
13984}
13985
bfc866a6 13986#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13987void
b99bd4ef
NC
13988arm_validate_fix (fixP)
13989 fixS * fixP;
13990{
13991 /* If the destination of the branch is a defined symbol which does not have
13992 the THUMB_FUNC attribute, then we must be calling a function which has
13993 the (interfacearm) attribute. We look for the Thumb entry point to that
13994 function and change the branch to refer to that function instead. */
13995 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13996 && fixP->fx_addsy != NULL
13997 && S_IS_DEFINED (fixP->fx_addsy)
13998 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13999 {
14000 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 14001 }
b99bd4ef 14002}
bfc866a6 14003#endif
b99bd4ef 14004
114424c6
AM
14005int
14006arm_force_relocation (fixp)
14007 struct fix * fixp;
14008{
14009#if defined (OBJ_COFF) && defined (TE_PE)
14010 if (fixp->fx_r_type == BFD_RELOC_RVA)
14011 return 1;
14012#endif
14013#ifdef OBJ_ELF
ae6063d4 14014 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
14015 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14016 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14017 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14018 return 1;
14019#endif
14020
14021 /* Resolve these relocations even if the symbol is extern or weak. */
14022 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 14023 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
14024 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14025 return 0;
14026
ae6063d4 14027 return generic_force_reloc (fixp);
114424c6
AM
14028}
14029
b99bd4ef
NC
14030#ifdef OBJ_COFF
14031/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14032 local labels from being added to the output symbol table when they
14033 are used with the ADRL pseudo op. The ADRL relocation should always
14034 be resolved before the binbary is emitted, so it is safe to say that
14035 it is adjustable. */
14036
b34976b6 14037bfd_boolean
b99bd4ef
NC
14038arm_fix_adjustable (fixP)
14039 fixS * fixP;
14040{
14041 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14042 return 1;
14043 return 0;
14044}
14045#endif
114424c6 14046
b99bd4ef
NC
14047#ifdef OBJ_ELF
14048/* Relocations against Thumb function names must be left unadjusted,
14049 so that the linker can use this information to correctly set the
14050 bottom bit of their addresses. The MIPS version of this function
14051 also prevents relocations that are mips-16 specific, but I do not
14052 know why it does this.
14053
14054 FIXME:
14055 There is one other problem that ought to be addressed here, but
14056 which currently is not: Taking the address of a label (rather
14057 than a function) and then later jumping to that address. Such
14058 addresses also ought to have their bottom bit set (assuming that
14059 they reside in Thumb code), but at the moment they will not. */
14060
b34976b6 14061bfd_boolean
b99bd4ef
NC
14062arm_fix_adjustable (fixP)
14063 fixS * fixP;
14064{
14065 if (fixP->fx_addsy == NULL)
14066 return 1;
14067
b99bd4ef
NC
14068 if (THUMB_IS_FUNC (fixP->fx_addsy)
14069 && fixP->fx_subsy == NULL)
14070 return 0;
14071
14072 /* We need the symbol name for the VTABLE entries. */
14073 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14074 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14075 return 0;
14076
a161fe53
AM
14077 /* Don't allow symbols to be discarded on GOT related relocs. */
14078 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14079 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14080 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14081 return 0;
14082
b99bd4ef
NC
14083 return 1;
14084}
14085
14086const char *
14087elf32_arm_target_format ()
14088{
14089 if (target_big_endian)
14090 {
14091 if (target_oabi)
14092 return "elf32-bigarm-oabi";
14093 else
14094 return "elf32-bigarm";
14095 }
14096 else
14097 {
14098 if (target_oabi)
14099 return "elf32-littlearm-oabi";
14100 else
14101 return "elf32-littlearm";
14102 }
14103}
14104
14105void
14106armelf_frob_symbol (symp, puntp)
14107 symbolS * symp;
14108 int * puntp;
14109{
14110 elf_frob_symbol (symp, puntp);
14111}
14112
b99bd4ef
NC
14113static bfd_reloc_code_real_type
14114arm_parse_reloc ()
14115{
14116 char id [16];
14117 char * ip;
14118 unsigned int i;
14119 static struct
14120 {
14121 char * str;
14122 int len;
14123 bfd_reloc_code_real_type reloc;
14124 }
14125 reloc_map[] =
14126 {
14127#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14128 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14129 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14130 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14131 branch instructions generated by GCC for PLT relocs. */
14132 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14133 { NULL, 0, BFD_RELOC_UNUSED }
14134#undef MAP
14135 };
14136
14137 for (i = 0, ip = input_line_pointer;
3882b010 14138 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14139 i++, ip++)
3882b010 14140 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14141
14142 for (i = 0; reloc_map[i].str; i++)
14143 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14144 break;
14145
14146 input_line_pointer += reloc_map[i].len;
14147
14148 return reloc_map[i].reloc;
14149}
14150
14151static void
14152s_arm_elf_cons (nbytes)
14153 int nbytes;
14154{
14155 expressionS exp;
14156
14157#ifdef md_flush_pending_output
14158 md_flush_pending_output ();
14159#endif
14160
14161 if (is_it_end_of_statement ())
14162 {
14163 demand_empty_rest_of_line ();
14164 return;
14165 }
14166
14167#ifdef md_cons_align
14168 md_cons_align (nbytes);
14169#endif
14170
6057a28f 14171 mapping_state (MAP_DATA);
b99bd4ef
NC
14172 do
14173 {
14174 bfd_reloc_code_real_type reloc;
14175
14176 expression (& exp);
14177
14178 if (exp.X_op == O_symbol
14179 && * input_line_pointer == '('
14180 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14181 {
14182 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14183 int size = bfd_get_reloc_size (howto);
14184
14185 if (size > nbytes)
14186 as_bad ("%s relocations do not fit in %d bytes",
14187 howto->name, nbytes);
14188 else
14189 {
14190 register char *p = frag_more ((int) nbytes);
14191 int offset = nbytes - size;
14192
14193 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14194 &exp, 0, reloc);
14195 }
14196 }
14197 else
14198 emit_expr (&exp, (unsigned int) nbytes);
14199 }
14200 while (*input_line_pointer++ == ',');
14201
14202 /* Put terminator back into stream. */
14203 input_line_pointer --;
14204 demand_empty_rest_of_line ();
14205}
14206
14207#endif /* OBJ_ELF */
14208
14209/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14210 of an rs_align_code fragment. */
14211
14212void
14213arm_handle_align (fragP)
14214 fragS *fragP;
14215{
14216 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14217 static char const thumb_noop[2] = { 0xc0, 0x46 };
14218 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14219 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14220
14221 int bytes, fix, noop_size;
14222 char * p;
14223 const char * noop;
cc8a6dd0 14224
b99bd4ef
NC
14225 if (fragP->fr_type != rs_align_code)
14226 return;
14227
14228 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14229 p = fragP->fr_literal + fragP->fr_fix;
14230 fix = 0;
cc8a6dd0 14231
b99bd4ef
NC
14232 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14233 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14234
b99bd4ef
NC
14235 if (fragP->tc_frag_data)
14236 {
14237 if (target_big_endian)
14238 noop = thumb_bigend_noop;
14239 else
14240 noop = thumb_noop;
14241 noop_size = sizeof (thumb_noop);
14242 }
14243 else
14244 {
14245 if (target_big_endian)
14246 noop = arm_bigend_noop;
14247 else
14248 noop = arm_noop;
14249 noop_size = sizeof (arm_noop);
14250 }
cc8a6dd0 14251
b99bd4ef
NC
14252 if (bytes & (noop_size - 1))
14253 {
14254 fix = bytes & (noop_size - 1);
14255 memset (p, 0, fix);
14256 p += fix;
14257 bytes -= fix;
14258 }
14259
14260 while (bytes >= noop_size)
14261 {
14262 memcpy (p, noop, noop_size);
14263 p += noop_size;
14264 bytes -= noop_size;
14265 fix += noop_size;
14266 }
cc8a6dd0 14267
b99bd4ef
NC
14268 fragP->fr_fix += fix;
14269 fragP->fr_var = noop_size;
14270}
14271
14272/* Called from md_do_align. Used to create an alignment
14273 frag in a code section. */
14274
14275void
14276arm_frag_align_code (n, max)
14277 int n;
14278 int max;
14279{
14280 char * p;
14281
2d2255b5 14282 /* We assume that there will never be a requirement
b99bd4ef
NC
14283 to support alignments greater than 32 bytes. */
14284 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14285 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14286
b99bd4ef
NC
14287 p = frag_var (rs_align_code,
14288 MAX_MEM_FOR_RS_ALIGN_CODE,
14289 1,
14290 (relax_substateT) max,
14291 (symbolS *) NULL,
14292 (offsetT) n,
14293 (char *) NULL);
14294 *p = 0;
14295
14296}
14297
14298/* Perform target specific initialisation of a frag. */
14299
14300void
14301arm_init_frag (fragP)
14302 fragS *fragP;
14303{
14304 /* Record whether this frag is in an ARM or a THUMB area. */
14305 fragP->tc_frag_data = thumb_mode;
14306}