]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
* bfd/elf32-arm.h (arm_print_private_bfd_data): Add EABI v3.
[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;
d507cf36 194static int meabi_flags = EF_ARM_EABI_UNKNOWN;
b99bd4ef
NC
195
196/* This array holds the chars that always start a comment. If the
197 pre-processor is disabled, these aren't very useful. */
f57c81f6 198const char comment_chars[] = "@";
b99bd4ef
NC
199
200/* This array holds the chars that only start a comment at the beginning of
201 a line. If the line seems to have the form '# 123 filename'
202 .line and .file directives will appear in the pre-processed output. */
203/* Note that input_file.c hand checks for '#' at the beginning of the
204 first line of the input file. This is because the compiler outputs
205 #NO_APP at the beginning of its output. */
206/* Also note that comments like this one will always work. */
05d2d07e 207const char line_comment_chars[] = "#";
b99bd4ef 208
da89cce1 209const char line_separator_chars[] = ";";
b99bd4ef
NC
210
211/* Chars that can be used to separate mant
212 from exp in floating point numbers. */
05d2d07e 213const char EXP_CHARS[] = "eE";
b99bd4ef
NC
214
215/* Chars that mean this number is a floating point constant. */
216/* As in 0f12.456 */
217/* or 0d1.2345e12 */
218
05d2d07e 219const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
220
221/* Prefix characters that indicate the start of an immediate
222 value. */
223#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
224
225#ifdef OBJ_ELF
226/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
227symbolS * GOT_symbol;
228#endif
229
230/* Size of relocation record. */
05d2d07e 231const int md_reloc_size = 8;
b99bd4ef
NC
232
233/* 0: assemble for ARM,
234 1: assemble for Thumb,
235 2: assemble for Thumb even though target CPU does not support thumb
236 instructions. */
237static int thumb_mode = 0;
238
239typedef struct arm_fix
240{
241 int thumb_mode;
242} arm_fix_data;
243
244struct arm_it
245{
05d2d07e 246 const char * error;
b99bd4ef 247 unsigned long instruction;
b99bd4ef
NC
248 int size;
249 struct
250 {
251 bfd_reloc_code_real_type type;
252 expressionS exp;
253 int pc_rel;
254 } reloc;
255};
256
257struct arm_it inst;
258
259enum asm_shift_index
260{
261 SHIFT_LSL = 0,
262 SHIFT_LSR,
263 SHIFT_ASR,
264 SHIFT_ROR,
265 SHIFT_RRX
266};
267
268struct asm_shift_properties
269{
270 enum asm_shift_index index;
271 unsigned long bit_field;
272 unsigned int allows_0 : 1;
273 unsigned int allows_32 : 1;
274};
275
276static const struct asm_shift_properties shift_properties [] =
277{
278 { SHIFT_LSL, 0, 1, 0},
279 { SHIFT_LSR, 0x20, 0, 1},
280 { SHIFT_ASR, 0x40, 0, 1},
281 { SHIFT_ROR, 0x60, 0, 0},
282 { SHIFT_RRX, 0x60, 0, 0}
283};
284
285struct asm_shift_name
286{
287 const char * name;
288 const struct asm_shift_properties * properties;
289};
290
291static const struct asm_shift_name shift_names [] =
292{
293 { "asl", shift_properties + SHIFT_LSL },
294 { "lsl", shift_properties + SHIFT_LSL },
295 { "lsr", shift_properties + SHIFT_LSR },
296 { "asr", shift_properties + SHIFT_ASR },
297 { "ror", shift_properties + SHIFT_ROR },
298 { "rrx", shift_properties + SHIFT_RRX },
299 { "ASL", shift_properties + SHIFT_LSL },
300 { "LSL", shift_properties + SHIFT_LSL },
301 { "LSR", shift_properties + SHIFT_LSR },
302 { "ASR", shift_properties + SHIFT_ASR },
303 { "ROR", shift_properties + SHIFT_ROR },
304 { "RRX", shift_properties + SHIFT_RRX }
305};
306
09d92015 307/* Any kind of shift is accepted. */
b99bd4ef 308#define NO_SHIFT_RESTRICT 1
09d92015
MM
309/* The shift operand must be an immediate value, not a register. */
310#define SHIFT_IMMEDIATE 0
311/* The shift must be LSL or ASR and the operand must be an immediate. */
312#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
313/* The shift must be ASR and the operand must be an immediate. */
314#define SHIFT_ASR_IMMEDIATE 3
315/* The shift must be LSL and the operand must be an immediate. */
316#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
317
318#define NUM_FLOAT_VALS 8
319
05d2d07e 320const char * fp_const[] =
b99bd4ef
NC
321{
322 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
323};
324
325/* Number of littlenums required to hold an extended precision number. */
326#define MAX_LITTLENUMS 6
327
328LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
329
330#define FAIL (-1)
331#define SUCCESS (0)
332
bfae80f2
RE
333/* Whether a Co-processor load/store operation accepts write-back forms. */
334#define CP_WB_OK 1
335#define CP_NO_WB 0
336
b99bd4ef
NC
337#define SUFF_S 1
338#define SUFF_D 2
339#define SUFF_E 3
340#define SUFF_P 4
341
342#define CP_T_X 0x00008000
343#define CP_T_Y 0x00400000
344#define CP_T_Pre 0x01000000
345#define CP_T_UD 0x00800000
346#define CP_T_WB 0x00200000
347
348#define CONDS_BIT 0x00100000
349#define LOAD_BIT 0x00100000
b99bd4ef
NC
350
351#define DOUBLE_LOAD_FLAG 0x00000001
352
353struct asm_cond
354{
05d2d07e 355 const char * template;
b99bd4ef
NC
356 unsigned long value;
357};
358
b99bd4ef 359#define COND_ALWAYS 0xe0000000
90e4755a 360#define COND_MASK 0xf0000000
b99bd4ef 361
05d2d07e 362static const struct asm_cond conds[] =
b99bd4ef
NC
363{
364 {"eq", 0x00000000},
365 {"ne", 0x10000000},
366 {"cs", 0x20000000}, {"hs", 0x20000000},
367 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
368 {"mi", 0x40000000},
369 {"pl", 0x50000000},
370 {"vs", 0x60000000},
371 {"vc", 0x70000000},
372 {"hi", 0x80000000},
373 {"ls", 0x90000000},
374 {"ge", 0xa0000000},
375 {"lt", 0xb0000000},
376 {"gt", 0xc0000000},
377 {"le", 0xd0000000},
378 {"al", 0xe0000000},
379 {"nv", 0xf0000000}
380};
381
b99bd4ef
NC
382struct asm_psr
383{
b34976b6
AM
384 const char *template;
385 bfd_boolean cpsr;
b99bd4ef
NC
386 unsigned long field;
387};
388
2d2255b5 389/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
390#define SPSR_BIT (1 << 22)
391
392/* How many bits to shift the PSR_xxx bits up by. */
393#define PSR_SHIFT 16
394
395#define PSR_c (1 << 0)
396#define PSR_x (1 << 1)
397#define PSR_s (1 << 2)
398#define PSR_f (1 << 3)
399
05d2d07e 400static const struct asm_psr psrs[] =
b99bd4ef 401{
b34976b6
AM
402 {"CPSR", TRUE, PSR_c | PSR_f},
403 {"CPSR_all", TRUE, PSR_c | PSR_f},
404 {"SPSR", FALSE, PSR_c | PSR_f},
405 {"SPSR_all", FALSE, PSR_c | PSR_f},
406 {"CPSR_flg", TRUE, PSR_f},
407 {"CPSR_f", TRUE, PSR_f},
408 {"SPSR_flg", FALSE, PSR_f},
409 {"SPSR_f", FALSE, PSR_f},
410 {"CPSR_c", TRUE, PSR_c},
411 {"CPSR_ctl", TRUE, PSR_c},
412 {"SPSR_c", FALSE, PSR_c},
413 {"SPSR_ctl", FALSE, PSR_c},
414 {"CPSR_x", TRUE, PSR_x},
415 {"CPSR_s", TRUE, PSR_s},
416 {"SPSR_x", FALSE, PSR_x},
417 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 418 /* Combinations of flags. */
b34976b6
AM
419 {"CPSR_fs", TRUE, PSR_f | PSR_s},
420 {"CPSR_fx", TRUE, PSR_f | PSR_x},
421 {"CPSR_fc", TRUE, PSR_f | PSR_c},
422 {"CPSR_sf", TRUE, PSR_s | PSR_f},
423 {"CPSR_sx", TRUE, PSR_s | PSR_x},
424 {"CPSR_sc", TRUE, PSR_s | PSR_c},
425 {"CPSR_xf", TRUE, PSR_x | PSR_f},
426 {"CPSR_xs", TRUE, PSR_x | PSR_s},
427 {"CPSR_xc", TRUE, PSR_x | PSR_c},
428 {"CPSR_cf", TRUE, PSR_c | PSR_f},
429 {"CPSR_cs", TRUE, PSR_c | PSR_s},
430 {"CPSR_cx", TRUE, PSR_c | PSR_x},
431 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
432 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
433 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
434 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
435 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
436 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
437 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
438 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
439 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
440 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
441 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
442 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
443 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
444 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
445 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
446 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
447 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
448 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
449 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
450 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
451 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
452 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
453 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
454 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
455 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
456 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
457 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
458 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
459 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
460 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
461 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
462 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
463 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
464 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
465 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
466 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
467 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
468 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
469 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
470 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
471 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
472 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
473 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
474 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
475 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
476 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
477 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
478 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
479 {"SPSR_fs", FALSE, PSR_f | PSR_s},
480 {"SPSR_fx", FALSE, PSR_f | PSR_x},
481 {"SPSR_fc", FALSE, PSR_f | PSR_c},
482 {"SPSR_sf", FALSE, PSR_s | PSR_f},
483 {"SPSR_sx", FALSE, PSR_s | PSR_x},
484 {"SPSR_sc", FALSE, PSR_s | PSR_c},
485 {"SPSR_xf", FALSE, PSR_x | PSR_f},
486 {"SPSR_xs", FALSE, PSR_x | PSR_s},
487 {"SPSR_xc", FALSE, PSR_x | PSR_c},
488 {"SPSR_cf", FALSE, PSR_c | PSR_f},
489 {"SPSR_cs", FALSE, PSR_c | PSR_s},
490 {"SPSR_cx", FALSE, PSR_c | PSR_x},
491 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
492 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
493 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
494 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
495 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
496 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
497 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
498 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
499 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
500 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
501 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
502 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
503 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
504 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
505 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
506 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
507 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
508 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
509 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
510 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
511 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
512 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
513 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
514 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
515 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
516 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
517 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
518 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
519 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
520 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
521 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
522 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
523 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
524 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
525 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
526 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
527 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
528 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
529 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
530 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
531 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
532 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
533 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
534 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
535 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
536 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
537 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
538 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
539};
540
e16bb312
NC
541enum wreg_type
542 {
543 IWMMXT_REG_WR = 0,
544 IWMMXT_REG_WC = 1,
545 IWMMXT_REG_WR_OR_WC = 2,
546 IWMMXT_REG_WCG
547 };
548
549enum iwmmxt_insn_type
550{
551 check_rd,
552 check_wr,
553 check_wrwr,
554 check_wrwrwr,
555 check_wrwrwcg,
556 check_tbcst,
557 check_tmovmsk,
558 check_tmia,
559 check_tmcrr,
560 check_tmrrc,
561 check_tmcr,
562 check_tmrc,
563 check_tinsr,
564 check_textrc,
565 check_waligni,
566 check_textrm,
567 check_wshufh
568};
569
bfae80f2
RE
570enum vfp_dp_reg_pos
571{
572 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
573};
574
575enum vfp_sp_reg_pos
576{
577 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
578};
579
580enum vfp_ldstm_type
581{
582 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
583};
584
585/* VFP system registers. */
586struct vfp_reg
587{
588 const char *name;
589 unsigned long regno;
590};
591
cc8a6dd0 592static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
593{
594 {"fpsid", 0x00000000},
595 {"FPSID", 0x00000000},
596 {"fpscr", 0x00010000},
597 {"FPSCR", 0x00010000},
598 {"fpexc", 0x00080000},
599 {"FPEXC", 0x00080000}
600};
601
6c43fab6
RE
602/* Structure for a hash table entry for a register. */
603struct reg_entry
604{
605 const char * name;
606 int number;
0bbf2aa4 607 bfd_boolean builtin;
6c43fab6
RE
608};
609
e28cd48c 610/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
611#define REG_SP 13
612#define REG_LR 14
613#define REG_PC 15
614
e16bb312
NC
615#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
616#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
617#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
618
0bbf2aa4
NC
619/* These are the standard names. Users can add aliases with .req.
620 and delete them with .unreq. */
621
6c43fab6
RE
622/* Integer Register Numbers. */
623static const struct reg_entry rn_table[] =
624{
0bbf2aa4
NC
625 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
626 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
627 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
628 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 629 /* ATPCS Synonyms. */
0bbf2aa4
NC
630 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
631 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
632 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 633 /* Well-known aliases. */
0bbf2aa4
NC
634 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
635 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
636 {NULL, 0, TRUE}
6c43fab6
RE
637};
638
e16bb312
NC
639#define WR_PREFIX 0x200
640#define WC_PREFIX 0x400
641
642static const struct reg_entry iwmmxt_table[] =
643{
5a6c6817 644 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
645 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
646 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
647 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
648 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
649 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
650 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
651 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
652 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
653 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
654 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
655 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
656 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
657
658 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
659 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
660 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
661 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
662 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
663 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
664 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
665 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
666 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
667 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
668 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
669 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
670 {NULL, 0, TRUE}
e16bb312
NC
671};
672
6c43fab6
RE
673/* Co-processor Numbers. */
674static const struct reg_entry cp_table[] =
675{
0bbf2aa4
NC
676 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
677 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
678 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
679 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
680 {NULL, 0, TRUE}
6c43fab6
RE
681};
682
683/* Co-processor Register Numbers. */
684static const struct reg_entry cn_table[] =
685{
0bbf2aa4
NC
686 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
687 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
688 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
689 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 690 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
691 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
692 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
693 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
694 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
695 {NULL, 0, TRUE}
6c43fab6
RE
696};
697
698/* FPA Registers. */
699static const struct reg_entry fn_table[] =
700{
0bbf2aa4
NC
701 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
702 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
703 {NULL, 0, TRUE}
6c43fab6
RE
704};
705
bfae80f2
RE
706/* VFP SP Registers. */
707static const struct reg_entry sn_table[] =
708{
0bbf2aa4
NC
709 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
710 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
711 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
712 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
713 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
714 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
715 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
716 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
717 {NULL, 0, TRUE}
bfae80f2
RE
718};
719
720/* VFP DP Registers. */
721static const struct reg_entry dn_table[] =
722{
0bbf2aa4
NC
723 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
724 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
725 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
726 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
727 {NULL, 0, TRUE}
bfae80f2
RE
728};
729
63e63b07 730/* Maverick DSP coprocessor registers. */
6c43fab6
RE
731static const struct reg_entry mav_mvf_table[] =
732{
0bbf2aa4
NC
733 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
734 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
735 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
736 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
737 {NULL, 0, TRUE}
6c43fab6
RE
738};
739
740static const struct reg_entry mav_mvd_table[] =
741{
0bbf2aa4
NC
742 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
743 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
744 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
745 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
746 {NULL, 0, TRUE}
6c43fab6
RE
747};
748
749static const struct reg_entry mav_mvfx_table[] =
750{
0bbf2aa4
NC
751 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
752 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
753 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
754 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
755 {NULL, 0, TRUE}
6c43fab6
RE
756};
757
758static const struct reg_entry mav_mvdx_table[] =
759{
0bbf2aa4
NC
760 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
761 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
762 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
763 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
764 {NULL, 0, TRUE}
6c43fab6
RE
765};
766
767static const struct reg_entry mav_mvax_table[] =
768{
0bbf2aa4
NC
769 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
770 {NULL, 0, TRUE}
6c43fab6
RE
771};
772
773static const struct reg_entry mav_dspsc_table[] =
774{
0bbf2aa4
NC
775 {"dspsc", 0, TRUE},
776 {NULL, 0, TRUE}
6c43fab6
RE
777};
778
779struct reg_map
780{
781 const struct reg_entry *names;
782 int max_regno;
783 struct hash_control *htab;
784 const char *expected;
785};
786
787struct reg_map all_reg_maps[] =
788{
789 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
790 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
791 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 792 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
793 {sn_table, 31, NULL, N_("VFP single precision register expected")},
794 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
795 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
796 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
797 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 798 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
799 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
800 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 801 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
802};
803
804/* Enumeration matching entries in table above. */
805enum arm_reg_type
806{
807 REG_TYPE_RN = 0,
808#define REG_TYPE_FIRST REG_TYPE_RN
809 REG_TYPE_CP = 1,
810 REG_TYPE_CN = 2,
811 REG_TYPE_FN = 3,
bfae80f2
RE
812 REG_TYPE_SN = 4,
813 REG_TYPE_DN = 5,
814 REG_TYPE_MVF = 6,
815 REG_TYPE_MVD = 7,
816 REG_TYPE_MVFX = 8,
817 REG_TYPE_MVDX = 9,
818 REG_TYPE_MVAX = 10,
819 REG_TYPE_DSPSC = 11,
e16bb312 820 REG_TYPE_IWMMXT = 12,
bfae80f2 821
e16bb312 822 REG_TYPE_MAX = 13
6c43fab6 823};
404ff6b5 824
b99bd4ef
NC
825/* Functions called by parser. */
826/* ARM instructions. */
f2b7cb0a
RE
827static void do_arit PARAMS ((char *));
828static void do_cmp PARAMS ((char *));
829static void do_mov PARAMS ((char *));
830static void do_ldst PARAMS ((char *));
831static void do_ldstt PARAMS ((char *));
832static void do_ldmstm PARAMS ((char *));
833static void do_branch PARAMS ((char *));
834static void do_swi PARAMS ((char *));
c9b604bd 835
b99bd4ef 836/* Pseudo Op codes. */
f2b7cb0a
RE
837static void do_adr PARAMS ((char *));
838static void do_adrl PARAMS ((char *));
839static void do_empty PARAMS ((char *));
c9b604bd
RE
840
841/* ARM v2. */
f2b7cb0a
RE
842static void do_mul PARAMS ((char *));
843static void do_mla PARAMS ((char *));
c9b604bd
RE
844
845/* ARM v2S. */
f2b7cb0a 846static void do_swap PARAMS ((char *));
c9b604bd
RE
847
848/* ARM v3. */
f2b7cb0a
RE
849static void do_msr PARAMS ((char *));
850static void do_mrs PARAMS ((char *));
c9b604bd
RE
851
852/* ARM v3M. */
f2b7cb0a 853static void do_mull PARAMS ((char *));
b99bd4ef 854
90e4755a 855/* ARM v4. */
f2b7cb0a 856static void do_ldstv4 PARAMS ((char *));
90e4755a 857
c9b604bd 858/* ARM v4T. */
f2b7cb0a 859static void do_bx PARAMS ((char *));
b99bd4ef 860
ea6ef066 861/* ARM v5T. */
f2b7cb0a
RE
862static void do_blx PARAMS ((char *));
863static void do_bkpt PARAMS ((char *));
864static void do_clz PARAMS ((char *));
865static void do_lstc2 PARAMS ((char *));
866static void do_cdp2 PARAMS ((char *));
867static void do_co_reg2 PARAMS ((char *));
b99bd4ef 868
ea6ef066 869/* ARM v5TExP. */
f2b7cb0a
RE
870static void do_smla PARAMS ((char *));
871static void do_smlal PARAMS ((char *));
872static void do_smul PARAMS ((char *));
873static void do_qadd PARAMS ((char *));
c9b604bd 874
ea6ef066 875/* ARM v5TE. */
f2b7cb0a
RE
876static void do_pld PARAMS ((char *));
877static void do_ldrd PARAMS ((char *));
878static void do_co_reg2c PARAMS ((char *));
b99bd4ef 879
ea6ef066
RE
880/* ARM v5TEJ. */
881static void do_bxj PARAMS ((char *));
882
09d92015
MM
883/* ARM V6. */
884static void do_cps PARAMS ((char *));
885static void do_cpsi PARAMS ((char *));
886static void do_ldrex PARAMS ((char *));
887static void do_pkhbt PARAMS ((char *));
888static void do_pkhtb PARAMS ((char *));
889static void do_qadd16 PARAMS ((char *));
890static void do_rev PARAMS ((char *));
891static void do_rfe PARAMS ((char *));
892static void do_sxtah PARAMS ((char *));
893static void do_sxth PARAMS ((char *));
894static void do_setend PARAMS ((char *));
895static void do_smlad PARAMS ((char *));
896static void do_smlald PARAMS ((char *));
897static void do_smmul PARAMS ((char *));
898static void do_ssat PARAMS ((char *));
899static void do_usat PARAMS ((char *));
900static void do_srs PARAMS ((char *));
901static void do_ssat16 PARAMS ((char *));
902static void do_usat16 PARAMS ((char *));
903static void do_strex PARAMS ((char *));
904static void do_umaal PARAMS ((char *));
905
906static void do_cps_mode PARAMS ((char **));
907static void do_cps_flags PARAMS ((char **, int));
908static int do_endian_specifier PARAMS ((char *));
909static void do_pkh_core PARAMS ((char *, int));
910static void do_sat PARAMS ((char **, int));
911static void do_sat16 PARAMS ((char **, int));
912
b99bd4ef 913/* Coprocessor Instructions. */
f2b7cb0a
RE
914static void do_cdp PARAMS ((char *));
915static void do_lstc PARAMS ((char *));
916static void do_co_reg PARAMS ((char *));
c9b604bd
RE
917
918/* FPA instructions. */
f2b7cb0a
RE
919static void do_fpa_ctrl PARAMS ((char *));
920static void do_fpa_ldst PARAMS ((char *));
921static void do_fpa_ldmstm PARAMS ((char *));
922static void do_fpa_dyadic PARAMS ((char *));
923static void do_fpa_monadic PARAMS ((char *));
924static void do_fpa_cmp PARAMS ((char *));
925static void do_fpa_from_reg PARAMS ((char *));
926static void do_fpa_to_reg PARAMS ((char *));
c9b604bd 927
bfae80f2
RE
928/* VFP instructions. */
929static void do_vfp_sp_monadic PARAMS ((char *));
930static void do_vfp_dp_monadic PARAMS ((char *));
931static void do_vfp_sp_dyadic PARAMS ((char *));
932static void do_vfp_dp_dyadic PARAMS ((char *));
933static void do_vfp_reg_from_sp PARAMS ((char *));
934static void do_vfp_sp_from_reg PARAMS ((char *));
e45d0630
PB
935static void do_vfp_reg2_from_sp2 PARAMS ((char *));
936static void do_vfp_sp2_from_reg2 PARAMS ((char *));
bfae80f2
RE
937static void do_vfp_reg_from_dp PARAMS ((char *));
938static void do_vfp_reg2_from_dp PARAMS ((char *));
939static void do_vfp_dp_from_reg PARAMS ((char *));
940static void do_vfp_dp_from_reg2 PARAMS ((char *));
941static void do_vfp_reg_from_ctrl PARAMS ((char *));
942static void do_vfp_ctrl_from_reg PARAMS ((char *));
943static void do_vfp_sp_ldst PARAMS ((char *));
944static void do_vfp_dp_ldst PARAMS ((char *));
945static void do_vfp_sp_ldstmia PARAMS ((char *));
946static void do_vfp_sp_ldstmdb PARAMS ((char *));
947static void do_vfp_dp_ldstmia PARAMS ((char *));
948static void do_vfp_dp_ldstmdb PARAMS ((char *));
949static void do_vfp_xp_ldstmia PARAMS ((char *));
950static void do_vfp_xp_ldstmdb PARAMS ((char *));
951static void do_vfp_sp_compare_z PARAMS ((char *));
952static void do_vfp_dp_compare_z PARAMS ((char *));
953static void do_vfp_dp_sp_cvt PARAMS ((char *));
954static void do_vfp_sp_dp_cvt PARAMS ((char *));
955
c9b604bd 956/* XScale. */
63e63b07
RE
957static void do_xsc_mia PARAMS ((char *));
958static void do_xsc_mar PARAMS ((char *));
959static void do_xsc_mra PARAMS ((char *));
f2b7cb0a
RE
960
961/* Maverick. */
63e63b07 962static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
6c43fab6 963 enum arm_reg_type));
63e63b07
RE
964static void do_mav_binops_1a PARAMS ((char *));
965static void do_mav_binops_1b PARAMS ((char *));
966static void do_mav_binops_1c PARAMS ((char *));
967static void do_mav_binops_1d PARAMS ((char *));
968static void do_mav_binops_1e PARAMS ((char *));
969static void do_mav_binops_1f PARAMS ((char *));
970static void do_mav_binops_1g PARAMS ((char *));
971static void do_mav_binops_1h PARAMS ((char *));
972static void do_mav_binops_1i PARAMS ((char *));
973static void do_mav_binops_1j PARAMS ((char *));
974static void do_mav_binops_1k PARAMS ((char *));
975static void do_mav_binops_1l PARAMS ((char *));
976static void do_mav_binops_1m PARAMS ((char *));
977static void do_mav_binops_1n PARAMS ((char *));
978static void do_mav_binops_1o PARAMS ((char *));
979static void do_mav_binops_2a PARAMS ((char *));
980static void do_mav_binops_2b PARAMS ((char *));
981static void do_mav_binops_2c PARAMS ((char *));
982static void do_mav_binops_3a PARAMS ((char *));
983static void do_mav_binops_3b PARAMS ((char *));
984static void do_mav_binops_3c PARAMS ((char *));
985static void do_mav_binops_3d PARAMS ((char *));
cc8a6dd0 986static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
987 enum arm_reg_type,
988 enum arm_reg_type));
63e63b07
RE
989static void do_mav_triple_4a PARAMS ((char *));
990static void do_mav_triple_4b PARAMS ((char *));
991static void do_mav_triple_5a PARAMS ((char *));
992static void do_mav_triple_5b PARAMS ((char *));
993static void do_mav_triple_5c PARAMS ((char *));
994static void do_mav_triple_5d PARAMS ((char *));
995static void do_mav_triple_5e PARAMS ((char *));
996static void do_mav_triple_5f PARAMS ((char *));
997static void do_mav_triple_5g PARAMS ((char *));
998static void do_mav_triple_5h PARAMS ((char *));
cc8a6dd0 999static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
1000 enum arm_reg_type,
1001 enum arm_reg_type,
1002 enum arm_reg_type));
63e63b07
RE
1003static void do_mav_quad_6a PARAMS ((char *));
1004static void do_mav_quad_6b PARAMS ((char *));
1005static void do_mav_dspsc_1 PARAMS ((char *));
1006static void do_mav_dspsc_2 PARAMS ((char *));
1007static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
6c43fab6 1008 enum arm_reg_type));
63e63b07
RE
1009static void do_mav_shift_1 PARAMS ((char *));
1010static void do_mav_shift_2 PARAMS ((char *));
1011static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1012static void do_mav_ldst_1 PARAMS ((char *));
1013static void do_mav_ldst_2 PARAMS ((char *));
1014static void do_mav_ldst_3 PARAMS ((char *));
1015static void do_mav_ldst_4 PARAMS ((char *));
1016
1017static int mav_reg_required_here PARAMS ((char **, int,
6c43fab6 1018 enum arm_reg_type));
63e63b07 1019static int mav_parse_offset PARAMS ((char **, int *));
404ff6b5 1020
90e4755a
RE
1021static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1022 int, int));
6c43fab6
RE
1023static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1024static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
05d2d07e 1025static const struct asm_psr * arm_psr_parse PARAMS ((char **));
90e4755a
RE
1026static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1027 fragS *));
b99bd4ef
NC
1028static int add_to_lit_pool PARAMS ((void));
1029static unsigned validate_immediate PARAMS ((unsigned));
90e4755a
RE
1030static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1031 unsigned int *));
b99bd4ef
NC
1032static int validate_offset_imm PARAMS ((unsigned int, int));
1033static void opcode_select PARAMS ((int));
1034static void end_of_line PARAMS ((char *));
1035static int reg_required_here PARAMS ((char **, int));
1036static int psr_required_here PARAMS ((char **));
1037static int co_proc_number PARAMS ((char **));
1038static int cp_opc_expr PARAMS ((char **, int, int));
1039static int cp_reg_required_here PARAMS ((char **, int));
1040static int fp_reg_required_here PARAMS ((char **, int));
bfae80f2
RE
1041static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1042static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1043static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1044static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1045static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1046static long vfp_dp_reg_list PARAMS ((char **));
1047static int vfp_psr_required_here PARAMS ((char **str));
1048static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
b99bd4ef 1049static int cp_address_offset PARAMS ((char **));
bfae80f2 1050static int cp_address_required_here PARAMS ((char **, int));
b99bd4ef
NC
1051static int my_get_float_expression PARAMS ((char **));
1052static int skip_past_comma PARAMS ((char **));
1053static int walk_no_bignums PARAMS ((symbolS *));
1054static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1055static int data_op2 PARAMS ((char **));
1056static int fp_op2 PARAMS ((char **));
1057static long reg_list PARAMS ((char **));
1058static void thumb_load_store PARAMS ((char *, int, int));
1059static int decode_shift PARAMS ((char **, int));
90e4755a
RE
1060static int ldst_extend PARAMS ((char **));
1061static int ldst_extend_v4 PARAMS ((char **));
b99bd4ef 1062static void thumb_add_sub PARAMS ((char *, int));
6c43fab6
RE
1063static void insert_reg PARAMS ((const struct reg_entry *,
1064 struct hash_control *));
b99bd4ef
NC
1065static void thumb_shift PARAMS ((char *, int));
1066static void thumb_mov_compare PARAMS ((char *, int));
f2b7cb0a 1067static void build_arm_ops_hsh PARAMS ((void));
b99bd4ef
NC
1068static void set_constant_flonums PARAMS ((void));
1069static valueT md_chars_to_number PARAMS ((char *, int));
6c43fab6
RE
1070static void build_reg_hsh PARAMS ((struct reg_map *));
1071static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1072static int create_register_alias PARAMS ((char *, char *));
f03698e6 1073static void output_inst PARAMS ((const char *));
2c20dfb2
NC
1074static int accum0_required_here PARAMS ((char **));
1075static int ld_mode_required_here PARAMS ((char **));
f2b7cb0a 1076static void do_branch25 PARAMS ((char *));
2c20dfb2 1077static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
1078#ifdef OBJ_ELF
1079static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1080#endif
1081
e16bb312
NC
1082static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1083static void do_iwmmxt_byte_addr PARAMS ((char *));
1084static void do_iwmmxt_tandc PARAMS ((char *));
1085static void do_iwmmxt_tbcst PARAMS ((char *));
1086static void do_iwmmxt_textrc PARAMS ((char *));
1087static void do_iwmmxt_textrm PARAMS ((char *));
1088static void do_iwmmxt_tinsr PARAMS ((char *));
1089static void do_iwmmxt_tmcr PARAMS ((char *));
1090static void do_iwmmxt_tmcrr PARAMS ((char *));
1091static void do_iwmmxt_tmia PARAMS ((char *));
1092static void do_iwmmxt_tmovmsk PARAMS ((char *));
1093static void do_iwmmxt_tmrc PARAMS ((char *));
1094static void do_iwmmxt_tmrrc PARAMS ((char *));
1095static void do_iwmmxt_torc PARAMS ((char *));
1096static void do_iwmmxt_waligni PARAMS ((char *));
1097static void do_iwmmxt_wmov PARAMS ((char *));
1098static void do_iwmmxt_word_addr PARAMS ((char *));
1099static void do_iwmmxt_wrwr PARAMS ((char *));
1100static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1101static void do_iwmmxt_wrwrwr PARAMS ((char *));
1102static void do_iwmmxt_wshufh PARAMS ((char *));
1103static void do_iwmmxt_wzero PARAMS ((char *));
1104static int cp_byte_address_offset PARAMS ((char **));
1105static int cp_byte_address_required_here PARAMS ((char **));
1106
b99bd4ef
NC
1107/* ARM instructions take 4bytes in the object file, Thumb instructions
1108 take 2: */
1109#define INSN_SIZE 4
1110
404ff6b5 1111/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 1112#define MAV_MODE1 0x100c
404ff6b5
AH
1113
1114/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 1115#define MAV_MODE2 0x0c10
404ff6b5 1116
34920d91
NC
1117/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1118#define MAV_MODE3 0x100c
404ff6b5
AH
1119
1120/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 1121#define MAV_MODE4 0x0c0010
404ff6b5
AH
1122
1123/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 1124#define MAV_MODE5 0x00100c
404ff6b5
AH
1125
1126/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 1127#define MAV_MODE6 0x00100c05
b99bd4ef
NC
1128
1129struct asm_opcode
1130{
1131 /* Basic string to match. */
05d2d07e 1132 const char * template;
b99bd4ef
NC
1133
1134 /* Basic instruction code. */
1135 unsigned long value;
1136
90e4755a
RE
1137 /* Offset into the template where the condition code (if any) will be.
1138 If zero, then the instruction is never conditional. */
1139 unsigned cond_offset;
b99bd4ef 1140
90e4755a
RE
1141 /* Which architecture variant provides this instruction. */
1142 unsigned long variant;
b99bd4ef
NC
1143
1144 /* Function to call to parse args. */
f2b7cb0a 1145 void (* parms) PARAMS ((char *));
b99bd4ef
NC
1146};
1147
05d2d07e 1148static const struct asm_opcode insns[] =
b99bd4ef 1149{
c9b604bd 1150 /* Core ARM Instructions. */
90e4755a
RE
1151 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1152 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1153 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1154 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1155 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1156 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1157 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1158 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1159 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1160 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1161 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1162 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1163 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1164 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1165 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1166 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1167 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1168 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1169 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1170 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1171
1172 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1173 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1174 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1175 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1176 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1177 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1178 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1179 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1183 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1184
1185 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1186 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1187 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1188 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1189
1190 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1191 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1192 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1193 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1194 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1195 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1196 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1197 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1198
1199 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1201 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1206 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1207
1208 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1209 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1210 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1215 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1216
1217 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
b99bd4ef 1218#ifdef TE_WINCE
c9b604bd 1219 /* XXX This is the wrong place to do this. Think multi-arch. */
90e4755a
RE
1220 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1221 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
b99bd4ef 1222#else
90e4755a
RE
1223 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1224 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
b99bd4ef
NC
1225#endif
1226
c9b604bd 1227 /* Pseudo ops. */
90e4755a
RE
1228 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1229 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1230 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
b99bd4ef 1231
c9b604bd 1232 /* ARM 2 multiplies. */
90e4755a
RE
1233 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1234 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1235 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1236 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 1237
67c1ffbe 1238 /* Generic coprocessor instructions. */
90e4755a
RE
1239 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1240 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1241 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1242 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1243 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1244 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1245 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
c9b604bd
RE
1246
1247 /* ARM 3 - swp instructions. */
90e4755a
RE
1248 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1249 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 1250
c9b604bd 1251 /* ARM 6 Status register instructions. */
90e4755a
RE
1252 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1253 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1254 /* ScottB: our code uses 0xe128f000 for msr.
c9b604bd 1255 NickC: but this is wrong because the bits 16 through 19 are
90e4755a 1256 handled by the PSR_xxx defines above. */
b99bd4ef 1257
f2b7cb0a 1258 /* ARM 7M long multiplies. */
90e4755a
RE
1259 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1260 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1261 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1262 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1263 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1264 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1265 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1266 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1267
1268 /* ARM Architecture 4. */
1269 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1270 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1271 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1272 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 1273
c9b604bd 1274 /* ARM Architecture 4T. */
cc8a6dd0 1275 /* Note: bx (and blx) are required on V5, even if the processor does
90e4755a
RE
1276 not support Thumb. */
1277 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1278
ea6ef066 1279 /* ARM Architecture 5T. */
90e4755a
RE
1280 /* Note: blx has 2 variants, so the .value is set dynamically.
1281 Only one of the variants has conditional execution. */
1282 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1283 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1284 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1285 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1286 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1287 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1288 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1289 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1290 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1291 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1292
ea6ef066 1293 /* ARM Architecture 5TExP. */
90e4755a
RE
1294 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1295 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1296 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1297 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1298
1299 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1300 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1301
1302 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1303 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1304 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1305 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1306
1307 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1308 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1309 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1310 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1311
1312 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1313 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1314
1315 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1316 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1317 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1318 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
c9b604bd 1319
ea6ef066 1320 /* ARM Architecture 5TE. */
90e4755a
RE
1321 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1322 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1323 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1324
1325 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1326 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
404ff6b5 1327
ea6ef066
RE
1328 /* ARM Architecture 5TEJ. */
1329 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1330
09d92015
MM
1331 /* ARM V6. */
1332 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1333 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1334 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1335 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1336 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1337 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1338 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1339 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1340 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1341 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1342 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1343 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1344 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1345 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1346 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1347 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1348 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1349 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1350 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1351 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1352 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1353 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1354 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1355 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1356 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1357 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1358 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1359 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1360 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1361 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1362 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1363 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1364 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1365 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1366 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1367 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1368 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1369 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1370 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1371 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1372 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1373 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1374 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1375 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1376 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1377 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1378 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1379 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1380 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1381 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1386 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1387 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1388 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1389 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1390 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1391 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1392 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1393 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1394 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1395 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1396 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1397 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1398 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1399 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1400 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1401 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1402 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1403 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1404 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1405 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1406 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1407 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1408 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1409 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1410 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1411 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1412 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1413 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1414 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1415 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1416 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1417 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1418 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1419 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1420 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1421 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1422 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1423 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1424 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1425 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1426 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1427 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1428 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1429 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1430 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1431
c9b604bd 1432 /* Core FPA instruction set (V1). */
90e4755a
RE
1433 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1434 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1435 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1437
1438 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1439 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1440 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1442
1443 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1445 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1447
1448 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460
1461 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473
1474 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486
1487 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499
1500 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512
1513 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525
1526 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538
1539 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551
1552 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564
1565 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577
1578 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590
1591 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603
1604 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616
1617 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629
1630 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1642
1643 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1645 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1655
1656 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668
1669 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681
1682 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694
1695 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707
1708 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720
1721 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733
1734 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746
1747 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759
1760 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772
1773 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785
1786 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798
1799 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1811
1812 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1814 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1824
1825 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1826 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1827 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1829 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1830 not be an optional suffix, but part of the instruction. To be
1831 compatible, we accept either. */
1832 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1833 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1834
1835 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1836 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1837 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1847
1848 /* The implementation of the FIX instruction is broken on some
1849 assemblers, in that it accepts a precision specifier as well as a
1850 rounding specifier, despite the fact that this is meaningless.
1851 To be more compatible, we accept it as well, though of course it
1852 does not set any bits. */
1853 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1854 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1855 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1865 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
c9b604bd
RE
1866
1867 /* Instructions that were new with the real FPA, call them V2. */
90e4755a
RE
1868 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1869 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1870 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1873 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
c9b604bd 1874
bfae80f2
RE
1875 /* VFP V1xD (single precision). */
1876 /* Moves and type conversions. */
1877 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1878 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1879 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1880 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1881 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1887 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1888 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1889
1890 /* Memory operations. */
1891 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1892 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1893 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1894 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1895 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1896 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1897 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1898 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1899 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1900 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1901 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1902 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1903 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1904 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1905 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1906 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1907 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1908 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1909
1910 /* Monadic operations. */
1911 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1912 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1914
1915 /* Dyadic operations. */
1916 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1925
1926 /* Comparisons. */
1927 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1928 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1929 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1930 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1931
1932 /* VFP V1 (Double precision). */
1933 /* Moves and type conversions. */
1934 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1935 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1936 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1937 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1938 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1939 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1940 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1941 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1942 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1943 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1944 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1945 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1947
1948 /* Memory operations. */
1949 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1950 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1951 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1952 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1953 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1954 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1955 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1956 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1957 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1958 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1959
1960 /* Monadic operations. */
1961 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1962 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1963 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1964
1965 /* Dyadic operations. */
1966 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1967 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1968 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1975
1976 /* Comparisons. */
1977 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1978 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1979 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1980 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1981
1982 /* VFP V2. */
e45d0630
PB
1983 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1984 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
bfae80f2
RE
1985 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1986 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1987
c9b604bd 1988 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
63e63b07
RE
1989 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1990 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1991 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1995 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1996 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1997
5a6c6817
NC
1998 /* Intel Wireless MMX technology instructions. */
1999 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2000 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2001 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2002 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2003 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2004 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2005 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2006 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2007 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2008 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2014 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2015 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2016 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2017 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2018 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2019 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2025 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2026 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2027 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2028 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2029 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2030 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2031 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2032 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2033 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2034 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2035 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2036 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2046 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2066 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2067 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2068 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2069 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2088 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2101 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2103 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2105 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2107 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2109 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2110 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2111 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2112 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2113 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2114 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2115 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2116 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2117 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2118 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2120 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2122 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2124 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2125 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2126 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2127 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2128 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2129 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2130 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2131 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2132 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2141 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2147 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2148 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2149 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2150 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2156 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2157 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2158 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2160 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2161
63e63b07
RE
2162 /* Cirrus Maverick instructions. */
2163 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2164 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2165 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2166 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2167 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2168 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2169 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2170 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2171 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2172 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2173 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2174 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2175 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2176 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2177 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2178 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2179 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2180 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
34920d91
NC
2181 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2182 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2183 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2184 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2185 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2186 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2187 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2188 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2189 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2190 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2191 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2192 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
63e63b07
RE
2193 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2194 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2195 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2196 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2197 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2198 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2199 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2200 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2201 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2202 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2203 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2204 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2205 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2206 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2207 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2208 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2209 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2210 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2211 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2212 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2213 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2214 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2215 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2216 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2217 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2218 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2219 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2220 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2221 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2222 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2223 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2224 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2225 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2226 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2227 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2228 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2229 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2230 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2231 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2232 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2233 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2235 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2236 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2237 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2238 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
b99bd4ef
NC
2239};
2240
2241/* Defines for various bits that we will want to toggle. */
2242#define INST_IMMEDIATE 0x02000000
2243#define OFFSET_REG 0x02000000
2244#define HWOFFSET_IMM 0x00400000
2245#define SHIFT_BY_REG 0x00000010
2246#define PRE_INDEX 0x01000000
2247#define INDEX_UP 0x00800000
2248#define WRITE_BACK 0x00200000
2249#define LDM_TYPE_2_OR_3 0x00400000
2250
2251#define LITERAL_MASK 0xf000f000
b99bd4ef 2252#define OPCODE_MASK 0xfe1fffff
90e4755a
RE
2253#define V4_STR_BIT 0x00000020
2254
b99bd4ef
NC
2255#define DATA_OP_SHIFT 21
2256
2257/* Codes to distinguish the arithmetic instructions. */
2258#define OPCODE_AND 0
2259#define OPCODE_EOR 1
2260#define OPCODE_SUB 2
2261#define OPCODE_RSB 3
2262#define OPCODE_ADD 4
2263#define OPCODE_ADC 5
2264#define OPCODE_SBC 6
2265#define OPCODE_RSC 7
2266#define OPCODE_TST 8
2267#define OPCODE_TEQ 9
2268#define OPCODE_CMP 10
2269#define OPCODE_CMN 11
2270#define OPCODE_ORR 12
2271#define OPCODE_MOV 13
2272#define OPCODE_BIC 14
2273#define OPCODE_MVN 15
2274
c9b604bd 2275/* Thumb v1 (ARMv4T). */
b99bd4ef
NC
2276static void do_t_nop PARAMS ((char *));
2277static void do_t_arit PARAMS ((char *));
2278static void do_t_add PARAMS ((char *));
2279static void do_t_asr PARAMS ((char *));
2280static void do_t_branch9 PARAMS ((char *));
2281static void do_t_branch12 PARAMS ((char *));
2282static void do_t_branch23 PARAMS ((char *));
2283static void do_t_bx PARAMS ((char *));
2284static void do_t_compare PARAMS ((char *));
2285static void do_t_ldmstm PARAMS ((char *));
2286static void do_t_ldr PARAMS ((char *));
2287static void do_t_ldrb PARAMS ((char *));
2288static void do_t_ldrh PARAMS ((char *));
2289static void do_t_lds PARAMS ((char *));
2290static void do_t_lsl PARAMS ((char *));
2291static void do_t_lsr PARAMS ((char *));
2292static void do_t_mov PARAMS ((char *));
2293static void do_t_push_pop PARAMS ((char *));
2294static void do_t_str PARAMS ((char *));
2295static void do_t_strb PARAMS ((char *));
2296static void do_t_strh PARAMS ((char *));
2297static void do_t_sub PARAMS ((char *));
2298static void do_t_swi PARAMS ((char *));
2299static void do_t_adr PARAMS ((char *));
2300
c9b604bd
RE
2301/* Thumb v2 (ARMv5T). */
2302static void do_t_blx PARAMS ((char *));
2303static void do_t_bkpt PARAMS ((char *));
2304
09d92015
MM
2305/* ARM V6. */
2306static void do_t_cps PARAMS ((char *));
2307static void do_t_cpy PARAMS ((char *));
2308static void do_t_setend PARAMS ((char *));;
2309
b99bd4ef
NC
2310#define T_OPCODE_MUL 0x4340
2311#define T_OPCODE_TST 0x4200
2312#define T_OPCODE_CMN 0x42c0
2313#define T_OPCODE_NEG 0x4240
2314#define T_OPCODE_MVN 0x43c0
2315
2316#define T_OPCODE_ADD_R3 0x1800
2317#define T_OPCODE_SUB_R3 0x1a00
2318#define T_OPCODE_ADD_HI 0x4400
2319#define T_OPCODE_ADD_ST 0xb000
2320#define T_OPCODE_SUB_ST 0xb080
2321#define T_OPCODE_ADD_SP 0xa800
2322#define T_OPCODE_ADD_PC 0xa000
2323#define T_OPCODE_ADD_I8 0x3000
2324#define T_OPCODE_SUB_I8 0x3800
2325#define T_OPCODE_ADD_I3 0x1c00
2326#define T_OPCODE_SUB_I3 0x1e00
2327
2328#define T_OPCODE_ASR_R 0x4100
2329#define T_OPCODE_LSL_R 0x4080
2330#define T_OPCODE_LSR_R 0x40c0
2331#define T_OPCODE_ASR_I 0x1000
2332#define T_OPCODE_LSL_I 0x0000
2333#define T_OPCODE_LSR_I 0x0800
2334
2335#define T_OPCODE_MOV_I8 0x2000
2336#define T_OPCODE_CMP_I8 0x2800
2337#define T_OPCODE_CMP_LR 0x4280
2338#define T_OPCODE_MOV_HR 0x4600
2339#define T_OPCODE_CMP_HR 0x4500
2340
2341#define T_OPCODE_LDR_PC 0x4800
2342#define T_OPCODE_LDR_SP 0x9800
2343#define T_OPCODE_STR_SP 0x9000
2344#define T_OPCODE_LDR_IW 0x6800
2345#define T_OPCODE_STR_IW 0x6000
2346#define T_OPCODE_LDR_IH 0x8800
2347#define T_OPCODE_STR_IH 0x8000
2348#define T_OPCODE_LDR_IB 0x7800
2349#define T_OPCODE_STR_IB 0x7000
2350#define T_OPCODE_LDR_RW 0x5800
2351#define T_OPCODE_STR_RW 0x5000
2352#define T_OPCODE_LDR_RH 0x5a00
2353#define T_OPCODE_STR_RH 0x5200
2354#define T_OPCODE_LDR_RB 0x5c00
2355#define T_OPCODE_STR_RB 0x5400
2356
2357#define T_OPCODE_PUSH 0xb400
2358#define T_OPCODE_POP 0xbc00
2359
2360#define T_OPCODE_BRANCH 0xe7fe
2361
2362static int thumb_reg PARAMS ((char ** str, int hi_lo));
2363
2364#define THUMB_SIZE 2 /* Size of thumb instruction. */
2365#define THUMB_REG_LO 0x1
2366#define THUMB_REG_HI 0x2
2367#define THUMB_REG_ANY 0x3
2368
2369#define THUMB_H1 0x0080
2370#define THUMB_H2 0x0040
2371
2372#define THUMB_ASR 0
2373#define THUMB_LSL 1
2374#define THUMB_LSR 2
2375
2376#define THUMB_MOVE 0
2377#define THUMB_COMPARE 1
09d92015 2378#define THUMB_CPY 2
b99bd4ef
NC
2379
2380#define THUMB_LOAD 0
2381#define THUMB_STORE 1
2382
2383#define THUMB_PP_PC_LR 0x0100
2384
2385/* These three are used for immediate shifts, do not alter. */
2386#define THUMB_WORD 2
2387#define THUMB_HALFWORD 1
2388#define THUMB_BYTE 0
2389
2390struct thumb_opcode
2391{
2392 /* Basic string to match. */
05d2d07e 2393 const char * template;
b99bd4ef
NC
2394
2395 /* Basic instruction code. */
2396 unsigned long value;
2397
2398 int size;
2399
2400 /* Which CPU variants this exists for. */
90e4755a 2401 unsigned long variant;
b99bd4ef
NC
2402
2403 /* Function to call to parse args. */
2404 void (* parms) PARAMS ((char *));
2405};
2406
05d2d07e 2407static const struct thumb_opcode tinsns[] =
b99bd4ef 2408{
c9b604bd 2409 /* Thumb v1 (ARMv4T). */
b89dddec
RE
2410 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2411 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2412 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2413 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2414 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2415 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2433 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2434 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
b89dddec
RE
2435 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2436 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2437 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2438 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2439 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2440 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2441 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2442 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2443 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2444 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2445 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2446 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2447 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2448 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2449 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2450 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2451 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2452 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2453 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2454 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2455 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2456 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2457 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2458 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2459 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2460 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2461 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2462 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2463 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2464 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
b99bd4ef 2465 /* Pseudo ops: */
b89dddec
RE
2466 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2467 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
c9b604bd
RE
2468 /* Thumb v2 (ARMv5T). */
2469 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2470 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
09d92015
MM
2471
2472 /* ARM V6. */
2473 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2474 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2475 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2476 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2477 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2478 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2479 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2480 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2481 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2482 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2483 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
b99bd4ef
NC
2484};
2485
f03698e6 2486#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 2487#define BAD_PC _("r15 not allowed here")
f03698e6 2488#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
2489#define ERR_NO_ACCUM _("acc0 expected")
2490
2491static struct hash_control * arm_ops_hsh = NULL;
2492static struct hash_control * arm_tops_hsh = NULL;
2493static struct hash_control * arm_cond_hsh = NULL;
2494static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
2495static struct hash_control * arm_psr_hsh = NULL;
2496
2497/* This table describes all the machine specific pseudo-ops the assembler
2498 has to support. The fields are:
2499 pseudo-op name without dot
2500 function to call to execute this pseudo-op
2501 Integer arg to pass to the function. */
2502
2503static void s_req PARAMS ((int));
0bbf2aa4 2504static void s_unreq PARAMS ((int));
b99bd4ef
NC
2505static void s_align PARAMS ((int));
2506static void s_bss PARAMS ((int));
2507static void s_even PARAMS ((int));
2508static void s_ltorg PARAMS ((int));
2509static void s_arm PARAMS ((int));
2510static void s_thumb PARAMS ((int));
2511static void s_code PARAMS ((int));
2512static void s_force_thumb PARAMS ((int));
2513static void s_thumb_func PARAMS ((int));
2514static void s_thumb_set PARAMS ((int));
76feaaf3 2515#ifdef OBJ_ELF
b99bd4ef
NC
2516static void s_arm_elf_cons PARAMS ((int));
2517#endif
2518
2519static int my_get_expression PARAMS ((expressionS *, char **));
2520
05d2d07e 2521const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2522{
0bbf2aa4 2523 /* Never called because '.req' does not start a line. */
b99bd4ef 2524 { "req", s_req, 0 },
0bbf2aa4 2525 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2526 { "bss", s_bss, 0 },
2527 { "align", s_align, 0 },
2528 { "arm", s_arm, 0 },
2529 { "thumb", s_thumb, 0 },
2530 { "code", s_code, 0 },
2531 { "force_thumb", s_force_thumb, 0 },
2532 { "thumb_func", s_thumb_func, 0 },
2533 { "thumb_set", s_thumb_set, 0 },
2534 { "even", s_even, 0 },
2535 { "ltorg", s_ltorg, 0 },
2536 { "pool", s_ltorg, 0 },
76feaaf3 2537#ifdef OBJ_ELF
b99bd4ef
NC
2538 { "word", s_arm_elf_cons, 4 },
2539 { "long", s_arm_elf_cons, 4 },
b99bd4ef
NC
2540#else
2541 { "word", cons, 4},
2542#endif
2543 { "extend", float_cons, 'x' },
2544 { "ldouble", float_cons, 'x' },
2545 { "packed", float_cons, 'p' },
2546 { 0, 0, 0 }
2547};
2548
03b1477f
RE
2549/* Other internal functions. */
2550static int arm_parse_extension PARAMS ((char *, int *));
2551static int arm_parse_cpu PARAMS ((char *));
2552static int arm_parse_arch PARAMS ((char *));
2553static int arm_parse_fpu PARAMS ((char *));
33a392fb 2554static int arm_parse_float_abi PARAMS ((char *));
d507cf36 2555static int arm_parse_eabi PARAMS ((char *));
0bbf2aa4 2556#if 0 /* Suppressed - for now. */
5a6c6817
NC
2557#if defined OBJ_COFF || defined OBJ_ELF
2558static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2559#endif
0bbf2aa4 2560#endif
03b1477f 2561
b99bd4ef
NC
2562/* Stuff needed to resolve the label ambiguity
2563 As:
2564 ...
2565 label: <insn>
2566 may differ from:
2567 ...
2568 label:
2569 <insn>
2570*/
2571
2572symbolS * last_label_seen;
b34976b6 2573static int label_is_thumb_function_name = FALSE;
b99bd4ef 2574
3d0c9500 2575/* Literal Pool stuff. */
b99bd4ef
NC
2576
2577#define MAX_LITERAL_POOL_SIZE 1024
2578
3d0c9500
NC
2579/* Literal pool structure. Held on a per-section
2580 and per-sub-section basis. */
2581typedef struct literal_pool
b99bd4ef 2582{
3d0c9500
NC
2583 expressionS literals [MAX_LITERAL_POOL_SIZE];
2584 unsigned int next_free_entry;
2585 unsigned int id;
2586 symbolS * symbol;
2587 segT section;
2588 subsegT sub_section;
61b5f74b 2589 struct literal_pool * next;
3d0c9500 2590} literal_pool;
b99bd4ef 2591
3d0c9500
NC
2592/* Pointer to a linked list of literal pools. */
2593literal_pool * list_of_pools = NULL;
b99bd4ef 2594
3d0c9500
NC
2595static literal_pool * find_literal_pool PARAMS ((void));
2596static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2597
3d0c9500
NC
2598static literal_pool *
2599find_literal_pool ()
2600{
2601 literal_pool * pool;
2602
2603 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2604 {
2605 if (pool->section == now_seg
2606 && pool->sub_section == now_subseg)
2607 break;
2608 }
2609
2610 return pool;
2611}
b99bd4ef 2612
3d0c9500
NC
2613static literal_pool *
2614find_or_make_literal_pool ()
2615{
2616 /* Next literal pool ID number. */
2617 static unsigned int latest_pool_num = 1;
2618 literal_pool * pool;
2619
2620 pool = find_literal_pool ();
b99bd4ef 2621
3d0c9500
NC
2622 if (pool == NULL)
2623 {
2624 /* Create a new pool. */
2625 pool = (literal_pool *) xmalloc (sizeof (* pool));
2626 if (! pool)
2627 return NULL;
2628
2629 pool->next_free_entry = 0;
2630 pool->section = now_seg;
2631 pool->sub_section = now_subseg;
2632 pool->next = list_of_pools;
2633 pool->symbol = NULL;
2634
2635 /* Add it to the list. */
2636 list_of_pools = pool;
2637 }
2638
2639 /* New pools, and emptied pools, will have a NULL symbol. */
2640 if (pool->symbol == NULL)
2641 {
2642 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2643 (valueT) 0, &zero_address_frag);
2644 pool->id = latest_pool_num ++;
2645 }
2646
2647 /* Done. */
2648 return pool;
2649}
2650
2651/* Add the literal in the global 'inst'
2652 structure to the relevent literal pool. */
b99bd4ef
NC
2653static int
2654add_to_lit_pool ()
2655{
61b5f74b 2656 literal_pool * pool;
3d0c9500 2657 unsigned int entry;
b99bd4ef 2658
3d0c9500 2659 pool = find_or_make_literal_pool ();
b99bd4ef 2660
3d0c9500
NC
2661 /* Check if this literal value is already in the pool. */
2662 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2663 {
3d0c9500
NC
2664 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2665 && (inst.reloc.exp.X_op == O_constant)
2666 && (pool->literals[entry].X_add_number
b99bd4ef 2667 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2668 && (pool->literals[entry].X_unsigned
2669 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2670 break;
2671
3d0c9500
NC
2672 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2673 && (inst.reloc.exp.X_op == O_symbol)
2674 && (pool->literals[entry].X_add_number
b99bd4ef 2675 == inst.reloc.exp.X_add_number)
3d0c9500 2676 && (pool->literals[entry].X_add_symbol
b99bd4ef 2677 == inst.reloc.exp.X_add_symbol)
3d0c9500 2678 && (pool->literals[entry].X_op_symbol
b99bd4ef 2679 == inst.reloc.exp.X_op_symbol))
3d0c9500 2680 break;
b99bd4ef
NC
2681 }
2682
3d0c9500
NC
2683 /* Do we need to create a new entry? */
2684 if (entry == pool->next_free_entry)
b99bd4ef 2685 {
3d0c9500 2686 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2687 {
ed71e111 2688 inst.error = _("literal pool overflow");
b99bd4ef
NC
2689 return FAIL;
2690 }
2691
3d0c9500
NC
2692 pool->literals[entry] = inst.reloc.exp;
2693 pool->next_free_entry += 1;
b99bd4ef
NC
2694 }
2695
3d0c9500 2696 inst.reloc.exp.X_op = O_symbol;
08df2379 2697 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2698 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2699
2700 return SUCCESS;
2701}
2702
2703/* Can't use symbol_new here, so have to create a symbol and then at
2704 a later date assign it a value. Thats what these functions do. */
2705
2706static void
2707symbol_locate (symbolP, name, segment, valu, frag)
2708 symbolS * symbolP;
05d2d07e 2709 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2710 segT segment; /* Segment identifier (SEG_<something>). */
2711 valueT valu; /* Symbol value. */
2712 fragS * frag; /* Associated fragment. */
2713{
2714 unsigned int name_length;
2715 char * preserved_copy_of_name;
2716
2717 name_length = strlen (name) + 1; /* +1 for \0. */
2718 obstack_grow (&notes, name, name_length);
2719 preserved_copy_of_name = obstack_finish (&notes);
2720#ifdef STRIP_UNDERSCORE
2721 if (preserved_copy_of_name[0] == '_')
2722 preserved_copy_of_name++;
2723#endif
2724
2725#ifdef tc_canonicalize_symbol_name
2726 preserved_copy_of_name =
2727 tc_canonicalize_symbol_name (preserved_copy_of_name);
2728#endif
2729
2730 S_SET_NAME (symbolP, preserved_copy_of_name);
2731
2732 S_SET_SEGMENT (symbolP, segment);
2733 S_SET_VALUE (symbolP, valu);
c62e1cc3 2734 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2735
2736 symbol_set_frag (symbolP, frag);
2737
2738 /* Link to end of symbol chain. */
2739 {
2740 extern int symbol_table_frozen;
2741 if (symbol_table_frozen)
2742 abort ();
2743 }
2744
2745 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2746
2747 obj_symbol_new_hook (symbolP);
2748
2749#ifdef tc_symbol_new_hook
2750 tc_symbol_new_hook (symbolP);
2751#endif
2752
2753#ifdef DEBUG_SYMS
2754 verify_symbol_chain (symbol_rootP, symbol_lastP);
2755#endif /* DEBUG_SYMS */
2756}
2757
2758/* Check that an immediate is valid.
2759 If so, convert it to the right format. */
2760
2761static unsigned int
2762validate_immediate (val)
2763 unsigned int val;
2764{
2765 unsigned int a;
2766 unsigned int i;
2767
2768#define rotate_left(v, n) (v << n | v >> (32 - n))
2769
2770 for (i = 0; i < 32; i += 2)
2771 if ((a = rotate_left (val, i)) <= 0xff)
2772 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2773
2774 return FAIL;
2775}
2776
2d2255b5 2777/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2778 values, added together. We already know that this value cannot be
2779 computed by just one ARM instruction. */
2780
2781static unsigned int
2782validate_immediate_twopart (val, highpart)
2783 unsigned int val;
2784 unsigned int * highpart;
2785{
2786 unsigned int a;
2787 unsigned int i;
2788
2789 for (i = 0; i < 32; i += 2)
2790 if (((a = rotate_left (val, i)) & 0xff) != 0)
2791 {
2792 if (a & 0xff00)
2793 {
2794 if (a & ~ 0xffff)
2795 continue;
2796 * highpart = (a >> 8) | ((i + 24) << 7);
2797 }
2798 else if (a & 0xff0000)
2799 {
2800 if (a & 0xff000000)
2801 continue;
2802 * highpart = (a >> 16) | ((i + 16) << 7);
2803 }
2804 else
2805 {
2806 assert (a & 0xff000000);
2807 * highpart = (a >> 24) | ((i + 8) << 7);
2808 }
2809
2810 return (a & 0xff) | (i << 7);
2811 }
2812
2813 return FAIL;
2814}
2815
2816static int
2817validate_offset_imm (val, hwse)
2818 unsigned int val;
2819 int hwse;
2820{
2821 if ((hwse && val > 255) || val > 4095)
2822 return FAIL;
2823 return val;
2824}
2825
6057a28f
NC
2826\f
2827#ifdef OBJ_ELF
2828enum mstate
2829{
2830 MAP_DATA,
2831 MAP_ARM,
2832 MAP_THUMB
2833};
2834
2835/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2836 (This text is taken from version B-02 of the spec):
2837
2838 4.4.7 Mapping and tagging symbols
2839
2840 A section of an ARM ELF file can contain a mixture of ARM code,
2841 Thumb code, and data. There are inline transitions between code
2842 and data at literal pool boundaries. There can also be inline
2843 transitions between ARM code and Thumb code, for example in
2844 ARM-Thumb inter-working veneers. Linkers, machine-level
2845 debuggers, profiling tools, and disassembly tools need to map
2846 images accurately. For example, setting an ARM breakpoint on a
2847 Thumb location, or in a literal pool, can crash the program
2848 being debugged, ruining the debugging session.
2849
2850 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2851 tagged (see section 4.4.7.2 below) using local symbols (with
2852 binding STB_LOCAL). To assist consumers, mapping and tagging
2853 symbols should be collated first in the symbol table, before
2854 other symbols with binding STB_LOCAL.
2855
2856 To allow properly collated mapping and tagging symbols to be
2857 skipped by consumers that have no interest in them, the first
2858 such symbol should have the name $m and its st_value field equal
2859 to the total number of mapping and tagging symbols (including
2860 the $m) in the symbol table.
2861
2862 4.4.7.1 Mapping symbols
2863
2864 $a Labels the first byte of a sequence of ARM instructions.
2865 Its type is STT_FUNC.
2866
2867 $d Labels the first byte of a sequence of data items.
2868 Its type is STT_OBJECT.
2869
2870 $t Labels the first byte of a sequence of Thumb instructions.
2871 Its type is STT_FUNC.
2872
2873 This list of mapping symbols may be extended in the future.
2874
2875 Section-relative mapping symbols
2876
2877 Mapping symbols defined in a section define a sequence of
2878 half-open address intervals that cover the address range of the
2879 section. Each interval starts at the address defined by a
2880 mapping symbol, and continues up to, but not including, the
2881 address defined by the next (in address order) mapping symbol or
2882 the end of the section. A corollary is that there must be a
2883 mapping symbol defined at the beginning of each section.
2884 Consumers can ignore the size of a section-relative mapping
2885 symbol. Producers can set it to 0.
2886
2887 Absolute mapping symbols
2888
2889 Because of the need to crystallize a Thumb address with the
2890 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2891 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2892 or $t.
2893
2894 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2895 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2896 where [x, y) denotes the half-open address range from x,
2897 inclusive, to y, exclusive.
2898
2899 In the absence of a mapping symbol, a consumer can interpret a
2900 function symbol with an odd value as the Thumb code address
2901 obtained by clearing the least significant bit of the
2902 value. This interpretation is deprecated, and it may not work in
2903 the future.
2904
2905 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2906 the EABI (which is still under development), so they are not
2907 implemented here. */
2908
2909static void
2910mapping_state (enum mstate state)
2911{
2912 static enum mstate mapstate = MAP_DATA;
2913 symbolS * symbolP;
2914 const char * symname;
2915 int type;
2916
2917 if (mapstate == state)
2918 /* The mapping symbol has already been emitted.
2919 There is nothing else to do. */
2920 return;
2921
2922 mapstate = state;
2923
2924 switch (state)
2925 {
2926 case MAP_DATA:
2927 symname = "$d";
2928 type = BSF_OBJECT;
2929 break;
2930 case MAP_ARM:
2931 symname = "$a";
2932 type = BSF_FUNCTION;
2933 break;
2934 case MAP_THUMB:
2935 symname = "$t";
2936 type = BSF_FUNCTION;
2937 break;
2938 default:
2939 abort ();
2940 }
2941
2942 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2943 symbol_table_insert (symbolP);
2944 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2945
2946 switch (state)
2947 {
2948 case MAP_ARM:
2949 THUMB_SET_FUNC (symbolP, 0);
2950 ARM_SET_THUMB (symbolP, 0);
2951 ARM_SET_INTERWORK (symbolP, support_interwork);
2952 break;
2953
2954 case MAP_THUMB:
2955 THUMB_SET_FUNC (symbolP, 1);
2956 ARM_SET_THUMB (symbolP, 1);
2957 ARM_SET_INTERWORK (symbolP, support_interwork);
2958 break;
2959
2960 case MAP_DATA:
2961 default:
2962 return;
2963 }
2964}
2965
2966/* When we change sections we need to issue a new mapping symbol. */
2967
9ce887a1 2968void
6057a28f
NC
2969arm_elf_change_section (void)
2970{
2971 flagword flags;
2972
2973 if (!SEG_NORMAL (now_seg))
2974 return;
2975
2976 flags = bfd_get_section_flags (stdoutput, now_seg);
2977
2978 /* We can ignore sections that only contain debug info. */
2979 if ((flags & SEC_ALLOC) == 0)
2980 return;
2981
2982 if (flags & SEC_CODE)
2983 {
2984 if (thumb_mode)
2985 mapping_state (MAP_THUMB);
2986 else
2987 mapping_state (MAP_ARM);
2988 }
2989 else
2990 /* This section does not contain code. Therefore it must contain data. */
2991 mapping_state (MAP_DATA);
2992}
2993#else
2994#define mapping_state(a)
2995#endif /* OBJ_ELF */
2996\f
2997
b99bd4ef
NC
2998static void
2999s_req (a)
3000 int a ATTRIBUTE_UNUSED;
3001{
f03698e6 3002 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
3003}
3004
0bbf2aa4
NC
3005/* The .unreq directive deletes an alias which was previously defined
3006 by .req. For example:
3007
3008 my_alias .req r11
3009 .unreq my_alias */
3010
3011static void
3012s_unreq (int a ATTRIBUTE_UNUSED)
3013{
3014 char *name;
3015 char saved_char;
3016
3017 skip_whitespace (input_line_pointer);
3018 name = input_line_pointer;
3019
3020 while (*input_line_pointer != 0
3021 && *input_line_pointer != ' '
3022 && *input_line_pointer != '\n')
3023 ++input_line_pointer;
3024
3025 saved_char = *input_line_pointer;
3026 *input_line_pointer = 0;
3027
3028 if (*name)
3029 {
3030 enum arm_reg_type req_type = arm_reg_parse_any (name);
3031
3032 if (req_type != REG_TYPE_MAX)
3033 {
3034 char *temp_name = name;
3035 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3036
3037 if (req_no != FAIL)
3038 {
3039 struct reg_entry *req_entry;
3040
3041 /* Check to see if this alias is a builtin one. */
3042 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3043
3044 if (!req_entry)
3045 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3046 else if (req_entry->builtin)
67c1ffbe 3047 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
3048 points to a const data structure, so we only need to
3049 free up the memory used by the key in the hash table.
3050 Unfortunately we have not recorded this value, so this
3051 is a memory leak. */
3052 /* FIXME: Should we issue a warning message ? */
3053 ;
3054 else
3055 {
67c1ffbe 3056 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
3057 key and the value, but fortunately the key is the same
3058 as the value->name field. */
3059 free ((char *) req_entry->name);
3060 free (req_entry);
3061 }
3062 }
3063 else
3064 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3065 }
3066 else
3067 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3068 }
3069 else
3070 as_bad (_("invalid syntax for .unreq directive"));
3071
3072 *input_line_pointer = saved_char;
3073 demand_empty_rest_of_line ();
3074}
3075
b99bd4ef
NC
3076static void
3077s_bss (ignore)
3078 int ignore ATTRIBUTE_UNUSED;
3079{
3080 /* We don't support putting frags in the BSS segment, we fake it by
3081 marking in_bss, then looking at s_skip for clues. */
3082 subseg_set (bss_section, 0);
3083 demand_empty_rest_of_line ();
6057a28f 3084 mapping_state (MAP_DATA);
b99bd4ef
NC
3085}
3086
3087static void
3088s_even (ignore)
3089 int ignore ATTRIBUTE_UNUSED;
3090{
3091 /* Never make frag if expect extra pass. */
3092 if (!need_pass_2)
3093 frag_align (1, 0, 0);
3094
3095 record_alignment (now_seg, 1);
3096
3097 demand_empty_rest_of_line ();
3098}
3099
3100static void
3101s_ltorg (ignored)
3102 int ignored ATTRIBUTE_UNUSED;
3103{
3d0c9500
NC
3104 unsigned int entry;
3105 literal_pool * pool;
b99bd4ef
NC
3106 char sym_name[20];
3107
3d0c9500
NC
3108 pool = find_literal_pool ();
3109 if (pool == NULL
3110 || pool->symbol == NULL
3111 || pool->next_free_entry == 0)
b99bd4ef
NC
3112 return;
3113
3114 /* Align pool as you have word accesses.
3115 Only make a frag if we have to. */
3116 if (!need_pass_2)
3117 frag_align (2, 0, 0);
3118
3119 record_alignment (now_seg, 2);
3120
3d0c9500 3121 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3122
3d0c9500 3123 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3124 (valueT) frag_now_fix (), frag_now);
3d0c9500 3125 symbol_table_insert (pool->symbol);
b99bd4ef 3126
3d0c9500 3127 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3128
3129#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3130 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3131#endif
3132
3d0c9500 3133 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3134 /* First output the expression in the instruction to the pool. */
3d0c9500 3135 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3136
3d0c9500
NC
3137 /* Mark the pool as empty. */
3138 pool->next_free_entry = 0;
3139 pool->symbol = NULL;
b99bd4ef
NC
3140}
3141
3142/* Same as s_align_ptwo but align 0 => align 2. */
3143
3144static void
3145s_align (unused)
3146 int unused ATTRIBUTE_UNUSED;
3147{
3148 register int temp;
3149 register long temp_fill;
3150 long max_alignment = 15;
3151
3152 temp = get_absolute_expression ();
3153 if (temp > max_alignment)
f03698e6 3154 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3155 else if (temp < 0)
3156 {
f03698e6 3157 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3158 temp = 0;
3159 }
3160
3161 if (*input_line_pointer == ',')
3162 {
3163 input_line_pointer++;
3164 temp_fill = get_absolute_expression ();
3165 }
3166 else
3167 temp_fill = 0;
3168
3169 if (!temp)
3170 temp = 2;
3171
3172 /* Only make a frag if we HAVE to. */
3173 if (temp && !need_pass_2)
3174 frag_align (temp, (int) temp_fill, 0);
3175 demand_empty_rest_of_line ();
3176
3177 record_alignment (now_seg, temp);
3178}
3179
3180static void
3181s_force_thumb (ignore)
3182 int ignore ATTRIBUTE_UNUSED;
3183{
3184 /* If we are not already in thumb mode go into it, EVEN if
3185 the target processor does not support thumb instructions.
3186 This is used by gcc/config/arm/lib1funcs.asm for example
3187 to compile interworking support functions even if the
3188 target processor should not support interworking. */
3189 if (! thumb_mode)
3190 {
3191 thumb_mode = 2;
3192
3193 record_alignment (now_seg, 1);
3194 }
3195
3196 demand_empty_rest_of_line ();
3197}
3198
3199static void
3200s_thumb_func (ignore)
3201 int ignore ATTRIBUTE_UNUSED;
3202{
3203 if (! thumb_mode)
3204 opcode_select (16);
3205
3206 /* The following label is the name/address of the start of a Thumb function.
3207 We need to know this for the interworking support. */
b34976b6 3208 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3209
3210 demand_empty_rest_of_line ();
3211}
3212
3213/* Perform a .set directive, but also mark the alias as
3214 being a thumb function. */
3215
3216static void
3217s_thumb_set (equiv)
3218 int equiv;
3219{
3220 /* XXX the following is a duplicate of the code for s_set() in read.c
3221 We cannot just call that code as we need to get at the symbol that
3222 is created. */
3223 register char * name;
3224 register char delim;
3225 register char * end_name;
3226 register symbolS * symbolP;
3227
3228 /* Especial apologies for the random logic:
3229 This just grew, and could be parsed much more simply!
3230 Dean - in haste. */
3231 name = input_line_pointer;
3232 delim = get_symbol_end ();
3233 end_name = input_line_pointer;
3234 *end_name = delim;
3235
3236 SKIP_WHITESPACE ();
3237
3238 if (*input_line_pointer != ',')
3239 {
3240 *end_name = 0;
f03698e6 3241 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3242 *end_name = delim;
3243 ignore_rest_of_line ();
3244 return;
3245 }
3246
3247 input_line_pointer++;
3248 *end_name = 0;
3249
3250 if (name[0] == '.' && name[1] == '\0')
3251 {
3252 /* XXX - this should not happen to .thumb_set. */
3253 abort ();
3254 }
3255
3256 if ((symbolP = symbol_find (name)) == NULL
3257 && (symbolP = md_undefined_symbol (name)) == NULL)
3258 {
3259#ifndef NO_LISTING
3260 /* When doing symbol listings, play games with dummy fragments living
3261 outside the normal fragment chain to record the file and line info
3262 for this symbol. */
3263 if (listing & LISTING_SYMBOLS)
3264 {
3265 extern struct list_info_struct * listing_tail;
3266 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3267
3268 memset (dummy_frag, 0, sizeof (fragS));
3269 dummy_frag->fr_type = rs_fill;
3270 dummy_frag->line = listing_tail;
3271 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3272 dummy_frag->fr_symbol = symbolP;
3273 }
3274 else
3275#endif
3276 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3277
3278#ifdef OBJ_COFF
3279 /* "set" symbols are local unless otherwise specified. */
3280 SF_SET_LOCAL (symbolP);
3281#endif /* OBJ_COFF */
3282 } /* Make a new symbol. */
3283
3284 symbol_table_insert (symbolP);
3285
3286 * end_name = delim;
3287
3288 if (equiv
3289 && S_IS_DEFINED (symbolP)
3290 && S_GET_SEGMENT (symbolP) != reg_section)
3291 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3292
3293 pseudo_set (symbolP);
3294
3295 demand_empty_rest_of_line ();
3296
3297 /* XXX Now we come to the Thumb specific bit of code. */
3298
3299 THUMB_SET_FUNC (symbolP, 1);
3300 ARM_SET_THUMB (symbolP, 1);
3301#if defined OBJ_ELF || defined OBJ_COFF
3302 ARM_SET_INTERWORK (symbolP, support_interwork);
3303#endif
3304}
3305
b99bd4ef
NC
3306static void
3307opcode_select (width)
3308 int width;
3309{
3310 switch (width)
3311 {
3312 case 16:
3313 if (! thumb_mode)
3314 {
b89dddec 3315 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3316 as_bad (_("selected processor does not support THUMB opcodes"));
3317
3318 thumb_mode = 1;
3319 /* No need to force the alignment, since we will have been
3320 coming from ARM mode, which is word-aligned. */
3321 record_alignment (now_seg, 1);
3322 }
6057a28f 3323 mapping_state (MAP_THUMB);
b99bd4ef
NC
3324 break;
3325
3326 case 32:
3327 if (thumb_mode)
3328 {
03b1477f 3329 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3330 as_bad (_("selected processor does not support ARM opcodes"));
3331
3332 thumb_mode = 0;
3333
3334 if (!need_pass_2)
cc8a6dd0 3335 frag_align (2, 0, 0);
b99bd4ef 3336
cc8a6dd0 3337 record_alignment (now_seg, 1);
b99bd4ef 3338 }
6057a28f 3339 mapping_state (MAP_ARM);
b99bd4ef
NC
3340 break;
3341
3342 default:
3343 as_bad (_("invalid instruction size selected (%d)"), width);
3344 }
3345}
3346
3347static void
3348s_arm (ignore)
3349 int ignore ATTRIBUTE_UNUSED;
3350{
3351 opcode_select (32);
3352 demand_empty_rest_of_line ();
3353}
3354
3355static void
3356s_thumb (ignore)
3357 int ignore ATTRIBUTE_UNUSED;
3358{
3359 opcode_select (16);
3360 demand_empty_rest_of_line ();
3361}
3362
3363static void
3364s_code (unused)
3365 int unused ATTRIBUTE_UNUSED;
3366{
3367 register int temp;
3368
3369 temp = get_absolute_expression ();
3370 switch (temp)
3371 {
3372 case 16:
3373 case 32:
3374 opcode_select (temp);
3375 break;
3376
3377 default:
3378 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3379 }
3380}
3381
3382static void
3383end_of_line (str)
f03698e6 3384 char *str;
b99bd4ef
NC
3385{
3386 skip_whitespace (str);
3387
f03698e6
RE
3388 if (*str != '\0' && !inst.error)
3389 inst.error = _("garbage following instruction");
b99bd4ef
NC
3390}
3391
3392static int
3393skip_past_comma (str)
3394 char ** str;
3395{
3396 char * p = * str, c;
3397 int comma = 0;
3398
3399 while ((c = *p) == ' ' || c == ',')
3400 {
3401 p++;
3402 if (c == ',' && comma++)
3403 return FAIL;
3404 }
3405
3406 if (c == '\0')
3407 return FAIL;
3408
3409 *str = p;
3410 return comma ? SUCCESS : FAIL;
3411}
3412
3413/* A standard register must be given at this point.
3414 SHIFT is the place to put it in inst.instruction.
3415 Restores input start point on error.
3416 Returns the reg#, or FAIL. */
3417
3418static int
3419reg_required_here (str, shift)
3420 char ** str;
3421 int shift;
3422{
3423 static char buff [128]; /* XXX */
3424 int reg;
3425 char * start = * str;
3426
6c43fab6 3427 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3428 {
3429 if (shift >= 0)
3430 inst.instruction |= reg << shift;
3431 return reg;
3432 }
3433
3434 /* Restore the start point, we may have got a reg of the wrong class. */
3435 *str = start;
3436
3437 /* In the few cases where we might be able to accept something else
3438 this error can be overridden. */
f03698e6 3439 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3440 inst.error = buff;
3441
3442 return FAIL;
3443}
3444
5a6c6817 3445/* A Intel Wireless MMX technology register
e16bb312
NC
3446 must be given at this point.
3447 Shift is the place to put it in inst.instruction.
3448 Restores input start point on err.
3449 Returns the reg#, or FAIL. */
3450
3451static int
3452wreg_required_here (str, shift, reg_type)
3453 char ** str;
3454 int shift;
3455 enum wreg_type reg_type;
3456{
3457 static char buff [128];
3458 int reg;
3459 char * start = *str;
3460
3461 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3462 {
3463 if (wr_register (reg)
3464 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3465 {
3466 if (shift >= 0)
3467 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3468 return reg;
3469 }
3470 else if (wc_register (reg)
3471 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3472 {
3473 if (shift >= 0)
3474 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3475 return reg;
3476 }
3477 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3478 {
3479 if (shift >= 0)
3480 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3481 return reg;
3482 }
3483 }
3484
3485 /* Restore the start point, we may have got a reg of the wrong class. */
3486 *str = start;
3487
3488 /* In the few cases where we might be able to accept
3489 something else this error can be overridden. */
5a6c6817 3490 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3491 inst.error = buff;
3492
3493 return FAIL;
3494}
3495
05d2d07e 3496static const struct asm_psr *
b99bd4ef
NC
3497arm_psr_parse (ccp)
3498 register char ** ccp;
3499{
3500 char * start = * ccp;
3501 char c;
3502 char * p;
05d2d07e 3503 const struct asm_psr * psr;
b99bd4ef
NC
3504
3505 p = start;
3506
3507 /* Skip to the end of the next word in the input stream. */
3508 do
3509 {
3510 c = *p++;
3511 }
3882b010 3512 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3513
3514 /* Terminate the word. */
3515 *--p = 0;
3516
3517 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3518 feature for ease of use and backwards compatibility. */
3519 if (!strncmp (start, "cpsr", 4))
3520 strncpy (start, "CPSR", 4);
3521 else if (!strncmp (start, "spsr", 4))
3522 strncpy (start, "SPSR", 4);
3523
3524 /* Now locate the word in the psr hash table. */
05d2d07e 3525 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3526
3527 /* Restore the input stream. */
3528 *p = c;
3529
3530 /* If we found a valid match, advance the
3531 stream pointer past the end of the word. */
3532 *ccp = p;
3533
3534 return psr;
3535}
3536
3537/* Parse the input looking for a PSR flag. */
3538
3539static int
3540psr_required_here (str)
3541 char ** str;
3542{
3543 char * start = * str;
05d2d07e 3544 const struct asm_psr * psr;
b99bd4ef
NC
3545
3546 psr = arm_psr_parse (str);
3547
3548 if (psr)
3549 {
3550 /* If this is the SPSR that is being modified, set the R bit. */
3551 if (! psr->cpsr)
3552 inst.instruction |= SPSR_BIT;
3553
3554 /* Set the psr flags in the MSR instruction. */
3555 inst.instruction |= psr->field << PSR_SHIFT;
3556
3557 return SUCCESS;
3558 }
3559
3560 /* In the few cases where we might be able to accept
3561 something else this error can be overridden. */
3562 inst.error = _("flag for {c}psr instruction expected");
3563
3564 /* Restore the start point. */
3565 *str = start;
3566 return FAIL;
3567}
3568
3569static int
3570co_proc_number (str)
6c43fab6 3571 char **str;
b99bd4ef
NC
3572{
3573 int processor, pchar;
6c43fab6 3574 char *start;
b99bd4ef 3575
6c43fab6
RE
3576 skip_whitespace (*str);
3577 start = *str;
b99bd4ef
NC
3578
3579 /* The data sheet seems to imply that just a number on its own is valid
3580 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3581 accept either. */
6c43fab6
RE
3582 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3583 == FAIL)
b99bd4ef 3584 {
6c43fab6
RE
3585 *str = start;
3586
3587 pchar = *(*str)++;
3588 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3589 {
6c43fab6
RE
3590 processor = pchar - '0';
3591 if (**str >= '0' && **str <= '9')
b99bd4ef 3592 {
6c43fab6
RE
3593 processor = processor * 10 + *(*str)++ - '0';
3594 if (processor > 15)
3595 {
f03698e6 3596 inst.error = _("illegal co-processor number");
6c43fab6
RE
3597 return FAIL;
3598 }
b99bd4ef
NC
3599 }
3600 }
6c43fab6
RE
3601 else
3602 {
f03698e6 3603 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
3604 return FAIL;
3605 }
b99bd4ef
NC
3606 }
3607
3608 inst.instruction |= processor << 8;
3609 return SUCCESS;
3610}
3611
3612static int
3613cp_opc_expr (str, where, length)
3614 char ** str;
3615 int where;
3616 int length;
3617{
3618 expressionS expr;
3619
3620 skip_whitespace (* str);
3621
3622 memset (&expr, '\0', sizeof (expr));
3623
3624 if (my_get_expression (&expr, str))
3625 return FAIL;
3626 if (expr.X_op != O_constant)
3627 {
3628 inst.error = _("bad or missing expression");
3629 return FAIL;
3630 }
3631
3632 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3633 {
3634 inst.error = _("immediate co-processor expression too large");
3635 return FAIL;
3636 }
3637
3638 inst.instruction |= expr.X_add_number << where;
3639 return SUCCESS;
3640}
3641
3642static int
3643cp_reg_required_here (str, where)
3644 char ** str;
3645 int where;
3646{
3647 int reg;
3648 char * start = *str;
3649
6c43fab6 3650 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3651 {
b99bd4ef
NC
3652 inst.instruction |= reg << where;
3653 return reg;
3654 }
3655
3656 /* In the few cases where we might be able to accept something else
3657 this error can be overridden. */
f03698e6 3658 inst.error = _("co-processor register expected");
b99bd4ef
NC
3659
3660 /* Restore the start point. */
3661 *str = start;
3662 return FAIL;
3663}
3664
3665static int
3666fp_reg_required_here (str, where)
3667 char ** str;
3668 int where;
3669{
3670 int reg;
3671 char * start = * str;
3672
6c43fab6 3673 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3674 {
b99bd4ef
NC
3675 inst.instruction |= reg << where;
3676 return reg;
3677 }
3678
3679 /* In the few cases where we might be able to accept something else
3680 this error can be overridden. */
f03698e6 3681 inst.error = _("floating point register expected");
b99bd4ef
NC
3682
3683 /* Restore the start point. */
3684 *str = start;
3685 return FAIL;
3686}
3687
3688static int
3689cp_address_offset (str)
3690 char ** str;
3691{
3692 int offset;
3693
3694 skip_whitespace (* str);
3695
3696 if (! is_immediate_prefix (**str))
3697 {
3698 inst.error = _("immediate expression expected");
3699 return FAIL;
3700 }
3701
3702 (*str)++;
3703
3704 if (my_get_expression (& inst.reloc.exp, str))
3705 return FAIL;
3706
3707 if (inst.reloc.exp.X_op == O_constant)
3708 {
3709 offset = inst.reloc.exp.X_add_number;
3710
3711 if (offset & 3)
3712 {
3713 inst.error = _("co-processor address must be word aligned");
3714 return FAIL;
3715 }
3716
3717 if (offset > 1023 || offset < -1023)
3718 {
3719 inst.error = _("offset too large");
3720 return FAIL;
3721 }
3722
3723 if (offset >= 0)
3724 inst.instruction |= INDEX_UP;
3725 else
3726 offset = -offset;
3727
3728 inst.instruction |= offset >> 2;
3729 }
3730 else
3731 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3732
3733 return SUCCESS;
3734}
3735
3736static int
bfae80f2 3737cp_address_required_here (str, wb_ok)
b99bd4ef 3738 char ** str;
bfae80f2 3739 int wb_ok;
b99bd4ef
NC
3740{
3741 char * p = * str;
3742 int pre_inc = 0;
3743 int write_back = 0;
3744
3745 if (*p == '[')
3746 {
3747 int reg;
3748
3749 p++;
3750 skip_whitespace (p);
3751
3752 if ((reg = reg_required_here (& p, 16)) == FAIL)
3753 return FAIL;
3754
3755 skip_whitespace (p);
3756
3757 if (*p == ']')
3758 {
3759 p++;
3760
f02232aa
NC
3761 skip_whitespace (p);
3762
3763 if (*p == '\0')
b99bd4ef 3764 {
f02232aa
NC
3765 /* As an extension to the official ARM syntax we allow:
3766
3767 [Rn]
3768
3769 as a short hand for:
3770
3771 [Rn,#0] */
3772 inst.instruction |= PRE_INDEX | INDEX_UP;
3773 *str = p;
3774 return SUCCESS;
3775 }
3776
3777 if (skip_past_comma (& p) == FAIL)
3778 {
3779 inst.error = _("comma expected after closing square bracket");
3780 return FAIL;
3781 }
b99bd4ef 3782
f02232aa
NC
3783 skip_whitespace (p);
3784
3785 if (*p == '#')
3786 {
3787 if (wb_ok)
b99bd4ef 3788 {
f02232aa
NC
3789 /* [Rn], #expr */
3790 write_back = WRITE_BACK;
3791
3792 if (reg == REG_PC)
3793 {
3794 inst.error = _("pc may not be used in post-increment");
3795 return FAIL;
3796 }
3797
3798 if (cp_address_offset (& p) == FAIL)
3799 return FAIL;
b99bd4ef 3800 }
f02232aa
NC
3801 else
3802 pre_inc = PRE_INDEX | INDEX_UP;
3803 }
3804 else if (*p == '{')
3805 {
3806 int option;
b99bd4ef 3807
f02232aa
NC
3808 /* [Rn], {<expr>} */
3809 p++;
3810
3811 skip_whitespace (p);
3812
3813 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3814 return FAIL;
f02232aa
NC
3815
3816 if (inst.reloc.exp.X_op == O_constant)
3817 {
3818 option = inst.reloc.exp.X_add_number;
3819
3820 if (option > 255 || option < 0)
3821 {
3822 inst.error = _("'option' field too large");
3823 return FAIL;
3824 }
3825
3826 skip_whitespace (p);
3827
3828 if (*p != '}')
3829 {
3830 inst.error = _("'}' expected at end of 'option' field");
3831 return FAIL;
3832 }
3833 else
3834 {
3835 p++;
3836 inst.instruction |= option;
3837 inst.instruction |= INDEX_UP;
3838 }
3839 }
3840 else
3841 {
3842 inst.error = _("non-constant expressions for 'option' field not supported");
3843 return FAIL;
3844 }
b99bd4ef
NC
3845 }
3846 else
f02232aa
NC
3847 {
3848 inst.error = _("# or { expected after comma");
3849 return FAIL;
3850 }
b99bd4ef
NC
3851 }
3852 else
3853 {
3854 /* '['Rn, #expr']'[!] */
3855
3856 if (skip_past_comma (& p) == FAIL)
3857 {
3858 inst.error = _("pre-indexed expression expected");
3859 return FAIL;
3860 }
3861
3862 pre_inc = PRE_INDEX;
3863
3864 if (cp_address_offset (& p) == FAIL)
3865 return FAIL;
3866
3867 skip_whitespace (p);
3868
3869 if (*p++ != ']')
3870 {
3871 inst.error = _("missing ]");
3872 return FAIL;
3873 }
3874
3875 skip_whitespace (p);
3876
bfae80f2 3877 if (wb_ok && *p == '!')
b99bd4ef
NC
3878 {
3879 if (reg == REG_PC)
3880 {
3881 inst.error = _("pc may not be used with write-back");
3882 return FAIL;
3883 }
3884
3885 p++;
3886 write_back = WRITE_BACK;
3887 }
3888 }
3889 }
3890 else
3891 {
3892 if (my_get_expression (&inst.reloc.exp, &p))
3893 return FAIL;
3894
3895 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3896 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3897 inst.reloc.pc_rel = 1;
3898 inst.instruction |= (REG_PC << 16);
3899 pre_inc = PRE_INDEX;
3900 }
3901
3902 inst.instruction |= write_back | pre_inc;
3903 *str = p;
3904 return SUCCESS;
3905}
3906
e16bb312
NC
3907static int
3908cp_byte_address_offset (str)
3909 char ** str;
3910{
3911 int offset;
3912
3913 skip_whitespace (* str);
3914
3915 if (! is_immediate_prefix (**str))
3916 {
3917 inst.error = _("immediate expression expected");
3918 return FAIL;
3919 }
3920
3921 (*str)++;
3922
3923 if (my_get_expression (& inst.reloc.exp, str))
3924 return FAIL;
3925
3926 if (inst.reloc.exp.X_op == O_constant)
3927 {
3928 offset = inst.reloc.exp.X_add_number;
3929
3930 if (offset > 255 || offset < -255)
3931 {
3932 inst.error = _("offset too large");
3933 return FAIL;
3934 }
3935
3936 if (offset >= 0)
3937 inst.instruction |= INDEX_UP;
3938 else
3939 offset = -offset;
3940
3941 inst.instruction |= offset;
3942 }
3943 else
3944 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3945
3946 return SUCCESS;
3947}
3948
3949static int
3950cp_byte_address_required_here (str)
3951 char ** str;
3952{
3953 char * p = * str;
3954 int pre_inc = 0;
3955 int write_back = 0;
3956
3957 if (*p == '[')
3958 {
3959 int reg;
3960
3961 p++;
3962 skip_whitespace (p);
3963
3964 if ((reg = reg_required_here (& p, 16)) == FAIL)
3965 return FAIL;
3966
3967 skip_whitespace (p);
3968
3969 if (*p == ']')
3970 {
3971 p++;
3972
3973 if (skip_past_comma (& p) == SUCCESS)
3974 {
3975 /* [Rn], #expr */
3976 write_back = WRITE_BACK;
3977
3978 if (reg == REG_PC)
3979 {
3980 inst.error = _("pc may not be used in post-increment");
3981 return FAIL;
3982 }
3983
3984 if (cp_byte_address_offset (& p) == FAIL)
3985 return FAIL;
3986 }
3987 else
3988 pre_inc = PRE_INDEX | INDEX_UP;
3989 }
3990 else
3991 {
3992 /* '['Rn, #expr']'[!] */
3993
3994 if (skip_past_comma (& p) == FAIL)
3995 {
3996 inst.error = _("pre-indexed expression expected");
3997 return FAIL;
3998 }
3999
4000 pre_inc = PRE_INDEX;
4001
4002 if (cp_byte_address_offset (& p) == FAIL)
4003 return FAIL;
4004
4005 skip_whitespace (p);
4006
4007 if (*p++ != ']')
4008 {
4009 inst.error = _("missing ]");
4010 return FAIL;
4011 }
4012
4013 skip_whitespace (p);
4014
4015 if (*p == '!')
4016 {
4017 if (reg == REG_PC)
4018 {
4019 inst.error = _("pc may not be used with write-back");
4020 return FAIL;
4021 }
4022
4023 p++;
4024 write_back = WRITE_BACK;
4025 }
4026 }
4027 }
4028 else
4029 {
4030 if (my_get_expression (&inst.reloc.exp, &p))
4031 return FAIL;
4032
4033 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4034 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4035 inst.reloc.pc_rel = 1;
4036 inst.instruction |= (REG_PC << 16);
4037 pre_inc = PRE_INDEX;
4038 }
4039
4040 inst.instruction |= write_back | pre_inc;
4041 *str = p;
4042 return SUCCESS;
4043}
4044
b99bd4ef 4045static void
f2b7cb0a 4046do_empty (str)
b99bd4ef 4047 char * str;
b99bd4ef
NC
4048{
4049 /* Do nothing really. */
b99bd4ef 4050 end_of_line (str);
b99bd4ef
NC
4051}
4052
4053static void
f2b7cb0a 4054do_mrs (str)
b99bd4ef 4055 char *str;
b99bd4ef
NC
4056{
4057 int skip = 0;
4058
4059 /* Only one syntax. */
4060 skip_whitespace (str);
4061
4062 if (reg_required_here (&str, 12) == FAIL)
4063 {
4064 inst.error = BAD_ARGS;
4065 return;
4066 }
4067
4068 if (skip_past_comma (&str) == FAIL)
4069 {
4070 inst.error = _("comma expected after register name");
4071 return;
4072 }
4073
4074 skip_whitespace (str);
4075
4076 if ( strcmp (str, "CPSR") == 0
4077 || strcmp (str, "SPSR") == 0
2d2255b5 4078 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4079 || strcmp (str, "cpsr") == 0
4080 || strcmp (str, "spsr") == 0)
4081 skip = 4;
4082
2d2255b5 4083 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4084 else if ( strcmp (str, "cpsr_all") == 0
4085 || strcmp (str, "spsr_all") == 0)
4086 skip = 8;
4087 else
4088 {
f03698e6 4089 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4090 return;
4091 }
4092
4093 if (* str == 's' || * str == 'S')
4094 inst.instruction |= SPSR_BIT;
4095 str += skip;
4096
b99bd4ef
NC
4097 end_of_line (str);
4098}
4099
4100/* Two possible forms:
4101 "{C|S}PSR_<field>, Rm",
4102 "{C|S}PSR_f, #expression". */
4103
4104static void
f2b7cb0a 4105do_msr (str)
b99bd4ef 4106 char * str;
b99bd4ef
NC
4107{
4108 skip_whitespace (str);
4109
4110 if (psr_required_here (& str) == FAIL)
4111 return;
4112
4113 if (skip_past_comma (& str) == FAIL)
4114 {
4115 inst.error = _("comma missing after psr flags");
4116 return;
4117 }
4118
4119 skip_whitespace (str);
4120
4121 if (reg_required_here (& str, 0) != FAIL)
4122 {
4123 inst.error = NULL;
b99bd4ef
NC
4124 end_of_line (str);
4125 return;
4126 }
4127
4128 if (! is_immediate_prefix (* str))
4129 {
4130 inst.error =
4131 _("only a register or immediate value can follow a psr flag");
4132 return;
4133 }
4134
4135 str ++;
4136 inst.error = NULL;
4137
4138 if (my_get_expression (& inst.reloc.exp, & str))
4139 {
4140 inst.error =
4141 _("only a register or immediate value can follow a psr flag");
4142 return;
4143 }
4144
4145#if 0 /* The first edition of the ARM architecture manual stated that
4146 writing anything other than the flags with an immediate operation
4147 had UNPREDICTABLE effects. This constraint was removed in the
4148 second edition of the specification. */
4149 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4150 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4151 {
4152 inst.error = _("immediate value cannot be used to set this field");
4153 return;
4154 }
4155#endif
4156
f2b7cb0a 4157 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4158
4159 if (inst.reloc.exp.X_add_symbol)
4160 {
4161 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4162 inst.reloc.pc_rel = 0;
4163 }
4164 else
4165 {
4166 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4167
4168 if (value == (unsigned) FAIL)
4169 {
f03698e6 4170 inst.error = _("invalid constant");
b99bd4ef
NC
4171 return;
4172 }
4173
4174 inst.instruction |= value;
4175 }
4176
4177 inst.error = NULL;
b99bd4ef
NC
4178 end_of_line (str);
4179}
4180
4181/* Long Multiply Parser
4182 UMULL RdLo, RdHi, Rm, Rs
4183 SMULL RdLo, RdHi, Rm, Rs
4184 UMLAL RdLo, RdHi, Rm, Rs
4185 SMLAL RdLo, RdHi, Rm, Rs. */
4186
4187static void
f2b7cb0a 4188do_mull (str)
b99bd4ef 4189 char * str;
b99bd4ef
NC
4190{
4191 int rdlo, rdhi, rm, rs;
4192
4193 /* Only one format "rdlo, rdhi, rm, rs". */
4194 skip_whitespace (str);
4195
4196 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4197 {
4198 inst.error = BAD_ARGS;
4199 return;
4200 }
4201
4202 if (skip_past_comma (&str) == FAIL
4203 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4204 {
4205 inst.error = BAD_ARGS;
4206 return;
4207 }
4208
4209 if (skip_past_comma (&str) == FAIL
4210 || (rm = reg_required_here (&str, 0)) == FAIL)
4211 {
4212 inst.error = BAD_ARGS;
4213 return;
4214 }
4215
4216 /* rdhi, rdlo and rm must all be different. */
4217 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4218 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4219
4220 if (skip_past_comma (&str) == FAIL
4221 || (rs = reg_required_here (&str, 8)) == FAIL)
4222 {
4223 inst.error = BAD_ARGS;
4224 return;
4225 }
4226
4227 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4228 {
4229 inst.error = BAD_PC;
4230 return;
4231 }
4232
b99bd4ef 4233 end_of_line (str);
b99bd4ef
NC
4234}
4235
4236static void
f2b7cb0a 4237do_mul (str)
b99bd4ef 4238 char * str;
b99bd4ef
NC
4239{
4240 int rd, rm;
4241
4242 /* Only one format "rd, rm, rs". */
4243 skip_whitespace (str);
4244
4245 if ((rd = reg_required_here (&str, 16)) == FAIL)
4246 {
4247 inst.error = BAD_ARGS;
4248 return;
4249 }
4250
4251 if (rd == REG_PC)
4252 {
4253 inst.error = BAD_PC;
4254 return;
4255 }
4256
4257 if (skip_past_comma (&str) == FAIL
4258 || (rm = reg_required_here (&str, 0)) == FAIL)
4259 {
4260 inst.error = BAD_ARGS;
4261 return;
4262 }
4263
4264 if (rm == REG_PC)
4265 {
4266 inst.error = BAD_PC;
4267 return;
4268 }
4269
4270 if (rm == rd)
4271 as_tsktsk (_("rd and rm should be different in mul"));
4272
4273 if (skip_past_comma (&str) == FAIL
4274 || (rm = reg_required_here (&str, 8)) == FAIL)
4275 {
4276 inst.error = BAD_ARGS;
4277 return;
4278 }
4279
4280 if (rm == REG_PC)
4281 {
4282 inst.error = BAD_PC;
4283 return;
4284 }
4285
b99bd4ef 4286 end_of_line (str);
b99bd4ef
NC
4287}
4288
4289static void
f2b7cb0a 4290do_mla (str)
b99bd4ef 4291 char * str;
b99bd4ef
NC
4292{
4293 int rd, rm;
4294
4295 /* Only one format "rd, rm, rs, rn". */
4296 skip_whitespace (str);
4297
4298 if ((rd = reg_required_here (&str, 16)) == FAIL)
4299 {
4300 inst.error = BAD_ARGS;
4301 return;
4302 }
4303
4304 if (rd == REG_PC)
4305 {
4306 inst.error = BAD_PC;
4307 return;
4308 }
4309
4310 if (skip_past_comma (&str) == FAIL
4311 || (rm = reg_required_here (&str, 0)) == FAIL)
4312 {
4313 inst.error = BAD_ARGS;
4314 return;
4315 }
4316
4317 if (rm == REG_PC)
4318 {
4319 inst.error = BAD_PC;
4320 return;
4321 }
4322
4323 if (rm == rd)
4324 as_tsktsk (_("rd and rm should be different in mla"));
4325
4326 if (skip_past_comma (&str) == FAIL
4327 || (rd = reg_required_here (&str, 8)) == FAIL
4328 || skip_past_comma (&str) == FAIL
4329 || (rm = reg_required_here (&str, 12)) == FAIL)
4330 {
4331 inst.error = BAD_ARGS;
4332 return;
4333 }
4334
4335 if (rd == REG_PC || rm == REG_PC)
4336 {
4337 inst.error = BAD_PC;
4338 return;
4339 }
4340
b99bd4ef 4341 end_of_line (str);
b99bd4ef
NC
4342}
4343
4344/* Expects *str -> the characters "acc0", possibly with leading blanks.
4345 Advances *str to the next non-alphanumeric.
4346 Returns 0, or else FAIL (in which case sets inst.error).
4347
4348 (In a future XScale, there may be accumulators other than zero.
4349 At that time this routine and its callers can be upgraded to suit.) */
4350
4351static int
4352accum0_required_here (str)
4353 char ** str;
4354{
4355 static char buff [128]; /* Note the address is taken. Hence, static. */
4356 char * p = * str;
4357 char c;
4358 int result = 0; /* The accum number. */
4359
4360 skip_whitespace (p);
4361
4362 *str = p; /* Advance caller's string pointer too. */
4363 c = *p++;
3882b010 4364 while (ISALNUM (c))
b99bd4ef
NC
4365 c = *p++;
4366
4367 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4368
4369 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4370 {
4371 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4372 inst.error = buff;
4373 result = FAIL;
4374 }
4375
4376 *p = c; /* Unzap. */
4377 *str = p; /* Caller's string pointer to after match. */
4378 return result;
4379}
4380
4381/* Expects **str -> after a comma. May be leading blanks.
4382 Advances *str, recognizing a load mode, and setting inst.instruction.
4383 Returns rn, or else FAIL (in which case may set inst.error
4384 and not advance str)
4385
4386 Note: doesn't know Rd, so no err checks that require such knowledge. */
4387
4388static int
4389ld_mode_required_here (string)
4390 char ** string;
4391{
4392 char * str = * string;
4393 int rn;
4394 int pre_inc = 0;
4395
4396 skip_whitespace (str);
4397
4398 if (* str == '[')
4399 {
4400 str++;
4401
4402 skip_whitespace (str);
4403
4404 if ((rn = reg_required_here (& str, 16)) == FAIL)
4405 return FAIL;
4406
4407 skip_whitespace (str);
4408
4409 if (* str == ']')
4410 {
4411 str ++;
4412
4413 if (skip_past_comma (& str) == SUCCESS)
4414 {
4415 /* [Rn],... (post inc) */
90e4755a 4416 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4417 return FAIL;
4418 }
4419 else /* [Rn] */
4420 {
cc8a6dd0 4421 skip_whitespace (str);
b99bd4ef 4422
cc8a6dd0
KH
4423 if (* str == '!')
4424 {
4425 str ++;
4426 inst.instruction |= WRITE_BACK;
4427 }
b99bd4ef
NC
4428
4429 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4430 pre_inc = 1;
4431 }
4432 }
4433 else /* [Rn,...] */
4434 {
4435 if (skip_past_comma (& str) == FAIL)
4436 {
4437 inst.error = _("pre-indexed expression expected");
4438 return FAIL;
4439 }
4440
4441 pre_inc = 1;
4442
90e4755a 4443 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4444 return FAIL;
4445
4446 skip_whitespace (str);
4447
4448 if (* str ++ != ']')
4449 {
4450 inst.error = _("missing ]");
4451 return FAIL;
4452 }
4453
4454 skip_whitespace (str);
4455
4456 if (* str == '!')
4457 {
4458 str ++;
4459 inst.instruction |= WRITE_BACK;
4460 }
4461 }
4462 }
4463 else if (* str == '=') /* ldr's "r,=label" syntax */
4464 /* We should never reach here, because <text> = <expression> is
4465 caught gas/read.c read_a_source_file() as a .set operation. */
4466 return FAIL;
4467 else /* PC +- 8 bit immediate offset. */
4468 {
4469 if (my_get_expression (& inst.reloc.exp, & str))
4470 return FAIL;
4471
4472 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4473 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4474 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4475 inst.reloc.pc_rel = 1;
4476 inst.instruction |= (REG_PC << 16);
4477
4478 rn = REG_PC;
4479 pre_inc = 1;
4480 }
4481
4482 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4483 * string = str;
4484
4485 return rn;
4486}
4487
4488/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4489 SMLAxy{cond} Rd,Rm,Rs,Rn
4490 SMLAWy{cond} Rd,Rm,Rs,Rn
4491 Error if any register is R15. */
4492
4493static void
f2b7cb0a 4494do_smla (str)
b99bd4ef 4495 char * str;
b99bd4ef
NC
4496{
4497 int rd, rm, rs, rn;
4498
4499 skip_whitespace (str);
4500
4501 if ((rd = reg_required_here (& str, 16)) == FAIL
4502 || skip_past_comma (& str) == FAIL
4503 || (rm = reg_required_here (& str, 0)) == FAIL
4504 || skip_past_comma (& str) == FAIL
4505 || (rs = reg_required_here (& str, 8)) == FAIL
4506 || skip_past_comma (& str) == FAIL
4507 || (rn = reg_required_here (& str, 12)) == FAIL)
4508 inst.error = BAD_ARGS;
4509
4510 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4511 inst.error = BAD_PC;
4512
b99bd4ef
NC
4513 else
4514 end_of_line (str);
4515}
4516
4517/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4518 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4519 Error if any register is R15.
4520 Warning if Rdlo == Rdhi. */
4521
4522static void
f2b7cb0a 4523do_smlal (str)
b99bd4ef 4524 char * str;
b99bd4ef
NC
4525{
4526 int rdlo, rdhi, rm, rs;
4527
4528 skip_whitespace (str);
4529
4530 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4531 || skip_past_comma (& str) == FAIL
4532 || (rdhi = reg_required_here (& str, 16)) == FAIL
4533 || skip_past_comma (& str) == FAIL
4534 || (rm = reg_required_here (& str, 0)) == FAIL
4535 || skip_past_comma (& str) == FAIL
4536 || (rs = reg_required_here (& str, 8)) == FAIL)
4537 {
4538 inst.error = BAD_ARGS;
4539 return;
4540 }
4541
4542 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4543 {
4544 inst.error = BAD_PC;
4545 return;
4546 }
4547
4548 if (rdlo == rdhi)
4549 as_tsktsk (_("rdhi and rdlo must be different"));
4550
f2b7cb0a 4551 end_of_line (str);
b99bd4ef
NC
4552}
4553
4554/* ARM V5E (El Segundo) signed-multiply (argument parse)
4555 SMULxy{cond} Rd,Rm,Rs
4556 Error if any register is R15. */
4557
4558static void
f2b7cb0a 4559do_smul (str)
b99bd4ef 4560 char * str;
b99bd4ef
NC
4561{
4562 int rd, rm, rs;
4563
4564 skip_whitespace (str);
4565
4566 if ((rd = reg_required_here (& str, 16)) == FAIL
4567 || skip_past_comma (& str) == FAIL
4568 || (rm = reg_required_here (& str, 0)) == FAIL
4569 || skip_past_comma (& str) == FAIL
4570 || (rs = reg_required_here (& str, 8)) == FAIL)
4571 inst.error = BAD_ARGS;
4572
4573 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4574 inst.error = BAD_PC;
4575
b99bd4ef
NC
4576 else
4577 end_of_line (str);
4578}
4579
4580/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4581 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4582 Error if any register is R15. */
4583
4584static void
f2b7cb0a 4585do_qadd (str)
b99bd4ef 4586 char * str;
b99bd4ef
NC
4587{
4588 int rd, rm, rn;
4589
4590 skip_whitespace (str);
4591
4592 if ((rd = reg_required_here (& str, 12)) == FAIL
4593 || skip_past_comma (& str) == FAIL
4594 || (rm = reg_required_here (& str, 0)) == FAIL
4595 || skip_past_comma (& str) == FAIL
4596 || (rn = reg_required_here (& str, 16)) == FAIL)
4597 inst.error = BAD_ARGS;
4598
4599 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4600 inst.error = BAD_PC;
4601
b99bd4ef
NC
4602 else
4603 end_of_line (str);
4604}
4605
4606/* ARM V5E (el Segundo)
4607 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4608 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4609
4610 These are equivalent to the XScale instructions MAR and MRA,
4611 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4612
4613 Result unpredicatable if Rd or Rn is R15. */
4614
4615static void
f2b7cb0a 4616do_co_reg2c (str)
b99bd4ef 4617 char * str;
b99bd4ef
NC
4618{
4619 int rd, rn;
4620
4621 skip_whitespace (str);
4622
4623 if (co_proc_number (& str) == FAIL)
4624 {
4625 if (!inst.error)
4626 inst.error = BAD_ARGS;
4627 return;
4628 }
4629
4630 if (skip_past_comma (& str) == FAIL
4631 || cp_opc_expr (& str, 4, 4) == FAIL)
4632 {
4633 if (!inst.error)
4634 inst.error = BAD_ARGS;
4635 return;
4636 }
4637
4638 if (skip_past_comma (& str) == FAIL
4639 || (rd = reg_required_here (& str, 12)) == FAIL)
4640 {
4641 if (!inst.error)
4642 inst.error = BAD_ARGS;
4643 return;
4644 }
4645
4646 if (skip_past_comma (& str) == FAIL
4647 || (rn = reg_required_here (& str, 16)) == FAIL)
4648 {
4649 if (!inst.error)
4650 inst.error = BAD_ARGS;
4651 return;
4652 }
4653
09d92015
MM
4654 /* Unpredictable result if rd or rn is R15. */
4655 if (rd == REG_PC || rn == REG_PC)
4656 as_tsktsk
4657 (_("Warning: instruction unpredictable when using r15"));
4658
4659 if (skip_past_comma (& str) == FAIL
4660 || cp_reg_required_here (& str, 0) == FAIL)
4661 {
4662 if (!inst.error)
4663 inst.error = BAD_ARGS;
4664 return;
4665 }
4666
4667 end_of_line (str);
4668}
4669
4670/* ARM V5 count-leading-zeroes instruction (argument parse)
4671 CLZ{<cond>} <Rd>, <Rm>
4672 Condition defaults to COND_ALWAYS.
4673 Error if Rd or Rm are R15. */
4674
4675static void
4676do_clz (str)
4677 char * str;
4678{
4679 int rd, rm;
4680
4681 skip_whitespace (str);
4682
4683 if (((rd = reg_required_here (& str, 12)) == FAIL)
4684 || (skip_past_comma (& str) == FAIL)
4685 || ((rm = reg_required_here (& str, 0)) == FAIL))
4686 inst.error = BAD_ARGS;
4687
4688 else if (rd == REG_PC || rm == REG_PC )
4689 inst.error = BAD_PC;
4690
4691 else
4692 end_of_line (str);
4693}
4694
4695/* ARM V5 (argument parse)
4696 LDC2{L} <coproc>, <CRd>, <addressing mode>
4697 STC2{L} <coproc>, <CRd>, <addressing mode>
4698 Instruction is not conditional, and has 0xf in the condition field.
4699 Otherwise, it's the same as LDC/STC. */
4700
4701static void
4702do_lstc2 (str)
4703 char * str;
4704{
4705 skip_whitespace (str);
4706
4707 if (co_proc_number (& str) == FAIL)
4708 {
4709 if (!inst.error)
4710 inst.error = BAD_ARGS;
4711 }
4712 else if (skip_past_comma (& str) == FAIL
4713 || cp_reg_required_here (& str, 12) == FAIL)
4714 {
4715 if (!inst.error)
4716 inst.error = BAD_ARGS;
4717 }
4718 else if (skip_past_comma (& str) == FAIL
4719 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4720 {
4721 if (! inst.error)
4722 inst.error = BAD_ARGS;
4723 }
4724 else
4725 end_of_line (str);
4726}
4727
4728/* ARM V5 (argument parse)
4729 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4730 Instruction is not conditional, and has 0xf in the condition field.
4731 Otherwise, it's the same as CDP. */
4732
4733static void
4734do_cdp2 (str)
4735 char * str;
4736{
4737 skip_whitespace (str);
4738
4739 if (co_proc_number (& str) == FAIL)
4740 {
4741 if (!inst.error)
4742 inst.error = BAD_ARGS;
4743 return;
4744 }
4745
4746 if (skip_past_comma (& str) == FAIL
4747 || cp_opc_expr (& str, 20,4) == FAIL)
4748 {
4749 if (!inst.error)
4750 inst.error = BAD_ARGS;
4751 return;
4752 }
4753
4754 if (skip_past_comma (& str) == FAIL
4755 || cp_reg_required_here (& str, 12) == FAIL)
4756 {
4757 if (!inst.error)
4758 inst.error = BAD_ARGS;
4759 return;
4760 }
4761
4762 if (skip_past_comma (& str) == FAIL
4763 || cp_reg_required_here (& str, 16) == FAIL)
4764 {
4765 if (!inst.error)
4766 inst.error = BAD_ARGS;
4767 return;
4768 }
4769
4770 if (skip_past_comma (& str) == FAIL
4771 || cp_reg_required_here (& str, 0) == FAIL)
4772 {
4773 if (!inst.error)
4774 inst.error = BAD_ARGS;
4775 return;
4776 }
4777
4778 if (skip_past_comma (& str) == SUCCESS)
4779 {
4780 if (cp_opc_expr (& str, 5, 3) == FAIL)
4781 {
4782 if (!inst.error)
4783 inst.error = BAD_ARGS;
4784 return;
4785 }
4786 }
4787
4788 end_of_line (str);
4789}
4790
4791/* ARM V5 (argument parse)
4792 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4793 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4794 Instruction is not conditional, and has 0xf in the condition field.
4795 Otherwise, it's the same as MCR/MRC. */
4796
4797static void
4798do_co_reg2 (str)
4799 char * str;
4800{
4801 skip_whitespace (str);
4802
4803 if (co_proc_number (& str) == FAIL)
4804 {
4805 if (!inst.error)
4806 inst.error = BAD_ARGS;
4807 return;
4808 }
4809
4810 if (skip_past_comma (& str) == FAIL
4811 || cp_opc_expr (& str, 21, 3) == FAIL)
4812 {
4813 if (!inst.error)
4814 inst.error = BAD_ARGS;
4815 return;
4816 }
4817
4818 if (skip_past_comma (& str) == FAIL
4819 || reg_required_here (& str, 12) == FAIL)
4820 {
4821 if (!inst.error)
4822 inst.error = BAD_ARGS;
4823 return;
4824 }
4825
4826 if (skip_past_comma (& str) == FAIL
4827 || cp_reg_required_here (& str, 16) == FAIL)
4828 {
4829 if (!inst.error)
4830 inst.error = BAD_ARGS;
4831 return;
4832 }
4833
4834 if (skip_past_comma (& str) == FAIL
4835 || cp_reg_required_here (& str, 0) == FAIL)
4836 {
4837 if (!inst.error)
4838 inst.error = BAD_ARGS;
4839 return;
4840 }
4841
4842 if (skip_past_comma (& str) == SUCCESS)
4843 {
4844 if (cp_opc_expr (& str, 5, 3) == FAIL)
4845 {
4846 if (!inst.error)
4847 inst.error = BAD_ARGS;
4848 return;
4849 }
4850 }
4851
4852 end_of_line (str);
4853}
4854
4855/* ARM v5TEJ. Jump to Jazelle code. */
4856static void
4857do_bxj (str)
4858 char * str;
4859{
4860 int reg;
4861
4862 skip_whitespace (str);
4863
4864 if ((reg = reg_required_here (&str, 0)) == FAIL)
4865 {
4866 inst.error = BAD_ARGS;
4867 return;
4868 }
4869
4870 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4871 if (reg == REG_PC)
4872 as_tsktsk (_("use of r15 in bxj is not really useful"));
4873
4874 end_of_line (str);
4875}
4876
4877/* ARM V6 umaal (argument parse). */
4878
4879static void
4880do_umaal (str)
4881 char *str;
4882{
4883
4884 int rdlo, rdhi, rm, rs;
4885
4886 skip_whitespace (str);
4887 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4888 || skip_past_comma (& str) == FAIL
4889 || (rdhi = reg_required_here (& str, 16)) == FAIL
4890 || skip_past_comma (& str) == FAIL
4891 || (rm = reg_required_here (& str, 0)) == FAIL
4892 || skip_past_comma (& str) == FAIL
5533419b 4893 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4894 {
4895 inst.error = BAD_ARGS;
4896 return;
4897 }
4898
4899 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4900 {
4901 inst.error = BAD_PC;
4902 return;
4903 }
4904
4905 end_of_line (str);
4906}
4907
4908/* ARM V6 strex (argument parse). */
4909
4910static void
4911do_strex (str)
4912 char *str;
4913{
4914 int rd, rm, rn;
4915
4916 /* Parse Rd, Rm,. */
4917 skip_whitespace (str);
4918 if ((rd = reg_required_here (& str, 12)) == FAIL
4919 || skip_past_comma (& str) == FAIL
4920 || (rm = reg_required_here (& str, 0)) == FAIL
4921 || skip_past_comma (& str) == FAIL)
4922 {
4923 inst.error = BAD_ARGS;
4924 return;
4925 }
4926 if (rd == REG_PC || rm == REG_PC)
4927 {
4928 inst.error = BAD_PC;
4929 return;
4930 }
4931 if (rd == rm)
4932 {
4933 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4934 return;
4935 }
4936
4937 /* Skip past '['. */
4938 if ((strlen (str) >= 1)
4939 && strncmp (str, "[", 1) == 0)
4940 str+=1;
4941 skip_whitespace (str);
4942
4943 /* Parse Rn. */
4944 if ((rn = reg_required_here (& str, 16)) == FAIL)
4945 {
4946 inst.error = BAD_ARGS;
4947 return;
4948 }
4949 else if (rn == REG_PC)
4950 {
4951 inst.error = BAD_PC;
4952 return;
4953 }
4954 if (rd == rn)
4955 {
4956 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4957 return;
4958 }
4959 skip_whitespace (str);
4960
4961 /* Skip past ']'. */
4962 if ((strlen (str) >= 1)
4963 && strncmp (str, "]", 1) == 0)
4964 str+=1;
4965
4966 end_of_line (str);
4967}
4968
4969/* ARM V6 ssat (argument parse). */
4970
4971static void
4972do_ssat (str)
4973 char* str;
4974{
4975 do_sat (&str, /*bias=*/-1);
4976 end_of_line (str);
4977}
4978
4979/* ARM V6 usat (argument parse). */
4980
4981static void
4982do_usat (str)
4983 char* str;
4984{
4985 do_sat (&str, /*bias=*/0);
4986 end_of_line (str);
4987}
4988
4989static void
4990do_sat (str, bias)
4991 char **str;
4992 int bias;
4993{
4994 int rd, rm;
4995 expressionS expr;
4996
4997 skip_whitespace (*str);
4998
4999 /* Parse <Rd>, field. */
5000 if ((rd = reg_required_here (str, 12)) == FAIL
5001 || skip_past_comma (str) == FAIL)
5002 {
5003 inst.error = BAD_ARGS;
5004 return;
5005 }
5006 if (rd == REG_PC)
5007 {
5008 inst.error = BAD_PC;
5009 return;
5010 }
5011
5012 /* Parse #<immed>, field. */
5013 if (is_immediate_prefix (**str))
5014 (*str)++;
5015 else
5016 {
5017 inst.error = _("immediate expression expected");
5018 return;
5019 }
5020 if (my_get_expression (&expr, str))
5021 {
5022 inst.error = _("bad expression");
5023 return;
5024 }
5025 if (expr.X_op != O_constant)
5026 {
5027 inst.error = _("constant expression expected");
5028 return;
5029 }
5030 if (expr.X_add_number + bias < 0
5031 || expr.X_add_number + bias > 31)
5032 {
5033 inst.error = _("immediate value out of range");
5034 return;
5035 }
5036 inst.instruction |= (expr.X_add_number + bias) << 16;
5037 if (skip_past_comma (str) == FAIL)
5038 {
5039 inst.error = BAD_ARGS;
5040 return;
5041 }
5042
5043 /* Parse <Rm> field. */
5044 if ((rm = reg_required_here (str, 0)) == FAIL)
5045 {
5046 inst.error = BAD_ARGS;
5047 return;
5048 }
5049 if (rm == REG_PC)
5050 {
5051 inst.error = BAD_PC;
5052 return;
5053 }
5054
5055 if (skip_past_comma (str) == SUCCESS)
5056 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5057}
5058
5059/* ARM V6 ssat16 (argument parse). */
5060
5061static void
5062do_ssat16 (str)
5063 char *str;
5064{
5065 do_sat16 (&str, /*bias=*/-1);
5066 end_of_line (str);
5067}
5068
5069static void
5070do_usat16 (str)
5071 char *str;
5072{
5073 do_sat16 (&str, /*bias=*/0);
5074 end_of_line (str);
5075}
5076
5077static void
5078do_sat16 (str, bias)
5079 char **str;
5080 int bias;
5081{
5082 int rd, rm;
5083 expressionS expr;
5084
5085 skip_whitespace (*str);
5086
5087 /* Parse the <Rd> field. */
5088 if ((rd = reg_required_here (str, 12)) == FAIL
5089 || skip_past_comma (str) == FAIL)
5090 {
5091 inst.error = BAD_ARGS;
5092 return;
5093 }
5094 if (rd == REG_PC)
5095 {
5096 inst.error = BAD_PC;
5097 return;
5098 }
5099
5100 /* Parse #<immed>, field. */
5101 if (is_immediate_prefix (**str))
5102 (*str)++;
5103 else
5104 {
5105 inst.error = _("immediate expression expected");
5106 return;
5107 }
5108 if (my_get_expression (&expr, str))
5109 {
5110 inst.error = _("bad expression");
5111 return;
5112 }
5113 if (expr.X_op != O_constant)
5114 {
5115 inst.error = _("constant expression expected");
5116 return;
5117 }
5118 if (expr.X_add_number + bias < 0
5119 || expr.X_add_number + bias > 15)
5120 {
5121 inst.error = _("immediate value out of range");
5122 return;
5123 }
5124 inst.instruction |= (expr.X_add_number + bias) << 16;
5125 if (skip_past_comma (str) == FAIL)
5126 {
5127 inst.error = BAD_ARGS;
5128 return;
5129 }
5130
5131 /* Parse <Rm> field. */
5132 if ((rm = reg_required_here (str, 0)) == FAIL)
5133 {
5134 inst.error = BAD_ARGS;
5135 return;
5136 }
5137 if (rm == REG_PC)
5138 {
5139 inst.error = BAD_PC;
5140 return;
5141 }
5142}
5143
5144/* ARM V6 srs (argument parse). */
5145
5146static void
5147do_srs (str)
5148 char* str;
5149{
5150 char *exclam;
5151 skip_whitespace (str);
5152 exclam = strchr (str, '!');
5153 if (exclam)
5154 *exclam = '\0';
5155 do_cps_mode (&str);
5156 if (exclam)
5157 *exclam = '!';
5158 if (*str == '!')
5159 {
5160 inst.instruction |= WRITE_BACK;
5161 str++;
5162 }
5163 end_of_line (str);
5164}
5165
5166/* ARM V6 SMMUL (argument parse). */
5167
5168static void
5169do_smmul (str)
5170 char* str;
5171{
5172 int rd, rm, rs;
5173
5174 skip_whitespace (str);
5175 if ((rd = reg_required_here (&str, 16)) == FAIL
5176 || skip_past_comma (&str) == FAIL
5177 || (rm = reg_required_here (&str, 0)) == FAIL
5178 || skip_past_comma (&str) == FAIL
5179 || (rs = reg_required_here (&str, 8)) == FAIL)
5180 {
5181 inst.error = BAD_ARGS;
5182 return;
5183 }
5184
5185 if (rd == REG_PC
5186 || rm == REG_PC
5187 || rs == REG_PC)
5188 {
5189 inst.error = BAD_PC;
5190 return;
5191 }
5192
5193 end_of_line (str);
5194
5195}
5196
5197/* ARM V6 SMLALD (argument parse). */
5198
5199static void
5200do_smlald (str)
5201 char* str;
5202{
5203 int rdlo, rdhi, rm, rs;
5204 skip_whitespace (str);
5205 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5206 || skip_past_comma (&str) == FAIL
5207 || (rdhi = reg_required_here (&str, 16)) == FAIL
5208 || skip_past_comma (&str) == FAIL
5209 || (rm = reg_required_here (&str, 0)) == FAIL
5210 || skip_past_comma (&str) == FAIL
5211 || (rs = reg_required_here (&str, 8)) == FAIL)
5212 {
5213 inst.error = BAD_ARGS;
5214 return;
5215 }
5216
5217 if (rdlo == REG_PC
5218 || rdhi == REG_PC
5219 || rm == REG_PC
5220 || rs == REG_PC)
5221 {
5222 inst.error = BAD_PC;
5223 return;
5224 }
5225
5226 end_of_line (str);
5227}
5228
5229/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5230 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5231
5232static void
5233do_smlad (str)
5234 char *str;
5235{
5236 int rd, rm, rs, rn;
5237
5238 skip_whitespace (str);
5239 if ((rd = reg_required_here (&str, 16)) == FAIL
5240 || skip_past_comma (&str) == FAIL
5241 || (rm = reg_required_here (&str, 0)) == FAIL
5242 || skip_past_comma (&str) == FAIL
5243 || (rs = reg_required_here (&str, 8)) == FAIL
5244 || skip_past_comma (&str) == FAIL
5245 || (rn = reg_required_here (&str, 12)) == FAIL)
5246 {
5247 inst.error = BAD_ARGS;
5248 return;
5249 }
5250
5251 if (rd == REG_PC
5252 || rn == REG_PC
5253 || rs == REG_PC
5254 || rm == REG_PC)
5255 {
5256 inst.error = BAD_PC;
5257 return;
5258 }
5259
5260 end_of_line (str);
5261}
5262
5263/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5264 preserving the other bits.
5265
5266 setend <endian_specifier>, where <endian_specifier> is either
5267 BE or LE. */
5268
5269static void
5270do_setend (str)
5271 char *str;
5272{
5273 if (do_endian_specifier (str))
5274 inst.instruction |= 0x200;
5275}
5276
5277/* Returns true if the endian-specifier indicates big-endianness. */
5278
5279static int
5280do_endian_specifier (str)
5281 char *str;
5282{
5283 int big_endian = 0;
5284
5285 skip_whitespace (str);
5286 if (strlen (str) < 2)
5287 inst.error = _("missing endian specifier");
5288 else if (strncasecmp (str, "BE", 2) == 0)
5289 {
5290 str += 2;
5291 big_endian = 1;
5292 }
5293 else if (strncasecmp (str, "LE", 2) == 0)
5294 str += 2;
5295 else
5296 inst.error = _("valid endian specifiers are be or le");
5297
5298 end_of_line (str);
5299
5300 return big_endian;
5301}
5302
5303/* ARM V6 SXTH.
5304
5305 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5306 Condition defaults to COND_ALWAYS.
5307 Error if any register uses R15. */
5308
5309static void
5310do_sxth (str)
5311 char *str;
5312{
5313 int rd, rm;
5314 expressionS expr;
5315 int rotation_clear_mask = 0xfffff3ff;
5316 int rotation_eight_mask = 0x00000400;
5317 int rotation_sixteen_mask = 0x00000800;
5318 int rotation_twenty_four_mask = 0x00000c00;
5319
5320 skip_whitespace (str);
5321 if ((rd = reg_required_here (&str, 12)) == FAIL
5322 || skip_past_comma (&str) == FAIL
5323 || (rm = reg_required_here (&str, 0)) == FAIL)
5324 {
5325 inst.error = BAD_ARGS;
5326 return;
5327 }
5328
5329 else if (rd == REG_PC || rm == REG_PC)
5330 {
5331 inst.error = BAD_PC;
5332 return;
5333 }
5334
5335 /* Zero out the rotation field. */
5336 inst.instruction &= rotation_clear_mask;
5337
5338 /* Check for lack of optional rotation field. */
5339 if (skip_past_comma (&str) == FAIL)
5340 {
5341 end_of_line (str);
5342 return;
5343 }
5344
5345 /* Move past 'ROR'. */
5346 skip_whitespace (str);
5347 if (strncasecmp (str, "ROR", 3) == 0)
5348 str+=3;
5349 else
5350 {
5351 inst.error = _("missing rotation field after comma");
5352 return;
5353 }
5354
5355 /* Get the immediate constant. */
5356 skip_whitespace (str);
5357 if (is_immediate_prefix (* str))
5358 str++;
5359 else
5360 {
5361 inst.error = _("immediate expression expected");
5362 return;
5363 }
5364
5365 if (my_get_expression (&expr, &str))
5366 {
5367 inst.error = _("bad expression");
5368 return;
5369 }
5370
5371 if (expr.X_op != O_constant)
5372 {
5373 inst.error = _("constant expression expected");
5374 return;
5375 }
5376
5377 switch (expr.X_add_number)
5378 {
5379 case 0:
5380 /* Rotation field has already been zeroed. */
5381 break;
5382 case 8:
5383 inst.instruction |= rotation_eight_mask;
5384 break;
5385
5386 case 16:
5387 inst.instruction |= rotation_sixteen_mask;
5388 break;
5389
5390 case 24:
5391 inst.instruction |= rotation_twenty_four_mask;
5392 break;
5393
5394 default:
5395 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5396 break;
5397 }
5398
5399 end_of_line (str);
5400
5401}
5402
5403/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5404 extends it to 32-bits, and adds the result to a value in another
5405 register. You can specify a rotation by 0, 8, 16, or 24 bits
5406 before extracting the 16-bit value.
5407 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5408 Condition defaults to COND_ALWAYS.
5409 Error if any register uses R15. */
5410
5411static void
5412do_sxtah (str)
5413 char *str;
5414{
5415 int rd, rn, rm;
5416 expressionS expr;
5417 int rotation_clear_mask = 0xfffff3ff;
5418 int rotation_eight_mask = 0x00000400;
5419 int rotation_sixteen_mask = 0x00000800;
5420 int rotation_twenty_four_mask = 0x00000c00;
5421
5422 skip_whitespace (str);
5423 if ((rd = reg_required_here (&str, 12)) == FAIL
5424 || skip_past_comma (&str) == FAIL
5425 || (rn = reg_required_here (&str, 16)) == FAIL
5426 || skip_past_comma (&str) == FAIL
5427 || (rm = reg_required_here (&str, 0)) == FAIL)
5428 {
5429 inst.error = BAD_ARGS;
5430 return;
5431 }
5432
5433 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5434 {
5435 inst.error = BAD_PC;
5436 return;
5437 }
5438
5439 /* Zero out the rotation field. */
5440 inst.instruction &= rotation_clear_mask;
5441
5442 /* Check for lack of optional rotation field. */
5443 if (skip_past_comma (&str) == FAIL)
5444 {
5445 end_of_line (str);
5446 return;
5447 }
5448
5449 /* Move past 'ROR'. */
5450 skip_whitespace (str);
5451 if (strncasecmp (str, "ROR", 3) == 0)
5452 str+=3;
5453 else
5454 {
5455 inst.error = _("missing rotation field after comma");
5456 return;
5457 }
5458
5459 /* Get the immediate constant. */
5460 skip_whitespace (str);
5461 if (is_immediate_prefix (* str))
5462 str++;
5463 else
5464 {
5465 inst.error = _("immediate expression expected");
5466 return;
5467 }
5468
5469 if (my_get_expression (&expr, &str))
5470 {
5471 inst.error = _("bad expression");
5472 return;
5473 }
5474
5475 if (expr.X_op != O_constant)
5476 {
5477 inst.error = _("constant expression expected");
5478 return;
5479 }
5480
5481 switch (expr.X_add_number)
5482 {
5483 case 0:
5484 /* Rotation field has already been zeroed. */
5485 break;
5486
5487 case 8:
5488 inst.instruction |= rotation_eight_mask;
5489 break;
5490
5491 case 16:
5492 inst.instruction |= rotation_sixteen_mask;
5493 break;
5494
5495 case 24:
5496 inst.instruction |= rotation_twenty_four_mask;
5497 break;
5498
5499 default:
5500 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5501 break;
5502 }
5503
5504 end_of_line (str);
5505
5506}
5507
5508
5509/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5510 word at the specified address and the following word
5511 respectively.
5512 Unconditionally executed.
5513 Error if Rn is R15.
5514*/
5515
5516static void
5517do_rfe (str)
5518 char *str;
5519{
5520 int rn;
5521
5522 skip_whitespace (str);
5523
5524 if ((rn = reg_required_here (&str, 16)) == FAIL)
5525 return;
b99bd4ef 5526
09d92015 5527 if (rn == REG_PC)
b99bd4ef 5528 {
09d92015 5529 inst.error = BAD_PC;
b99bd4ef
NC
5530 return;
5531 }
5532
09d92015
MM
5533 skip_whitespace (str);
5534
5535 if (*str == '!')
5536 {
5537 inst.instruction |= WRITE_BACK;
5538 str++;
5539 }
b99bd4ef
NC
5540 end_of_line (str);
5541}
5542
09d92015
MM
5543/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5544 register (argument parse).
5545 REV{<cond>} Rd, Rm.
5546 Condition defaults to COND_ALWAYS.
5547 Error if Rd or Rm are R15. */
b99bd4ef
NC
5548
5549static void
09d92015
MM
5550do_rev (str)
5551 char* str;
b99bd4ef
NC
5552{
5553 int rd, rm;
5554
b99bd4ef
NC
5555 skip_whitespace (str);
5556
09d92015
MM
5557 if ((rd = reg_required_here (&str, 12)) == FAIL
5558 || skip_past_comma (&str) == FAIL
5559 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5560 inst.error = BAD_ARGS;
5561
09d92015 5562 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5563 inst.error = BAD_PC;
5564
5565 else
5566 end_of_line (str);
5567}
5568
09d92015
MM
5569/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5570 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5571 Condition defaults to COND_ALWAYS.
5572 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5573
5574static void
09d92015
MM
5575do_qadd16 (str)
5576 char* str;
b99bd4ef 5577{
09d92015
MM
5578 int rd, rm, rn;
5579
b99bd4ef
NC
5580 skip_whitespace (str);
5581
09d92015
MM
5582 if ((rd = reg_required_here (&str, 12)) == FAIL
5583 || skip_past_comma (&str) == FAIL
5584 || (rn = reg_required_here (&str, 16)) == FAIL
5585 || skip_past_comma (&str) == FAIL
5586 || (rm = reg_required_here (&str, 0)) == FAIL)
5587 inst.error = BAD_ARGS;
5588
5589 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5590 inst.error = BAD_PC;
5591
b99bd4ef
NC
5592 else
5593 end_of_line (str);
5594}
5595
09d92015
MM
5596/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5597 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5598 Condition defaults to COND_ALWAYS.
5599 Error if Rd, Rn or Rm are R15. */
5600
5601static void
5602do_pkhbt (str)
5603 char* str;
5604{
5605 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5606}
5607
5608/* ARM V6 PKHTB (Argument Parse). */
5609
5610static void
5611do_pkhtb (str)
5612 char* str;
5613{
5614 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5615}
b99bd4ef
NC
5616
5617static void
09d92015
MM
5618do_pkh_core (str, shift)
5619 char* str;
5620 int shift;
b99bd4ef 5621{
09d92015 5622 int rd, rn, rm;
b99bd4ef 5623
09d92015
MM
5624 skip_whitespace (str);
5625 if (((rd = reg_required_here (&str, 12)) == FAIL)
5626 || (skip_past_comma (&str) == FAIL)
5627 || ((rn = reg_required_here (&str, 16)) == FAIL)
5628 || (skip_past_comma (&str) == FAIL)
5629 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5630 {
09d92015 5631 inst.error = BAD_ARGS;
b99bd4ef
NC
5632 return;
5633 }
5634
09d92015 5635 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5636 {
09d92015 5637 inst.error = BAD_PC;
b99bd4ef
NC
5638 return;
5639 }
5640
09d92015
MM
5641 /* Check for optional shift immediate constant. */
5642 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5643 {
09d92015
MM
5644 if (shift == SHIFT_ASR_IMMEDIATE)
5645 {
5646 /* If the shift specifier is ommited, turn the instruction
5647 into pkhbt rd, rm, rn. First, switch the instruction
5648 code, and clear the rn and rm fields. */
5649 inst.instruction &= 0xfff0f010;
5650 /* Now, re-encode the registers. */
5651 inst.instruction |= (rm << 16) | rn;
5652 }
b99bd4ef
NC
5653 return;
5654 }
5655
09d92015
MM
5656 decode_shift (&str, shift);
5657}
5658
5659/* ARM V6 Load Register Exclusive instruction (argument parse).
5660 LDREX{<cond>} <Rd, [<Rn>]
5661 Condition defaults to COND_ALWAYS.
5662 Error if Rd or Rn are R15.
5663 See ARMARMv6 A4.1.27: LDREX. */
5664
5665
5666static void
5667do_ldrex (str)
5668 char * str;
5669{
5670 int rd, rn;
5671
5672 skip_whitespace (str);
5673
5674 /* Parse Rd. */
5675 if (((rd = reg_required_here (&str, 12)) == FAIL)
5676 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5677 {
09d92015 5678 inst.error = BAD_ARGS;
b99bd4ef
NC
5679 return;
5680 }
09d92015 5681 else if (rd == REG_PC)
b99bd4ef 5682 {
09d92015 5683 inst.error = BAD_PC;
b99bd4ef
NC
5684 return;
5685 }
09d92015 5686 skip_whitespace (str);
b99bd4ef 5687
09d92015
MM
5688 /* Skip past '['. */
5689 if ((strlen (str) >= 1)
5690 &&strncmp (str, "[", 1) == 0)
5691 str+=1;
5692 skip_whitespace (str);
5693
5694 /* Parse Rn. */
5695 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5696 {
09d92015
MM
5697 inst.error = BAD_ARGS;
5698 return;
b99bd4ef 5699 }
09d92015
MM
5700 else if (rn == REG_PC)
5701 {
5702 inst.error = BAD_PC;
5703 return;
5704 }
5705 skip_whitespace (str);
b99bd4ef 5706
09d92015
MM
5707 /* Skip past ']'. */
5708 if ((strlen (str) >= 1)
5709 && strncmp (str, "]", 1) == 0)
5710 str+=1;
5711
b99bd4ef
NC
5712 end_of_line (str);
5713}
5714
09d92015
MM
5715/* ARM V6 change processor state instruction (argument parse)
5716 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5717
5718static void
09d92015
MM
5719do_cps (str)
5720 char * str;
b99bd4ef 5721{
09d92015
MM
5722 do_cps_mode (&str);
5723 end_of_line (str);
5724}
b99bd4ef 5725
09d92015
MM
5726static void
5727do_cpsi (str)
5728 char * str;
5729{
5730 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5731
09d92015 5732 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5733 {
09d92015
MM
5734 skip_whitespace (str);
5735 do_cps_mode (&str);
b99bd4ef 5736 }
09d92015
MM
5737 end_of_line (str);
5738}
b99bd4ef 5739
09d92015
MM
5740static void
5741do_cps_mode (str)
5742 char **str;
5743{
5744 expressionS expr;
5745
5746 skip_whitespace (*str);
5747
5748 if (! is_immediate_prefix (**str))
b99bd4ef 5749 {
09d92015 5750 inst.error = _("immediate expression expected");
b99bd4ef
NC
5751 return;
5752 }
5753
09d92015
MM
5754 (*str)++; /* Strip off the immediate signifier. */
5755 if (my_get_expression (&expr, str))
b99bd4ef 5756 {
09d92015 5757 inst.error = _("bad expression");
b99bd4ef
NC
5758 return;
5759 }
5760
09d92015 5761 if (expr.X_op != O_constant)
b99bd4ef 5762 {
09d92015 5763 inst.error = _("constant expression expected");
b99bd4ef
NC
5764 return;
5765 }
09d92015
MM
5766
5767 /* The mode is a 5 bit field. Valid values are 0-31. */
5768 if (((unsigned) expr.X_add_number) > 31
5769 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5770 {
09d92015
MM
5771 inst.error = _("invalid constant");
5772 return;
b99bd4ef 5773 }
09d92015
MM
5774
5775 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5776}
5777
ea6ef066 5778static void
09d92015
MM
5779do_cps_flags (str, thumb_p)
5780 char **str;
5781 int thumb_p;
ea6ef066 5782{
09d92015
MM
5783 struct cps_flag {
5784 char character;
5785 unsigned long arm_value;
5786 unsigned long thumb_value;
5787 };
5788 static struct cps_flag flag_table[] = {
5789 {'a', 0x100, 0x4 },
5790 {'i', 0x080, 0x2 },
5791 {'f', 0x040, 0x1 }
5792 };
ea6ef066 5793
09d92015 5794 int saw_a_flag = 0;
ea6ef066 5795
09d92015
MM
5796 skip_whitespace (*str);
5797
5798 /* Get the a, f and i flags. */
5799 while (**str && **str != ',')
ea6ef066 5800 {
09d92015
MM
5801 struct cps_flag *p;
5802 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5803 for (p = flag_table; p < q; ++p)
5804 if (strncasecmp (*str, &p->character, 1) == 0)
5805 {
5806 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5807 saw_a_flag = 1;
5808 break;
5809 }
5810 if (p == q)
5811 {
5812 inst.error = _("unrecognized flag");
5813 return;
5814 }
5815 (*str)++;
ea6ef066 5816 }
09d92015
MM
5817 if (!saw_a_flag)
5818 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5819}
5820
b99bd4ef
NC
5821/* THUMB V5 breakpoint instruction (argument parse)
5822 BKPT <immed_8>. */
5823
5824static void
5825do_t_bkpt (str)
5826 char * str;
5827{
5828 expressionS expr;
5829 unsigned long number;
5830
5831 skip_whitespace (str);
5832
5833 /* Allow optional leading '#'. */
5834 if (is_immediate_prefix (*str))
5835 str ++;
5836
5837 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5838 if (my_get_expression (& expr, & str)
5839 || (expr.X_op != O_constant
5840 /* As a convenience we allow 'bkpt' without an operand. */
5841 && expr.X_op != O_absent))
b99bd4ef 5842 {
143c8e19 5843 inst.error = _("bad expression");
b99bd4ef
NC
5844 return;
5845 }
5846
5847 number = expr.X_add_number;
5848
5849 /* Check it fits an 8 bit unsigned. */
5850 if (number != (number & 0xff))
5851 {
5852 inst.error = _("immediate value out of range");
5853 return;
5854 }
5855
5856 inst.instruction |= number;
5857
5858 end_of_line (str);
5859}
5860
5861/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5862 Expects inst.instruction is set for BLX(1).
5863 Note: this is cloned from do_branch, and the reloc changed to be a
5864 new one that can cope with setting one extra bit (the H bit). */
5865
5866static void
f2b7cb0a 5867do_branch25 (str)
b99bd4ef 5868 char * str;
b99bd4ef
NC
5869{
5870 if (my_get_expression (& inst.reloc.exp, & str))
5871 return;
5872
5873#ifdef OBJ_ELF
5874 {
5875 char * save_in;
5876
5877 /* ScottB: February 5, 1998 */
5878 /* Check to see of PLT32 reloc required for the instruction. */
5879
5880 /* arm_parse_reloc() works on input_line_pointer.
5881 We actually want to parse the operands to the branch instruction
5882 passed in 'str'. Save the input pointer and restore it later. */
5883 save_in = input_line_pointer;
5884 input_line_pointer = str;
5885
5886 if (inst.reloc.exp.X_op == O_symbol
5887 && *str == '('
5888 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5889 {
5890 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5891 inst.reloc.pc_rel = 0;
5892 /* Modify str to point to after parsed operands, otherwise
5893 end_of_line() will complain about the (PLT) left in str. */
5894 str = input_line_pointer;
5895 }
5896 else
5897 {
5898 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5899 inst.reloc.pc_rel = 1;
5900 }
5901
5902 input_line_pointer = save_in;
5903 }
5904#else
5905 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5906 inst.reloc.pc_rel = 1;
5907#endif /* OBJ_ELF */
5908
5909 end_of_line (str);
5910}
5911
5912/* ARM V5 branch-link-exchange instruction (argument parse)
5913 BLX <target_addr> ie BLX(1)
5914 BLX{<condition>} <Rm> ie BLX(2)
5915 Unfortunately, there are two different opcodes for this mnemonic.
5916 So, the insns[].value is not used, and the code here zaps values
5917 into inst.instruction.
5918 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5919
5920static void
f2b7cb0a 5921do_blx (str)
b99bd4ef 5922 char * str;
b99bd4ef
NC
5923{
5924 char * mystr = str;
5925 int rm;
5926
b99bd4ef
NC
5927 skip_whitespace (mystr);
5928 rm = reg_required_here (& mystr, 0);
5929
5930 /* The above may set inst.error. Ignore his opinion. */
5931 inst.error = 0;
5932
5933 if (rm != FAIL)
5934 {
5935 /* Arg is a register.
5936 Use the condition code our caller put in inst.instruction.
5937 Pass ourselves off as a BX with a funny opcode. */
5938 inst.instruction |= 0x012fff30;
f2b7cb0a 5939 do_bx (str);
b99bd4ef
NC
5940 }
5941 else
5942 {
5943 /* This must be is BLX <target address>, no condition allowed. */
5944 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5945 {
5946 inst.error = BAD_COND;
b99bd4ef 5947 return;
cc8a6dd0 5948 }
b99bd4ef
NC
5949
5950 inst.instruction = 0xfafffffe;
5951
5952 /* Process like a B/BL, but with a different reloc.
5953 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5954 do_branch25 (str);
b99bd4ef
NC
5955 }
5956}
5957
5958/* ARM V5 Thumb BLX (argument parse)
5959 BLX <target_addr> which is BLX(1)
5960 BLX <Rm> which is BLX(2)
5961 Unfortunately, there are two different opcodes for this mnemonic.
5962 So, the tinsns[].value is not used, and the code here zaps values
5963 into inst.instruction. */
5964
5965static void
5966do_t_blx (str)
5967 char * str;
5968{
5969 char * mystr = str;
5970 int rm;
5971
5972 skip_whitespace (mystr);
5973 inst.instruction = 0x4780;
5974
5975 /* Note that this call is to the ARM register recognizer. BLX(2)
5976 uses the ARM register space, not the Thumb one, so a call to
5977 thumb_reg() would be wrong. */
5978 rm = reg_required_here (& mystr, 3);
5979 inst.error = 0;
5980
5981 if (rm != FAIL)
5982 {
5983 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5984 inst.size = 2;
5985 }
5986 else
5987 {
5988 /* No ARM register. This must be BLX(1). Change the .instruction. */
5989 inst.instruction = 0xf7ffeffe;
5990 inst.size = 4;
5991
5992 if (my_get_expression (& inst.reloc.exp, & mystr))
5993 return;
5994
5995 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5996 inst.reloc.pc_rel = 1;
5997 }
5998
5999 end_of_line (mystr);
6000}
6001
6002/* ARM V5 breakpoint instruction (argument parse)
6003 BKPT <16 bit unsigned immediate>
6004 Instruction is not conditional.
6005 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 6006 and it is an error if the caller tried to override that. */
b99bd4ef
NC
6007
6008static void
f2b7cb0a 6009do_bkpt (str)
b99bd4ef 6010 char * str;
b99bd4ef
NC
6011{
6012 expressionS expr;
6013 unsigned long number;
6014
6015 skip_whitespace (str);
6016
6017 /* Allow optional leading '#'. */
6018 if (is_immediate_prefix (* str))
6019 str++;
6020
6021 memset (& expr, '\0', sizeof (expr));
6022
143c8e19
NC
6023 if (my_get_expression (& expr, & str)
6024 || (expr.X_op != O_constant
6025 /* As a convenience we allow 'bkpt' without an operand. */
6026 && expr.X_op != O_absent))
b99bd4ef 6027 {
143c8e19 6028 inst.error = _("bad expression");
b99bd4ef
NC
6029 return;
6030 }
6031
6032 number = expr.X_add_number;
6033
6034 /* Check it fits a 16 bit unsigned. */
6035 if (number != (number & 0xffff))
6036 {
6037 inst.error = _("immediate value out of range");
6038 return;
6039 }
6040
6041 /* Top 12 of 16 bits to bits 19:8. */
6042 inst.instruction |= (number & 0xfff0) << 4;
6043
6044 /* Bottom 4 of 16 bits to bits 3:0. */
6045 inst.instruction |= number & 0xf;
6046
6047 end_of_line (str);
b99bd4ef
NC
6048}
6049
09d92015
MM
6050/* THUMB CPS instruction (argument parse). */
6051
6052static void
6053do_t_cps (str)
6054 char *str;
6055{
6056 do_cps_flags (&str, /*thumb_p=*/1);
6057 end_of_line (str);
6058}
6059
6060/* THUMB CPY instruction (argument parse). */
6061
6062static void
6063do_t_cpy (str)
6064 char *str;
6065{
6066 thumb_mov_compare (str, THUMB_CPY);
6067}
6068
6069/* THUMB SETEND instruction (argument parse). */
6070
6071static void
6072do_t_setend (str)
6073 char *str;
6074{
6075 if (do_endian_specifier (str))
6076 inst.instruction |= 0x8;
6077}
6078
e16bb312
NC
6079static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6080
6081/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6082
6083static unsigned long
6084check_iwmmxt_insn (str, insn_type, immediate_size)
6085 char * str;
6086 enum iwmmxt_insn_type insn_type;
6087 int immediate_size;
6088{
6089 int reg = 0;
6090 const char * inst_error;
6091 expressionS expr;
6092 unsigned long number;
6093
6094 inst_error = inst.error;
6095 if (!inst.error)
6096 inst.error = BAD_ARGS;
6097 skip_whitespace (str);
6098
6099 switch (insn_type)
6100 {
6101 case check_rd:
6102 if ((reg = reg_required_here (&str, 12)) == FAIL)
6103 return FAIL;
6104 break;
6105
6106 case check_wr:
6107 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6108 return FAIL;
6109 break;
6110
6111 case check_wrwr:
6112 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6113 || skip_past_comma (&str) == FAIL
6114 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6115 return FAIL;
6116 break;
6117
6118 case check_wrwrwr:
6119 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6120 || skip_past_comma (&str) == FAIL
6121 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6122 || skip_past_comma (&str) == FAIL
6123 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6124 return FAIL;
6125 break;
6126
6127 case check_wrwrwcg:
6128 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6129 || skip_past_comma (&str) == FAIL
6130 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6131 || skip_past_comma (&str) == FAIL
6132 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6133 return FAIL;
6134 break;
6135
6136 case check_tbcst:
6137 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6138 || skip_past_comma (&str) == FAIL
6139 || reg_required_here (&str, 12) == FAIL))
6140 return FAIL;
6141 break;
6142
6143 case check_tmovmsk:
6144 if ((reg_required_here (&str, 12) == FAIL
6145 || skip_past_comma (&str) == FAIL
6146 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6147 return FAIL;
6148 break;
6149
6150 case check_tmia:
6151 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6152 || skip_past_comma (&str) == FAIL
6153 || reg_required_here (&str, 0) == FAIL
6154 || skip_past_comma (&str) == FAIL
6155 || reg_required_here (&str, 12) == FAIL))
6156 return FAIL;
6157 break;
6158
6159 case check_tmcrr:
6160 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6161 || skip_past_comma (&str) == FAIL
6162 || reg_required_here (&str, 12) == FAIL
6163 || skip_past_comma (&str) == FAIL
6164 || reg_required_here (&str, 16) == FAIL))
6165 return FAIL;
6166 break;
6167
6168 case check_tmrrc:
6169 if ((reg_required_here (&str, 12) == FAIL
6170 || skip_past_comma (&str) == FAIL
6171 || reg_required_here (&str, 16) == FAIL
6172 || skip_past_comma (&str) == FAIL
6173 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6174 return FAIL;
6175 break;
6176
6177 case check_tmcr:
6178 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6179 || skip_past_comma (&str) == FAIL
6180 || reg_required_here (&str, 12) == FAIL))
6181 return FAIL;
6182 break;
6183
6184 case check_tmrc:
6185 if ((reg_required_here (&str, 12) == FAIL
6186 || skip_past_comma (&str) == FAIL
6187 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6188 return FAIL;
6189 break;
6190
6191 case check_tinsr:
6192 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6193 || skip_past_comma (&str) == FAIL
6194 || reg_required_here (&str, 12) == FAIL
6195 || skip_past_comma (&str) == FAIL))
6196 return FAIL;
6197 break;
6198
6199 case check_textrc:
6200 if ((reg_required_here (&str, 12) == FAIL
6201 || skip_past_comma (&str) == FAIL))
6202 return FAIL;
6203 break;
6204
6205 case check_waligni:
6206 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6207 || skip_past_comma (&str) == FAIL
6208 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6209 || skip_past_comma (&str) == FAIL
6210 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6211 || skip_past_comma (&str) == FAIL))
6212 return FAIL;
6213 break;
6214
6215 case check_textrm:
6216 if ((reg_required_here (&str, 12) == FAIL
6217 || skip_past_comma (&str) == FAIL
6218 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6219 || skip_past_comma (&str) == FAIL))
6220 return FAIL;
6221 break;
6222
6223 case check_wshufh:
6224 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6225 || skip_past_comma (&str) == FAIL
6226 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6227 || skip_past_comma (&str) == FAIL))
6228 return FAIL;
6229 break;
6230 }
6231
6232 if (immediate_size == 0)
6233 {
6234 end_of_line (str);
6235 inst.error = inst_error;
6236 return reg;
6237 }
6238 else
6239 {
6240 skip_whitespace (str);
6241
6242 /* Allow optional leading '#'. */
6243 if (is_immediate_prefix (* str))
6244 str++;
6245
6246 memset (& expr, '\0', sizeof (expr));
6247
6248 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6249 {
6250 inst.error = _("bad or missing expression");
6251 return FAIL;
6252 }
6253
6254 number = expr.X_add_number;
6255
6256 if (number != (number & immediate_size))
6257 {
6258 inst.error = _("immediate value out of range");
6259 return FAIL;
6260 }
6261 end_of_line (str);
6262 inst.error = inst_error;
6263 return number;
6264 }
6265}
6266
6267static void
6268do_iwmmxt_byte_addr (str)
6269 char * str;
6270{
6271 int op = (inst.instruction & 0x300) >> 8;
6272 int reg;
6273
6274 inst.instruction &= ~0x300;
6275 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6276
6277 skip_whitespace (str);
6278
6279 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6280 || skip_past_comma (& str) == FAIL
6281 || cp_byte_address_required_here (&str) == FAIL)
6282 {
6283 if (! inst.error)
6284 inst.error = BAD_ARGS;
6285 }
6286 else
6287 end_of_line (str);
6288
6289 if (wc_register (reg))
6290 {
ece01a63 6291 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6292 inst.instruction |= 0xf0000100;
6293 inst.instruction &= ~0x00400000;
6294 }
6295}
6296
6297static void
6298do_iwmmxt_tandc (str)
6299 char * str;
6300{
6301 int reg;
6302
6303 reg = check_iwmmxt_insn (str, check_rd, 0);
6304
6305 if (reg != REG_PC && !inst.error)
6306 inst.error = _("only r15 allowed here");
e16bb312
NC
6307}
6308
6309static void
6310do_iwmmxt_tbcst (str)
6311 char * str;
6312{
6313 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6314}
6315
6316static void
6317do_iwmmxt_textrc (str)
6318 char * str;
6319{
6320 unsigned long number;
6321
6322 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6323 return;
6324
6325 inst.instruction |= number & 0x7;
e16bb312
NC
6326}
6327
6328static void
6329do_iwmmxt_textrm (str)
6330 char * str;
6331{
6332 unsigned long number;
6333
6334 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6335 return;
6336
6337 inst.instruction |= number & 0x7;
6338}
6339
6340static void
6341do_iwmmxt_tinsr (str)
6342 char * str;
6343{
6344 unsigned long number;
6345
6346 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6347 return;
6348
6349 inst.instruction |= number & 0x7;
e16bb312
NC
6350}
6351
6352static void
6353do_iwmmxt_tmcr (str)
6354 char * str;
6355{
6356 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6357}
6358
6359static void
6360do_iwmmxt_tmcrr (str)
6361 char * str;
6362{
6363 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6364}
6365
6366static void
6367do_iwmmxt_tmia (str)
6368 char * str;
6369{
6370 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6371}
6372
6373static void
6374do_iwmmxt_tmovmsk (str)
6375 char * str;
6376{
6377 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6378}
6379
6380static void
6381do_iwmmxt_tmrc (str)
6382 char * str;
6383{
6384 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6385}
6386
6387static void
6388do_iwmmxt_tmrrc (str)
6389 char * str;
6390{
6391 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6392}
6393
6394static void
6395do_iwmmxt_torc (str)
6396 char * str;
6397{
6398 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6399}
6400
6401static void
6402do_iwmmxt_waligni (str)
6403 char * str;
6404{
6405 unsigned long number;
6406
6407 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6408 return;
6409
6410 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6411}
6412
6413static void
6414do_iwmmxt_wmov (str)
6415 char * str;
6416{
6417 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6418 return;
6419
6420 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6421}
6422
6423static void
6424do_iwmmxt_word_addr (str)
6425 char * str;
6426{
6427 int op = (inst.instruction & 0x300) >> 8;
6428 int reg;
6429
6430 inst.instruction &= ~0x300;
6431 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6432
6433 skip_whitespace (str);
6434
6435 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6436 || skip_past_comma (& str) == FAIL
6437 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6438 {
6439 if (! inst.error)
6440 inst.error = BAD_ARGS;
6441 }
6442 else
6443 end_of_line (str);
6444
6445 if (wc_register (reg))
6446 {
ece01a63
ILT
6447 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6448 as_bad (_("conditional execution not supported with control register"));
6449 if (op != 2)
6450 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6451 inst.instruction |= 0xf0000100;
6452 inst.instruction &= ~0x00400000;
6453 }
6454}
6455
6456static void
6457do_iwmmxt_wrwr (str)
6458 char * str;
6459{
6460 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6461}
6462
6463static void
6464do_iwmmxt_wrwrwcg (str)
6465 char * str;
6466{
6467 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6468}
6469
6470static void
6471do_iwmmxt_wrwrwr (str)
6472 char * str;
6473{
6474 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6475}
6476
6477static void
6478do_iwmmxt_wshufh (str)
6479 char * str;
6480{
6481 unsigned long number;
6482
6483 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6484 return;
6485
6486 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6487}
6488
6489static void
6490do_iwmmxt_wzero (str)
6491 char * str;
6492{
6493 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6494 return;
6495
6496 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6497}
6498
b99bd4ef
NC
6499/* Xscale multiply-accumulate (argument parse)
6500 MIAcc acc0,Rm,Rs
6501 MIAPHcc acc0,Rm,Rs
6502 MIAxycc acc0,Rm,Rs. */
6503
6504static void
63e63b07 6505do_xsc_mia (str)
b99bd4ef 6506 char * str;
b99bd4ef
NC
6507{
6508 int rs;
6509 int rm;
6510
f2b7cb0a 6511 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6512 inst.error = ERR_NO_ACCUM;
6513
6514 else if (skip_past_comma (& str) == FAIL
6515 || (rm = reg_required_here (& str, 0)) == FAIL)
6516 inst.error = BAD_ARGS;
6517
6518 else if (skip_past_comma (& str) == FAIL
6519 || (rs = reg_required_here (& str, 12)) == FAIL)
6520 inst.error = BAD_ARGS;
6521
6522 /* inst.instruction has now been zapped with both rm and rs. */
6523 else if (rm == REG_PC || rs == REG_PC)
6524 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6525
6526 else
6527 end_of_line (str);
6528}
6529
6530/* Xscale move-accumulator-register (argument parse)
6531
6532 MARcc acc0,RdLo,RdHi. */
6533
6534static void
63e63b07 6535do_xsc_mar (str)
b99bd4ef 6536 char * str;
b99bd4ef
NC
6537{
6538 int rdlo, rdhi;
6539
f2b7cb0a 6540 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6541 inst.error = ERR_NO_ACCUM;
6542
6543 else if (skip_past_comma (& str) == FAIL
6544 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6545 inst.error = BAD_ARGS;
6546
6547 else if (skip_past_comma (& str) == FAIL
6548 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6549 inst.error = BAD_ARGS;
6550
6551 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6552 else if (rdlo == REG_PC || rdhi == REG_PC)
6553 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6554
6555 else
6556 end_of_line (str);
6557}
6558
6559/* Xscale move-register-accumulator (argument parse)
6560
6561 MRAcc RdLo,RdHi,acc0. */
6562
6563static void
63e63b07 6564do_xsc_mra (str)
b99bd4ef 6565 char * str;
b99bd4ef
NC
6566{
6567 int rdlo;
6568 int rdhi;
6569
b99bd4ef
NC
6570 skip_whitespace (str);
6571
6572 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6573 inst.error = BAD_ARGS;
6574
6575 else if (skip_past_comma (& str) == FAIL
6576 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6577 inst.error = BAD_ARGS;
6578
6579 else if (skip_past_comma (& str) == FAIL
6580 || accum0_required_here (& str) == FAIL)
6581 inst.error = ERR_NO_ACCUM;
6582
6583 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6584 else if (rdlo == rdhi)
6585 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6586
6587 else if (rdlo == REG_PC || rdhi == REG_PC)
6588 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6589 else
6590 end_of_line (str);
6591}
6592
c9b604bd 6593/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6594
6595 PLD <addr_mode>
6596
6597 Syntactically, like LDR with B=1, W=0, L=1. */
6598
6599static void
f2b7cb0a 6600do_pld (str)
b99bd4ef 6601 char * str;
b99bd4ef
NC
6602{
6603 int rd;
6604
b99bd4ef
NC
6605 skip_whitespace (str);
6606
6607 if (* str != '[')
6608 {
6609 inst.error = _("'[' expected after PLD mnemonic");
6610 return;
6611 }
6612
90e4755a 6613 ++str;
b99bd4ef
NC
6614 skip_whitespace (str);
6615
6616 if ((rd = reg_required_here (& str, 16)) == FAIL)
6617 return;
6618
6619 skip_whitespace (str);
6620
90e4755a 6621 if (*str == ']')
b99bd4ef
NC
6622 {
6623 /* [Rn], ... ? */
90e4755a 6624 ++str;
b99bd4ef
NC
6625 skip_whitespace (str);
6626
90e4755a
RE
6627 /* Post-indexed addressing is not allowed with PLD. */
6628 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6629 {
90e4755a
RE
6630 inst.error
6631 = _("post-indexed expression used in preload instruction");
6632 return;
b99bd4ef 6633 }
90e4755a 6634 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6635 {
6636 inst.error = _("writeback used in preload instruction");
90e4755a 6637 ++str;
b99bd4ef
NC
6638 }
6639 else /* [Rn] */
6640 inst.instruction |= INDEX_UP | PRE_INDEX;
6641 }
6642 else /* [Rn, ...] */
6643 {
6644 if (skip_past_comma (& str) == FAIL)
6645 {
6646 inst.error = _("pre-indexed expression expected");
6647 return;
6648 }
6649
90e4755a 6650 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6651 return;
6652
6653 skip_whitespace (str);
6654
6655 if (* str != ']')
6656 {
6657 inst.error = _("missing ]");
6658 return;
6659 }
6660
6661 ++ str;
6662 skip_whitespace (str);
6663
6664 if (* str == '!') /* [Rn]! */
6665 {
6666 inst.error = _("writeback used in preload instruction");
6667 ++ str;
6668 }
6669
6670 inst.instruction |= PRE_INDEX;
6671 }
6672
6673 end_of_line (str);
6674}
6675
c9b604bd 6676/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6677 Mode is like LDRH.
6678
6679 LDRccD R, mode
6680 STRccD R, mode. */
6681
6682static void
f2b7cb0a 6683do_ldrd (str)
b99bd4ef 6684 char * str;
b99bd4ef
NC
6685{
6686 int rd;
6687 int rn;
6688
b99bd4ef
NC
6689 skip_whitespace (str);
6690
6691 if ((rd = reg_required_here (& str, 12)) == FAIL)
6692 {
6693 inst.error = BAD_ARGS;
6694 return;
6695 }
6696
6697 if (skip_past_comma (& str) == FAIL
6698 || (rn = ld_mode_required_here (& str)) == FAIL)
6699 {
6700 if (!inst.error)
cc8a6dd0 6701 inst.error = BAD_ARGS;
b99bd4ef
NC
6702 return;
6703 }
6704
6705 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6706 if (rd & 1) /* Unpredictable result if Rd is odd. */
6707 {
f03698e6 6708 inst.error = _("destination register must be even");
b99bd4ef
NC
6709 return;
6710 }
6711
90e4755a 6712 if (rd == REG_LR)
b99bd4ef 6713 {
f2b7cb0a 6714 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6715 return;
6716 }
6717
6718 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6719 && ((inst.instruction & WRITE_BACK)
6720 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6721 as_warn (_("pre/post-indexing used when modified address register is destination"));
6722
90e4755a
RE
6723 /* For an index-register load, the index register must not overlap the
6724 destination (even if not write-back). */
6725 if ((inst.instruction & V4_STR_BIT) == 0
6726 && (inst.instruction & HWOFFSET_IMM) == 0)
6727 {
6728 int rm = inst.instruction & 0x0000000f;
6729
6730 if (rm == rd || (rm == rd + 1))
6731 as_warn (_("ldrd destination registers must not overlap index register"));
6732 }
6733
b99bd4ef
NC
6734 end_of_line (str);
6735}
6736
6737/* Returns the index into fp_values of a floating point number,
6738 or -1 if not in the table. */
6739
6740static int
6741my_get_float_expression (str)
6742 char ** str;
6743{
6744 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6745 char * save_in;
6746 expressionS exp;
6747 int i;
6748 int j;
6749
6750 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6751
6752 /* Look for a raw floating point number. */
6753 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6754 && is_end_of_line[(unsigned char) *save_in])
6755 {
6756 for (i = 0; i < NUM_FLOAT_VALS; i++)
6757 {
6758 for (j = 0; j < MAX_LITTLENUMS; j++)
6759 {
6760 if (words[j] != fp_values[i][j])
6761 break;
6762 }
6763
6764 if (j == MAX_LITTLENUMS)
6765 {
6766 *str = save_in;
6767 return i;
6768 }
6769 }
6770 }
6771
6772 /* Try and parse a more complex expression, this will probably fail
6773 unless the code uses a floating point prefix (eg "0f"). */
6774 save_in = input_line_pointer;
6775 input_line_pointer = *str;
6776 if (expression (&exp) == absolute_section
6777 && exp.X_op == O_big
6778 && exp.X_add_number < 0)
6779 {
6780 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6781 Ditto for 15. */
6782 if (gen_to_words (words, 5, (long) 15) == 0)
6783 {
6784 for (i = 0; i < NUM_FLOAT_VALS; i++)
6785 {
6786 for (j = 0; j < MAX_LITTLENUMS; j++)
6787 {
6788 if (words[j] != fp_values[i][j])
6789 break;
6790 }
6791
6792 if (j == MAX_LITTLENUMS)
6793 {
6794 *str = input_line_pointer;
6795 input_line_pointer = save_in;
6796 return i;
6797 }
6798 }
6799 }
6800 }
6801
6802 *str = input_line_pointer;
6803 input_line_pointer = save_in;
6804 return -1;
6805}
6806
b34976b6 6807/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6808
6809static int
6810walk_no_bignums (sp)
6811 symbolS * sp;
6812{
6813 if (symbol_get_value_expression (sp)->X_op == O_big)
6814 return 1;
6815
6816 if (symbol_get_value_expression (sp)->X_add_symbol)
6817 {
6818 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6819 || (symbol_get_value_expression (sp)->X_op_symbol
6820 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6821 }
6822
6823 return 0;
6824}
6825
f03698e6
RE
6826static int in_my_get_expression = 0;
6827
b99bd4ef
NC
6828static int
6829my_get_expression (ep, str)
6830 expressionS * ep;
6831 char ** str;
6832{
6833 char * save_in;
6834 segT seg;
6835
6836 save_in = input_line_pointer;
6837 input_line_pointer = *str;
f03698e6 6838 in_my_get_expression = 1;
b99bd4ef 6839 seg = expression (ep);
f03698e6
RE
6840 in_my_get_expression = 0;
6841
6842 if (ep->X_op == O_illegal)
6843 {
6844 /* We found a bad expression in md_operand(). */
6845 *str = input_line_pointer;
6846 input_line_pointer = save_in;
6847 return 1;
6848 }
b99bd4ef
NC
6849
6850#ifdef OBJ_AOUT
6851 if (seg != absolute_section
6852 && seg != text_section
6853 && seg != data_section
6854 && seg != bss_section
6855 && seg != undefined_section)
6856 {
6857 inst.error = _("bad_segment");
6858 *str = input_line_pointer;
6859 input_line_pointer = save_in;
6860 return 1;
6861 }
6862#endif
6863
6864 /* Get rid of any bignums now, so that we don't generate an error for which
6865 we can't establish a line number later on. Big numbers are never valid
6866 in instructions, which is where this routine is always called. */
6867 if (ep->X_op == O_big
6868 || (ep->X_add_symbol
6869 && (walk_no_bignums (ep->X_add_symbol)
6870 || (ep->X_op_symbol
6871 && walk_no_bignums (ep->X_op_symbol)))))
6872 {
f03698e6 6873 inst.error = _("invalid constant");
b99bd4ef
NC
6874 *str = input_line_pointer;
6875 input_line_pointer = save_in;
6876 return 1;
6877 }
6878
6879 *str = input_line_pointer;
6880 input_line_pointer = save_in;
6881 return 0;
6882}
6883
cc8a6dd0 6884/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6885 instruction in the error message. */
6886void
ce058b6c 6887md_operand (expr)
f03698e6
RE
6888 expressionS *expr;
6889{
6890 if (in_my_get_expression)
6891 {
6892 expr->X_op = O_illegal;
6893 if (inst.error == NULL)
6894 inst.error = _("bad expression");
6895 }
6896}
6897
09d92015 6898/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6899
6900static int
09d92015 6901decode_shift (str, kind)
b99bd4ef 6902 char ** str;
09d92015 6903 int kind;
b99bd4ef
NC
6904{
6905 const struct asm_shift_name * shift;
6906 char * p;
6907 char c;
6908
6909 skip_whitespace (* str);
6910
3882b010 6911 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6912 ;
6913
6914 if (p == * str)
6915 {
f03698e6 6916 inst.error = _("shift expression expected");
b99bd4ef
NC
6917 return FAIL;
6918 }
6919
6920 c = * p;
6921 * p = '\0';
6922 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6923 * p = c;
6924
6925 if (shift == NULL)
6926 {
f03698e6 6927 inst.error = _("shift expression expected");
b99bd4ef
NC
6928 return FAIL;
6929 }
6930
6931 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6932
09d92015
MM
6933 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6934 && shift->properties->index != SHIFT_LSL
6935 && shift->properties->index != SHIFT_ASR)
6936 {
6937 inst.error = _("'LSL' or 'ASR' required");
6938 return FAIL;
6939 }
6940 else if (kind == SHIFT_LSL_IMMEDIATE
6941 && shift->properties->index != SHIFT_LSL)
6942 {
6943 inst.error = _("'LSL' required");
6944 return FAIL;
6945 }
6946 else if (kind == SHIFT_ASR_IMMEDIATE
6947 && shift->properties->index != SHIFT_ASR)
6948 {
6949 inst.error = _("'ASR' required");
6950 return FAIL;
6951 }
6952
b99bd4ef
NC
6953 if (shift->properties->index == SHIFT_RRX)
6954 {
6955 * str = p;
6956 inst.instruction |= shift->properties->bit_field;
6957 return SUCCESS;
6958 }
6959
6960 skip_whitespace (p);
6961
09d92015 6962 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6963 {
6964 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6965 * str = p;
6966 return SUCCESS;
6967 }
6968 else if (! is_immediate_prefix (* p))
6969 {
09d92015 6970 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6971 ? _("shift requires register or #expression")
6972 : _("shift requires #expression"));
6973 * str = p;
6974 return FAIL;
6975 }
6976
6977 inst.error = NULL;
6978 p ++;
6979
6980 if (my_get_expression (& inst.reloc.exp, & p))
6981 return FAIL;
6982
6983 /* Validate some simple #expressions. */
6984 if (inst.reloc.exp.X_op == O_constant)
6985 {
6986 unsigned num = inst.reloc.exp.X_add_number;
6987
6988 /* Reject operations greater than 32. */
6989 if (num > 32
6990 /* Reject a shift of 0 unless the mode allows it. */
6991 || (num == 0 && shift->properties->allows_0 == 0)
6992 /* Reject a shift of 32 unless the mode allows it. */
6993 || (num == 32 && shift->properties->allows_32 == 0)
6994 )
6995 {
6996 /* As a special case we allow a shift of zero for
6997 modes that do not support it to be recoded as an
6998 logical shift left of zero (ie nothing). We warn
6999 about this though. */
7000 if (num == 0)
7001 {
f03698e6 7002 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
7003 shift = & shift_names[0];
7004 assert (shift->properties->index == SHIFT_LSL);
7005 }
7006 else
7007 {
f03698e6 7008 inst.error = _("invalid immediate shift");
b99bd4ef
NC
7009 return FAIL;
7010 }
7011 }
7012
7013 /* Shifts of 32 are encoded as 0, for those shifts that
7014 support it. */
7015 if (num == 32)
7016 num = 0;
7017
7018 inst.instruction |= (num << 7) | shift->properties->bit_field;
7019 }
7020 else
7021 {
7022 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7023 inst.reloc.pc_rel = 0;
7024 inst.instruction |= shift->properties->bit_field;
7025 }
7026
7027 * str = p;
7028 return SUCCESS;
7029}
7030
7031/* Do those data_ops which can take a negative immediate constant
2d2255b5 7032 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
7033 MOV <-> MVN
7034 AND <-> BIC
7035 ADC <-> SBC
7036 by inverting the second operand, and
7037 ADD <-> SUB
7038 CMP <-> CMN
7039 by negating the second operand. */
7040
7041static int
7042negate_data_op (instruction, value)
7043 unsigned long * instruction;
7044 unsigned long value;
7045{
7046 int op, new_inst;
7047 unsigned long negated, inverted;
7048
7049 negated = validate_immediate (-value);
7050 inverted = validate_immediate (~value);
7051
7052 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7053 switch (op)
7054 {
7055 /* First negates. */
7056 case OPCODE_SUB: /* ADD <-> SUB */
7057 new_inst = OPCODE_ADD;
7058 value = negated;
7059 break;
7060
7061 case OPCODE_ADD:
7062 new_inst = OPCODE_SUB;
7063 value = negated;
7064 break;
7065
7066 case OPCODE_CMP: /* CMP <-> CMN */
7067 new_inst = OPCODE_CMN;
7068 value = negated;
7069 break;
7070
7071 case OPCODE_CMN:
7072 new_inst = OPCODE_CMP;
7073 value = negated;
7074 break;
7075
7076 /* Now Inverted ops. */
7077 case OPCODE_MOV: /* MOV <-> MVN */
7078 new_inst = OPCODE_MVN;
7079 value = inverted;
7080 break;
7081
7082 case OPCODE_MVN:
7083 new_inst = OPCODE_MOV;
7084 value = inverted;
7085 break;
7086
7087 case OPCODE_AND: /* AND <-> BIC */
7088 new_inst = OPCODE_BIC;
7089 value = inverted;
7090 break;
7091
7092 case OPCODE_BIC:
7093 new_inst = OPCODE_AND;
7094 value = inverted;
7095 break;
7096
7097 case OPCODE_ADC: /* ADC <-> SBC */
7098 new_inst = OPCODE_SBC;
7099 value = inverted;
7100 break;
7101
7102 case OPCODE_SBC:
7103 new_inst = OPCODE_ADC;
7104 value = inverted;
7105 break;
7106
7107 /* We cannot do anything. */
7108 default:
7109 return FAIL;
7110 }
7111
7112 if (value == (unsigned) FAIL)
7113 return FAIL;
7114
7115 *instruction &= OPCODE_MASK;
7116 *instruction |= new_inst << DATA_OP_SHIFT;
7117 return value;
7118}
7119
7120static int
7121data_op2 (str)
7122 char ** str;
7123{
7124 int value;
7125 expressionS expr;
7126
7127 skip_whitespace (* str);
7128
7129 if (reg_required_here (str, 0) != FAIL)
7130 {
7131 if (skip_past_comma (str) == SUCCESS)
7132 /* Shift operation on register. */
7133 return decode_shift (str, NO_SHIFT_RESTRICT);
7134
7135 return SUCCESS;
7136 }
7137 else
7138 {
7139 /* Immediate expression. */
7140 if (is_immediate_prefix (**str))
7141 {
7142 (*str)++;
7143 inst.error = NULL;
7144
7145 if (my_get_expression (&inst.reloc.exp, str))
7146 return FAIL;
7147
7148 if (inst.reloc.exp.X_add_symbol)
7149 {
7150 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7151 inst.reloc.pc_rel = 0;
7152 }
7153 else
7154 {
7155 if (skip_past_comma (str) == SUCCESS)
7156 {
7157 /* #x, y -- ie explicit rotation by Y. */
7158 if (my_get_expression (&expr, str))
7159 return FAIL;
7160
7161 if (expr.X_op != O_constant)
7162 {
f03698e6 7163 inst.error = _("constant expression expected");
b99bd4ef
NC
7164 return FAIL;
7165 }
7166
7167 /* Rotate must be a multiple of 2. */
7168 if (((unsigned) expr.X_add_number) > 30
7169 || (expr.X_add_number & 1) != 0
7170 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7171 {
f03698e6 7172 inst.error = _("invalid constant");
b99bd4ef
NC
7173 return FAIL;
7174 }
7175 inst.instruction |= INST_IMMEDIATE;
7176 inst.instruction |= inst.reloc.exp.X_add_number;
7177 inst.instruction |= expr.X_add_number << 7;
7178 return SUCCESS;
7179 }
7180
7181 /* Implicit rotation, select a suitable one. */
7182 value = validate_immediate (inst.reloc.exp.X_add_number);
7183
7184 if (value == FAIL)
7185 {
7186 /* Can't be done. Perhaps the code reads something like
7187 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7188 if ((value = negate_data_op (&inst.instruction,
7189 inst.reloc.exp.X_add_number))
7190 == FAIL)
7191 {
f03698e6 7192 inst.error = _("invalid constant");
b99bd4ef
NC
7193 return FAIL;
7194 }
7195 }
7196
7197 inst.instruction |= value;
7198 }
7199
7200 inst.instruction |= INST_IMMEDIATE;
7201 return SUCCESS;
7202 }
7203
7204 (*str)++;
f03698e6 7205 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7206 return FAIL;
7207 }
7208}
7209
7210static int
7211fp_op2 (str)
7212 char ** str;
7213{
7214 skip_whitespace (* str);
7215
7216 if (fp_reg_required_here (str, 0) != FAIL)
7217 return SUCCESS;
7218 else
7219 {
7220 /* Immediate expression. */
7221 if (*((*str)++) == '#')
7222 {
7223 int i;
7224
7225 inst.error = NULL;
7226
7227 skip_whitespace (* str);
7228
7229 /* First try and match exact strings, this is to guarantee
7230 that some formats will work even for cross assembly. */
7231
7232 for (i = 0; fp_const[i]; i++)
7233 {
7234 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7235 {
7236 char *start = *str;
7237
7238 *str += strlen (fp_const[i]);
7239 if (is_end_of_line[(unsigned char) **str])
7240 {
7241 inst.instruction |= i + 8;
7242 return SUCCESS;
7243 }
7244 *str = start;
7245 }
7246 }
7247
7248 /* Just because we didn't get a match doesn't mean that the
7249 constant isn't valid, just that it is in a format that we
7250 don't automatically recognize. Try parsing it with
7251 the standard expression routines. */
7252 if ((i = my_get_float_expression (str)) >= 0)
7253 {
7254 inst.instruction |= i + 8;
7255 return SUCCESS;
7256 }
7257
f03698e6 7258 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7259 return FAIL;
7260 }
7261 inst.error =
f03698e6 7262 _("floating point register or immediate expression expected");
b99bd4ef
NC
7263 return FAIL;
7264 }
7265}
7266
7267static void
f2b7cb0a 7268do_arit (str)
b99bd4ef 7269 char * str;
b99bd4ef
NC
7270{
7271 skip_whitespace (str);
7272
7273 if (reg_required_here (&str, 12) == FAIL
7274 || skip_past_comma (&str) == FAIL
7275 || reg_required_here (&str, 16) == FAIL
7276 || skip_past_comma (&str) == FAIL
7277 || data_op2 (&str) == FAIL)
7278 {
7279 if (!inst.error)
7280 inst.error = BAD_ARGS;
7281 return;
7282 }
7283
b99bd4ef 7284 end_of_line (str);
b99bd4ef
NC
7285}
7286
7287static void
f2b7cb0a 7288do_adr (str)
b99bd4ef 7289 char * str;
b99bd4ef 7290{
90e4755a
RE
7291 /* This is a pseudo-op of the form "adr rd, label" to be converted
7292 into a relative address of the form "add rd, pc, #label-.-8". */
7293 skip_whitespace (str);
7294
7295 if (reg_required_here (&str, 12) == FAIL
7296 || skip_past_comma (&str) == FAIL
7297 || my_get_expression (&inst.reloc.exp, &str))
7298 {
7299 if (!inst.error)
7300 inst.error = BAD_ARGS;
7301 return;
7302 }
7303
7304 /* Frag hacking will turn this into a sub instruction if the offset turns
7305 out to be negative. */
7306 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 7307#ifndef TE_WINCE
90e4755a 7308 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 7309#endif
90e4755a
RE
7310 inst.reloc.pc_rel = 1;
7311
7312 end_of_line (str);
7313}
7314
7315static void
f2b7cb0a 7316do_adrl (str)
90e4755a 7317 char * str;
90e4755a
RE
7318{
7319 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7320 into a relative address of the form:
7321 add rd, pc, #low(label-.-8)"
7322 add rd, rd, #high(label-.-8)" */
7323
7324 skip_whitespace (str);
7325
7326 if (reg_required_here (&str, 12) == FAIL
7327 || skip_past_comma (&str) == FAIL
7328 || my_get_expression (&inst.reloc.exp, &str))
7329 {
7330 if (!inst.error)
7331 inst.error = BAD_ARGS;
7332
7333 return;
7334 }
7335
7336 end_of_line (str);
7337 /* Frag hacking will turn this into a sub instruction if the offset turns
7338 out to be negative. */
7339 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
250355db 7340#ifndef TE_WINCE
90e4755a 7341 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 7342#endif
90e4755a
RE
7343 inst.reloc.pc_rel = 1;
7344 inst.size = INSN_SIZE * 2;
90e4755a
RE
7345}
7346
7347static void
f2b7cb0a 7348do_cmp (str)
90e4755a 7349 char * str;
90e4755a
RE
7350{
7351 skip_whitespace (str);
7352
7353 if (reg_required_here (&str, 16) == FAIL)
7354 {
7355 if (!inst.error)
7356 inst.error = BAD_ARGS;
7357 return;
7358 }
7359
7360 if (skip_past_comma (&str) == FAIL
7361 || data_op2 (&str) == FAIL)
7362 {
7363 if (!inst.error)
7364 inst.error = BAD_ARGS;
7365 return;
7366 }
7367
90e4755a 7368 end_of_line (str);
90e4755a
RE
7369}
7370
7371static void
f2b7cb0a 7372do_mov (str)
90e4755a 7373 char * str;
90e4755a
RE
7374{
7375 skip_whitespace (str);
7376
7377 if (reg_required_here (&str, 12) == FAIL)
7378 {
7379 if (!inst.error)
7380 inst.error = BAD_ARGS;
7381 return;
7382 }
7383
7384 if (skip_past_comma (&str) == FAIL
7385 || data_op2 (&str) == FAIL)
7386 {
7387 if (!inst.error)
7388 inst.error = BAD_ARGS;
7389 return;
7390 }
7391
90e4755a 7392 end_of_line (str);
90e4755a
RE
7393}
7394
7395static int
7396ldst_extend (str)
7397 char ** str;
7398{
7399 int add = INDEX_UP;
7400
7401 switch (**str)
7402 {
7403 case '#':
7404 case '$':
7405 (*str)++;
7406 if (my_get_expression (& inst.reloc.exp, str))
7407 return FAIL;
7408
7409 if (inst.reloc.exp.X_op == O_constant)
7410 {
7411 int value = inst.reloc.exp.X_add_number;
7412
7413 if (value < -4095 || value > 4095)
7414 {
7415 inst.error = _("address offset too large");
7416 return FAIL;
7417 }
7418
7419 if (value < 0)
7420 {
7421 value = -value;
7422 add = 0;
7423 }
7424
7425 inst.instruction |= add | value;
7426 }
7427 else
7428 {
7429 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7430 inst.reloc.pc_rel = 0;
7431 }
7432 return SUCCESS;
7433
7434 case '-':
7435 add = 0;
7436 /* Fall through. */
7437
7438 case '+':
7439 (*str)++;
7440 /* Fall through. */
7441
7442 default:
7443 if (reg_required_here (str, 0) == FAIL)
7444 return FAIL;
7445
7446 inst.instruction |= add | OFFSET_REG;
7447 if (skip_past_comma (str) == SUCCESS)
09d92015 7448 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7449
7450 return SUCCESS;
7451 }
7452}
7453
7454static void
f2b7cb0a 7455do_ldst (str)
90e4755a 7456 char * str;
90e4755a
RE
7457{
7458 int pre_inc = 0;
7459 int conflict_reg;
7460 int value;
7461
b99bd4ef
NC
7462 skip_whitespace (str);
7463
90e4755a
RE
7464 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7465 {
7466 if (!inst.error)
7467 inst.error = BAD_ARGS;
7468 return;
7469 }
7470
7471 if (skip_past_comma (&str) == FAIL)
7472 {
f03698e6 7473 inst.error = _("address expected");
90e4755a
RE
7474 return;
7475 }
7476
90e4755a
RE
7477 if (*str == '[')
7478 {
7479 int reg;
7480
7481 str++;
7482
7483 skip_whitespace (str);
7484
7485 if ((reg = reg_required_here (&str, 16)) == FAIL)
7486 return;
7487
7488 /* Conflicts can occur on stores as well as loads. */
7489 conflict_reg = (conflict_reg == reg);
7490
7491 skip_whitespace (str);
7492
7493 if (*str == ']')
7494 {
7495 str ++;
7496
7497 if (skip_past_comma (&str) == SUCCESS)
7498 {
7499 /* [Rn],... (post inc) */
7500 if (ldst_extend (&str) == FAIL)
7501 return;
7502 if (conflict_reg)
7503 as_warn (_("%s register same as write-back base"),
7504 ((inst.instruction & LOAD_BIT)
7505 ? _("destination") : _("source")));
7506 }
7507 else
7508 {
7509 /* [Rn] */
7510 skip_whitespace (str);
7511
7512 if (*str == '!')
7513 {
7514 if (conflict_reg)
7515 as_warn (_("%s register same as write-back base"),
7516 ((inst.instruction & LOAD_BIT)
7517 ? _("destination") : _("source")));
7518 str++;
7519 inst.instruction |= WRITE_BACK;
7520 }
7521
7522 inst.instruction |= INDEX_UP;
7523 pre_inc = 1;
7524 }
7525 }
7526 else
7527 {
7528 /* [Rn,...] */
7529 if (skip_past_comma (&str) == FAIL)
7530 {
7531 inst.error = _("pre-indexed expression expected");
7532 return;
7533 }
7534
7535 pre_inc = 1;
7536 if (ldst_extend (&str) == FAIL)
7537 return;
7538
7539 skip_whitespace (str);
7540
7541 if (*str++ != ']')
7542 {
7543 inst.error = _("missing ]");
7544 return;
7545 }
7546
7547 skip_whitespace (str);
7548
7549 if (*str == '!')
7550 {
7551 if (conflict_reg)
7552 as_warn (_("%s register same as write-back base"),
7553 ((inst.instruction & LOAD_BIT)
7554 ? _("destination") : _("source")));
7555 str++;
7556 inst.instruction |= WRITE_BACK;
7557 }
7558 }
7559 }
7560 else if (*str == '=')
7561 {
f03698e6
RE
7562 if ((inst.instruction & LOAD_BIT) == 0)
7563 {
7564 inst.error = _("invalid pseudo operation");
7565 return;
7566 }
7567
90e4755a
RE
7568 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7569 str++;
7570
7571 skip_whitespace (str);
7572
7573 if (my_get_expression (&inst.reloc.exp, &str))
7574 return;
7575
7576 if (inst.reloc.exp.X_op != O_constant
7577 && inst.reloc.exp.X_op != O_symbol)
7578 {
f03698e6 7579 inst.error = _("constant expression expected");
90e4755a
RE
7580 return;
7581 }
7582
e28cd48c 7583 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7584 {
e28cd48c
RE
7585 value = validate_immediate (inst.reloc.exp.X_add_number);
7586
7587 if (value != FAIL)
90e4755a 7588 {
e28cd48c
RE
7589 /* This can be done with a mov instruction. */
7590 inst.instruction &= LITERAL_MASK;
7591 inst.instruction |= (INST_IMMEDIATE
7592 | (OPCODE_MOV << DATA_OP_SHIFT));
7593 inst.instruction |= value & 0xfff;
7594 end_of_line (str);
90e4755a
RE
7595 return;
7596 }
b99bd4ef 7597
e28cd48c
RE
7598 value = validate_immediate (~inst.reloc.exp.X_add_number);
7599
7600 if (value != FAIL)
7601 {
7602 /* This can be done with a mvn instruction. */
7603 inst.instruction &= LITERAL_MASK;
7604 inst.instruction |= (INST_IMMEDIATE
7605 | (OPCODE_MVN << DATA_OP_SHIFT));
7606 inst.instruction |= value & 0xfff;
7607 end_of_line (str);
7608 return;
7609 }
90e4755a 7610 }
e28cd48c
RE
7611
7612 /* Insert into literal pool. */
7613 if (add_to_lit_pool () == FAIL)
7614 {
7615 if (!inst.error)
7616 inst.error = _("literal pool insertion failed");
7617 return;
7618 }
7619
7620 /* Change the instruction exp to point to the pool. */
7621 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7622 inst.reloc.pc_rel = 1;
7623 inst.instruction |= (REG_PC << 16);
7624 pre_inc = 1;
1cac9012
NC
7625 }
7626 else
7627 {
90e4755a
RE
7628 if (my_get_expression (&inst.reloc.exp, &str))
7629 return;
7630
7631 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7632#ifndef TE_WINCE
7633 /* PC rel adjust. */
7634 inst.reloc.exp.X_add_number -= 8;
7635#endif
1cac9012 7636 inst.reloc.pc_rel = 1;
90e4755a
RE
7637 inst.instruction |= (REG_PC << 16);
7638 pre_inc = 1;
b99bd4ef
NC
7639 }
7640
90e4755a 7641 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7642 end_of_line (str);
b99bd4ef
NC
7643}
7644
7645static void
f2b7cb0a 7646do_ldstt (str)
90e4755a 7647 char * str;
b99bd4ef 7648{
90e4755a
RE
7649 int conflict_reg;
7650
b99bd4ef
NC
7651 skip_whitespace (str);
7652
90e4755a 7653 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7654 {
7655 if (!inst.error)
7656 inst.error = BAD_ARGS;
7657 return;
7658 }
7659
90e4755a 7660 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7661 {
f03698e6 7662 inst.error = _("address expected");
b99bd4ef
NC
7663 return;
7664 }
7665
90e4755a
RE
7666 if (*str == '[')
7667 {
7668 int reg;
b99bd4ef 7669
90e4755a 7670 str++;
b99bd4ef 7671
90e4755a 7672 skip_whitespace (str);
b99bd4ef 7673
90e4755a
RE
7674 if ((reg = reg_required_here (&str, 16)) == FAIL)
7675 return;
b99bd4ef 7676
90e4755a
RE
7677 /* ldrt/strt always use post-indexed addressing, so if the base is
7678 the same as Rd, we warn. */
7679 if (conflict_reg == reg)
7680 as_warn (_("%s register same as write-back base"),
7681 ((inst.instruction & LOAD_BIT)
7682 ? _("destination") : _("source")));
7683
7684 skip_whitespace (str);
7685
7686 if (*str == ']')
7687 {
7688 str ++;
7689
7690 if (skip_past_comma (&str) == SUCCESS)
7691 {
7692 /* [Rn],... (post inc) */
7693 if (ldst_extend (&str) == FAIL)
7694 return;
7695 }
7696 else
7697 {
7698 /* [Rn] */
7699 skip_whitespace (str);
7700
7701 /* Skip a write-back '!'. */
7702 if (*str == '!')
7703 str++;
7704
7705 inst.instruction |= INDEX_UP;
7706 }
7707 }
7708 else
7709 {
7710 inst.error = _("post-indexed expression expected");
7711 return;
7712 }
7713 }
7714 else
b99bd4ef 7715 {
90e4755a 7716 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7717 return;
7718 }
7719
b99bd4ef 7720 end_of_line (str);
b99bd4ef
NC
7721}
7722
7723static int
90e4755a 7724ldst_extend_v4 (str)
b99bd4ef 7725 char ** str;
b99bd4ef
NC
7726{
7727 int add = INDEX_UP;
7728
7729 switch (**str)
7730 {
7731 case '#':
7732 case '$':
7733 (*str)++;
7734 if (my_get_expression (& inst.reloc.exp, str))
7735 return FAIL;
7736
7737 if (inst.reloc.exp.X_op == O_constant)
7738 {
7739 int value = inst.reloc.exp.X_add_number;
7740
90e4755a 7741 if (value < -255 || value > 255)
b99bd4ef
NC
7742 {
7743 inst.error = _("address offset too large");
7744 return FAIL;
7745 }
7746
7747 if (value < 0)
7748 {
7749 value = -value;
7750 add = 0;
7751 }
7752
7753 /* Halfword and signextension instructions have the
7754 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7755 inst.instruction |= (add | HWOFFSET_IMM
7756 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7757 }
7758 else
7759 {
90e4755a
RE
7760 inst.instruction |= HWOFFSET_IMM;
7761 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7762 inst.reloc.pc_rel = 0;
7763 }
7764 return SUCCESS;
7765
7766 case '-':
7767 add = 0;
7768 /* Fall through. */
7769
7770 case '+':
7771 (*str)++;
7772 /* Fall through. */
7773
7774 default:
7775 if (reg_required_here (str, 0) == FAIL)
7776 return FAIL;
7777
90e4755a 7778 inst.instruction |= add;
b99bd4ef
NC
7779 return SUCCESS;
7780 }
7781}
7782
90e4755a 7783/* Halfword and signed-byte load/store operations. */
b99bd4ef 7784static void
f2b7cb0a 7785do_ldstv4 (str)
b99bd4ef 7786 char * str;
b99bd4ef 7787{
b99bd4ef
NC
7788 int pre_inc = 0;
7789 int conflict_reg;
7790 int value;
7791
b99bd4ef
NC
7792 skip_whitespace (str);
7793
7794 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7795 {
7796 if (!inst.error)
7797 inst.error = BAD_ARGS;
7798 return;
7799 }
7800
7801 if (skip_past_comma (& str) == FAIL)
7802 {
f03698e6 7803 inst.error = _("address expected");
b99bd4ef
NC
7804 return;
7805 }
7806
7807 if (*str == '[')
7808 {
7809 int reg;
7810
7811 str++;
7812
7813 skip_whitespace (str);
7814
7815 if ((reg = reg_required_here (&str, 16)) == FAIL)
7816 return;
7817
7818 /* Conflicts can occur on stores as well as loads. */
7819 conflict_reg = (conflict_reg == reg);
7820
7821 skip_whitespace (str);
7822
7823 if (*str == ']')
7824 {
7825 str ++;
7826
7827 if (skip_past_comma (&str) == SUCCESS)
7828 {
7829 /* [Rn],... (post inc) */
90e4755a 7830 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7831 return;
7832 if (conflict_reg)
90e4755a
RE
7833 as_warn (_("%s register same as write-back base"),
7834 ((inst.instruction & LOAD_BIT)
7835 ? _("destination") : _("source")));
b99bd4ef
NC
7836 }
7837 else
7838 {
7839 /* [Rn] */
90e4755a 7840 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7841
7842 skip_whitespace (str);
7843
7844 if (*str == '!')
7845 {
7846 if (conflict_reg)
7847 as_warn (_("%s register same as write-back base"),
7848 ((inst.instruction & LOAD_BIT)
7849 ? _("destination") : _("source")));
7850 str++;
7851 inst.instruction |= WRITE_BACK;
7852 }
7853
90e4755a
RE
7854 inst.instruction |= INDEX_UP;
7855 pre_inc = 1;
b99bd4ef
NC
7856 }
7857 }
7858 else
7859 {
7860 /* [Rn,...] */
7861 if (skip_past_comma (&str) == FAIL)
7862 {
7863 inst.error = _("pre-indexed expression expected");
7864 return;
7865 }
7866
7867 pre_inc = 1;
90e4755a 7868 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7869 return;
7870
7871 skip_whitespace (str);
7872
7873 if (*str++ != ']')
7874 {
7875 inst.error = _("missing ]");
7876 return;
7877 }
7878
7879 skip_whitespace (str);
7880
7881 if (*str == '!')
7882 {
7883 if (conflict_reg)
7884 as_warn (_("%s register same as write-back base"),
7885 ((inst.instruction & LOAD_BIT)
7886 ? _("destination") : _("source")));
7887 str++;
7888 inst.instruction |= WRITE_BACK;
7889 }
7890 }
7891 }
7892 else if (*str == '=')
7893 {
f03698e6
RE
7894 if ((inst.instruction & LOAD_BIT) == 0)
7895 {
7896 inst.error = _("invalid pseudo operation");
7897 return;
7898 }
7899
90e4755a 7900 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7901 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7902 str++;
7903
7904 skip_whitespace (str);
7905
7906 if (my_get_expression (&inst.reloc.exp, &str))
7907 return;
7908
7909 if (inst.reloc.exp.X_op != O_constant
7910 && inst.reloc.exp.X_op != O_symbol)
7911 {
f03698e6 7912 inst.error = _("constant expression expected");
b99bd4ef
NC
7913 return;
7914 }
7915
d8273442 7916 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7917 {
d8273442
NC
7918 value = validate_immediate (inst.reloc.exp.X_add_number);
7919
7920 if (value != FAIL)
b99bd4ef 7921 {
d8273442
NC
7922 /* This can be done with a mov instruction. */
7923 inst.instruction &= LITERAL_MASK;
7924 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7925 inst.instruction |= value & 0xfff;
d8273442 7926 end_of_line (str);
b99bd4ef
NC
7927 return;
7928 }
cc8a6dd0 7929
d8273442 7930 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7931
d8273442 7932 if (value != FAIL)
b99bd4ef 7933 {
d8273442
NC
7934 /* This can be done with a mvn instruction. */
7935 inst.instruction &= LITERAL_MASK;
7936 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7937 inst.instruction |= value & 0xfff;
d8273442
NC
7938 end_of_line (str);
7939 return;
b99bd4ef 7940 }
b99bd4ef 7941 }
d8273442
NC
7942
7943 /* Insert into literal pool. */
7944 if (add_to_lit_pool () == FAIL)
7945 {
7946 if (!inst.error)
7947 inst.error = _("literal pool insertion failed");
7948 return;
7949 }
7950
7951 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7952 inst.instruction |= HWOFFSET_IMM;
7953 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7954 inst.reloc.pc_rel = 1;
7955 inst.instruction |= (REG_PC << 16);
7956 pre_inc = 1;
b99bd4ef
NC
7957 }
7958 else
7959 {
7960 if (my_get_expression (&inst.reloc.exp, &str))
7961 return;
7962
90e4755a
RE
7963 inst.instruction |= HWOFFSET_IMM;
7964 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7965#ifndef TE_WINCE
7966 /* PC rel adjust. */
7967 inst.reloc.exp.X_add_number -= 8;
7968#endif
7969 inst.reloc.pc_rel = 1;
7970 inst.instruction |= (REG_PC << 16);
7971 pre_inc = 1;
7972 }
7973
90e4755a 7974 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7975 end_of_line (str);
b99bd4ef
NC
7976}
7977
7978static long
7979reg_list (strp)
7980 char ** strp;
7981{
7982 char * str = * strp;
7983 long range = 0;
7984 int another_range;
7985
7986 /* We come back here if we get ranges concatenated by '+' or '|'. */
7987 do
7988 {
7989 another_range = 0;
7990
7991 if (*str == '{')
7992 {
7993 int in_range = 0;
7994 int cur_reg = -1;
7995
7996 str++;
7997 do
7998 {
7999 int reg;
8000
8001 skip_whitespace (str);
8002
8003 if ((reg = reg_required_here (& str, -1)) == FAIL)
8004 return FAIL;
8005
8006 if (in_range)
8007 {
8008 int i;
8009
8010 if (reg <= cur_reg)
8011 {
f03698e6 8012 inst.error = _("bad range in register list");
b99bd4ef
NC
8013 return FAIL;
8014 }
8015
8016 for (i = cur_reg + 1; i < reg; i++)
8017 {
8018 if (range & (1 << i))
8019 as_tsktsk
f03698e6 8020 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8021 i);
8022 else
8023 range |= 1 << i;
8024 }
8025 in_range = 0;
8026 }
8027
8028 if (range & (1 << reg))
f03698e6 8029 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8030 reg);
8031 else if (reg <= cur_reg)
f03698e6 8032 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
8033
8034 range |= 1 << reg;
8035 cur_reg = reg;
8036 }
8037 while (skip_past_comma (&str) != FAIL
8038 || (in_range = 1, *str++ == '-'));
8039 str--;
8040 skip_whitespace (str);
8041
8042 if (*str++ != '}')
8043 {
f03698e6 8044 inst.error = _("missing `}'");
b99bd4ef
NC
8045 return FAIL;
8046 }
8047 }
8048 else
8049 {
8050 expressionS expr;
8051
8052 if (my_get_expression (&expr, &str))
8053 return FAIL;
8054
8055 if (expr.X_op == O_constant)
8056 {
8057 if (expr.X_add_number
8058 != (expr.X_add_number & 0x0000ffff))
8059 {
8060 inst.error = _("invalid register mask");
8061 return FAIL;
8062 }
8063
8064 if ((range & expr.X_add_number) != 0)
8065 {
8066 int regno = range & expr.X_add_number;
8067
8068 regno &= -regno;
8069 regno = (1 << regno) - 1;
8070 as_tsktsk
f03698e6 8071 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8072 regno);
8073 }
8074
8075 range |= expr.X_add_number;
8076 }
8077 else
8078 {
8079 if (inst.reloc.type != 0)
8080 {
8081 inst.error = _("expression too complex");
8082 return FAIL;
8083 }
8084
8085 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8086 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8087 inst.reloc.pc_rel = 0;
8088 }
8089 }
8090
8091 skip_whitespace (str);
8092
8093 if (*str == '|' || *str == '+')
8094 {
8095 str++;
8096 another_range = 1;
8097 }
8098 }
8099 while (another_range);
8100
8101 *strp = str;
8102 return range;
8103}
8104
8105static void
f2b7cb0a 8106do_ldmstm (str)
b99bd4ef 8107 char * str;
b99bd4ef
NC
8108{
8109 int base_reg;
8110 long range;
8111
8112 skip_whitespace (str);
8113
8114 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8115 return;
8116
8117 if (base_reg == REG_PC)
8118 {
8119 inst.error = _("r15 not allowed as base register");
8120 return;
8121 }
8122
8123 skip_whitespace (str);
8124
8125 if (*str == '!')
8126 {
90e4755a 8127 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8128 str++;
8129 }
8130
8131 if (skip_past_comma (&str) == FAIL
8132 || (range = reg_list (&str)) == FAIL)
8133 {
8134 if (! inst.error)
8135 inst.error = BAD_ARGS;
8136 return;
8137 }
8138
8139 if (*str == '^')
8140 {
8141 str++;
90e4755a 8142 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8143 }
8144
6189168b
NC
8145 if (inst.instruction & WRITE_BACK)
8146 {
8147 /* Check for unpredictable uses of writeback. */
8148 if (inst.instruction & LOAD_BIT)
8149 {
8150 /* Not allowed in LDM type 2. */
8151 if ((inst.instruction & LDM_TYPE_2_OR_3)
8152 && ((range & (1 << REG_PC)) == 0))
8153 as_warn (_("writeback of base register is UNPREDICTABLE"));
8154 /* Only allowed if base reg not in list for other types. */
8155 else if (range & (1 << base_reg))
8156 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8157 }
8158 else /* STM. */
8159 {
8160 /* Not allowed for type 2. */
8161 if (inst.instruction & LDM_TYPE_2_OR_3)
8162 as_warn (_("writeback of base register is UNPREDICTABLE"));
8163 /* Only allowed if base reg not in list, or first in list. */
8164 else if ((range & (1 << base_reg))
8165 && (range & ((1 << base_reg) - 1)))
8166 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8167 }
8168 }
61b5f74b 8169
f2b7cb0a 8170 inst.instruction |= range;
b99bd4ef 8171 end_of_line (str);
b99bd4ef
NC
8172}
8173
8174static void
f2b7cb0a 8175do_swi (str)
b99bd4ef 8176 char * str;
b99bd4ef
NC
8177{
8178 skip_whitespace (str);
8179
8180 /* Allow optional leading '#'. */
8181 if (is_immediate_prefix (*str))
8182 str++;
8183
8184 if (my_get_expression (& inst.reloc.exp, & str))
8185 return;
8186
8187 inst.reloc.type = BFD_RELOC_ARM_SWI;
8188 inst.reloc.pc_rel = 0;
b99bd4ef 8189 end_of_line (str);
b99bd4ef
NC
8190}
8191
8192static void
f2b7cb0a 8193do_swap (str)
b99bd4ef 8194 char * str;
b99bd4ef
NC
8195{
8196 int reg;
8197
8198 skip_whitespace (str);
8199
8200 if ((reg = reg_required_here (&str, 12)) == FAIL)
8201 return;
8202
8203 if (reg == REG_PC)
8204 {
8205 inst.error = _("r15 not allowed in swap");
8206 return;
8207 }
8208
8209 if (skip_past_comma (&str) == FAIL
8210 || (reg = reg_required_here (&str, 0)) == FAIL)
8211 {
8212 if (!inst.error)
8213 inst.error = BAD_ARGS;
8214 return;
8215 }
8216
8217 if (reg == REG_PC)
8218 {
8219 inst.error = _("r15 not allowed in swap");
8220 return;
8221 }
8222
8223 if (skip_past_comma (&str) == FAIL
8224 || *str++ != '[')
8225 {
8226 inst.error = BAD_ARGS;
8227 return;
8228 }
8229
8230 skip_whitespace (str);
8231
8232 if ((reg = reg_required_here (&str, 16)) == FAIL)
8233 return;
8234
8235 if (reg == REG_PC)
8236 {
8237 inst.error = BAD_PC;
8238 return;
8239 }
8240
8241 skip_whitespace (str);
8242
8243 if (*str++ != ']')
8244 {
8245 inst.error = _("missing ]");
8246 return;
8247 }
8248
b99bd4ef 8249 end_of_line (str);
b99bd4ef
NC
8250}
8251
8252static void
f2b7cb0a 8253do_branch (str)
b99bd4ef 8254 char * str;
b99bd4ef
NC
8255{
8256 if (my_get_expression (&inst.reloc.exp, &str))
8257 return;
8258
8259#ifdef OBJ_ELF
8260 {
8261 char * save_in;
8262
8263 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8264 required for the instruction. */
8265
8266 /* arm_parse_reloc () works on input_line_pointer.
8267 We actually want to parse the operands to the branch instruction
8268 passed in 'str'. Save the input pointer and restore it later. */
8269 save_in = input_line_pointer;
8270 input_line_pointer = str;
8271 if (inst.reloc.exp.X_op == O_symbol
8272 && *str == '('
8273 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8274 {
8275 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8276 inst.reloc.pc_rel = 0;
8277 /* Modify str to point to after parsed operands, otherwise
8278 end_of_line() will complain about the (PLT) left in str. */
8279 str = input_line_pointer;
8280 }
8281 else
8282 {
8283 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8284 inst.reloc.pc_rel = 1;
8285 }
8286 input_line_pointer = save_in;
8287 }
8288#else
8289 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8290 inst.reloc.pc_rel = 1;
8291#endif /* OBJ_ELF */
8292
8293 end_of_line (str);
b99bd4ef
NC
8294}
8295
8296static void
f2b7cb0a 8297do_bx (str)
b99bd4ef 8298 char * str;
b99bd4ef
NC
8299{
8300 int reg;
8301
8302 skip_whitespace (str);
8303
8304 if ((reg = reg_required_here (&str, 0)) == FAIL)
8305 {
8306 inst.error = BAD_ARGS;
8307 return;
8308 }
8309
8310 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8311 if (reg == REG_PC)
f03698e6 8312 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8313
8314 end_of_line (str);
8315}
8316
8317static void
f2b7cb0a 8318do_cdp (str)
b99bd4ef 8319 char * str;
b99bd4ef
NC
8320{
8321 /* Co-processor data operation.
8322 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8323 skip_whitespace (str);
8324
8325 if (co_proc_number (&str) == FAIL)
8326 {
8327 if (!inst.error)
8328 inst.error = BAD_ARGS;
8329 return;
8330 }
8331
8332 if (skip_past_comma (&str) == FAIL
8333 || cp_opc_expr (&str, 20,4) == FAIL)
8334 {
8335 if (!inst.error)
8336 inst.error = BAD_ARGS;
8337 return;
8338 }
8339
8340 if (skip_past_comma (&str) == FAIL
8341 || cp_reg_required_here (&str, 12) == FAIL)
8342 {
8343 if (!inst.error)
8344 inst.error = BAD_ARGS;
8345 return;
8346 }
8347
8348 if (skip_past_comma (&str) == FAIL
8349 || cp_reg_required_here (&str, 16) == FAIL)
8350 {
8351 if (!inst.error)
8352 inst.error = BAD_ARGS;
8353 return;
8354 }
8355
8356 if (skip_past_comma (&str) == FAIL
8357 || cp_reg_required_here (&str, 0) == FAIL)
8358 {
8359 if (!inst.error)
8360 inst.error = BAD_ARGS;
8361 return;
8362 }
8363
8364 if (skip_past_comma (&str) == SUCCESS)
8365 {
8366 if (cp_opc_expr (&str, 5, 3) == FAIL)
8367 {
8368 if (!inst.error)
8369 inst.error = BAD_ARGS;
8370 return;
8371 }
8372 }
8373
8374 end_of_line (str);
b99bd4ef
NC
8375}
8376
8377static void
f2b7cb0a 8378do_lstc (str)
b99bd4ef 8379 char * str;
b99bd4ef
NC
8380{
8381 /* Co-processor register load/store.
8382 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8383
8384 skip_whitespace (str);
8385
8386 if (co_proc_number (&str) == FAIL)
8387 {
8388 if (!inst.error)
8389 inst.error = BAD_ARGS;
8390 return;
8391 }
8392
8393 if (skip_past_comma (&str) == FAIL
8394 || cp_reg_required_here (&str, 12) == FAIL)
8395 {
8396 if (!inst.error)
8397 inst.error = BAD_ARGS;
8398 return;
8399 }
8400
8401 if (skip_past_comma (&str) == FAIL
bfae80f2 8402 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8403 {
8404 if (! inst.error)
8405 inst.error = BAD_ARGS;
8406 return;
8407 }
8408
b99bd4ef 8409 end_of_line (str);
b99bd4ef
NC
8410}
8411
8412static void
f2b7cb0a 8413do_co_reg (str)
b99bd4ef 8414 char * str;
b99bd4ef
NC
8415{
8416 /* Co-processor register transfer.
8417 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8418
8419 skip_whitespace (str);
8420
8421 if (co_proc_number (&str) == FAIL)
8422 {
8423 if (!inst.error)
8424 inst.error = BAD_ARGS;
8425 return;
8426 }
8427
8428 if (skip_past_comma (&str) == FAIL
8429 || cp_opc_expr (&str, 21, 3) == FAIL)
8430 {
8431 if (!inst.error)
8432 inst.error = BAD_ARGS;
8433 return;
8434 }
8435
8436 if (skip_past_comma (&str) == FAIL
8437 || reg_required_here (&str, 12) == FAIL)
8438 {
8439 if (!inst.error)
8440 inst.error = BAD_ARGS;
8441 return;
8442 }
8443
8444 if (skip_past_comma (&str) == FAIL
8445 || cp_reg_required_here (&str, 16) == FAIL)
8446 {
8447 if (!inst.error)
8448 inst.error = BAD_ARGS;
8449 return;
8450 }
8451
8452 if (skip_past_comma (&str) == FAIL
8453 || cp_reg_required_here (&str, 0) == FAIL)
8454 {
8455 if (!inst.error)
8456 inst.error = BAD_ARGS;
8457 return;
8458 }
8459
8460 if (skip_past_comma (&str) == SUCCESS)
8461 {
8462 if (cp_opc_expr (&str, 5, 3) == FAIL)
8463 {
8464 if (!inst.error)
8465 inst.error = BAD_ARGS;
8466 return;
8467 }
8468 }
b99bd4ef
NC
8469
8470 end_of_line (str);
b99bd4ef
NC
8471}
8472
8473static void
f2b7cb0a 8474do_fpa_ctrl (str)
b99bd4ef 8475 char * str;
b99bd4ef
NC
8476{
8477 /* FP control registers.
8478 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8479
8480 skip_whitespace (str);
8481
8482 if (reg_required_here (&str, 12) == FAIL)
8483 {
8484 if (!inst.error)
8485 inst.error = BAD_ARGS;
8486 return;
8487 }
8488
8489 end_of_line (str);
b99bd4ef
NC
8490}
8491
8492static void
f2b7cb0a 8493do_fpa_ldst (str)
b99bd4ef 8494 char * str;
b99bd4ef
NC
8495{
8496 skip_whitespace (str);
8497
b99bd4ef
NC
8498 if (fp_reg_required_here (&str, 12) == FAIL)
8499 {
8500 if (!inst.error)
8501 inst.error = BAD_ARGS;
8502 return;
8503 }
8504
8505 if (skip_past_comma (&str) == FAIL
bfae80f2 8506 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8507 {
8508 if (!inst.error)
8509 inst.error = BAD_ARGS;
8510 return;
8511 }
8512
8513 end_of_line (str);
8514}
8515
8516static void
f2b7cb0a 8517do_fpa_ldmstm (str)
b99bd4ef 8518 char * str;
b99bd4ef
NC
8519{
8520 int num_regs;
8521
8522 skip_whitespace (str);
8523
8524 if (fp_reg_required_here (&str, 12) == FAIL)
8525 {
8526 if (! inst.error)
8527 inst.error = BAD_ARGS;
8528 return;
8529 }
8530
8531 /* Get Number of registers to transfer. */
8532 if (skip_past_comma (&str) == FAIL
8533 || my_get_expression (&inst.reloc.exp, &str))
8534 {
8535 if (! inst.error)
8536 inst.error = _("constant expression expected");
8537 return;
8538 }
8539
8540 if (inst.reloc.exp.X_op != O_constant)
8541 {
f03698e6 8542 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8543 return;
8544 }
8545
8546 num_regs = inst.reloc.exp.X_add_number;
8547
8548 if (num_regs < 1 || num_regs > 4)
8549 {
8550 inst.error = _("number of registers must be in the range [1:4]");
8551 return;
8552 }
8553
8554 switch (num_regs)
8555 {
8556 case 1:
8557 inst.instruction |= CP_T_X;
8558 break;
8559 case 2:
8560 inst.instruction |= CP_T_Y;
8561 break;
8562 case 3:
8563 inst.instruction |= CP_T_Y | CP_T_X;
8564 break;
8565 case 4:
8566 break;
8567 default:
8568 abort ();
8569 }
8570
e28cd48c 8571 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8572 {
8573 int reg;
8574 int write_back;
8575 int offset;
8576
8577 /* The instruction specified "ea" or "fd", so we can only accept
8578 [Rn]{!}. The instruction does not really support stacking or
8579 unstacking, so we have to emulate these by setting appropriate
8580 bits and offsets. */
8581 if (skip_past_comma (&str) == FAIL
8582 || *str != '[')
8583 {
8584 if (! inst.error)
8585 inst.error = BAD_ARGS;
8586 return;
8587 }
8588
8589 str++;
8590 skip_whitespace (str);
8591
8592 if ((reg = reg_required_here (&str, 16)) == FAIL)
8593 return;
8594
8595 skip_whitespace (str);
8596
8597 if (*str != ']')
8598 {
8599 inst.error = BAD_ARGS;
8600 return;
8601 }
8602
8603 str++;
8604 if (*str == '!')
8605 {
8606 write_back = 1;
8607 str++;
8608 if (reg == REG_PC)
8609 {
8610 inst.error =
f03698e6 8611 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8612 return;
8613 }
8614 }
8615 else
8616 write_back = 0;
8617
90e4755a 8618 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8619 {
8620 /* Pre-decrement. */
8621 offset = 3 * num_regs;
8622 if (write_back)
90e4755a 8623 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8624 }
8625 else
8626 {
8627 /* Post-increment. */
8628 if (write_back)
8629 {
90e4755a 8630 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8631 offset = 3 * num_regs;
8632 }
8633 else
8634 {
8635 /* No write-back, so convert this into a standard pre-increment
8636 instruction -- aesthetically more pleasing. */
90e4755a 8637 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8638 offset = 0;
8639 }
8640 }
8641
f2b7cb0a 8642 inst.instruction |= offset;
b99bd4ef
NC
8643 }
8644 else if (skip_past_comma (&str) == FAIL
bfae80f2 8645 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8646 {
8647 if (! inst.error)
8648 inst.error = BAD_ARGS;
8649 return;
8650 }
8651
8652 end_of_line (str);
8653}
8654
8655static void
f2b7cb0a 8656do_fpa_dyadic (str)
b99bd4ef 8657 char * str;
b99bd4ef
NC
8658{
8659 skip_whitespace (str);
8660
b99bd4ef
NC
8661 if (fp_reg_required_here (&str, 12) == FAIL)
8662 {
8663 if (! inst.error)
8664 inst.error = BAD_ARGS;
8665 return;
8666 }
8667
8668 if (skip_past_comma (&str) == FAIL
8669 || fp_reg_required_here (&str, 16) == FAIL)
8670 {
8671 if (! inst.error)
8672 inst.error = BAD_ARGS;
8673 return;
8674 }
8675
8676 if (skip_past_comma (&str) == FAIL
8677 || fp_op2 (&str) == FAIL)
8678 {
8679 if (! inst.error)
8680 inst.error = BAD_ARGS;
8681 return;
8682 }
8683
b99bd4ef 8684 end_of_line (str);
b99bd4ef
NC
8685}
8686
8687static void
f2b7cb0a 8688do_fpa_monadic (str)
b99bd4ef 8689 char * str;
b99bd4ef
NC
8690{
8691 skip_whitespace (str);
8692
b99bd4ef
NC
8693 if (fp_reg_required_here (&str, 12) == FAIL)
8694 {
8695 if (! inst.error)
8696 inst.error = BAD_ARGS;
8697 return;
8698 }
8699
8700 if (skip_past_comma (&str) == FAIL
8701 || fp_op2 (&str) == FAIL)
8702 {
8703 if (! inst.error)
8704 inst.error = BAD_ARGS;
8705 return;
8706 }
8707
b99bd4ef 8708 end_of_line (str);
b99bd4ef
NC
8709}
8710
8711static void
f2b7cb0a 8712do_fpa_cmp (str)
b99bd4ef 8713 char * str;
b99bd4ef
NC
8714{
8715 skip_whitespace (str);
8716
8717 if (fp_reg_required_here (&str, 16) == FAIL)
8718 {
8719 if (! inst.error)
8720 inst.error = BAD_ARGS;
8721 return;
8722 }
8723
8724 if (skip_past_comma (&str) == FAIL
8725 || fp_op2 (&str) == FAIL)
8726 {
8727 if (! inst.error)
8728 inst.error = BAD_ARGS;
8729 return;
8730 }
8731
b99bd4ef 8732 end_of_line (str);
b99bd4ef
NC
8733}
8734
8735static void
f2b7cb0a 8736do_fpa_from_reg (str)
b99bd4ef 8737 char * str;
b99bd4ef
NC
8738{
8739 skip_whitespace (str);
8740
b99bd4ef
NC
8741 if (fp_reg_required_here (&str, 16) == FAIL)
8742 {
8743 if (! inst.error)
8744 inst.error = BAD_ARGS;
8745 return;
8746 }
8747
8748 if (skip_past_comma (&str) == FAIL
8749 || reg_required_here (&str, 12) == FAIL)
8750 {
8751 if (! inst.error)
8752 inst.error = BAD_ARGS;
8753 return;
8754 }
8755
b99bd4ef 8756 end_of_line (str);
b99bd4ef
NC
8757}
8758
8759static void
f2b7cb0a 8760do_fpa_to_reg (str)
b99bd4ef 8761 char * str;
b99bd4ef
NC
8762{
8763 skip_whitespace (str);
8764
8765 if (reg_required_here (&str, 12) == FAIL)
8766 return;
8767
8768 if (skip_past_comma (&str) == FAIL
8769 || fp_reg_required_here (&str, 0) == FAIL)
8770 {
8771 if (! inst.error)
8772 inst.error = BAD_ARGS;
8773 return;
8774 }
8775
b99bd4ef 8776 end_of_line (str);
b99bd4ef
NC
8777}
8778
b99bd4ef 8779static int
bfae80f2
RE
8780vfp_sp_reg_required_here (str, pos)
8781 char **str;
8782 enum vfp_sp_reg_pos pos;
b99bd4ef 8783{
bfae80f2
RE
8784 int reg;
8785 char *start = *str;
b99bd4ef 8786
bfae80f2 8787 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8788 {
bfae80f2 8789 switch (pos)
b99bd4ef 8790 {
bfae80f2
RE
8791 case VFP_REG_Sd:
8792 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8793 break;
8794
8795 case VFP_REG_Sn:
8796 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8797 break;
8798
8799 case VFP_REG_Sm:
8800 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8801 break;
8802
8803 default:
8804 abort ();
b99bd4ef 8805 }
bfae80f2
RE
8806 return reg;
8807 }
b99bd4ef 8808
bfae80f2
RE
8809 /* In the few cases where we might be able to accept something else
8810 this error can be overridden. */
8811 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8812
8813 /* Restore the start point. */
8814 *str = start;
8815 return FAIL;
8816}
8817
8818static int
8819vfp_dp_reg_required_here (str, pos)
8820 char **str;
f201ccb3 8821 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8822{
8823 int reg;
8824 char *start = *str;
8825
8826 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8827 {
8828 switch (pos)
b99bd4ef 8829 {
bfae80f2
RE
8830 case VFP_REG_Dd:
8831 inst.instruction |= reg << 12;
8832 break;
b99bd4ef 8833
bfae80f2
RE
8834 case VFP_REG_Dn:
8835 inst.instruction |= reg << 16;
8836 break;
8837
8838 case VFP_REG_Dm:
8839 inst.instruction |= reg << 0;
8840 break;
8841
8842 default:
8843 abort ();
8844 }
8845 return reg;
b99bd4ef
NC
8846 }
8847
bfae80f2
RE
8848 /* In the few cases where we might be able to accept something else
8849 this error can be overridden. */
8850 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8851
bfae80f2
RE
8852 /* Restore the start point. */
8853 *str = start;
8854 return FAIL;
8855}
b99bd4ef
NC
8856
8857static void
bfae80f2
RE
8858do_vfp_sp_monadic (str)
8859 char *str;
b99bd4ef 8860{
b99bd4ef
NC
8861 skip_whitespace (str);
8862
bfae80f2
RE
8863 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8864 return;
8865
8866 if (skip_past_comma (&str) == FAIL
8867 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8868 {
8869 if (! inst.error)
8870 inst.error = BAD_ARGS;
8871 return;
8872 }
8873
bfae80f2 8874 end_of_line (str);
bfae80f2
RE
8875}
8876
8877static void
8878do_vfp_dp_monadic (str)
8879 char *str;
8880{
8881 skip_whitespace (str);
8882
8883 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8884 return;
8885
8886 if (skip_past_comma (&str) == FAIL
8887 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8888 {
bfae80f2
RE
8889 if (! inst.error)
8890 inst.error = BAD_ARGS;
8891 return;
b99bd4ef 8892 }
b99bd4ef 8893
bfae80f2 8894 end_of_line (str);
bfae80f2 8895}
b99bd4ef 8896
bfae80f2
RE
8897static void
8898do_vfp_sp_dyadic (str)
8899 char *str;
8900{
8901 skip_whitespace (str);
b99bd4ef 8902
bfae80f2
RE
8903 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8904 return;
b99bd4ef 8905
bfae80f2
RE
8906 if (skip_past_comma (&str) == FAIL
8907 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8908 || skip_past_comma (&str) == FAIL
8909 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8910 {
bfae80f2
RE
8911 if (! inst.error)
8912 inst.error = BAD_ARGS;
8913 return;
8914 }
b99bd4ef 8915
bfae80f2 8916 end_of_line (str);
bfae80f2 8917}
b99bd4ef 8918
bfae80f2
RE
8919static void
8920do_vfp_dp_dyadic (str)
8921 char *str;
8922{
8923 skip_whitespace (str);
b99bd4ef 8924
bfae80f2
RE
8925 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8926 return;
b99bd4ef 8927
bfae80f2
RE
8928 if (skip_past_comma (&str) == FAIL
8929 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8930 || skip_past_comma (&str) == FAIL
8931 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8932 {
8933 if (! inst.error)
8934 inst.error = BAD_ARGS;
8935 return;
8936 }
b99bd4ef 8937
bfae80f2 8938 end_of_line (str);
bfae80f2 8939}
b99bd4ef 8940
bfae80f2
RE
8941static void
8942do_vfp_reg_from_sp (str)
8943 char *str;
8944{
8945 skip_whitespace (str);
8946
8947 if (reg_required_here (&str, 12) == FAIL)
8948 return;
8949
8950 if (skip_past_comma (&str) == FAIL
8951 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8952 {
8953 if (! inst.error)
8954 inst.error = BAD_ARGS;
8955 return;
8956 }
8957
8958 end_of_line (str);
bfae80f2
RE
8959}
8960
8961static void
e45d0630 8962do_vfp_reg2_from_sp2 (str)
bfae80f2
RE
8963 char *str;
8964{
8965 skip_whitespace (str);
8966
e45d0630
PB
8967 if (reg_required_here (&str, 12) == FAIL
8968 || skip_past_comma (&str) == FAIL
bfae80f2
RE
8969 || reg_required_here (&str, 16) == FAIL
8970 || skip_past_comma (&str) == FAIL)
8971 {
8972 if (! inst.error)
8973 inst.error = BAD_ARGS;
8974 return;
8975 }
8976
8977 /* We require exactly two consecutive SP registers. */
8978 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8979 {
8980 if (! inst.error)
8981 inst.error = _("only two consecutive VFP SP registers allowed here");
8982 }
8983
8984 end_of_line (str);
bfae80f2
RE
8985}
8986
8987static void
8988do_vfp_sp_from_reg (str)
8989 char *str;
8990{
8991 skip_whitespace (str);
8992
8993 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8994 return;
8995
8996 if (skip_past_comma (&str) == FAIL
8997 || reg_required_here (&str, 12) == FAIL)
8998 {
8999 if (! inst.error)
9000 inst.error = BAD_ARGS;
9001 return;
9002 }
9003
9004 end_of_line (str);
bfae80f2
RE
9005}
9006
e45d0630
PB
9007static void
9008do_vfp_sp2_from_reg2 (str)
9009 char *str;
9010{
9011 skip_whitespace (str);
9012
9013 /* We require exactly two consecutive SP registers. */
9014 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9015 {
9016 if (! inst.error)
9017 inst.error = _("only two consecutive VFP SP registers allowed here");
9018 }
9019
9020 if (skip_past_comma (&str) == FAIL
9021 || reg_required_here (&str, 12) == FAIL
9022 || skip_past_comma (&str) == FAIL
9023 || reg_required_here (&str, 16) == FAIL)
9024 {
9025 if (! inst.error)
9026 inst.error = BAD_ARGS;
9027 return;
9028 }
9029
9030 end_of_line (str);
9031}
9032
bfae80f2
RE
9033static void
9034do_vfp_reg_from_dp (str)
9035 char *str;
9036{
9037 skip_whitespace (str);
9038
9039 if (reg_required_here (&str, 12) == FAIL)
9040 return;
9041
9042 if (skip_past_comma (&str) == FAIL
9043 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9044 {
9045 if (! inst.error)
9046 inst.error = BAD_ARGS;
9047 return;
9048 }
9049
9050 end_of_line (str);
bfae80f2
RE
9051}
9052
9053static void
9054do_vfp_reg2_from_dp (str)
9055 char *str;
9056{
9057 skip_whitespace (str);
9058
9059 if (reg_required_here (&str, 12) == FAIL)
9060 return;
9061
9062 if (skip_past_comma (&str) == FAIL
9063 || reg_required_here (&str, 16) == FAIL
9064 || skip_past_comma (&str) == FAIL
9065 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9066 {
9067 if (! inst.error)
9068 inst.error = BAD_ARGS;
9069 return;
9070 }
9071
9072 end_of_line (str);
bfae80f2
RE
9073}
9074
9075static void
9076do_vfp_dp_from_reg (str)
9077 char *str;
9078{
9079 skip_whitespace (str);
9080
9081 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9082 return;
9083
9084 if (skip_past_comma (&str) == FAIL
9085 || reg_required_here (&str, 12) == FAIL)
9086 {
9087 if (! inst.error)
9088 inst.error = BAD_ARGS;
9089 return;
9090 }
9091
9092 end_of_line (str);
bfae80f2
RE
9093}
9094
9095static void
9096do_vfp_dp_from_reg2 (str)
9097 char *str;
9098{
9099 skip_whitespace (str);
9100
9101 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9102 return;
9103
9104 if (skip_past_comma (&str) == FAIL
9105 || reg_required_here (&str, 12) == FAIL
9106 || skip_past_comma (&str) == FAIL
e45d0630 9107 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
9108 {
9109 if (! inst.error)
9110 inst.error = BAD_ARGS;
9111 return;
9112 }
9113
9114 end_of_line (str);
bfae80f2
RE
9115}
9116
9117static const struct vfp_reg *
9118vfp_psr_parse (str)
9119 char **str;
9120{
9121 char *start = *str;
9122 char c;
9123 char *p;
9124 const struct vfp_reg *vreg;
9125
9126 p = start;
9127
9128 /* Find the end of the current token. */
9129 do
9130 {
9131 c = *p++;
9132 }
9133 while (ISALPHA (c));
9134
9135 /* Mark it. */
9136 *--p = 0;
9137
cc8a6dd0 9138 for (vreg = vfp_regs + 0;
bfae80f2
RE
9139 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9140 vreg++)
9141 {
9142 if (strcmp (start, vreg->name) == 0)
9143 {
9144 *p = c;
9145 *str = p;
9146 return vreg;
9147 }
9148 }
9149
9150 *p = c;
9151 return NULL;
9152}
9153
9154static int
9155vfp_psr_required_here (str)
9156 char **str;
9157{
9158 char *start = *str;
9159 const struct vfp_reg *vreg;
9160
9161 vreg = vfp_psr_parse (str);
9162
9163 if (vreg)
9164 {
9165 inst.instruction |= vreg->regno;
9166 return SUCCESS;
9167 }
9168
9169 inst.error = _("VFP system register expected");
9170
9171 *str = start;
9172 return FAIL;
9173}
9174
9175static void
9176do_vfp_reg_from_ctrl (str)
9177 char *str;
9178{
9179 skip_whitespace (str);
9180
9181 if (reg_required_here (&str, 12) == FAIL)
9182 return;
9183
9184 if (skip_past_comma (&str) == FAIL
9185 || vfp_psr_required_here (&str) == FAIL)
9186 {
9187 if (! inst.error)
9188 inst.error = BAD_ARGS;
9189 return;
9190 }
9191
9192 end_of_line (str);
bfae80f2
RE
9193}
9194
9195static void
9196do_vfp_ctrl_from_reg (str)
9197 char *str;
9198{
9199 skip_whitespace (str);
9200
9201 if (vfp_psr_required_here (&str) == FAIL)
9202 return;
9203
9204 if (skip_past_comma (&str) == FAIL
9205 || reg_required_here (&str, 12) == FAIL)
9206 {
9207 if (! inst.error)
9208 inst.error = BAD_ARGS;
9209 return;
9210 }
9211
9212 end_of_line (str);
bfae80f2
RE
9213}
9214
9215static void
9216do_vfp_sp_ldst (str)
9217 char *str;
9218{
9219 skip_whitespace (str);
9220
9221 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9222 {
9223 if (!inst.error)
9224 inst.error = BAD_ARGS;
9225 return;
9226 }
9227
9228 if (skip_past_comma (&str) == FAIL
9229 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9230 {
9231 if (!inst.error)
9232 inst.error = BAD_ARGS;
9233 return;
9234 }
9235
9236 end_of_line (str);
bfae80f2
RE
9237}
9238
9239static void
9240do_vfp_dp_ldst (str)
9241 char *str;
9242{
9243 skip_whitespace (str);
9244
9245 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9246 {
9247 if (!inst.error)
9248 inst.error = BAD_ARGS;
9249 return;
9250 }
9251
9252 if (skip_past_comma (&str) == FAIL
9253 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9254 {
9255 if (!inst.error)
9256 inst.error = BAD_ARGS;
9257 return;
9258 }
9259
9260 end_of_line (str);
bfae80f2
RE
9261}
9262
9263/* Parse and encode a VFP SP register list, storing the initial
9264 register in position POS and returning the range as the result. If
9265 the string is invalid return FAIL (an invalid range). */
9266static long
9267vfp_sp_reg_list (str, pos)
9268 char **str;
9269 enum vfp_sp_reg_pos pos;
9270{
9271 long range = 0;
9272 int base_reg = 0;
9273 int new_base;
9274 long base_bits = 0;
9275 int count = 0;
9276 long tempinst;
9277 unsigned long mask = 0;
9278 int warned = 0;
9279
9280 if (**str != '{')
9281 return FAIL;
9282
9283 (*str)++;
9284 skip_whitespace (*str);
9285
9286 tempinst = inst.instruction;
9287
9288 do
9289 {
9290 inst.instruction = 0;
9291
9292 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9293 return FAIL;
9294
9295 if (count == 0 || base_reg > new_base)
9296 {
9297 base_reg = new_base;
9298 base_bits = inst.instruction;
9299 }
9300
9301 if (mask & (1 << new_base))
9302 {
9303 inst.error = _("invalid register list");
9304 return FAIL;
9305 }
9306
9307 if ((mask >> new_base) != 0 && ! warned)
9308 {
9309 as_tsktsk (_("register list not in ascending order"));
9310 warned = 1;
9311 }
9312
9313 mask |= 1 << new_base;
9314 count++;
9315
9316 skip_whitespace (*str);
9317
9318 if (**str == '-') /* We have the start of a range expression */
9319 {
9320 int high_range;
9321
9322 (*str)++;
9323
9324 if ((high_range
9325 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9326 == FAIL)
9327 {
9328 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9329 return FAIL;
9330 }
9331
9332 if (high_range <= new_base)
9333 {
9334 inst.error = _("register range not in ascending order");
9335 return FAIL;
9336 }
9337
9338 for (new_base++; new_base <= high_range; new_base++)
9339 {
9340 if (mask & (1 << new_base))
9341 {
9342 inst.error = _("invalid register list");
9343 return FAIL;
9344 }
9345
9346 mask |= 1 << new_base;
9347 count++;
9348 }
9349 }
9350 }
9351 while (skip_past_comma (str) != FAIL);
9352
9353 if (**str != '}')
9354 {
9355 inst.error = _("invalid register list");
9356 return FAIL;
9357 }
9358
9359 (*str)++;
9360
9361 range = count;
9362
9363 /* Sanity check -- should have raised a parse error above. */
9364 if (count == 0 || count > 32)
c62e1cc3 9365 abort ();
bfae80f2
RE
9366
9367 /* Final test -- the registers must be consecutive. */
9368 while (count--)
9369 {
9370 if ((mask & (1 << base_reg++)) == 0)
9371 {
9372 inst.error = _("non-contiguous register range");
9373 return FAIL;
9374 }
9375 }
9376
9377 inst.instruction = tempinst | base_bits;
9378 return range;
9379}
9380
9381static long
9382vfp_dp_reg_list (str)
9383 char **str;
9384{
9385 long range = 0;
9386 int base_reg = 0;
9387 int new_base;
9388 int count = 0;
9389 long tempinst;
9390 unsigned long mask = 0;
9391 int warned = 0;
9392
9393 if (**str != '{')
9394 return FAIL;
9395
9396 (*str)++;
9397 skip_whitespace (*str);
9398
9399 tempinst = inst.instruction;
9400
9401 do
9402 {
9403 inst.instruction = 0;
9404
9405 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9406 return FAIL;
9407
9408 if (count == 0 || base_reg > new_base)
9409 {
9410 base_reg = new_base;
9411 range = inst.instruction;
9412 }
9413
9414 if (mask & (1 << new_base))
9415 {
9416 inst.error = _("invalid register list");
9417 return FAIL;
9418 }
9419
9420 if ((mask >> new_base) != 0 && ! warned)
9421 {
9422 as_tsktsk (_("register list not in ascending order"));
9423 warned = 1;
9424 }
9425
9426 mask |= 1 << new_base;
9427 count++;
9428
9429 skip_whitespace (*str);
9430
9431 if (**str == '-') /* We have the start of a range expression */
9432 {
9433 int high_range;
9434
9435 (*str)++;
9436
9437 if ((high_range
9438 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9439 == FAIL)
9440 {
9441 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9442 return FAIL;
9443 }
9444
9445 if (high_range <= new_base)
9446 {
9447 inst.error = _("register range not in ascending order");
9448 return FAIL;
9449 }
9450
9451 for (new_base++; new_base <= high_range; new_base++)
9452 {
9453 if (mask & (1 << new_base))
9454 {
9455 inst.error = _("invalid register list");
9456 return FAIL;
9457 }
9458
9459 mask |= 1 << new_base;
9460 count++;
9461 }
9462 }
9463 }
9464 while (skip_past_comma (str) != FAIL);
9465
9466 if (**str != '}')
9467 {
9468 inst.error = _("invalid register list");
9469 return FAIL;
9470 }
9471
9472 (*str)++;
9473
9474 range |= 2 * count;
9475
9476 /* Sanity check -- should have raised a parse error above. */
9477 if (count == 0 || count > 16)
c62e1cc3 9478 abort ();
bfae80f2
RE
9479
9480 /* Final test -- the registers must be consecutive. */
9481 while (count--)
9482 {
9483 if ((mask & (1 << base_reg++)) == 0)
9484 {
9485 inst.error = _("non-contiguous register range");
9486 return FAIL;
9487 }
9488 }
9489
9490 inst.instruction = tempinst;
9491 return range;
9492}
9493
9494static void
c62e1cc3 9495vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9496 char *str;
9497 enum vfp_ldstm_type ldstm_type;
9498{
9499 long range;
9500
9501 skip_whitespace (str);
9502
9503 if (reg_required_here (&str, 16) == FAIL)
9504 return;
9505
9506 skip_whitespace (str);
9507
9508 if (*str == '!')
9509 {
9510 inst.instruction |= WRITE_BACK;
9511 str++;
9512 }
9513 else if (ldstm_type != VFP_LDSTMIA)
9514 {
9515 inst.error = _("this addressing mode requires base-register writeback");
9516 return;
9517 }
9518
9519 if (skip_past_comma (&str) == FAIL
9520 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9521 {
9522 if (!inst.error)
9523 inst.error = BAD_ARGS;
9524 return;
9525 }
9526
9527 inst.instruction |= range;
9528 end_of_line (str);
9529}
9530
9531static void
c62e1cc3 9532vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9533 char *str;
9534 enum vfp_ldstm_type ldstm_type;
9535{
9536 long range;
9537
9538 skip_whitespace (str);
9539
9540 if (reg_required_here (&str, 16) == FAIL)
9541 return;
9542
9543 skip_whitespace (str);
9544
9545 if (*str == '!')
9546 {
9547 inst.instruction |= WRITE_BACK;
9548 str++;
9549 }
9550 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9551 {
9552 inst.error = _("this addressing mode requires base-register writeback");
9553 return;
9554 }
9555
9556 if (skip_past_comma (&str) == FAIL
9557 || (range = vfp_dp_reg_list (&str)) == FAIL)
9558 {
9559 if (!inst.error)
9560 inst.error = BAD_ARGS;
9561 return;
9562 }
9563
9564 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9565 range += 1;
9566
9567 inst.instruction |= range;
9568 end_of_line (str);
9569}
9570
9571static void
9572do_vfp_sp_ldstmia (str)
9573 char *str;
9574{
9575 vfp_sp_ldstm (str, VFP_LDSTMIA);
9576}
9577
9578static void
9579do_vfp_sp_ldstmdb (str)
9580 char *str;
9581{
9582 vfp_sp_ldstm (str, VFP_LDSTMDB);
9583}
9584
9585static void
9586do_vfp_dp_ldstmia (str)
9587 char *str;
9588{
9589 vfp_dp_ldstm (str, VFP_LDSTMIA);
9590}
9591
9592static void
9593do_vfp_dp_ldstmdb (str)
9594 char *str;
9595{
9596 vfp_dp_ldstm (str, VFP_LDSTMDB);
9597}
9598
9599static void
9600do_vfp_xp_ldstmia (str)
9601 char *str;
9602{
9603 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9604}
9605
9606static void
9607do_vfp_xp_ldstmdb (str)
9608 char *str;
9609{
9610 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9611}
9612
9613static void
9614do_vfp_sp_compare_z (str)
9615 char *str;
9616{
9617 skip_whitespace (str);
9618
9619 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9620 {
9621 if (!inst.error)
9622 inst.error = BAD_ARGS;
9623 return;
9624 }
9625
9626 end_of_line (str);
bfae80f2
RE
9627}
9628
9629static void
9630do_vfp_dp_compare_z (str)
9631 char *str;
9632{
9633 skip_whitespace (str);
9634
9635 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9636 {
9637 if (!inst.error)
9638 inst.error = BAD_ARGS;
9639 return;
9640 }
9641
9642 end_of_line (str);
bfae80f2
RE
9643}
9644
9645static void
9646do_vfp_dp_sp_cvt (str)
9647 char *str;
9648{
9649 skip_whitespace (str);
9650
9651 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9652 return;
9653
9654 if (skip_past_comma (&str) == FAIL
9655 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9656 {
9657 if (! inst.error)
9658 inst.error = BAD_ARGS;
9659 return;
9660 }
9661
9662 end_of_line (str);
bfae80f2
RE
9663}
9664
9665static void
9666do_vfp_sp_dp_cvt (str)
9667 char *str;
9668{
9669 skip_whitespace (str);
9670
9671 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9672 return;
9673
9674 if (skip_past_comma (&str) == FAIL
9675 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9676 {
9677 if (! inst.error)
9678 inst.error = BAD_ARGS;
9679 return;
9680 }
9681
9682 end_of_line (str);
bfae80f2
RE
9683}
9684
9685/* Thumb specific routines. */
9686
9687/* Parse and validate that a register is of the right form, this saves
9688 repeated checking of this information in many similar cases.
9689 Unlike the 32-bit case we do not insert the register into the opcode
9690 here, since the position is often unknown until the full instruction
9691 has been parsed. */
9692
9693static int
9694thumb_reg (strp, hi_lo)
9695 char ** strp;
9696 int hi_lo;
9697{
9698 int reg;
9699
9700 if ((reg = reg_required_here (strp, -1)) == FAIL)
9701 return FAIL;
9702
9703 switch (hi_lo)
9704 {
9705 case THUMB_REG_LO:
9706 if (reg > 7)
9707 {
9708 inst.error = _("lo register required");
9709 return FAIL;
9710 }
9711 break;
9712
9713 case THUMB_REG_HI:
9714 if (reg < 8)
9715 {
9716 inst.error = _("hi register required");
9717 return FAIL;
9718 }
9719 break;
9720
9721 default:
9722 break;
9723 }
9724
9725 return reg;
9726}
9727
9728/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9729 was SUB. */
9730
9731static void
9732thumb_add_sub (str, subtract)
9733 char * str;
9734 int subtract;
9735{
9736 int Rd, Rs, Rn = FAIL;
9737
9738 skip_whitespace (str);
9739
9740 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9741 || skip_past_comma (&str) == FAIL)
9742 {
9743 if (! inst.error)
9744 inst.error = BAD_ARGS;
9745 return;
9746 }
9747
9748 if (is_immediate_prefix (*str))
9749 {
9750 Rs = Rd;
9751 str++;
9752 if (my_get_expression (&inst.reloc.exp, &str))
9753 return;
9754 }
9755 else
9756 {
9757 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9758 return;
9759
9760 if (skip_past_comma (&str) == FAIL)
9761 {
9762 /* Two operand format, shuffle the registers
9763 and pretend there are 3. */
9764 Rn = Rs;
9765 Rs = Rd;
9766 }
9767 else if (is_immediate_prefix (*str))
9768 {
9769 str++;
9770 if (my_get_expression (&inst.reloc.exp, &str))
9771 return;
9772 }
9773 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9774 return;
9775 }
9776
9777 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9778 for the latter case, EXPR contains the immediate that was found. */
9779 if (Rn != FAIL)
9780 {
9781 /* All register format. */
9782 if (Rd > 7 || Rs > 7 || Rn > 7)
9783 {
9784 if (Rs != Rd)
9785 {
9786 inst.error = _("dest and source1 must be the same register");
9787 return;
9788 }
9789
9790 /* Can't do this for SUB. */
9791 if (subtract)
9792 {
9793 inst.error = _("subtract valid only on lo regs");
9794 return;
9795 }
9796
9797 inst.instruction = (T_OPCODE_ADD_HI
9798 | (Rd > 7 ? THUMB_H1 : 0)
9799 | (Rn > 7 ? THUMB_H2 : 0));
9800 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9801 }
9802 else
9803 {
9804 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9805 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9806 }
9807 }
9808 else
9809 {
9810 /* Immediate expression, now things start to get nasty. */
9811
9812 /* First deal with HI regs, only very restricted cases allowed:
9813 Adjusting SP, and using PC or SP to get an address. */
9814 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9815 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9816 {
9817 inst.error = _("invalid Hi register with immediate");
9818 return;
9819 }
9820
9821 if (inst.reloc.exp.X_op != O_constant)
9822 {
9823 /* Value isn't known yet, all we can do is store all the fragments
9824 we know about in the instruction and let the reloc hacking
9825 work it all out. */
9826 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9827 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9828 }
9829 else
9830 {
9831 int offset = inst.reloc.exp.X_add_number;
9832
9833 if (subtract)
358b94bd 9834 offset = - offset;
bfae80f2
RE
9835
9836 if (offset < 0)
9837 {
358b94bd 9838 offset = - offset;
bfae80f2
RE
9839 subtract = 1;
9840
9841 /* Quick check, in case offset is MIN_INT. */
9842 if (offset < 0)
9843 {
9844 inst.error = _("immediate value out of range");
9845 return;
9846 }
9847 }
358b94bd
NC
9848 /* Note - you cannot convert a subtract of 0 into an
9849 add of 0 because the carry flag is set differently. */
9850 else if (offset > 0)
bfae80f2
RE
9851 subtract = 0;
9852
9853 if (Rd == REG_SP)
9854 {
9855 if (offset & ~0x1fc)
9856 {
9857 inst.error = _("invalid immediate value for stack adjust");
9858 return;
b99bd4ef
NC
9859 }
9860 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9861 inst.instruction |= offset >> 2;
9862 }
9863 else if (Rs == REG_PC || Rs == REG_SP)
9864 {
9865 if (subtract
9866 || (offset & ~0x3fc))
9867 {
9868 inst.error = _("invalid immediate for address calculation");
9869 return;
9870 }
9871 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9872 : T_OPCODE_ADD_SP);
9873 inst.instruction |= (Rd << 8) | (offset >> 2);
9874 }
9875 else if (Rs == Rd)
9876 {
9877 if (offset & ~0xff)
9878 {
9879 inst.error = _("immediate value out of range");
9880 return;
9881 }
9882 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9883 inst.instruction |= (Rd << 8) | offset;
9884 }
9885 else
9886 {
9887 if (offset & ~0x7)
9888 {
9889 inst.error = _("immediate value out of range");
9890 return;
9891 }
9892 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9893 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9894 }
9895 }
9896 }
9897
9898 end_of_line (str);
9899}
9900
9901static void
9902thumb_shift (str, shift)
9903 char * str;
9904 int shift;
9905{
9906 int Rd, Rs, Rn = FAIL;
9907
9908 skip_whitespace (str);
9909
9910 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9911 || skip_past_comma (&str) == FAIL)
9912 {
9913 if (! inst.error)
9914 inst.error = BAD_ARGS;
9915 return;
9916 }
9917
9918 if (is_immediate_prefix (*str))
9919 {
9920 /* Two operand immediate format, set Rs to Rd. */
9921 Rs = Rd;
9922 str ++;
9923 if (my_get_expression (&inst.reloc.exp, &str))
9924 return;
9925 }
9926 else
9927 {
9928 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9929 return;
9930
9931 if (skip_past_comma (&str) == FAIL)
9932 {
9933 /* Two operand format, shuffle the registers
9934 and pretend there are 3. */
9935 Rn = Rs;
9936 Rs = Rd;
9937 }
9938 else if (is_immediate_prefix (*str))
9939 {
9940 str++;
9941 if (my_get_expression (&inst.reloc.exp, &str))
9942 return;
9943 }
9944 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9945 return;
9946 }
9947
9948 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9949 for the latter case, EXPR contains the immediate that was found. */
9950
9951 if (Rn != FAIL)
9952 {
9953 if (Rs != Rd)
9954 {
9955 inst.error = _("source1 and dest must be same register");
9956 return;
9957 }
9958
9959 switch (shift)
9960 {
9961 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9962 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9963 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9964 }
9965
9966 inst.instruction |= Rd | (Rn << 3);
9967 }
9968 else
9969 {
9970 switch (shift)
9971 {
9972 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9973 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9974 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9975 }
9976
9977 if (inst.reloc.exp.X_op != O_constant)
9978 {
9979 /* Value isn't known yet, create a dummy reloc and let reloc
9980 hacking fix it up. */
9981 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9982 }
9983 else
9984 {
9985 unsigned shift_value = inst.reloc.exp.X_add_number;
9986
9987 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9988 {
f03698e6 9989 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9990 return;
9991 }
9992
9993 /* Shifts of zero are handled by converting to LSL. */
9994 if (shift_value == 0)
9995 inst.instruction = T_OPCODE_LSL_I;
9996
9997 /* Shifts of 32 are encoded as a shift of zero. */
9998 if (shift_value == 32)
9999 shift_value = 0;
10000
10001 inst.instruction |= shift_value << 6;
10002 }
10003
10004 inst.instruction |= Rd | (Rs << 3);
10005 }
10006
10007 end_of_line (str);
10008}
10009
10010static void
10011thumb_mov_compare (str, move)
10012 char * str;
10013 int move;
10014{
10015 int Rd, Rs = FAIL;
10016
10017 skip_whitespace (str);
10018
10019 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10020 || skip_past_comma (&str) == FAIL)
10021 {
10022 if (! inst.error)
10023 inst.error = BAD_ARGS;
10024 return;
10025 }
10026
09d92015 10027 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
10028 {
10029 str++;
10030 if (my_get_expression (&inst.reloc.exp, &str))
10031 return;
10032 }
10033 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10034 return;
10035
10036 if (Rs != FAIL)
10037 {
09d92015 10038 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
10039 {
10040 if (move == THUMB_MOVE)
10041 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10042 since a MOV instruction produces unpredictable results. */
10043 inst.instruction = T_OPCODE_ADD_I3;
10044 else
10045 inst.instruction = T_OPCODE_CMP_LR;
10046 inst.instruction |= Rd | (Rs << 3);
10047 }
10048 else
10049 {
10050 if (move == THUMB_MOVE)
10051 inst.instruction = T_OPCODE_MOV_HR;
09d92015 10052 else if (move != THUMB_CPY)
b99bd4ef
NC
10053 inst.instruction = T_OPCODE_CMP_HR;
10054
10055 if (Rd > 7)
10056 inst.instruction |= THUMB_H1;
10057
10058 if (Rs > 7)
10059 inst.instruction |= THUMB_H2;
10060
10061 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10062 }
10063 }
10064 else
10065 {
10066 if (Rd > 7)
10067 {
10068 inst.error = _("only lo regs allowed with immediate");
10069 return;
10070 }
10071
10072 if (move == THUMB_MOVE)
10073 inst.instruction = T_OPCODE_MOV_I8;
10074 else
10075 inst.instruction = T_OPCODE_CMP_I8;
10076
10077 inst.instruction |= Rd << 8;
10078
10079 if (inst.reloc.exp.X_op != O_constant)
10080 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10081 else
10082 {
10083 unsigned value = inst.reloc.exp.X_add_number;
10084
10085 if (value > 255)
10086 {
10087 inst.error = _("invalid immediate");
10088 return;
10089 }
10090
10091 inst.instruction |= value;
10092 }
10093 }
10094
10095 end_of_line (str);
10096}
10097
10098static void
10099thumb_load_store (str, load_store, size)
10100 char * str;
10101 int load_store;
10102 int size;
10103{
10104 int Rd, Rb, Ro = FAIL;
10105
10106 skip_whitespace (str);
10107
10108 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10109 || skip_past_comma (&str) == FAIL)
10110 {
10111 if (! inst.error)
10112 inst.error = BAD_ARGS;
10113 return;
10114 }
10115
10116 if (*str == '[')
10117 {
10118 str++;
10119 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10120 return;
10121
10122 if (skip_past_comma (&str) != FAIL)
10123 {
10124 if (is_immediate_prefix (*str))
10125 {
10126 str++;
10127 if (my_get_expression (&inst.reloc.exp, &str))
10128 return;
10129 }
10130 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10131 return;
10132 }
10133 else
10134 {
10135 inst.reloc.exp.X_op = O_constant;
10136 inst.reloc.exp.X_add_number = 0;
10137 }
10138
10139 if (*str != ']')
10140 {
10141 inst.error = _("expected ']'");
10142 return;
10143 }
10144 str++;
10145 }
10146 else if (*str == '=')
10147 {
f03698e6
RE
10148 if (load_store != THUMB_LOAD)
10149 {
10150 inst.error = _("invalid pseudo operation");
10151 return;
10152 }
10153
b99bd4ef
NC
10154 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10155 str++;
10156
10157 skip_whitespace (str);
10158
10159 if (my_get_expression (& inst.reloc.exp, & str))
10160 return;
10161
10162 end_of_line (str);
10163
10164 if ( inst.reloc.exp.X_op != O_constant
10165 && inst.reloc.exp.X_op != O_symbol)
10166 {
10167 inst.error = "Constant expression expected";
10168 return;
10169 }
10170
10171 if (inst.reloc.exp.X_op == O_constant
10172 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10173 {
10174 /* This can be done with a mov instruction. */
10175
10176 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10177 inst.instruction |= inst.reloc.exp.X_add_number;
10178 return;
10179 }
10180
10181 /* Insert into literal pool. */
10182 if (add_to_lit_pool () == FAIL)
10183 {
10184 if (!inst.error)
10185 inst.error = "literal pool insertion failed";
10186 return;
10187 }
10188
10189 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10190 inst.reloc.pc_rel = 1;
10191 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10192 /* Adjust ARM pipeline offset to Thumb. */
10193 inst.reloc.exp.X_add_number += 4;
10194
10195 return;
10196 }
10197 else
10198 {
10199 if (my_get_expression (&inst.reloc.exp, &str))
10200 return;
10201
10202 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10203 inst.reloc.pc_rel = 1;
10204 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10205 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10206 end_of_line (str);
10207 return;
10208 }
10209
10210 if (Rb == REG_PC || Rb == REG_SP)
10211 {
10212 if (size != THUMB_WORD)
10213 {
10214 inst.error = _("byte or halfword not valid for base register");
10215 return;
10216 }
10217 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10218 {
f03698e6 10219 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10220 return;
10221 }
10222 else if (Ro != FAIL)
10223 {
f03698e6 10224 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10225 return;
10226 }
10227
10228 if (Rb == REG_PC)
10229 inst.instruction = T_OPCODE_LDR_PC;
10230 else if (load_store == THUMB_LOAD)
10231 inst.instruction = T_OPCODE_LDR_SP;
10232 else
10233 inst.instruction = T_OPCODE_STR_SP;
10234
10235 inst.instruction |= Rd << 8;
10236 if (inst.reloc.exp.X_op == O_constant)
10237 {
10238 unsigned offset = inst.reloc.exp.X_add_number;
10239
10240 if (offset & ~0x3fc)
10241 {
10242 inst.error = _("invalid offset");
10243 return;
10244 }
10245
10246 inst.instruction |= offset >> 2;
10247 }
10248 else
10249 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10250 }
10251 else if (Rb > 7)
10252 {
10253 inst.error = _("invalid base register in load/store");
10254 return;
10255 }
10256 else if (Ro == FAIL)
10257 {
10258 /* Immediate offset. */
10259 if (size == THUMB_WORD)
10260 inst.instruction = (load_store == THUMB_LOAD
10261 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10262 else if (size == THUMB_HALFWORD)
10263 inst.instruction = (load_store == THUMB_LOAD
10264 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10265 else
10266 inst.instruction = (load_store == THUMB_LOAD
10267 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10268
10269 inst.instruction |= Rd | (Rb << 3);
10270
10271 if (inst.reloc.exp.X_op == O_constant)
10272 {
10273 unsigned offset = inst.reloc.exp.X_add_number;
10274
10275 if (offset & ~(0x1f << size))
10276 {
f03698e6 10277 inst.error = _("invalid offset");
b99bd4ef
NC
10278 return;
10279 }
10280 inst.instruction |= (offset >> size) << 6;
10281 }
10282 else
10283 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10284 }
10285 else
10286 {
10287 /* Register offset. */
10288 if (size == THUMB_WORD)
10289 inst.instruction = (load_store == THUMB_LOAD
10290 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10291 else if (size == THUMB_HALFWORD)
10292 inst.instruction = (load_store == THUMB_LOAD
10293 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10294 else
10295 inst.instruction = (load_store == THUMB_LOAD
10296 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10297
10298 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10299 }
10300
10301 end_of_line (str);
10302}
10303
404ff6b5
AH
10304/* A register must be given at this point.
10305
404ff6b5
AH
10306 Shift is the place to put it in inst.instruction.
10307
404ff6b5
AH
10308 Restores input start point on err.
10309 Returns the reg#, or FAIL. */
10310
10311static int
63e63b07 10312mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10313 char ** str;
10314 int shift;
6c43fab6 10315 enum arm_reg_type regtype;
404ff6b5 10316{
6c43fab6
RE
10317 int reg;
10318 char *start = *str;
404ff6b5 10319
6c43fab6 10320 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10321 {
404ff6b5
AH
10322 if (shift >= 0)
10323 inst.instruction |= reg << shift;
10324
6c43fab6 10325 return reg;
404ff6b5
AH
10326 }
10327
6c43fab6 10328 /* Restore the start point. */
404ff6b5 10329 *str = start;
cc8a6dd0 10330
404ff6b5
AH
10331 /* In the few cases where we might be able to accept something else
10332 this error can be overridden. */
6c43fab6 10333 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10334
404ff6b5
AH
10335 return FAIL;
10336}
10337
63e63b07 10338/* Cirrus Maverick Instructions. */
404ff6b5
AH
10339
10340/* Wrapper functions. */
10341
10342static void
63e63b07 10343do_mav_binops_1a (str)
6c43fab6
RE
10344 char * str;
10345{
63e63b07 10346 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10347}
10348
10349static void
63e63b07 10350do_mav_binops_1b (str)
6c43fab6
RE
10351 char * str;
10352{
63e63b07 10353 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10354}
10355
10356static void
63e63b07 10357do_mav_binops_1c (str)
404ff6b5 10358 char * str;
404ff6b5 10359{
63e63b07 10360 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10361}
10362
10363static void
63e63b07 10364do_mav_binops_1d (str)
404ff6b5 10365 char * str;
404ff6b5 10366{
63e63b07 10367 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10368}
10369
10370static void
63e63b07 10371do_mav_binops_1e (str)
404ff6b5 10372 char * str;
404ff6b5 10373{
63e63b07 10374 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10375}
10376
10377static void
63e63b07 10378do_mav_binops_1f (str)
404ff6b5 10379 char * str;
404ff6b5 10380{
63e63b07 10381 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10382}
10383
10384static void
63e63b07 10385do_mav_binops_1g (str)
404ff6b5 10386 char * str;
404ff6b5 10387{
63e63b07 10388 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10389}
10390
10391static void
63e63b07 10392do_mav_binops_1h (str)
404ff6b5 10393 char * str;
404ff6b5 10394{
63e63b07 10395 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10396}
10397
6c43fab6 10398static void
63e63b07 10399do_mav_binops_1i (str)
6c43fab6
RE
10400 char * str;
10401{
63e63b07 10402 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10403}
10404
10405static void
63e63b07 10406do_mav_binops_1j (str)
6c43fab6
RE
10407 char * str;
10408{
63e63b07 10409 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10410}
10411
10412static void
63e63b07 10413do_mav_binops_1k (str)
6c43fab6
RE
10414 char * str;
10415{
63e63b07 10416 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10417}
10418
10419static void
63e63b07 10420do_mav_binops_1l (str)
6c43fab6
RE
10421 char * str;
10422{
63e63b07 10423 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10424}
10425
10426static void
63e63b07 10427do_mav_binops_1m (str)
6c43fab6
RE
10428 char * str;
10429{
63e63b07 10430 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10431}
10432
10433static void
63e63b07 10434do_mav_binops_1n (str)
6c43fab6
RE
10435 char * str;
10436{
63e63b07 10437 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10438}
10439
10440static void
63e63b07 10441do_mav_binops_1o (str)
6c43fab6
RE
10442 char * str;
10443{
63e63b07 10444 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10445}
10446
10447static void
63e63b07 10448do_mav_binops_2a (str)
6c43fab6
RE
10449 char * str;
10450{
63e63b07 10451 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10452}
10453
10454static void
63e63b07 10455do_mav_binops_2b (str)
6c43fab6
RE
10456 char * str;
10457{
63e63b07 10458 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10459}
10460
10461static void
63e63b07 10462do_mav_binops_2c (str)
6c43fab6
RE
10463 char * str;
10464{
63e63b07 10465 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10466}
10467
10468static void
63e63b07 10469do_mav_binops_3a (str)
6c43fab6
RE
10470 char * str;
10471{
63e63b07 10472 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10473}
10474
10475static void
63e63b07 10476do_mav_binops_3b (str)
6c43fab6
RE
10477 char * str;
10478{
63e63b07 10479 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10480}
10481
10482static void
63e63b07 10483do_mav_binops_3c (str)
6c43fab6
RE
10484 char * str;
10485{
63e63b07 10486 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10487}
10488
10489static void
63e63b07 10490do_mav_binops_3d (str)
6c43fab6
RE
10491 char * str;
10492{
63e63b07 10493 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10494}
10495
10496static void
63e63b07 10497do_mav_triple_4a (str)
6c43fab6
RE
10498 char * str;
10499{
63e63b07 10500 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10501}
10502
10503static void
63e63b07 10504do_mav_triple_4b (str)
6c43fab6
RE
10505 char * str;
10506{
63e63b07 10507 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10508}
10509
10510static void
63e63b07 10511do_mav_triple_5a (str)
6c43fab6
RE
10512 char * str;
10513{
63e63b07 10514 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10515}
10516
10517static void
63e63b07 10518do_mav_triple_5b (str)
6c43fab6
RE
10519 char * str;
10520{
63e63b07 10521 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10522}
10523
10524static void
63e63b07 10525do_mav_triple_5c (str)
6c43fab6
RE
10526 char * str;
10527{
63e63b07 10528 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10529}
10530
10531static void
63e63b07 10532do_mav_triple_5d (str)
6c43fab6
RE
10533 char * str;
10534{
63e63b07 10535 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10536}
10537
10538static void
63e63b07 10539do_mav_triple_5e (str)
6c43fab6
RE
10540 char * str;
10541{
63e63b07 10542 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10543}
10544
10545static void
63e63b07 10546do_mav_triple_5f (str)
6c43fab6
RE
10547 char * str;
10548{
63e63b07 10549 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10550}
10551
10552static void
63e63b07 10553do_mav_triple_5g (str)
6c43fab6
RE
10554 char * str;
10555{
63e63b07 10556 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10557}
10558
10559static void
63e63b07 10560do_mav_triple_5h (str)
6c43fab6
RE
10561 char * str;
10562{
63e63b07 10563 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10564}
10565
10566static void
63e63b07 10567do_mav_quad_6a (str)
6c43fab6
RE
10568 char * str;
10569{
63e63b07 10570 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10571 REG_TYPE_MVFX);
10572}
10573
10574static void
63e63b07 10575do_mav_quad_6b (str)
6c43fab6
RE
10576 char * str;
10577{
63e63b07 10578 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10579 REG_TYPE_MVFX);
10580}
10581
34920d91 10582/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
404ff6b5 10583static void
63e63b07 10584do_mav_dspsc_1 (str)
404ff6b5 10585 char * str;
404ff6b5 10586{
6c43fab6
RE
10587 skip_whitespace (str);
10588
10589 /* cfmvsc32. */
63e63b07 10590 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10591 || skip_past_comma (&str) == FAIL
34920d91 10592 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
6c43fab6
RE
10593 {
10594 if (!inst.error)
10595 inst.error = BAD_ARGS;
10596
10597 return;
10598 }
10599
10600 end_of_line (str);
404ff6b5
AH
10601}
10602
34920d91 10603/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
404ff6b5 10604static void
63e63b07 10605do_mav_dspsc_2 (str)
404ff6b5 10606 char * str;
404ff6b5 10607{
6c43fab6
RE
10608 skip_whitespace (str);
10609
10610 /* cfmv32sc. */
34920d91 10611 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
6c43fab6 10612 || skip_past_comma (&str) == FAIL
63e63b07 10613 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10614 {
10615 if (!inst.error)
10616 inst.error = BAD_ARGS;
10617
10618 return;
10619 }
10620
10621 end_of_line (str);
404ff6b5
AH
10622}
10623
10624static void
63e63b07 10625do_mav_shift_1 (str)
404ff6b5 10626 char * str;
404ff6b5 10627{
63e63b07 10628 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10629}
10630
10631static void
63e63b07 10632do_mav_shift_2 (str)
404ff6b5 10633 char * str;
404ff6b5 10634{
63e63b07 10635 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10636}
10637
10638static void
63e63b07 10639do_mav_ldst_1 (str)
404ff6b5 10640 char * str;
404ff6b5 10641{
63e63b07 10642 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10643}
10644
10645static void
63e63b07 10646do_mav_ldst_2 (str)
404ff6b5 10647 char * str;
404ff6b5 10648{
63e63b07 10649 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10650}
10651
10652static void
63e63b07 10653do_mav_ldst_3 (str)
404ff6b5 10654 char * str;
404ff6b5 10655{
63e63b07 10656 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10657}
10658
10659static void
63e63b07 10660do_mav_ldst_4 (str)
404ff6b5 10661 char * str;
404ff6b5 10662{
63e63b07 10663 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10664}
10665
10666/* Isnsn like "foo X,Y". */
10667
10668static void
63e63b07 10669do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10670 char * str;
404ff6b5 10671 int mode;
6c43fab6
RE
10672 enum arm_reg_type reg0;
10673 enum arm_reg_type reg1;
404ff6b5 10674{
6c43fab6 10675 int shift0, shift1;
404ff6b5 10676
6c43fab6
RE
10677 shift0 = mode & 0xff;
10678 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10679
10680 skip_whitespace (str);
10681
63e63b07 10682 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10683 || skip_past_comma (&str) == FAIL
63e63b07 10684 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10685 {
10686 if (!inst.error)
10687 inst.error = BAD_ARGS;
10688 }
10689 else
10690 end_of_line (str);
404ff6b5
AH
10691}
10692
10693/* Isnsn like "foo X,Y,Z". */
10694
10695static void
63e63b07 10696do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10697 char * str;
404ff6b5 10698 int mode;
6c43fab6
RE
10699 enum arm_reg_type reg0;
10700 enum arm_reg_type reg1;
10701 enum arm_reg_type reg2;
404ff6b5 10702{
6c43fab6 10703 int shift0, shift1, shift2;
404ff6b5 10704
6c43fab6
RE
10705 shift0 = mode & 0xff;
10706 shift1 = (mode >> 8) & 0xff;
10707 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10708
10709 skip_whitespace (str);
10710
63e63b07 10711 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10712 || skip_past_comma (&str) == FAIL
63e63b07 10713 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10714 || skip_past_comma (&str) == FAIL
63e63b07 10715 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10716 {
10717 if (!inst.error)
10718 inst.error = BAD_ARGS;
10719 }
10720 else
10721 end_of_line (str);
404ff6b5
AH
10722}
10723
10724/* Isnsn like "foo W,X,Y,Z".
10725 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10726
10727static void
63e63b07 10728do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10729 char * str;
404ff6b5 10730 int mode;
6c43fab6
RE
10731 enum arm_reg_type reg0;
10732 enum arm_reg_type reg1;
10733 enum arm_reg_type reg2;
10734 enum arm_reg_type reg3;
404ff6b5 10735{
6c43fab6 10736 int shift0, shift1, shift2, shift3;
404ff6b5 10737
6c43fab6
RE
10738 shift0= mode & 0xff;
10739 shift1 = (mode >> 8) & 0xff;
10740 shift2 = (mode >> 16) & 0xff;
10741 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10742
10743 skip_whitespace (str);
10744
63e63b07 10745 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10746 || skip_past_comma (&str) == FAIL
63e63b07 10747 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10748 || skip_past_comma (&str) == FAIL
63e63b07 10749 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10750 || skip_past_comma (&str) == FAIL
63e63b07 10751 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10752 {
10753 if (!inst.error)
10754 inst.error = BAD_ARGS;
10755 }
10756 else
10757 end_of_line (str);
404ff6b5
AH
10758}
10759
63e63b07 10760/* Maverick shift immediate instructions.
404ff6b5
AH
10761 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10762 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10763
10764static void
63e63b07 10765do_mav_shift (str, reg0, reg1)
404ff6b5 10766 char * str;
6c43fab6
RE
10767 enum arm_reg_type reg0;
10768 enum arm_reg_type reg1;
404ff6b5
AH
10769{
10770 int error;
10771 int imm, neg = 0;
10772
10773 skip_whitespace (str);
10774
10775 error = 0;
10776
63e63b07 10777 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10778 || skip_past_comma (&str) == FAIL
63e63b07 10779 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10780 || skip_past_comma (&str) == FAIL)
10781 {
10782 if (!inst.error)
10783 inst.error = BAD_ARGS;
10784 return;
10785 }
10786
10787 /* Calculate the immediate operand.
10788 The operand is a 7bit signed number. */
10789 skip_whitespace (str);
10790
10791 if (*str == '#')
10792 ++str;
10793
8420dfca 10794 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10795 {
10796 inst.error = _("expecting immediate, 7bit operand");
10797 return;
10798 }
10799
10800 if (*str == '-')
10801 {
10802 neg = 1;
10803 ++str;
10804 }
10805
8420dfca 10806 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10807 imm = imm * 10 + *str - '0';
10808
10809 if (imm > 64)
10810 {
10811 inst.error = _("immediate out of range");
10812 return;
10813 }
10814
10815 /* Make negative imm's into 7bit signed numbers. */
10816 if (neg)
10817 {
10818 imm = -imm;
10819 imm &= 0x0000007f;
10820 }
10821
10822 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10823 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10824 Bit 4 should be 0. */
10825 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10826
10827 inst.instruction |= imm;
404ff6b5 10828 end_of_line (str);
404ff6b5
AH
10829}
10830
10831static int
63e63b07 10832mav_parse_offset (str, negative)
404ff6b5
AH
10833 char ** str;
10834 int *negative;
10835{
10836 char * p = *str;
10837 int offset;
10838
10839 *negative = 0;
10840
10841 skip_whitespace (p);
10842
10843 if (*p == '#')
10844 ++p;
10845
10846 if (*p == '-')
10847 {
10848 *negative = 1;
10849 ++p;
10850 }
10851
8420dfca 10852 if (!ISDIGIT (*p))
404ff6b5
AH
10853 {
10854 inst.error = _("offset expected");
10855 return 0;
10856 }
10857
8420dfca 10858 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10859 offset = offset * 10 + *p - '0';
10860
10861 if (offset > 0xff)
10862 {
10863 inst.error = _("offset out of range");
10864 return 0;
10865 }
10866
10867 *str = p;
10868
10869 return *negative ? -offset : offset;
10870}
10871
63e63b07 10872/* Maverick load/store instructions.
404ff6b5
AH
10873 <insn><cond> CRd,[Rn,<offset>]{!}.
10874 <insn><cond> CRd,[Rn],<offset>. */
10875
10876static void
63e63b07 10877do_mav_ldst (str, reg0)
404ff6b5 10878 char * str;
6c43fab6 10879 enum arm_reg_type reg0;
404ff6b5
AH
10880{
10881 int offset, negative;
404ff6b5
AH
10882
10883 skip_whitespace (str);
10884
63e63b07 10885 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10886 || skip_past_comma (&str) == FAIL
404ff6b5 10887 || *str++ != '['
6c43fab6 10888 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10889 goto fail_ldst;
10890
6c43fab6 10891 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10892 {
10893 /* You are here: "<offset>]{!}". */
10894 inst.instruction |= PRE_INDEX;
10895
63e63b07 10896 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10897
10898 if (inst.error)
10899 return;
10900
10901 if (*str++ != ']')
10902 {
10903 inst.error = _("missing ]");
10904 return;
10905 }
10906
10907 if (*str == '!')
10908 {
10909 inst.instruction |= WRITE_BACK;
10910 ++str;
10911 }
10912 }
10913 else
10914 {
10915 /* You are here: "], <offset>". */
10916 if (*str++ != ']')
10917 {
10918 inst.error = _("missing ]");
10919 return;
10920 }
10921
10922 if (skip_past_comma (&str) == FAIL
63e63b07 10923 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10924 goto fail_ldst;
10925
10926 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10927 }
10928
10929 if (negative)
10930 offset = -offset;
10931 else
2d2255b5 10932 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10933
10934 inst.instruction |= offset >> 2;
404ff6b5
AH
10935 end_of_line (str);
10936 return;
10937
10938fail_ldst:
10939 if (!inst.error)
10940 inst.error = BAD_ARGS;
404ff6b5
AH
10941}
10942
b99bd4ef
NC
10943static void
10944do_t_nop (str)
10945 char * str;
10946{
10947 /* Do nothing. */
10948 end_of_line (str);
b99bd4ef
NC
10949}
10950
10951/* Handle the Format 4 instructions that do not have equivalents in other
10952 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10953 BIC and MVN. */
10954
10955static void
10956do_t_arit (str)
10957 char * str;
10958{
10959 int Rd, Rs, Rn;
10960
10961 skip_whitespace (str);
10962
10963 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10964 || skip_past_comma (&str) == FAIL
10965 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10966 {
10967 inst.error = BAD_ARGS;
10968 return;
10969 }
10970
10971 if (skip_past_comma (&str) != FAIL)
10972 {
10973 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10974 (It isn't allowed for CMP either, but that isn't handled by this
10975 function.) */
10976 if (inst.instruction == T_OPCODE_TST
10977 || inst.instruction == T_OPCODE_CMN
10978 || inst.instruction == T_OPCODE_NEG
10979 || inst.instruction == T_OPCODE_MVN)
10980 {
10981 inst.error = BAD_ARGS;
10982 return;
10983 }
10984
10985 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10986 return;
10987
10988 if (Rs != Rd)
10989 {
10990 inst.error = _("dest and source1 must be the same register");
10991 return;
10992 }
10993 Rs = Rn;
10994 }
10995
10996 if (inst.instruction == T_OPCODE_MUL
10997 && Rs == Rd)
10998 as_tsktsk (_("Rs and Rd must be different in MUL"));
10999
11000 inst.instruction |= Rd | (Rs << 3);
11001 end_of_line (str);
11002}
11003
11004static void
11005do_t_add (str)
11006 char * str;
11007{
11008 thumb_add_sub (str, 0);
11009}
11010
11011static void
11012do_t_asr (str)
11013 char * str;
11014{
11015 thumb_shift (str, THUMB_ASR);
11016}
11017
11018static void
11019do_t_branch9 (str)
11020 char * str;
11021{
11022 if (my_get_expression (&inst.reloc.exp, &str))
11023 return;
11024 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11025 inst.reloc.pc_rel = 1;
11026 end_of_line (str);
11027}
11028
11029static void
11030do_t_branch12 (str)
11031 char * str;
11032{
11033 if (my_get_expression (&inst.reloc.exp, &str))
11034 return;
11035 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11036 inst.reloc.pc_rel = 1;
11037 end_of_line (str);
11038}
11039
11040/* Find the real, Thumb encoded start of a Thumb function. */
11041
11042static symbolS *
11043find_real_start (symbolP)
11044 symbolS * symbolP;
11045{
11046 char * real_start;
11047 const char * name = S_GET_NAME (symbolP);
11048 symbolS * new_target;
11049
2d2255b5 11050 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11051#define STUB_NAME ".real_start_of"
11052
11053 if (name == NULL)
11054 abort ();
11055
11056 /* Names that start with '.' are local labels, not function entry points.
11057 The compiler may generate BL instructions to these labels because it
11058 needs to perform a branch to a far away location. */
11059 if (name[0] == '.')
11060 return symbolP;
11061
11062 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11063 sprintf (real_start, "%s%s", STUB_NAME, name);
11064
11065 new_target = symbol_find (real_start);
11066
11067 if (new_target == NULL)
11068 {
11069 as_warn ("Failed to find real start of function: %s\n", name);
11070 new_target = symbolP;
11071 }
11072
11073 free (real_start);
11074
11075 return new_target;
11076}
11077
11078static void
11079do_t_branch23 (str)
11080 char * str;
11081{
11082 if (my_get_expression (& inst.reloc.exp, & str))
11083 return;
11084
11085 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11086 inst.reloc.pc_rel = 1;
11087 end_of_line (str);
11088
11089 /* If the destination of the branch is a defined symbol which does not have
11090 the THUMB_FUNC attribute, then we must be calling a function which has
11091 the (interfacearm) attribute. We look for the Thumb entry point to that
11092 function and change the branch to refer to that function instead. */
11093 if ( inst.reloc.exp.X_op == O_symbol
11094 && inst.reloc.exp.X_add_symbol != NULL
11095 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11096 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11097 inst.reloc.exp.X_add_symbol =
11098 find_real_start (inst.reloc.exp.X_add_symbol);
11099}
11100
11101static void
11102do_t_bx (str)
11103 char * str;
11104{
11105 int reg;
11106
11107 skip_whitespace (str);
11108
11109 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11110 return;
11111
11112 /* This sets THUMB_H2 from the top bit of reg. */
11113 inst.instruction |= reg << 3;
11114
11115 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11116 should cause the alignment to be checked once it is known. This is
11117 because BX PC only works if the instruction is word aligned. */
11118
11119 end_of_line (str);
11120}
11121
11122static void
11123do_t_compare (str)
11124 char * str;
11125{
11126 thumb_mov_compare (str, THUMB_COMPARE);
11127}
11128
11129static void
11130do_t_ldmstm (str)
11131 char * str;
11132{
11133 int Rb;
11134 long range;
11135
11136 skip_whitespace (str);
11137
11138 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11139 return;
11140
11141 if (*str != '!')
f03698e6 11142 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11143 else
11144 str++;
11145
11146 if (skip_past_comma (&str) == FAIL
11147 || (range = reg_list (&str)) == FAIL)
11148 {
11149 if (! inst.error)
11150 inst.error = BAD_ARGS;
11151 return;
11152 }
11153
11154 if (inst.reloc.type != BFD_RELOC_NONE)
11155 {
11156 /* This really doesn't seem worth it. */
11157 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11158 inst.error = _("expression too complex");
b99bd4ef
NC
11159 return;
11160 }
11161
11162 if (range & ~0xff)
11163 {
11164 inst.error = _("only lo-regs valid in load/store multiple");
11165 return;
11166 }
11167
11168 inst.instruction |= (Rb << 8) | range;
11169 end_of_line (str);
11170}
11171
11172static void
11173do_t_ldr (str)
11174 char * str;
11175{
11176 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11177}
11178
11179static void
11180do_t_ldrb (str)
11181 char * str;
11182{
11183 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11184}
11185
11186static void
11187do_t_ldrh (str)
11188 char * str;
11189{
11190 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11191}
11192
11193static void
11194do_t_lds (str)
11195 char * str;
11196{
11197 int Rd, Rb, Ro;
11198
11199 skip_whitespace (str);
11200
11201 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11202 || skip_past_comma (&str) == FAIL
11203 || *str++ != '['
11204 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11205 || skip_past_comma (&str) == FAIL
11206 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11207 || *str++ != ']')
11208 {
11209 if (! inst.error)
f03698e6 11210 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11211 return;
11212 }
11213
11214 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11215 end_of_line (str);
11216}
11217
11218static void
11219do_t_lsl (str)
11220 char * str;
11221{
11222 thumb_shift (str, THUMB_LSL);
11223}
11224
11225static void
11226do_t_lsr (str)
11227 char * str;
11228{
11229 thumb_shift (str, THUMB_LSR);
11230}
11231
11232static void
11233do_t_mov (str)
11234 char * str;
11235{
11236 thumb_mov_compare (str, THUMB_MOVE);
11237}
11238
11239static void
11240do_t_push_pop (str)
11241 char * str;
11242{
11243 long range;
11244
11245 skip_whitespace (str);
11246
11247 if ((range = reg_list (&str)) == FAIL)
11248 {
11249 if (! inst.error)
11250 inst.error = BAD_ARGS;
11251 return;
11252 }
11253
11254 if (inst.reloc.type != BFD_RELOC_NONE)
11255 {
11256 /* This really doesn't seem worth it. */
11257 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11258 inst.error = _("expression too complex");
b99bd4ef
NC
11259 return;
11260 }
11261
11262 if (range & ~0xff)
11263 {
11264 if ((inst.instruction == T_OPCODE_PUSH
11265 && (range & ~0xff) == 1 << REG_LR)
11266 || (inst.instruction == T_OPCODE_POP
11267 && (range & ~0xff) == 1 << REG_PC))
11268 {
11269 inst.instruction |= THUMB_PP_PC_LR;
11270 range &= 0xff;
11271 }
11272 else
11273 {
11274 inst.error = _("invalid register list to push/pop instruction");
11275 return;
11276 }
11277 }
11278
11279 inst.instruction |= range;
11280 end_of_line (str);
11281}
11282
11283static void
11284do_t_str (str)
11285 char * str;
11286{
11287 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11288}
11289
11290static void
11291do_t_strb (str)
11292 char * str;
11293{
11294 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11295}
11296
11297static void
11298do_t_strh (str)
11299 char * str;
11300{
11301 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11302}
11303
11304static void
11305do_t_sub (str)
11306 char * str;
11307{
11308 thumb_add_sub (str, 1);
11309}
11310
11311static void
11312do_t_swi (str)
11313 char * str;
11314{
11315 skip_whitespace (str);
11316
11317 if (my_get_expression (&inst.reloc.exp, &str))
11318 return;
11319
11320 inst.reloc.type = BFD_RELOC_ARM_SWI;
11321 end_of_line (str);
b99bd4ef
NC
11322}
11323
11324static void
11325do_t_adr (str)
11326 char * str;
11327{
11328 int reg;
11329
11330 /* This is a pseudo-op of the form "adr rd, label" to be converted
11331 into a relative address of the form "add rd, pc, #label-.-4". */
11332 skip_whitespace (str);
11333
11334 /* Store Rd in temporary location inside instruction. */
11335 if ((reg = reg_required_here (&str, 4)) == FAIL
11336 || (reg > 7) /* For Thumb reg must be r0..r7. */
11337 || skip_past_comma (&str) == FAIL
11338 || my_get_expression (&inst.reloc.exp, &str))
11339 {
11340 if (!inst.error)
11341 inst.error = BAD_ARGS;
11342 return;
11343 }
11344
11345 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11346 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11347 inst.reloc.pc_rel = 1;
11348 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11349
11350 end_of_line (str);
11351}
11352
11353static void
6c43fab6
RE
11354insert_reg (r, htab)
11355 const struct reg_entry *r;
11356 struct hash_control *htab;
b99bd4ef 11357{
6c43fab6 11358 int len = strlen (r->name) + 2;
b99bd4ef
NC
11359 char * buf = (char *) xmalloc (len);
11360 char * buf2 = (char *) xmalloc (len);
11361 int i = 0;
11362
11363#ifdef REGISTER_PREFIX
11364 buf[i++] = REGISTER_PREFIX;
11365#endif
11366
6c43fab6 11367 strcpy (buf + i, r->name);
b99bd4ef
NC
11368
11369 for (i = 0; buf[i]; i++)
3882b010 11370 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11371
11372 buf2[i] = '\0';
11373
6c43fab6
RE
11374 hash_insert (htab, buf, (PTR) r);
11375 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11376}
11377
11378static void
6c43fab6
RE
11379build_reg_hsh (map)
11380 struct reg_map *map;
11381{
11382 const struct reg_entry *r;
11383
11384 if ((map->htab = hash_new ()) == NULL)
f03698e6 11385 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11386
11387 for (r = map->names; r->name != NULL; r++)
11388 insert_reg (r, map->htab);
11389}
11390
11391static void
11392insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11393 char *str;
11394 int regnum;
6c43fab6 11395 struct hash_control *htab;
b99bd4ef 11396{
0bbf2aa4
NC
11397 const char *error;
11398 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11399 const char *name = xmalloc (strlen (str) + 1);
11400
11401 strcpy ((char *) name, str);
11402
b99bd4ef
NC
11403 new->name = name;
11404 new->number = regnum;
0bbf2aa4 11405 new->builtin = FALSE;
b99bd4ef 11406
0bbf2aa4
NC
11407 error = hash_insert (htab, name, (PTR) new);
11408 if (error)
11409 {
11410 as_bad (_("failed to create an alias for %s, reason: %s"),
11411 str, error);
11412 free ((char *) name);
11413 free (new);
11414 }
b99bd4ef
NC
11415}
11416
6c43fab6
RE
11417/* Look for the .req directive. This is of the form:
11418
0bbf2aa4 11419 new_register_name .req existing_register_name
6c43fab6
RE
11420
11421 If we find one, or if it looks sufficiently like one that we want to
11422 handle any error here, return non-zero. Otherwise return zero. */
11423static int
11424create_register_alias (newname, p)
11425 char *newname;
11426 char *p;
11427{
11428 char *q;
11429 char c;
11430
11431 q = p;
11432 skip_whitespace (q);
11433
11434 c = *p;
11435 *p = '\0';
11436
11437 if (*q && !strncmp (q, ".req ", 5))
11438 {
11439 char *copy_of_str;
11440 char *r;
11441
11442#ifdef IGNORE_OPCODE_CASE
11443 newname = original_case_string;
11444#endif
11445 copy_of_str = newname;
11446
11447 q += 4;
11448 skip_whitespace (q);
11449
11450 for (r = q; *r != '\0'; r++)
11451 if (*r == ' ')
11452 break;
11453
11454 if (r != q)
11455 {
11456 enum arm_reg_type new_type, old_type;
11457 int old_regno;
11458 char d = *r;
11459
11460 *r = '\0';
11461 old_type = arm_reg_parse_any (q);
11462 *r = d;
11463
11464 new_type = arm_reg_parse_any (newname);
11465
11466 if (new_type == REG_TYPE_MAX)
11467 {
11468 if (old_type != REG_TYPE_MAX)
11469 {
11470 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11471 insert_reg_alias (newname, old_regno,
11472 all_reg_maps[old_type].htab);
11473 }
11474 else
11475 as_warn (_("register '%s' does not exist\n"), q);
11476 }
11477 else if (old_type == REG_TYPE_MAX)
11478 {
11479 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11480 copy_of_str, q);
11481 }
11482 else
11483 {
11484 /* Do not warn about redefinitions to the same alias. */
11485 if (new_type != old_type
11486 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11487 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11488 as_warn (_("ignoring redefinition of register alias '%s'"),
11489 copy_of_str);
11490
11491 }
11492 }
11493 else
11494 as_warn (_("ignoring incomplete .req pseuso op"));
11495
11496 *p = c;
11497 return 1;
11498 }
0bbf2aa4 11499
6c43fab6
RE
11500 *p = c;
11501 return 0;
11502}
cc8a6dd0 11503
b99bd4ef
NC
11504static void
11505set_constant_flonums ()
11506{
11507 int i;
11508
11509 for (i = 0; i < NUM_FLOAT_VALS; i++)
11510 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11511 abort ();
11512}
11513
90e4755a
RE
11514/* Iterate over the base tables to create the instruction patterns. */
11515static void
11516build_arm_ops_hsh ()
11517{
11518 unsigned int i;
11519 unsigned int j;
11520 static struct obstack insn_obstack;
11521
11522 obstack_begin (&insn_obstack, 4000);
11523
11524 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11525 {
6c43fab6 11526 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11527
11528 if (insn->cond_offset != 0)
11529 {
11530 /* Insn supports conditional execution. Build the varaints
11531 and insert them in the hash table. */
11532 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11533 {
11534 unsigned len = strlen (insn->template);
11535 struct asm_opcode *new;
11536 char *template;
11537
11538 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11539 /* All condition codes are two characters. */
11540 template = obstack_alloc (&insn_obstack, len + 3);
11541
11542 strncpy (template, insn->template, insn->cond_offset);
11543 strcpy (template + insn->cond_offset, conds[j].template);
11544 if (len > insn->cond_offset)
11545 strcpy (template + insn->cond_offset + 2,
11546 insn->template + insn->cond_offset);
11547 new->template = template;
11548 new->cond_offset = 0;
11549 new->variant = insn->variant;
11550 new->parms = insn->parms;
11551 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11552
11553 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11554 }
11555 }
11556 /* Finally, insert the unconditional insn in the table directly;
11557 no need to build a copy. */
11558 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11559 }
11560}
11561
0bbf2aa4 11562#if 0 /* Suppressed - for now. */
5a6c6817
NC
11563#if defined OBJ_ELF || defined OBJ_COFF
11564
11565#ifdef OBJ_ELF
11566#define arm_Note Elf_External_Note
11567#else
11568typedef struct
11569{
11570 unsigned char namesz[4]; /* Size of entry's owner string. */
11571 unsigned char descsz[4]; /* Size of the note descriptor. */
11572 unsigned char type[4]; /* Interpretation of the descriptor. */
11573 char name[1]; /* Start of the name+desc data. */
11574} arm_Note;
11575#endif
11576
11577/* The description is kept to a fix sized in order to make updating
11578 it and merging it easier. */
11579#define ARM_NOTE_DESCRIPTION_LENGTH 8
11580
11581static void
11582arm_add_note (name, description, type)
11583 const char * name;
11584 const char * description;
11585 unsigned int type;
11586{
11587 arm_Note note ATTRIBUTE_UNUSED;
11588 char * p;
11589 unsigned int name_len;
11590
11591 name_len = (strlen (name) + 1 + 3) & ~3;
11592
11593 p = frag_more (sizeof (note.namesz));
11594 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11595
11596 p = frag_more (sizeof (note.descsz));
11597 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11598
11599 p = frag_more (sizeof (note.type));
11600 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11601
11602 p = frag_more (name_len);
11603 strcpy (p, name);
11604
11605 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11606 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11607 frag_align (2, 0, 0);
11608}
11609#endif
0bbf2aa4 11610#endif
5a6c6817 11611
b99bd4ef
NC
11612void
11613md_begin ()
11614{
11615 unsigned mach;
11616 unsigned int i;
11617
11618 if ( (arm_ops_hsh = hash_new ()) == NULL
11619 || (arm_tops_hsh = hash_new ()) == NULL
11620 || (arm_cond_hsh = hash_new ()) == NULL
11621 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11622 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11623 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11624
90e4755a 11625 build_arm_ops_hsh ();
b99bd4ef
NC
11626 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11627 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11628 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11629 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11630 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11631 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11632 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11633 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11634
6c43fab6
RE
11635 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11636 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11637
11638 set_constant_flonums ();
11639
03b1477f
RE
11640 /* Set the cpu variant based on the command-line options. We prefer
11641 -mcpu= over -march= if both are set (as for GCC); and we prefer
11642 -mfpu= over any other way of setting the floating point unit.
11643 Use of legacy options with new options are faulted. */
11644 if (legacy_cpu != -1)
11645 {
11646 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11647 as_bad (_("use of old and new-style options to set CPU type"));
11648
11649 mcpu_cpu_opt = legacy_cpu;
11650 }
11651 else if (mcpu_cpu_opt == -1)
11652 mcpu_cpu_opt = march_cpu_opt;
11653
11654 if (legacy_fpu != -1)
11655 {
11656 if (mfpu_opt != -1)
11657 as_bad (_("use of old and new-style options to set FPU type"));
11658
11659 mfpu_opt = legacy_fpu;
11660 }
11661 else if (mfpu_opt == -1)
11662 {
39c2da32
RE
11663#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11664 /* Some environments specify a default FPU. If they don't, infer it
11665 from the processor. */
03b1477f
RE
11666 if (mcpu_fpu_opt != -1)
11667 mfpu_opt = mcpu_fpu_opt;
11668 else
11669 mfpu_opt = march_fpu_opt;
39c2da32
RE
11670#else
11671 mfpu_opt = FPU_DEFAULT;
11672#endif
03b1477f
RE
11673 }
11674
11675 if (mfpu_opt == -1)
11676 {
11677 if (mcpu_cpu_opt == -1)
11678 mfpu_opt = FPU_DEFAULT;
11679 else if (mcpu_cpu_opt & ARM_EXT_V5)
11680 mfpu_opt = FPU_ARCH_VFP_V2;
11681 else
11682 mfpu_opt = FPU_ARCH_FPA;
11683 }
11684
11685 if (mcpu_cpu_opt == -1)
11686 mcpu_cpu_opt = CPU_DEFAULT;
11687
11688 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11689
b99bd4ef
NC
11690#if defined OBJ_COFF || defined OBJ_ELF
11691 {
d507cf36
PB
11692 unsigned int flags = meabi_flags;
11693
11694 switch (meabi_flags)
33a392fb 11695 {
d507cf36
PB
11696 case EF_ARM_EABI_UNKNOWN:
11697 /* Set the flags in the private structure. */
11698 if (uses_apcs_26) flags |= F_APCS26;
11699 if (support_interwork) flags |= F_INTERWORK;
11700 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11701 if (pic_code) flags |= F_PIC;
11702 if ((cpu_variant & FPU_ANY) == FPU_NONE
11703 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
11704 {
11705 flags |= F_SOFT_FLOAT;
11706 }
11707 switch (mfloat_abi_opt)
11708 {
11709 case ARM_FLOAT_ABI_SOFT:
11710 case ARM_FLOAT_ABI_SOFTFP:
11711 flags |= F_SOFT_FLOAT;
11712 break;
33a392fb 11713
d507cf36
PB
11714 case ARM_FLOAT_ABI_HARD:
11715 if (flags & F_SOFT_FLOAT)
11716 as_bad (_("hard-float conflicts with specified fpu"));
11717 break;
11718 }
11719 /* Using VFP conventions (even if soft-float). */
11720 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
03b1477f 11721
fde78edd 11722#if defined OBJ_ELF
d507cf36
PB
11723 if (cpu_variant & FPU_ARCH_MAVERICK)
11724 flags |= EF_ARM_MAVERICK_FLOAT;
fde78edd 11725#endif
d507cf36
PB
11726 break;
11727
11728 case EF_ARM_EABI_VER3:
11729 /* No additional flags to set. */
11730 break;
11731
11732 default:
11733 abort ();
11734 }
b99bd4ef
NC
11735
11736 bfd_set_private_flags (stdoutput, flags);
11737
11738 /* We have run out flags in the COFF header to encode the
11739 status of ATPCS support, so instead we create a dummy,
11740 empty, debug section called .arm.atpcs. */
11741 if (atpcs)
11742 {
11743 asection * sec;
11744
11745 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11746
11747 if (sec != NULL)
11748 {
11749 bfd_set_section_flags
11750 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11751 bfd_set_section_size (stdoutput, sec, 0);
11752 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11753 }
11754 }
11755 }
11756#endif
11757
11758 /* Record the CPU type as well. */
11759 switch (cpu_variant & ARM_CPU_MASK)
11760 {
11761 case ARM_2:
11762 mach = bfd_mach_arm_2;
11763 break;
11764
11765 case ARM_3: /* Also ARM_250. */
11766 mach = bfd_mach_arm_2a;
11767 break;
11768
b89dddec
RE
11769 case ARM_6: /* Also ARM_7. */
11770 mach = bfd_mach_arm_3;
11771 break;
11772
b99bd4ef 11773 default:
5a6c6817 11774 mach = bfd_mach_arm_unknown;
b99bd4ef 11775 break;
b99bd4ef
NC
11776 }
11777
11778 /* Catch special cases. */
e16bb312
NC
11779 if (cpu_variant & ARM_CEXT_IWMMXT)
11780 mach = bfd_mach_arm_iWMMXt;
11781 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11782 mach = bfd_mach_arm_XScale;
fde78edd
NC
11783 else if (cpu_variant & ARM_CEXT_MAVERICK)
11784 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11785 else if (cpu_variant & ARM_EXT_V5E)
11786 mach = bfd_mach_arm_5TE;
11787 else if (cpu_variant & ARM_EXT_V5)
11788 {
b89dddec 11789 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11790 mach = bfd_mach_arm_5T;
11791 else
11792 mach = bfd_mach_arm_5;
11793 }
b89dddec 11794 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11795 {
b89dddec 11796 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11797 mach = bfd_mach_arm_4T;
11798 else
11799 mach = bfd_mach_arm_4;
11800 }
b89dddec 11801 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11802 mach = bfd_mach_arm_3M;
11803
5a6c6817 11804#if 0 /* Suppressed - for now. */
e16bb312 11805#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11806
11807 /* Create a .note section to fully identify this arm binary. */
11808
11809#define NOTE_ARCH_STRING "arch: "
11810
11811#if defined OBJ_COFF && ! defined NT_VERSION
11812#define NT_VERSION 1
11813#define NT_ARCH 2
11814#endif
11815
e16bb312 11816 {
e16bb312
NC
11817 segT current_seg = now_seg;
11818 subsegT current_subseg = now_subseg;
11819 asection * arm_arch;
5a6c6817
NC
11820 const char * arch_string;
11821
e16bb312
NC
11822 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11823
11824#ifdef OBJ_COFF
11825 bfd_set_section_flags (stdoutput, arm_arch,
11826 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11827 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11828#else
11829 bfd_set_section_flags (stdoutput, arm_arch,
11830 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11831#endif
11832 arm_arch->output_section = arm_arch;
11833 subseg_set (arm_arch, 0);
e16bb312 11834
5a6c6817
NC
11835 switch (mach)
11836 {
11837 default:
11838 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11839 case bfd_mach_arm_2: arch_string = "armv2"; break;
11840 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11841 case bfd_mach_arm_3: arch_string = "armv3"; break;
11842 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11843 case bfd_mach_arm_4: arch_string = "armv4"; break;
11844 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11845 case bfd_mach_arm_5: arch_string = "armv5"; break;
11846 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11847 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11848 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11849 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11850 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11851 }
11852
11853 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11854
11855 subseg_set (current_seg, current_subseg);
11856 }
11857#endif
5a6c6817
NC
11858#endif /* Suppressed code. */
11859
b99bd4ef
NC
11860 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11861}
11862
11863/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11864 for use in the a.out file, and stores them in the array pointed to by buf.
11865 This knows about the endian-ness of the target machine and does
11866 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11867 2 (short) and 4 (long) Floating numbers are put out as a series of
11868 LITTLENUMS (shorts, here at least). */
11869
11870void
11871md_number_to_chars (buf, val, n)
11872 char * buf;
11873 valueT val;
11874 int n;
11875{
11876 if (target_big_endian)
11877 number_to_chars_bigendian (buf, val, n);
11878 else
11879 number_to_chars_littleendian (buf, val, n);
11880}
11881
11882static valueT
11883md_chars_to_number (buf, n)
11884 char * buf;
11885 int n;
11886{
11887 valueT result = 0;
11888 unsigned char * where = (unsigned char *) buf;
11889
11890 if (target_big_endian)
11891 {
11892 while (n--)
11893 {
11894 result <<= 8;
11895 result |= (*where++ & 255);
11896 }
11897 }
11898 else
11899 {
11900 while (n--)
11901 {
11902 result <<= 8;
11903 result |= (where[n] & 255);
11904 }
11905 }
11906
11907 return result;
11908}
11909
11910/* Turn a string in input_line_pointer into a floating point constant
11911 of type TYPE, and store the appropriate bytes in *LITP. The number
11912 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11913 returned, or NULL on OK.
11914
11915 Note that fp constants aren't represent in the normal way on the ARM.
11916 In big endian mode, things are as expected. However, in little endian
11917 mode fp constants are big-endian word-wise, and little-endian byte-wise
11918 within the words. For example, (double) 1.1 in big endian mode is
11919 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11920 the byte sequence 99 99 f1 3f 9a 99 99 99.
11921
11922 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11923
11924char *
11925md_atof (type, litP, sizeP)
11926 char type;
11927 char * litP;
11928 int * sizeP;
11929{
11930 int prec;
11931 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11932 char *t;
11933 int i;
11934
11935 switch (type)
11936 {
11937 case 'f':
11938 case 'F':
11939 case 's':
11940 case 'S':
11941 prec = 2;
11942 break;
11943
11944 case 'd':
11945 case 'D':
11946 case 'r':
11947 case 'R':
11948 prec = 4;
11949 break;
11950
11951 case 'x':
11952 case 'X':
11953 prec = 6;
11954 break;
11955
11956 case 'p':
11957 case 'P':
11958 prec = 6;
11959 break;
11960
11961 default:
11962 *sizeP = 0;
f03698e6 11963 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11964 }
11965
11966 t = atof_ieee (input_line_pointer, type, words);
11967 if (t)
11968 input_line_pointer = t;
11969 *sizeP = prec * 2;
11970
11971 if (target_big_endian)
11972 {
11973 for (i = 0; i < prec; i++)
11974 {
11975 md_number_to_chars (litP, (valueT) words[i], 2);
11976 litP += 2;
11977 }
11978 }
11979 else
11980 {
bfae80f2
RE
11981 if (cpu_variant & FPU_ARCH_VFP)
11982 for (i = prec - 1; i >= 0; i--)
11983 {
11984 md_number_to_chars (litP, (valueT) words[i], 2);
11985 litP += 2;
11986 }
11987 else
11988 /* For a 4 byte float the order of elements in `words' is 1 0.
11989 For an 8 byte float the order is 1 0 3 2. */
11990 for (i = 0; i < prec; i += 2)
11991 {
11992 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11993 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11994 litP += 4;
11995 }
b99bd4ef
NC
11996 }
11997
11998 return 0;
11999}
12000
12001/* The knowledge of the PC's pipeline offset is built into the insns
12002 themselves. */
12003
12004long
12005md_pcrel_from (fixP)
12006 fixS * fixP;
12007{
12008 if (fixP->fx_addsy
12009 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
12010 && fixP->fx_subsy == NULL)
12011 return 0;
12012
12013 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12014 {
12015 /* PC relative addressing on the Thumb is slightly odd
12016 as the bottom two bits of the PC are forced to zero
12017 for the calculation. */
12018 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12019 }
12020
12021#ifdef TE_WINCE
2d2255b5
KH
12022 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12023 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
12024 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12025#else
12026 return fixP->fx_where + fixP->fx_frag->fr_address;
12027#endif
12028}
12029
12030/* Round up a section size to the appropriate boundary. */
12031
12032valueT
12033md_section_align (segment, size)
12034 segT segment ATTRIBUTE_UNUSED;
12035 valueT size;
12036{
12037#ifdef OBJ_ELF
12038 return size;
12039#else
12040 /* Round all sects to multiple of 4. */
12041 return (size + 3) & ~3;
12042#endif
12043}
12044
12045/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12046 Otherwise we have no need to default values of symbols. */
12047
12048symbolS *
12049md_undefined_symbol (name)
12050 char * name ATTRIBUTE_UNUSED;
12051{
12052#ifdef OBJ_ELF
12053 if (name[0] == '_' && name[1] == 'G'
12054 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12055 {
12056 if (!GOT_symbol)
12057 {
12058 if (symbol_find (name))
12059 as_bad ("GOT already in the symbol table");
12060
12061 GOT_symbol = symbol_new (name, undefined_section,
12062 (valueT) 0, & zero_address_frag);
12063 }
12064
12065 return GOT_symbol;
12066 }
12067#endif
12068
12069 return 0;
12070}
12071
12072/* arm_reg_parse () := if it looks like a register, return its token and
12073 advance the pointer. */
12074
12075static int
6c43fab6 12076arm_reg_parse (ccp, htab)
b99bd4ef 12077 register char ** ccp;
6c43fab6 12078 struct hash_control *htab;
b99bd4ef
NC
12079{
12080 char * start = * ccp;
12081 char c;
12082 char * p;
12083 struct reg_entry * reg;
12084
12085#ifdef REGISTER_PREFIX
12086 if (*start != REGISTER_PREFIX)
12087 return FAIL;
12088 p = start + 1;
12089#else
12090 p = start;
12091#ifdef OPTIONAL_REGISTER_PREFIX
12092 if (*p == OPTIONAL_REGISTER_PREFIX)
12093 p++, start++;
12094#endif
12095#endif
3882b010 12096 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12097 return FAIL;
12098
12099 c = *p++;
3882b010 12100 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12101 c = *p++;
12102
12103 *--p = 0;
6c43fab6 12104 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12105 *p = c;
12106
12107 if (reg)
12108 {
12109 *ccp = p;
12110 return reg->number;
12111 }
12112
12113 return FAIL;
12114}
12115
6c43fab6
RE
12116/* Search for the following register name in each of the possible reg name
12117 tables. Return the classification if found, or REG_TYPE_MAX if not
12118 present. */
12119static enum arm_reg_type
12120arm_reg_parse_any (cp)
12121 char *cp;
12122{
12123 int i;
12124
12125 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12126 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12127 return (enum arm_reg_type) i;
12128
12129 return REG_TYPE_MAX;
12130}
12131
94f592af
NC
12132void
12133md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12134 fixS * fixP;
94f592af 12135 valueT * valP;
b99bd4ef
NC
12136 segT seg;
12137{
94f592af 12138 offsetT value = * valP;
b99bd4ef
NC
12139 offsetT newval;
12140 unsigned int newimm;
12141 unsigned long temp;
12142 int sign;
12143 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12144 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12145
12146 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12147
12148 /* Note whether this will delete the relocation. */
12149#if 0
12150 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12151 doesn't work fully.) */
12152 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12153 && !fixP->fx_pcrel)
12154#else
12155 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12156#endif
12157 fixP->fx_done = 1;
12158
12159 /* If this symbol is in a different section then we need to leave it for
12160 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12161 so we have to undo it's effects here. */
12162 if (fixP->fx_pcrel)
12163 {
12164 if (fixP->fx_addsy != NULL
12165 && S_IS_DEFINED (fixP->fx_addsy)
12166 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12167 {
12168 if (target_oabi
12169 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12170 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12171 ))
12172 value = 0;
12173 else
12174 value += md_pcrel_from (fixP);
12175 }
12176 }
12177
12178 /* Remember value for emit_reloc. */
12179 fixP->fx_addnumber = value;
12180
12181 switch (fixP->fx_r_type)
12182 {
12183 case BFD_RELOC_ARM_IMMEDIATE:
12184 newimm = validate_immediate (value);
12185 temp = md_chars_to_number (buf, INSN_SIZE);
12186
12187 /* If the instruction will fail, see if we can fix things up by
12188 changing the opcode. */
12189 if (newimm == (unsigned int) FAIL
12190 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12191 {
12192 as_bad_where (fixP->fx_file, fixP->fx_line,
12193 _("invalid constant (%lx) after fixup"),
12194 (unsigned long) value);
12195 break;
12196 }
12197
12198 newimm |= (temp & 0xfffff000);
12199 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
6189168b 12200 fixP->fx_done = 1;
b99bd4ef
NC
12201 break;
12202
12203 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12204 {
12205 unsigned int highpart = 0;
12206 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12207
b99bd4ef
NC
12208 newimm = validate_immediate (value);
12209 temp = md_chars_to_number (buf, INSN_SIZE);
12210
12211 /* If the instruction will fail, see if we can fix things up by
12212 changing the opcode. */
12213 if (newimm == (unsigned int) FAIL
12214 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12215 {
12216 /* No ? OK - try using two ADD instructions to generate
12217 the value. */
12218 newimm = validate_immediate_twopart (value, & highpart);
12219
12220 /* Yes - then make sure that the second instruction is
12221 also an add. */
12222 if (newimm != (unsigned int) FAIL)
12223 newinsn = temp;
12224 /* Still No ? Try using a negated value. */
12225 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12226 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12227 /* Otherwise - give up. */
12228 else
12229 {
12230 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12231 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12232 (long) value);
b99bd4ef
NC
12233 break;
12234 }
12235
12236 /* Replace the first operand in the 2nd instruction (which
12237 is the PC) with the destination register. We have
12238 already added in the PC in the first instruction and we
12239 do not want to do it again. */
12240 newinsn &= ~ 0xf0000;
12241 newinsn |= ((newinsn & 0x0f000) << 4);
12242 }
12243
12244 newimm |= (temp & 0xfffff000);
12245 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12246
12247 highpart |= (newinsn & 0xfffff000);
12248 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12249 }
12250 break;
12251
12252 case BFD_RELOC_ARM_OFFSET_IMM:
12253 sign = value >= 0;
12254
12255 if (value < 0)
12256 value = - value;
12257
12258 if (validate_offset_imm (value, 0) == FAIL)
12259 {
12260 as_bad_where (fixP->fx_file, fixP->fx_line,
12261 _("bad immediate value for offset (%ld)"),
12262 (long) value);
12263 break;
12264 }
12265
12266 newval = md_chars_to_number (buf, INSN_SIZE);
12267 newval &= 0xff7ff000;
12268 newval |= value | (sign ? INDEX_UP : 0);
12269 md_number_to_chars (buf, newval, INSN_SIZE);
12270 break;
12271
12272 case BFD_RELOC_ARM_OFFSET_IMM8:
12273 case BFD_RELOC_ARM_HWLITERAL:
12274 sign = value >= 0;
12275
12276 if (value < 0)
12277 value = - value;
12278
12279 if (validate_offset_imm (value, 1) == FAIL)
12280 {
12281 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12282 as_bad_where (fixP->fx_file, fixP->fx_line,
12283 _("invalid literal constant: pool needs to be closer"));
12284 else
12285 as_bad (_("bad immediate value for half-word offset (%ld)"),
12286 (long) value);
12287 break;
12288 }
12289
12290 newval = md_chars_to_number (buf, INSN_SIZE);
12291 newval &= 0xff7ff0f0;
12292 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12293 md_number_to_chars (buf, newval, INSN_SIZE);
12294 break;
12295
12296 case BFD_RELOC_ARM_LITERAL:
12297 sign = value >= 0;
12298
12299 if (value < 0)
12300 value = - value;
12301
12302 if (validate_offset_imm (value, 0) == FAIL)
12303 {
12304 as_bad_where (fixP->fx_file, fixP->fx_line,
12305 _("invalid literal constant: pool needs to be closer"));
12306 break;
12307 }
12308
12309 newval = md_chars_to_number (buf, INSN_SIZE);
12310 newval &= 0xff7ff000;
12311 newval |= value | (sign ? INDEX_UP : 0);
12312 md_number_to_chars (buf, newval, INSN_SIZE);
12313 break;
12314
12315 case BFD_RELOC_ARM_SHIFT_IMM:
12316 newval = md_chars_to_number (buf, INSN_SIZE);
12317 if (((unsigned long) value) > 32
12318 || (value == 32
12319 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12320 {
12321 as_bad_where (fixP->fx_file, fixP->fx_line,
12322 _("shift expression is too large"));
12323 break;
12324 }
12325
12326 if (value == 0)
12327 /* Shifts of zero must be done as lsl. */
12328 newval &= ~0x60;
12329 else if (value == 32)
12330 value = 0;
12331 newval &= 0xfffff07f;
12332 newval |= (value & 0x1f) << 7;
12333 md_number_to_chars (buf, newval, INSN_SIZE);
12334 break;
12335
12336 case BFD_RELOC_ARM_SWI:
12337 if (arm_data->thumb_mode)
12338 {
12339 if (((unsigned long) value) > 0xff)
12340 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12341 _("invalid swi expression"));
b99bd4ef
NC
12342 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12343 newval |= value;
12344 md_number_to_chars (buf, newval, THUMB_SIZE);
12345 }
12346 else
12347 {
12348 if (((unsigned long) value) > 0x00ffffff)
12349 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12350 _("invalid swi expression"));
b99bd4ef
NC
12351 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12352 newval |= value;
12353 md_number_to_chars (buf, newval, INSN_SIZE);
12354 }
12355 break;
12356
12357 case BFD_RELOC_ARM_MULTI:
12358 if (((unsigned long) value) > 0xffff)
12359 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12360 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12361 newval = value | md_chars_to_number (buf, INSN_SIZE);
12362 md_number_to_chars (buf, newval, INSN_SIZE);
12363 break;
12364
12365 case BFD_RELOC_ARM_PCREL_BRANCH:
12366 newval = md_chars_to_number (buf, INSN_SIZE);
12367
12368 /* Sign-extend a 24-bit number. */
12369#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12370
12371#ifdef OBJ_ELF
12372 if (! target_oabi)
12373 value = fixP->fx_offset;
12374#endif
12375
12376 /* We are going to store value (shifted right by two) in the
12377 instruction, in a 24 bit, signed field. Thus we need to check
12378 that none of the top 8 bits of the shifted value (top 7 bits of
12379 the unshifted, unsigned value) are set, or that they are all set. */
12380 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12381 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12382 {
12383#ifdef OBJ_ELF
12384 /* Normally we would be stuck at this point, since we cannot store
12385 the absolute address that is the destination of the branch in the
12386 24 bits of the branch instruction. If however, we happen to know
12387 that the destination of the branch is in the same section as the
2d2255b5 12388 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12389 ourselves and not have to bother the linker with it.
12390
12391 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12392 because I have not worked out how to do this for OBJ_COFF or
12393 target_oabi. */
12394 if (! target_oabi
12395 && fixP->fx_addsy != NULL
12396 && S_IS_DEFINED (fixP->fx_addsy)
12397 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12398 {
12399 /* Get pc relative value to go into the branch. */
94f592af 12400 value = * valP;
b99bd4ef
NC
12401
12402 /* Permit a backward branch provided that enough bits
12403 are set. Allow a forwards branch, provided that
12404 enough bits are clear. */
12405 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12406 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12407 fixP->fx_done = 1;
12408 }
12409
12410 if (! fixP->fx_done)
12411#endif
12412 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12413 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12414 }
12415
12416 value >>= 2;
12417 value += SEXT24 (newval);
12418
12419 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12420 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12421 as_bad_where (fixP->fx_file, fixP->fx_line,
12422 _("out of range branch"));
12423
12424 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12425 md_number_to_chars (buf, newval, INSN_SIZE);
12426 break;
12427
12428 case BFD_RELOC_ARM_PCREL_BLX:
12429 {
12430 offsetT hbit;
12431 newval = md_chars_to_number (buf, INSN_SIZE);
12432
12433#ifdef OBJ_ELF
12434 if (! target_oabi)
12435 value = fixP->fx_offset;
12436#endif
12437 hbit = (value >> 1) & 1;
12438 value = (value >> 2) & 0x00ffffff;
12439 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12440 newval = value | (newval & 0xfe000000) | (hbit << 24);
12441 md_number_to_chars (buf, newval, INSN_SIZE);
12442 }
12443 break;
12444
12445 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12446 newval = md_chars_to_number (buf, THUMB_SIZE);
12447 {
12448 addressT diff = (newval & 0xff) << 1;
12449 if (diff & 0x100)
12450 diff |= ~0xff;
12451
12452 value += diff;
12453 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12454 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12455 _("branch out of range"));
b99bd4ef
NC
12456 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12457 }
12458 md_number_to_chars (buf, newval, THUMB_SIZE);
12459 break;
12460
12461 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12462 newval = md_chars_to_number (buf, THUMB_SIZE);
12463 {
12464 addressT diff = (newval & 0x7ff) << 1;
12465 if (diff & 0x800)
12466 diff |= ~0x7ff;
12467
12468 value += diff;
12469 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12470 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12471 _("branch out of range"));
b99bd4ef
NC
12472 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12473 }
12474 md_number_to_chars (buf, newval, THUMB_SIZE);
12475 break;
12476
12477 case BFD_RELOC_THUMB_PCREL_BLX:
12478 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12479 {
12480 offsetT newval2;
12481 addressT diff;
12482
12483 newval = md_chars_to_number (buf, THUMB_SIZE);
12484 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12485 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12486 if (diff & 0x400000)
12487 diff |= ~0x3fffff;
12488#ifdef OBJ_ELF
12489 value = fixP->fx_offset;
12490#endif
12491 value += diff;
c62e1cc3 12492
b99bd4ef
NC
12493 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12494 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12495 _("branch with link out of range"));
b99bd4ef
NC
12496
12497 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12498 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12499 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12500 /* For a BLX instruction, make sure that the relocation is rounded up
12501 to a word boundary. This follows the semantics of the instruction
12502 which specifies that bit 1 of the target address will come from bit
12503 1 of the base address. */
12504 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12505 md_number_to_chars (buf, newval, THUMB_SIZE);
12506 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12507 }
12508 break;
12509
12510 case BFD_RELOC_8:
12511 if (fixP->fx_done || fixP->fx_pcrel)
12512 md_number_to_chars (buf, value, 1);
12513#ifdef OBJ_ELF
12514 else if (!target_oabi)
12515 {
12516 value = fixP->fx_offset;
12517 md_number_to_chars (buf, value, 1);
12518 }
12519#endif
12520 break;
12521
12522 case BFD_RELOC_16:
12523 if (fixP->fx_done || fixP->fx_pcrel)
12524 md_number_to_chars (buf, value, 2);
12525#ifdef OBJ_ELF
12526 else if (!target_oabi)
12527 {
12528 value = fixP->fx_offset;
12529 md_number_to_chars (buf, value, 2);
12530 }
12531#endif
12532 break;
12533
12534#ifdef OBJ_ELF
12535 case BFD_RELOC_ARM_GOT32:
12536 case BFD_RELOC_ARM_GOTOFF:
12537 md_number_to_chars (buf, 0, 4);
12538 break;
12539#endif
12540
12541 case BFD_RELOC_RVA:
12542 case BFD_RELOC_32:
12543 if (fixP->fx_done || fixP->fx_pcrel)
12544 md_number_to_chars (buf, value, 4);
12545#ifdef OBJ_ELF
12546 else if (!target_oabi)
12547 {
12548 value = fixP->fx_offset;
12549 md_number_to_chars (buf, value, 4);
12550 }
12551#endif
12552 break;
12553
12554#ifdef OBJ_ELF
12555 case BFD_RELOC_ARM_PLT32:
12556 /* It appears the instruction is fully prepared at this point. */
12557 break;
12558#endif
12559
b99bd4ef
NC
12560 case BFD_RELOC_ARM_CP_OFF_IMM:
12561 sign = value >= 0;
12562 if (value < -1023 || value > 1023 || (value & 3))
12563 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12564 _("illegal value for co-processor offset"));
b99bd4ef
NC
12565 if (value < 0)
12566 value = -value;
12567 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12568 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12569 md_number_to_chars (buf, newval, INSN_SIZE);
12570 break;
12571
e16bb312
NC
12572 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12573 sign = value >= 0;
12574 if (value < -255 || value > 255)
12575 as_bad_where (fixP->fx_file, fixP->fx_line,
12576 _("Illegal value for co-processor offset"));
12577 if (value < 0)
12578 value = -value;
12579 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12580 newval |= value | (sign ? INDEX_UP : 0);
12581 md_number_to_chars (buf, newval , INSN_SIZE);
12582 break;
12583
b99bd4ef
NC
12584 case BFD_RELOC_ARM_THUMB_OFFSET:
12585 newval = md_chars_to_number (buf, THUMB_SIZE);
12586 /* Exactly what ranges, and where the offset is inserted depends
12587 on the type of instruction, we can establish this from the
12588 top 4 bits. */
12589 switch (newval >> 12)
12590 {
12591 case 4: /* PC load. */
12592 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12593 forced to zero for these loads, so we will need to round
12594 up the offset if the instruction address is not word
12595 aligned (since the final address produced must be, and
12596 we can only describe word-aligned immediate offsets). */
12597
12598 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12599 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12600 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12601 (unsigned int) (fixP->fx_frag->fr_address
12602 + fixP->fx_where + value));
12603
12604 if ((value + 2) & ~0x3fe)
12605 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12606 _("invalid offset, value too big (0x%08lX)"),
12607 (long) value);
b99bd4ef
NC
12608
12609 /* Round up, since pc will be rounded down. */
12610 newval |= (value + 2) >> 2;
12611 break;
12612
12613 case 9: /* SP load/store. */
12614 if (value & ~0x3fc)
12615 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12616 _("invalid offset, value too big (0x%08lX)"),
12617 (long) value);
b99bd4ef
NC
12618 newval |= value >> 2;
12619 break;
12620
12621 case 6: /* Word load/store. */
12622 if (value & ~0x7c)
12623 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12624 _("invalid offset, value too big (0x%08lX)"),
12625 (long) value);
b99bd4ef
NC
12626 newval |= value << 4; /* 6 - 2. */
12627 break;
12628
12629 case 7: /* Byte load/store. */
12630 if (value & ~0x1f)
12631 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12632 _("invalid offset, value too big (0x%08lX)"),
12633 (long) value);
b99bd4ef
NC
12634 newval |= value << 6;
12635 break;
12636
12637 case 8: /* Halfword load/store. */
12638 if (value & ~0x3e)
12639 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12640 _("invalid offset, value too big (0x%08lX)"),
12641 (long) value);
b99bd4ef
NC
12642 newval |= value << 5; /* 6 - 1. */
12643 break;
12644
12645 default:
12646 as_bad_where (fixP->fx_file, fixP->fx_line,
12647 "Unable to process relocation for thumb opcode: %lx",
12648 (unsigned long) newval);
12649 break;
12650 }
12651 md_number_to_chars (buf, newval, THUMB_SIZE);
12652 break;
12653
12654 case BFD_RELOC_ARM_THUMB_ADD:
12655 /* This is a complicated relocation, since we use it for all of
12656 the following immediate relocations:
12657
12658 3bit ADD/SUB
12659 8bit ADD/SUB
12660 9bit ADD/SUB SP word-aligned
12661 10bit ADD PC/SP word-aligned
12662
12663 The type of instruction being processed is encoded in the
12664 instruction field:
12665
12666 0x8000 SUB
12667 0x00F0 Rd
12668 0x000F Rs
12669 */
12670 newval = md_chars_to_number (buf, THUMB_SIZE);
12671 {
12672 int rd = (newval >> 4) & 0xf;
12673 int rs = newval & 0xf;
12674 int subtract = newval & 0x8000;
12675
12676 if (rd == REG_SP)
12677 {
12678 if (value & ~0x1fc)
12679 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12680 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12681 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12682 newval |= value >> 2;
12683 }
12684 else if (rs == REG_PC || rs == REG_SP)
12685 {
12686 if (subtract ||
12687 value & ~0x3fc)
12688 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12689 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12690 (unsigned long) value);
12691 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12692 newval |= rd << 8;
12693 newval |= value >> 2;
12694 }
12695 else if (rs == rd)
12696 {
12697 if (value & ~0xff)
12698 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12699 _("invalid 8bit immediate"));
b99bd4ef
NC
12700 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12701 newval |= (rd << 8) | value;
12702 }
12703 else
12704 {
12705 if (value & ~0x7)
12706 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12707 _("invalid 3bit immediate"));
b99bd4ef
NC
12708 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12709 newval |= rd | (rs << 3) | (value << 6);
12710 }
12711 }
12712 md_number_to_chars (buf, newval, THUMB_SIZE);
12713 break;
12714
12715 case BFD_RELOC_ARM_THUMB_IMM:
12716 newval = md_chars_to_number (buf, THUMB_SIZE);
12717 switch (newval >> 11)
12718 {
12719 case 0x04: /* 8bit immediate MOV. */
12720 case 0x05: /* 8bit immediate CMP. */
12721 if (value < 0 || value > 255)
12722 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12723 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12724 (long) value);
12725 newval |= value;
12726 break;
12727
12728 default:
12729 abort ();
12730 }
12731 md_number_to_chars (buf, newval, THUMB_SIZE);
12732 break;
12733
12734 case BFD_RELOC_ARM_THUMB_SHIFT:
12735 /* 5bit shift value (0..31). */
12736 if (value < 0 || value > 31)
12737 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12738 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12739 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12740 newval |= value << 6;
12741 md_number_to_chars (buf, newval, THUMB_SIZE);
12742 break;
12743
12744 case BFD_RELOC_VTABLE_INHERIT:
12745 case BFD_RELOC_VTABLE_ENTRY:
12746 fixP->fx_done = 0;
94f592af 12747 return;
b99bd4ef
NC
12748
12749 case BFD_RELOC_NONE:
12750 default:
12751 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12752 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12753 }
b99bd4ef
NC
12754}
12755
12756/* Translate internal representation of relocation info to BFD target
12757 format. */
12758
12759arelent *
12760tc_gen_reloc (section, fixp)
12761 asection * section ATTRIBUTE_UNUSED;
12762 fixS * fixp;
12763{
12764 arelent * reloc;
12765 bfd_reloc_code_real_type code;
12766
12767 reloc = (arelent *) xmalloc (sizeof (arelent));
12768
12769 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12770 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12771 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12772
12773 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12774#ifndef OBJ_ELF
12775 if (fixp->fx_pcrel == 0)
12776 reloc->addend = fixp->fx_offset;
12777 else
12778 reloc->addend = fixp->fx_offset = reloc->address;
12779#else /* OBJ_ELF */
12780 reloc->addend = fixp->fx_offset;
12781#endif
12782
12783 switch (fixp->fx_r_type)
12784 {
12785 case BFD_RELOC_8:
12786 if (fixp->fx_pcrel)
12787 {
12788 code = BFD_RELOC_8_PCREL;
12789 break;
12790 }
12791
12792 case BFD_RELOC_16:
12793 if (fixp->fx_pcrel)
12794 {
12795 code = BFD_RELOC_16_PCREL;
12796 break;
12797 }
12798
12799 case BFD_RELOC_32:
12800 if (fixp->fx_pcrel)
12801 {
12802 code = BFD_RELOC_32_PCREL;
12803 break;
12804 }
12805
12806 case BFD_RELOC_ARM_PCREL_BRANCH:
12807 case BFD_RELOC_ARM_PCREL_BLX:
12808 case BFD_RELOC_RVA:
12809 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12810 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12811 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12812 case BFD_RELOC_THUMB_PCREL_BLX:
12813 case BFD_RELOC_VTABLE_ENTRY:
12814 case BFD_RELOC_VTABLE_INHERIT:
12815 code = fixp->fx_r_type;
12816 break;
12817
12818 case BFD_RELOC_ARM_LITERAL:
12819 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12820 /* If this is called then the a literal has
12821 been referenced across a section boundary. */
b99bd4ef 12822 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12823 _("literal referenced across section boundary"));
b99bd4ef
NC
12824 return NULL;
12825
12826#ifdef OBJ_ELF
12827 case BFD_RELOC_ARM_GOT32:
12828 case BFD_RELOC_ARM_GOTOFF:
12829 case BFD_RELOC_ARM_PLT32:
12830 code = fixp->fx_r_type;
12831 break;
12832#endif
12833
12834 case BFD_RELOC_ARM_IMMEDIATE:
12835 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12836 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12837 return NULL;
12838
12839 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12840 as_bad_where (fixp->fx_file, fixp->fx_line,
12841 _("ADRL used for a symbol not defined in the same file"));
12842 return NULL;
12843
12844 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12845 if (fixp->fx_addsy != NULL
12846 && !S_IS_DEFINED (fixp->fx_addsy)
12847 && S_IS_LOCAL (fixp->fx_addsy))
12848 {
12849 as_bad_where (fixp->fx_file, fixp->fx_line,
12850 _("undefined local label `%s'"),
12851 S_GET_NAME (fixp->fx_addsy));
12852 return NULL;
12853 }
12854
b99bd4ef 12855 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12856 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12857 return NULL;
12858
12859 default:
12860 {
12861 char * type;
12862
12863 switch (fixp->fx_r_type)
12864 {
b99bd4ef
NC
12865 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12866 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12867 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12868 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12869 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12870 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12871 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12872 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12873 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12874 default: type = _("<unknown>"); break;
12875 }
12876 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12877 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12878 type);
12879 return NULL;
12880 }
12881 }
12882
12883#ifdef OBJ_ELF
8df7094c 12884 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12885 && GOT_symbol
12886 && fixp->fx_addsy == GOT_symbol)
12887 {
12888 code = BFD_RELOC_ARM_GOTPC;
12889 reloc->addend = fixp->fx_offset = reloc->address;
12890 }
12891#endif
12892
12893 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12894
12895 if (reloc->howto == NULL)
12896 {
12897 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12898 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12899 bfd_get_reloc_code_name (code));
12900 return NULL;
12901 }
12902
12903 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12904 vtable entry to be used in the relocation's section offset. */
12905 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12906 reloc->address = fixp->fx_offset;
12907
12908 return reloc;
12909}
12910
12911int
12912md_estimate_size_before_relax (fragP, segtype)
12913 fragS * fragP ATTRIBUTE_UNUSED;
12914 segT segtype ATTRIBUTE_UNUSED;
12915{
12916 as_fatal (_("md_estimate_size_before_relax\n"));
12917 return 1;
12918}
12919
12920static void
f03698e6
RE
12921output_inst (str)
12922 const char *str;
b99bd4ef
NC
12923{
12924 char * to = NULL;
12925
12926 if (inst.error)
12927 {
f03698e6 12928 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12929 return;
12930 }
12931
12932 to = frag_more (inst.size);
12933
12934 if (thumb_mode && (inst.size > THUMB_SIZE))
12935 {
12936 assert (inst.size == (2 * THUMB_SIZE));
12937 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12938 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12939 }
12940 else if (inst.size > INSN_SIZE)
12941 {
12942 assert (inst.size == (2 * INSN_SIZE));
12943 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12944 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12945 }
12946 else
12947 md_number_to_chars (to, inst.instruction, inst.size);
12948
12949 if (inst.reloc.type != BFD_RELOC_NONE)
12950 fix_new_arm (frag_now, to - frag_now->fr_literal,
12951 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12952 inst.reloc.type);
12953
12954#ifdef OBJ_ELF
12955 dwarf2_emit_insn (inst.size);
12956#endif
12957}
12958
12959void
12960md_assemble (str)
12961 char * str;
12962{
6c43fab6
RE
12963 char c;
12964 char *p;
12965 char *start;
b99bd4ef
NC
12966
12967 /* Align the instruction.
12968 This may not be the right thing to do but ... */
12969#if 0
12970 arm_align (2, 0);
12971#endif
b99bd4ef
NC
12972
12973 /* Align the previous label if needed. */
12974 if (last_label_seen != NULL)
12975 {
12976 symbol_set_frag (last_label_seen, frag_now);
12977 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12978 S_SET_SEGMENT (last_label_seen, now_seg);
12979 }
12980
12981 memset (&inst, '\0', sizeof (inst));
12982 inst.reloc.type = BFD_RELOC_NONE;
12983
12984 skip_whitespace (str);
12985
12986 /* Scan up to the end of the op-code, which must end in white space or
12987 end of string. */
12988 for (start = p = str; *p != '\0'; p++)
12989 if (*p == ' ')
12990 break;
12991
12992 if (p == str)
12993 {
f03698e6 12994 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12995 return;
12996 }
12997
12998 if (thumb_mode)
12999 {
05d2d07e 13000 const struct thumb_opcode * opcode;
b99bd4ef
NC
13001
13002 c = *p;
13003 *p = '\0';
05d2d07e 13004 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
13005 *p = c;
13006
13007 if (opcode)
13008 {
13009 /* Check that this instruction is supported for this CPU. */
90e4755a 13010 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 13011 {
f03698e6 13012 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13013 return;
13014 }
13015
6057a28f 13016 mapping_state (MAP_THUMB);
b99bd4ef
NC
13017 inst.instruction = opcode->value;
13018 inst.size = opcode->size;
13019 (*opcode->parms) (p);
f03698e6 13020 output_inst (str);
b99bd4ef
NC
13021 return;
13022 }
13023 }
13024 else
13025 {
05d2d07e 13026 const struct asm_opcode * opcode;
b99bd4ef 13027
90e4755a
RE
13028 c = *p;
13029 *p = '\0';
6c43fab6 13030 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 13031 *p = c;
b99bd4ef 13032
90e4755a 13033 if (opcode)
b99bd4ef 13034 {
90e4755a
RE
13035 /* Check that this instruction is supported for this CPU. */
13036 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 13037 {
f03698e6 13038 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13039 return;
13040 }
13041
6057a28f 13042 mapping_state (MAP_ARM);
90e4755a
RE
13043 inst.instruction = opcode->value;
13044 inst.size = INSN_SIZE;
f2b7cb0a 13045 (*opcode->parms) (p);
f03698e6 13046 output_inst (str);
90e4755a 13047 return;
b99bd4ef
NC
13048 }
13049 }
13050
13051 /* It wasn't an instruction, but it might be a register alias of the form
13052 alias .req reg. */
6c43fab6
RE
13053 if (create_register_alias (str, p))
13054 return;
b99bd4ef 13055
b99bd4ef
NC
13056 as_bad (_("bad instruction `%s'"), start);
13057}
13058
13059/* md_parse_option
13060 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 13061 See if it's a processor-specific option.
03b1477f
RE
13062
13063 This routine is somewhat complicated by the need for backwards
13064 compatibility (since older releases of gcc can't be changed).
13065 The new options try to make the interface as compatible as
13066 possible with GCC.
13067
13068 New options (supported) are:
13069
13070 -mcpu=<cpu name> Assemble for selected processor
13071 -march=<architecture name> Assemble for selected architecture
13072 -mfpu=<fpu architecture> Assemble for selected FPU.
13073 -EB/-mbig-endian Big-endian
13074 -EL/-mlittle-endian Little-endian
13075 -k Generate PIC code
13076 -mthumb Start in Thumb mode
13077 -mthumb-interwork Code supports ARM/Thumb interworking
13078
3d0c9500 13079 For now we will also provide support for:
03b1477f
RE
13080
13081 -mapcs-32 32-bit Program counter
13082 -mapcs-26 26-bit Program counter
13083 -macps-float Floats passed in FP registers
13084 -mapcs-reentrant Reentrant code
13085 -matpcs
13086 (sometime these will probably be replaced with -mapcs=<list of options>
13087 and -matpcs=<list of options>)
13088
13089 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13090 Cpu variants, the arm part is optional:
13091 -m[arm]1 Currently not supported.
13092 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13093 -m[arm]3 Arm 3 processor
13094 -m[arm]6[xx], Arm 6 processors
13095 -m[arm]7[xx][t][[d]m] Arm 7 processors
13096 -m[arm]8[10] Arm 8 processors
13097 -m[arm]9[20][tdmi] Arm 9 processors
13098 -mstrongarm[110[0]] StrongARM processors
13099 -mxscale XScale processors
13100 -m[arm]v[2345[t[e]]] Arm architectures
13101 -mall All (except the ARM1)
13102 FP variants:
13103 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13104 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13105 -mvfpxd VFP Single precision
13106 -mvfp All VFP
b99bd4ef 13107 -mno-fpu Disable all floating point instructions
b99bd4ef 13108
03b1477f
RE
13109 The following CPU names are recognized:
13110 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13111 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13112 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13113 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13114 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13115 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13116 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13117
13118 */
13119
5a38dc70 13120const char * md_shortopts = "m:k";
03b1477f 13121
b99bd4ef
NC
13122#ifdef ARM_BI_ENDIAN
13123#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13124#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13125#else
21f0f23a
RE
13126#if TARGET_BYTES_BIG_ENDIAN
13127#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13128#else
13129#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13130#endif
ce058b6c 13131#endif
03b1477f
RE
13132
13133struct option md_longopts[] =
13134{
13135#ifdef OPTION_EB
13136 {"EB", no_argument, NULL, OPTION_EB},
13137#endif
13138#ifdef OPTION_EL
13139 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13140#endif
13141 {NULL, no_argument, NULL, 0}
13142};
13143
13144size_t md_longopts_size = sizeof (md_longopts);
13145
03b1477f 13146struct arm_option_table
b99bd4ef 13147{
03b1477f
RE
13148 char *option; /* Option name to match. */
13149 char *help; /* Help information. */
13150 int *var; /* Variable to change. */
13151 int value; /* What to change it to. */
13152 char *deprecated; /* If non-null, print this message. */
13153};
b99bd4ef 13154
cc8a6dd0 13155struct arm_option_table arm_opts[] =
03b1477f
RE
13156{
13157 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13158 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13159 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13160 &support_interwork, 1, NULL},
13161 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13162 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13163 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13164 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13165 1, NULL},
13166 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13167 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13168 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13169 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13170 NULL},
13171
13172 /* These are recognized by the assembler, but have no affect on code. */
13173 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13174 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13175
13176 /* DON'T add any new processors to this list -- we want the whole list
13177 to go away... Add them to the processors table instead. */
13178 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13179 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13180 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13181 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13182 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13183 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13184 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13185 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13186 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13187 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13188 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13189 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13190 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13191 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13192 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13193 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13194 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13195 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13196 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13197 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13198 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13199 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13200 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13201 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13202 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13203 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13204 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13205 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13206 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13207 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13208 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13209 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13210 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13211 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13212 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13213 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13214 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13215 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13216 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13217 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13218 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13219 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13220 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13221 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13222 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13223 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13224 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13225 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13226 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13227 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13228 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13229 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13230 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13231 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13232 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13233 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13234 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13235 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13236 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13237 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13238 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13239 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13240 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13241 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13242 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13243 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13244 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13245 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13246 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13247 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13248 N_("use -mcpu=strongarm110")},
13249 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13250 N_("use -mcpu=strongarm1100")},
13251 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13252 N_("use -mcpu=strongarm1110")},
13253 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13254 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13255 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13256
13257 /* Architecture variants -- don't add any more to this list either. */
13258 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13259 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13260 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13261 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13262 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13263 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13264 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13265 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13266 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13267 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13268 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13269 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13270 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13271 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13272 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13273 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13274 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13275 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13276
13277 /* Floating point variants -- don't add any more to this list either. */
13278 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13279 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13280 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13281 {"mno-fpu", NULL, &legacy_fpu, 0,
13282 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13283
13284 {NULL, NULL, NULL, 0, NULL}
13285};
21f0f23a 13286
03b1477f
RE
13287struct arm_cpu_option_table
13288{
13289 char *name;
13290 int value;
13291 /* For some CPUs we assume an FPU unless the user explicitly sets
13292 -mfpu=... */
13293 int default_fpu;
13294};
13295
13296/* This list should, at a minimum, contain all the cpu names
13297 recognized by GCC. */
13298static struct arm_cpu_option_table arm_cpus[] =
13299{
13300 {"all", ARM_ANY, FPU_ARCH_FPA},
13301 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13302 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13303 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13304 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13305 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13307 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13308 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13309 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13310 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13312 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13314 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13315 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13316 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13317 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13318 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13319 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13320 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13321 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13322 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13323 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13324 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13325 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13326 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13327 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13328 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13329 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13330 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13331 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13332 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13333 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13334 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13335 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13336 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13337 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13338 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13339 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13340 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13341 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13342 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13343 /* For V5 or later processors we default to using VFP; but the user
13344 should really set the FPU type explicitly. */
13345 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13346 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13347 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13348 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13349 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13350 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13351 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13352 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13353 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13354 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13355 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13356 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13357 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 13358 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015
MM
13359 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13360 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13361 /* ??? XSCALE is really an architecture. */
13362 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13363 /* ??? iwmmxt is not a processor. */
e16bb312 13364 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13365 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13366 /* Maverick */
33a392fb 13367 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13368 {NULL, 0, 0}
13369};
cc8a6dd0 13370
03b1477f
RE
13371struct arm_arch_option_table
13372{
13373 char *name;
13374 int value;
13375 int default_fpu;
13376};
13377
13378/* This list should, at a minimum, contain all the architecture names
13379 recognized by GCC. */
13380static struct arm_arch_option_table arm_archs[] =
13381{
13382 {"all", ARM_ANY, FPU_ARCH_FPA},
13383 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13384 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13385 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13386 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13387 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13388 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13389 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13390 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13391 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13392 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13393 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13394 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13395 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13396 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13397 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13398 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13399 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13400 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13401 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13402 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13403 {NULL, 0, 0}
13404};
13405
13406/* ISA extensions in the co-processor space. */
13407struct arm_arch_extension_table
13408{
13409 char *name;
13410 int value;
13411};
13412
13413static struct arm_arch_extension_table arm_extensions[] =
13414{
13415 {"maverick", ARM_CEXT_MAVERICK},
13416 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13417 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13418 {NULL, 0}
13419};
b99bd4ef 13420
03b1477f
RE
13421struct arm_fpu_option_table
13422{
13423 char *name;
13424 int value;
13425};
13426
13427/* This list should, at a minimum, contain all the fpu names
13428 recognized by GCC. */
13429static struct arm_fpu_option_table arm_fpus[] =
13430{
13431 {"softfpa", FPU_NONE},
13432 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13433 {"fpe2", FPU_ARCH_FPE},
13434 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13435 {"fpa", FPU_ARCH_FPA},
13436 {"fpa10", FPU_ARCH_FPA},
13437 {"fpa11", FPU_ARCH_FPA},
13438 {"arm7500fe", FPU_ARCH_FPA},
13439 {"softvfp", FPU_ARCH_VFP},
13440 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13441 {"vfp", FPU_ARCH_VFP_V2},
13442 {"vfp9", FPU_ARCH_VFP_V2},
13443 {"vfp10", FPU_ARCH_VFP_V2},
13444 {"vfp10-r0", FPU_ARCH_VFP_V1},
13445 {"vfpxd", FPU_ARCH_VFP_V1xD},
13446 {"arm1020t", FPU_ARCH_VFP_V1},
13447 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13448 {"arm1136jfs", FPU_ARCH_VFP_V2},
33a392fb
PB
13449 {"maverick", FPU_ARCH_MAVERICK},
13450 {NULL, 0}
13451};
13452
13453struct arm_float_abi_option_table
13454{
13455 char *name;
13456 int value;
13457};
13458
13459static struct arm_float_abi_option_table arm_float_abis[] =
13460{
13461 {"hard", ARM_FLOAT_ABI_HARD},
13462 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13463 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13464 {NULL, 0}
13465};
13466
d507cf36
PB
13467struct arm_eabi_option_table
13468{
13469 char *name;
13470 unsigned int value;
13471};
13472
13473/* We only know hot to output GNU and ver 3 (AAELF) formats. */
13474static struct arm_eabi_option_table arm_eabis[] =
13475{
13476 {"gnu", EF_ARM_EABI_UNKNOWN},
13477 {"3", EF_ARM_EABI_VER3},
13478 {NULL, 0}
13479};
13480
03b1477f
RE
13481struct arm_long_option_table
13482{
13483 char *option; /* Substring to match. */
13484 char *help; /* Help information. */
13485 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13486 char *deprecated; /* If non-null, print this message. */
13487};
13488
13489static int
13490arm_parse_extension (str, opt_p)
13491 char *str;
13492 int *opt_p;
13493{
13494 while (str != NULL && *str != 0)
13495 {
13496 struct arm_arch_extension_table *opt;
13497 char *ext;
13498 int optlen;
13499
13500 if (*str != '+')
b99bd4ef 13501 {
03b1477f
RE
13502 as_bad (_("invalid architectural extension"));
13503 return 0;
13504 }
b99bd4ef 13505
03b1477f
RE
13506 str++;
13507 ext = strchr (str, '+');
b99bd4ef 13508
03b1477f
RE
13509 if (ext != NULL)
13510 optlen = ext - str;
13511 else
13512 optlen = strlen (str);
b99bd4ef 13513
03b1477f
RE
13514 if (optlen == 0)
13515 {
13516 as_bad (_("missing architectural extension"));
13517 return 0;
13518 }
b99bd4ef 13519
03b1477f
RE
13520 for (opt = arm_extensions; opt->name != NULL; opt++)
13521 if (strncmp (opt->name, str, optlen) == 0)
13522 {
13523 *opt_p |= opt->value;
13524 break;
13525 }
bfae80f2 13526
03b1477f
RE
13527 if (opt->name == NULL)
13528 {
13529 as_bad (_("unknown architectural extnsion `%s'"), str);
13530 return 0;
13531 }
b99bd4ef 13532
03b1477f
RE
13533 str = ext;
13534 };
b99bd4ef 13535
03b1477f
RE
13536 return 1;
13537}
b99bd4ef 13538
03b1477f
RE
13539static int
13540arm_parse_cpu (str)
13541 char *str;
13542{
13543 struct arm_cpu_option_table *opt;
13544 char *ext = strchr (str, '+');
13545 int optlen;
b99bd4ef 13546
03b1477f
RE
13547 if (ext != NULL)
13548 optlen = ext - str;
13549 else
13550 optlen = strlen (str);
b99bd4ef 13551
03b1477f
RE
13552 if (optlen == 0)
13553 {
13554 as_bad (_("missing cpu name `%s'"), str);
13555 return 0;
13556 }
b99bd4ef 13557
03b1477f
RE
13558 for (opt = arm_cpus; opt->name != NULL; opt++)
13559 if (strncmp (opt->name, str, optlen) == 0)
13560 {
13561 mcpu_cpu_opt = opt->value;
13562 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13563
03b1477f
RE
13564 if (ext != NULL)
13565 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13566
03b1477f
RE
13567 return 1;
13568 }
b99bd4ef 13569
03b1477f
RE
13570 as_bad (_("unknown cpu `%s'"), str);
13571 return 0;
13572}
b99bd4ef 13573
03b1477f
RE
13574static int
13575arm_parse_arch (str)
13576 char *str;
13577{
13578 struct arm_arch_option_table *opt;
13579 char *ext = strchr (str, '+');
13580 int optlen;
b99bd4ef 13581
03b1477f
RE
13582 if (ext != NULL)
13583 optlen = ext - str;
13584 else
13585 optlen = strlen (str);
b99bd4ef 13586
03b1477f
RE
13587 if (optlen == 0)
13588 {
13589 as_bad (_("missing architecture name `%s'"), str);
13590 return 0;
13591 }
b99bd4ef 13592
b99bd4ef 13593
03b1477f
RE
13594 for (opt = arm_archs; opt->name != NULL; opt++)
13595 if (strcmp (opt->name, str) == 0)
13596 {
13597 march_cpu_opt = opt->value;
13598 march_fpu_opt = opt->default_fpu;
b99bd4ef 13599
03b1477f
RE
13600 if (ext != NULL)
13601 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13602
03b1477f
RE
13603 return 1;
13604 }
b99bd4ef 13605
03b1477f
RE
13606 as_bad (_("unknown architecture `%s'\n"), str);
13607 return 0;
13608}
13609
13610static int
13611arm_parse_fpu (str)
13612 char *str;
13613{
13614 struct arm_fpu_option_table *opt;
b99bd4ef 13615
03b1477f
RE
13616 for (opt = arm_fpus; opt->name != NULL; opt++)
13617 if (strcmp (opt->name, str) == 0)
13618 {
13619 mfpu_opt = opt->value;
13620 return 1;
13621 }
b99bd4ef 13622
03b1477f
RE
13623 as_bad (_("unknown floating point format `%s'\n"), str);
13624 return 0;
13625}
b99bd4ef 13626
33a392fb
PB
13627static int
13628arm_parse_float_abi (str)
13629 char * str;
13630{
13631 struct arm_float_abi_option_table *opt;
13632
13633 for (opt = arm_float_abis; opt->name != NULL; opt++)
13634 if (strcmp (opt->name, str) == 0)
13635 {
13636 mfloat_abi_opt = opt->value;
13637 return 1;
13638 }
13639
13640 as_bad (_("unknown floating point abi `%s'\n"), str);
13641 return 0;
13642}
13643
d507cf36
PB
13644static int
13645arm_parse_eabi (str)
13646 char * str;
13647{
13648 struct arm_eabi_option_table *opt;
13649
13650 for (opt = arm_eabis; opt->name != NULL; opt++)
13651 if (strcmp (opt->name, str) == 0)
13652 {
13653 meabi_flags = opt->value;
13654 return 1;
13655 }
13656 as_bad (_("unknown EABI `%s'\n"), str);
13657 return 0;
13658}
13659
03b1477f
RE
13660struct arm_long_option_table arm_long_opts[] =
13661{
13662 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13663 arm_parse_cpu, NULL},
13664 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13665 arm_parse_arch, NULL},
13666 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13667 arm_parse_fpu, NULL},
33a392fb
PB
13668 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13669 arm_parse_float_abi, NULL},
d507cf36
PB
13670 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13671 arm_parse_eabi, NULL},
03b1477f
RE
13672 {NULL, NULL, 0, NULL}
13673};
b99bd4ef 13674
03b1477f
RE
13675int
13676md_parse_option (c, arg)
13677 int c;
13678 char * arg;
13679{
13680 struct arm_option_table *opt;
13681 struct arm_long_option_table *lopt;
b99bd4ef 13682
03b1477f
RE
13683 switch (c)
13684 {
13685#ifdef OPTION_EB
13686 case OPTION_EB:
13687 target_big_endian = 1;
b99bd4ef 13688 break;
03b1477f 13689#endif
b99bd4ef 13690
03b1477f
RE
13691#ifdef OPTION_EL
13692 case OPTION_EL:
13693 target_big_endian = 0;
b99bd4ef
NC
13694 break;
13695#endif
13696
03b1477f 13697 case 'a':
cc8a6dd0 13698 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13699 ones. */
13700 return 0;
13701
b99bd4ef 13702 default:
03b1477f
RE
13703 for (opt = arm_opts; opt->option != NULL; opt++)
13704 {
13705 if (c == opt->option[0]
13706 && ((arg == NULL && opt->option[1] == 0)
13707 || strcmp (arg, opt->option + 1) == 0))
13708 {
13709#if WARN_DEPRECATED
13710 /* If the option is deprecated, tell the user. */
13711 if (opt->deprecated != NULL)
13712 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13713 arg ? arg : "", _(opt->deprecated));
13714#endif
13715
13716 if (opt->var != NULL)
13717 *opt->var = opt->value;
13718
13719 return 1;
13720 }
13721 }
13722
13723 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13724 {
cc8a6dd0 13725 /* These options are expected to have an argument. */
03b1477f
RE
13726 if (c == lopt->option[0]
13727 && arg != NULL
cc8a6dd0 13728 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13729 strlen (lopt->option + 1)) == 0)
13730 {
13731#if WARN_DEPRECATED
13732 /* If the option is deprecated, tell the user. */
13733 if (lopt->deprecated != NULL)
13734 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13735 _(lopt->deprecated));
13736#endif
13737
13738 /* Call the sup-option parser. */
13739 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13740 }
13741 }
13742
13743 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
13744 return 0;
13745 }
13746
13747 return 1;
13748}
13749
13750void
13751md_show_usage (fp)
13752 FILE * fp;
13753{
03b1477f
RE
13754 struct arm_option_table *opt;
13755 struct arm_long_option_table *lopt;
13756
13757 fprintf (fp, _(" ARM-specific assembler options:\n"));
13758
13759 for (opt = arm_opts; opt->option != NULL; opt++)
13760 if (opt->help != NULL)
13761 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13762
13763 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13764 if (lopt->help != NULL)
13765 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13766
13767#ifdef OPTION_EB
b99bd4ef 13768 fprintf (fp, _("\
03b1477f 13769 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13770#endif
03b1477f
RE
13771
13772#ifdef OPTION_EL
b99bd4ef 13773 fprintf (fp, _("\
03b1477f 13774 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13775#endif
13776}
13777
13778/* We need to be able to fix up arbitrary expressions in some statements.
13779 This is so that we can handle symbols that are an arbitrary distance from
13780 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13781 which returns part of an address in a form which will be valid for
13782 a data instruction. We do this by pushing the expression into a symbol
13783 in the expr_section, and creating a fix for that. */
13784
13785static void
13786fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13787 fragS * frag;
13788 int where;
13789 short int size;
13790 expressionS * exp;
13791 int pc_rel;
13792 int reloc;
13793{
13794 fixS * new_fix;
13795 arm_fix_data * arm_data;
13796
13797 switch (exp->X_op)
13798 {
13799 case O_constant:
13800 case O_symbol:
13801 case O_add:
13802 case O_subtract:
13803 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13804 break;
13805
13806 default:
13807 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13808 pc_rel, reloc);
13809 break;
13810 }
13811
13812 /* Mark whether the fix is to a THUMB instruction, or an ARM
13813 instruction. */
13814 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13815 new_fix->tc_fix_data = (PTR) arm_data;
13816 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13817}
13818
13819/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13820
13821void
13822cons_fix_new_arm (frag, where, size, exp)
13823 fragS * frag;
13824 int where;
13825 int size;
13826 expressionS * exp;
13827{
13828 bfd_reloc_code_real_type type;
13829 int pcrel = 0;
13830
13831 /* Pick a reloc.
13832 FIXME: @@ Should look at CPU word size. */
13833 switch (size)
13834 {
13835 case 1:
13836 type = BFD_RELOC_8;
13837 break;
13838 case 2:
13839 type = BFD_RELOC_16;
13840 break;
13841 case 4:
13842 default:
13843 type = BFD_RELOC_32;
13844 break;
13845 case 8:
13846 type = BFD_RELOC_64;
13847 break;
13848 }
13849
13850 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13851}
13852
13853/* A good place to do this, although this was probably not intended
13854 for this kind of use. We need to dump the literal pool before
13855 references are made to a null symbol pointer. */
13856
13857void
13858arm_cleanup ()
13859{
3d0c9500 13860 literal_pool * pool;
b99bd4ef 13861
3d0c9500
NC
13862 for (pool = list_of_pools; pool; pool = pool->next)
13863 {
13864 /* Put it at the end of the relevent section. */
13865 subseg_set (pool->section, pool->sub_section);
13866 s_ltorg (0);
13867 }
b99bd4ef
NC
13868}
13869
13870void
13871arm_start_line_hook ()
13872{
13873 last_label_seen = NULL;
13874}
13875
13876void
13877arm_frob_label (sym)
13878 symbolS * sym;
13879{
13880 last_label_seen = sym;
13881
13882 ARM_SET_THUMB (sym, thumb_mode);
13883
13884#if defined OBJ_COFF || defined OBJ_ELF
13885 ARM_SET_INTERWORK (sym, support_interwork);
13886#endif
13887
13888 /* Note - do not allow local symbols (.Lxxx) to be labeled
13889 as Thumb functions. This is because these labels, whilst
13890 they exist inside Thumb code, are not the entry points for
13891 possible ARM->Thumb calls. Also, these labels can be used
13892 as part of a computed goto or switch statement. eg gcc
13893 can generate code that looks like this:
13894
13895 ldr r2, [pc, .Laaa]
13896 lsl r3, r3, #2
13897 ldr r2, [r3, r2]
13898 mov pc, r2
cc8a6dd0 13899
b99bd4ef
NC
13900 .Lbbb: .word .Lxxx
13901 .Lccc: .word .Lyyy
13902 ..etc...
13903 .Laaa: .word Lbbb
13904
13905 The first instruction loads the address of the jump table.
13906 The second instruction converts a table index into a byte offset.
13907 The third instruction gets the jump address out of the table.
13908 The fourth instruction performs the jump.
cc8a6dd0 13909
b99bd4ef
NC
13910 If the address stored at .Laaa is that of a symbol which has the
13911 Thumb_Func bit set, then the linker will arrange for this address
13912 to have the bottom bit set, which in turn would mean that the
13913 address computation performed by the third instruction would end
13914 up with the bottom bit set. Since the ARM is capable of unaligned
13915 word loads, the instruction would then load the incorrect address
13916 out of the jump table, and chaos would ensue. */
13917 if (label_is_thumb_function_name
13918 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13919 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13920 {
13921 /* When the address of a Thumb function is taken the bottom
13922 bit of that address should be set. This will allow
13923 interworking between Arm and Thumb functions to work
13924 correctly. */
13925
13926 THUMB_SET_FUNC (sym, 1);
13927
b34976b6 13928 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13929 }
13930}
13931
13932/* Adjust the symbol table. This marks Thumb symbols as distinct from
13933 ARM ones. */
13934
13935void
13936arm_adjust_symtab ()
13937{
13938#ifdef OBJ_COFF
13939 symbolS * sym;
13940
13941 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13942 {
13943 if (ARM_IS_THUMB (sym))
13944 {
13945 if (THUMB_IS_FUNC (sym))
13946 {
13947 /* Mark the symbol as a Thumb function. */
13948 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13949 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13950 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13951
13952 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13953 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13954 else
13955 as_bad (_("%s: unexpected function type: %d"),
13956 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13957 }
cc8a6dd0 13958 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13959 {
13960 case C_EXT:
13961 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13962 break;
13963 case C_STAT:
13964 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13965 break;
13966 case C_LABEL:
13967 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13968 break;
13969 default:
13970 /* Do nothing. */
13971 break;
13972 }
13973 }
13974
13975 if (ARM_IS_INTERWORK (sym))
13976 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13977 }
13978#endif
13979#ifdef OBJ_ELF
13980 symbolS * sym;
13981 char bind;
13982
13983 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13984 {
13985 if (ARM_IS_THUMB (sym))
13986 {
13987 elf_symbol_type * elf_sym;
13988
13989 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13990 bind = ELF_ST_BIND (elf_sym);
13991
13992 /* If it's a .thumb_func, declare it as so,
13993 otherwise tag label as .code 16. */
13994 if (THUMB_IS_FUNC (sym))
13995 elf_sym->internal_elf_sym.st_info =
13996 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13997 else
13998 elf_sym->internal_elf_sym.st_info =
13999 ELF_ST_INFO (bind, STT_ARM_16BIT);
14000 }
14001 }
14002#endif
14003}
14004
14005int
14006arm_data_in_code ()
14007{
14008 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
14009 {
14010 *input_line_pointer = '/';
14011 input_line_pointer += 5;
14012 *input_line_pointer = 0;
14013 return 1;
14014 }
14015
14016 return 0;
14017}
14018
14019char *
14020arm_canonicalize_symbol_name (name)
14021 char * name;
14022{
14023 int len;
14024
14025 if (thumb_mode && (len = strlen (name)) > 5
14026 && streq (name + len - 5, "/data"))
14027 *(name + len - 5) = 0;
14028
14029 return name;
14030}
14031
bfc866a6 14032#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 14033void
b99bd4ef
NC
14034arm_validate_fix (fixP)
14035 fixS * fixP;
14036{
14037 /* If the destination of the branch is a defined symbol which does not have
14038 the THUMB_FUNC attribute, then we must be calling a function which has
14039 the (interfacearm) attribute. We look for the Thumb entry point to that
14040 function and change the branch to refer to that function instead. */
14041 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
14042 && fixP->fx_addsy != NULL
14043 && S_IS_DEFINED (fixP->fx_addsy)
14044 && ! THUMB_IS_FUNC (fixP->fx_addsy))
14045 {
14046 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 14047 }
b99bd4ef 14048}
bfc866a6 14049#endif
b99bd4ef 14050
114424c6
AM
14051int
14052arm_force_relocation (fixp)
14053 struct fix * fixp;
14054{
14055#if defined (OBJ_COFF) && defined (TE_PE)
14056 if (fixp->fx_r_type == BFD_RELOC_RVA)
14057 return 1;
14058#endif
14059#ifdef OBJ_ELF
ae6063d4 14060 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
14061 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14062 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14063 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14064 return 1;
14065#endif
14066
14067 /* Resolve these relocations even if the symbol is extern or weak. */
14068 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 14069 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
14070 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14071 return 0;
14072
ae6063d4 14073 return generic_force_reloc (fixp);
114424c6
AM
14074}
14075
b99bd4ef
NC
14076#ifdef OBJ_COFF
14077/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14078 local labels from being added to the output symbol table when they
14079 are used with the ADRL pseudo op. The ADRL relocation should always
14080 be resolved before the binbary is emitted, so it is safe to say that
14081 it is adjustable. */
14082
b34976b6 14083bfd_boolean
b99bd4ef
NC
14084arm_fix_adjustable (fixP)
14085 fixS * fixP;
14086{
14087 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14088 return 1;
14089 return 0;
14090}
14091#endif
114424c6 14092
b99bd4ef
NC
14093#ifdef OBJ_ELF
14094/* Relocations against Thumb function names must be left unadjusted,
14095 so that the linker can use this information to correctly set the
14096 bottom bit of their addresses. The MIPS version of this function
14097 also prevents relocations that are mips-16 specific, but I do not
14098 know why it does this.
14099
14100 FIXME:
14101 There is one other problem that ought to be addressed here, but
14102 which currently is not: Taking the address of a label (rather
14103 than a function) and then later jumping to that address. Such
14104 addresses also ought to have their bottom bit set (assuming that
14105 they reside in Thumb code), but at the moment they will not. */
14106
b34976b6 14107bfd_boolean
b99bd4ef
NC
14108arm_fix_adjustable (fixP)
14109 fixS * fixP;
14110{
14111 if (fixP->fx_addsy == NULL)
14112 return 1;
14113
b99bd4ef
NC
14114 if (THUMB_IS_FUNC (fixP->fx_addsy)
14115 && fixP->fx_subsy == NULL)
14116 return 0;
14117
14118 /* We need the symbol name for the VTABLE entries. */
14119 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14120 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14121 return 0;
14122
a161fe53
AM
14123 /* Don't allow symbols to be discarded on GOT related relocs. */
14124 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14125 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14126 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14127 return 0;
14128
b99bd4ef
NC
14129 return 1;
14130}
14131
14132const char *
14133elf32_arm_target_format ()
14134{
14135 if (target_big_endian)
14136 {
14137 if (target_oabi)
14138 return "elf32-bigarm-oabi";
14139 else
14140 return "elf32-bigarm";
14141 }
14142 else
14143 {
14144 if (target_oabi)
14145 return "elf32-littlearm-oabi";
14146 else
14147 return "elf32-littlearm";
14148 }
14149}
14150
14151void
14152armelf_frob_symbol (symp, puntp)
14153 symbolS * symp;
14154 int * puntp;
14155{
14156 elf_frob_symbol (symp, puntp);
14157}
14158
b99bd4ef
NC
14159static bfd_reloc_code_real_type
14160arm_parse_reloc ()
14161{
14162 char id [16];
14163 char * ip;
14164 unsigned int i;
14165 static struct
14166 {
14167 char * str;
14168 int len;
14169 bfd_reloc_code_real_type reloc;
14170 }
14171 reloc_map[] =
14172 {
14173#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14174 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14175 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14176 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14177 branch instructions generated by GCC for PLT relocs. */
14178 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14179 { NULL, 0, BFD_RELOC_UNUSED }
14180#undef MAP
14181 };
14182
14183 for (i = 0, ip = input_line_pointer;
3882b010 14184 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14185 i++, ip++)
3882b010 14186 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14187
14188 for (i = 0; reloc_map[i].str; i++)
14189 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14190 break;
14191
14192 input_line_pointer += reloc_map[i].len;
14193
14194 return reloc_map[i].reloc;
14195}
14196
14197static void
14198s_arm_elf_cons (nbytes)
14199 int nbytes;
14200{
14201 expressionS exp;
14202
14203#ifdef md_flush_pending_output
14204 md_flush_pending_output ();
14205#endif
14206
14207 if (is_it_end_of_statement ())
14208 {
14209 demand_empty_rest_of_line ();
14210 return;
14211 }
14212
14213#ifdef md_cons_align
14214 md_cons_align (nbytes);
14215#endif
14216
6057a28f 14217 mapping_state (MAP_DATA);
b99bd4ef
NC
14218 do
14219 {
14220 bfd_reloc_code_real_type reloc;
14221
14222 expression (& exp);
14223
14224 if (exp.X_op == O_symbol
14225 && * input_line_pointer == '('
14226 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14227 {
14228 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14229 int size = bfd_get_reloc_size (howto);
14230
14231 if (size > nbytes)
14232 as_bad ("%s relocations do not fit in %d bytes",
14233 howto->name, nbytes);
14234 else
14235 {
14236 register char *p = frag_more ((int) nbytes);
14237 int offset = nbytes - size;
14238
14239 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14240 &exp, 0, reloc);
14241 }
14242 }
14243 else
14244 emit_expr (&exp, (unsigned int) nbytes);
14245 }
14246 while (*input_line_pointer++ == ',');
14247
14248 /* Put terminator back into stream. */
14249 input_line_pointer --;
14250 demand_empty_rest_of_line ();
14251}
14252
14253#endif /* OBJ_ELF */
14254
14255/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14256 of an rs_align_code fragment. */
14257
14258void
14259arm_handle_align (fragP)
14260 fragS *fragP;
14261{
14262 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14263 static char const thumb_noop[2] = { 0xc0, 0x46 };
14264 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14265 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14266
14267 int bytes, fix, noop_size;
14268 char * p;
14269 const char * noop;
cc8a6dd0 14270
b99bd4ef
NC
14271 if (fragP->fr_type != rs_align_code)
14272 return;
14273
14274 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14275 p = fragP->fr_literal + fragP->fr_fix;
14276 fix = 0;
cc8a6dd0 14277
b99bd4ef
NC
14278 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14279 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14280
b99bd4ef
NC
14281 if (fragP->tc_frag_data)
14282 {
14283 if (target_big_endian)
14284 noop = thumb_bigend_noop;
14285 else
14286 noop = thumb_noop;
14287 noop_size = sizeof (thumb_noop);
14288 }
14289 else
14290 {
14291 if (target_big_endian)
14292 noop = arm_bigend_noop;
14293 else
14294 noop = arm_noop;
14295 noop_size = sizeof (arm_noop);
14296 }
cc8a6dd0 14297
b99bd4ef
NC
14298 if (bytes & (noop_size - 1))
14299 {
14300 fix = bytes & (noop_size - 1);
14301 memset (p, 0, fix);
14302 p += fix;
14303 bytes -= fix;
14304 }
14305
14306 while (bytes >= noop_size)
14307 {
14308 memcpy (p, noop, noop_size);
14309 p += noop_size;
14310 bytes -= noop_size;
14311 fix += noop_size;
14312 }
cc8a6dd0 14313
b99bd4ef
NC
14314 fragP->fr_fix += fix;
14315 fragP->fr_var = noop_size;
14316}
14317
14318/* Called from md_do_align. Used to create an alignment
14319 frag in a code section. */
14320
14321void
14322arm_frag_align_code (n, max)
14323 int n;
14324 int max;
14325{
14326 char * p;
14327
2d2255b5 14328 /* We assume that there will never be a requirement
b99bd4ef
NC
14329 to support alignments greater than 32 bytes. */
14330 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14331 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14332
b99bd4ef
NC
14333 p = frag_var (rs_align_code,
14334 MAX_MEM_FOR_RS_ALIGN_CODE,
14335 1,
14336 (relax_substateT) max,
14337 (symbolS *) NULL,
14338 (offsetT) n,
14339 (char *) NULL);
14340 *p = 0;
14341
14342}
14343
14344/* Perform target specific initialisation of a frag. */
14345
14346void
14347arm_init_frag (fragP)
14348 fragS *fragP;
14349{
14350 /* Record whether this frag is in an ARM or a THUMB area. */
14351 fragP->tc_frag_data = thumb_mode;
14352}