2004-04-22 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
69b97547 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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;
7cc69913 194#ifdef OBJ_ELF
d507cf36 195static int meabi_flags = EF_ARM_EABI_UNKNOWN;
7cc69913 196#endif
b99bd4ef
NC
197
198/* This array holds the chars that always start a comment. If the
199 pre-processor is disabled, these aren't very useful. */
f57c81f6 200const char comment_chars[] = "@";
b99bd4ef
NC
201
202/* This array holds the chars that only start a comment at the beginning of
203 a line. If the line seems to have the form '# 123 filename'
204 .line and .file directives will appear in the pre-processed output. */
205/* Note that input_file.c hand checks for '#' at the beginning of the
206 first line of the input file. This is because the compiler outputs
207 #NO_APP at the beginning of its output. */
208/* Also note that comments like this one will always work. */
05d2d07e 209const char line_comment_chars[] = "#";
b99bd4ef 210
da89cce1 211const char line_separator_chars[] = ";";
b99bd4ef
NC
212
213/* Chars that can be used to separate mant
214 from exp in floating point numbers. */
05d2d07e 215const char EXP_CHARS[] = "eE";
b99bd4ef
NC
216
217/* Chars that mean this number is a floating point constant. */
218/* As in 0f12.456 */
219/* or 0d1.2345e12 */
220
05d2d07e 221const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
222
223/* Prefix characters that indicate the start of an immediate
224 value. */
225#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
226
227#ifdef OBJ_ELF
228/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
229symbolS * GOT_symbol;
230#endif
231
232/* Size of relocation record. */
05d2d07e 233const int md_reloc_size = 8;
b99bd4ef
NC
234
235/* 0: assemble for ARM,
236 1: assemble for Thumb,
237 2: assemble for Thumb even though target CPU does not support thumb
238 instructions. */
239static int thumb_mode = 0;
240
241typedef struct arm_fix
242{
243 int thumb_mode;
244} arm_fix_data;
245
246struct arm_it
247{
05d2d07e 248 const char * error;
b99bd4ef 249 unsigned long instruction;
b99bd4ef
NC
250 int size;
251 struct
252 {
253 bfd_reloc_code_real_type type;
254 expressionS exp;
255 int pc_rel;
256 } reloc;
257};
258
259struct arm_it inst;
260
261enum asm_shift_index
262{
263 SHIFT_LSL = 0,
264 SHIFT_LSR,
265 SHIFT_ASR,
266 SHIFT_ROR,
267 SHIFT_RRX
268};
269
270struct asm_shift_properties
271{
272 enum asm_shift_index index;
273 unsigned long bit_field;
274 unsigned int allows_0 : 1;
275 unsigned int allows_32 : 1;
276};
277
278static const struct asm_shift_properties shift_properties [] =
279{
280 { SHIFT_LSL, 0, 1, 0},
281 { SHIFT_LSR, 0x20, 0, 1},
282 { SHIFT_ASR, 0x40, 0, 1},
283 { SHIFT_ROR, 0x60, 0, 0},
284 { SHIFT_RRX, 0x60, 0, 0}
285};
286
287struct asm_shift_name
288{
289 const char * name;
290 const struct asm_shift_properties * properties;
291};
292
293static const struct asm_shift_name shift_names [] =
294{
295 { "asl", shift_properties + SHIFT_LSL },
296 { "lsl", shift_properties + SHIFT_LSL },
297 { "lsr", shift_properties + SHIFT_LSR },
298 { "asr", shift_properties + SHIFT_ASR },
299 { "ror", shift_properties + SHIFT_ROR },
300 { "rrx", shift_properties + SHIFT_RRX },
301 { "ASL", shift_properties + SHIFT_LSL },
302 { "LSL", shift_properties + SHIFT_LSL },
303 { "LSR", shift_properties + SHIFT_LSR },
304 { "ASR", shift_properties + SHIFT_ASR },
305 { "ROR", shift_properties + SHIFT_ROR },
306 { "RRX", shift_properties + SHIFT_RRX }
307};
308
09d92015 309/* Any kind of shift is accepted. */
b99bd4ef 310#define NO_SHIFT_RESTRICT 1
09d92015
MM
311/* The shift operand must be an immediate value, not a register. */
312#define SHIFT_IMMEDIATE 0
313/* The shift must be LSL or ASR and the operand must be an immediate. */
314#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
315/* The shift must be ASR and the operand must be an immediate. */
316#define SHIFT_ASR_IMMEDIATE 3
317/* The shift must be LSL and the operand must be an immediate. */
318#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
319
320#define NUM_FLOAT_VALS 8
321
05d2d07e 322const char * fp_const[] =
b99bd4ef
NC
323{
324 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
325};
326
327/* Number of littlenums required to hold an extended precision number. */
328#define MAX_LITTLENUMS 6
329
330LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
331
332#define FAIL (-1)
333#define SUCCESS (0)
334
bfae80f2
RE
335/* Whether a Co-processor load/store operation accepts write-back forms. */
336#define CP_WB_OK 1
337#define CP_NO_WB 0
338
b99bd4ef
NC
339#define SUFF_S 1
340#define SUFF_D 2
341#define SUFF_E 3
342#define SUFF_P 4
343
344#define CP_T_X 0x00008000
345#define CP_T_Y 0x00400000
346#define CP_T_Pre 0x01000000
347#define CP_T_UD 0x00800000
348#define CP_T_WB 0x00200000
349
350#define CONDS_BIT 0x00100000
351#define LOAD_BIT 0x00100000
b99bd4ef
NC
352
353#define DOUBLE_LOAD_FLAG 0x00000001
354
355struct asm_cond
356{
05d2d07e 357 const char * template;
b99bd4ef
NC
358 unsigned long value;
359};
360
b99bd4ef 361#define COND_ALWAYS 0xe0000000
90e4755a 362#define COND_MASK 0xf0000000
b99bd4ef 363
05d2d07e 364static const struct asm_cond conds[] =
b99bd4ef
NC
365{
366 {"eq", 0x00000000},
367 {"ne", 0x10000000},
368 {"cs", 0x20000000}, {"hs", 0x20000000},
369 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
370 {"mi", 0x40000000},
371 {"pl", 0x50000000},
372 {"vs", 0x60000000},
373 {"vc", 0x70000000},
374 {"hi", 0x80000000},
375 {"ls", 0x90000000},
376 {"ge", 0xa0000000},
377 {"lt", 0xb0000000},
378 {"gt", 0xc0000000},
379 {"le", 0xd0000000},
380 {"al", 0xe0000000},
381 {"nv", 0xf0000000}
382};
383
b99bd4ef
NC
384struct asm_psr
385{
b34976b6
AM
386 const char *template;
387 bfd_boolean cpsr;
b99bd4ef
NC
388 unsigned long field;
389};
390
2d2255b5 391/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
392#define SPSR_BIT (1 << 22)
393
394/* How many bits to shift the PSR_xxx bits up by. */
395#define PSR_SHIFT 16
396
397#define PSR_c (1 << 0)
398#define PSR_x (1 << 1)
399#define PSR_s (1 << 2)
400#define PSR_f (1 << 3)
401
05d2d07e 402static const struct asm_psr psrs[] =
b99bd4ef 403{
b34976b6
AM
404 {"CPSR", TRUE, PSR_c | PSR_f},
405 {"CPSR_all", TRUE, PSR_c | PSR_f},
406 {"SPSR", FALSE, PSR_c | PSR_f},
407 {"SPSR_all", FALSE, PSR_c | PSR_f},
408 {"CPSR_flg", TRUE, PSR_f},
409 {"CPSR_f", TRUE, PSR_f},
410 {"SPSR_flg", FALSE, PSR_f},
411 {"SPSR_f", FALSE, PSR_f},
412 {"CPSR_c", TRUE, PSR_c},
413 {"CPSR_ctl", TRUE, PSR_c},
414 {"SPSR_c", FALSE, PSR_c},
415 {"SPSR_ctl", FALSE, PSR_c},
416 {"CPSR_x", TRUE, PSR_x},
417 {"CPSR_s", TRUE, PSR_s},
418 {"SPSR_x", FALSE, PSR_x},
419 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 420 /* Combinations of flags. */
b34976b6
AM
421 {"CPSR_fs", TRUE, PSR_f | PSR_s},
422 {"CPSR_fx", TRUE, PSR_f | PSR_x},
423 {"CPSR_fc", TRUE, PSR_f | PSR_c},
424 {"CPSR_sf", TRUE, PSR_s | PSR_f},
425 {"CPSR_sx", TRUE, PSR_s | PSR_x},
426 {"CPSR_sc", TRUE, PSR_s | PSR_c},
427 {"CPSR_xf", TRUE, PSR_x | PSR_f},
428 {"CPSR_xs", TRUE, PSR_x | PSR_s},
429 {"CPSR_xc", TRUE, PSR_x | PSR_c},
430 {"CPSR_cf", TRUE, PSR_c | PSR_f},
431 {"CPSR_cs", TRUE, PSR_c | PSR_s},
432 {"CPSR_cx", TRUE, PSR_c | PSR_x},
433 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
434 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
435 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
436 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
437 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
438 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
439 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
440 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
441 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
442 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
443 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
444 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
445 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
446 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
447 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
448 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
449 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
450 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
451 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
452 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
453 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
454 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
455 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
456 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
457 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
458 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
459 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
460 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
461 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
462 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
463 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
464 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
465 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
466 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
467 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
468 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
469 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
470 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
471 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
472 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
473 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
474 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
475 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
476 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
477 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
478 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
479 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
480 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
481 {"SPSR_fs", FALSE, PSR_f | PSR_s},
482 {"SPSR_fx", FALSE, PSR_f | PSR_x},
483 {"SPSR_fc", FALSE, PSR_f | PSR_c},
484 {"SPSR_sf", FALSE, PSR_s | PSR_f},
485 {"SPSR_sx", FALSE, PSR_s | PSR_x},
486 {"SPSR_sc", FALSE, PSR_s | PSR_c},
487 {"SPSR_xf", FALSE, PSR_x | PSR_f},
488 {"SPSR_xs", FALSE, PSR_x | PSR_s},
489 {"SPSR_xc", FALSE, PSR_x | PSR_c},
490 {"SPSR_cf", FALSE, PSR_c | PSR_f},
491 {"SPSR_cs", FALSE, PSR_c | PSR_s},
492 {"SPSR_cx", FALSE, PSR_c | PSR_x},
493 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
494 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
495 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
496 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
497 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
498 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
499 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
500 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
501 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
502 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
503 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
504 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
505 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
506 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
507 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
508 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
509 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
510 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
511 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
512 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
513 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
514 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
515 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
516 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
517 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
518 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
519 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
520 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
521 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
522 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
523 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
524 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
525 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
526 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
527 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
528 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
529 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
530 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
531 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
532 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
533 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
534 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
535 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
536 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
537 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
538 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
539 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
540 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
541};
542
e16bb312
NC
543enum wreg_type
544 {
545 IWMMXT_REG_WR = 0,
546 IWMMXT_REG_WC = 1,
547 IWMMXT_REG_WR_OR_WC = 2,
548 IWMMXT_REG_WCG
549 };
550
551enum iwmmxt_insn_type
552{
553 check_rd,
554 check_wr,
555 check_wrwr,
556 check_wrwrwr,
557 check_wrwrwcg,
558 check_tbcst,
559 check_tmovmsk,
560 check_tmia,
561 check_tmcrr,
562 check_tmrrc,
563 check_tmcr,
564 check_tmrc,
565 check_tinsr,
566 check_textrc,
567 check_waligni,
568 check_textrm,
569 check_wshufh
570};
571
bfae80f2
RE
572enum vfp_dp_reg_pos
573{
574 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
575};
576
577enum vfp_sp_reg_pos
578{
579 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
580};
581
582enum vfp_ldstm_type
583{
584 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
585};
586
587/* VFP system registers. */
588struct vfp_reg
589{
590 const char *name;
591 unsigned long regno;
592};
593
cc8a6dd0 594static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
595{
596 {"fpsid", 0x00000000},
597 {"FPSID", 0x00000000},
598 {"fpscr", 0x00010000},
599 {"FPSCR", 0x00010000},
600 {"fpexc", 0x00080000},
601 {"FPEXC", 0x00080000}
602};
603
6c43fab6
RE
604/* Structure for a hash table entry for a register. */
605struct reg_entry
606{
607 const char * name;
608 int number;
0bbf2aa4 609 bfd_boolean builtin;
6c43fab6
RE
610};
611
e28cd48c 612/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
613#define REG_SP 13
614#define REG_LR 14
615#define REG_PC 15
616
e16bb312
NC
617#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
618#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
619#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
620
0bbf2aa4
NC
621/* These are the standard names. Users can add aliases with .req.
622 and delete them with .unreq. */
623
6c43fab6
RE
624/* Integer Register Numbers. */
625static const struct reg_entry rn_table[] =
626{
0bbf2aa4
NC
627 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
628 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
629 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
630 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 631 /* ATPCS Synonyms. */
0bbf2aa4
NC
632 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
633 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
634 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 635 /* Well-known aliases. */
0bbf2aa4
NC
636 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
637 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
638 {NULL, 0, TRUE}
6c43fab6
RE
639};
640
e16bb312
NC
641#define WR_PREFIX 0x200
642#define WC_PREFIX 0x400
643
644static const struct reg_entry iwmmxt_table[] =
645{
5a6c6817 646 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
647 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
648 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
649 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
650 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
651 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
652 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
653 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
654 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
655 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
656 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
657 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
658 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
659
660 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
661 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
662 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
663 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
664 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
665 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
666 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
667 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
668 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
669 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
670 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
671 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
672 {NULL, 0, TRUE}
e16bb312
NC
673};
674
6c43fab6
RE
675/* Co-processor Numbers. */
676static const struct reg_entry cp_table[] =
677{
0bbf2aa4
NC
678 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
679 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
680 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
681 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
682 {NULL, 0, TRUE}
6c43fab6
RE
683};
684
685/* Co-processor Register Numbers. */
686static const struct reg_entry cn_table[] =
687{
0bbf2aa4
NC
688 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
689 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
690 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
691 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 692 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
693 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
694 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
695 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
696 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
697 {NULL, 0, TRUE}
6c43fab6
RE
698};
699
700/* FPA Registers. */
701static const struct reg_entry fn_table[] =
702{
0bbf2aa4
NC
703 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
704 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
705 {NULL, 0, TRUE}
6c43fab6
RE
706};
707
bfae80f2
RE
708/* VFP SP Registers. */
709static const struct reg_entry sn_table[] =
710{
0bbf2aa4
NC
711 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
712 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
713 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
714 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
715 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
716 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
717 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
718 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
719 {NULL, 0, TRUE}
bfae80f2
RE
720};
721
722/* VFP DP Registers. */
723static const struct reg_entry dn_table[] =
724{
0bbf2aa4
NC
725 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
726 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
727 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
728 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
729 {NULL, 0, TRUE}
bfae80f2
RE
730};
731
63e63b07 732/* Maverick DSP coprocessor registers. */
6c43fab6
RE
733static const struct reg_entry mav_mvf_table[] =
734{
0bbf2aa4
NC
735 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
736 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
737 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
738 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
739 {NULL, 0, TRUE}
6c43fab6
RE
740};
741
742static const struct reg_entry mav_mvd_table[] =
743{
0bbf2aa4
NC
744 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
745 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
746 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
747 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
748 {NULL, 0, TRUE}
6c43fab6
RE
749};
750
751static const struct reg_entry mav_mvfx_table[] =
752{
0bbf2aa4
NC
753 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
754 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
755 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
756 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
757 {NULL, 0, TRUE}
6c43fab6
RE
758};
759
760static const struct reg_entry mav_mvdx_table[] =
761{
0bbf2aa4
NC
762 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
763 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
764 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
765 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
766 {NULL, 0, TRUE}
6c43fab6
RE
767};
768
769static const struct reg_entry mav_mvax_table[] =
770{
0bbf2aa4
NC
771 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
772 {NULL, 0, TRUE}
6c43fab6
RE
773};
774
775static const struct reg_entry mav_dspsc_table[] =
776{
0bbf2aa4
NC
777 {"dspsc", 0, TRUE},
778 {NULL, 0, TRUE}
6c43fab6
RE
779};
780
781struct reg_map
782{
783 const struct reg_entry *names;
784 int max_regno;
785 struct hash_control *htab;
786 const char *expected;
787};
788
789struct reg_map all_reg_maps[] =
790{
791 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
792 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
793 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 794 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
795 {sn_table, 31, NULL, N_("VFP single precision register expected")},
796 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
797 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
798 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
799 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 800 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
801 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
802 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 803 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
804};
805
806/* Enumeration matching entries in table above. */
807enum arm_reg_type
808{
809 REG_TYPE_RN = 0,
810#define REG_TYPE_FIRST REG_TYPE_RN
811 REG_TYPE_CP = 1,
812 REG_TYPE_CN = 2,
813 REG_TYPE_FN = 3,
bfae80f2
RE
814 REG_TYPE_SN = 4,
815 REG_TYPE_DN = 5,
816 REG_TYPE_MVF = 6,
817 REG_TYPE_MVD = 7,
818 REG_TYPE_MVFX = 8,
819 REG_TYPE_MVDX = 9,
820 REG_TYPE_MVAX = 10,
821 REG_TYPE_DSPSC = 11,
e16bb312 822 REG_TYPE_IWMMXT = 12,
bfae80f2 823
e16bb312 824 REG_TYPE_MAX = 13
6c43fab6 825};
404ff6b5 826
b99bd4ef
NC
827/* Functions called by parser. */
828/* ARM instructions. */
f2b7cb0a
RE
829static void do_arit PARAMS ((char *));
830static void do_cmp PARAMS ((char *));
831static void do_mov PARAMS ((char *));
832static void do_ldst PARAMS ((char *));
833static void do_ldstt PARAMS ((char *));
834static void do_ldmstm PARAMS ((char *));
835static void do_branch PARAMS ((char *));
836static void do_swi PARAMS ((char *));
c9b604bd 837
b99bd4ef 838/* Pseudo Op codes. */
f2b7cb0a
RE
839static void do_adr PARAMS ((char *));
840static void do_adrl PARAMS ((char *));
841static void do_empty PARAMS ((char *));
c9b604bd
RE
842
843/* ARM v2. */
f2b7cb0a
RE
844static void do_mul PARAMS ((char *));
845static void do_mla PARAMS ((char *));
c9b604bd
RE
846
847/* ARM v2S. */
f2b7cb0a 848static void do_swap PARAMS ((char *));
c9b604bd
RE
849
850/* ARM v3. */
f2b7cb0a
RE
851static void do_msr PARAMS ((char *));
852static void do_mrs PARAMS ((char *));
c9b604bd
RE
853
854/* ARM v3M. */
f2b7cb0a 855static void do_mull PARAMS ((char *));
b99bd4ef 856
90e4755a 857/* ARM v4. */
f2b7cb0a 858static void do_ldstv4 PARAMS ((char *));
90e4755a 859
c9b604bd 860/* ARM v4T. */
f2b7cb0a 861static void do_bx PARAMS ((char *));
b99bd4ef 862
ea6ef066 863/* ARM v5T. */
f2b7cb0a
RE
864static void do_blx PARAMS ((char *));
865static void do_bkpt PARAMS ((char *));
866static void do_clz PARAMS ((char *));
867static void do_lstc2 PARAMS ((char *));
868static void do_cdp2 PARAMS ((char *));
869static void do_co_reg2 PARAMS ((char *));
b99bd4ef 870
ea6ef066 871/* ARM v5TExP. */
f2b7cb0a
RE
872static void do_smla PARAMS ((char *));
873static void do_smlal PARAMS ((char *));
874static void do_smul PARAMS ((char *));
875static void do_qadd PARAMS ((char *));
c9b604bd 876
ea6ef066 877/* ARM v5TE. */
f2b7cb0a
RE
878static void do_pld PARAMS ((char *));
879static void do_ldrd PARAMS ((char *));
880static void do_co_reg2c PARAMS ((char *));
b99bd4ef 881
ea6ef066
RE
882/* ARM v5TEJ. */
883static void do_bxj PARAMS ((char *));
884
09d92015
MM
885/* ARM V6. */
886static void do_cps PARAMS ((char *));
887static void do_cpsi PARAMS ((char *));
888static void do_ldrex PARAMS ((char *));
889static void do_pkhbt PARAMS ((char *));
890static void do_pkhtb PARAMS ((char *));
891static void do_qadd16 PARAMS ((char *));
892static void do_rev PARAMS ((char *));
893static void do_rfe PARAMS ((char *));
894static void do_sxtah PARAMS ((char *));
895static void do_sxth PARAMS ((char *));
896static void do_setend PARAMS ((char *));
897static void do_smlad PARAMS ((char *));
898static void do_smlald PARAMS ((char *));
899static void do_smmul PARAMS ((char *));
900static void do_ssat PARAMS ((char *));
901static void do_usat PARAMS ((char *));
902static void do_srs PARAMS ((char *));
903static void do_ssat16 PARAMS ((char *));
904static void do_usat16 PARAMS ((char *));
905static void do_strex PARAMS ((char *));
906static void do_umaal PARAMS ((char *));
907
908static void do_cps_mode PARAMS ((char **));
909static void do_cps_flags PARAMS ((char **, int));
910static int do_endian_specifier PARAMS ((char *));
911static void do_pkh_core PARAMS ((char *, int));
912static void do_sat PARAMS ((char **, int));
913static void do_sat16 PARAMS ((char **, int));
914
b99bd4ef 915/* Coprocessor Instructions. */
f2b7cb0a
RE
916static void do_cdp PARAMS ((char *));
917static void do_lstc PARAMS ((char *));
918static void do_co_reg PARAMS ((char *));
c9b604bd
RE
919
920/* FPA instructions. */
f2b7cb0a
RE
921static void do_fpa_ctrl PARAMS ((char *));
922static void do_fpa_ldst PARAMS ((char *));
923static void do_fpa_ldmstm PARAMS ((char *));
924static void do_fpa_dyadic PARAMS ((char *));
925static void do_fpa_monadic PARAMS ((char *));
926static void do_fpa_cmp PARAMS ((char *));
927static void do_fpa_from_reg PARAMS ((char *));
928static void do_fpa_to_reg PARAMS ((char *));
c9b604bd 929
bfae80f2
RE
930/* VFP instructions. */
931static void do_vfp_sp_monadic PARAMS ((char *));
932static void do_vfp_dp_monadic PARAMS ((char *));
933static void do_vfp_sp_dyadic PARAMS ((char *));
934static void do_vfp_dp_dyadic PARAMS ((char *));
935static void do_vfp_reg_from_sp PARAMS ((char *));
936static void do_vfp_sp_from_reg PARAMS ((char *));
e45d0630
PB
937static void do_vfp_reg2_from_sp2 PARAMS ((char *));
938static void do_vfp_sp2_from_reg2 PARAMS ((char *));
bfae80f2
RE
939static void do_vfp_reg_from_dp PARAMS ((char *));
940static void do_vfp_reg2_from_dp PARAMS ((char *));
941static void do_vfp_dp_from_reg PARAMS ((char *));
942static void do_vfp_dp_from_reg2 PARAMS ((char *));
943static void do_vfp_reg_from_ctrl PARAMS ((char *));
944static void do_vfp_ctrl_from_reg PARAMS ((char *));
945static void do_vfp_sp_ldst PARAMS ((char *));
946static void do_vfp_dp_ldst PARAMS ((char *));
947static void do_vfp_sp_ldstmia PARAMS ((char *));
948static void do_vfp_sp_ldstmdb PARAMS ((char *));
949static void do_vfp_dp_ldstmia PARAMS ((char *));
950static void do_vfp_dp_ldstmdb PARAMS ((char *));
951static void do_vfp_xp_ldstmia PARAMS ((char *));
952static void do_vfp_xp_ldstmdb PARAMS ((char *));
953static void do_vfp_sp_compare_z PARAMS ((char *));
954static void do_vfp_dp_compare_z PARAMS ((char *));
955static void do_vfp_dp_sp_cvt PARAMS ((char *));
956static void do_vfp_sp_dp_cvt PARAMS ((char *));
957
c9b604bd 958/* XScale. */
63e63b07
RE
959static void do_xsc_mia PARAMS ((char *));
960static void do_xsc_mar PARAMS ((char *));
961static void do_xsc_mra PARAMS ((char *));
f2b7cb0a
RE
962
963/* Maverick. */
63e63b07 964static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
6c43fab6 965 enum arm_reg_type));
63e63b07
RE
966static void do_mav_binops_1a PARAMS ((char *));
967static void do_mav_binops_1b PARAMS ((char *));
968static void do_mav_binops_1c PARAMS ((char *));
969static void do_mav_binops_1d PARAMS ((char *));
970static void do_mav_binops_1e PARAMS ((char *));
971static void do_mav_binops_1f PARAMS ((char *));
972static void do_mav_binops_1g PARAMS ((char *));
973static void do_mav_binops_1h PARAMS ((char *));
974static void do_mav_binops_1i PARAMS ((char *));
975static void do_mav_binops_1j PARAMS ((char *));
976static void do_mav_binops_1k PARAMS ((char *));
977static void do_mav_binops_1l PARAMS ((char *));
978static void do_mav_binops_1m PARAMS ((char *));
979static void do_mav_binops_1n PARAMS ((char *));
980static void do_mav_binops_1o PARAMS ((char *));
981static void do_mav_binops_2a PARAMS ((char *));
982static void do_mav_binops_2b PARAMS ((char *));
983static void do_mav_binops_2c PARAMS ((char *));
984static void do_mav_binops_3a PARAMS ((char *));
985static void do_mav_binops_3b PARAMS ((char *));
986static void do_mav_binops_3c PARAMS ((char *));
987static void do_mav_binops_3d PARAMS ((char *));
cc8a6dd0 988static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
989 enum arm_reg_type,
990 enum arm_reg_type));
63e63b07
RE
991static void do_mav_triple_4a PARAMS ((char *));
992static void do_mav_triple_4b PARAMS ((char *));
993static void do_mav_triple_5a PARAMS ((char *));
994static void do_mav_triple_5b PARAMS ((char *));
995static void do_mav_triple_5c PARAMS ((char *));
996static void do_mav_triple_5d PARAMS ((char *));
997static void do_mav_triple_5e PARAMS ((char *));
998static void do_mav_triple_5f PARAMS ((char *));
999static void do_mav_triple_5g PARAMS ((char *));
1000static void do_mav_triple_5h PARAMS ((char *));
cc8a6dd0 1001static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
1002 enum arm_reg_type,
1003 enum arm_reg_type,
1004 enum arm_reg_type));
63e63b07
RE
1005static void do_mav_quad_6a PARAMS ((char *));
1006static void do_mav_quad_6b PARAMS ((char *));
1007static void do_mav_dspsc_1 PARAMS ((char *));
1008static void do_mav_dspsc_2 PARAMS ((char *));
1009static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
6c43fab6 1010 enum arm_reg_type));
63e63b07
RE
1011static void do_mav_shift_1 PARAMS ((char *));
1012static void do_mav_shift_2 PARAMS ((char *));
1013static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
1014static void do_mav_ldst_1 PARAMS ((char *));
1015static void do_mav_ldst_2 PARAMS ((char *));
1016static void do_mav_ldst_3 PARAMS ((char *));
1017static void do_mav_ldst_4 PARAMS ((char *));
1018
1019static int mav_reg_required_here PARAMS ((char **, int,
6c43fab6 1020 enum arm_reg_type));
63e63b07 1021static int mav_parse_offset PARAMS ((char **, int *));
404ff6b5 1022
90e4755a
RE
1023static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1024 int, int));
6c43fab6
RE
1025static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1026static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
05d2d07e 1027static const struct asm_psr * arm_psr_parse PARAMS ((char **));
90e4755a
RE
1028static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1029 fragS *));
b99bd4ef
NC
1030static int add_to_lit_pool PARAMS ((void));
1031static unsigned validate_immediate PARAMS ((unsigned));
90e4755a
RE
1032static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1033 unsigned int *));
b99bd4ef
NC
1034static int validate_offset_imm PARAMS ((unsigned int, int));
1035static void opcode_select PARAMS ((int));
1036static void end_of_line PARAMS ((char *));
1037static int reg_required_here PARAMS ((char **, int));
1038static int psr_required_here PARAMS ((char **));
1039static int co_proc_number PARAMS ((char **));
1040static int cp_opc_expr PARAMS ((char **, int, int));
1041static int cp_reg_required_here PARAMS ((char **, int));
1042static int fp_reg_required_here PARAMS ((char **, int));
bfae80f2
RE
1043static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1044static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1045static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1046static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1047static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1048static long vfp_dp_reg_list PARAMS ((char **));
1049static int vfp_psr_required_here PARAMS ((char **str));
1050static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
b99bd4ef 1051static int cp_address_offset PARAMS ((char **));
bfae80f2 1052static int cp_address_required_here PARAMS ((char **, int));
b99bd4ef
NC
1053static int my_get_float_expression PARAMS ((char **));
1054static int skip_past_comma PARAMS ((char **));
1055static int walk_no_bignums PARAMS ((symbolS *));
1056static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1057static int data_op2 PARAMS ((char **));
1058static int fp_op2 PARAMS ((char **));
1059static long reg_list PARAMS ((char **));
1060static void thumb_load_store PARAMS ((char *, int, int));
1061static int decode_shift PARAMS ((char **, int));
90e4755a
RE
1062static int ldst_extend PARAMS ((char **));
1063static int ldst_extend_v4 PARAMS ((char **));
b99bd4ef 1064static void thumb_add_sub PARAMS ((char *, int));
6c43fab6
RE
1065static void insert_reg PARAMS ((const struct reg_entry *,
1066 struct hash_control *));
b99bd4ef
NC
1067static void thumb_shift PARAMS ((char *, int));
1068static void thumb_mov_compare PARAMS ((char *, int));
f2b7cb0a 1069static void build_arm_ops_hsh PARAMS ((void));
b99bd4ef
NC
1070static void set_constant_flonums PARAMS ((void));
1071static valueT md_chars_to_number PARAMS ((char *, int));
6c43fab6
RE
1072static void build_reg_hsh PARAMS ((struct reg_map *));
1073static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1074static int create_register_alias PARAMS ((char *, char *));
f03698e6 1075static void output_inst PARAMS ((const char *));
2c20dfb2
NC
1076static int accum0_required_here PARAMS ((char **));
1077static int ld_mode_required_here PARAMS ((char **));
f2b7cb0a 1078static void do_branch25 PARAMS ((char *));
2c20dfb2 1079static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
1080#ifdef OBJ_ELF
1081static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1082#endif
1083
e16bb312
NC
1084static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1085static void do_iwmmxt_byte_addr PARAMS ((char *));
1086static void do_iwmmxt_tandc PARAMS ((char *));
1087static void do_iwmmxt_tbcst PARAMS ((char *));
1088static void do_iwmmxt_textrc PARAMS ((char *));
1089static void do_iwmmxt_textrm PARAMS ((char *));
1090static void do_iwmmxt_tinsr PARAMS ((char *));
1091static void do_iwmmxt_tmcr PARAMS ((char *));
1092static void do_iwmmxt_tmcrr PARAMS ((char *));
1093static void do_iwmmxt_tmia PARAMS ((char *));
1094static void do_iwmmxt_tmovmsk PARAMS ((char *));
1095static void do_iwmmxt_tmrc PARAMS ((char *));
1096static void do_iwmmxt_tmrrc PARAMS ((char *));
1097static void do_iwmmxt_torc PARAMS ((char *));
1098static void do_iwmmxt_waligni PARAMS ((char *));
1099static void do_iwmmxt_wmov PARAMS ((char *));
1100static void do_iwmmxt_word_addr PARAMS ((char *));
1101static void do_iwmmxt_wrwr PARAMS ((char *));
1102static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1103static void do_iwmmxt_wrwrwr PARAMS ((char *));
1104static void do_iwmmxt_wshufh PARAMS ((char *));
1105static void do_iwmmxt_wzero PARAMS ((char *));
1106static int cp_byte_address_offset PARAMS ((char **));
1107static int cp_byte_address_required_here PARAMS ((char **));
1108
b99bd4ef
NC
1109/* ARM instructions take 4bytes in the object file, Thumb instructions
1110 take 2: */
1111#define INSN_SIZE 4
1112
404ff6b5 1113/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 1114#define MAV_MODE1 0x100c
404ff6b5
AH
1115
1116/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 1117#define MAV_MODE2 0x0c10
404ff6b5 1118
34920d91
NC
1119/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1120#define MAV_MODE3 0x100c
404ff6b5
AH
1121
1122/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 1123#define MAV_MODE4 0x0c0010
404ff6b5
AH
1124
1125/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 1126#define MAV_MODE5 0x00100c
404ff6b5
AH
1127
1128/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 1129#define MAV_MODE6 0x00100c05
b99bd4ef
NC
1130
1131struct asm_opcode
1132{
1133 /* Basic string to match. */
05d2d07e 1134 const char * template;
b99bd4ef
NC
1135
1136 /* Basic instruction code. */
1137 unsigned long value;
1138
90e4755a
RE
1139 /* Offset into the template where the condition code (if any) will be.
1140 If zero, then the instruction is never conditional. */
1141 unsigned cond_offset;
b99bd4ef 1142
90e4755a
RE
1143 /* Which architecture variant provides this instruction. */
1144 unsigned long variant;
b99bd4ef
NC
1145
1146 /* Function to call to parse args. */
f2b7cb0a 1147 void (* parms) PARAMS ((char *));
b99bd4ef
NC
1148};
1149
05d2d07e 1150static const struct asm_opcode insns[] =
b99bd4ef 1151{
c9b604bd 1152 /* Core ARM Instructions. */
90e4755a
RE
1153 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1154 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1155 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1156 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1157 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1158 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1159 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1160 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1161 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1162 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1163 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1164 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1165 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1166 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1167 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1168 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1169 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1170 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1171 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1172 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1173
1174 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1175 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1176 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1177 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1178 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1179 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1180 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1181 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1182 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1183 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1184 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1185 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1186
1187 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1188 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1189 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1190 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1191
1192 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1193 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1194 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1195 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1196 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1197 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1198 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1199 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1200
1201 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1202 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1203 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1204 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1205 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1206 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1207 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1208 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1209
1210 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1211 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1212 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1213 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1214 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1215 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1216 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1217 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1218
1219 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
b99bd4ef 1220#ifdef TE_WINCE
c9b604bd 1221 /* XXX This is the wrong place to do this. Think multi-arch. */
90e4755a
RE
1222 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1223 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
b99bd4ef 1224#else
90e4755a
RE
1225 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1226 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
b99bd4ef
NC
1227#endif
1228
c9b604bd 1229 /* Pseudo ops. */
90e4755a
RE
1230 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1231 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1232 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
b99bd4ef 1233
c9b604bd 1234 /* ARM 2 multiplies. */
90e4755a
RE
1235 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1236 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1237 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1238 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 1239
67c1ffbe 1240 /* Generic coprocessor instructions. */
90e4755a
RE
1241 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1242 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1243 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1244 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1245 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1246 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1247 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
c9b604bd
RE
1248
1249 /* ARM 3 - swp instructions. */
90e4755a
RE
1250 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1251 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 1252
c9b604bd 1253 /* ARM 6 Status register instructions. */
90e4755a
RE
1254 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1255 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1256 /* ScottB: our code uses 0xe128f000 for msr.
c9b604bd 1257 NickC: but this is wrong because the bits 16 through 19 are
90e4755a 1258 handled by the PSR_xxx defines above. */
b99bd4ef 1259
f2b7cb0a 1260 /* ARM 7M long multiplies. */
90e4755a
RE
1261 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1262 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1263 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1264 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1265 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1266 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1267 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1268 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1269
1270 /* ARM Architecture 4. */
1271 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1272 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1273 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1274 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 1275
c9b604bd 1276 /* ARM Architecture 4T. */
cc8a6dd0 1277 /* Note: bx (and blx) are required on V5, even if the processor does
90e4755a
RE
1278 not support Thumb. */
1279 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1280
ea6ef066 1281 /* ARM Architecture 5T. */
90e4755a
RE
1282 /* Note: blx has 2 variants, so the .value is set dynamically.
1283 Only one of the variants has conditional execution. */
1284 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1285 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1286 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1287 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1288 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1289 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1290 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1291 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1292 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1293 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1294
ea6ef066 1295 /* ARM Architecture 5TExP. */
90e4755a
RE
1296 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1297 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1298 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1299 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1300
1301 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1302 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1303
1304 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1305 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1306 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1307 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1308
1309 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1310 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1311 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1312 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1313
1314 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1315 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1316
1317 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1318 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1319 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1320 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
c9b604bd 1321
ea6ef066 1322 /* ARM Architecture 5TE. */
90e4755a
RE
1323 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1324 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1325 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1326
1327 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1328 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
404ff6b5 1329
ea6ef066
RE
1330 /* ARM Architecture 5TEJ. */
1331 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1332
09d92015
MM
1333 /* ARM V6. */
1334 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1335 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1336 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1337 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1338 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1339 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1340 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1341 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1342 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1343 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1344 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1345 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1346 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1347 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1348 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1349 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1350 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1351 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1352 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1353 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1354 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1355 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1356 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1357 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1358 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1359 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1360 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1361 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1362 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1363 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1364 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1365 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1366 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1367 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1368 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1369 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1370 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1371 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1372 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1373 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1374 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1375 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1376 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1377 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1378 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1379 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1380 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1381 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1382 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1383 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1384 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1385 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1386 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1387 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1388 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1389 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1390 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1391 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1392 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1393 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1394 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1395 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1396 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1397 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1398 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1399 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1400 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1401 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1402 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1403 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1404 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1405 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1406 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1407 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1408 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1409 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1410 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1411 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1412 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1413 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1414 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1415 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1416 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1417 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1418 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1419 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1420 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1421 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1422 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1423 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1424 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1425 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1426 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1427 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1428 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1429 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1430 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1431 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1432 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1433
c9b604bd 1434 /* Core FPA instruction set (V1). */
90e4755a
RE
1435 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1436 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1437 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1438 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1439
1440 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1441 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1442 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1443 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1444
1445 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1446 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1447 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1448 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1449
1450 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1459 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462
1463 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1472 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475
1476 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1485 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488
1489 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1498 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501
1502 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1511 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514
1515 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1524 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527
1528 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1537 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540
1541 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1550 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553
1554 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1563 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566
1567 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1576 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579
1580 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1589 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592
1593 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1602 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605
1606 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1615 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618
1619 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1628 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631
1632 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1641 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1642 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1643 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1644
1645 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1646 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1647 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1648 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1649 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1650 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1651 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1652 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1653 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1654 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1655 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1656 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1657
1658 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1667 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670
1671 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1680 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683
1684 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1693 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696
1697 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1706 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709
1710 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1719 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722
1723 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1732 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735
1736 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1745 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748
1749 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1758 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761
1762 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1771 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774
1775 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1784 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787
1788 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1797 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800
1801 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1810 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1811 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1812 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1813
1814 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1815 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1816 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1817 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1818 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1819 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1820 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1821 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1822 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1823 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1824 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1825 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1826
1827 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1828 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1829 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1830 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1831 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1832 not be an optional suffix, but part of the instruction. To be
1833 compatible, we accept either. */
1834 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1835 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1836
1837 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1838 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1839 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1840 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1841 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1842 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1843 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1844 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1845 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1846 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1847 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1848 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1849
1850 /* The implementation of the FIX instruction is broken on some
1851 assemblers, in that it accepts a precision specifier as well as a
1852 rounding specifier, despite the fact that this is meaningless.
1853 To be more compatible, we accept it as well, though of course it
1854 does not set any bits. */
1855 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1856 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1857 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1858 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1859 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1860 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1861 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1862 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1863 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1864 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1865 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1866 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1867 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
c9b604bd
RE
1868
1869 /* Instructions that were new with the real FPA, call them V2. */
90e4755a
RE
1870 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1871 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1872 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1873 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1874 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1875 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
c9b604bd 1876
bfae80f2
RE
1877 /* VFP V1xD (single precision). */
1878 /* Moves and type conversions. */
1879 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1880 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1881 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1882 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1883 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1887 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1888 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1889 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1890 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1891
1892 /* Memory operations. */
1893 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1894 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1895 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1896 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1897 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1898 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1899 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1900 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1901 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1902 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1903 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1904 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1905 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1906 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1907 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1908 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1909 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1910 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1911
1912 /* Monadic operations. */
1913 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1914 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1915 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1916
1917 /* Dyadic operations. */
1918 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1925 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1926 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1927
1928 /* Comparisons. */
1929 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1930 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1931 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1932 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1933
1934 /* VFP V1 (Double precision). */
1935 /* Moves and type conversions. */
1936 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1937 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1938 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1939 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1940 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1941 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1942 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1943 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1944 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1945 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1946 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1947 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1948 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1949
1950 /* Memory operations. */
1951 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1952 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1953 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1954 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1955 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1956 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1957 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1958 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1959 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1960 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1961
1962 /* Monadic operations. */
1963 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1964 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1965 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1966
1967 /* Dyadic operations. */
1968 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1969 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1970 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1971 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1972 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1973 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1974 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1975 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1976 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1977
1978 /* Comparisons. */
1979 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1980 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1981 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1982 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1983
1984 /* VFP V2. */
e45d0630
PB
1985 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
1986 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
bfae80f2
RE
1987 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1988 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1989
c9b604bd 1990 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
63e63b07
RE
1991 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1992 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1993 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1994 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1995 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1996 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1997 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1998 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1999
5a6c6817
NC
2000 /* Intel Wireless MMX technology instructions. */
2001 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2002 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2003 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2004 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2005 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2006 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2007 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2008 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2009 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2010 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2014 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2015 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2016 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2017 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2018 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2019 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2020 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2021 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2025 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2026 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2027 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2028 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2029 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2030 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2031 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2032 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2033 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2034 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2035 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2036 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2037 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2038 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2048 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2068 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2069 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2070 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2071 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2090 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2103 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2105 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2107 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2109 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2111 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2112 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2113 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2114 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2115 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2116 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2117 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2118 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2120 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2122 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2124 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2125 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2126 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2127 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2128 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2129 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2130 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2131 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2132 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2133 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2134 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2141 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2142 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2143 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2147 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2148 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2149 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2150 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2151 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2152 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2156 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2157 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2158 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2160 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2161 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2162 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2163
63e63b07
RE
2164 /* Cirrus Maverick instructions. */
2165 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2166 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2167 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2168 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2169 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2170 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2171 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2172 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2173 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2174 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2175 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2176 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2177 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2178 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2179 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2180 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2181 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2182 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
34920d91
NC
2183 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2184 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2185 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2186 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2187 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2188 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2189 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2190 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2191 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2192 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2193 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2194 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
63e63b07
RE
2195 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2196 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2197 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2198 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2199 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2200 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2201 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2202 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2203 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2204 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2205 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2206 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2207 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2208 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2209 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2210 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2211 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2212 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2213 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2214 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2215 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2216 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2217 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2218 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2219 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2220 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2221 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2222 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2223 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2224 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2225 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2226 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2227 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2228 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2229 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2230 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2231 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2232 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2233 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2235 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2236 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2237 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2238 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2239 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2240 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
b99bd4ef
NC
2241};
2242
2243/* Defines for various bits that we will want to toggle. */
2244#define INST_IMMEDIATE 0x02000000
2245#define OFFSET_REG 0x02000000
2246#define HWOFFSET_IMM 0x00400000
2247#define SHIFT_BY_REG 0x00000010
2248#define PRE_INDEX 0x01000000
2249#define INDEX_UP 0x00800000
2250#define WRITE_BACK 0x00200000
2251#define LDM_TYPE_2_OR_3 0x00400000
2252
2253#define LITERAL_MASK 0xf000f000
b99bd4ef 2254#define OPCODE_MASK 0xfe1fffff
90e4755a
RE
2255#define V4_STR_BIT 0x00000020
2256
b99bd4ef
NC
2257#define DATA_OP_SHIFT 21
2258
2259/* Codes to distinguish the arithmetic instructions. */
2260#define OPCODE_AND 0
2261#define OPCODE_EOR 1
2262#define OPCODE_SUB 2
2263#define OPCODE_RSB 3
2264#define OPCODE_ADD 4
2265#define OPCODE_ADC 5
2266#define OPCODE_SBC 6
2267#define OPCODE_RSC 7
2268#define OPCODE_TST 8
2269#define OPCODE_TEQ 9
2270#define OPCODE_CMP 10
2271#define OPCODE_CMN 11
2272#define OPCODE_ORR 12
2273#define OPCODE_MOV 13
2274#define OPCODE_BIC 14
2275#define OPCODE_MVN 15
2276
c9b604bd 2277/* Thumb v1 (ARMv4T). */
b99bd4ef
NC
2278static void do_t_nop PARAMS ((char *));
2279static void do_t_arit PARAMS ((char *));
2280static void do_t_add PARAMS ((char *));
2281static void do_t_asr PARAMS ((char *));
2282static void do_t_branch9 PARAMS ((char *));
2283static void do_t_branch12 PARAMS ((char *));
2284static void do_t_branch23 PARAMS ((char *));
2285static void do_t_bx PARAMS ((char *));
2286static void do_t_compare PARAMS ((char *));
2287static void do_t_ldmstm PARAMS ((char *));
2288static void do_t_ldr PARAMS ((char *));
2289static void do_t_ldrb PARAMS ((char *));
2290static void do_t_ldrh PARAMS ((char *));
2291static void do_t_lds PARAMS ((char *));
2292static void do_t_lsl PARAMS ((char *));
2293static void do_t_lsr PARAMS ((char *));
2294static void do_t_mov PARAMS ((char *));
2295static void do_t_push_pop PARAMS ((char *));
2296static void do_t_str PARAMS ((char *));
2297static void do_t_strb PARAMS ((char *));
2298static void do_t_strh PARAMS ((char *));
2299static void do_t_sub PARAMS ((char *));
2300static void do_t_swi PARAMS ((char *));
2301static void do_t_adr PARAMS ((char *));
2302
c9b604bd
RE
2303/* Thumb v2 (ARMv5T). */
2304static void do_t_blx PARAMS ((char *));
2305static void do_t_bkpt PARAMS ((char *));
2306
09d92015
MM
2307/* ARM V6. */
2308static void do_t_cps PARAMS ((char *));
2309static void do_t_cpy PARAMS ((char *));
2310static void do_t_setend PARAMS ((char *));;
2311
b99bd4ef
NC
2312#define T_OPCODE_MUL 0x4340
2313#define T_OPCODE_TST 0x4200
2314#define T_OPCODE_CMN 0x42c0
2315#define T_OPCODE_NEG 0x4240
2316#define T_OPCODE_MVN 0x43c0
2317
2318#define T_OPCODE_ADD_R3 0x1800
2319#define T_OPCODE_SUB_R3 0x1a00
2320#define T_OPCODE_ADD_HI 0x4400
2321#define T_OPCODE_ADD_ST 0xb000
2322#define T_OPCODE_SUB_ST 0xb080
2323#define T_OPCODE_ADD_SP 0xa800
2324#define T_OPCODE_ADD_PC 0xa000
2325#define T_OPCODE_ADD_I8 0x3000
2326#define T_OPCODE_SUB_I8 0x3800
2327#define T_OPCODE_ADD_I3 0x1c00
2328#define T_OPCODE_SUB_I3 0x1e00
2329
2330#define T_OPCODE_ASR_R 0x4100
2331#define T_OPCODE_LSL_R 0x4080
2332#define T_OPCODE_LSR_R 0x40c0
2333#define T_OPCODE_ASR_I 0x1000
2334#define T_OPCODE_LSL_I 0x0000
2335#define T_OPCODE_LSR_I 0x0800
2336
2337#define T_OPCODE_MOV_I8 0x2000
2338#define T_OPCODE_CMP_I8 0x2800
2339#define T_OPCODE_CMP_LR 0x4280
2340#define T_OPCODE_MOV_HR 0x4600
2341#define T_OPCODE_CMP_HR 0x4500
2342
2343#define T_OPCODE_LDR_PC 0x4800
2344#define T_OPCODE_LDR_SP 0x9800
2345#define T_OPCODE_STR_SP 0x9000
2346#define T_OPCODE_LDR_IW 0x6800
2347#define T_OPCODE_STR_IW 0x6000
2348#define T_OPCODE_LDR_IH 0x8800
2349#define T_OPCODE_STR_IH 0x8000
2350#define T_OPCODE_LDR_IB 0x7800
2351#define T_OPCODE_STR_IB 0x7000
2352#define T_OPCODE_LDR_RW 0x5800
2353#define T_OPCODE_STR_RW 0x5000
2354#define T_OPCODE_LDR_RH 0x5a00
2355#define T_OPCODE_STR_RH 0x5200
2356#define T_OPCODE_LDR_RB 0x5c00
2357#define T_OPCODE_STR_RB 0x5400
2358
2359#define T_OPCODE_PUSH 0xb400
2360#define T_OPCODE_POP 0xbc00
2361
2362#define T_OPCODE_BRANCH 0xe7fe
2363
2364static int thumb_reg PARAMS ((char ** str, int hi_lo));
2365
2366#define THUMB_SIZE 2 /* Size of thumb instruction. */
2367#define THUMB_REG_LO 0x1
2368#define THUMB_REG_HI 0x2
2369#define THUMB_REG_ANY 0x3
2370
2371#define THUMB_H1 0x0080
2372#define THUMB_H2 0x0040
2373
2374#define THUMB_ASR 0
2375#define THUMB_LSL 1
2376#define THUMB_LSR 2
2377
2378#define THUMB_MOVE 0
2379#define THUMB_COMPARE 1
09d92015 2380#define THUMB_CPY 2
b99bd4ef
NC
2381
2382#define THUMB_LOAD 0
2383#define THUMB_STORE 1
2384
2385#define THUMB_PP_PC_LR 0x0100
2386
2387/* These three are used for immediate shifts, do not alter. */
2388#define THUMB_WORD 2
2389#define THUMB_HALFWORD 1
2390#define THUMB_BYTE 0
2391
2392struct thumb_opcode
2393{
2394 /* Basic string to match. */
05d2d07e 2395 const char * template;
b99bd4ef
NC
2396
2397 /* Basic instruction code. */
2398 unsigned long value;
2399
2400 int size;
2401
2402 /* Which CPU variants this exists for. */
90e4755a 2403 unsigned long variant;
b99bd4ef
NC
2404
2405 /* Function to call to parse args. */
2406 void (* parms) PARAMS ((char *));
2407};
2408
05d2d07e 2409static const struct thumb_opcode tinsns[] =
b99bd4ef 2410{
c9b604bd 2411 /* Thumb v1 (ARMv4T). */
b89dddec
RE
2412 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2413 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2414 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2415 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2416 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2417 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2419 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2420 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2421 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2422 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2423 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2424 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2425 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2426 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2427 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2428 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2429 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2430 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2431 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2432 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2433 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2434 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2435 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2436 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
b89dddec
RE
2437 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2438 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2439 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2440 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2441 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2442 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2443 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2444 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2445 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2446 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2447 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2448 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2449 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2450 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2451 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2452 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2453 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2454 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2455 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2456 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2457 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2458 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2459 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2460 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2461 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2462 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2463 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2464 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2465 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2466 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
b99bd4ef 2467 /* Pseudo ops: */
b89dddec
RE
2468 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2469 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
c9b604bd
RE
2470 /* Thumb v2 (ARMv5T). */
2471 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2472 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
09d92015
MM
2473
2474 /* ARM V6. */
2475 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2476 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2477 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2478 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2479 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2480 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2481 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2482 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2483 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2484 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2485 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
b99bd4ef
NC
2486};
2487
f03698e6 2488#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 2489#define BAD_PC _("r15 not allowed here")
f03698e6 2490#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
2491#define ERR_NO_ACCUM _("acc0 expected")
2492
2493static struct hash_control * arm_ops_hsh = NULL;
2494static struct hash_control * arm_tops_hsh = NULL;
2495static struct hash_control * arm_cond_hsh = NULL;
2496static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
2497static struct hash_control * arm_psr_hsh = NULL;
2498
2499/* This table describes all the machine specific pseudo-ops the assembler
2500 has to support. The fields are:
2501 pseudo-op name without dot
2502 function to call to execute this pseudo-op
2503 Integer arg to pass to the function. */
2504
2505static void s_req PARAMS ((int));
0bbf2aa4 2506static void s_unreq PARAMS ((int));
b99bd4ef
NC
2507static void s_align PARAMS ((int));
2508static void s_bss PARAMS ((int));
2509static void s_even PARAMS ((int));
2510static void s_ltorg PARAMS ((int));
2511static void s_arm PARAMS ((int));
2512static void s_thumb PARAMS ((int));
2513static void s_code PARAMS ((int));
2514static void s_force_thumb PARAMS ((int));
2515static void s_thumb_func PARAMS ((int));
2516static void s_thumb_set PARAMS ((int));
76feaaf3 2517#ifdef OBJ_ELF
b99bd4ef
NC
2518static void s_arm_elf_cons PARAMS ((int));
2519#endif
2520
2521static int my_get_expression PARAMS ((expressionS *, char **));
2522
05d2d07e 2523const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2524{
0bbf2aa4 2525 /* Never called because '.req' does not start a line. */
b99bd4ef 2526 { "req", s_req, 0 },
0bbf2aa4 2527 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2528 { "bss", s_bss, 0 },
2529 { "align", s_align, 0 },
2530 { "arm", s_arm, 0 },
2531 { "thumb", s_thumb, 0 },
2532 { "code", s_code, 0 },
2533 { "force_thumb", s_force_thumb, 0 },
2534 { "thumb_func", s_thumb_func, 0 },
2535 { "thumb_set", s_thumb_set, 0 },
2536 { "even", s_even, 0 },
2537 { "ltorg", s_ltorg, 0 },
2538 { "pool", s_ltorg, 0 },
76feaaf3 2539#ifdef OBJ_ELF
b99bd4ef
NC
2540 { "word", s_arm_elf_cons, 4 },
2541 { "long", s_arm_elf_cons, 4 },
b99bd4ef
NC
2542#else
2543 { "word", cons, 4},
2544#endif
2545 { "extend", float_cons, 'x' },
2546 { "ldouble", float_cons, 'x' },
2547 { "packed", float_cons, 'p' },
2548 { 0, 0, 0 }
2549};
2550
03b1477f
RE
2551/* Other internal functions. */
2552static int arm_parse_extension PARAMS ((char *, int *));
2553static int arm_parse_cpu PARAMS ((char *));
2554static int arm_parse_arch PARAMS ((char *));
2555static int arm_parse_fpu PARAMS ((char *));
33a392fb 2556static int arm_parse_float_abi PARAMS ((char *));
7cc69913 2557#ifdef OBJ_ELF
d507cf36 2558static int arm_parse_eabi PARAMS ((char *));
7cc69913 2559#endif
0bbf2aa4 2560#if 0 /* Suppressed - for now. */
5a6c6817
NC
2561#if defined OBJ_COFF || defined OBJ_ELF
2562static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2563#endif
0bbf2aa4 2564#endif
03b1477f 2565
b99bd4ef
NC
2566/* Stuff needed to resolve the label ambiguity
2567 As:
2568 ...
2569 label: <insn>
2570 may differ from:
2571 ...
2572 label:
2573 <insn>
2574*/
2575
2576symbolS * last_label_seen;
b34976b6 2577static int label_is_thumb_function_name = FALSE;
b99bd4ef 2578
3d0c9500 2579/* Literal Pool stuff. */
b99bd4ef
NC
2580
2581#define MAX_LITERAL_POOL_SIZE 1024
2582
3d0c9500
NC
2583/* Literal pool structure. Held on a per-section
2584 and per-sub-section basis. */
2585typedef struct literal_pool
b99bd4ef 2586{
3d0c9500
NC
2587 expressionS literals [MAX_LITERAL_POOL_SIZE];
2588 unsigned int next_free_entry;
2589 unsigned int id;
2590 symbolS * symbol;
2591 segT section;
2592 subsegT sub_section;
61b5f74b 2593 struct literal_pool * next;
3d0c9500 2594} literal_pool;
b99bd4ef 2595
3d0c9500
NC
2596/* Pointer to a linked list of literal pools. */
2597literal_pool * list_of_pools = NULL;
b99bd4ef 2598
3d0c9500
NC
2599static literal_pool * find_literal_pool PARAMS ((void));
2600static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2601
3d0c9500
NC
2602static literal_pool *
2603find_literal_pool ()
2604{
2605 literal_pool * pool;
2606
2607 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2608 {
2609 if (pool->section == now_seg
2610 && pool->sub_section == now_subseg)
2611 break;
2612 }
2613
2614 return pool;
2615}
b99bd4ef 2616
3d0c9500
NC
2617static literal_pool *
2618find_or_make_literal_pool ()
2619{
2620 /* Next literal pool ID number. */
2621 static unsigned int latest_pool_num = 1;
2622 literal_pool * pool;
2623
2624 pool = find_literal_pool ();
b99bd4ef 2625
3d0c9500
NC
2626 if (pool == NULL)
2627 {
2628 /* Create a new pool. */
2629 pool = (literal_pool *) xmalloc (sizeof (* pool));
2630 if (! pool)
2631 return NULL;
2632
2633 pool->next_free_entry = 0;
2634 pool->section = now_seg;
2635 pool->sub_section = now_subseg;
2636 pool->next = list_of_pools;
2637 pool->symbol = NULL;
2638
2639 /* Add it to the list. */
2640 list_of_pools = pool;
2641 }
2642
2643 /* New pools, and emptied pools, will have a NULL symbol. */
2644 if (pool->symbol == NULL)
2645 {
2646 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2647 (valueT) 0, &zero_address_frag);
2648 pool->id = latest_pool_num ++;
2649 }
2650
2651 /* Done. */
2652 return pool;
2653}
2654
2655/* Add the literal in the global 'inst'
2656 structure to the relevent literal pool. */
b99bd4ef
NC
2657static int
2658add_to_lit_pool ()
2659{
61b5f74b 2660 literal_pool * pool;
3d0c9500 2661 unsigned int entry;
b99bd4ef 2662
3d0c9500 2663 pool = find_or_make_literal_pool ();
b99bd4ef 2664
3d0c9500
NC
2665 /* Check if this literal value is already in the pool. */
2666 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2667 {
3d0c9500
NC
2668 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2669 && (inst.reloc.exp.X_op == O_constant)
2670 && (pool->literals[entry].X_add_number
b99bd4ef 2671 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2672 && (pool->literals[entry].X_unsigned
2673 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2674 break;
2675
3d0c9500
NC
2676 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2677 && (inst.reloc.exp.X_op == O_symbol)
2678 && (pool->literals[entry].X_add_number
b99bd4ef 2679 == inst.reloc.exp.X_add_number)
3d0c9500 2680 && (pool->literals[entry].X_add_symbol
b99bd4ef 2681 == inst.reloc.exp.X_add_symbol)
3d0c9500 2682 && (pool->literals[entry].X_op_symbol
b99bd4ef 2683 == inst.reloc.exp.X_op_symbol))
3d0c9500 2684 break;
b99bd4ef
NC
2685 }
2686
3d0c9500
NC
2687 /* Do we need to create a new entry? */
2688 if (entry == pool->next_free_entry)
b99bd4ef 2689 {
3d0c9500 2690 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2691 {
ed71e111 2692 inst.error = _("literal pool overflow");
b99bd4ef
NC
2693 return FAIL;
2694 }
2695
3d0c9500
NC
2696 pool->literals[entry] = inst.reloc.exp;
2697 pool->next_free_entry += 1;
b99bd4ef
NC
2698 }
2699
3d0c9500 2700 inst.reloc.exp.X_op = O_symbol;
08df2379 2701 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2702 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2703
2704 return SUCCESS;
2705}
2706
2707/* Can't use symbol_new here, so have to create a symbol and then at
2708 a later date assign it a value. Thats what these functions do. */
2709
2710static void
2711symbol_locate (symbolP, name, segment, valu, frag)
2712 symbolS * symbolP;
05d2d07e 2713 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2714 segT segment; /* Segment identifier (SEG_<something>). */
2715 valueT valu; /* Symbol value. */
2716 fragS * frag; /* Associated fragment. */
2717{
2718 unsigned int name_length;
2719 char * preserved_copy_of_name;
2720
2721 name_length = strlen (name) + 1; /* +1 for \0. */
2722 obstack_grow (&notes, name, name_length);
2723 preserved_copy_of_name = obstack_finish (&notes);
2724#ifdef STRIP_UNDERSCORE
2725 if (preserved_copy_of_name[0] == '_')
2726 preserved_copy_of_name++;
2727#endif
2728
2729#ifdef tc_canonicalize_symbol_name
2730 preserved_copy_of_name =
2731 tc_canonicalize_symbol_name (preserved_copy_of_name);
2732#endif
2733
2734 S_SET_NAME (symbolP, preserved_copy_of_name);
2735
2736 S_SET_SEGMENT (symbolP, segment);
2737 S_SET_VALUE (symbolP, valu);
c62e1cc3 2738 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2739
2740 symbol_set_frag (symbolP, frag);
2741
2742 /* Link to end of symbol chain. */
2743 {
2744 extern int symbol_table_frozen;
2745 if (symbol_table_frozen)
2746 abort ();
2747 }
2748
2749 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2750
2751 obj_symbol_new_hook (symbolP);
2752
2753#ifdef tc_symbol_new_hook
2754 tc_symbol_new_hook (symbolP);
2755#endif
2756
2757#ifdef DEBUG_SYMS
2758 verify_symbol_chain (symbol_rootP, symbol_lastP);
2759#endif /* DEBUG_SYMS */
2760}
2761
2762/* Check that an immediate is valid.
2763 If so, convert it to the right format. */
2764
2765static unsigned int
2766validate_immediate (val)
2767 unsigned int val;
2768{
2769 unsigned int a;
2770 unsigned int i;
2771
2772#define rotate_left(v, n) (v << n | v >> (32 - n))
2773
2774 for (i = 0; i < 32; i += 2)
2775 if ((a = rotate_left (val, i)) <= 0xff)
2776 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2777
2778 return FAIL;
2779}
2780
2d2255b5 2781/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2782 values, added together. We already know that this value cannot be
2783 computed by just one ARM instruction. */
2784
2785static unsigned int
2786validate_immediate_twopart (val, highpart)
2787 unsigned int val;
2788 unsigned int * highpart;
2789{
2790 unsigned int a;
2791 unsigned int i;
2792
2793 for (i = 0; i < 32; i += 2)
2794 if (((a = rotate_left (val, i)) & 0xff) != 0)
2795 {
2796 if (a & 0xff00)
2797 {
2798 if (a & ~ 0xffff)
2799 continue;
2800 * highpart = (a >> 8) | ((i + 24) << 7);
2801 }
2802 else if (a & 0xff0000)
2803 {
2804 if (a & 0xff000000)
2805 continue;
2806 * highpart = (a >> 16) | ((i + 16) << 7);
2807 }
2808 else
2809 {
2810 assert (a & 0xff000000);
2811 * highpart = (a >> 24) | ((i + 8) << 7);
2812 }
2813
2814 return (a & 0xff) | (i << 7);
2815 }
2816
2817 return FAIL;
2818}
2819
2820static int
2821validate_offset_imm (val, hwse)
2822 unsigned int val;
2823 int hwse;
2824{
2825 if ((hwse && val > 255) || val > 4095)
2826 return FAIL;
2827 return val;
2828}
2829
6057a28f
NC
2830\f
2831#ifdef OBJ_ELF
6057a28f
NC
2832/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2833 (This text is taken from version B-02 of the spec):
2834
2835 4.4.7 Mapping and tagging symbols
2836
2837 A section of an ARM ELF file can contain a mixture of ARM code,
2838 Thumb code, and data. There are inline transitions between code
2839 and data at literal pool boundaries. There can also be inline
2840 transitions between ARM code and Thumb code, for example in
2841 ARM-Thumb inter-working veneers. Linkers, machine-level
2842 debuggers, profiling tools, and disassembly tools need to map
2843 images accurately. For example, setting an ARM breakpoint on a
2844 Thumb location, or in a literal pool, can crash the program
2845 being debugged, ruining the debugging session.
2846
2847 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2848 tagged (see section 4.4.7.2 below) using local symbols (with
2849 binding STB_LOCAL). To assist consumers, mapping and tagging
2850 symbols should be collated first in the symbol table, before
2851 other symbols with binding STB_LOCAL.
2852
2853 To allow properly collated mapping and tagging symbols to be
2854 skipped by consumers that have no interest in them, the first
2855 such symbol should have the name $m and its st_value field equal
2856 to the total number of mapping and tagging symbols (including
2857 the $m) in the symbol table.
2858
2859 4.4.7.1 Mapping symbols
2860
2861 $a Labels the first byte of a sequence of ARM instructions.
2862 Its type is STT_FUNC.
2863
2864 $d Labels the first byte of a sequence of data items.
2865 Its type is STT_OBJECT.
2866
2867 $t Labels the first byte of a sequence of Thumb instructions.
2868 Its type is STT_FUNC.
2869
2870 This list of mapping symbols may be extended in the future.
2871
2872 Section-relative mapping symbols
2873
2874 Mapping symbols defined in a section define a sequence of
2875 half-open address intervals that cover the address range of the
2876 section. Each interval starts at the address defined by a
2877 mapping symbol, and continues up to, but not including, the
2878 address defined by the next (in address order) mapping symbol or
2879 the end of the section. A corollary is that there must be a
2880 mapping symbol defined at the beginning of each section.
2881 Consumers can ignore the size of a section-relative mapping
2882 symbol. Producers can set it to 0.
2883
2884 Absolute mapping symbols
2885
2886 Because of the need to crystallize a Thumb address with the
2887 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2888 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2889 or $t.
2890
2891 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2892 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2893 where [x, y) denotes the half-open address range from x,
2894 inclusive, to y, exclusive.
2895
2896 In the absence of a mapping symbol, a consumer can interpret a
2897 function symbol with an odd value as the Thumb code address
2898 obtained by clearing the least significant bit of the
2899 value. This interpretation is deprecated, and it may not work in
2900 the future.
2901
2902 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2903 the EABI (which is still under development), so they are not
2904 implemented here. */
2905
69b97547
NC
2906static enum mstate mapstate = MAP_UNDEFINED;
2907
6057a28f
NC
2908static void
2909mapping_state (enum mstate state)
2910{
6057a28f
NC
2911 symbolS * symbolP;
2912 const char * symname;
2913 int type;
2914
2915 if (mapstate == state)
2916 /* The mapping symbol has already been emitted.
2917 There is nothing else to do. */
2918 return;
2919
2920 mapstate = state;
2921
2922 switch (state)
2923 {
2924 case MAP_DATA:
2925 symname = "$d";
2926 type = BSF_OBJECT;
2927 break;
2928 case MAP_ARM:
2929 symname = "$a";
2930 type = BSF_FUNCTION;
2931 break;
2932 case MAP_THUMB:
2933 symname = "$t";
2934 type = BSF_FUNCTION;
2935 break;
69b97547
NC
2936 case MAP_UNDEFINED:
2937 return;
6057a28f
NC
2938 default:
2939 abort ();
2940 }
2941
69b97547
NC
2942 seg_info (now_seg)->tc_segment_info_data = state;
2943
6057a28f
NC
2944 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2945 symbol_table_insert (symbolP);
2946 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2947
2948 switch (state)
2949 {
2950 case MAP_ARM:
2951 THUMB_SET_FUNC (symbolP, 0);
2952 ARM_SET_THUMB (symbolP, 0);
2953 ARM_SET_INTERWORK (symbolP, support_interwork);
2954 break;
2955
2956 case MAP_THUMB:
2957 THUMB_SET_FUNC (symbolP, 1);
2958 ARM_SET_THUMB (symbolP, 1);
2959 ARM_SET_INTERWORK (symbolP, support_interwork);
2960 break;
2961
2962 case MAP_DATA:
2963 default:
2964 return;
2965 }
2966}
2967
2968/* When we change sections we need to issue a new mapping symbol. */
2969
9ce887a1 2970void
6057a28f
NC
2971arm_elf_change_section (void)
2972{
2973 flagword flags;
2974
2975 if (!SEG_NORMAL (now_seg))
2976 return;
2977
2978 flags = bfd_get_section_flags (stdoutput, now_seg);
2979
2980 /* We can ignore sections that only contain debug info. */
2981 if ((flags & SEC_ALLOC) == 0)
2982 return;
2983
69b97547 2984 mapstate = seg_info (now_seg)->tc_segment_info_data;
6057a28f
NC
2985}
2986#else
2987#define mapping_state(a)
2988#endif /* OBJ_ELF */
2989\f
2990
b99bd4ef
NC
2991static void
2992s_req (a)
2993 int a ATTRIBUTE_UNUSED;
2994{
f03698e6 2995 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
2996}
2997
0bbf2aa4
NC
2998/* The .unreq directive deletes an alias which was previously defined
2999 by .req. For example:
3000
3001 my_alias .req r11
3002 .unreq my_alias */
3003
3004static void
3005s_unreq (int a ATTRIBUTE_UNUSED)
3006{
3007 char *name;
3008 char saved_char;
3009
3010 skip_whitespace (input_line_pointer);
3011 name = input_line_pointer;
3012
3013 while (*input_line_pointer != 0
3014 && *input_line_pointer != ' '
3015 && *input_line_pointer != '\n')
3016 ++input_line_pointer;
3017
3018 saved_char = *input_line_pointer;
3019 *input_line_pointer = 0;
3020
3021 if (*name)
3022 {
3023 enum arm_reg_type req_type = arm_reg_parse_any (name);
3024
3025 if (req_type != REG_TYPE_MAX)
3026 {
3027 char *temp_name = name;
3028 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3029
3030 if (req_no != FAIL)
3031 {
3032 struct reg_entry *req_entry;
3033
3034 /* Check to see if this alias is a builtin one. */
3035 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3036
3037 if (!req_entry)
3038 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3039 else if (req_entry->builtin)
67c1ffbe 3040 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
3041 points to a const data structure, so we only need to
3042 free up the memory used by the key in the hash table.
3043 Unfortunately we have not recorded this value, so this
3044 is a memory leak. */
3045 /* FIXME: Should we issue a warning message ? */
3046 ;
3047 else
3048 {
67c1ffbe 3049 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
3050 key and the value, but fortunately the key is the same
3051 as the value->name field. */
3052 free ((char *) req_entry->name);
3053 free (req_entry);
3054 }
3055 }
3056 else
3057 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3058 }
3059 else
3060 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3061 }
3062 else
3063 as_bad (_("invalid syntax for .unreq directive"));
3064
3065 *input_line_pointer = saved_char;
3066 demand_empty_rest_of_line ();
3067}
3068
b99bd4ef
NC
3069static void
3070s_bss (ignore)
3071 int ignore ATTRIBUTE_UNUSED;
3072{
3073 /* We don't support putting frags in the BSS segment, we fake it by
3074 marking in_bss, then looking at s_skip for clues. */
3075 subseg_set (bss_section, 0);
3076 demand_empty_rest_of_line ();
6057a28f 3077 mapping_state (MAP_DATA);
b99bd4ef
NC
3078}
3079
3080static void
3081s_even (ignore)
3082 int ignore ATTRIBUTE_UNUSED;
3083{
3084 /* Never make frag if expect extra pass. */
3085 if (!need_pass_2)
3086 frag_align (1, 0, 0);
3087
3088 record_alignment (now_seg, 1);
3089
3090 demand_empty_rest_of_line ();
3091}
3092
3093static void
3094s_ltorg (ignored)
3095 int ignored ATTRIBUTE_UNUSED;
3096{
3d0c9500
NC
3097 unsigned int entry;
3098 literal_pool * pool;
b99bd4ef
NC
3099 char sym_name[20];
3100
3d0c9500
NC
3101 pool = find_literal_pool ();
3102 if (pool == NULL
3103 || pool->symbol == NULL
3104 || pool->next_free_entry == 0)
b99bd4ef
NC
3105 return;
3106
69b97547
NC
3107 mapping_state (MAP_DATA);
3108
b99bd4ef
NC
3109 /* Align pool as you have word accesses.
3110 Only make a frag if we have to. */
3111 if (!need_pass_2)
3112 frag_align (2, 0, 0);
3113
3114 record_alignment (now_seg, 2);
3115
3d0c9500 3116 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3117
3d0c9500 3118 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3119 (valueT) frag_now_fix (), frag_now);
3d0c9500 3120 symbol_table_insert (pool->symbol);
b99bd4ef 3121
3d0c9500 3122 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3123
3124#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3125 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3126#endif
3127
3d0c9500 3128 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3129 /* First output the expression in the instruction to the pool. */
3d0c9500 3130 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3131
3d0c9500
NC
3132 /* Mark the pool as empty. */
3133 pool->next_free_entry = 0;
3134 pool->symbol = NULL;
b99bd4ef
NC
3135}
3136
3137/* Same as s_align_ptwo but align 0 => align 2. */
3138
3139static void
3140s_align (unused)
3141 int unused ATTRIBUTE_UNUSED;
3142{
3143 register int temp;
3144 register long temp_fill;
3145 long max_alignment = 15;
3146
3147 temp = get_absolute_expression ();
3148 if (temp > max_alignment)
f03698e6 3149 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3150 else if (temp < 0)
3151 {
f03698e6 3152 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3153 temp = 0;
3154 }
3155
3156 if (*input_line_pointer == ',')
3157 {
3158 input_line_pointer++;
3159 temp_fill = get_absolute_expression ();
3160 }
3161 else
3162 temp_fill = 0;
3163
3164 if (!temp)
3165 temp = 2;
3166
3167 /* Only make a frag if we HAVE to. */
3168 if (temp && !need_pass_2)
3169 frag_align (temp, (int) temp_fill, 0);
3170 demand_empty_rest_of_line ();
3171
3172 record_alignment (now_seg, temp);
3173}
3174
3175static void
3176s_force_thumb (ignore)
3177 int ignore ATTRIBUTE_UNUSED;
3178{
3179 /* If we are not already in thumb mode go into it, EVEN if
3180 the target processor does not support thumb instructions.
3181 This is used by gcc/config/arm/lib1funcs.asm for example
3182 to compile interworking support functions even if the
3183 target processor should not support interworking. */
3184 if (! thumb_mode)
3185 {
3186 thumb_mode = 2;
3187
3188 record_alignment (now_seg, 1);
3189 }
3190
3191 demand_empty_rest_of_line ();
3192}
3193
3194static void
3195s_thumb_func (ignore)
3196 int ignore ATTRIBUTE_UNUSED;
3197{
3198 if (! thumb_mode)
3199 opcode_select (16);
3200
3201 /* The following label is the name/address of the start of a Thumb function.
3202 We need to know this for the interworking support. */
b34976b6 3203 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3204
3205 demand_empty_rest_of_line ();
3206}
3207
3208/* Perform a .set directive, but also mark the alias as
3209 being a thumb function. */
3210
3211static void
3212s_thumb_set (equiv)
3213 int equiv;
3214{
3215 /* XXX the following is a duplicate of the code for s_set() in read.c
3216 We cannot just call that code as we need to get at the symbol that
3217 is created. */
3218 register char * name;
3219 register char delim;
3220 register char * end_name;
3221 register symbolS * symbolP;
3222
3223 /* Especial apologies for the random logic:
3224 This just grew, and could be parsed much more simply!
3225 Dean - in haste. */
3226 name = input_line_pointer;
3227 delim = get_symbol_end ();
3228 end_name = input_line_pointer;
3229 *end_name = delim;
3230
3231 SKIP_WHITESPACE ();
3232
3233 if (*input_line_pointer != ',')
3234 {
3235 *end_name = 0;
f03698e6 3236 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3237 *end_name = delim;
3238 ignore_rest_of_line ();
3239 return;
3240 }
3241
3242 input_line_pointer++;
3243 *end_name = 0;
3244
3245 if (name[0] == '.' && name[1] == '\0')
3246 {
3247 /* XXX - this should not happen to .thumb_set. */
3248 abort ();
3249 }
3250
3251 if ((symbolP = symbol_find (name)) == NULL
3252 && (symbolP = md_undefined_symbol (name)) == NULL)
3253 {
3254#ifndef NO_LISTING
3255 /* When doing symbol listings, play games with dummy fragments living
3256 outside the normal fragment chain to record the file and line info
3257 for this symbol. */
3258 if (listing & LISTING_SYMBOLS)
3259 {
3260 extern struct list_info_struct * listing_tail;
3261 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3262
3263 memset (dummy_frag, 0, sizeof (fragS));
3264 dummy_frag->fr_type = rs_fill;
3265 dummy_frag->line = listing_tail;
3266 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3267 dummy_frag->fr_symbol = symbolP;
3268 }
3269 else
3270#endif
3271 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3272
3273#ifdef OBJ_COFF
3274 /* "set" symbols are local unless otherwise specified. */
3275 SF_SET_LOCAL (symbolP);
3276#endif /* OBJ_COFF */
3277 } /* Make a new symbol. */
3278
3279 symbol_table_insert (symbolP);
3280
3281 * end_name = delim;
3282
3283 if (equiv
3284 && S_IS_DEFINED (symbolP)
3285 && S_GET_SEGMENT (symbolP) != reg_section)
3286 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3287
3288 pseudo_set (symbolP);
3289
3290 demand_empty_rest_of_line ();
3291
3292 /* XXX Now we come to the Thumb specific bit of code. */
3293
3294 THUMB_SET_FUNC (symbolP, 1);
3295 ARM_SET_THUMB (symbolP, 1);
3296#if defined OBJ_ELF || defined OBJ_COFF
3297 ARM_SET_INTERWORK (symbolP, support_interwork);
3298#endif
3299}
3300
b99bd4ef
NC
3301static void
3302opcode_select (width)
3303 int width;
3304{
3305 switch (width)
3306 {
3307 case 16:
3308 if (! thumb_mode)
3309 {
b89dddec 3310 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3311 as_bad (_("selected processor does not support THUMB opcodes"));
3312
3313 thumb_mode = 1;
3314 /* No need to force the alignment, since we will have been
3315 coming from ARM mode, which is word-aligned. */
3316 record_alignment (now_seg, 1);
3317 }
6057a28f 3318 mapping_state (MAP_THUMB);
b99bd4ef
NC
3319 break;
3320
3321 case 32:
3322 if (thumb_mode)
3323 {
03b1477f 3324 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3325 as_bad (_("selected processor does not support ARM opcodes"));
3326
3327 thumb_mode = 0;
3328
3329 if (!need_pass_2)
cc8a6dd0 3330 frag_align (2, 0, 0);
b99bd4ef 3331
cc8a6dd0 3332 record_alignment (now_seg, 1);
b99bd4ef 3333 }
6057a28f 3334 mapping_state (MAP_ARM);
b99bd4ef
NC
3335 break;
3336
3337 default:
3338 as_bad (_("invalid instruction size selected (%d)"), width);
3339 }
3340}
3341
3342static void
3343s_arm (ignore)
3344 int ignore ATTRIBUTE_UNUSED;
3345{
3346 opcode_select (32);
3347 demand_empty_rest_of_line ();
3348}
3349
3350static void
3351s_thumb (ignore)
3352 int ignore ATTRIBUTE_UNUSED;
3353{
3354 opcode_select (16);
3355 demand_empty_rest_of_line ();
3356}
3357
3358static void
3359s_code (unused)
3360 int unused ATTRIBUTE_UNUSED;
3361{
3362 register int temp;
3363
3364 temp = get_absolute_expression ();
3365 switch (temp)
3366 {
3367 case 16:
3368 case 32:
3369 opcode_select (temp);
3370 break;
3371
3372 default:
3373 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3374 }
3375}
3376
3377static void
3378end_of_line (str)
f03698e6 3379 char *str;
b99bd4ef
NC
3380{
3381 skip_whitespace (str);
3382
f03698e6
RE
3383 if (*str != '\0' && !inst.error)
3384 inst.error = _("garbage following instruction");
b99bd4ef
NC
3385}
3386
3387static int
3388skip_past_comma (str)
3389 char ** str;
3390{
3391 char * p = * str, c;
3392 int comma = 0;
3393
3394 while ((c = *p) == ' ' || c == ',')
3395 {
3396 p++;
3397 if (c == ',' && comma++)
3398 return FAIL;
3399 }
3400
3401 if (c == '\0')
3402 return FAIL;
3403
3404 *str = p;
3405 return comma ? SUCCESS : FAIL;
3406}
3407
3408/* A standard register must be given at this point.
3409 SHIFT is the place to put it in inst.instruction.
3410 Restores input start point on error.
3411 Returns the reg#, or FAIL. */
3412
3413static int
3414reg_required_here (str, shift)
3415 char ** str;
3416 int shift;
3417{
3418 static char buff [128]; /* XXX */
3419 int reg;
3420 char * start = * str;
3421
6c43fab6 3422 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3423 {
3424 if (shift >= 0)
3425 inst.instruction |= reg << shift;
3426 return reg;
3427 }
3428
3429 /* Restore the start point, we may have got a reg of the wrong class. */
3430 *str = start;
3431
3432 /* In the few cases where we might be able to accept something else
3433 this error can be overridden. */
f03698e6 3434 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3435 inst.error = buff;
3436
3437 return FAIL;
3438}
3439
5a6c6817 3440/* A Intel Wireless MMX technology register
e16bb312
NC
3441 must be given at this point.
3442 Shift is the place to put it in inst.instruction.
3443 Restores input start point on err.
3444 Returns the reg#, or FAIL. */
3445
3446static int
3447wreg_required_here (str, shift, reg_type)
3448 char ** str;
3449 int shift;
3450 enum wreg_type reg_type;
3451{
3452 static char buff [128];
3453 int reg;
3454 char * start = *str;
3455
3456 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3457 {
3458 if (wr_register (reg)
3459 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3460 {
3461 if (shift >= 0)
3462 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3463 return reg;
3464 }
3465 else if (wc_register (reg)
3466 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3467 {
3468 if (shift >= 0)
3469 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3470 return reg;
3471 }
3472 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3473 {
3474 if (shift >= 0)
3475 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3476 return reg;
3477 }
3478 }
3479
3480 /* Restore the start point, we may have got a reg of the wrong class. */
3481 *str = start;
3482
3483 /* In the few cases where we might be able to accept
3484 something else this error can be overridden. */
5a6c6817 3485 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3486 inst.error = buff;
3487
3488 return FAIL;
3489}
3490
05d2d07e 3491static const struct asm_psr *
b99bd4ef
NC
3492arm_psr_parse (ccp)
3493 register char ** ccp;
3494{
3495 char * start = * ccp;
3496 char c;
3497 char * p;
05d2d07e 3498 const struct asm_psr * psr;
b99bd4ef
NC
3499
3500 p = start;
3501
3502 /* Skip to the end of the next word in the input stream. */
3503 do
3504 {
3505 c = *p++;
3506 }
3882b010 3507 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3508
3509 /* Terminate the word. */
3510 *--p = 0;
3511
3512 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3513 feature for ease of use and backwards compatibility. */
3514 if (!strncmp (start, "cpsr", 4))
3515 strncpy (start, "CPSR", 4);
3516 else if (!strncmp (start, "spsr", 4))
3517 strncpy (start, "SPSR", 4);
3518
3519 /* Now locate the word in the psr hash table. */
05d2d07e 3520 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3521
3522 /* Restore the input stream. */
3523 *p = c;
3524
3525 /* If we found a valid match, advance the
3526 stream pointer past the end of the word. */
3527 *ccp = p;
3528
3529 return psr;
3530}
3531
3532/* Parse the input looking for a PSR flag. */
3533
3534static int
3535psr_required_here (str)
3536 char ** str;
3537{
3538 char * start = * str;
05d2d07e 3539 const struct asm_psr * psr;
b99bd4ef
NC
3540
3541 psr = arm_psr_parse (str);
3542
3543 if (psr)
3544 {
3545 /* If this is the SPSR that is being modified, set the R bit. */
3546 if (! psr->cpsr)
3547 inst.instruction |= SPSR_BIT;
3548
3549 /* Set the psr flags in the MSR instruction. */
3550 inst.instruction |= psr->field << PSR_SHIFT;
3551
3552 return SUCCESS;
3553 }
3554
3555 /* In the few cases where we might be able to accept
3556 something else this error can be overridden. */
3557 inst.error = _("flag for {c}psr instruction expected");
3558
3559 /* Restore the start point. */
3560 *str = start;
3561 return FAIL;
3562}
3563
3564static int
3565co_proc_number (str)
6c43fab6 3566 char **str;
b99bd4ef
NC
3567{
3568 int processor, pchar;
6c43fab6 3569 char *start;
b99bd4ef 3570
6c43fab6
RE
3571 skip_whitespace (*str);
3572 start = *str;
b99bd4ef
NC
3573
3574 /* The data sheet seems to imply that just a number on its own is valid
3575 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3576 accept either. */
6c43fab6
RE
3577 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3578 == FAIL)
b99bd4ef 3579 {
6c43fab6
RE
3580 *str = start;
3581
3582 pchar = *(*str)++;
3583 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3584 {
6c43fab6
RE
3585 processor = pchar - '0';
3586 if (**str >= '0' && **str <= '9')
b99bd4ef 3587 {
6c43fab6
RE
3588 processor = processor * 10 + *(*str)++ - '0';
3589 if (processor > 15)
3590 {
f03698e6 3591 inst.error = _("illegal co-processor number");
6c43fab6
RE
3592 return FAIL;
3593 }
b99bd4ef
NC
3594 }
3595 }
6c43fab6
RE
3596 else
3597 {
f03698e6 3598 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
3599 return FAIL;
3600 }
b99bd4ef
NC
3601 }
3602
3603 inst.instruction |= processor << 8;
3604 return SUCCESS;
3605}
3606
3607static int
3608cp_opc_expr (str, where, length)
3609 char ** str;
3610 int where;
3611 int length;
3612{
3613 expressionS expr;
3614
3615 skip_whitespace (* str);
3616
3617 memset (&expr, '\0', sizeof (expr));
3618
3619 if (my_get_expression (&expr, str))
3620 return FAIL;
3621 if (expr.X_op != O_constant)
3622 {
3623 inst.error = _("bad or missing expression");
3624 return FAIL;
3625 }
3626
3627 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3628 {
3629 inst.error = _("immediate co-processor expression too large");
3630 return FAIL;
3631 }
3632
3633 inst.instruction |= expr.X_add_number << where;
3634 return SUCCESS;
3635}
3636
3637static int
3638cp_reg_required_here (str, where)
3639 char ** str;
3640 int where;
3641{
3642 int reg;
3643 char * start = *str;
3644
6c43fab6 3645 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3646 {
b99bd4ef
NC
3647 inst.instruction |= reg << where;
3648 return reg;
3649 }
3650
3651 /* In the few cases where we might be able to accept something else
3652 this error can be overridden. */
f03698e6 3653 inst.error = _("co-processor register expected");
b99bd4ef
NC
3654
3655 /* Restore the start point. */
3656 *str = start;
3657 return FAIL;
3658}
3659
3660static int
3661fp_reg_required_here (str, where)
3662 char ** str;
3663 int where;
3664{
3665 int reg;
3666 char * start = * str;
3667
6c43fab6 3668 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3669 {
b99bd4ef
NC
3670 inst.instruction |= reg << where;
3671 return reg;
3672 }
3673
3674 /* In the few cases where we might be able to accept something else
3675 this error can be overridden. */
f03698e6 3676 inst.error = _("floating point register expected");
b99bd4ef
NC
3677
3678 /* Restore the start point. */
3679 *str = start;
3680 return FAIL;
3681}
3682
3683static int
3684cp_address_offset (str)
3685 char ** str;
3686{
3687 int offset;
3688
3689 skip_whitespace (* str);
3690
3691 if (! is_immediate_prefix (**str))
3692 {
3693 inst.error = _("immediate expression expected");
3694 return FAIL;
3695 }
3696
3697 (*str)++;
3698
3699 if (my_get_expression (& inst.reloc.exp, str))
3700 return FAIL;
3701
3702 if (inst.reloc.exp.X_op == O_constant)
3703 {
3704 offset = inst.reloc.exp.X_add_number;
3705
3706 if (offset & 3)
3707 {
3708 inst.error = _("co-processor address must be word aligned");
3709 return FAIL;
3710 }
3711
3712 if (offset > 1023 || offset < -1023)
3713 {
3714 inst.error = _("offset too large");
3715 return FAIL;
3716 }
3717
3718 if (offset >= 0)
3719 inst.instruction |= INDEX_UP;
3720 else
3721 offset = -offset;
3722
3723 inst.instruction |= offset >> 2;
3724 }
3725 else
3726 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3727
3728 return SUCCESS;
3729}
3730
3731static int
bfae80f2 3732cp_address_required_here (str, wb_ok)
b99bd4ef 3733 char ** str;
bfae80f2 3734 int wb_ok;
b99bd4ef
NC
3735{
3736 char * p = * str;
3737 int pre_inc = 0;
3738 int write_back = 0;
3739
3740 if (*p == '[')
3741 {
3742 int reg;
3743
3744 p++;
3745 skip_whitespace (p);
3746
3747 if ((reg = reg_required_here (& p, 16)) == FAIL)
3748 return FAIL;
3749
3750 skip_whitespace (p);
3751
3752 if (*p == ']')
3753 {
3754 p++;
3755
f02232aa
NC
3756 skip_whitespace (p);
3757
3758 if (*p == '\0')
b99bd4ef 3759 {
f02232aa
NC
3760 /* As an extension to the official ARM syntax we allow:
3761
3762 [Rn]
3763
3764 as a short hand for:
3765
3766 [Rn,#0] */
3767 inst.instruction |= PRE_INDEX | INDEX_UP;
3768 *str = p;
3769 return SUCCESS;
3770 }
3771
3772 if (skip_past_comma (& p) == FAIL)
3773 {
3774 inst.error = _("comma expected after closing square bracket");
3775 return FAIL;
3776 }
b99bd4ef 3777
f02232aa
NC
3778 skip_whitespace (p);
3779
3780 if (*p == '#')
3781 {
3782 if (wb_ok)
b99bd4ef 3783 {
f02232aa
NC
3784 /* [Rn], #expr */
3785 write_back = WRITE_BACK;
3786
3787 if (reg == REG_PC)
3788 {
3789 inst.error = _("pc may not be used in post-increment");
3790 return FAIL;
3791 }
3792
3793 if (cp_address_offset (& p) == FAIL)
3794 return FAIL;
b99bd4ef 3795 }
f02232aa
NC
3796 else
3797 pre_inc = PRE_INDEX | INDEX_UP;
3798 }
3799 else if (*p == '{')
3800 {
3801 int option;
b99bd4ef 3802
f02232aa
NC
3803 /* [Rn], {<expr>} */
3804 p++;
3805
3806 skip_whitespace (p);
3807
3808 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3809 return FAIL;
f02232aa
NC
3810
3811 if (inst.reloc.exp.X_op == O_constant)
3812 {
3813 option = inst.reloc.exp.X_add_number;
3814
3815 if (option > 255 || option < 0)
3816 {
3817 inst.error = _("'option' field too large");
3818 return FAIL;
3819 }
3820
3821 skip_whitespace (p);
3822
3823 if (*p != '}')
3824 {
3825 inst.error = _("'}' expected at end of 'option' field");
3826 return FAIL;
3827 }
3828 else
3829 {
3830 p++;
3831 inst.instruction |= option;
3832 inst.instruction |= INDEX_UP;
3833 }
3834 }
3835 else
3836 {
3837 inst.error = _("non-constant expressions for 'option' field not supported");
3838 return FAIL;
3839 }
b99bd4ef
NC
3840 }
3841 else
f02232aa
NC
3842 {
3843 inst.error = _("# or { expected after comma");
3844 return FAIL;
3845 }
b99bd4ef
NC
3846 }
3847 else
3848 {
3849 /* '['Rn, #expr']'[!] */
3850
3851 if (skip_past_comma (& p) == FAIL)
3852 {
3853 inst.error = _("pre-indexed expression expected");
3854 return FAIL;
3855 }
3856
3857 pre_inc = PRE_INDEX;
3858
3859 if (cp_address_offset (& p) == FAIL)
3860 return FAIL;
3861
3862 skip_whitespace (p);
3863
3864 if (*p++ != ']')
3865 {
3866 inst.error = _("missing ]");
3867 return FAIL;
3868 }
3869
3870 skip_whitespace (p);
3871
bfae80f2 3872 if (wb_ok && *p == '!')
b99bd4ef
NC
3873 {
3874 if (reg == REG_PC)
3875 {
3876 inst.error = _("pc may not be used with write-back");
3877 return FAIL;
3878 }
3879
3880 p++;
3881 write_back = WRITE_BACK;
3882 }
3883 }
3884 }
3885 else
3886 {
3887 if (my_get_expression (&inst.reloc.exp, &p))
3888 return FAIL;
3889
3890 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3891 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3892 inst.reloc.pc_rel = 1;
3893 inst.instruction |= (REG_PC << 16);
3894 pre_inc = PRE_INDEX;
3895 }
3896
3897 inst.instruction |= write_back | pre_inc;
3898 *str = p;
3899 return SUCCESS;
3900}
3901
e16bb312
NC
3902static int
3903cp_byte_address_offset (str)
3904 char ** str;
3905{
3906 int offset;
3907
3908 skip_whitespace (* str);
3909
3910 if (! is_immediate_prefix (**str))
3911 {
3912 inst.error = _("immediate expression expected");
3913 return FAIL;
3914 }
3915
3916 (*str)++;
3917
3918 if (my_get_expression (& inst.reloc.exp, str))
3919 return FAIL;
3920
3921 if (inst.reloc.exp.X_op == O_constant)
3922 {
3923 offset = inst.reloc.exp.X_add_number;
3924
3925 if (offset > 255 || offset < -255)
3926 {
3927 inst.error = _("offset too large");
3928 return FAIL;
3929 }
3930
3931 if (offset >= 0)
3932 inst.instruction |= INDEX_UP;
3933 else
3934 offset = -offset;
3935
3936 inst.instruction |= offset;
3937 }
3938 else
3939 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3940
3941 return SUCCESS;
3942}
3943
3944static int
3945cp_byte_address_required_here (str)
3946 char ** str;
3947{
3948 char * p = * str;
3949 int pre_inc = 0;
3950 int write_back = 0;
3951
3952 if (*p == '[')
3953 {
3954 int reg;
3955
3956 p++;
3957 skip_whitespace (p);
3958
3959 if ((reg = reg_required_here (& p, 16)) == FAIL)
3960 return FAIL;
3961
3962 skip_whitespace (p);
3963
3964 if (*p == ']')
3965 {
3966 p++;
3967
3968 if (skip_past_comma (& p) == SUCCESS)
3969 {
3970 /* [Rn], #expr */
3971 write_back = WRITE_BACK;
3972
3973 if (reg == REG_PC)
3974 {
3975 inst.error = _("pc may not be used in post-increment");
3976 return FAIL;
3977 }
3978
3979 if (cp_byte_address_offset (& p) == FAIL)
3980 return FAIL;
3981 }
3982 else
3983 pre_inc = PRE_INDEX | INDEX_UP;
3984 }
3985 else
3986 {
3987 /* '['Rn, #expr']'[!] */
3988
3989 if (skip_past_comma (& p) == FAIL)
3990 {
3991 inst.error = _("pre-indexed expression expected");
3992 return FAIL;
3993 }
3994
3995 pre_inc = PRE_INDEX;
3996
3997 if (cp_byte_address_offset (& p) == FAIL)
3998 return FAIL;
3999
4000 skip_whitespace (p);
4001
4002 if (*p++ != ']')
4003 {
4004 inst.error = _("missing ]");
4005 return FAIL;
4006 }
4007
4008 skip_whitespace (p);
4009
4010 if (*p == '!')
4011 {
4012 if (reg == REG_PC)
4013 {
4014 inst.error = _("pc may not be used with write-back");
4015 return FAIL;
4016 }
4017
4018 p++;
4019 write_back = WRITE_BACK;
4020 }
4021 }
4022 }
4023 else
4024 {
4025 if (my_get_expression (&inst.reloc.exp, &p))
4026 return FAIL;
4027
4028 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4029 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4030 inst.reloc.pc_rel = 1;
4031 inst.instruction |= (REG_PC << 16);
4032 pre_inc = PRE_INDEX;
4033 }
4034
4035 inst.instruction |= write_back | pre_inc;
4036 *str = p;
4037 return SUCCESS;
4038}
4039
b99bd4ef 4040static void
f2b7cb0a 4041do_empty (str)
b99bd4ef 4042 char * str;
b99bd4ef
NC
4043{
4044 /* Do nothing really. */
b99bd4ef 4045 end_of_line (str);
b99bd4ef
NC
4046}
4047
4048static void
f2b7cb0a 4049do_mrs (str)
b99bd4ef 4050 char *str;
b99bd4ef
NC
4051{
4052 int skip = 0;
4053
4054 /* Only one syntax. */
4055 skip_whitespace (str);
4056
4057 if (reg_required_here (&str, 12) == FAIL)
4058 {
4059 inst.error = BAD_ARGS;
4060 return;
4061 }
4062
4063 if (skip_past_comma (&str) == FAIL)
4064 {
4065 inst.error = _("comma expected after register name");
4066 return;
4067 }
4068
4069 skip_whitespace (str);
4070
4071 if ( strcmp (str, "CPSR") == 0
4072 || strcmp (str, "SPSR") == 0
2d2255b5 4073 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4074 || strcmp (str, "cpsr") == 0
4075 || strcmp (str, "spsr") == 0)
4076 skip = 4;
4077
2d2255b5 4078 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4079 else if ( strcmp (str, "cpsr_all") == 0
4080 || strcmp (str, "spsr_all") == 0)
4081 skip = 8;
4082 else
4083 {
f03698e6 4084 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4085 return;
4086 }
4087
4088 if (* str == 's' || * str == 'S')
4089 inst.instruction |= SPSR_BIT;
4090 str += skip;
4091
b99bd4ef
NC
4092 end_of_line (str);
4093}
4094
4095/* Two possible forms:
4096 "{C|S}PSR_<field>, Rm",
4097 "{C|S}PSR_f, #expression". */
4098
4099static void
f2b7cb0a 4100do_msr (str)
b99bd4ef 4101 char * str;
b99bd4ef
NC
4102{
4103 skip_whitespace (str);
4104
4105 if (psr_required_here (& str) == FAIL)
4106 return;
4107
4108 if (skip_past_comma (& str) == FAIL)
4109 {
4110 inst.error = _("comma missing after psr flags");
4111 return;
4112 }
4113
4114 skip_whitespace (str);
4115
4116 if (reg_required_here (& str, 0) != FAIL)
4117 {
4118 inst.error = NULL;
b99bd4ef
NC
4119 end_of_line (str);
4120 return;
4121 }
4122
4123 if (! is_immediate_prefix (* str))
4124 {
4125 inst.error =
4126 _("only a register or immediate value can follow a psr flag");
4127 return;
4128 }
4129
4130 str ++;
4131 inst.error = NULL;
4132
4133 if (my_get_expression (& inst.reloc.exp, & str))
4134 {
4135 inst.error =
4136 _("only a register or immediate value can follow a psr flag");
4137 return;
4138 }
4139
4140#if 0 /* The first edition of the ARM architecture manual stated that
4141 writing anything other than the flags with an immediate operation
4142 had UNPREDICTABLE effects. This constraint was removed in the
4143 second edition of the specification. */
4144 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4145 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4146 {
4147 inst.error = _("immediate value cannot be used to set this field");
4148 return;
4149 }
4150#endif
4151
f2b7cb0a 4152 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4153
4154 if (inst.reloc.exp.X_add_symbol)
4155 {
4156 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4157 inst.reloc.pc_rel = 0;
4158 }
4159 else
4160 {
4161 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4162
4163 if (value == (unsigned) FAIL)
4164 {
f03698e6 4165 inst.error = _("invalid constant");
b99bd4ef
NC
4166 return;
4167 }
4168
4169 inst.instruction |= value;
4170 }
4171
4172 inst.error = NULL;
b99bd4ef
NC
4173 end_of_line (str);
4174}
4175
4176/* Long Multiply Parser
4177 UMULL RdLo, RdHi, Rm, Rs
4178 SMULL RdLo, RdHi, Rm, Rs
4179 UMLAL RdLo, RdHi, Rm, Rs
4180 SMLAL RdLo, RdHi, Rm, Rs. */
4181
4182static void
f2b7cb0a 4183do_mull (str)
b99bd4ef 4184 char * str;
b99bd4ef
NC
4185{
4186 int rdlo, rdhi, rm, rs;
4187
4188 /* Only one format "rdlo, rdhi, rm, rs". */
4189 skip_whitespace (str);
4190
4191 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4192 {
4193 inst.error = BAD_ARGS;
4194 return;
4195 }
4196
4197 if (skip_past_comma (&str) == FAIL
4198 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4199 {
4200 inst.error = BAD_ARGS;
4201 return;
4202 }
4203
4204 if (skip_past_comma (&str) == FAIL
4205 || (rm = reg_required_here (&str, 0)) == FAIL)
4206 {
4207 inst.error = BAD_ARGS;
4208 return;
4209 }
4210
4211 /* rdhi, rdlo and rm must all be different. */
4212 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4213 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4214
4215 if (skip_past_comma (&str) == FAIL
4216 || (rs = reg_required_here (&str, 8)) == FAIL)
4217 {
4218 inst.error = BAD_ARGS;
4219 return;
4220 }
4221
4222 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4223 {
4224 inst.error = BAD_PC;
4225 return;
4226 }
4227
b99bd4ef 4228 end_of_line (str);
b99bd4ef
NC
4229}
4230
4231static void
f2b7cb0a 4232do_mul (str)
b99bd4ef 4233 char * str;
b99bd4ef
NC
4234{
4235 int rd, rm;
4236
4237 /* Only one format "rd, rm, rs". */
4238 skip_whitespace (str);
4239
4240 if ((rd = reg_required_here (&str, 16)) == FAIL)
4241 {
4242 inst.error = BAD_ARGS;
4243 return;
4244 }
4245
4246 if (rd == REG_PC)
4247 {
4248 inst.error = BAD_PC;
4249 return;
4250 }
4251
4252 if (skip_past_comma (&str) == FAIL
4253 || (rm = reg_required_here (&str, 0)) == FAIL)
4254 {
4255 inst.error = BAD_ARGS;
4256 return;
4257 }
4258
4259 if (rm == REG_PC)
4260 {
4261 inst.error = BAD_PC;
4262 return;
4263 }
4264
4265 if (rm == rd)
4266 as_tsktsk (_("rd and rm should be different in mul"));
4267
4268 if (skip_past_comma (&str) == FAIL
4269 || (rm = reg_required_here (&str, 8)) == FAIL)
4270 {
4271 inst.error = BAD_ARGS;
4272 return;
4273 }
4274
4275 if (rm == REG_PC)
4276 {
4277 inst.error = BAD_PC;
4278 return;
4279 }
4280
b99bd4ef 4281 end_of_line (str);
b99bd4ef
NC
4282}
4283
4284static void
f2b7cb0a 4285do_mla (str)
b99bd4ef 4286 char * str;
b99bd4ef
NC
4287{
4288 int rd, rm;
4289
4290 /* Only one format "rd, rm, rs, rn". */
4291 skip_whitespace (str);
4292
4293 if ((rd = reg_required_here (&str, 16)) == FAIL)
4294 {
4295 inst.error = BAD_ARGS;
4296 return;
4297 }
4298
4299 if (rd == REG_PC)
4300 {
4301 inst.error = BAD_PC;
4302 return;
4303 }
4304
4305 if (skip_past_comma (&str) == FAIL
4306 || (rm = reg_required_here (&str, 0)) == FAIL)
4307 {
4308 inst.error = BAD_ARGS;
4309 return;
4310 }
4311
4312 if (rm == REG_PC)
4313 {
4314 inst.error = BAD_PC;
4315 return;
4316 }
4317
4318 if (rm == rd)
4319 as_tsktsk (_("rd and rm should be different in mla"));
4320
4321 if (skip_past_comma (&str) == FAIL
4322 || (rd = reg_required_here (&str, 8)) == FAIL
4323 || skip_past_comma (&str) == FAIL
4324 || (rm = reg_required_here (&str, 12)) == FAIL)
4325 {
4326 inst.error = BAD_ARGS;
4327 return;
4328 }
4329
4330 if (rd == REG_PC || rm == REG_PC)
4331 {
4332 inst.error = BAD_PC;
4333 return;
4334 }
4335
b99bd4ef 4336 end_of_line (str);
b99bd4ef
NC
4337}
4338
4339/* Expects *str -> the characters "acc0", possibly with leading blanks.
4340 Advances *str to the next non-alphanumeric.
4341 Returns 0, or else FAIL (in which case sets inst.error).
4342
4343 (In a future XScale, there may be accumulators other than zero.
4344 At that time this routine and its callers can be upgraded to suit.) */
4345
4346static int
4347accum0_required_here (str)
4348 char ** str;
4349{
4350 static char buff [128]; /* Note the address is taken. Hence, static. */
4351 char * p = * str;
4352 char c;
4353 int result = 0; /* The accum number. */
4354
4355 skip_whitespace (p);
4356
4357 *str = p; /* Advance caller's string pointer too. */
4358 c = *p++;
3882b010 4359 while (ISALNUM (c))
b99bd4ef
NC
4360 c = *p++;
4361
4362 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4363
4364 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4365 {
4366 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4367 inst.error = buff;
4368 result = FAIL;
4369 }
4370
4371 *p = c; /* Unzap. */
4372 *str = p; /* Caller's string pointer to after match. */
4373 return result;
4374}
4375
4376/* Expects **str -> after a comma. May be leading blanks.
4377 Advances *str, recognizing a load mode, and setting inst.instruction.
4378 Returns rn, or else FAIL (in which case may set inst.error
4379 and not advance str)
4380
4381 Note: doesn't know Rd, so no err checks that require such knowledge. */
4382
4383static int
4384ld_mode_required_here (string)
4385 char ** string;
4386{
4387 char * str = * string;
4388 int rn;
4389 int pre_inc = 0;
4390
4391 skip_whitespace (str);
4392
4393 if (* str == '[')
4394 {
4395 str++;
4396
4397 skip_whitespace (str);
4398
4399 if ((rn = reg_required_here (& str, 16)) == FAIL)
4400 return FAIL;
4401
4402 skip_whitespace (str);
4403
4404 if (* str == ']')
4405 {
4406 str ++;
4407
4408 if (skip_past_comma (& str) == SUCCESS)
4409 {
4410 /* [Rn],... (post inc) */
90e4755a 4411 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4412 return FAIL;
4413 }
4414 else /* [Rn] */
4415 {
cc8a6dd0 4416 skip_whitespace (str);
b99bd4ef 4417
cc8a6dd0
KH
4418 if (* str == '!')
4419 {
4420 str ++;
4421 inst.instruction |= WRITE_BACK;
4422 }
b99bd4ef
NC
4423
4424 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4425 pre_inc = 1;
4426 }
4427 }
4428 else /* [Rn,...] */
4429 {
4430 if (skip_past_comma (& str) == FAIL)
4431 {
4432 inst.error = _("pre-indexed expression expected");
4433 return FAIL;
4434 }
4435
4436 pre_inc = 1;
4437
90e4755a 4438 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4439 return FAIL;
4440
4441 skip_whitespace (str);
4442
4443 if (* str ++ != ']')
4444 {
4445 inst.error = _("missing ]");
4446 return FAIL;
4447 }
4448
4449 skip_whitespace (str);
4450
4451 if (* str == '!')
4452 {
4453 str ++;
4454 inst.instruction |= WRITE_BACK;
4455 }
4456 }
4457 }
4458 else if (* str == '=') /* ldr's "r,=label" syntax */
4459 /* We should never reach here, because <text> = <expression> is
4460 caught gas/read.c read_a_source_file() as a .set operation. */
4461 return FAIL;
4462 else /* PC +- 8 bit immediate offset. */
4463 {
4464 if (my_get_expression (& inst.reloc.exp, & str))
4465 return FAIL;
4466
4467 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4468 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4469 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4470 inst.reloc.pc_rel = 1;
4471 inst.instruction |= (REG_PC << 16);
4472
4473 rn = REG_PC;
4474 pre_inc = 1;
4475 }
4476
4477 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4478 * string = str;
4479
4480 return rn;
4481}
4482
4483/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4484 SMLAxy{cond} Rd,Rm,Rs,Rn
4485 SMLAWy{cond} Rd,Rm,Rs,Rn
4486 Error if any register is R15. */
4487
4488static void
f2b7cb0a 4489do_smla (str)
b99bd4ef 4490 char * str;
b99bd4ef
NC
4491{
4492 int rd, rm, rs, rn;
4493
4494 skip_whitespace (str);
4495
4496 if ((rd = reg_required_here (& str, 16)) == FAIL
4497 || skip_past_comma (& str) == FAIL
4498 || (rm = reg_required_here (& str, 0)) == FAIL
4499 || skip_past_comma (& str) == FAIL
4500 || (rs = reg_required_here (& str, 8)) == FAIL
4501 || skip_past_comma (& str) == FAIL
4502 || (rn = reg_required_here (& str, 12)) == FAIL)
4503 inst.error = BAD_ARGS;
4504
4505 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4506 inst.error = BAD_PC;
4507
b99bd4ef
NC
4508 else
4509 end_of_line (str);
4510}
4511
4512/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4513 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4514 Error if any register is R15.
4515 Warning if Rdlo == Rdhi. */
4516
4517static void
f2b7cb0a 4518do_smlal (str)
b99bd4ef 4519 char * str;
b99bd4ef
NC
4520{
4521 int rdlo, rdhi, rm, rs;
4522
4523 skip_whitespace (str);
4524
4525 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4526 || skip_past_comma (& str) == FAIL
4527 || (rdhi = reg_required_here (& str, 16)) == FAIL
4528 || skip_past_comma (& str) == FAIL
4529 || (rm = reg_required_here (& str, 0)) == FAIL
4530 || skip_past_comma (& str) == FAIL
4531 || (rs = reg_required_here (& str, 8)) == FAIL)
4532 {
4533 inst.error = BAD_ARGS;
4534 return;
4535 }
4536
4537 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4538 {
4539 inst.error = BAD_PC;
4540 return;
4541 }
4542
4543 if (rdlo == rdhi)
4544 as_tsktsk (_("rdhi and rdlo must be different"));
4545
f2b7cb0a 4546 end_of_line (str);
b99bd4ef
NC
4547}
4548
4549/* ARM V5E (El Segundo) signed-multiply (argument parse)
4550 SMULxy{cond} Rd,Rm,Rs
4551 Error if any register is R15. */
4552
4553static void
f2b7cb0a 4554do_smul (str)
b99bd4ef 4555 char * str;
b99bd4ef
NC
4556{
4557 int rd, rm, rs;
4558
4559 skip_whitespace (str);
4560
4561 if ((rd = reg_required_here (& str, 16)) == FAIL
4562 || skip_past_comma (& str) == FAIL
4563 || (rm = reg_required_here (& str, 0)) == FAIL
4564 || skip_past_comma (& str) == FAIL
4565 || (rs = reg_required_here (& str, 8)) == FAIL)
4566 inst.error = BAD_ARGS;
4567
4568 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4569 inst.error = BAD_PC;
4570
b99bd4ef
NC
4571 else
4572 end_of_line (str);
4573}
4574
4575/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4576 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4577 Error if any register is R15. */
4578
4579static void
f2b7cb0a 4580do_qadd (str)
b99bd4ef 4581 char * str;
b99bd4ef
NC
4582{
4583 int rd, rm, rn;
4584
4585 skip_whitespace (str);
4586
4587 if ((rd = reg_required_here (& str, 12)) == FAIL
4588 || skip_past_comma (& str) == FAIL
4589 || (rm = reg_required_here (& str, 0)) == FAIL
4590 || skip_past_comma (& str) == FAIL
4591 || (rn = reg_required_here (& str, 16)) == FAIL)
4592 inst.error = BAD_ARGS;
4593
4594 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4595 inst.error = BAD_PC;
4596
b99bd4ef
NC
4597 else
4598 end_of_line (str);
4599}
4600
4601/* ARM V5E (el Segundo)
4602 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4603 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4604
4605 These are equivalent to the XScale instructions MAR and MRA,
4606 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4607
4608 Result unpredicatable if Rd or Rn is R15. */
4609
4610static void
f2b7cb0a 4611do_co_reg2c (str)
b99bd4ef 4612 char * str;
b99bd4ef
NC
4613{
4614 int rd, rn;
4615
4616 skip_whitespace (str);
4617
4618 if (co_proc_number (& str) == FAIL)
4619 {
4620 if (!inst.error)
4621 inst.error = BAD_ARGS;
4622 return;
4623 }
4624
4625 if (skip_past_comma (& str) == FAIL
4626 || cp_opc_expr (& str, 4, 4) == FAIL)
4627 {
4628 if (!inst.error)
4629 inst.error = BAD_ARGS;
4630 return;
4631 }
4632
4633 if (skip_past_comma (& str) == FAIL
4634 || (rd = reg_required_here (& str, 12)) == FAIL)
4635 {
4636 if (!inst.error)
4637 inst.error = BAD_ARGS;
4638 return;
4639 }
4640
4641 if (skip_past_comma (& str) == FAIL
4642 || (rn = reg_required_here (& str, 16)) == FAIL)
4643 {
4644 if (!inst.error)
4645 inst.error = BAD_ARGS;
4646 return;
4647 }
4648
09d92015
MM
4649 /* Unpredictable result if rd or rn is R15. */
4650 if (rd == REG_PC || rn == REG_PC)
4651 as_tsktsk
4652 (_("Warning: instruction unpredictable when using r15"));
4653
4654 if (skip_past_comma (& str) == FAIL
4655 || cp_reg_required_here (& str, 0) == FAIL)
4656 {
4657 if (!inst.error)
4658 inst.error = BAD_ARGS;
4659 return;
4660 }
4661
4662 end_of_line (str);
4663}
4664
4665/* ARM V5 count-leading-zeroes instruction (argument parse)
4666 CLZ{<cond>} <Rd>, <Rm>
4667 Condition defaults to COND_ALWAYS.
4668 Error if Rd or Rm are R15. */
4669
4670static void
4671do_clz (str)
4672 char * str;
4673{
4674 int rd, rm;
4675
4676 skip_whitespace (str);
4677
4678 if (((rd = reg_required_here (& str, 12)) == FAIL)
4679 || (skip_past_comma (& str) == FAIL)
4680 || ((rm = reg_required_here (& str, 0)) == FAIL))
4681 inst.error = BAD_ARGS;
4682
4683 else if (rd == REG_PC || rm == REG_PC )
4684 inst.error = BAD_PC;
4685
4686 else
4687 end_of_line (str);
4688}
4689
4690/* ARM V5 (argument parse)
4691 LDC2{L} <coproc>, <CRd>, <addressing mode>
4692 STC2{L} <coproc>, <CRd>, <addressing mode>
4693 Instruction is not conditional, and has 0xf in the condition field.
4694 Otherwise, it's the same as LDC/STC. */
4695
4696static void
4697do_lstc2 (str)
4698 char * str;
4699{
4700 skip_whitespace (str);
4701
4702 if (co_proc_number (& str) == FAIL)
4703 {
4704 if (!inst.error)
4705 inst.error = BAD_ARGS;
4706 }
4707 else if (skip_past_comma (& str) == FAIL
4708 || cp_reg_required_here (& str, 12) == FAIL)
4709 {
4710 if (!inst.error)
4711 inst.error = BAD_ARGS;
4712 }
4713 else if (skip_past_comma (& str) == FAIL
4714 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4715 {
4716 if (! inst.error)
4717 inst.error = BAD_ARGS;
4718 }
4719 else
4720 end_of_line (str);
4721}
4722
4723/* ARM V5 (argument parse)
4724 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4725 Instruction is not conditional, and has 0xf in the condition field.
4726 Otherwise, it's the same as CDP. */
4727
4728static void
4729do_cdp2 (str)
4730 char * str;
4731{
4732 skip_whitespace (str);
4733
4734 if (co_proc_number (& str) == FAIL)
4735 {
4736 if (!inst.error)
4737 inst.error = BAD_ARGS;
4738 return;
4739 }
4740
4741 if (skip_past_comma (& str) == FAIL
4742 || cp_opc_expr (& str, 20,4) == FAIL)
4743 {
4744 if (!inst.error)
4745 inst.error = BAD_ARGS;
4746 return;
4747 }
4748
4749 if (skip_past_comma (& str) == FAIL
4750 || cp_reg_required_here (& str, 12) == FAIL)
4751 {
4752 if (!inst.error)
4753 inst.error = BAD_ARGS;
4754 return;
4755 }
4756
4757 if (skip_past_comma (& str) == FAIL
4758 || cp_reg_required_here (& str, 16) == FAIL)
4759 {
4760 if (!inst.error)
4761 inst.error = BAD_ARGS;
4762 return;
4763 }
4764
4765 if (skip_past_comma (& str) == FAIL
4766 || cp_reg_required_here (& str, 0) == FAIL)
4767 {
4768 if (!inst.error)
4769 inst.error = BAD_ARGS;
4770 return;
4771 }
4772
4773 if (skip_past_comma (& str) == SUCCESS)
4774 {
4775 if (cp_opc_expr (& str, 5, 3) == FAIL)
4776 {
4777 if (!inst.error)
4778 inst.error = BAD_ARGS;
4779 return;
4780 }
4781 }
4782
4783 end_of_line (str);
4784}
4785
4786/* ARM V5 (argument parse)
4787 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4788 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4789 Instruction is not conditional, and has 0xf in the condition field.
4790 Otherwise, it's the same as MCR/MRC. */
4791
4792static void
4793do_co_reg2 (str)
4794 char * str;
4795{
4796 skip_whitespace (str);
4797
4798 if (co_proc_number (& str) == FAIL)
4799 {
4800 if (!inst.error)
4801 inst.error = BAD_ARGS;
4802 return;
4803 }
4804
4805 if (skip_past_comma (& str) == FAIL
4806 || cp_opc_expr (& str, 21, 3) == FAIL)
4807 {
4808 if (!inst.error)
4809 inst.error = BAD_ARGS;
4810 return;
4811 }
4812
4813 if (skip_past_comma (& str) == FAIL
4814 || reg_required_here (& str, 12) == FAIL)
4815 {
4816 if (!inst.error)
4817 inst.error = BAD_ARGS;
4818 return;
4819 }
4820
4821 if (skip_past_comma (& str) == FAIL
4822 || cp_reg_required_here (& str, 16) == FAIL)
4823 {
4824 if (!inst.error)
4825 inst.error = BAD_ARGS;
4826 return;
4827 }
4828
4829 if (skip_past_comma (& str) == FAIL
4830 || cp_reg_required_here (& str, 0) == FAIL)
4831 {
4832 if (!inst.error)
4833 inst.error = BAD_ARGS;
4834 return;
4835 }
4836
4837 if (skip_past_comma (& str) == SUCCESS)
4838 {
4839 if (cp_opc_expr (& str, 5, 3) == FAIL)
4840 {
4841 if (!inst.error)
4842 inst.error = BAD_ARGS;
4843 return;
4844 }
4845 }
4846
4847 end_of_line (str);
4848}
4849
4850/* ARM v5TEJ. Jump to Jazelle code. */
4851static void
4852do_bxj (str)
4853 char * str;
4854{
4855 int reg;
4856
4857 skip_whitespace (str);
4858
4859 if ((reg = reg_required_here (&str, 0)) == FAIL)
4860 {
4861 inst.error = BAD_ARGS;
4862 return;
4863 }
4864
4865 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4866 if (reg == REG_PC)
4867 as_tsktsk (_("use of r15 in bxj is not really useful"));
4868
4869 end_of_line (str);
4870}
4871
4872/* ARM V6 umaal (argument parse). */
4873
4874static void
4875do_umaal (str)
4876 char *str;
4877{
4878
4879 int rdlo, rdhi, rm, rs;
4880
4881 skip_whitespace (str);
4882 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4883 || skip_past_comma (& str) == FAIL
4884 || (rdhi = reg_required_here (& str, 16)) == FAIL
4885 || skip_past_comma (& str) == FAIL
4886 || (rm = reg_required_here (& str, 0)) == FAIL
4887 || skip_past_comma (& str) == FAIL
5533419b 4888 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4889 {
4890 inst.error = BAD_ARGS;
4891 return;
4892 }
4893
4894 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4895 {
4896 inst.error = BAD_PC;
4897 return;
4898 }
4899
4900 end_of_line (str);
4901}
4902
4903/* ARM V6 strex (argument parse). */
4904
4905static void
4906do_strex (str)
4907 char *str;
4908{
4909 int rd, rm, rn;
4910
4911 /* Parse Rd, Rm,. */
4912 skip_whitespace (str);
4913 if ((rd = reg_required_here (& str, 12)) == FAIL
4914 || skip_past_comma (& str) == FAIL
4915 || (rm = reg_required_here (& str, 0)) == FAIL
4916 || skip_past_comma (& str) == FAIL)
4917 {
4918 inst.error = BAD_ARGS;
4919 return;
4920 }
4921 if (rd == REG_PC || rm == REG_PC)
4922 {
4923 inst.error = BAD_PC;
4924 return;
4925 }
4926 if (rd == rm)
4927 {
4928 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4929 return;
4930 }
4931
4932 /* Skip past '['. */
4933 if ((strlen (str) >= 1)
4934 && strncmp (str, "[", 1) == 0)
4935 str+=1;
4936 skip_whitespace (str);
4937
4938 /* Parse Rn. */
4939 if ((rn = reg_required_here (& str, 16)) == FAIL)
4940 {
4941 inst.error = BAD_ARGS;
4942 return;
4943 }
4944 else if (rn == REG_PC)
4945 {
4946 inst.error = BAD_PC;
4947 return;
4948 }
4949 if (rd == rn)
4950 {
4951 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4952 return;
4953 }
4954 skip_whitespace (str);
4955
4956 /* Skip past ']'. */
4957 if ((strlen (str) >= 1)
4958 && strncmp (str, "]", 1) == 0)
4959 str+=1;
4960
4961 end_of_line (str);
4962}
4963
4964/* ARM V6 ssat (argument parse). */
4965
4966static void
4967do_ssat (str)
4968 char* str;
4969{
4970 do_sat (&str, /*bias=*/-1);
4971 end_of_line (str);
4972}
4973
4974/* ARM V6 usat (argument parse). */
4975
4976static void
4977do_usat (str)
4978 char* str;
4979{
4980 do_sat (&str, /*bias=*/0);
4981 end_of_line (str);
4982}
4983
4984static void
4985do_sat (str, bias)
4986 char **str;
4987 int bias;
4988{
4989 int rd, rm;
4990 expressionS expr;
4991
4992 skip_whitespace (*str);
4993
4994 /* Parse <Rd>, field. */
4995 if ((rd = reg_required_here (str, 12)) == FAIL
4996 || skip_past_comma (str) == FAIL)
4997 {
4998 inst.error = BAD_ARGS;
4999 return;
5000 }
5001 if (rd == REG_PC)
5002 {
5003 inst.error = BAD_PC;
5004 return;
5005 }
5006
5007 /* Parse #<immed>, field. */
5008 if (is_immediate_prefix (**str))
5009 (*str)++;
5010 else
5011 {
5012 inst.error = _("immediate expression expected");
5013 return;
5014 }
5015 if (my_get_expression (&expr, str))
5016 {
5017 inst.error = _("bad expression");
5018 return;
5019 }
5020 if (expr.X_op != O_constant)
5021 {
5022 inst.error = _("constant expression expected");
5023 return;
5024 }
5025 if (expr.X_add_number + bias < 0
5026 || expr.X_add_number + bias > 31)
5027 {
5028 inst.error = _("immediate value out of range");
5029 return;
5030 }
5031 inst.instruction |= (expr.X_add_number + bias) << 16;
5032 if (skip_past_comma (str) == FAIL)
5033 {
5034 inst.error = BAD_ARGS;
5035 return;
5036 }
5037
5038 /* Parse <Rm> field. */
5039 if ((rm = reg_required_here (str, 0)) == FAIL)
5040 {
5041 inst.error = BAD_ARGS;
5042 return;
5043 }
5044 if (rm == REG_PC)
5045 {
5046 inst.error = BAD_PC;
5047 return;
5048 }
5049
5050 if (skip_past_comma (str) == SUCCESS)
5051 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5052}
5053
5054/* ARM V6 ssat16 (argument parse). */
5055
5056static void
5057do_ssat16 (str)
5058 char *str;
5059{
5060 do_sat16 (&str, /*bias=*/-1);
5061 end_of_line (str);
5062}
5063
5064static void
5065do_usat16 (str)
5066 char *str;
5067{
5068 do_sat16 (&str, /*bias=*/0);
5069 end_of_line (str);
5070}
5071
5072static void
5073do_sat16 (str, bias)
5074 char **str;
5075 int bias;
5076{
5077 int rd, rm;
5078 expressionS expr;
5079
5080 skip_whitespace (*str);
5081
5082 /* Parse the <Rd> field. */
5083 if ((rd = reg_required_here (str, 12)) == FAIL
5084 || skip_past_comma (str) == FAIL)
5085 {
5086 inst.error = BAD_ARGS;
5087 return;
5088 }
5089 if (rd == REG_PC)
5090 {
5091 inst.error = BAD_PC;
5092 return;
5093 }
5094
5095 /* Parse #<immed>, field. */
5096 if (is_immediate_prefix (**str))
5097 (*str)++;
5098 else
5099 {
5100 inst.error = _("immediate expression expected");
5101 return;
5102 }
5103 if (my_get_expression (&expr, str))
5104 {
5105 inst.error = _("bad expression");
5106 return;
5107 }
5108 if (expr.X_op != O_constant)
5109 {
5110 inst.error = _("constant expression expected");
5111 return;
5112 }
5113 if (expr.X_add_number + bias < 0
5114 || expr.X_add_number + bias > 15)
5115 {
5116 inst.error = _("immediate value out of range");
5117 return;
5118 }
5119 inst.instruction |= (expr.X_add_number + bias) << 16;
5120 if (skip_past_comma (str) == FAIL)
5121 {
5122 inst.error = BAD_ARGS;
5123 return;
5124 }
5125
5126 /* Parse <Rm> field. */
5127 if ((rm = reg_required_here (str, 0)) == FAIL)
5128 {
5129 inst.error = BAD_ARGS;
5130 return;
5131 }
5132 if (rm == REG_PC)
5133 {
5134 inst.error = BAD_PC;
5135 return;
5136 }
5137}
5138
5139/* ARM V6 srs (argument parse). */
5140
5141static void
5142do_srs (str)
5143 char* str;
5144{
5145 char *exclam;
5146 skip_whitespace (str);
5147 exclam = strchr (str, '!');
5148 if (exclam)
5149 *exclam = '\0';
5150 do_cps_mode (&str);
5151 if (exclam)
5152 *exclam = '!';
5153 if (*str == '!')
5154 {
5155 inst.instruction |= WRITE_BACK;
5156 str++;
5157 }
5158 end_of_line (str);
5159}
5160
5161/* ARM V6 SMMUL (argument parse). */
5162
5163static void
5164do_smmul (str)
5165 char* str;
5166{
5167 int rd, rm, rs;
5168
5169 skip_whitespace (str);
5170 if ((rd = reg_required_here (&str, 16)) == FAIL
5171 || skip_past_comma (&str) == FAIL
5172 || (rm = reg_required_here (&str, 0)) == FAIL
5173 || skip_past_comma (&str) == FAIL
5174 || (rs = reg_required_here (&str, 8)) == FAIL)
5175 {
5176 inst.error = BAD_ARGS;
5177 return;
5178 }
5179
5180 if (rd == REG_PC
5181 || rm == REG_PC
5182 || rs == REG_PC)
5183 {
5184 inst.error = BAD_PC;
5185 return;
5186 }
5187
5188 end_of_line (str);
5189
5190}
5191
5192/* ARM V6 SMLALD (argument parse). */
5193
5194static void
5195do_smlald (str)
5196 char* str;
5197{
5198 int rdlo, rdhi, rm, rs;
5199 skip_whitespace (str);
5200 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5201 || skip_past_comma (&str) == FAIL
5202 || (rdhi = reg_required_here (&str, 16)) == FAIL
5203 || skip_past_comma (&str) == FAIL
5204 || (rm = reg_required_here (&str, 0)) == FAIL
5205 || skip_past_comma (&str) == FAIL
5206 || (rs = reg_required_here (&str, 8)) == FAIL)
5207 {
5208 inst.error = BAD_ARGS;
5209 return;
5210 }
5211
5212 if (rdlo == REG_PC
5213 || rdhi == REG_PC
5214 || rm == REG_PC
5215 || rs == REG_PC)
5216 {
5217 inst.error = BAD_PC;
5218 return;
5219 }
5220
5221 end_of_line (str);
5222}
5223
5224/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5225 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5226
5227static void
5228do_smlad (str)
5229 char *str;
5230{
5231 int rd, rm, rs, rn;
5232
5233 skip_whitespace (str);
5234 if ((rd = reg_required_here (&str, 16)) == FAIL
5235 || skip_past_comma (&str) == FAIL
5236 || (rm = reg_required_here (&str, 0)) == FAIL
5237 || skip_past_comma (&str) == FAIL
5238 || (rs = reg_required_here (&str, 8)) == FAIL
5239 || skip_past_comma (&str) == FAIL
5240 || (rn = reg_required_here (&str, 12)) == FAIL)
5241 {
5242 inst.error = BAD_ARGS;
5243 return;
5244 }
5245
5246 if (rd == REG_PC
5247 || rn == REG_PC
5248 || rs == REG_PC
5249 || rm == REG_PC)
5250 {
5251 inst.error = BAD_PC;
5252 return;
5253 }
5254
5255 end_of_line (str);
5256}
5257
5258/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5259 preserving the other bits.
5260
5261 setend <endian_specifier>, where <endian_specifier> is either
5262 BE or LE. */
5263
5264static void
5265do_setend (str)
5266 char *str;
5267{
5268 if (do_endian_specifier (str))
5269 inst.instruction |= 0x200;
5270}
5271
5272/* Returns true if the endian-specifier indicates big-endianness. */
5273
5274static int
5275do_endian_specifier (str)
5276 char *str;
5277{
5278 int big_endian = 0;
5279
5280 skip_whitespace (str);
5281 if (strlen (str) < 2)
5282 inst.error = _("missing endian specifier");
5283 else if (strncasecmp (str, "BE", 2) == 0)
5284 {
5285 str += 2;
5286 big_endian = 1;
5287 }
5288 else if (strncasecmp (str, "LE", 2) == 0)
5289 str += 2;
5290 else
5291 inst.error = _("valid endian specifiers are be or le");
5292
5293 end_of_line (str);
5294
5295 return big_endian;
5296}
5297
5298/* ARM V6 SXTH.
5299
5300 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5301 Condition defaults to COND_ALWAYS.
5302 Error if any register uses R15. */
5303
5304static void
5305do_sxth (str)
5306 char *str;
5307{
5308 int rd, rm;
5309 expressionS expr;
5310 int rotation_clear_mask = 0xfffff3ff;
5311 int rotation_eight_mask = 0x00000400;
5312 int rotation_sixteen_mask = 0x00000800;
5313 int rotation_twenty_four_mask = 0x00000c00;
5314
5315 skip_whitespace (str);
5316 if ((rd = reg_required_here (&str, 12)) == FAIL
5317 || skip_past_comma (&str) == FAIL
5318 || (rm = reg_required_here (&str, 0)) == FAIL)
5319 {
5320 inst.error = BAD_ARGS;
5321 return;
5322 }
5323
5324 else if (rd == REG_PC || rm == REG_PC)
5325 {
5326 inst.error = BAD_PC;
5327 return;
5328 }
5329
5330 /* Zero out the rotation field. */
5331 inst.instruction &= rotation_clear_mask;
5332
5333 /* Check for lack of optional rotation field. */
5334 if (skip_past_comma (&str) == FAIL)
5335 {
5336 end_of_line (str);
5337 return;
5338 }
5339
5340 /* Move past 'ROR'. */
5341 skip_whitespace (str);
5342 if (strncasecmp (str, "ROR", 3) == 0)
5343 str+=3;
5344 else
5345 {
5346 inst.error = _("missing rotation field after comma");
5347 return;
5348 }
5349
5350 /* Get the immediate constant. */
5351 skip_whitespace (str);
5352 if (is_immediate_prefix (* str))
5353 str++;
5354 else
5355 {
5356 inst.error = _("immediate expression expected");
5357 return;
5358 }
5359
5360 if (my_get_expression (&expr, &str))
5361 {
5362 inst.error = _("bad expression");
5363 return;
5364 }
5365
5366 if (expr.X_op != O_constant)
5367 {
5368 inst.error = _("constant expression expected");
5369 return;
5370 }
5371
5372 switch (expr.X_add_number)
5373 {
5374 case 0:
5375 /* Rotation field has already been zeroed. */
5376 break;
5377 case 8:
5378 inst.instruction |= rotation_eight_mask;
5379 break;
5380
5381 case 16:
5382 inst.instruction |= rotation_sixteen_mask;
5383 break;
5384
5385 case 24:
5386 inst.instruction |= rotation_twenty_four_mask;
5387 break;
5388
5389 default:
5390 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5391 break;
5392 }
5393
5394 end_of_line (str);
5395
5396}
5397
5398/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5399 extends it to 32-bits, and adds the result to a value in another
5400 register. You can specify a rotation by 0, 8, 16, or 24 bits
5401 before extracting the 16-bit value.
5402 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5403 Condition defaults to COND_ALWAYS.
5404 Error if any register uses R15. */
5405
5406static void
5407do_sxtah (str)
5408 char *str;
5409{
5410 int rd, rn, rm;
5411 expressionS expr;
5412 int rotation_clear_mask = 0xfffff3ff;
5413 int rotation_eight_mask = 0x00000400;
5414 int rotation_sixteen_mask = 0x00000800;
5415 int rotation_twenty_four_mask = 0x00000c00;
5416
5417 skip_whitespace (str);
5418 if ((rd = reg_required_here (&str, 12)) == FAIL
5419 || skip_past_comma (&str) == FAIL
5420 || (rn = reg_required_here (&str, 16)) == FAIL
5421 || skip_past_comma (&str) == FAIL
5422 || (rm = reg_required_here (&str, 0)) == FAIL)
5423 {
5424 inst.error = BAD_ARGS;
5425 return;
5426 }
5427
5428 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5429 {
5430 inst.error = BAD_PC;
5431 return;
5432 }
5433
5434 /* Zero out the rotation field. */
5435 inst.instruction &= rotation_clear_mask;
5436
5437 /* Check for lack of optional rotation field. */
5438 if (skip_past_comma (&str) == FAIL)
5439 {
5440 end_of_line (str);
5441 return;
5442 }
5443
5444 /* Move past 'ROR'. */
5445 skip_whitespace (str);
5446 if (strncasecmp (str, "ROR", 3) == 0)
5447 str+=3;
5448 else
5449 {
5450 inst.error = _("missing rotation field after comma");
5451 return;
5452 }
5453
5454 /* Get the immediate constant. */
5455 skip_whitespace (str);
5456 if (is_immediate_prefix (* str))
5457 str++;
5458 else
5459 {
5460 inst.error = _("immediate expression expected");
5461 return;
5462 }
5463
5464 if (my_get_expression (&expr, &str))
5465 {
5466 inst.error = _("bad expression");
5467 return;
5468 }
5469
5470 if (expr.X_op != O_constant)
5471 {
5472 inst.error = _("constant expression expected");
5473 return;
5474 }
5475
5476 switch (expr.X_add_number)
5477 {
5478 case 0:
5479 /* Rotation field has already been zeroed. */
5480 break;
5481
5482 case 8:
5483 inst.instruction |= rotation_eight_mask;
5484 break;
5485
5486 case 16:
5487 inst.instruction |= rotation_sixteen_mask;
5488 break;
5489
5490 case 24:
5491 inst.instruction |= rotation_twenty_four_mask;
5492 break;
5493
5494 default:
5495 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5496 break;
5497 }
5498
5499 end_of_line (str);
5500
5501}
5502
5503
5504/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5505 word at the specified address and the following word
5506 respectively.
5507 Unconditionally executed.
5508 Error if Rn is R15.
5509*/
5510
5511static void
5512do_rfe (str)
5513 char *str;
5514{
5515 int rn;
5516
5517 skip_whitespace (str);
5518
5519 if ((rn = reg_required_here (&str, 16)) == FAIL)
5520 return;
b99bd4ef 5521
09d92015 5522 if (rn == REG_PC)
b99bd4ef 5523 {
09d92015 5524 inst.error = BAD_PC;
b99bd4ef
NC
5525 return;
5526 }
5527
09d92015
MM
5528 skip_whitespace (str);
5529
5530 if (*str == '!')
5531 {
5532 inst.instruction |= WRITE_BACK;
5533 str++;
5534 }
b99bd4ef
NC
5535 end_of_line (str);
5536}
5537
09d92015
MM
5538/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5539 register (argument parse).
5540 REV{<cond>} Rd, Rm.
5541 Condition defaults to COND_ALWAYS.
5542 Error if Rd or Rm are R15. */
b99bd4ef
NC
5543
5544static void
09d92015
MM
5545do_rev (str)
5546 char* str;
b99bd4ef
NC
5547{
5548 int rd, rm;
5549
b99bd4ef
NC
5550 skip_whitespace (str);
5551
09d92015
MM
5552 if ((rd = reg_required_here (&str, 12)) == FAIL
5553 || skip_past_comma (&str) == FAIL
5554 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5555 inst.error = BAD_ARGS;
5556
09d92015 5557 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5558 inst.error = BAD_PC;
5559
5560 else
5561 end_of_line (str);
5562}
5563
09d92015
MM
5564/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5565 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5566 Condition defaults to COND_ALWAYS.
5567 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5568
5569static void
09d92015
MM
5570do_qadd16 (str)
5571 char* str;
b99bd4ef 5572{
09d92015
MM
5573 int rd, rm, rn;
5574
b99bd4ef
NC
5575 skip_whitespace (str);
5576
09d92015
MM
5577 if ((rd = reg_required_here (&str, 12)) == FAIL
5578 || skip_past_comma (&str) == FAIL
5579 || (rn = reg_required_here (&str, 16)) == FAIL
5580 || skip_past_comma (&str) == FAIL
5581 || (rm = reg_required_here (&str, 0)) == FAIL)
5582 inst.error = BAD_ARGS;
5583
5584 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5585 inst.error = BAD_PC;
5586
b99bd4ef
NC
5587 else
5588 end_of_line (str);
5589}
5590
09d92015
MM
5591/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5592 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5593 Condition defaults to COND_ALWAYS.
5594 Error if Rd, Rn or Rm are R15. */
5595
5596static void
5597do_pkhbt (str)
5598 char* str;
5599{
5600 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5601}
5602
5603/* ARM V6 PKHTB (Argument Parse). */
5604
5605static void
5606do_pkhtb (str)
5607 char* str;
5608{
5609 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5610}
b99bd4ef
NC
5611
5612static void
09d92015
MM
5613do_pkh_core (str, shift)
5614 char* str;
5615 int shift;
b99bd4ef 5616{
09d92015 5617 int rd, rn, rm;
b99bd4ef 5618
09d92015
MM
5619 skip_whitespace (str);
5620 if (((rd = reg_required_here (&str, 12)) == FAIL)
5621 || (skip_past_comma (&str) == FAIL)
5622 || ((rn = reg_required_here (&str, 16)) == FAIL)
5623 || (skip_past_comma (&str) == FAIL)
5624 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5625 {
09d92015 5626 inst.error = BAD_ARGS;
b99bd4ef
NC
5627 return;
5628 }
5629
09d92015 5630 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5631 {
09d92015 5632 inst.error = BAD_PC;
b99bd4ef
NC
5633 return;
5634 }
5635
09d92015
MM
5636 /* Check for optional shift immediate constant. */
5637 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5638 {
09d92015
MM
5639 if (shift == SHIFT_ASR_IMMEDIATE)
5640 {
5641 /* If the shift specifier is ommited, turn the instruction
5642 into pkhbt rd, rm, rn. First, switch the instruction
5643 code, and clear the rn and rm fields. */
5644 inst.instruction &= 0xfff0f010;
5645 /* Now, re-encode the registers. */
5646 inst.instruction |= (rm << 16) | rn;
5647 }
b99bd4ef
NC
5648 return;
5649 }
5650
09d92015
MM
5651 decode_shift (&str, shift);
5652}
5653
5654/* ARM V6 Load Register Exclusive instruction (argument parse).
5655 LDREX{<cond>} <Rd, [<Rn>]
5656 Condition defaults to COND_ALWAYS.
5657 Error if Rd or Rn are R15.
5658 See ARMARMv6 A4.1.27: LDREX. */
5659
5660
5661static void
5662do_ldrex (str)
5663 char * str;
5664{
5665 int rd, rn;
5666
5667 skip_whitespace (str);
5668
5669 /* Parse Rd. */
5670 if (((rd = reg_required_here (&str, 12)) == FAIL)
5671 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5672 {
09d92015 5673 inst.error = BAD_ARGS;
b99bd4ef
NC
5674 return;
5675 }
09d92015 5676 else if (rd == REG_PC)
b99bd4ef 5677 {
09d92015 5678 inst.error = BAD_PC;
b99bd4ef
NC
5679 return;
5680 }
09d92015 5681 skip_whitespace (str);
b99bd4ef 5682
09d92015
MM
5683 /* Skip past '['. */
5684 if ((strlen (str) >= 1)
5685 &&strncmp (str, "[", 1) == 0)
5686 str+=1;
5687 skip_whitespace (str);
5688
5689 /* Parse Rn. */
5690 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5691 {
09d92015
MM
5692 inst.error = BAD_ARGS;
5693 return;
b99bd4ef 5694 }
09d92015
MM
5695 else if (rn == REG_PC)
5696 {
5697 inst.error = BAD_PC;
5698 return;
5699 }
5700 skip_whitespace (str);
b99bd4ef 5701
09d92015
MM
5702 /* Skip past ']'. */
5703 if ((strlen (str) >= 1)
5704 && strncmp (str, "]", 1) == 0)
5705 str+=1;
5706
b99bd4ef
NC
5707 end_of_line (str);
5708}
5709
09d92015
MM
5710/* ARM V6 change processor state instruction (argument parse)
5711 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5712
5713static void
09d92015
MM
5714do_cps (str)
5715 char * str;
b99bd4ef 5716{
09d92015
MM
5717 do_cps_mode (&str);
5718 end_of_line (str);
5719}
b99bd4ef 5720
09d92015
MM
5721static void
5722do_cpsi (str)
5723 char * str;
5724{
5725 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5726
09d92015 5727 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5728 {
09d92015
MM
5729 skip_whitespace (str);
5730 do_cps_mode (&str);
b99bd4ef 5731 }
09d92015
MM
5732 end_of_line (str);
5733}
b99bd4ef 5734
09d92015
MM
5735static void
5736do_cps_mode (str)
5737 char **str;
5738{
5739 expressionS expr;
5740
5741 skip_whitespace (*str);
5742
5743 if (! is_immediate_prefix (**str))
b99bd4ef 5744 {
09d92015 5745 inst.error = _("immediate expression expected");
b99bd4ef
NC
5746 return;
5747 }
5748
09d92015
MM
5749 (*str)++; /* Strip off the immediate signifier. */
5750 if (my_get_expression (&expr, str))
b99bd4ef 5751 {
09d92015 5752 inst.error = _("bad expression");
b99bd4ef
NC
5753 return;
5754 }
5755
09d92015 5756 if (expr.X_op != O_constant)
b99bd4ef 5757 {
09d92015 5758 inst.error = _("constant expression expected");
b99bd4ef
NC
5759 return;
5760 }
09d92015
MM
5761
5762 /* The mode is a 5 bit field. Valid values are 0-31. */
5763 if (((unsigned) expr.X_add_number) > 31
5764 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5765 {
09d92015
MM
5766 inst.error = _("invalid constant");
5767 return;
b99bd4ef 5768 }
09d92015
MM
5769
5770 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5771}
5772
ea6ef066 5773static void
09d92015
MM
5774do_cps_flags (str, thumb_p)
5775 char **str;
5776 int thumb_p;
ea6ef066 5777{
09d92015
MM
5778 struct cps_flag {
5779 char character;
5780 unsigned long arm_value;
5781 unsigned long thumb_value;
5782 };
5783 static struct cps_flag flag_table[] = {
5784 {'a', 0x100, 0x4 },
5785 {'i', 0x080, 0x2 },
5786 {'f', 0x040, 0x1 }
5787 };
ea6ef066 5788
09d92015 5789 int saw_a_flag = 0;
ea6ef066 5790
09d92015
MM
5791 skip_whitespace (*str);
5792
5793 /* Get the a, f and i flags. */
5794 while (**str && **str != ',')
ea6ef066 5795 {
09d92015
MM
5796 struct cps_flag *p;
5797 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5798 for (p = flag_table; p < q; ++p)
5799 if (strncasecmp (*str, &p->character, 1) == 0)
5800 {
5801 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5802 saw_a_flag = 1;
5803 break;
5804 }
5805 if (p == q)
5806 {
5807 inst.error = _("unrecognized flag");
5808 return;
5809 }
5810 (*str)++;
ea6ef066 5811 }
09d92015
MM
5812 if (!saw_a_flag)
5813 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5814}
5815
b99bd4ef
NC
5816/* THUMB V5 breakpoint instruction (argument parse)
5817 BKPT <immed_8>. */
5818
5819static void
5820do_t_bkpt (str)
5821 char * str;
5822{
5823 expressionS expr;
5824 unsigned long number;
5825
5826 skip_whitespace (str);
5827
5828 /* Allow optional leading '#'. */
5829 if (is_immediate_prefix (*str))
5830 str ++;
5831
5832 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5833 if (my_get_expression (& expr, & str)
5834 || (expr.X_op != O_constant
5835 /* As a convenience we allow 'bkpt' without an operand. */
5836 && expr.X_op != O_absent))
b99bd4ef 5837 {
143c8e19 5838 inst.error = _("bad expression");
b99bd4ef
NC
5839 return;
5840 }
5841
5842 number = expr.X_add_number;
5843
5844 /* Check it fits an 8 bit unsigned. */
5845 if (number != (number & 0xff))
5846 {
5847 inst.error = _("immediate value out of range");
5848 return;
5849 }
5850
5851 inst.instruction |= number;
5852
5853 end_of_line (str);
5854}
5855
5856/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5857 Expects inst.instruction is set for BLX(1).
5858 Note: this is cloned from do_branch, and the reloc changed to be a
5859 new one that can cope with setting one extra bit (the H bit). */
5860
5861static void
f2b7cb0a 5862do_branch25 (str)
b99bd4ef 5863 char * str;
b99bd4ef
NC
5864{
5865 if (my_get_expression (& inst.reloc.exp, & str))
5866 return;
5867
5868#ifdef OBJ_ELF
5869 {
5870 char * save_in;
5871
5872 /* ScottB: February 5, 1998 */
5873 /* Check to see of PLT32 reloc required for the instruction. */
5874
5875 /* arm_parse_reloc() works on input_line_pointer.
5876 We actually want to parse the operands to the branch instruction
5877 passed in 'str'. Save the input pointer and restore it later. */
5878 save_in = input_line_pointer;
5879 input_line_pointer = str;
5880
5881 if (inst.reloc.exp.X_op == O_symbol
5882 && *str == '('
5883 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5884 {
5885 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5886 inst.reloc.pc_rel = 0;
5887 /* Modify str to point to after parsed operands, otherwise
5888 end_of_line() will complain about the (PLT) left in str. */
5889 str = input_line_pointer;
5890 }
5891 else
5892 {
5893 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5894 inst.reloc.pc_rel = 1;
5895 }
5896
5897 input_line_pointer = save_in;
5898 }
5899#else
5900 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5901 inst.reloc.pc_rel = 1;
5902#endif /* OBJ_ELF */
5903
5904 end_of_line (str);
5905}
5906
5907/* ARM V5 branch-link-exchange instruction (argument parse)
5908 BLX <target_addr> ie BLX(1)
5909 BLX{<condition>} <Rm> ie BLX(2)
5910 Unfortunately, there are two different opcodes for this mnemonic.
5911 So, the insns[].value is not used, and the code here zaps values
5912 into inst.instruction.
5913 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5914
5915static void
f2b7cb0a 5916do_blx (str)
b99bd4ef 5917 char * str;
b99bd4ef
NC
5918{
5919 char * mystr = str;
5920 int rm;
5921
b99bd4ef
NC
5922 skip_whitespace (mystr);
5923 rm = reg_required_here (& mystr, 0);
5924
5925 /* The above may set inst.error. Ignore his opinion. */
5926 inst.error = 0;
5927
5928 if (rm != FAIL)
5929 {
5930 /* Arg is a register.
5931 Use the condition code our caller put in inst.instruction.
5932 Pass ourselves off as a BX with a funny opcode. */
5933 inst.instruction |= 0x012fff30;
f2b7cb0a 5934 do_bx (str);
b99bd4ef
NC
5935 }
5936 else
5937 {
5938 /* This must be is BLX <target address>, no condition allowed. */
5939 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5940 {
5941 inst.error = BAD_COND;
b99bd4ef 5942 return;
cc8a6dd0 5943 }
b99bd4ef
NC
5944
5945 inst.instruction = 0xfafffffe;
5946
5947 /* Process like a B/BL, but with a different reloc.
5948 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5949 do_branch25 (str);
b99bd4ef
NC
5950 }
5951}
5952
5953/* ARM V5 Thumb BLX (argument parse)
5954 BLX <target_addr> which is BLX(1)
5955 BLX <Rm> which is BLX(2)
5956 Unfortunately, there are two different opcodes for this mnemonic.
5957 So, the tinsns[].value is not used, and the code here zaps values
5958 into inst.instruction. */
5959
5960static void
5961do_t_blx (str)
5962 char * str;
5963{
5964 char * mystr = str;
5965 int rm;
5966
5967 skip_whitespace (mystr);
5968 inst.instruction = 0x4780;
5969
5970 /* Note that this call is to the ARM register recognizer. BLX(2)
5971 uses the ARM register space, not the Thumb one, so a call to
5972 thumb_reg() would be wrong. */
5973 rm = reg_required_here (& mystr, 3);
5974 inst.error = 0;
5975
5976 if (rm != FAIL)
5977 {
5978 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5979 inst.size = 2;
5980 }
5981 else
5982 {
5983 /* No ARM register. This must be BLX(1). Change the .instruction. */
5984 inst.instruction = 0xf7ffeffe;
5985 inst.size = 4;
5986
5987 if (my_get_expression (& inst.reloc.exp, & mystr))
5988 return;
5989
5990 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5991 inst.reloc.pc_rel = 1;
5992 }
5993
5994 end_of_line (mystr);
5995}
5996
5997/* ARM V5 breakpoint instruction (argument parse)
5998 BKPT <16 bit unsigned immediate>
5999 Instruction is not conditional.
6000 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 6001 and it is an error if the caller tried to override that. */
b99bd4ef
NC
6002
6003static void
f2b7cb0a 6004do_bkpt (str)
b99bd4ef 6005 char * str;
b99bd4ef
NC
6006{
6007 expressionS expr;
6008 unsigned long number;
6009
6010 skip_whitespace (str);
6011
6012 /* Allow optional leading '#'. */
6013 if (is_immediate_prefix (* str))
6014 str++;
6015
6016 memset (& expr, '\0', sizeof (expr));
6017
143c8e19
NC
6018 if (my_get_expression (& expr, & str)
6019 || (expr.X_op != O_constant
6020 /* As a convenience we allow 'bkpt' without an operand. */
6021 && expr.X_op != O_absent))
b99bd4ef 6022 {
143c8e19 6023 inst.error = _("bad expression");
b99bd4ef
NC
6024 return;
6025 }
6026
6027 number = expr.X_add_number;
6028
6029 /* Check it fits a 16 bit unsigned. */
6030 if (number != (number & 0xffff))
6031 {
6032 inst.error = _("immediate value out of range");
6033 return;
6034 }
6035
6036 /* Top 12 of 16 bits to bits 19:8. */
6037 inst.instruction |= (number & 0xfff0) << 4;
6038
6039 /* Bottom 4 of 16 bits to bits 3:0. */
6040 inst.instruction |= number & 0xf;
6041
6042 end_of_line (str);
b99bd4ef
NC
6043}
6044
09d92015
MM
6045/* THUMB CPS instruction (argument parse). */
6046
6047static void
6048do_t_cps (str)
6049 char *str;
6050{
6051 do_cps_flags (&str, /*thumb_p=*/1);
6052 end_of_line (str);
6053}
6054
6055/* THUMB CPY instruction (argument parse). */
6056
6057static void
6058do_t_cpy (str)
6059 char *str;
6060{
6061 thumb_mov_compare (str, THUMB_CPY);
6062}
6063
6064/* THUMB SETEND instruction (argument parse). */
6065
6066static void
6067do_t_setend (str)
6068 char *str;
6069{
6070 if (do_endian_specifier (str))
6071 inst.instruction |= 0x8;
6072}
6073
e16bb312
NC
6074static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6075
6076/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6077
6078static unsigned long
6079check_iwmmxt_insn (str, insn_type, immediate_size)
6080 char * str;
6081 enum iwmmxt_insn_type insn_type;
6082 int immediate_size;
6083{
6084 int reg = 0;
6085 const char * inst_error;
6086 expressionS expr;
6087 unsigned long number;
6088
6089 inst_error = inst.error;
6090 if (!inst.error)
6091 inst.error = BAD_ARGS;
6092 skip_whitespace (str);
6093
6094 switch (insn_type)
6095 {
6096 case check_rd:
6097 if ((reg = reg_required_here (&str, 12)) == FAIL)
6098 return FAIL;
6099 break;
6100
6101 case check_wr:
6102 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6103 return FAIL;
6104 break;
6105
6106 case check_wrwr:
6107 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6108 || skip_past_comma (&str) == FAIL
6109 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6110 return FAIL;
6111 break;
6112
6113 case check_wrwrwr:
6114 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6115 || skip_past_comma (&str) == FAIL
6116 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6119 return FAIL;
6120 break;
6121
6122 case check_wrwrwcg:
6123 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6124 || skip_past_comma (&str) == FAIL
6125 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6126 || skip_past_comma (&str) == FAIL
6127 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6128 return FAIL;
6129 break;
6130
6131 case check_tbcst:
6132 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || reg_required_here (&str, 12) == FAIL))
6135 return FAIL;
6136 break;
6137
6138 case check_tmovmsk:
6139 if ((reg_required_here (&str, 12) == FAIL
6140 || skip_past_comma (&str) == FAIL
6141 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6142 return FAIL;
6143 break;
6144
6145 case check_tmia:
6146 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6147 || skip_past_comma (&str) == FAIL
6148 || reg_required_here (&str, 0) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || reg_required_here (&str, 12) == FAIL))
6151 return FAIL;
6152 break;
6153
6154 case check_tmcrr:
6155 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6156 || skip_past_comma (&str) == FAIL
6157 || reg_required_here (&str, 12) == FAIL
6158 || skip_past_comma (&str) == FAIL
6159 || reg_required_here (&str, 16) == FAIL))
6160 return FAIL;
6161 break;
6162
6163 case check_tmrrc:
6164 if ((reg_required_here (&str, 12) == FAIL
6165 || skip_past_comma (&str) == FAIL
6166 || reg_required_here (&str, 16) == FAIL
6167 || skip_past_comma (&str) == FAIL
6168 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6169 return FAIL;
6170 break;
6171
6172 case check_tmcr:
6173 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6174 || skip_past_comma (&str) == FAIL
6175 || reg_required_here (&str, 12) == FAIL))
6176 return FAIL;
6177 break;
6178
6179 case check_tmrc:
6180 if ((reg_required_here (&str, 12) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6183 return FAIL;
6184 break;
6185
6186 case check_tinsr:
6187 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6188 || skip_past_comma (&str) == FAIL
6189 || reg_required_here (&str, 12) == FAIL
6190 || skip_past_comma (&str) == FAIL))
6191 return FAIL;
6192 break;
6193
6194 case check_textrc:
6195 if ((reg_required_here (&str, 12) == FAIL
6196 || skip_past_comma (&str) == FAIL))
6197 return FAIL;
6198 break;
6199
6200 case check_waligni:
6201 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6202 || skip_past_comma (&str) == FAIL
6203 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6204 || skip_past_comma (&str) == FAIL
6205 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6206 || skip_past_comma (&str) == FAIL))
6207 return FAIL;
6208 break;
6209
6210 case check_textrm:
6211 if ((reg_required_here (&str, 12) == FAIL
6212 || skip_past_comma (&str) == FAIL
6213 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6214 || skip_past_comma (&str) == FAIL))
6215 return FAIL;
6216 break;
6217
6218 case check_wshufh:
6219 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6220 || skip_past_comma (&str) == FAIL
6221 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6222 || skip_past_comma (&str) == FAIL))
6223 return FAIL;
6224 break;
6225 }
6226
6227 if (immediate_size == 0)
6228 {
6229 end_of_line (str);
6230 inst.error = inst_error;
6231 return reg;
6232 }
6233 else
6234 {
6235 skip_whitespace (str);
6236
6237 /* Allow optional leading '#'. */
6238 if (is_immediate_prefix (* str))
6239 str++;
6240
6241 memset (& expr, '\0', sizeof (expr));
6242
6243 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6244 {
6245 inst.error = _("bad or missing expression");
6246 return FAIL;
6247 }
6248
6249 number = expr.X_add_number;
6250
6251 if (number != (number & immediate_size))
6252 {
6253 inst.error = _("immediate value out of range");
6254 return FAIL;
6255 }
6256 end_of_line (str);
6257 inst.error = inst_error;
6258 return number;
6259 }
6260}
6261
6262static void
6263do_iwmmxt_byte_addr (str)
6264 char * str;
6265{
6266 int op = (inst.instruction & 0x300) >> 8;
6267 int reg;
6268
6269 inst.instruction &= ~0x300;
6270 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6271
6272 skip_whitespace (str);
6273
6274 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6275 || skip_past_comma (& str) == FAIL
6276 || cp_byte_address_required_here (&str) == FAIL)
6277 {
6278 if (! inst.error)
6279 inst.error = BAD_ARGS;
6280 }
6281 else
6282 end_of_line (str);
6283
6284 if (wc_register (reg))
6285 {
ece01a63 6286 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6287 inst.instruction |= 0xf0000100;
6288 inst.instruction &= ~0x00400000;
6289 }
6290}
6291
6292static void
6293do_iwmmxt_tandc (str)
6294 char * str;
6295{
6296 int reg;
6297
6298 reg = check_iwmmxt_insn (str, check_rd, 0);
6299
6300 if (reg != REG_PC && !inst.error)
6301 inst.error = _("only r15 allowed here");
e16bb312
NC
6302}
6303
6304static void
6305do_iwmmxt_tbcst (str)
6306 char * str;
6307{
6308 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6309}
6310
6311static void
6312do_iwmmxt_textrc (str)
6313 char * str;
6314{
6315 unsigned long number;
6316
6317 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6318 return;
6319
6320 inst.instruction |= number & 0x7;
e16bb312
NC
6321}
6322
6323static void
6324do_iwmmxt_textrm (str)
6325 char * str;
6326{
6327 unsigned long number;
6328
6329 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6330 return;
6331
6332 inst.instruction |= number & 0x7;
6333}
6334
6335static void
6336do_iwmmxt_tinsr (str)
6337 char * str;
6338{
6339 unsigned long number;
6340
6341 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6342 return;
6343
6344 inst.instruction |= number & 0x7;
e16bb312
NC
6345}
6346
6347static void
6348do_iwmmxt_tmcr (str)
6349 char * str;
6350{
6351 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6352}
6353
6354static void
6355do_iwmmxt_tmcrr (str)
6356 char * str;
6357{
6358 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6359}
6360
6361static void
6362do_iwmmxt_tmia (str)
6363 char * str;
6364{
6365 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6366}
6367
6368static void
6369do_iwmmxt_tmovmsk (str)
6370 char * str;
6371{
6372 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6373}
6374
6375static void
6376do_iwmmxt_tmrc (str)
6377 char * str;
6378{
6379 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6380}
6381
6382static void
6383do_iwmmxt_tmrrc (str)
6384 char * str;
6385{
6386 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6387}
6388
6389static void
6390do_iwmmxt_torc (str)
6391 char * str;
6392{
6393 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6394}
6395
6396static void
6397do_iwmmxt_waligni (str)
6398 char * str;
6399{
6400 unsigned long number;
6401
6402 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6403 return;
6404
6405 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6406}
6407
6408static void
6409do_iwmmxt_wmov (str)
6410 char * str;
6411{
6412 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6413 return;
6414
6415 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6416}
6417
6418static void
6419do_iwmmxt_word_addr (str)
6420 char * str;
6421{
6422 int op = (inst.instruction & 0x300) >> 8;
6423 int reg;
6424
6425 inst.instruction &= ~0x300;
6426 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6427
6428 skip_whitespace (str);
6429
6430 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6431 || skip_past_comma (& str) == FAIL
6432 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6433 {
6434 if (! inst.error)
6435 inst.error = BAD_ARGS;
6436 }
6437 else
6438 end_of_line (str);
6439
6440 if (wc_register (reg))
6441 {
ece01a63
ILT
6442 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6443 as_bad (_("conditional execution not supported with control register"));
6444 if (op != 2)
6445 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6446 inst.instruction |= 0xf0000100;
6447 inst.instruction &= ~0x00400000;
6448 }
6449}
6450
6451static void
6452do_iwmmxt_wrwr (str)
6453 char * str;
6454{
6455 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6456}
6457
6458static void
6459do_iwmmxt_wrwrwcg (str)
6460 char * str;
6461{
6462 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6463}
6464
6465static void
6466do_iwmmxt_wrwrwr (str)
6467 char * str;
6468{
6469 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6470}
6471
6472static void
6473do_iwmmxt_wshufh (str)
6474 char * str;
6475{
6476 unsigned long number;
6477
6478 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6479 return;
6480
6481 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6482}
6483
6484static void
6485do_iwmmxt_wzero (str)
6486 char * str;
6487{
6488 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6489 return;
6490
6491 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6492}
6493
b99bd4ef
NC
6494/* Xscale multiply-accumulate (argument parse)
6495 MIAcc acc0,Rm,Rs
6496 MIAPHcc acc0,Rm,Rs
6497 MIAxycc acc0,Rm,Rs. */
6498
6499static void
63e63b07 6500do_xsc_mia (str)
b99bd4ef 6501 char * str;
b99bd4ef
NC
6502{
6503 int rs;
6504 int rm;
6505
f2b7cb0a 6506 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6507 inst.error = ERR_NO_ACCUM;
6508
6509 else if (skip_past_comma (& str) == FAIL
6510 || (rm = reg_required_here (& str, 0)) == FAIL)
6511 inst.error = BAD_ARGS;
6512
6513 else if (skip_past_comma (& str) == FAIL
6514 || (rs = reg_required_here (& str, 12)) == FAIL)
6515 inst.error = BAD_ARGS;
6516
6517 /* inst.instruction has now been zapped with both rm and rs. */
6518 else if (rm == REG_PC || rs == REG_PC)
6519 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6520
6521 else
6522 end_of_line (str);
6523}
6524
6525/* Xscale move-accumulator-register (argument parse)
6526
6527 MARcc acc0,RdLo,RdHi. */
6528
6529static void
63e63b07 6530do_xsc_mar (str)
b99bd4ef 6531 char * str;
b99bd4ef
NC
6532{
6533 int rdlo, rdhi;
6534
f2b7cb0a 6535 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6536 inst.error = ERR_NO_ACCUM;
6537
6538 else if (skip_past_comma (& str) == FAIL
6539 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6540 inst.error = BAD_ARGS;
6541
6542 else if (skip_past_comma (& str) == FAIL
6543 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6544 inst.error = BAD_ARGS;
6545
6546 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6547 else if (rdlo == REG_PC || rdhi == REG_PC)
6548 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6549
6550 else
6551 end_of_line (str);
6552}
6553
6554/* Xscale move-register-accumulator (argument parse)
6555
6556 MRAcc RdLo,RdHi,acc0. */
6557
6558static void
63e63b07 6559do_xsc_mra (str)
b99bd4ef 6560 char * str;
b99bd4ef
NC
6561{
6562 int rdlo;
6563 int rdhi;
6564
b99bd4ef
NC
6565 skip_whitespace (str);
6566
6567 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6568 inst.error = BAD_ARGS;
6569
6570 else if (skip_past_comma (& str) == FAIL
6571 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6572 inst.error = BAD_ARGS;
6573
6574 else if (skip_past_comma (& str) == FAIL
6575 || accum0_required_here (& str) == FAIL)
6576 inst.error = ERR_NO_ACCUM;
6577
6578 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6579 else if (rdlo == rdhi)
6580 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6581
6582 else if (rdlo == REG_PC || rdhi == REG_PC)
6583 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6584 else
6585 end_of_line (str);
6586}
6587
c9b604bd 6588/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6589
6590 PLD <addr_mode>
6591
6592 Syntactically, like LDR with B=1, W=0, L=1. */
6593
6594static void
f2b7cb0a 6595do_pld (str)
b99bd4ef 6596 char * str;
b99bd4ef
NC
6597{
6598 int rd;
6599
b99bd4ef
NC
6600 skip_whitespace (str);
6601
6602 if (* str != '[')
6603 {
6604 inst.error = _("'[' expected after PLD mnemonic");
6605 return;
6606 }
6607
90e4755a 6608 ++str;
b99bd4ef
NC
6609 skip_whitespace (str);
6610
6611 if ((rd = reg_required_here (& str, 16)) == FAIL)
6612 return;
6613
6614 skip_whitespace (str);
6615
90e4755a 6616 if (*str == ']')
b99bd4ef
NC
6617 {
6618 /* [Rn], ... ? */
90e4755a 6619 ++str;
b99bd4ef
NC
6620 skip_whitespace (str);
6621
90e4755a
RE
6622 /* Post-indexed addressing is not allowed with PLD. */
6623 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6624 {
90e4755a
RE
6625 inst.error
6626 = _("post-indexed expression used in preload instruction");
6627 return;
b99bd4ef 6628 }
90e4755a 6629 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6630 {
6631 inst.error = _("writeback used in preload instruction");
90e4755a 6632 ++str;
b99bd4ef
NC
6633 }
6634 else /* [Rn] */
6635 inst.instruction |= INDEX_UP | PRE_INDEX;
6636 }
6637 else /* [Rn, ...] */
6638 {
6639 if (skip_past_comma (& str) == FAIL)
6640 {
6641 inst.error = _("pre-indexed expression expected");
6642 return;
6643 }
6644
90e4755a 6645 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6646 return;
6647
6648 skip_whitespace (str);
6649
6650 if (* str != ']')
6651 {
6652 inst.error = _("missing ]");
6653 return;
6654 }
6655
6656 ++ str;
6657 skip_whitespace (str);
6658
6659 if (* str == '!') /* [Rn]! */
6660 {
6661 inst.error = _("writeback used in preload instruction");
6662 ++ str;
6663 }
6664
6665 inst.instruction |= PRE_INDEX;
6666 }
6667
6668 end_of_line (str);
6669}
6670
c9b604bd 6671/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6672 Mode is like LDRH.
6673
6674 LDRccD R, mode
6675 STRccD R, mode. */
6676
6677static void
f2b7cb0a 6678do_ldrd (str)
b99bd4ef 6679 char * str;
b99bd4ef
NC
6680{
6681 int rd;
6682 int rn;
6683
b99bd4ef
NC
6684 skip_whitespace (str);
6685
6686 if ((rd = reg_required_here (& str, 12)) == FAIL)
6687 {
6688 inst.error = BAD_ARGS;
6689 return;
6690 }
6691
6692 if (skip_past_comma (& str) == FAIL
6693 || (rn = ld_mode_required_here (& str)) == FAIL)
6694 {
6695 if (!inst.error)
cc8a6dd0 6696 inst.error = BAD_ARGS;
b99bd4ef
NC
6697 return;
6698 }
6699
6700 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6701 if (rd & 1) /* Unpredictable result if Rd is odd. */
6702 {
f03698e6 6703 inst.error = _("destination register must be even");
b99bd4ef
NC
6704 return;
6705 }
6706
90e4755a 6707 if (rd == REG_LR)
b99bd4ef 6708 {
f2b7cb0a 6709 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6710 return;
6711 }
6712
6713 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6714 && ((inst.instruction & WRITE_BACK)
6715 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6716 as_warn (_("pre/post-indexing used when modified address register is destination"));
6717
90e4755a
RE
6718 /* For an index-register load, the index register must not overlap the
6719 destination (even if not write-back). */
6720 if ((inst.instruction & V4_STR_BIT) == 0
6721 && (inst.instruction & HWOFFSET_IMM) == 0)
6722 {
6723 int rm = inst.instruction & 0x0000000f;
6724
6725 if (rm == rd || (rm == rd + 1))
6726 as_warn (_("ldrd destination registers must not overlap index register"));
6727 }
6728
b99bd4ef
NC
6729 end_of_line (str);
6730}
6731
6732/* Returns the index into fp_values of a floating point number,
6733 or -1 if not in the table. */
6734
6735static int
6736my_get_float_expression (str)
6737 char ** str;
6738{
6739 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6740 char * save_in;
6741 expressionS exp;
6742 int i;
6743 int j;
6744
6745 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6746
6747 /* Look for a raw floating point number. */
6748 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6749 && is_end_of_line[(unsigned char) *save_in])
6750 {
6751 for (i = 0; i < NUM_FLOAT_VALS; i++)
6752 {
6753 for (j = 0; j < MAX_LITTLENUMS; j++)
6754 {
6755 if (words[j] != fp_values[i][j])
6756 break;
6757 }
6758
6759 if (j == MAX_LITTLENUMS)
6760 {
6761 *str = save_in;
6762 return i;
6763 }
6764 }
6765 }
6766
6767 /* Try and parse a more complex expression, this will probably fail
6768 unless the code uses a floating point prefix (eg "0f"). */
6769 save_in = input_line_pointer;
6770 input_line_pointer = *str;
6771 if (expression (&exp) == absolute_section
6772 && exp.X_op == O_big
6773 && exp.X_add_number < 0)
6774 {
6775 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6776 Ditto for 15. */
6777 if (gen_to_words (words, 5, (long) 15) == 0)
6778 {
6779 for (i = 0; i < NUM_FLOAT_VALS; i++)
6780 {
6781 for (j = 0; j < MAX_LITTLENUMS; j++)
6782 {
6783 if (words[j] != fp_values[i][j])
6784 break;
6785 }
6786
6787 if (j == MAX_LITTLENUMS)
6788 {
6789 *str = input_line_pointer;
6790 input_line_pointer = save_in;
6791 return i;
6792 }
6793 }
6794 }
6795 }
6796
6797 *str = input_line_pointer;
6798 input_line_pointer = save_in;
6799 return -1;
6800}
6801
b34976b6 6802/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6803
6804static int
6805walk_no_bignums (sp)
6806 symbolS * sp;
6807{
6808 if (symbol_get_value_expression (sp)->X_op == O_big)
6809 return 1;
6810
6811 if (symbol_get_value_expression (sp)->X_add_symbol)
6812 {
6813 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6814 || (symbol_get_value_expression (sp)->X_op_symbol
6815 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6816 }
6817
6818 return 0;
6819}
6820
f03698e6
RE
6821static int in_my_get_expression = 0;
6822
b99bd4ef
NC
6823static int
6824my_get_expression (ep, str)
6825 expressionS * ep;
6826 char ** str;
6827{
6828 char * save_in;
6829 segT seg;
6830
6831 save_in = input_line_pointer;
6832 input_line_pointer = *str;
f03698e6 6833 in_my_get_expression = 1;
b99bd4ef 6834 seg = expression (ep);
f03698e6
RE
6835 in_my_get_expression = 0;
6836
6837 if (ep->X_op == O_illegal)
6838 {
6839 /* We found a bad expression in md_operand(). */
6840 *str = input_line_pointer;
6841 input_line_pointer = save_in;
6842 return 1;
6843 }
b99bd4ef
NC
6844
6845#ifdef OBJ_AOUT
6846 if (seg != absolute_section
6847 && seg != text_section
6848 && seg != data_section
6849 && seg != bss_section
6850 && seg != undefined_section)
6851 {
6852 inst.error = _("bad_segment");
6853 *str = input_line_pointer;
6854 input_line_pointer = save_in;
6855 return 1;
6856 }
6857#endif
6858
6859 /* Get rid of any bignums now, so that we don't generate an error for which
6860 we can't establish a line number later on. Big numbers are never valid
6861 in instructions, which is where this routine is always called. */
6862 if (ep->X_op == O_big
6863 || (ep->X_add_symbol
6864 && (walk_no_bignums (ep->X_add_symbol)
6865 || (ep->X_op_symbol
6866 && walk_no_bignums (ep->X_op_symbol)))))
6867 {
f03698e6 6868 inst.error = _("invalid constant");
b99bd4ef
NC
6869 *str = input_line_pointer;
6870 input_line_pointer = save_in;
6871 return 1;
6872 }
6873
6874 *str = input_line_pointer;
6875 input_line_pointer = save_in;
6876 return 0;
6877}
6878
cc8a6dd0 6879/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6880 instruction in the error message. */
6881void
ce058b6c 6882md_operand (expr)
f03698e6
RE
6883 expressionS *expr;
6884{
6885 if (in_my_get_expression)
6886 {
6887 expr->X_op = O_illegal;
6888 if (inst.error == NULL)
6889 inst.error = _("bad expression");
6890 }
6891}
6892
09d92015 6893/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6894
6895static int
09d92015 6896decode_shift (str, kind)
b99bd4ef 6897 char ** str;
09d92015 6898 int kind;
b99bd4ef
NC
6899{
6900 const struct asm_shift_name * shift;
6901 char * p;
6902 char c;
6903
6904 skip_whitespace (* str);
6905
3882b010 6906 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6907 ;
6908
6909 if (p == * str)
6910 {
f03698e6 6911 inst.error = _("shift expression expected");
b99bd4ef
NC
6912 return FAIL;
6913 }
6914
6915 c = * p;
6916 * p = '\0';
6917 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6918 * p = c;
6919
6920 if (shift == NULL)
6921 {
f03698e6 6922 inst.error = _("shift expression expected");
b99bd4ef
NC
6923 return FAIL;
6924 }
6925
6926 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6927
09d92015
MM
6928 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6929 && shift->properties->index != SHIFT_LSL
6930 && shift->properties->index != SHIFT_ASR)
6931 {
6932 inst.error = _("'LSL' or 'ASR' required");
6933 return FAIL;
6934 }
6935 else if (kind == SHIFT_LSL_IMMEDIATE
6936 && shift->properties->index != SHIFT_LSL)
6937 {
6938 inst.error = _("'LSL' required");
6939 return FAIL;
6940 }
6941 else if (kind == SHIFT_ASR_IMMEDIATE
6942 && shift->properties->index != SHIFT_ASR)
6943 {
6944 inst.error = _("'ASR' required");
6945 return FAIL;
6946 }
6947
b99bd4ef
NC
6948 if (shift->properties->index == SHIFT_RRX)
6949 {
6950 * str = p;
6951 inst.instruction |= shift->properties->bit_field;
6952 return SUCCESS;
6953 }
6954
6955 skip_whitespace (p);
6956
09d92015 6957 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6958 {
6959 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6960 * str = p;
6961 return SUCCESS;
6962 }
6963 else if (! is_immediate_prefix (* p))
6964 {
09d92015 6965 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6966 ? _("shift requires register or #expression")
6967 : _("shift requires #expression"));
6968 * str = p;
6969 return FAIL;
6970 }
6971
6972 inst.error = NULL;
6973 p ++;
6974
6975 if (my_get_expression (& inst.reloc.exp, & p))
6976 return FAIL;
6977
6978 /* Validate some simple #expressions. */
6979 if (inst.reloc.exp.X_op == O_constant)
6980 {
6981 unsigned num = inst.reloc.exp.X_add_number;
6982
6983 /* Reject operations greater than 32. */
6984 if (num > 32
6985 /* Reject a shift of 0 unless the mode allows it. */
6986 || (num == 0 && shift->properties->allows_0 == 0)
6987 /* Reject a shift of 32 unless the mode allows it. */
6988 || (num == 32 && shift->properties->allows_32 == 0)
6989 )
6990 {
6991 /* As a special case we allow a shift of zero for
6992 modes that do not support it to be recoded as an
6993 logical shift left of zero (ie nothing). We warn
6994 about this though. */
6995 if (num == 0)
6996 {
f03698e6 6997 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
6998 shift = & shift_names[0];
6999 assert (shift->properties->index == SHIFT_LSL);
7000 }
7001 else
7002 {
f03698e6 7003 inst.error = _("invalid immediate shift");
b99bd4ef
NC
7004 return FAIL;
7005 }
7006 }
7007
7008 /* Shifts of 32 are encoded as 0, for those shifts that
7009 support it. */
7010 if (num == 32)
7011 num = 0;
7012
7013 inst.instruction |= (num << 7) | shift->properties->bit_field;
7014 }
7015 else
7016 {
7017 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7018 inst.reloc.pc_rel = 0;
7019 inst.instruction |= shift->properties->bit_field;
7020 }
7021
7022 * str = p;
7023 return SUCCESS;
7024}
7025
7026/* Do those data_ops which can take a negative immediate constant
2d2255b5 7027 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
7028 MOV <-> MVN
7029 AND <-> BIC
7030 ADC <-> SBC
7031 by inverting the second operand, and
7032 ADD <-> SUB
7033 CMP <-> CMN
7034 by negating the second operand. */
7035
7036static int
7037negate_data_op (instruction, value)
7038 unsigned long * instruction;
7039 unsigned long value;
7040{
7041 int op, new_inst;
7042 unsigned long negated, inverted;
7043
7044 negated = validate_immediate (-value);
7045 inverted = validate_immediate (~value);
7046
7047 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7048 switch (op)
7049 {
7050 /* First negates. */
7051 case OPCODE_SUB: /* ADD <-> SUB */
7052 new_inst = OPCODE_ADD;
7053 value = negated;
7054 break;
7055
7056 case OPCODE_ADD:
7057 new_inst = OPCODE_SUB;
7058 value = negated;
7059 break;
7060
7061 case OPCODE_CMP: /* CMP <-> CMN */
7062 new_inst = OPCODE_CMN;
7063 value = negated;
7064 break;
7065
7066 case OPCODE_CMN:
7067 new_inst = OPCODE_CMP;
7068 value = negated;
7069 break;
7070
7071 /* Now Inverted ops. */
7072 case OPCODE_MOV: /* MOV <-> MVN */
7073 new_inst = OPCODE_MVN;
7074 value = inverted;
7075 break;
7076
7077 case OPCODE_MVN:
7078 new_inst = OPCODE_MOV;
7079 value = inverted;
7080 break;
7081
7082 case OPCODE_AND: /* AND <-> BIC */
7083 new_inst = OPCODE_BIC;
7084 value = inverted;
7085 break;
7086
7087 case OPCODE_BIC:
7088 new_inst = OPCODE_AND;
7089 value = inverted;
7090 break;
7091
7092 case OPCODE_ADC: /* ADC <-> SBC */
7093 new_inst = OPCODE_SBC;
7094 value = inverted;
7095 break;
7096
7097 case OPCODE_SBC:
7098 new_inst = OPCODE_ADC;
7099 value = inverted;
7100 break;
7101
7102 /* We cannot do anything. */
7103 default:
7104 return FAIL;
7105 }
7106
7107 if (value == (unsigned) FAIL)
7108 return FAIL;
7109
7110 *instruction &= OPCODE_MASK;
7111 *instruction |= new_inst << DATA_OP_SHIFT;
7112 return value;
7113}
7114
7115static int
7116data_op2 (str)
7117 char ** str;
7118{
7119 int value;
7120 expressionS expr;
7121
7122 skip_whitespace (* str);
7123
7124 if (reg_required_here (str, 0) != FAIL)
7125 {
7126 if (skip_past_comma (str) == SUCCESS)
7127 /* Shift operation on register. */
7128 return decode_shift (str, NO_SHIFT_RESTRICT);
7129
7130 return SUCCESS;
7131 }
7132 else
7133 {
7134 /* Immediate expression. */
7135 if (is_immediate_prefix (**str))
7136 {
7137 (*str)++;
7138 inst.error = NULL;
7139
7140 if (my_get_expression (&inst.reloc.exp, str))
7141 return FAIL;
7142
7143 if (inst.reloc.exp.X_add_symbol)
7144 {
7145 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7146 inst.reloc.pc_rel = 0;
7147 }
7148 else
7149 {
7150 if (skip_past_comma (str) == SUCCESS)
7151 {
7152 /* #x, y -- ie explicit rotation by Y. */
7153 if (my_get_expression (&expr, str))
7154 return FAIL;
7155
7156 if (expr.X_op != O_constant)
7157 {
f03698e6 7158 inst.error = _("constant expression expected");
b99bd4ef
NC
7159 return FAIL;
7160 }
7161
7162 /* Rotate must be a multiple of 2. */
7163 if (((unsigned) expr.X_add_number) > 30
7164 || (expr.X_add_number & 1) != 0
7165 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7166 {
f03698e6 7167 inst.error = _("invalid constant");
b99bd4ef
NC
7168 return FAIL;
7169 }
7170 inst.instruction |= INST_IMMEDIATE;
7171 inst.instruction |= inst.reloc.exp.X_add_number;
7172 inst.instruction |= expr.X_add_number << 7;
7173 return SUCCESS;
7174 }
7175
7176 /* Implicit rotation, select a suitable one. */
7177 value = validate_immediate (inst.reloc.exp.X_add_number);
7178
7179 if (value == FAIL)
7180 {
7181 /* Can't be done. Perhaps the code reads something like
7182 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7183 if ((value = negate_data_op (&inst.instruction,
7184 inst.reloc.exp.X_add_number))
7185 == FAIL)
7186 {
f03698e6 7187 inst.error = _("invalid constant");
b99bd4ef
NC
7188 return FAIL;
7189 }
7190 }
7191
7192 inst.instruction |= value;
7193 }
7194
7195 inst.instruction |= INST_IMMEDIATE;
7196 return SUCCESS;
7197 }
7198
7199 (*str)++;
f03698e6 7200 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7201 return FAIL;
7202 }
7203}
7204
7205static int
7206fp_op2 (str)
7207 char ** str;
7208{
7209 skip_whitespace (* str);
7210
7211 if (fp_reg_required_here (str, 0) != FAIL)
7212 return SUCCESS;
7213 else
7214 {
7215 /* Immediate expression. */
7216 if (*((*str)++) == '#')
7217 {
7218 int i;
7219
7220 inst.error = NULL;
7221
7222 skip_whitespace (* str);
7223
7224 /* First try and match exact strings, this is to guarantee
7225 that some formats will work even for cross assembly. */
7226
7227 for (i = 0; fp_const[i]; i++)
7228 {
7229 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7230 {
7231 char *start = *str;
7232
7233 *str += strlen (fp_const[i]);
7234 if (is_end_of_line[(unsigned char) **str])
7235 {
7236 inst.instruction |= i + 8;
7237 return SUCCESS;
7238 }
7239 *str = start;
7240 }
7241 }
7242
7243 /* Just because we didn't get a match doesn't mean that the
7244 constant isn't valid, just that it is in a format that we
7245 don't automatically recognize. Try parsing it with
7246 the standard expression routines. */
7247 if ((i = my_get_float_expression (str)) >= 0)
7248 {
7249 inst.instruction |= i + 8;
7250 return SUCCESS;
7251 }
7252
f03698e6 7253 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7254 return FAIL;
7255 }
7256 inst.error =
f03698e6 7257 _("floating point register or immediate expression expected");
b99bd4ef
NC
7258 return FAIL;
7259 }
7260}
7261
7262static void
f2b7cb0a 7263do_arit (str)
b99bd4ef 7264 char * str;
b99bd4ef
NC
7265{
7266 skip_whitespace (str);
7267
7268 if (reg_required_here (&str, 12) == FAIL
7269 || skip_past_comma (&str) == FAIL
7270 || reg_required_here (&str, 16) == FAIL
7271 || skip_past_comma (&str) == FAIL
7272 || data_op2 (&str) == FAIL)
7273 {
7274 if (!inst.error)
7275 inst.error = BAD_ARGS;
7276 return;
7277 }
7278
b99bd4ef 7279 end_of_line (str);
b99bd4ef
NC
7280}
7281
7282static void
f2b7cb0a 7283do_adr (str)
b99bd4ef 7284 char * str;
b99bd4ef 7285{
90e4755a
RE
7286 /* This is a pseudo-op of the form "adr rd, label" to be converted
7287 into a relative address of the form "add rd, pc, #label-.-8". */
7288 skip_whitespace (str);
7289
7290 if (reg_required_here (&str, 12) == FAIL
7291 || skip_past_comma (&str) == FAIL
7292 || my_get_expression (&inst.reloc.exp, &str))
7293 {
7294 if (!inst.error)
7295 inst.error = BAD_ARGS;
7296 return;
7297 }
7298
7299 /* Frag hacking will turn this into a sub instruction if the offset turns
7300 out to be negative. */
7301 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 7302#ifndef TE_WINCE
90e4755a 7303 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 7304#endif
90e4755a
RE
7305 inst.reloc.pc_rel = 1;
7306
7307 end_of_line (str);
7308}
7309
7310static void
f2b7cb0a 7311do_adrl (str)
90e4755a 7312 char * str;
90e4755a
RE
7313{
7314 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7315 into a relative address of the form:
7316 add rd, pc, #low(label-.-8)"
7317 add rd, rd, #high(label-.-8)" */
7318
7319 skip_whitespace (str);
7320
7321 if (reg_required_here (&str, 12) == FAIL
7322 || skip_past_comma (&str) == FAIL
7323 || my_get_expression (&inst.reloc.exp, &str))
7324 {
7325 if (!inst.error)
7326 inst.error = BAD_ARGS;
7327
7328 return;
7329 }
7330
7331 end_of_line (str);
7332 /* Frag hacking will turn this into a sub instruction if the offset turns
7333 out to be negative. */
7334 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
250355db 7335#ifndef TE_WINCE
90e4755a 7336 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 7337#endif
90e4755a
RE
7338 inst.reloc.pc_rel = 1;
7339 inst.size = INSN_SIZE * 2;
90e4755a
RE
7340}
7341
7342static void
f2b7cb0a 7343do_cmp (str)
90e4755a 7344 char * str;
90e4755a
RE
7345{
7346 skip_whitespace (str);
7347
7348 if (reg_required_here (&str, 16) == FAIL)
7349 {
7350 if (!inst.error)
7351 inst.error = BAD_ARGS;
7352 return;
7353 }
7354
7355 if (skip_past_comma (&str) == FAIL
7356 || data_op2 (&str) == FAIL)
7357 {
7358 if (!inst.error)
7359 inst.error = BAD_ARGS;
7360 return;
7361 }
7362
90e4755a 7363 end_of_line (str);
90e4755a
RE
7364}
7365
7366static void
f2b7cb0a 7367do_mov (str)
90e4755a 7368 char * str;
90e4755a
RE
7369{
7370 skip_whitespace (str);
7371
7372 if (reg_required_here (&str, 12) == FAIL)
7373 {
7374 if (!inst.error)
7375 inst.error = BAD_ARGS;
7376 return;
7377 }
7378
7379 if (skip_past_comma (&str) == FAIL
7380 || data_op2 (&str) == FAIL)
7381 {
7382 if (!inst.error)
7383 inst.error = BAD_ARGS;
7384 return;
7385 }
7386
90e4755a 7387 end_of_line (str);
90e4755a
RE
7388}
7389
7390static int
7391ldst_extend (str)
7392 char ** str;
7393{
7394 int add = INDEX_UP;
7395
7396 switch (**str)
7397 {
7398 case '#':
7399 case '$':
7400 (*str)++;
7401 if (my_get_expression (& inst.reloc.exp, str))
7402 return FAIL;
7403
7404 if (inst.reloc.exp.X_op == O_constant)
7405 {
7406 int value = inst.reloc.exp.X_add_number;
7407
7408 if (value < -4095 || value > 4095)
7409 {
7410 inst.error = _("address offset too large");
7411 return FAIL;
7412 }
7413
7414 if (value < 0)
7415 {
7416 value = -value;
7417 add = 0;
7418 }
7419
7420 inst.instruction |= add | value;
7421 }
7422 else
7423 {
7424 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7425 inst.reloc.pc_rel = 0;
7426 }
7427 return SUCCESS;
7428
7429 case '-':
7430 add = 0;
7431 /* Fall through. */
7432
7433 case '+':
7434 (*str)++;
7435 /* Fall through. */
7436
7437 default:
7438 if (reg_required_here (str, 0) == FAIL)
7439 return FAIL;
7440
7441 inst.instruction |= add | OFFSET_REG;
7442 if (skip_past_comma (str) == SUCCESS)
09d92015 7443 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7444
7445 return SUCCESS;
7446 }
7447}
7448
7449static void
f2b7cb0a 7450do_ldst (str)
90e4755a 7451 char * str;
90e4755a
RE
7452{
7453 int pre_inc = 0;
7454 int conflict_reg;
7455 int value;
7456
b99bd4ef
NC
7457 skip_whitespace (str);
7458
90e4755a
RE
7459 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7460 {
7461 if (!inst.error)
7462 inst.error = BAD_ARGS;
7463 return;
7464 }
7465
7466 if (skip_past_comma (&str) == FAIL)
7467 {
f03698e6 7468 inst.error = _("address expected");
90e4755a
RE
7469 return;
7470 }
7471
90e4755a
RE
7472 if (*str == '[')
7473 {
7474 int reg;
7475
7476 str++;
7477
7478 skip_whitespace (str);
7479
7480 if ((reg = reg_required_here (&str, 16)) == FAIL)
7481 return;
7482
7483 /* Conflicts can occur on stores as well as loads. */
7484 conflict_reg = (conflict_reg == reg);
7485
7486 skip_whitespace (str);
7487
7488 if (*str == ']')
7489 {
7490 str ++;
7491
7492 if (skip_past_comma (&str) == SUCCESS)
7493 {
7494 /* [Rn],... (post inc) */
7495 if (ldst_extend (&str) == FAIL)
7496 return;
7497 if (conflict_reg)
7498 as_warn (_("%s register same as write-back base"),
7499 ((inst.instruction & LOAD_BIT)
7500 ? _("destination") : _("source")));
7501 }
7502 else
7503 {
7504 /* [Rn] */
7505 skip_whitespace (str);
7506
7507 if (*str == '!')
7508 {
7509 if (conflict_reg)
7510 as_warn (_("%s register same as write-back base"),
7511 ((inst.instruction & LOAD_BIT)
7512 ? _("destination") : _("source")));
7513 str++;
7514 inst.instruction |= WRITE_BACK;
7515 }
7516
7517 inst.instruction |= INDEX_UP;
7518 pre_inc = 1;
7519 }
7520 }
7521 else
7522 {
7523 /* [Rn,...] */
7524 if (skip_past_comma (&str) == FAIL)
7525 {
7526 inst.error = _("pre-indexed expression expected");
7527 return;
7528 }
7529
7530 pre_inc = 1;
7531 if (ldst_extend (&str) == FAIL)
7532 return;
7533
7534 skip_whitespace (str);
7535
7536 if (*str++ != ']')
7537 {
7538 inst.error = _("missing ]");
7539 return;
7540 }
7541
7542 skip_whitespace (str);
7543
7544 if (*str == '!')
7545 {
7546 if (conflict_reg)
7547 as_warn (_("%s register same as write-back base"),
7548 ((inst.instruction & LOAD_BIT)
7549 ? _("destination") : _("source")));
7550 str++;
7551 inst.instruction |= WRITE_BACK;
7552 }
7553 }
7554 }
7555 else if (*str == '=')
7556 {
f03698e6
RE
7557 if ((inst.instruction & LOAD_BIT) == 0)
7558 {
7559 inst.error = _("invalid pseudo operation");
7560 return;
7561 }
7562
90e4755a
RE
7563 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7564 str++;
7565
7566 skip_whitespace (str);
7567
7568 if (my_get_expression (&inst.reloc.exp, &str))
7569 return;
7570
7571 if (inst.reloc.exp.X_op != O_constant
7572 && inst.reloc.exp.X_op != O_symbol)
7573 {
f03698e6 7574 inst.error = _("constant expression expected");
90e4755a
RE
7575 return;
7576 }
7577
e28cd48c 7578 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7579 {
e28cd48c
RE
7580 value = validate_immediate (inst.reloc.exp.X_add_number);
7581
7582 if (value != FAIL)
90e4755a 7583 {
e28cd48c
RE
7584 /* This can be done with a mov instruction. */
7585 inst.instruction &= LITERAL_MASK;
7586 inst.instruction |= (INST_IMMEDIATE
7587 | (OPCODE_MOV << DATA_OP_SHIFT));
7588 inst.instruction |= value & 0xfff;
7589 end_of_line (str);
90e4755a
RE
7590 return;
7591 }
b99bd4ef 7592
e28cd48c
RE
7593 value = validate_immediate (~inst.reloc.exp.X_add_number);
7594
7595 if (value != FAIL)
7596 {
7597 /* This can be done with a mvn instruction. */
7598 inst.instruction &= LITERAL_MASK;
7599 inst.instruction |= (INST_IMMEDIATE
7600 | (OPCODE_MVN << DATA_OP_SHIFT));
7601 inst.instruction |= value & 0xfff;
7602 end_of_line (str);
7603 return;
7604 }
90e4755a 7605 }
e28cd48c
RE
7606
7607 /* Insert into literal pool. */
7608 if (add_to_lit_pool () == FAIL)
7609 {
7610 if (!inst.error)
7611 inst.error = _("literal pool insertion failed");
7612 return;
7613 }
7614
7615 /* Change the instruction exp to point to the pool. */
7616 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7617 inst.reloc.pc_rel = 1;
7618 inst.instruction |= (REG_PC << 16);
7619 pre_inc = 1;
1cac9012
NC
7620 }
7621 else
7622 {
90e4755a
RE
7623 if (my_get_expression (&inst.reloc.exp, &str))
7624 return;
7625
7626 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7627#ifndef TE_WINCE
7628 /* PC rel adjust. */
7629 inst.reloc.exp.X_add_number -= 8;
7630#endif
1cac9012 7631 inst.reloc.pc_rel = 1;
90e4755a
RE
7632 inst.instruction |= (REG_PC << 16);
7633 pre_inc = 1;
b99bd4ef
NC
7634 }
7635
90e4755a 7636 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7637 end_of_line (str);
b99bd4ef
NC
7638}
7639
7640static void
f2b7cb0a 7641do_ldstt (str)
90e4755a 7642 char * str;
b99bd4ef 7643{
90e4755a
RE
7644 int conflict_reg;
7645
b99bd4ef
NC
7646 skip_whitespace (str);
7647
90e4755a 7648 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7649 {
7650 if (!inst.error)
7651 inst.error = BAD_ARGS;
7652 return;
7653 }
7654
90e4755a 7655 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7656 {
f03698e6 7657 inst.error = _("address expected");
b99bd4ef
NC
7658 return;
7659 }
7660
90e4755a
RE
7661 if (*str == '[')
7662 {
7663 int reg;
b99bd4ef 7664
90e4755a 7665 str++;
b99bd4ef 7666
90e4755a 7667 skip_whitespace (str);
b99bd4ef 7668
90e4755a
RE
7669 if ((reg = reg_required_here (&str, 16)) == FAIL)
7670 return;
b99bd4ef 7671
90e4755a
RE
7672 /* ldrt/strt always use post-indexed addressing, so if the base is
7673 the same as Rd, we warn. */
7674 if (conflict_reg == reg)
7675 as_warn (_("%s register same as write-back base"),
7676 ((inst.instruction & LOAD_BIT)
7677 ? _("destination") : _("source")));
7678
7679 skip_whitespace (str);
7680
7681 if (*str == ']')
7682 {
7683 str ++;
7684
7685 if (skip_past_comma (&str) == SUCCESS)
7686 {
7687 /* [Rn],... (post inc) */
7688 if (ldst_extend (&str) == FAIL)
7689 return;
7690 }
7691 else
7692 {
7693 /* [Rn] */
7694 skip_whitespace (str);
7695
7696 /* Skip a write-back '!'. */
7697 if (*str == '!')
7698 str++;
7699
7700 inst.instruction |= INDEX_UP;
7701 }
7702 }
7703 else
7704 {
7705 inst.error = _("post-indexed expression expected");
7706 return;
7707 }
7708 }
7709 else
b99bd4ef 7710 {
90e4755a 7711 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7712 return;
7713 }
7714
b99bd4ef 7715 end_of_line (str);
b99bd4ef
NC
7716}
7717
7718static int
90e4755a 7719ldst_extend_v4 (str)
b99bd4ef 7720 char ** str;
b99bd4ef
NC
7721{
7722 int add = INDEX_UP;
7723
7724 switch (**str)
7725 {
7726 case '#':
7727 case '$':
7728 (*str)++;
7729 if (my_get_expression (& inst.reloc.exp, str))
7730 return FAIL;
7731
7732 if (inst.reloc.exp.X_op == O_constant)
7733 {
7734 int value = inst.reloc.exp.X_add_number;
7735
90e4755a 7736 if (value < -255 || value > 255)
b99bd4ef
NC
7737 {
7738 inst.error = _("address offset too large");
7739 return FAIL;
7740 }
7741
7742 if (value < 0)
7743 {
7744 value = -value;
7745 add = 0;
7746 }
7747
7748 /* Halfword and signextension instructions have the
7749 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7750 inst.instruction |= (add | HWOFFSET_IMM
7751 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7752 }
7753 else
7754 {
90e4755a
RE
7755 inst.instruction |= HWOFFSET_IMM;
7756 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7757 inst.reloc.pc_rel = 0;
7758 }
7759 return SUCCESS;
7760
7761 case '-':
7762 add = 0;
7763 /* Fall through. */
7764
7765 case '+':
7766 (*str)++;
7767 /* Fall through. */
7768
7769 default:
7770 if (reg_required_here (str, 0) == FAIL)
7771 return FAIL;
7772
90e4755a 7773 inst.instruction |= add;
b99bd4ef
NC
7774 return SUCCESS;
7775 }
7776}
7777
90e4755a 7778/* Halfword and signed-byte load/store operations. */
b99bd4ef 7779static void
f2b7cb0a 7780do_ldstv4 (str)
b99bd4ef 7781 char * str;
b99bd4ef 7782{
b99bd4ef
NC
7783 int pre_inc = 0;
7784 int conflict_reg;
7785 int value;
7786
b99bd4ef
NC
7787 skip_whitespace (str);
7788
7789 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7790 {
7791 if (!inst.error)
7792 inst.error = BAD_ARGS;
7793 return;
7794 }
7795
7796 if (skip_past_comma (& str) == FAIL)
7797 {
f03698e6 7798 inst.error = _("address expected");
b99bd4ef
NC
7799 return;
7800 }
7801
7802 if (*str == '[')
7803 {
7804 int reg;
7805
7806 str++;
7807
7808 skip_whitespace (str);
7809
7810 if ((reg = reg_required_here (&str, 16)) == FAIL)
7811 return;
7812
7813 /* Conflicts can occur on stores as well as loads. */
7814 conflict_reg = (conflict_reg == reg);
7815
7816 skip_whitespace (str);
7817
7818 if (*str == ']')
7819 {
7820 str ++;
7821
7822 if (skip_past_comma (&str) == SUCCESS)
7823 {
7824 /* [Rn],... (post inc) */
90e4755a 7825 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7826 return;
7827 if (conflict_reg)
90e4755a
RE
7828 as_warn (_("%s register same as write-back base"),
7829 ((inst.instruction & LOAD_BIT)
7830 ? _("destination") : _("source")));
b99bd4ef
NC
7831 }
7832 else
7833 {
7834 /* [Rn] */
90e4755a 7835 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7836
7837 skip_whitespace (str);
7838
7839 if (*str == '!')
7840 {
7841 if (conflict_reg)
7842 as_warn (_("%s register same as write-back base"),
7843 ((inst.instruction & LOAD_BIT)
7844 ? _("destination") : _("source")));
7845 str++;
7846 inst.instruction |= WRITE_BACK;
7847 }
7848
90e4755a
RE
7849 inst.instruction |= INDEX_UP;
7850 pre_inc = 1;
b99bd4ef
NC
7851 }
7852 }
7853 else
7854 {
7855 /* [Rn,...] */
7856 if (skip_past_comma (&str) == FAIL)
7857 {
7858 inst.error = _("pre-indexed expression expected");
7859 return;
7860 }
7861
7862 pre_inc = 1;
90e4755a 7863 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7864 return;
7865
7866 skip_whitespace (str);
7867
7868 if (*str++ != ']')
7869 {
7870 inst.error = _("missing ]");
7871 return;
7872 }
7873
7874 skip_whitespace (str);
7875
7876 if (*str == '!')
7877 {
7878 if (conflict_reg)
7879 as_warn (_("%s register same as write-back base"),
7880 ((inst.instruction & LOAD_BIT)
7881 ? _("destination") : _("source")));
7882 str++;
7883 inst.instruction |= WRITE_BACK;
7884 }
7885 }
7886 }
7887 else if (*str == '=')
7888 {
f03698e6
RE
7889 if ((inst.instruction & LOAD_BIT) == 0)
7890 {
7891 inst.error = _("invalid pseudo operation");
7892 return;
7893 }
7894
90e4755a 7895 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7896 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7897 str++;
7898
7899 skip_whitespace (str);
7900
7901 if (my_get_expression (&inst.reloc.exp, &str))
7902 return;
7903
7904 if (inst.reloc.exp.X_op != O_constant
7905 && inst.reloc.exp.X_op != O_symbol)
7906 {
f03698e6 7907 inst.error = _("constant expression expected");
b99bd4ef
NC
7908 return;
7909 }
7910
d8273442 7911 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7912 {
d8273442
NC
7913 value = validate_immediate (inst.reloc.exp.X_add_number);
7914
7915 if (value != FAIL)
b99bd4ef 7916 {
d8273442
NC
7917 /* This can be done with a mov instruction. */
7918 inst.instruction &= LITERAL_MASK;
7919 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7920 inst.instruction |= value & 0xfff;
d8273442 7921 end_of_line (str);
b99bd4ef
NC
7922 return;
7923 }
cc8a6dd0 7924
d8273442 7925 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7926
d8273442 7927 if (value != FAIL)
b99bd4ef 7928 {
d8273442
NC
7929 /* This can be done with a mvn instruction. */
7930 inst.instruction &= LITERAL_MASK;
7931 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7932 inst.instruction |= value & 0xfff;
d8273442
NC
7933 end_of_line (str);
7934 return;
b99bd4ef 7935 }
b99bd4ef 7936 }
d8273442
NC
7937
7938 /* Insert into literal pool. */
7939 if (add_to_lit_pool () == FAIL)
7940 {
7941 if (!inst.error)
7942 inst.error = _("literal pool insertion failed");
7943 return;
7944 }
7945
7946 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7947 inst.instruction |= HWOFFSET_IMM;
7948 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7949 inst.reloc.pc_rel = 1;
7950 inst.instruction |= (REG_PC << 16);
7951 pre_inc = 1;
b99bd4ef
NC
7952 }
7953 else
7954 {
7955 if (my_get_expression (&inst.reloc.exp, &str))
7956 return;
7957
90e4755a
RE
7958 inst.instruction |= HWOFFSET_IMM;
7959 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7960#ifndef TE_WINCE
7961 /* PC rel adjust. */
7962 inst.reloc.exp.X_add_number -= 8;
7963#endif
7964 inst.reloc.pc_rel = 1;
7965 inst.instruction |= (REG_PC << 16);
7966 pre_inc = 1;
7967 }
7968
90e4755a 7969 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7970 end_of_line (str);
b99bd4ef
NC
7971}
7972
7973static long
7974reg_list (strp)
7975 char ** strp;
7976{
7977 char * str = * strp;
7978 long range = 0;
7979 int another_range;
7980
7981 /* We come back here if we get ranges concatenated by '+' or '|'. */
7982 do
7983 {
7984 another_range = 0;
7985
7986 if (*str == '{')
7987 {
7988 int in_range = 0;
7989 int cur_reg = -1;
7990
7991 str++;
7992 do
7993 {
7994 int reg;
7995
7996 skip_whitespace (str);
7997
7998 if ((reg = reg_required_here (& str, -1)) == FAIL)
7999 return FAIL;
8000
8001 if (in_range)
8002 {
8003 int i;
8004
8005 if (reg <= cur_reg)
8006 {
f03698e6 8007 inst.error = _("bad range in register list");
b99bd4ef
NC
8008 return FAIL;
8009 }
8010
8011 for (i = cur_reg + 1; i < reg; i++)
8012 {
8013 if (range & (1 << i))
8014 as_tsktsk
f03698e6 8015 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8016 i);
8017 else
8018 range |= 1 << i;
8019 }
8020 in_range = 0;
8021 }
8022
8023 if (range & (1 << reg))
f03698e6 8024 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8025 reg);
8026 else if (reg <= cur_reg)
f03698e6 8027 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
8028
8029 range |= 1 << reg;
8030 cur_reg = reg;
8031 }
8032 while (skip_past_comma (&str) != FAIL
8033 || (in_range = 1, *str++ == '-'));
8034 str--;
8035 skip_whitespace (str);
8036
8037 if (*str++ != '}')
8038 {
f03698e6 8039 inst.error = _("missing `}'");
b99bd4ef
NC
8040 return FAIL;
8041 }
8042 }
8043 else
8044 {
8045 expressionS expr;
8046
8047 if (my_get_expression (&expr, &str))
8048 return FAIL;
8049
8050 if (expr.X_op == O_constant)
8051 {
8052 if (expr.X_add_number
8053 != (expr.X_add_number & 0x0000ffff))
8054 {
8055 inst.error = _("invalid register mask");
8056 return FAIL;
8057 }
8058
8059 if ((range & expr.X_add_number) != 0)
8060 {
8061 int regno = range & expr.X_add_number;
8062
8063 regno &= -regno;
8064 regno = (1 << regno) - 1;
8065 as_tsktsk
f03698e6 8066 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8067 regno);
8068 }
8069
8070 range |= expr.X_add_number;
8071 }
8072 else
8073 {
8074 if (inst.reloc.type != 0)
8075 {
8076 inst.error = _("expression too complex");
8077 return FAIL;
8078 }
8079
8080 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8081 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8082 inst.reloc.pc_rel = 0;
8083 }
8084 }
8085
8086 skip_whitespace (str);
8087
8088 if (*str == '|' || *str == '+')
8089 {
8090 str++;
8091 another_range = 1;
8092 }
8093 }
8094 while (another_range);
8095
8096 *strp = str;
8097 return range;
8098}
8099
8100static void
f2b7cb0a 8101do_ldmstm (str)
b99bd4ef 8102 char * str;
b99bd4ef
NC
8103{
8104 int base_reg;
8105 long range;
8106
8107 skip_whitespace (str);
8108
8109 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8110 return;
8111
8112 if (base_reg == REG_PC)
8113 {
8114 inst.error = _("r15 not allowed as base register");
8115 return;
8116 }
8117
8118 skip_whitespace (str);
8119
8120 if (*str == '!')
8121 {
90e4755a 8122 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8123 str++;
8124 }
8125
8126 if (skip_past_comma (&str) == FAIL
8127 || (range = reg_list (&str)) == FAIL)
8128 {
8129 if (! inst.error)
8130 inst.error = BAD_ARGS;
8131 return;
8132 }
8133
8134 if (*str == '^')
8135 {
8136 str++;
90e4755a 8137 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8138 }
8139
6189168b
NC
8140 if (inst.instruction & WRITE_BACK)
8141 {
8142 /* Check for unpredictable uses of writeback. */
8143 if (inst.instruction & LOAD_BIT)
8144 {
8145 /* Not allowed in LDM type 2. */
8146 if ((inst.instruction & LDM_TYPE_2_OR_3)
8147 && ((range & (1 << REG_PC)) == 0))
8148 as_warn (_("writeback of base register is UNPREDICTABLE"));
8149 /* Only allowed if base reg not in list for other types. */
8150 else if (range & (1 << base_reg))
8151 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8152 }
8153 else /* STM. */
8154 {
8155 /* Not allowed for type 2. */
8156 if (inst.instruction & LDM_TYPE_2_OR_3)
8157 as_warn (_("writeback of base register is UNPREDICTABLE"));
8158 /* Only allowed if base reg not in list, or first in list. */
8159 else if ((range & (1 << base_reg))
8160 && (range & ((1 << base_reg) - 1)))
8161 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8162 }
8163 }
61b5f74b 8164
f2b7cb0a 8165 inst.instruction |= range;
b99bd4ef 8166 end_of_line (str);
b99bd4ef
NC
8167}
8168
8169static void
f2b7cb0a 8170do_swi (str)
b99bd4ef 8171 char * str;
b99bd4ef
NC
8172{
8173 skip_whitespace (str);
8174
8175 /* Allow optional leading '#'. */
8176 if (is_immediate_prefix (*str))
8177 str++;
8178
8179 if (my_get_expression (& inst.reloc.exp, & str))
8180 return;
8181
8182 inst.reloc.type = BFD_RELOC_ARM_SWI;
8183 inst.reloc.pc_rel = 0;
b99bd4ef 8184 end_of_line (str);
b99bd4ef
NC
8185}
8186
8187static void
f2b7cb0a 8188do_swap (str)
b99bd4ef 8189 char * str;
b99bd4ef
NC
8190{
8191 int reg;
8192
8193 skip_whitespace (str);
8194
8195 if ((reg = reg_required_here (&str, 12)) == FAIL)
8196 return;
8197
8198 if (reg == REG_PC)
8199 {
8200 inst.error = _("r15 not allowed in swap");
8201 return;
8202 }
8203
8204 if (skip_past_comma (&str) == FAIL
8205 || (reg = reg_required_here (&str, 0)) == FAIL)
8206 {
8207 if (!inst.error)
8208 inst.error = BAD_ARGS;
8209 return;
8210 }
8211
8212 if (reg == REG_PC)
8213 {
8214 inst.error = _("r15 not allowed in swap");
8215 return;
8216 }
8217
8218 if (skip_past_comma (&str) == FAIL
8219 || *str++ != '[')
8220 {
8221 inst.error = BAD_ARGS;
8222 return;
8223 }
8224
8225 skip_whitespace (str);
8226
8227 if ((reg = reg_required_here (&str, 16)) == FAIL)
8228 return;
8229
8230 if (reg == REG_PC)
8231 {
8232 inst.error = BAD_PC;
8233 return;
8234 }
8235
8236 skip_whitespace (str);
8237
8238 if (*str++ != ']')
8239 {
8240 inst.error = _("missing ]");
8241 return;
8242 }
8243
b99bd4ef 8244 end_of_line (str);
b99bd4ef
NC
8245}
8246
8247static void
f2b7cb0a 8248do_branch (str)
b99bd4ef 8249 char * str;
b99bd4ef
NC
8250{
8251 if (my_get_expression (&inst.reloc.exp, &str))
8252 return;
8253
8254#ifdef OBJ_ELF
8255 {
8256 char * save_in;
8257
8258 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8259 required for the instruction. */
8260
8261 /* arm_parse_reloc () works on input_line_pointer.
8262 We actually want to parse the operands to the branch instruction
8263 passed in 'str'. Save the input pointer and restore it later. */
8264 save_in = input_line_pointer;
8265 input_line_pointer = str;
8266 if (inst.reloc.exp.X_op == O_symbol
8267 && *str == '('
8268 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8269 {
8270 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8271 inst.reloc.pc_rel = 0;
8272 /* Modify str to point to after parsed operands, otherwise
8273 end_of_line() will complain about the (PLT) left in str. */
8274 str = input_line_pointer;
8275 }
8276 else
8277 {
8278 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8279 inst.reloc.pc_rel = 1;
8280 }
8281 input_line_pointer = save_in;
8282 }
8283#else
8284 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8285 inst.reloc.pc_rel = 1;
8286#endif /* OBJ_ELF */
8287
8288 end_of_line (str);
b99bd4ef
NC
8289}
8290
8291static void
f2b7cb0a 8292do_bx (str)
b99bd4ef 8293 char * str;
b99bd4ef
NC
8294{
8295 int reg;
8296
8297 skip_whitespace (str);
8298
8299 if ((reg = reg_required_here (&str, 0)) == FAIL)
8300 {
8301 inst.error = BAD_ARGS;
8302 return;
8303 }
8304
8305 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8306 if (reg == REG_PC)
f03698e6 8307 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8308
8309 end_of_line (str);
8310}
8311
8312static void
f2b7cb0a 8313do_cdp (str)
b99bd4ef 8314 char * str;
b99bd4ef
NC
8315{
8316 /* Co-processor data operation.
8317 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8318 skip_whitespace (str);
8319
8320 if (co_proc_number (&str) == FAIL)
8321 {
8322 if (!inst.error)
8323 inst.error = BAD_ARGS;
8324 return;
8325 }
8326
8327 if (skip_past_comma (&str) == FAIL
8328 || cp_opc_expr (&str, 20,4) == FAIL)
8329 {
8330 if (!inst.error)
8331 inst.error = BAD_ARGS;
8332 return;
8333 }
8334
8335 if (skip_past_comma (&str) == FAIL
8336 || cp_reg_required_here (&str, 12) == FAIL)
8337 {
8338 if (!inst.error)
8339 inst.error = BAD_ARGS;
8340 return;
8341 }
8342
8343 if (skip_past_comma (&str) == FAIL
8344 || cp_reg_required_here (&str, 16) == FAIL)
8345 {
8346 if (!inst.error)
8347 inst.error = BAD_ARGS;
8348 return;
8349 }
8350
8351 if (skip_past_comma (&str) == FAIL
8352 || cp_reg_required_here (&str, 0) == FAIL)
8353 {
8354 if (!inst.error)
8355 inst.error = BAD_ARGS;
8356 return;
8357 }
8358
8359 if (skip_past_comma (&str) == SUCCESS)
8360 {
8361 if (cp_opc_expr (&str, 5, 3) == FAIL)
8362 {
8363 if (!inst.error)
8364 inst.error = BAD_ARGS;
8365 return;
8366 }
8367 }
8368
8369 end_of_line (str);
b99bd4ef
NC
8370}
8371
8372static void
f2b7cb0a 8373do_lstc (str)
b99bd4ef 8374 char * str;
b99bd4ef
NC
8375{
8376 /* Co-processor register load/store.
8377 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8378
8379 skip_whitespace (str);
8380
8381 if (co_proc_number (&str) == FAIL)
8382 {
8383 if (!inst.error)
8384 inst.error = BAD_ARGS;
8385 return;
8386 }
8387
8388 if (skip_past_comma (&str) == FAIL
8389 || cp_reg_required_here (&str, 12) == FAIL)
8390 {
8391 if (!inst.error)
8392 inst.error = BAD_ARGS;
8393 return;
8394 }
8395
8396 if (skip_past_comma (&str) == FAIL
bfae80f2 8397 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8398 {
8399 if (! inst.error)
8400 inst.error = BAD_ARGS;
8401 return;
8402 }
8403
b99bd4ef 8404 end_of_line (str);
b99bd4ef
NC
8405}
8406
8407static void
f2b7cb0a 8408do_co_reg (str)
b99bd4ef 8409 char * str;
b99bd4ef
NC
8410{
8411 /* Co-processor register transfer.
8412 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8413
8414 skip_whitespace (str);
8415
8416 if (co_proc_number (&str) == FAIL)
8417 {
8418 if (!inst.error)
8419 inst.error = BAD_ARGS;
8420 return;
8421 }
8422
8423 if (skip_past_comma (&str) == FAIL
8424 || cp_opc_expr (&str, 21, 3) == FAIL)
8425 {
8426 if (!inst.error)
8427 inst.error = BAD_ARGS;
8428 return;
8429 }
8430
8431 if (skip_past_comma (&str) == FAIL
8432 || reg_required_here (&str, 12) == FAIL)
8433 {
8434 if (!inst.error)
8435 inst.error = BAD_ARGS;
8436 return;
8437 }
8438
8439 if (skip_past_comma (&str) == FAIL
8440 || cp_reg_required_here (&str, 16) == FAIL)
8441 {
8442 if (!inst.error)
8443 inst.error = BAD_ARGS;
8444 return;
8445 }
8446
8447 if (skip_past_comma (&str) == FAIL
8448 || cp_reg_required_here (&str, 0) == FAIL)
8449 {
8450 if (!inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8453 }
8454
8455 if (skip_past_comma (&str) == SUCCESS)
8456 {
8457 if (cp_opc_expr (&str, 5, 3) == FAIL)
8458 {
8459 if (!inst.error)
8460 inst.error = BAD_ARGS;
8461 return;
8462 }
8463 }
b99bd4ef
NC
8464
8465 end_of_line (str);
b99bd4ef
NC
8466}
8467
8468static void
f2b7cb0a 8469do_fpa_ctrl (str)
b99bd4ef 8470 char * str;
b99bd4ef
NC
8471{
8472 /* FP control registers.
8473 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8474
8475 skip_whitespace (str);
8476
8477 if (reg_required_here (&str, 12) == FAIL)
8478 {
8479 if (!inst.error)
8480 inst.error = BAD_ARGS;
8481 return;
8482 }
8483
8484 end_of_line (str);
b99bd4ef
NC
8485}
8486
8487static void
f2b7cb0a 8488do_fpa_ldst (str)
b99bd4ef 8489 char * str;
b99bd4ef
NC
8490{
8491 skip_whitespace (str);
8492
b99bd4ef
NC
8493 if (fp_reg_required_here (&str, 12) == FAIL)
8494 {
8495 if (!inst.error)
8496 inst.error = BAD_ARGS;
8497 return;
8498 }
8499
8500 if (skip_past_comma (&str) == FAIL
bfae80f2 8501 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8502 {
8503 if (!inst.error)
8504 inst.error = BAD_ARGS;
8505 return;
8506 }
8507
8508 end_of_line (str);
8509}
8510
8511static void
f2b7cb0a 8512do_fpa_ldmstm (str)
b99bd4ef 8513 char * str;
b99bd4ef
NC
8514{
8515 int num_regs;
8516
8517 skip_whitespace (str);
8518
8519 if (fp_reg_required_here (&str, 12) == FAIL)
8520 {
8521 if (! inst.error)
8522 inst.error = BAD_ARGS;
8523 return;
8524 }
8525
8526 /* Get Number of registers to transfer. */
8527 if (skip_past_comma (&str) == FAIL
8528 || my_get_expression (&inst.reloc.exp, &str))
8529 {
8530 if (! inst.error)
8531 inst.error = _("constant expression expected");
8532 return;
8533 }
8534
8535 if (inst.reloc.exp.X_op != O_constant)
8536 {
f03698e6 8537 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8538 return;
8539 }
8540
8541 num_regs = inst.reloc.exp.X_add_number;
8542
8543 if (num_regs < 1 || num_regs > 4)
8544 {
8545 inst.error = _("number of registers must be in the range [1:4]");
8546 return;
8547 }
8548
8549 switch (num_regs)
8550 {
8551 case 1:
8552 inst.instruction |= CP_T_X;
8553 break;
8554 case 2:
8555 inst.instruction |= CP_T_Y;
8556 break;
8557 case 3:
8558 inst.instruction |= CP_T_Y | CP_T_X;
8559 break;
8560 case 4:
8561 break;
8562 default:
8563 abort ();
8564 }
8565
e28cd48c 8566 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8567 {
8568 int reg;
8569 int write_back;
8570 int offset;
8571
8572 /* The instruction specified "ea" or "fd", so we can only accept
8573 [Rn]{!}. The instruction does not really support stacking or
8574 unstacking, so we have to emulate these by setting appropriate
8575 bits and offsets. */
8576 if (skip_past_comma (&str) == FAIL
8577 || *str != '[')
8578 {
8579 if (! inst.error)
8580 inst.error = BAD_ARGS;
8581 return;
8582 }
8583
8584 str++;
8585 skip_whitespace (str);
8586
8587 if ((reg = reg_required_here (&str, 16)) == FAIL)
8588 return;
8589
8590 skip_whitespace (str);
8591
8592 if (*str != ']')
8593 {
8594 inst.error = BAD_ARGS;
8595 return;
8596 }
8597
8598 str++;
8599 if (*str == '!')
8600 {
8601 write_back = 1;
8602 str++;
8603 if (reg == REG_PC)
8604 {
8605 inst.error =
f03698e6 8606 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8607 return;
8608 }
8609 }
8610 else
8611 write_back = 0;
8612
90e4755a 8613 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8614 {
8615 /* Pre-decrement. */
8616 offset = 3 * num_regs;
8617 if (write_back)
90e4755a 8618 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8619 }
8620 else
8621 {
8622 /* Post-increment. */
8623 if (write_back)
8624 {
90e4755a 8625 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8626 offset = 3 * num_regs;
8627 }
8628 else
8629 {
8630 /* No write-back, so convert this into a standard pre-increment
8631 instruction -- aesthetically more pleasing. */
90e4755a 8632 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8633 offset = 0;
8634 }
8635 }
8636
f2b7cb0a 8637 inst.instruction |= offset;
b99bd4ef
NC
8638 }
8639 else if (skip_past_comma (&str) == FAIL
bfae80f2 8640 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8641 {
8642 if (! inst.error)
8643 inst.error = BAD_ARGS;
8644 return;
8645 }
8646
8647 end_of_line (str);
8648}
8649
8650static void
f2b7cb0a 8651do_fpa_dyadic (str)
b99bd4ef 8652 char * str;
b99bd4ef
NC
8653{
8654 skip_whitespace (str);
8655
b99bd4ef
NC
8656 if (fp_reg_required_here (&str, 12) == FAIL)
8657 {
8658 if (! inst.error)
8659 inst.error = BAD_ARGS;
8660 return;
8661 }
8662
8663 if (skip_past_comma (&str) == FAIL
8664 || fp_reg_required_here (&str, 16) == FAIL)
8665 {
8666 if (! inst.error)
8667 inst.error = BAD_ARGS;
8668 return;
8669 }
8670
8671 if (skip_past_comma (&str) == FAIL
8672 || fp_op2 (&str) == FAIL)
8673 {
8674 if (! inst.error)
8675 inst.error = BAD_ARGS;
8676 return;
8677 }
8678
b99bd4ef 8679 end_of_line (str);
b99bd4ef
NC
8680}
8681
8682static void
f2b7cb0a 8683do_fpa_monadic (str)
b99bd4ef 8684 char * str;
b99bd4ef
NC
8685{
8686 skip_whitespace (str);
8687
b99bd4ef
NC
8688 if (fp_reg_required_here (&str, 12) == FAIL)
8689 {
8690 if (! inst.error)
8691 inst.error = BAD_ARGS;
8692 return;
8693 }
8694
8695 if (skip_past_comma (&str) == FAIL
8696 || fp_op2 (&str) == FAIL)
8697 {
8698 if (! inst.error)
8699 inst.error = BAD_ARGS;
8700 return;
8701 }
8702
b99bd4ef 8703 end_of_line (str);
b99bd4ef
NC
8704}
8705
8706static void
f2b7cb0a 8707do_fpa_cmp (str)
b99bd4ef 8708 char * str;
b99bd4ef
NC
8709{
8710 skip_whitespace (str);
8711
8712 if (fp_reg_required_here (&str, 16) == FAIL)
8713 {
8714 if (! inst.error)
8715 inst.error = BAD_ARGS;
8716 return;
8717 }
8718
8719 if (skip_past_comma (&str) == FAIL
8720 || fp_op2 (&str) == FAIL)
8721 {
8722 if (! inst.error)
8723 inst.error = BAD_ARGS;
8724 return;
8725 }
8726
b99bd4ef 8727 end_of_line (str);
b99bd4ef
NC
8728}
8729
8730static void
f2b7cb0a 8731do_fpa_from_reg (str)
b99bd4ef 8732 char * str;
b99bd4ef
NC
8733{
8734 skip_whitespace (str);
8735
b99bd4ef
NC
8736 if (fp_reg_required_here (&str, 16) == FAIL)
8737 {
8738 if (! inst.error)
8739 inst.error = BAD_ARGS;
8740 return;
8741 }
8742
8743 if (skip_past_comma (&str) == FAIL
8744 || reg_required_here (&str, 12) == FAIL)
8745 {
8746 if (! inst.error)
8747 inst.error = BAD_ARGS;
8748 return;
8749 }
8750
b99bd4ef 8751 end_of_line (str);
b99bd4ef
NC
8752}
8753
8754static void
f2b7cb0a 8755do_fpa_to_reg (str)
b99bd4ef 8756 char * str;
b99bd4ef
NC
8757{
8758 skip_whitespace (str);
8759
8760 if (reg_required_here (&str, 12) == FAIL)
8761 return;
8762
8763 if (skip_past_comma (&str) == FAIL
8764 || fp_reg_required_here (&str, 0) == FAIL)
8765 {
8766 if (! inst.error)
8767 inst.error = BAD_ARGS;
8768 return;
8769 }
8770
b99bd4ef 8771 end_of_line (str);
b99bd4ef
NC
8772}
8773
b99bd4ef 8774static int
bfae80f2
RE
8775vfp_sp_reg_required_here (str, pos)
8776 char **str;
8777 enum vfp_sp_reg_pos pos;
b99bd4ef 8778{
bfae80f2
RE
8779 int reg;
8780 char *start = *str;
b99bd4ef 8781
bfae80f2 8782 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8783 {
bfae80f2 8784 switch (pos)
b99bd4ef 8785 {
bfae80f2
RE
8786 case VFP_REG_Sd:
8787 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8788 break;
8789
8790 case VFP_REG_Sn:
8791 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8792 break;
8793
8794 case VFP_REG_Sm:
8795 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8796 break;
8797
8798 default:
8799 abort ();
b99bd4ef 8800 }
bfae80f2
RE
8801 return reg;
8802 }
b99bd4ef 8803
bfae80f2
RE
8804 /* In the few cases where we might be able to accept something else
8805 this error can be overridden. */
8806 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8807
8808 /* Restore the start point. */
8809 *str = start;
8810 return FAIL;
8811}
8812
8813static int
8814vfp_dp_reg_required_here (str, pos)
8815 char **str;
f201ccb3 8816 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8817{
8818 int reg;
8819 char *start = *str;
8820
8821 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8822 {
8823 switch (pos)
b99bd4ef 8824 {
bfae80f2
RE
8825 case VFP_REG_Dd:
8826 inst.instruction |= reg << 12;
8827 break;
b99bd4ef 8828
bfae80f2
RE
8829 case VFP_REG_Dn:
8830 inst.instruction |= reg << 16;
8831 break;
8832
8833 case VFP_REG_Dm:
8834 inst.instruction |= reg << 0;
8835 break;
8836
8837 default:
8838 abort ();
8839 }
8840 return reg;
b99bd4ef
NC
8841 }
8842
bfae80f2
RE
8843 /* In the few cases where we might be able to accept something else
8844 this error can be overridden. */
8845 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8846
bfae80f2
RE
8847 /* Restore the start point. */
8848 *str = start;
8849 return FAIL;
8850}
b99bd4ef
NC
8851
8852static void
bfae80f2
RE
8853do_vfp_sp_monadic (str)
8854 char *str;
b99bd4ef 8855{
b99bd4ef
NC
8856 skip_whitespace (str);
8857
bfae80f2
RE
8858 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8859 return;
8860
8861 if (skip_past_comma (&str) == FAIL
8862 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8863 {
8864 if (! inst.error)
8865 inst.error = BAD_ARGS;
8866 return;
8867 }
8868
bfae80f2 8869 end_of_line (str);
bfae80f2
RE
8870}
8871
8872static void
8873do_vfp_dp_monadic (str)
8874 char *str;
8875{
8876 skip_whitespace (str);
8877
8878 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8879 return;
8880
8881 if (skip_past_comma (&str) == FAIL
8882 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8883 {
bfae80f2
RE
8884 if (! inst.error)
8885 inst.error = BAD_ARGS;
8886 return;
b99bd4ef 8887 }
b99bd4ef 8888
bfae80f2 8889 end_of_line (str);
bfae80f2 8890}
b99bd4ef 8891
bfae80f2
RE
8892static void
8893do_vfp_sp_dyadic (str)
8894 char *str;
8895{
8896 skip_whitespace (str);
b99bd4ef 8897
bfae80f2
RE
8898 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8899 return;
b99bd4ef 8900
bfae80f2
RE
8901 if (skip_past_comma (&str) == FAIL
8902 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8903 || skip_past_comma (&str) == FAIL
8904 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8905 {
bfae80f2
RE
8906 if (! inst.error)
8907 inst.error = BAD_ARGS;
8908 return;
8909 }
b99bd4ef 8910
bfae80f2 8911 end_of_line (str);
bfae80f2 8912}
b99bd4ef 8913
bfae80f2
RE
8914static void
8915do_vfp_dp_dyadic (str)
8916 char *str;
8917{
8918 skip_whitespace (str);
b99bd4ef 8919
bfae80f2
RE
8920 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8921 return;
b99bd4ef 8922
bfae80f2
RE
8923 if (skip_past_comma (&str) == FAIL
8924 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8925 || skip_past_comma (&str) == FAIL
8926 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8927 {
8928 if (! inst.error)
8929 inst.error = BAD_ARGS;
8930 return;
8931 }
b99bd4ef 8932
bfae80f2 8933 end_of_line (str);
bfae80f2 8934}
b99bd4ef 8935
bfae80f2
RE
8936static void
8937do_vfp_reg_from_sp (str)
8938 char *str;
8939{
8940 skip_whitespace (str);
8941
8942 if (reg_required_here (&str, 12) == FAIL)
8943 return;
8944
8945 if (skip_past_comma (&str) == FAIL
8946 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8947 {
8948 if (! inst.error)
8949 inst.error = BAD_ARGS;
8950 return;
8951 }
8952
8953 end_of_line (str);
bfae80f2
RE
8954}
8955
8956static void
e45d0630 8957do_vfp_reg2_from_sp2 (str)
bfae80f2
RE
8958 char *str;
8959{
8960 skip_whitespace (str);
8961
e45d0630
PB
8962 if (reg_required_here (&str, 12) == FAIL
8963 || skip_past_comma (&str) == FAIL
bfae80f2
RE
8964 || reg_required_here (&str, 16) == FAIL
8965 || skip_past_comma (&str) == FAIL)
8966 {
8967 if (! inst.error)
8968 inst.error = BAD_ARGS;
8969 return;
8970 }
8971
8972 /* We require exactly two consecutive SP registers. */
8973 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8974 {
8975 if (! inst.error)
8976 inst.error = _("only two consecutive VFP SP registers allowed here");
8977 }
8978
8979 end_of_line (str);
bfae80f2
RE
8980}
8981
8982static void
8983do_vfp_sp_from_reg (str)
8984 char *str;
8985{
8986 skip_whitespace (str);
8987
8988 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8989 return;
8990
8991 if (skip_past_comma (&str) == FAIL
8992 || reg_required_here (&str, 12) == FAIL)
8993 {
8994 if (! inst.error)
8995 inst.error = BAD_ARGS;
8996 return;
8997 }
8998
8999 end_of_line (str);
bfae80f2
RE
9000}
9001
e45d0630
PB
9002static void
9003do_vfp_sp2_from_reg2 (str)
9004 char *str;
9005{
9006 skip_whitespace (str);
9007
9008 /* We require exactly two consecutive SP registers. */
9009 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9010 {
9011 if (! inst.error)
9012 inst.error = _("only two consecutive VFP SP registers allowed here");
9013 }
9014
9015 if (skip_past_comma (&str) == FAIL
9016 || reg_required_here (&str, 12) == FAIL
9017 || skip_past_comma (&str) == FAIL
9018 || reg_required_here (&str, 16) == FAIL)
9019 {
9020 if (! inst.error)
9021 inst.error = BAD_ARGS;
9022 return;
9023 }
9024
9025 end_of_line (str);
9026}
9027
bfae80f2
RE
9028static void
9029do_vfp_reg_from_dp (str)
9030 char *str;
9031{
9032 skip_whitespace (str);
9033
9034 if (reg_required_here (&str, 12) == FAIL)
9035 return;
9036
9037 if (skip_past_comma (&str) == FAIL
9038 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9039 {
9040 if (! inst.error)
9041 inst.error = BAD_ARGS;
9042 return;
9043 }
9044
9045 end_of_line (str);
bfae80f2
RE
9046}
9047
9048static void
9049do_vfp_reg2_from_dp (str)
9050 char *str;
9051{
9052 skip_whitespace (str);
9053
9054 if (reg_required_here (&str, 12) == FAIL)
9055 return;
9056
9057 if (skip_past_comma (&str) == FAIL
9058 || reg_required_here (&str, 16) == FAIL
9059 || skip_past_comma (&str) == FAIL
9060 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9061 {
9062 if (! inst.error)
9063 inst.error = BAD_ARGS;
9064 return;
9065 }
9066
9067 end_of_line (str);
bfae80f2
RE
9068}
9069
9070static void
9071do_vfp_dp_from_reg (str)
9072 char *str;
9073{
9074 skip_whitespace (str);
9075
9076 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9077 return;
9078
9079 if (skip_past_comma (&str) == FAIL
9080 || reg_required_here (&str, 12) == FAIL)
9081 {
9082 if (! inst.error)
9083 inst.error = BAD_ARGS;
9084 return;
9085 }
9086
9087 end_of_line (str);
bfae80f2
RE
9088}
9089
9090static void
9091do_vfp_dp_from_reg2 (str)
9092 char *str;
9093{
9094 skip_whitespace (str);
9095
9096 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9097 return;
9098
9099 if (skip_past_comma (&str) == FAIL
9100 || reg_required_here (&str, 12) == FAIL
9101 || skip_past_comma (&str) == FAIL
e45d0630 9102 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
9103 {
9104 if (! inst.error)
9105 inst.error = BAD_ARGS;
9106 return;
9107 }
9108
9109 end_of_line (str);
bfae80f2
RE
9110}
9111
9112static const struct vfp_reg *
9113vfp_psr_parse (str)
9114 char **str;
9115{
9116 char *start = *str;
9117 char c;
9118 char *p;
9119 const struct vfp_reg *vreg;
9120
9121 p = start;
9122
9123 /* Find the end of the current token. */
9124 do
9125 {
9126 c = *p++;
9127 }
9128 while (ISALPHA (c));
9129
9130 /* Mark it. */
9131 *--p = 0;
9132
cc8a6dd0 9133 for (vreg = vfp_regs + 0;
bfae80f2
RE
9134 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9135 vreg++)
9136 {
9137 if (strcmp (start, vreg->name) == 0)
9138 {
9139 *p = c;
9140 *str = p;
9141 return vreg;
9142 }
9143 }
9144
9145 *p = c;
9146 return NULL;
9147}
9148
9149static int
9150vfp_psr_required_here (str)
9151 char **str;
9152{
9153 char *start = *str;
9154 const struct vfp_reg *vreg;
9155
9156 vreg = vfp_psr_parse (str);
9157
9158 if (vreg)
9159 {
9160 inst.instruction |= vreg->regno;
9161 return SUCCESS;
9162 }
9163
9164 inst.error = _("VFP system register expected");
9165
9166 *str = start;
9167 return FAIL;
9168}
9169
9170static void
9171do_vfp_reg_from_ctrl (str)
9172 char *str;
9173{
9174 skip_whitespace (str);
9175
9176 if (reg_required_here (&str, 12) == FAIL)
9177 return;
9178
9179 if (skip_past_comma (&str) == FAIL
9180 || vfp_psr_required_here (&str) == FAIL)
9181 {
9182 if (! inst.error)
9183 inst.error = BAD_ARGS;
9184 return;
9185 }
9186
9187 end_of_line (str);
bfae80f2
RE
9188}
9189
9190static void
9191do_vfp_ctrl_from_reg (str)
9192 char *str;
9193{
9194 skip_whitespace (str);
9195
9196 if (vfp_psr_required_here (&str) == FAIL)
9197 return;
9198
9199 if (skip_past_comma (&str) == FAIL
9200 || reg_required_here (&str, 12) == FAIL)
9201 {
9202 if (! inst.error)
9203 inst.error = BAD_ARGS;
9204 return;
9205 }
9206
9207 end_of_line (str);
bfae80f2
RE
9208}
9209
9210static void
9211do_vfp_sp_ldst (str)
9212 char *str;
9213{
9214 skip_whitespace (str);
9215
9216 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9217 {
9218 if (!inst.error)
9219 inst.error = BAD_ARGS;
9220 return;
9221 }
9222
9223 if (skip_past_comma (&str) == FAIL
9224 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9225 {
9226 if (!inst.error)
9227 inst.error = BAD_ARGS;
9228 return;
9229 }
9230
9231 end_of_line (str);
bfae80f2
RE
9232}
9233
9234static void
9235do_vfp_dp_ldst (str)
9236 char *str;
9237{
9238 skip_whitespace (str);
9239
9240 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9241 {
9242 if (!inst.error)
9243 inst.error = BAD_ARGS;
9244 return;
9245 }
9246
9247 if (skip_past_comma (&str) == FAIL
9248 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9249 {
9250 if (!inst.error)
9251 inst.error = BAD_ARGS;
9252 return;
9253 }
9254
9255 end_of_line (str);
bfae80f2
RE
9256}
9257
9258/* Parse and encode a VFP SP register list, storing the initial
9259 register in position POS and returning the range as the result. If
9260 the string is invalid return FAIL (an invalid range). */
9261static long
9262vfp_sp_reg_list (str, pos)
9263 char **str;
9264 enum vfp_sp_reg_pos pos;
9265{
9266 long range = 0;
9267 int base_reg = 0;
9268 int new_base;
9269 long base_bits = 0;
9270 int count = 0;
9271 long tempinst;
9272 unsigned long mask = 0;
9273 int warned = 0;
9274
9275 if (**str != '{')
9276 return FAIL;
9277
9278 (*str)++;
9279 skip_whitespace (*str);
9280
9281 tempinst = inst.instruction;
9282
9283 do
9284 {
9285 inst.instruction = 0;
9286
9287 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9288 return FAIL;
9289
9290 if (count == 0 || base_reg > new_base)
9291 {
9292 base_reg = new_base;
9293 base_bits = inst.instruction;
9294 }
9295
9296 if (mask & (1 << new_base))
9297 {
9298 inst.error = _("invalid register list");
9299 return FAIL;
9300 }
9301
9302 if ((mask >> new_base) != 0 && ! warned)
9303 {
9304 as_tsktsk (_("register list not in ascending order"));
9305 warned = 1;
9306 }
9307
9308 mask |= 1 << new_base;
9309 count++;
9310
9311 skip_whitespace (*str);
9312
9313 if (**str == '-') /* We have the start of a range expression */
9314 {
9315 int high_range;
9316
9317 (*str)++;
9318
9319 if ((high_range
9320 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9321 == FAIL)
9322 {
9323 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9324 return FAIL;
9325 }
9326
9327 if (high_range <= new_base)
9328 {
9329 inst.error = _("register range not in ascending order");
9330 return FAIL;
9331 }
9332
9333 for (new_base++; new_base <= high_range; new_base++)
9334 {
9335 if (mask & (1 << new_base))
9336 {
9337 inst.error = _("invalid register list");
9338 return FAIL;
9339 }
9340
9341 mask |= 1 << new_base;
9342 count++;
9343 }
9344 }
9345 }
9346 while (skip_past_comma (str) != FAIL);
9347
9348 if (**str != '}')
9349 {
9350 inst.error = _("invalid register list");
9351 return FAIL;
9352 }
9353
9354 (*str)++;
9355
9356 range = count;
9357
9358 /* Sanity check -- should have raised a parse error above. */
9359 if (count == 0 || count > 32)
c62e1cc3 9360 abort ();
bfae80f2
RE
9361
9362 /* Final test -- the registers must be consecutive. */
9363 while (count--)
9364 {
9365 if ((mask & (1 << base_reg++)) == 0)
9366 {
9367 inst.error = _("non-contiguous register range");
9368 return FAIL;
9369 }
9370 }
9371
9372 inst.instruction = tempinst | base_bits;
9373 return range;
9374}
9375
9376static long
9377vfp_dp_reg_list (str)
9378 char **str;
9379{
9380 long range = 0;
9381 int base_reg = 0;
9382 int new_base;
9383 int count = 0;
9384 long tempinst;
9385 unsigned long mask = 0;
9386 int warned = 0;
9387
9388 if (**str != '{')
9389 return FAIL;
9390
9391 (*str)++;
9392 skip_whitespace (*str);
9393
9394 tempinst = inst.instruction;
9395
9396 do
9397 {
9398 inst.instruction = 0;
9399
9400 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9401 return FAIL;
9402
9403 if (count == 0 || base_reg > new_base)
9404 {
9405 base_reg = new_base;
9406 range = inst.instruction;
9407 }
9408
9409 if (mask & (1 << new_base))
9410 {
9411 inst.error = _("invalid register list");
9412 return FAIL;
9413 }
9414
9415 if ((mask >> new_base) != 0 && ! warned)
9416 {
9417 as_tsktsk (_("register list not in ascending order"));
9418 warned = 1;
9419 }
9420
9421 mask |= 1 << new_base;
9422 count++;
9423
9424 skip_whitespace (*str);
9425
9426 if (**str == '-') /* We have the start of a range expression */
9427 {
9428 int high_range;
9429
9430 (*str)++;
9431
9432 if ((high_range
9433 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9434 == FAIL)
9435 {
9436 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9437 return FAIL;
9438 }
9439
9440 if (high_range <= new_base)
9441 {
9442 inst.error = _("register range not in ascending order");
9443 return FAIL;
9444 }
9445
9446 for (new_base++; new_base <= high_range; new_base++)
9447 {
9448 if (mask & (1 << new_base))
9449 {
9450 inst.error = _("invalid register list");
9451 return FAIL;
9452 }
9453
9454 mask |= 1 << new_base;
9455 count++;
9456 }
9457 }
9458 }
9459 while (skip_past_comma (str) != FAIL);
9460
9461 if (**str != '}')
9462 {
9463 inst.error = _("invalid register list");
9464 return FAIL;
9465 }
9466
9467 (*str)++;
9468
9469 range |= 2 * count;
9470
9471 /* Sanity check -- should have raised a parse error above. */
9472 if (count == 0 || count > 16)
c62e1cc3 9473 abort ();
bfae80f2
RE
9474
9475 /* Final test -- the registers must be consecutive. */
9476 while (count--)
9477 {
9478 if ((mask & (1 << base_reg++)) == 0)
9479 {
9480 inst.error = _("non-contiguous register range");
9481 return FAIL;
9482 }
9483 }
9484
9485 inst.instruction = tempinst;
9486 return range;
9487}
9488
9489static void
c62e1cc3 9490vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9491 char *str;
9492 enum vfp_ldstm_type ldstm_type;
9493{
9494 long range;
9495
9496 skip_whitespace (str);
9497
9498 if (reg_required_here (&str, 16) == FAIL)
9499 return;
9500
9501 skip_whitespace (str);
9502
9503 if (*str == '!')
9504 {
9505 inst.instruction |= WRITE_BACK;
9506 str++;
9507 }
9508 else if (ldstm_type != VFP_LDSTMIA)
9509 {
9510 inst.error = _("this addressing mode requires base-register writeback");
9511 return;
9512 }
9513
9514 if (skip_past_comma (&str) == FAIL
9515 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9516 {
9517 if (!inst.error)
9518 inst.error = BAD_ARGS;
9519 return;
9520 }
9521
9522 inst.instruction |= range;
9523 end_of_line (str);
9524}
9525
9526static void
c62e1cc3 9527vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9528 char *str;
9529 enum vfp_ldstm_type ldstm_type;
9530{
9531 long range;
9532
9533 skip_whitespace (str);
9534
9535 if (reg_required_here (&str, 16) == FAIL)
9536 return;
9537
9538 skip_whitespace (str);
9539
9540 if (*str == '!')
9541 {
9542 inst.instruction |= WRITE_BACK;
9543 str++;
9544 }
9545 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9546 {
9547 inst.error = _("this addressing mode requires base-register writeback");
9548 return;
9549 }
9550
9551 if (skip_past_comma (&str) == FAIL
9552 || (range = vfp_dp_reg_list (&str)) == FAIL)
9553 {
9554 if (!inst.error)
9555 inst.error = BAD_ARGS;
9556 return;
9557 }
9558
9559 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9560 range += 1;
9561
9562 inst.instruction |= range;
9563 end_of_line (str);
9564}
9565
9566static void
9567do_vfp_sp_ldstmia (str)
9568 char *str;
9569{
9570 vfp_sp_ldstm (str, VFP_LDSTMIA);
9571}
9572
9573static void
9574do_vfp_sp_ldstmdb (str)
9575 char *str;
9576{
9577 vfp_sp_ldstm (str, VFP_LDSTMDB);
9578}
9579
9580static void
9581do_vfp_dp_ldstmia (str)
9582 char *str;
9583{
9584 vfp_dp_ldstm (str, VFP_LDSTMIA);
9585}
9586
9587static void
9588do_vfp_dp_ldstmdb (str)
9589 char *str;
9590{
9591 vfp_dp_ldstm (str, VFP_LDSTMDB);
9592}
9593
9594static void
9595do_vfp_xp_ldstmia (str)
9596 char *str;
9597{
9598 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9599}
9600
9601static void
9602do_vfp_xp_ldstmdb (str)
9603 char *str;
9604{
9605 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9606}
9607
9608static void
9609do_vfp_sp_compare_z (str)
9610 char *str;
9611{
9612 skip_whitespace (str);
9613
9614 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9615 {
9616 if (!inst.error)
9617 inst.error = BAD_ARGS;
9618 return;
9619 }
9620
9621 end_of_line (str);
bfae80f2
RE
9622}
9623
9624static void
9625do_vfp_dp_compare_z (str)
9626 char *str;
9627{
9628 skip_whitespace (str);
9629
9630 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9631 {
9632 if (!inst.error)
9633 inst.error = BAD_ARGS;
9634 return;
9635 }
9636
9637 end_of_line (str);
bfae80f2
RE
9638}
9639
9640static void
9641do_vfp_dp_sp_cvt (str)
9642 char *str;
9643{
9644 skip_whitespace (str);
9645
9646 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9647 return;
9648
9649 if (skip_past_comma (&str) == FAIL
9650 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9651 {
9652 if (! inst.error)
9653 inst.error = BAD_ARGS;
9654 return;
9655 }
9656
9657 end_of_line (str);
bfae80f2
RE
9658}
9659
9660static void
9661do_vfp_sp_dp_cvt (str)
9662 char *str;
9663{
9664 skip_whitespace (str);
9665
9666 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9667 return;
9668
9669 if (skip_past_comma (&str) == FAIL
9670 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9671 {
9672 if (! inst.error)
9673 inst.error = BAD_ARGS;
9674 return;
9675 }
9676
9677 end_of_line (str);
bfae80f2
RE
9678}
9679
9680/* Thumb specific routines. */
9681
9682/* Parse and validate that a register is of the right form, this saves
9683 repeated checking of this information in many similar cases.
9684 Unlike the 32-bit case we do not insert the register into the opcode
9685 here, since the position is often unknown until the full instruction
9686 has been parsed. */
9687
9688static int
9689thumb_reg (strp, hi_lo)
9690 char ** strp;
9691 int hi_lo;
9692{
9693 int reg;
9694
9695 if ((reg = reg_required_here (strp, -1)) == FAIL)
9696 return FAIL;
9697
9698 switch (hi_lo)
9699 {
9700 case THUMB_REG_LO:
9701 if (reg > 7)
9702 {
9703 inst.error = _("lo register required");
9704 return FAIL;
9705 }
9706 break;
9707
9708 case THUMB_REG_HI:
9709 if (reg < 8)
9710 {
9711 inst.error = _("hi register required");
9712 return FAIL;
9713 }
9714 break;
9715
9716 default:
9717 break;
9718 }
9719
9720 return reg;
9721}
9722
9723/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9724 was SUB. */
9725
9726static void
9727thumb_add_sub (str, subtract)
9728 char * str;
9729 int subtract;
9730{
9731 int Rd, Rs, Rn = FAIL;
9732
9733 skip_whitespace (str);
9734
9735 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9736 || skip_past_comma (&str) == FAIL)
9737 {
9738 if (! inst.error)
9739 inst.error = BAD_ARGS;
9740 return;
9741 }
9742
9743 if (is_immediate_prefix (*str))
9744 {
9745 Rs = Rd;
9746 str++;
9747 if (my_get_expression (&inst.reloc.exp, &str))
9748 return;
9749 }
9750 else
9751 {
9752 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9753 return;
9754
9755 if (skip_past_comma (&str) == FAIL)
9756 {
9757 /* Two operand format, shuffle the registers
9758 and pretend there are 3. */
9759 Rn = Rs;
9760 Rs = Rd;
9761 }
9762 else if (is_immediate_prefix (*str))
9763 {
9764 str++;
9765 if (my_get_expression (&inst.reloc.exp, &str))
9766 return;
9767 }
9768 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9769 return;
9770 }
9771
9772 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9773 for the latter case, EXPR contains the immediate that was found. */
9774 if (Rn != FAIL)
9775 {
9776 /* All register format. */
9777 if (Rd > 7 || Rs > 7 || Rn > 7)
9778 {
9779 if (Rs != Rd)
9780 {
9781 inst.error = _("dest and source1 must be the same register");
9782 return;
9783 }
9784
9785 /* Can't do this for SUB. */
9786 if (subtract)
9787 {
9788 inst.error = _("subtract valid only on lo regs");
9789 return;
9790 }
9791
9792 inst.instruction = (T_OPCODE_ADD_HI
9793 | (Rd > 7 ? THUMB_H1 : 0)
9794 | (Rn > 7 ? THUMB_H2 : 0));
9795 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9796 }
9797 else
9798 {
9799 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9800 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9801 }
9802 }
9803 else
9804 {
9805 /* Immediate expression, now things start to get nasty. */
9806
9807 /* First deal with HI regs, only very restricted cases allowed:
9808 Adjusting SP, and using PC or SP to get an address. */
9809 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9810 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9811 {
9812 inst.error = _("invalid Hi register with immediate");
9813 return;
9814 }
9815
9816 if (inst.reloc.exp.X_op != O_constant)
9817 {
9818 /* Value isn't known yet, all we can do is store all the fragments
9819 we know about in the instruction and let the reloc hacking
9820 work it all out. */
9821 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9822 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9823 }
9824 else
9825 {
9826 int offset = inst.reloc.exp.X_add_number;
9827
9828 if (subtract)
358b94bd 9829 offset = - offset;
bfae80f2
RE
9830
9831 if (offset < 0)
9832 {
358b94bd 9833 offset = - offset;
bfae80f2
RE
9834 subtract = 1;
9835
9836 /* Quick check, in case offset is MIN_INT. */
9837 if (offset < 0)
9838 {
9839 inst.error = _("immediate value out of range");
9840 return;
9841 }
9842 }
358b94bd
NC
9843 /* Note - you cannot convert a subtract of 0 into an
9844 add of 0 because the carry flag is set differently. */
9845 else if (offset > 0)
bfae80f2
RE
9846 subtract = 0;
9847
9848 if (Rd == REG_SP)
9849 {
9850 if (offset & ~0x1fc)
9851 {
9852 inst.error = _("invalid immediate value for stack adjust");
9853 return;
b99bd4ef
NC
9854 }
9855 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9856 inst.instruction |= offset >> 2;
9857 }
9858 else if (Rs == REG_PC || Rs == REG_SP)
9859 {
9860 if (subtract
9861 || (offset & ~0x3fc))
9862 {
9863 inst.error = _("invalid immediate for address calculation");
9864 return;
9865 }
9866 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9867 : T_OPCODE_ADD_SP);
9868 inst.instruction |= (Rd << 8) | (offset >> 2);
9869 }
9870 else if (Rs == Rd)
9871 {
9872 if (offset & ~0xff)
9873 {
9874 inst.error = _("immediate value out of range");
9875 return;
9876 }
9877 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9878 inst.instruction |= (Rd << 8) | offset;
9879 }
9880 else
9881 {
9882 if (offset & ~0x7)
9883 {
9884 inst.error = _("immediate value out of range");
9885 return;
9886 }
9887 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9888 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9889 }
9890 }
9891 }
9892
9893 end_of_line (str);
9894}
9895
9896static void
9897thumb_shift (str, shift)
9898 char * str;
9899 int shift;
9900{
9901 int Rd, Rs, Rn = FAIL;
9902
9903 skip_whitespace (str);
9904
9905 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9906 || skip_past_comma (&str) == FAIL)
9907 {
9908 if (! inst.error)
9909 inst.error = BAD_ARGS;
9910 return;
9911 }
9912
9913 if (is_immediate_prefix (*str))
9914 {
9915 /* Two operand immediate format, set Rs to Rd. */
9916 Rs = Rd;
9917 str ++;
9918 if (my_get_expression (&inst.reloc.exp, &str))
9919 return;
9920 }
9921 else
9922 {
9923 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9924 return;
9925
9926 if (skip_past_comma (&str) == FAIL)
9927 {
9928 /* Two operand format, shuffle the registers
9929 and pretend there are 3. */
9930 Rn = Rs;
9931 Rs = Rd;
9932 }
9933 else if (is_immediate_prefix (*str))
9934 {
9935 str++;
9936 if (my_get_expression (&inst.reloc.exp, &str))
9937 return;
9938 }
9939 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9940 return;
9941 }
9942
9943 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9944 for the latter case, EXPR contains the immediate that was found. */
9945
9946 if (Rn != FAIL)
9947 {
9948 if (Rs != Rd)
9949 {
9950 inst.error = _("source1 and dest must be same register");
9951 return;
9952 }
9953
9954 switch (shift)
9955 {
9956 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9957 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9958 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9959 }
9960
9961 inst.instruction |= Rd | (Rn << 3);
9962 }
9963 else
9964 {
9965 switch (shift)
9966 {
9967 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9968 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9969 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9970 }
9971
9972 if (inst.reloc.exp.X_op != O_constant)
9973 {
9974 /* Value isn't known yet, create a dummy reloc and let reloc
9975 hacking fix it up. */
9976 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9977 }
9978 else
9979 {
9980 unsigned shift_value = inst.reloc.exp.X_add_number;
9981
9982 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9983 {
f03698e6 9984 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9985 return;
9986 }
9987
9988 /* Shifts of zero are handled by converting to LSL. */
9989 if (shift_value == 0)
9990 inst.instruction = T_OPCODE_LSL_I;
9991
9992 /* Shifts of 32 are encoded as a shift of zero. */
9993 if (shift_value == 32)
9994 shift_value = 0;
9995
9996 inst.instruction |= shift_value << 6;
9997 }
9998
9999 inst.instruction |= Rd | (Rs << 3);
10000 }
10001
10002 end_of_line (str);
10003}
10004
10005static void
10006thumb_mov_compare (str, move)
10007 char * str;
10008 int move;
10009{
10010 int Rd, Rs = FAIL;
10011
10012 skip_whitespace (str);
10013
10014 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10015 || skip_past_comma (&str) == FAIL)
10016 {
10017 if (! inst.error)
10018 inst.error = BAD_ARGS;
10019 return;
10020 }
10021
09d92015 10022 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
10023 {
10024 str++;
10025 if (my_get_expression (&inst.reloc.exp, &str))
10026 return;
10027 }
10028 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10029 return;
10030
10031 if (Rs != FAIL)
10032 {
09d92015 10033 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
10034 {
10035 if (move == THUMB_MOVE)
10036 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10037 since a MOV instruction produces unpredictable results. */
10038 inst.instruction = T_OPCODE_ADD_I3;
10039 else
10040 inst.instruction = T_OPCODE_CMP_LR;
10041 inst.instruction |= Rd | (Rs << 3);
10042 }
10043 else
10044 {
10045 if (move == THUMB_MOVE)
10046 inst.instruction = T_OPCODE_MOV_HR;
09d92015 10047 else if (move != THUMB_CPY)
b99bd4ef
NC
10048 inst.instruction = T_OPCODE_CMP_HR;
10049
10050 if (Rd > 7)
10051 inst.instruction |= THUMB_H1;
10052
10053 if (Rs > 7)
10054 inst.instruction |= THUMB_H2;
10055
10056 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10057 }
10058 }
10059 else
10060 {
10061 if (Rd > 7)
10062 {
10063 inst.error = _("only lo regs allowed with immediate");
10064 return;
10065 }
10066
10067 if (move == THUMB_MOVE)
10068 inst.instruction = T_OPCODE_MOV_I8;
10069 else
10070 inst.instruction = T_OPCODE_CMP_I8;
10071
10072 inst.instruction |= Rd << 8;
10073
10074 if (inst.reloc.exp.X_op != O_constant)
10075 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10076 else
10077 {
10078 unsigned value = inst.reloc.exp.X_add_number;
10079
10080 if (value > 255)
10081 {
10082 inst.error = _("invalid immediate");
10083 return;
10084 }
10085
10086 inst.instruction |= value;
10087 }
10088 }
10089
10090 end_of_line (str);
10091}
10092
10093static void
10094thumb_load_store (str, load_store, size)
10095 char * str;
10096 int load_store;
10097 int size;
10098{
10099 int Rd, Rb, Ro = FAIL;
10100
10101 skip_whitespace (str);
10102
10103 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10104 || skip_past_comma (&str) == FAIL)
10105 {
10106 if (! inst.error)
10107 inst.error = BAD_ARGS;
10108 return;
10109 }
10110
10111 if (*str == '[')
10112 {
10113 str++;
10114 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10115 return;
10116
10117 if (skip_past_comma (&str) != FAIL)
10118 {
10119 if (is_immediate_prefix (*str))
10120 {
10121 str++;
10122 if (my_get_expression (&inst.reloc.exp, &str))
10123 return;
10124 }
10125 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10126 return;
10127 }
10128 else
10129 {
10130 inst.reloc.exp.X_op = O_constant;
10131 inst.reloc.exp.X_add_number = 0;
10132 }
10133
10134 if (*str != ']')
10135 {
10136 inst.error = _("expected ']'");
10137 return;
10138 }
10139 str++;
10140 }
10141 else if (*str == '=')
10142 {
f03698e6
RE
10143 if (load_store != THUMB_LOAD)
10144 {
10145 inst.error = _("invalid pseudo operation");
10146 return;
10147 }
10148
b99bd4ef
NC
10149 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10150 str++;
10151
10152 skip_whitespace (str);
10153
10154 if (my_get_expression (& inst.reloc.exp, & str))
10155 return;
10156
10157 end_of_line (str);
10158
10159 if ( inst.reloc.exp.X_op != O_constant
10160 && inst.reloc.exp.X_op != O_symbol)
10161 {
10162 inst.error = "Constant expression expected";
10163 return;
10164 }
10165
10166 if (inst.reloc.exp.X_op == O_constant
10167 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10168 {
10169 /* This can be done with a mov instruction. */
10170
10171 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10172 inst.instruction |= inst.reloc.exp.X_add_number;
10173 return;
10174 }
10175
10176 /* Insert into literal pool. */
10177 if (add_to_lit_pool () == FAIL)
10178 {
10179 if (!inst.error)
10180 inst.error = "literal pool insertion failed";
10181 return;
10182 }
10183
10184 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10185 inst.reloc.pc_rel = 1;
10186 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10187 /* Adjust ARM pipeline offset to Thumb. */
10188 inst.reloc.exp.X_add_number += 4;
10189
10190 return;
10191 }
10192 else
10193 {
10194 if (my_get_expression (&inst.reloc.exp, &str))
10195 return;
10196
10197 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10198 inst.reloc.pc_rel = 1;
10199 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10200 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10201 end_of_line (str);
10202 return;
10203 }
10204
10205 if (Rb == REG_PC || Rb == REG_SP)
10206 {
10207 if (size != THUMB_WORD)
10208 {
10209 inst.error = _("byte or halfword not valid for base register");
10210 return;
10211 }
10212 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10213 {
f03698e6 10214 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10215 return;
10216 }
10217 else if (Ro != FAIL)
10218 {
f03698e6 10219 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10220 return;
10221 }
10222
10223 if (Rb == REG_PC)
10224 inst.instruction = T_OPCODE_LDR_PC;
10225 else if (load_store == THUMB_LOAD)
10226 inst.instruction = T_OPCODE_LDR_SP;
10227 else
10228 inst.instruction = T_OPCODE_STR_SP;
10229
10230 inst.instruction |= Rd << 8;
10231 if (inst.reloc.exp.X_op == O_constant)
10232 {
10233 unsigned offset = inst.reloc.exp.X_add_number;
10234
10235 if (offset & ~0x3fc)
10236 {
10237 inst.error = _("invalid offset");
10238 return;
10239 }
10240
10241 inst.instruction |= offset >> 2;
10242 }
10243 else
10244 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10245 }
10246 else if (Rb > 7)
10247 {
10248 inst.error = _("invalid base register in load/store");
10249 return;
10250 }
10251 else if (Ro == FAIL)
10252 {
10253 /* Immediate offset. */
10254 if (size == THUMB_WORD)
10255 inst.instruction = (load_store == THUMB_LOAD
10256 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10257 else if (size == THUMB_HALFWORD)
10258 inst.instruction = (load_store == THUMB_LOAD
10259 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10260 else
10261 inst.instruction = (load_store == THUMB_LOAD
10262 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10263
10264 inst.instruction |= Rd | (Rb << 3);
10265
10266 if (inst.reloc.exp.X_op == O_constant)
10267 {
10268 unsigned offset = inst.reloc.exp.X_add_number;
10269
10270 if (offset & ~(0x1f << size))
10271 {
f03698e6 10272 inst.error = _("invalid offset");
b99bd4ef
NC
10273 return;
10274 }
10275 inst.instruction |= (offset >> size) << 6;
10276 }
10277 else
10278 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10279 }
10280 else
10281 {
10282 /* Register offset. */
10283 if (size == THUMB_WORD)
10284 inst.instruction = (load_store == THUMB_LOAD
10285 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10286 else if (size == THUMB_HALFWORD)
10287 inst.instruction = (load_store == THUMB_LOAD
10288 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10289 else
10290 inst.instruction = (load_store == THUMB_LOAD
10291 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10292
10293 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10294 }
10295
10296 end_of_line (str);
10297}
10298
404ff6b5
AH
10299/* A register must be given at this point.
10300
404ff6b5
AH
10301 Shift is the place to put it in inst.instruction.
10302
404ff6b5
AH
10303 Restores input start point on err.
10304 Returns the reg#, or FAIL. */
10305
10306static int
63e63b07 10307mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10308 char ** str;
10309 int shift;
6c43fab6 10310 enum arm_reg_type regtype;
404ff6b5 10311{
6c43fab6
RE
10312 int reg;
10313 char *start = *str;
404ff6b5 10314
6c43fab6 10315 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10316 {
404ff6b5
AH
10317 if (shift >= 0)
10318 inst.instruction |= reg << shift;
10319
6c43fab6 10320 return reg;
404ff6b5
AH
10321 }
10322
6c43fab6 10323 /* Restore the start point. */
404ff6b5 10324 *str = start;
cc8a6dd0 10325
404ff6b5
AH
10326 /* In the few cases where we might be able to accept something else
10327 this error can be overridden. */
6c43fab6 10328 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10329
404ff6b5
AH
10330 return FAIL;
10331}
10332
63e63b07 10333/* Cirrus Maverick Instructions. */
404ff6b5
AH
10334
10335/* Wrapper functions. */
10336
10337static void
63e63b07 10338do_mav_binops_1a (str)
6c43fab6
RE
10339 char * str;
10340{
63e63b07 10341 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10342}
10343
10344static void
63e63b07 10345do_mav_binops_1b (str)
6c43fab6
RE
10346 char * str;
10347{
63e63b07 10348 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10349}
10350
10351static void
63e63b07 10352do_mav_binops_1c (str)
404ff6b5 10353 char * str;
404ff6b5 10354{
63e63b07 10355 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10356}
10357
10358static void
63e63b07 10359do_mav_binops_1d (str)
404ff6b5 10360 char * str;
404ff6b5 10361{
63e63b07 10362 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10363}
10364
10365static void
63e63b07 10366do_mav_binops_1e (str)
404ff6b5 10367 char * str;
404ff6b5 10368{
63e63b07 10369 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10370}
10371
10372static void
63e63b07 10373do_mav_binops_1f (str)
404ff6b5 10374 char * str;
404ff6b5 10375{
63e63b07 10376 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10377}
10378
10379static void
63e63b07 10380do_mav_binops_1g (str)
404ff6b5 10381 char * str;
404ff6b5 10382{
63e63b07 10383 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10384}
10385
10386static void
63e63b07 10387do_mav_binops_1h (str)
404ff6b5 10388 char * str;
404ff6b5 10389{
63e63b07 10390 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10391}
10392
6c43fab6 10393static void
63e63b07 10394do_mav_binops_1i (str)
6c43fab6
RE
10395 char * str;
10396{
63e63b07 10397 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10398}
10399
10400static void
63e63b07 10401do_mav_binops_1j (str)
6c43fab6
RE
10402 char * str;
10403{
63e63b07 10404 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10405}
10406
10407static void
63e63b07 10408do_mav_binops_1k (str)
6c43fab6
RE
10409 char * str;
10410{
63e63b07 10411 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10412}
10413
10414static void
63e63b07 10415do_mav_binops_1l (str)
6c43fab6
RE
10416 char * str;
10417{
63e63b07 10418 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10419}
10420
10421static void
63e63b07 10422do_mav_binops_1m (str)
6c43fab6
RE
10423 char * str;
10424{
63e63b07 10425 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10426}
10427
10428static void
63e63b07 10429do_mav_binops_1n (str)
6c43fab6
RE
10430 char * str;
10431{
63e63b07 10432 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10433}
10434
10435static void
63e63b07 10436do_mav_binops_1o (str)
6c43fab6
RE
10437 char * str;
10438{
63e63b07 10439 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10440}
10441
10442static void
63e63b07 10443do_mav_binops_2a (str)
6c43fab6
RE
10444 char * str;
10445{
63e63b07 10446 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10447}
10448
10449static void
63e63b07 10450do_mav_binops_2b (str)
6c43fab6
RE
10451 char * str;
10452{
63e63b07 10453 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10454}
10455
10456static void
63e63b07 10457do_mav_binops_2c (str)
6c43fab6
RE
10458 char * str;
10459{
63e63b07 10460 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10461}
10462
10463static void
63e63b07 10464do_mav_binops_3a (str)
6c43fab6
RE
10465 char * str;
10466{
63e63b07 10467 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10468}
10469
10470static void
63e63b07 10471do_mav_binops_3b (str)
6c43fab6
RE
10472 char * str;
10473{
63e63b07 10474 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10475}
10476
10477static void
63e63b07 10478do_mav_binops_3c (str)
6c43fab6
RE
10479 char * str;
10480{
63e63b07 10481 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10482}
10483
10484static void
63e63b07 10485do_mav_binops_3d (str)
6c43fab6
RE
10486 char * str;
10487{
63e63b07 10488 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10489}
10490
10491static void
63e63b07 10492do_mav_triple_4a (str)
6c43fab6
RE
10493 char * str;
10494{
63e63b07 10495 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10496}
10497
10498static void
63e63b07 10499do_mav_triple_4b (str)
6c43fab6
RE
10500 char * str;
10501{
63e63b07 10502 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10503}
10504
10505static void
63e63b07 10506do_mav_triple_5a (str)
6c43fab6
RE
10507 char * str;
10508{
63e63b07 10509 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10510}
10511
10512static void
63e63b07 10513do_mav_triple_5b (str)
6c43fab6
RE
10514 char * str;
10515{
63e63b07 10516 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10517}
10518
10519static void
63e63b07 10520do_mav_triple_5c (str)
6c43fab6
RE
10521 char * str;
10522{
63e63b07 10523 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10524}
10525
10526static void
63e63b07 10527do_mav_triple_5d (str)
6c43fab6
RE
10528 char * str;
10529{
63e63b07 10530 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10531}
10532
10533static void
63e63b07 10534do_mav_triple_5e (str)
6c43fab6
RE
10535 char * str;
10536{
63e63b07 10537 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10538}
10539
10540static void
63e63b07 10541do_mav_triple_5f (str)
6c43fab6
RE
10542 char * str;
10543{
63e63b07 10544 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10545}
10546
10547static void
63e63b07 10548do_mav_triple_5g (str)
6c43fab6
RE
10549 char * str;
10550{
63e63b07 10551 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10552}
10553
10554static void
63e63b07 10555do_mav_triple_5h (str)
6c43fab6
RE
10556 char * str;
10557{
63e63b07 10558 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10559}
10560
10561static void
63e63b07 10562do_mav_quad_6a (str)
6c43fab6
RE
10563 char * str;
10564{
63e63b07 10565 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10566 REG_TYPE_MVFX);
10567}
10568
10569static void
63e63b07 10570do_mav_quad_6b (str)
6c43fab6
RE
10571 char * str;
10572{
63e63b07 10573 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10574 REG_TYPE_MVFX);
10575}
10576
34920d91 10577/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
404ff6b5 10578static void
63e63b07 10579do_mav_dspsc_1 (str)
404ff6b5 10580 char * str;
404ff6b5 10581{
6c43fab6
RE
10582 skip_whitespace (str);
10583
10584 /* cfmvsc32. */
63e63b07 10585 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10586 || skip_past_comma (&str) == FAIL
34920d91 10587 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
6c43fab6
RE
10588 {
10589 if (!inst.error)
10590 inst.error = BAD_ARGS;
10591
10592 return;
10593 }
10594
10595 end_of_line (str);
404ff6b5
AH
10596}
10597
34920d91 10598/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
404ff6b5 10599static void
63e63b07 10600do_mav_dspsc_2 (str)
404ff6b5 10601 char * str;
404ff6b5 10602{
6c43fab6
RE
10603 skip_whitespace (str);
10604
10605 /* cfmv32sc. */
34920d91 10606 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
6c43fab6 10607 || skip_past_comma (&str) == FAIL
63e63b07 10608 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10609 {
10610 if (!inst.error)
10611 inst.error = BAD_ARGS;
10612
10613 return;
10614 }
10615
10616 end_of_line (str);
404ff6b5
AH
10617}
10618
10619static void
63e63b07 10620do_mav_shift_1 (str)
404ff6b5 10621 char * str;
404ff6b5 10622{
63e63b07 10623 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10624}
10625
10626static void
63e63b07 10627do_mav_shift_2 (str)
404ff6b5 10628 char * str;
404ff6b5 10629{
63e63b07 10630 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10631}
10632
10633static void
63e63b07 10634do_mav_ldst_1 (str)
404ff6b5 10635 char * str;
404ff6b5 10636{
63e63b07 10637 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10638}
10639
10640static void
63e63b07 10641do_mav_ldst_2 (str)
404ff6b5 10642 char * str;
404ff6b5 10643{
63e63b07 10644 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10645}
10646
10647static void
63e63b07 10648do_mav_ldst_3 (str)
404ff6b5 10649 char * str;
404ff6b5 10650{
63e63b07 10651 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10652}
10653
10654static void
63e63b07 10655do_mav_ldst_4 (str)
404ff6b5 10656 char * str;
404ff6b5 10657{
63e63b07 10658 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10659}
10660
10661/* Isnsn like "foo X,Y". */
10662
10663static void
63e63b07 10664do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10665 char * str;
404ff6b5 10666 int mode;
6c43fab6
RE
10667 enum arm_reg_type reg0;
10668 enum arm_reg_type reg1;
404ff6b5 10669{
6c43fab6 10670 int shift0, shift1;
404ff6b5 10671
6c43fab6
RE
10672 shift0 = mode & 0xff;
10673 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10674
10675 skip_whitespace (str);
10676
63e63b07 10677 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10678 || skip_past_comma (&str) == FAIL
63e63b07 10679 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10680 {
10681 if (!inst.error)
10682 inst.error = BAD_ARGS;
10683 }
10684 else
10685 end_of_line (str);
404ff6b5
AH
10686}
10687
10688/* Isnsn like "foo X,Y,Z". */
10689
10690static void
63e63b07 10691do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10692 char * str;
404ff6b5 10693 int mode;
6c43fab6
RE
10694 enum arm_reg_type reg0;
10695 enum arm_reg_type reg1;
10696 enum arm_reg_type reg2;
404ff6b5 10697{
6c43fab6 10698 int shift0, shift1, shift2;
404ff6b5 10699
6c43fab6
RE
10700 shift0 = mode & 0xff;
10701 shift1 = (mode >> 8) & 0xff;
10702 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10703
10704 skip_whitespace (str);
10705
63e63b07 10706 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10707 || skip_past_comma (&str) == FAIL
63e63b07 10708 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10709 || skip_past_comma (&str) == FAIL
63e63b07 10710 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10711 {
10712 if (!inst.error)
10713 inst.error = BAD_ARGS;
10714 }
10715 else
10716 end_of_line (str);
404ff6b5
AH
10717}
10718
10719/* Isnsn like "foo W,X,Y,Z".
10720 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10721
10722static void
63e63b07 10723do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10724 char * str;
404ff6b5 10725 int mode;
6c43fab6
RE
10726 enum arm_reg_type reg0;
10727 enum arm_reg_type reg1;
10728 enum arm_reg_type reg2;
10729 enum arm_reg_type reg3;
404ff6b5 10730{
6c43fab6 10731 int shift0, shift1, shift2, shift3;
404ff6b5 10732
6c43fab6
RE
10733 shift0= mode & 0xff;
10734 shift1 = (mode >> 8) & 0xff;
10735 shift2 = (mode >> 16) & 0xff;
10736 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10737
10738 skip_whitespace (str);
10739
63e63b07 10740 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10741 || skip_past_comma (&str) == FAIL
63e63b07 10742 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10743 || skip_past_comma (&str) == FAIL
63e63b07 10744 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10745 || skip_past_comma (&str) == FAIL
63e63b07 10746 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10747 {
10748 if (!inst.error)
10749 inst.error = BAD_ARGS;
10750 }
10751 else
10752 end_of_line (str);
404ff6b5
AH
10753}
10754
63e63b07 10755/* Maverick shift immediate instructions.
404ff6b5
AH
10756 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10757 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10758
10759static void
63e63b07 10760do_mav_shift (str, reg0, reg1)
404ff6b5 10761 char * str;
6c43fab6
RE
10762 enum arm_reg_type reg0;
10763 enum arm_reg_type reg1;
404ff6b5
AH
10764{
10765 int error;
10766 int imm, neg = 0;
10767
10768 skip_whitespace (str);
10769
10770 error = 0;
10771
63e63b07 10772 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10773 || skip_past_comma (&str) == FAIL
63e63b07 10774 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10775 || skip_past_comma (&str) == FAIL)
10776 {
10777 if (!inst.error)
10778 inst.error = BAD_ARGS;
10779 return;
10780 }
10781
10782 /* Calculate the immediate operand.
10783 The operand is a 7bit signed number. */
10784 skip_whitespace (str);
10785
10786 if (*str == '#')
10787 ++str;
10788
8420dfca 10789 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10790 {
10791 inst.error = _("expecting immediate, 7bit operand");
10792 return;
10793 }
10794
10795 if (*str == '-')
10796 {
10797 neg = 1;
10798 ++str;
10799 }
10800
8420dfca 10801 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10802 imm = imm * 10 + *str - '0';
10803
10804 if (imm > 64)
10805 {
10806 inst.error = _("immediate out of range");
10807 return;
10808 }
10809
10810 /* Make negative imm's into 7bit signed numbers. */
10811 if (neg)
10812 {
10813 imm = -imm;
10814 imm &= 0x0000007f;
10815 }
10816
10817 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10818 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10819 Bit 4 should be 0. */
10820 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10821
10822 inst.instruction |= imm;
404ff6b5 10823 end_of_line (str);
404ff6b5
AH
10824}
10825
10826static int
63e63b07 10827mav_parse_offset (str, negative)
404ff6b5
AH
10828 char ** str;
10829 int *negative;
10830{
10831 char * p = *str;
10832 int offset;
10833
10834 *negative = 0;
10835
10836 skip_whitespace (p);
10837
10838 if (*p == '#')
10839 ++p;
10840
10841 if (*p == '-')
10842 {
10843 *negative = 1;
10844 ++p;
10845 }
10846
8420dfca 10847 if (!ISDIGIT (*p))
404ff6b5
AH
10848 {
10849 inst.error = _("offset expected");
10850 return 0;
10851 }
10852
8420dfca 10853 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10854 offset = offset * 10 + *p - '0';
10855
10856 if (offset > 0xff)
10857 {
10858 inst.error = _("offset out of range");
10859 return 0;
10860 }
10861
10862 *str = p;
10863
10864 return *negative ? -offset : offset;
10865}
10866
63e63b07 10867/* Maverick load/store instructions.
404ff6b5
AH
10868 <insn><cond> CRd,[Rn,<offset>]{!}.
10869 <insn><cond> CRd,[Rn],<offset>. */
10870
10871static void
63e63b07 10872do_mav_ldst (str, reg0)
404ff6b5 10873 char * str;
6c43fab6 10874 enum arm_reg_type reg0;
404ff6b5
AH
10875{
10876 int offset, negative;
404ff6b5
AH
10877
10878 skip_whitespace (str);
10879
63e63b07 10880 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10881 || skip_past_comma (&str) == FAIL
404ff6b5 10882 || *str++ != '['
6c43fab6 10883 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10884 goto fail_ldst;
10885
6c43fab6 10886 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10887 {
10888 /* You are here: "<offset>]{!}". */
10889 inst.instruction |= PRE_INDEX;
10890
63e63b07 10891 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10892
10893 if (inst.error)
10894 return;
10895
10896 if (*str++ != ']')
10897 {
10898 inst.error = _("missing ]");
10899 return;
10900 }
10901
10902 if (*str == '!')
10903 {
10904 inst.instruction |= WRITE_BACK;
10905 ++str;
10906 }
10907 }
10908 else
10909 {
10910 /* You are here: "], <offset>". */
10911 if (*str++ != ']')
10912 {
10913 inst.error = _("missing ]");
10914 return;
10915 }
10916
10917 if (skip_past_comma (&str) == FAIL
63e63b07 10918 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10919 goto fail_ldst;
10920
10921 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10922 }
10923
10924 if (negative)
10925 offset = -offset;
10926 else
2d2255b5 10927 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10928
10929 inst.instruction |= offset >> 2;
404ff6b5
AH
10930 end_of_line (str);
10931 return;
10932
10933fail_ldst:
10934 if (!inst.error)
10935 inst.error = BAD_ARGS;
404ff6b5
AH
10936}
10937
b99bd4ef
NC
10938static void
10939do_t_nop (str)
10940 char * str;
10941{
10942 /* Do nothing. */
10943 end_of_line (str);
b99bd4ef
NC
10944}
10945
10946/* Handle the Format 4 instructions that do not have equivalents in other
10947 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10948 BIC and MVN. */
10949
10950static void
10951do_t_arit (str)
10952 char * str;
10953{
10954 int Rd, Rs, Rn;
10955
10956 skip_whitespace (str);
10957
10958 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10959 || skip_past_comma (&str) == FAIL
10960 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10961 {
10962 inst.error = BAD_ARGS;
10963 return;
10964 }
10965
10966 if (skip_past_comma (&str) != FAIL)
10967 {
10968 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10969 (It isn't allowed for CMP either, but that isn't handled by this
10970 function.) */
10971 if (inst.instruction == T_OPCODE_TST
10972 || inst.instruction == T_OPCODE_CMN
10973 || inst.instruction == T_OPCODE_NEG
10974 || inst.instruction == T_OPCODE_MVN)
10975 {
10976 inst.error = BAD_ARGS;
10977 return;
10978 }
10979
10980 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10981 return;
10982
10983 if (Rs != Rd)
10984 {
10985 inst.error = _("dest and source1 must be the same register");
10986 return;
10987 }
10988 Rs = Rn;
10989 }
10990
10991 if (inst.instruction == T_OPCODE_MUL
10992 && Rs == Rd)
10993 as_tsktsk (_("Rs and Rd must be different in MUL"));
10994
10995 inst.instruction |= Rd | (Rs << 3);
10996 end_of_line (str);
10997}
10998
10999static void
11000do_t_add (str)
11001 char * str;
11002{
11003 thumb_add_sub (str, 0);
11004}
11005
11006static void
11007do_t_asr (str)
11008 char * str;
11009{
11010 thumb_shift (str, THUMB_ASR);
11011}
11012
11013static void
11014do_t_branch9 (str)
11015 char * str;
11016{
11017 if (my_get_expression (&inst.reloc.exp, &str))
11018 return;
11019 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11020 inst.reloc.pc_rel = 1;
11021 end_of_line (str);
11022}
11023
11024static void
11025do_t_branch12 (str)
11026 char * str;
11027{
11028 if (my_get_expression (&inst.reloc.exp, &str))
11029 return;
11030 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11031 inst.reloc.pc_rel = 1;
11032 end_of_line (str);
11033}
11034
11035/* Find the real, Thumb encoded start of a Thumb function. */
11036
11037static symbolS *
11038find_real_start (symbolP)
11039 symbolS * symbolP;
11040{
11041 char * real_start;
11042 const char * name = S_GET_NAME (symbolP);
11043 symbolS * new_target;
11044
2d2255b5 11045 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11046#define STUB_NAME ".real_start_of"
11047
11048 if (name == NULL)
11049 abort ();
11050
11051 /* Names that start with '.' are local labels, not function entry points.
11052 The compiler may generate BL instructions to these labels because it
11053 needs to perform a branch to a far away location. */
11054 if (name[0] == '.')
11055 return symbolP;
11056
11057 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11058 sprintf (real_start, "%s%s", STUB_NAME, name);
11059
11060 new_target = symbol_find (real_start);
11061
11062 if (new_target == NULL)
11063 {
11064 as_warn ("Failed to find real start of function: %s\n", name);
11065 new_target = symbolP;
11066 }
11067
11068 free (real_start);
11069
11070 return new_target;
11071}
11072
11073static void
11074do_t_branch23 (str)
11075 char * str;
11076{
11077 if (my_get_expression (& inst.reloc.exp, & str))
11078 return;
11079
11080 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11081 inst.reloc.pc_rel = 1;
11082 end_of_line (str);
11083
11084 /* If the destination of the branch is a defined symbol which does not have
11085 the THUMB_FUNC attribute, then we must be calling a function which has
11086 the (interfacearm) attribute. We look for the Thumb entry point to that
11087 function and change the branch to refer to that function instead. */
11088 if ( inst.reloc.exp.X_op == O_symbol
11089 && inst.reloc.exp.X_add_symbol != NULL
11090 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11091 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11092 inst.reloc.exp.X_add_symbol =
11093 find_real_start (inst.reloc.exp.X_add_symbol);
11094}
11095
11096static void
11097do_t_bx (str)
11098 char * str;
11099{
11100 int reg;
11101
11102 skip_whitespace (str);
11103
11104 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11105 return;
11106
11107 /* This sets THUMB_H2 from the top bit of reg. */
11108 inst.instruction |= reg << 3;
11109
11110 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11111 should cause the alignment to be checked once it is known. This is
11112 because BX PC only works if the instruction is word aligned. */
11113
11114 end_of_line (str);
11115}
11116
11117static void
11118do_t_compare (str)
11119 char * str;
11120{
11121 thumb_mov_compare (str, THUMB_COMPARE);
11122}
11123
11124static void
11125do_t_ldmstm (str)
11126 char * str;
11127{
11128 int Rb;
11129 long range;
11130
11131 skip_whitespace (str);
11132
11133 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11134 return;
11135
11136 if (*str != '!')
f03698e6 11137 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11138 else
11139 str++;
11140
11141 if (skip_past_comma (&str) == FAIL
11142 || (range = reg_list (&str)) == FAIL)
11143 {
11144 if (! inst.error)
11145 inst.error = BAD_ARGS;
11146 return;
11147 }
11148
11149 if (inst.reloc.type != BFD_RELOC_NONE)
11150 {
11151 /* This really doesn't seem worth it. */
11152 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11153 inst.error = _("expression too complex");
b99bd4ef
NC
11154 return;
11155 }
11156
11157 if (range & ~0xff)
11158 {
11159 inst.error = _("only lo-regs valid in load/store multiple");
11160 return;
11161 }
11162
11163 inst.instruction |= (Rb << 8) | range;
11164 end_of_line (str);
11165}
11166
11167static void
11168do_t_ldr (str)
11169 char * str;
11170{
11171 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11172}
11173
11174static void
11175do_t_ldrb (str)
11176 char * str;
11177{
11178 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11179}
11180
11181static void
11182do_t_ldrh (str)
11183 char * str;
11184{
11185 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11186}
11187
11188static void
11189do_t_lds (str)
11190 char * str;
11191{
11192 int Rd, Rb, Ro;
11193
11194 skip_whitespace (str);
11195
11196 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11197 || skip_past_comma (&str) == FAIL
11198 || *str++ != '['
11199 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11200 || skip_past_comma (&str) == FAIL
11201 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11202 || *str++ != ']')
11203 {
11204 if (! inst.error)
f03698e6 11205 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11206 return;
11207 }
11208
11209 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11210 end_of_line (str);
11211}
11212
11213static void
11214do_t_lsl (str)
11215 char * str;
11216{
11217 thumb_shift (str, THUMB_LSL);
11218}
11219
11220static void
11221do_t_lsr (str)
11222 char * str;
11223{
11224 thumb_shift (str, THUMB_LSR);
11225}
11226
11227static void
11228do_t_mov (str)
11229 char * str;
11230{
11231 thumb_mov_compare (str, THUMB_MOVE);
11232}
11233
11234static void
11235do_t_push_pop (str)
11236 char * str;
11237{
11238 long range;
11239
11240 skip_whitespace (str);
11241
11242 if ((range = reg_list (&str)) == FAIL)
11243 {
11244 if (! inst.error)
11245 inst.error = BAD_ARGS;
11246 return;
11247 }
11248
11249 if (inst.reloc.type != BFD_RELOC_NONE)
11250 {
11251 /* This really doesn't seem worth it. */
11252 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11253 inst.error = _("expression too complex");
b99bd4ef
NC
11254 return;
11255 }
11256
11257 if (range & ~0xff)
11258 {
11259 if ((inst.instruction == T_OPCODE_PUSH
11260 && (range & ~0xff) == 1 << REG_LR)
11261 || (inst.instruction == T_OPCODE_POP
11262 && (range & ~0xff) == 1 << REG_PC))
11263 {
11264 inst.instruction |= THUMB_PP_PC_LR;
11265 range &= 0xff;
11266 }
11267 else
11268 {
11269 inst.error = _("invalid register list to push/pop instruction");
11270 return;
11271 }
11272 }
11273
11274 inst.instruction |= range;
11275 end_of_line (str);
11276}
11277
11278static void
11279do_t_str (str)
11280 char * str;
11281{
11282 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11283}
11284
11285static void
11286do_t_strb (str)
11287 char * str;
11288{
11289 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11290}
11291
11292static void
11293do_t_strh (str)
11294 char * str;
11295{
11296 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11297}
11298
11299static void
11300do_t_sub (str)
11301 char * str;
11302{
11303 thumb_add_sub (str, 1);
11304}
11305
11306static void
11307do_t_swi (str)
11308 char * str;
11309{
11310 skip_whitespace (str);
11311
11312 if (my_get_expression (&inst.reloc.exp, &str))
11313 return;
11314
11315 inst.reloc.type = BFD_RELOC_ARM_SWI;
11316 end_of_line (str);
b99bd4ef
NC
11317}
11318
11319static void
11320do_t_adr (str)
11321 char * str;
11322{
11323 int reg;
11324
11325 /* This is a pseudo-op of the form "adr rd, label" to be converted
11326 into a relative address of the form "add rd, pc, #label-.-4". */
11327 skip_whitespace (str);
11328
11329 /* Store Rd in temporary location inside instruction. */
11330 if ((reg = reg_required_here (&str, 4)) == FAIL
11331 || (reg > 7) /* For Thumb reg must be r0..r7. */
11332 || skip_past_comma (&str) == FAIL
11333 || my_get_expression (&inst.reloc.exp, &str))
11334 {
11335 if (!inst.error)
11336 inst.error = BAD_ARGS;
11337 return;
11338 }
11339
11340 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11341 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11342 inst.reloc.pc_rel = 1;
11343 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11344
11345 end_of_line (str);
11346}
11347
11348static void
6c43fab6
RE
11349insert_reg (r, htab)
11350 const struct reg_entry *r;
11351 struct hash_control *htab;
b99bd4ef 11352{
6c43fab6 11353 int len = strlen (r->name) + 2;
b99bd4ef
NC
11354 char * buf = (char *) xmalloc (len);
11355 char * buf2 = (char *) xmalloc (len);
11356 int i = 0;
11357
11358#ifdef REGISTER_PREFIX
11359 buf[i++] = REGISTER_PREFIX;
11360#endif
11361
6c43fab6 11362 strcpy (buf + i, r->name);
b99bd4ef
NC
11363
11364 for (i = 0; buf[i]; i++)
3882b010 11365 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11366
11367 buf2[i] = '\0';
11368
6c43fab6
RE
11369 hash_insert (htab, buf, (PTR) r);
11370 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11371}
11372
11373static void
6c43fab6
RE
11374build_reg_hsh (map)
11375 struct reg_map *map;
11376{
11377 const struct reg_entry *r;
11378
11379 if ((map->htab = hash_new ()) == NULL)
f03698e6 11380 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11381
11382 for (r = map->names; r->name != NULL; r++)
11383 insert_reg (r, map->htab);
11384}
11385
11386static void
11387insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11388 char *str;
11389 int regnum;
6c43fab6 11390 struct hash_control *htab;
b99bd4ef 11391{
0bbf2aa4
NC
11392 const char *error;
11393 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11394 const char *name = xmalloc (strlen (str) + 1);
11395
11396 strcpy ((char *) name, str);
11397
b99bd4ef
NC
11398 new->name = name;
11399 new->number = regnum;
0bbf2aa4 11400 new->builtin = FALSE;
b99bd4ef 11401
0bbf2aa4
NC
11402 error = hash_insert (htab, name, (PTR) new);
11403 if (error)
11404 {
11405 as_bad (_("failed to create an alias for %s, reason: %s"),
11406 str, error);
11407 free ((char *) name);
11408 free (new);
11409 }
b99bd4ef
NC
11410}
11411
6c43fab6
RE
11412/* Look for the .req directive. This is of the form:
11413
0bbf2aa4 11414 new_register_name .req existing_register_name
6c43fab6
RE
11415
11416 If we find one, or if it looks sufficiently like one that we want to
11417 handle any error here, return non-zero. Otherwise return zero. */
11418static int
11419create_register_alias (newname, p)
11420 char *newname;
11421 char *p;
11422{
11423 char *q;
11424 char c;
11425
11426 q = p;
11427 skip_whitespace (q);
11428
11429 c = *p;
11430 *p = '\0';
11431
11432 if (*q && !strncmp (q, ".req ", 5))
11433 {
11434 char *copy_of_str;
11435 char *r;
11436
11437#ifdef IGNORE_OPCODE_CASE
11438 newname = original_case_string;
11439#endif
11440 copy_of_str = newname;
11441
11442 q += 4;
11443 skip_whitespace (q);
11444
11445 for (r = q; *r != '\0'; r++)
11446 if (*r == ' ')
11447 break;
11448
11449 if (r != q)
11450 {
11451 enum arm_reg_type new_type, old_type;
11452 int old_regno;
11453 char d = *r;
11454
11455 *r = '\0';
11456 old_type = arm_reg_parse_any (q);
11457 *r = d;
11458
11459 new_type = arm_reg_parse_any (newname);
11460
11461 if (new_type == REG_TYPE_MAX)
11462 {
11463 if (old_type != REG_TYPE_MAX)
11464 {
11465 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11466 insert_reg_alias (newname, old_regno,
11467 all_reg_maps[old_type].htab);
11468 }
11469 else
11470 as_warn (_("register '%s' does not exist\n"), q);
11471 }
11472 else if (old_type == REG_TYPE_MAX)
11473 {
11474 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11475 copy_of_str, q);
11476 }
11477 else
11478 {
11479 /* Do not warn about redefinitions to the same alias. */
11480 if (new_type != old_type
11481 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11482 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11483 as_warn (_("ignoring redefinition of register alias '%s'"),
11484 copy_of_str);
11485
11486 }
11487 }
11488 else
11489 as_warn (_("ignoring incomplete .req pseuso op"));
11490
11491 *p = c;
11492 return 1;
11493 }
0bbf2aa4 11494
6c43fab6
RE
11495 *p = c;
11496 return 0;
11497}
cc8a6dd0 11498
b99bd4ef
NC
11499static void
11500set_constant_flonums ()
11501{
11502 int i;
11503
11504 for (i = 0; i < NUM_FLOAT_VALS; i++)
11505 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11506 abort ();
11507}
11508
90e4755a
RE
11509/* Iterate over the base tables to create the instruction patterns. */
11510static void
11511build_arm_ops_hsh ()
11512{
11513 unsigned int i;
11514 unsigned int j;
11515 static struct obstack insn_obstack;
11516
11517 obstack_begin (&insn_obstack, 4000);
11518
11519 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11520 {
6c43fab6 11521 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11522
11523 if (insn->cond_offset != 0)
11524 {
11525 /* Insn supports conditional execution. Build the varaints
11526 and insert them in the hash table. */
11527 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11528 {
11529 unsigned len = strlen (insn->template);
11530 struct asm_opcode *new;
11531 char *template;
11532
11533 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11534 /* All condition codes are two characters. */
11535 template = obstack_alloc (&insn_obstack, len + 3);
11536
11537 strncpy (template, insn->template, insn->cond_offset);
11538 strcpy (template + insn->cond_offset, conds[j].template);
11539 if (len > insn->cond_offset)
11540 strcpy (template + insn->cond_offset + 2,
11541 insn->template + insn->cond_offset);
11542 new->template = template;
11543 new->cond_offset = 0;
11544 new->variant = insn->variant;
11545 new->parms = insn->parms;
11546 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11547
11548 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11549 }
11550 }
11551 /* Finally, insert the unconditional insn in the table directly;
11552 no need to build a copy. */
11553 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11554 }
11555}
11556
0bbf2aa4 11557#if 0 /* Suppressed - for now. */
5a6c6817
NC
11558#if defined OBJ_ELF || defined OBJ_COFF
11559
11560#ifdef OBJ_ELF
11561#define arm_Note Elf_External_Note
11562#else
11563typedef struct
11564{
11565 unsigned char namesz[4]; /* Size of entry's owner string. */
11566 unsigned char descsz[4]; /* Size of the note descriptor. */
11567 unsigned char type[4]; /* Interpretation of the descriptor. */
11568 char name[1]; /* Start of the name+desc data. */
11569} arm_Note;
11570#endif
11571
11572/* The description is kept to a fix sized in order to make updating
11573 it and merging it easier. */
11574#define ARM_NOTE_DESCRIPTION_LENGTH 8
11575
11576static void
11577arm_add_note (name, description, type)
11578 const char * name;
11579 const char * description;
11580 unsigned int type;
11581{
11582 arm_Note note ATTRIBUTE_UNUSED;
11583 char * p;
11584 unsigned int name_len;
11585
11586 name_len = (strlen (name) + 1 + 3) & ~3;
11587
11588 p = frag_more (sizeof (note.namesz));
11589 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11590
11591 p = frag_more (sizeof (note.descsz));
11592 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11593
11594 p = frag_more (sizeof (note.type));
11595 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11596
11597 p = frag_more (name_len);
11598 strcpy (p, name);
11599
11600 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11601 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11602 frag_align (2, 0, 0);
11603}
11604#endif
0bbf2aa4 11605#endif
5a6c6817 11606
b99bd4ef
NC
11607void
11608md_begin ()
11609{
11610 unsigned mach;
11611 unsigned int i;
11612
11613 if ( (arm_ops_hsh = hash_new ()) == NULL
11614 || (arm_tops_hsh = hash_new ()) == NULL
11615 || (arm_cond_hsh = hash_new ()) == NULL
11616 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11617 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11618 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11619
90e4755a 11620 build_arm_ops_hsh ();
b99bd4ef
NC
11621 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11622 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11623 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11624 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11625 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11626 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11627 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11628 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11629
6c43fab6
RE
11630 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11631 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11632
11633 set_constant_flonums ();
11634
03b1477f
RE
11635 /* Set the cpu variant based on the command-line options. We prefer
11636 -mcpu= over -march= if both are set (as for GCC); and we prefer
11637 -mfpu= over any other way of setting the floating point unit.
11638 Use of legacy options with new options are faulted. */
11639 if (legacy_cpu != -1)
11640 {
11641 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11642 as_bad (_("use of old and new-style options to set CPU type"));
11643
11644 mcpu_cpu_opt = legacy_cpu;
11645 }
11646 else if (mcpu_cpu_opt == -1)
11647 mcpu_cpu_opt = march_cpu_opt;
11648
11649 if (legacy_fpu != -1)
11650 {
11651 if (mfpu_opt != -1)
11652 as_bad (_("use of old and new-style options to set FPU type"));
11653
11654 mfpu_opt = legacy_fpu;
11655 }
11656 else if (mfpu_opt == -1)
11657 {
39c2da32
RE
11658#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11659 /* Some environments specify a default FPU. If they don't, infer it
11660 from the processor. */
03b1477f
RE
11661 if (mcpu_fpu_opt != -1)
11662 mfpu_opt = mcpu_fpu_opt;
11663 else
11664 mfpu_opt = march_fpu_opt;
39c2da32
RE
11665#else
11666 mfpu_opt = FPU_DEFAULT;
11667#endif
03b1477f
RE
11668 }
11669
11670 if (mfpu_opt == -1)
11671 {
11672 if (mcpu_cpu_opt == -1)
11673 mfpu_opt = FPU_DEFAULT;
11674 else if (mcpu_cpu_opt & ARM_EXT_V5)
11675 mfpu_opt = FPU_ARCH_VFP_V2;
11676 else
11677 mfpu_opt = FPU_ARCH_FPA;
11678 }
11679
11680 if (mcpu_cpu_opt == -1)
11681 mcpu_cpu_opt = CPU_DEFAULT;
11682
11683 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11684
b99bd4ef 11685 {
7cc69913
NC
11686 unsigned int flags = 0;
11687
11688#if defined OBJ_ELF
11689 flags = meabi_flags;
d507cf36
PB
11690
11691 switch (meabi_flags)
33a392fb 11692 {
d507cf36 11693 case EF_ARM_EABI_UNKNOWN:
7cc69913
NC
11694#endif
11695#if defined OBJ_COFF || defined OBJ_ELF
d507cf36
PB
11696 /* Set the flags in the private structure. */
11697 if (uses_apcs_26) flags |= F_APCS26;
11698 if (support_interwork) flags |= F_INTERWORK;
11699 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11700 if (pic_code) flags |= F_PIC;
11701 if ((cpu_variant & FPU_ANY) == FPU_NONE
11702 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11703 flags |= F_SOFT_FLOAT;
11704
d507cf36
PB
11705 switch (mfloat_abi_opt)
11706 {
11707 case ARM_FLOAT_ABI_SOFT:
11708 case ARM_FLOAT_ABI_SOFTFP:
11709 flags |= F_SOFT_FLOAT;
11710 break;
33a392fb 11711
d507cf36
PB
11712 case ARM_FLOAT_ABI_HARD:
11713 if (flags & F_SOFT_FLOAT)
11714 as_bad (_("hard-float conflicts with specified fpu"));
11715 break;
11716 }
03b1477f 11717
7cc69913
NC
11718 /* Using VFP conventions (even if soft-float). */
11719 if (cpu_variant & FPU_VFP_EXT_NONE)
11720 flags |= F_VFP_FLOAT;
11721#endif
fde78edd 11722#if defined OBJ_ELF
d507cf36
PB
11723 if (cpu_variant & FPU_ARCH_MAVERICK)
11724 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11725 break;
11726
11727 case EF_ARM_EABI_VER3:
11728 /* No additional flags to set. */
11729 break;
11730
11731 default:
11732 abort ();
11733 }
7cc69913
NC
11734#endif
11735#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef
NC
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 }
b99bd4ef 11755#endif
7cc69913 11756 }
b99bd4ef
NC
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
7cc69913 13473#ifdef OBJ_ELF
d507cf36
PB
13474/* We only know hot to output GNU and ver 3 (AAELF) formats. */
13475static struct arm_eabi_option_table arm_eabis[] =
13476{
13477 {"gnu", EF_ARM_EABI_UNKNOWN},
13478 {"3", EF_ARM_EABI_VER3},
13479 {NULL, 0}
13480};
7cc69913 13481#endif
d507cf36 13482
03b1477f
RE
13483struct arm_long_option_table
13484{
13485 char *option; /* Substring to match. */
13486 char *help; /* Help information. */
13487 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13488 char *deprecated; /* If non-null, print this message. */
13489};
13490
13491static int
13492arm_parse_extension (str, opt_p)
13493 char *str;
13494 int *opt_p;
13495{
13496 while (str != NULL && *str != 0)
13497 {
13498 struct arm_arch_extension_table *opt;
13499 char *ext;
13500 int optlen;
13501
13502 if (*str != '+')
b99bd4ef 13503 {
03b1477f
RE
13504 as_bad (_("invalid architectural extension"));
13505 return 0;
13506 }
b99bd4ef 13507
03b1477f
RE
13508 str++;
13509 ext = strchr (str, '+');
b99bd4ef 13510
03b1477f
RE
13511 if (ext != NULL)
13512 optlen = ext - str;
13513 else
13514 optlen = strlen (str);
b99bd4ef 13515
03b1477f
RE
13516 if (optlen == 0)
13517 {
13518 as_bad (_("missing architectural extension"));
13519 return 0;
13520 }
b99bd4ef 13521
03b1477f
RE
13522 for (opt = arm_extensions; opt->name != NULL; opt++)
13523 if (strncmp (opt->name, str, optlen) == 0)
13524 {
13525 *opt_p |= opt->value;
13526 break;
13527 }
bfae80f2 13528
03b1477f
RE
13529 if (opt->name == NULL)
13530 {
13531 as_bad (_("unknown architectural extnsion `%s'"), str);
13532 return 0;
13533 }
b99bd4ef 13534
03b1477f
RE
13535 str = ext;
13536 };
b99bd4ef 13537
03b1477f
RE
13538 return 1;
13539}
b99bd4ef 13540
03b1477f
RE
13541static int
13542arm_parse_cpu (str)
13543 char *str;
13544{
13545 struct arm_cpu_option_table *opt;
13546 char *ext = strchr (str, '+');
13547 int optlen;
b99bd4ef 13548
03b1477f
RE
13549 if (ext != NULL)
13550 optlen = ext - str;
13551 else
13552 optlen = strlen (str);
b99bd4ef 13553
03b1477f
RE
13554 if (optlen == 0)
13555 {
13556 as_bad (_("missing cpu name `%s'"), str);
13557 return 0;
13558 }
b99bd4ef 13559
03b1477f
RE
13560 for (opt = arm_cpus; opt->name != NULL; opt++)
13561 if (strncmp (opt->name, str, optlen) == 0)
13562 {
13563 mcpu_cpu_opt = opt->value;
13564 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13565
03b1477f
RE
13566 if (ext != NULL)
13567 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13568
03b1477f
RE
13569 return 1;
13570 }
b99bd4ef 13571
03b1477f
RE
13572 as_bad (_("unknown cpu `%s'"), str);
13573 return 0;
13574}
b99bd4ef 13575
03b1477f
RE
13576static int
13577arm_parse_arch (str)
13578 char *str;
13579{
13580 struct arm_arch_option_table *opt;
13581 char *ext = strchr (str, '+');
13582 int optlen;
b99bd4ef 13583
03b1477f
RE
13584 if (ext != NULL)
13585 optlen = ext - str;
13586 else
13587 optlen = strlen (str);
b99bd4ef 13588
03b1477f
RE
13589 if (optlen == 0)
13590 {
13591 as_bad (_("missing architecture name `%s'"), str);
13592 return 0;
13593 }
b99bd4ef 13594
b99bd4ef 13595
03b1477f
RE
13596 for (opt = arm_archs; opt->name != NULL; opt++)
13597 if (strcmp (opt->name, str) == 0)
13598 {
13599 march_cpu_opt = opt->value;
13600 march_fpu_opt = opt->default_fpu;
b99bd4ef 13601
03b1477f
RE
13602 if (ext != NULL)
13603 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13604
03b1477f
RE
13605 return 1;
13606 }
b99bd4ef 13607
03b1477f
RE
13608 as_bad (_("unknown architecture `%s'\n"), str);
13609 return 0;
13610}
13611
13612static int
13613arm_parse_fpu (str)
13614 char *str;
13615{
13616 struct arm_fpu_option_table *opt;
b99bd4ef 13617
03b1477f
RE
13618 for (opt = arm_fpus; opt->name != NULL; opt++)
13619 if (strcmp (opt->name, str) == 0)
13620 {
13621 mfpu_opt = opt->value;
13622 return 1;
13623 }
b99bd4ef 13624
03b1477f
RE
13625 as_bad (_("unknown floating point format `%s'\n"), str);
13626 return 0;
13627}
b99bd4ef 13628
33a392fb
PB
13629static int
13630arm_parse_float_abi (str)
13631 char * str;
13632{
13633 struct arm_float_abi_option_table *opt;
13634
13635 for (opt = arm_float_abis; opt->name != NULL; opt++)
13636 if (strcmp (opt->name, str) == 0)
13637 {
13638 mfloat_abi_opt = opt->value;
13639 return 1;
13640 }
13641
13642 as_bad (_("unknown floating point abi `%s'\n"), str);
13643 return 0;
13644}
13645
7cc69913 13646#ifdef OBJ_ELF
d507cf36
PB
13647static int
13648arm_parse_eabi (str)
13649 char * str;
13650{
13651 struct arm_eabi_option_table *opt;
13652
13653 for (opt = arm_eabis; opt->name != NULL; opt++)
13654 if (strcmp (opt->name, str) == 0)
13655 {
13656 meabi_flags = opt->value;
13657 return 1;
13658 }
13659 as_bad (_("unknown EABI `%s'\n"), str);
13660 return 0;
13661}
7cc69913 13662#endif
d507cf36 13663
03b1477f
RE
13664struct arm_long_option_table arm_long_opts[] =
13665{
13666 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13667 arm_parse_cpu, NULL},
13668 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13669 arm_parse_arch, NULL},
13670 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13671 arm_parse_fpu, NULL},
33a392fb
PB
13672 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13673 arm_parse_float_abi, NULL},
7cc69913 13674#ifdef OBJ_ELF
d507cf36
PB
13675 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13676 arm_parse_eabi, NULL},
7cc69913 13677#endif
03b1477f
RE
13678 {NULL, NULL, 0, NULL}
13679};
b99bd4ef 13680
03b1477f
RE
13681int
13682md_parse_option (c, arg)
13683 int c;
13684 char * arg;
13685{
13686 struct arm_option_table *opt;
13687 struct arm_long_option_table *lopt;
b99bd4ef 13688
03b1477f
RE
13689 switch (c)
13690 {
13691#ifdef OPTION_EB
13692 case OPTION_EB:
13693 target_big_endian = 1;
b99bd4ef 13694 break;
03b1477f 13695#endif
b99bd4ef 13696
03b1477f
RE
13697#ifdef OPTION_EL
13698 case OPTION_EL:
13699 target_big_endian = 0;
b99bd4ef
NC
13700 break;
13701#endif
13702
03b1477f 13703 case 'a':
cc8a6dd0 13704 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13705 ones. */
13706 return 0;
13707
b99bd4ef 13708 default:
03b1477f
RE
13709 for (opt = arm_opts; opt->option != NULL; opt++)
13710 {
13711 if (c == opt->option[0]
13712 && ((arg == NULL && opt->option[1] == 0)
13713 || strcmp (arg, opt->option + 1) == 0))
13714 {
13715#if WARN_DEPRECATED
13716 /* If the option is deprecated, tell the user. */
13717 if (opt->deprecated != NULL)
13718 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13719 arg ? arg : "", _(opt->deprecated));
13720#endif
13721
13722 if (opt->var != NULL)
13723 *opt->var = opt->value;
13724
13725 return 1;
13726 }
13727 }
13728
13729 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13730 {
cc8a6dd0 13731 /* These options are expected to have an argument. */
03b1477f
RE
13732 if (c == lopt->option[0]
13733 && arg != NULL
cc8a6dd0 13734 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13735 strlen (lopt->option + 1)) == 0)
13736 {
13737#if WARN_DEPRECATED
13738 /* If the option is deprecated, tell the user. */
13739 if (lopt->deprecated != NULL)
13740 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13741 _(lopt->deprecated));
13742#endif
13743
13744 /* Call the sup-option parser. */
13745 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13746 }
13747 }
13748
13749 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
13750 return 0;
13751 }
13752
13753 return 1;
13754}
13755
13756void
13757md_show_usage (fp)
13758 FILE * fp;
13759{
03b1477f
RE
13760 struct arm_option_table *opt;
13761 struct arm_long_option_table *lopt;
13762
13763 fprintf (fp, _(" ARM-specific assembler options:\n"));
13764
13765 for (opt = arm_opts; opt->option != NULL; opt++)
13766 if (opt->help != NULL)
13767 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13768
13769 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13770 if (lopt->help != NULL)
13771 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13772
13773#ifdef OPTION_EB
b99bd4ef 13774 fprintf (fp, _("\
03b1477f 13775 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13776#endif
03b1477f
RE
13777
13778#ifdef OPTION_EL
b99bd4ef 13779 fprintf (fp, _("\
03b1477f 13780 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13781#endif
13782}
13783
13784/* We need to be able to fix up arbitrary expressions in some statements.
13785 This is so that we can handle symbols that are an arbitrary distance from
13786 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13787 which returns part of an address in a form which will be valid for
13788 a data instruction. We do this by pushing the expression into a symbol
13789 in the expr_section, and creating a fix for that. */
13790
13791static void
13792fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13793 fragS * frag;
13794 int where;
13795 short int size;
13796 expressionS * exp;
13797 int pc_rel;
13798 int reloc;
13799{
13800 fixS * new_fix;
13801 arm_fix_data * arm_data;
13802
13803 switch (exp->X_op)
13804 {
13805 case O_constant:
13806 case O_symbol:
13807 case O_add:
13808 case O_subtract:
13809 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13810 break;
13811
13812 default:
13813 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13814 pc_rel, reloc);
13815 break;
13816 }
13817
13818 /* Mark whether the fix is to a THUMB instruction, or an ARM
13819 instruction. */
13820 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13821 new_fix->tc_fix_data = (PTR) arm_data;
13822 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13823}
13824
13825/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13826
13827void
13828cons_fix_new_arm (frag, where, size, exp)
13829 fragS * frag;
13830 int where;
13831 int size;
13832 expressionS * exp;
13833{
13834 bfd_reloc_code_real_type type;
13835 int pcrel = 0;
13836
13837 /* Pick a reloc.
13838 FIXME: @@ Should look at CPU word size. */
13839 switch (size)
13840 {
13841 case 1:
13842 type = BFD_RELOC_8;
13843 break;
13844 case 2:
13845 type = BFD_RELOC_16;
13846 break;
13847 case 4:
13848 default:
13849 type = BFD_RELOC_32;
13850 break;
13851 case 8:
13852 type = BFD_RELOC_64;
13853 break;
13854 }
13855
13856 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13857}
13858
13859/* A good place to do this, although this was probably not intended
13860 for this kind of use. We need to dump the literal pool before
13861 references are made to a null symbol pointer. */
13862
13863void
13864arm_cleanup ()
13865{
3d0c9500 13866 literal_pool * pool;
b99bd4ef 13867
3d0c9500
NC
13868 for (pool = list_of_pools; pool; pool = pool->next)
13869 {
13870 /* Put it at the end of the relevent section. */
13871 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13872#ifdef OBJ_ELF
13873 arm_elf_change_section ();
13874#endif
3d0c9500
NC
13875 s_ltorg (0);
13876 }
b99bd4ef
NC
13877}
13878
13879void
13880arm_start_line_hook ()
13881{
13882 last_label_seen = NULL;
13883}
13884
13885void
13886arm_frob_label (sym)
13887 symbolS * sym;
13888{
13889 last_label_seen = sym;
13890
13891 ARM_SET_THUMB (sym, thumb_mode);
13892
13893#if defined OBJ_COFF || defined OBJ_ELF
13894 ARM_SET_INTERWORK (sym, support_interwork);
13895#endif
13896
13897 /* Note - do not allow local symbols (.Lxxx) to be labeled
13898 as Thumb functions. This is because these labels, whilst
13899 they exist inside Thumb code, are not the entry points for
13900 possible ARM->Thumb calls. Also, these labels can be used
13901 as part of a computed goto or switch statement. eg gcc
13902 can generate code that looks like this:
13903
13904 ldr r2, [pc, .Laaa]
13905 lsl r3, r3, #2
13906 ldr r2, [r3, r2]
13907 mov pc, r2
cc8a6dd0 13908
b99bd4ef
NC
13909 .Lbbb: .word .Lxxx
13910 .Lccc: .word .Lyyy
13911 ..etc...
13912 .Laaa: .word Lbbb
13913
13914 The first instruction loads the address of the jump table.
13915 The second instruction converts a table index into a byte offset.
13916 The third instruction gets the jump address out of the table.
13917 The fourth instruction performs the jump.
cc8a6dd0 13918
b99bd4ef
NC
13919 If the address stored at .Laaa is that of a symbol which has the
13920 Thumb_Func bit set, then the linker will arrange for this address
13921 to have the bottom bit set, which in turn would mean that the
13922 address computation performed by the third instruction would end
13923 up with the bottom bit set. Since the ARM is capable of unaligned
13924 word loads, the instruction would then load the incorrect address
13925 out of the jump table, and chaos would ensue. */
13926 if (label_is_thumb_function_name
13927 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13928 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13929 {
13930 /* When the address of a Thumb function is taken the bottom
13931 bit of that address should be set. This will allow
13932 interworking between Arm and Thumb functions to work
13933 correctly. */
13934
13935 THUMB_SET_FUNC (sym, 1);
13936
b34976b6 13937 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13938 }
13939}
13940
13941/* Adjust the symbol table. This marks Thumb symbols as distinct from
13942 ARM ones. */
13943
13944void
13945arm_adjust_symtab ()
13946{
13947#ifdef OBJ_COFF
13948 symbolS * sym;
13949
13950 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13951 {
13952 if (ARM_IS_THUMB (sym))
13953 {
13954 if (THUMB_IS_FUNC (sym))
13955 {
13956 /* Mark the symbol as a Thumb function. */
13957 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13958 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13959 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13960
13961 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13962 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13963 else
13964 as_bad (_("%s: unexpected function type: %d"),
13965 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13966 }
cc8a6dd0 13967 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13968 {
13969 case C_EXT:
13970 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13971 break;
13972 case C_STAT:
13973 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13974 break;
13975 case C_LABEL:
13976 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13977 break;
13978 default:
13979 /* Do nothing. */
13980 break;
13981 }
13982 }
13983
13984 if (ARM_IS_INTERWORK (sym))
13985 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13986 }
13987#endif
13988#ifdef OBJ_ELF
13989 symbolS * sym;
13990 char bind;
13991
13992 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13993 {
13994 if (ARM_IS_THUMB (sym))
13995 {
13996 elf_symbol_type * elf_sym;
13997
13998 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13999 bind = ELF_ST_BIND (elf_sym);
14000
14001 /* If it's a .thumb_func, declare it as so,
14002 otherwise tag label as .code 16. */
14003 if (THUMB_IS_FUNC (sym))
14004 elf_sym->internal_elf_sym.st_info =
14005 ELF_ST_INFO (bind, STT_ARM_TFUNC);
14006 else
14007 elf_sym->internal_elf_sym.st_info =
14008 ELF_ST_INFO (bind, STT_ARM_16BIT);
14009 }
14010 }
14011#endif
14012}
14013
14014int
14015arm_data_in_code ()
14016{
14017 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
14018 {
14019 *input_line_pointer = '/';
14020 input_line_pointer += 5;
14021 *input_line_pointer = 0;
14022 return 1;
14023 }
14024
14025 return 0;
14026}
14027
14028char *
14029arm_canonicalize_symbol_name (name)
14030 char * name;
14031{
14032 int len;
14033
14034 if (thumb_mode && (len = strlen (name)) > 5
14035 && streq (name + len - 5, "/data"))
14036 *(name + len - 5) = 0;
14037
14038 return name;
14039}
14040
bfc866a6 14041#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 14042void
b99bd4ef
NC
14043arm_validate_fix (fixP)
14044 fixS * fixP;
14045{
14046 /* If the destination of the branch is a defined symbol which does not have
14047 the THUMB_FUNC attribute, then we must be calling a function which has
14048 the (interfacearm) attribute. We look for the Thumb entry point to that
14049 function and change the branch to refer to that function instead. */
14050 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
14051 && fixP->fx_addsy != NULL
14052 && S_IS_DEFINED (fixP->fx_addsy)
14053 && ! THUMB_IS_FUNC (fixP->fx_addsy))
14054 {
14055 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 14056 }
b99bd4ef 14057}
bfc866a6 14058#endif
b99bd4ef 14059
114424c6
AM
14060int
14061arm_force_relocation (fixp)
14062 struct fix * fixp;
14063{
14064#if defined (OBJ_COFF) && defined (TE_PE)
14065 if (fixp->fx_r_type == BFD_RELOC_RVA)
14066 return 1;
14067#endif
14068#ifdef OBJ_ELF
ae6063d4 14069 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
14070 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14071 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14072 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14073 return 1;
14074#endif
14075
14076 /* Resolve these relocations even if the symbol is extern or weak. */
14077 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 14078 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
14079 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14080 return 0;
14081
ae6063d4 14082 return generic_force_reloc (fixp);
114424c6
AM
14083}
14084
b99bd4ef
NC
14085#ifdef OBJ_COFF
14086/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14087 local labels from being added to the output symbol table when they
14088 are used with the ADRL pseudo op. The ADRL relocation should always
14089 be resolved before the binbary is emitted, so it is safe to say that
14090 it is adjustable. */
14091
b34976b6 14092bfd_boolean
b99bd4ef
NC
14093arm_fix_adjustable (fixP)
14094 fixS * fixP;
14095{
14096 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14097 return 1;
14098 return 0;
14099}
14100#endif
114424c6 14101
b99bd4ef
NC
14102#ifdef OBJ_ELF
14103/* Relocations against Thumb function names must be left unadjusted,
14104 so that the linker can use this information to correctly set the
14105 bottom bit of their addresses. The MIPS version of this function
14106 also prevents relocations that are mips-16 specific, but I do not
14107 know why it does this.
14108
14109 FIXME:
14110 There is one other problem that ought to be addressed here, but
14111 which currently is not: Taking the address of a label (rather
14112 than a function) and then later jumping to that address. Such
14113 addresses also ought to have their bottom bit set (assuming that
14114 they reside in Thumb code), but at the moment they will not. */
14115
b34976b6 14116bfd_boolean
b99bd4ef
NC
14117arm_fix_adjustable (fixP)
14118 fixS * fixP;
14119{
14120 if (fixP->fx_addsy == NULL)
14121 return 1;
14122
b99bd4ef
NC
14123 if (THUMB_IS_FUNC (fixP->fx_addsy)
14124 && fixP->fx_subsy == NULL)
14125 return 0;
14126
14127 /* We need the symbol name for the VTABLE entries. */
14128 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14129 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14130 return 0;
14131
a161fe53
AM
14132 /* Don't allow symbols to be discarded on GOT related relocs. */
14133 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14134 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14135 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14136 return 0;
14137
b99bd4ef
NC
14138 return 1;
14139}
14140
14141const char *
14142elf32_arm_target_format ()
14143{
14144 if (target_big_endian)
14145 {
14146 if (target_oabi)
14147 return "elf32-bigarm-oabi";
14148 else
14149 return "elf32-bigarm";
14150 }
14151 else
14152 {
14153 if (target_oabi)
14154 return "elf32-littlearm-oabi";
14155 else
14156 return "elf32-littlearm";
14157 }
14158}
14159
14160void
14161armelf_frob_symbol (symp, puntp)
14162 symbolS * symp;
14163 int * puntp;
14164{
14165 elf_frob_symbol (symp, puntp);
14166}
14167
b99bd4ef
NC
14168static bfd_reloc_code_real_type
14169arm_parse_reloc ()
14170{
14171 char id [16];
14172 char * ip;
14173 unsigned int i;
14174 static struct
14175 {
14176 char * str;
14177 int len;
14178 bfd_reloc_code_real_type reloc;
14179 }
14180 reloc_map[] =
14181 {
14182#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14183 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14184 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14185 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14186 branch instructions generated by GCC for PLT relocs. */
14187 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14188 { NULL, 0, BFD_RELOC_UNUSED }
14189#undef MAP
14190 };
14191
14192 for (i = 0, ip = input_line_pointer;
3882b010 14193 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14194 i++, ip++)
3882b010 14195 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14196
14197 for (i = 0; reloc_map[i].str; i++)
14198 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14199 break;
14200
14201 input_line_pointer += reloc_map[i].len;
14202
14203 return reloc_map[i].reloc;
14204}
14205
14206static void
14207s_arm_elf_cons (nbytes)
14208 int nbytes;
14209{
14210 expressionS exp;
14211
14212#ifdef md_flush_pending_output
14213 md_flush_pending_output ();
14214#endif
14215
14216 if (is_it_end_of_statement ())
14217 {
14218 demand_empty_rest_of_line ();
14219 return;
14220 }
14221
14222#ifdef md_cons_align
14223 md_cons_align (nbytes);
14224#endif
14225
6057a28f 14226 mapping_state (MAP_DATA);
b99bd4ef
NC
14227 do
14228 {
14229 bfd_reloc_code_real_type reloc;
14230
14231 expression (& exp);
14232
14233 if (exp.X_op == O_symbol
14234 && * input_line_pointer == '('
14235 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14236 {
14237 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14238 int size = bfd_get_reloc_size (howto);
14239
14240 if (size > nbytes)
14241 as_bad ("%s relocations do not fit in %d bytes",
14242 howto->name, nbytes);
14243 else
14244 {
14245 register char *p = frag_more ((int) nbytes);
14246 int offset = nbytes - size;
14247
14248 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14249 &exp, 0, reloc);
14250 }
14251 }
14252 else
14253 emit_expr (&exp, (unsigned int) nbytes);
14254 }
14255 while (*input_line_pointer++ == ',');
14256
14257 /* Put terminator back into stream. */
14258 input_line_pointer --;
14259 demand_empty_rest_of_line ();
14260}
14261
14262#endif /* OBJ_ELF */
14263
14264/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14265 of an rs_align_code fragment. */
14266
14267void
14268arm_handle_align (fragP)
14269 fragS *fragP;
14270{
14271 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14272 static char const thumb_noop[2] = { 0xc0, 0x46 };
14273 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14274 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14275
14276 int bytes, fix, noop_size;
14277 char * p;
14278 const char * noop;
cc8a6dd0 14279
b99bd4ef
NC
14280 if (fragP->fr_type != rs_align_code)
14281 return;
14282
14283 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14284 p = fragP->fr_literal + fragP->fr_fix;
14285 fix = 0;
cc8a6dd0 14286
b99bd4ef
NC
14287 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14288 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14289
b99bd4ef
NC
14290 if (fragP->tc_frag_data)
14291 {
14292 if (target_big_endian)
14293 noop = thumb_bigend_noop;
14294 else
14295 noop = thumb_noop;
14296 noop_size = sizeof (thumb_noop);
14297 }
14298 else
14299 {
14300 if (target_big_endian)
14301 noop = arm_bigend_noop;
14302 else
14303 noop = arm_noop;
14304 noop_size = sizeof (arm_noop);
14305 }
cc8a6dd0 14306
b99bd4ef
NC
14307 if (bytes & (noop_size - 1))
14308 {
14309 fix = bytes & (noop_size - 1);
14310 memset (p, 0, fix);
14311 p += fix;
14312 bytes -= fix;
14313 }
14314
14315 while (bytes >= noop_size)
14316 {
14317 memcpy (p, noop, noop_size);
14318 p += noop_size;
14319 bytes -= noop_size;
14320 fix += noop_size;
14321 }
cc8a6dd0 14322
b99bd4ef
NC
14323 fragP->fr_fix += fix;
14324 fragP->fr_var = noop_size;
14325}
14326
14327/* Called from md_do_align. Used to create an alignment
14328 frag in a code section. */
14329
14330void
14331arm_frag_align_code (n, max)
14332 int n;
14333 int max;
14334{
14335 char * p;
14336
2d2255b5 14337 /* We assume that there will never be a requirement
b99bd4ef
NC
14338 to support alignments greater than 32 bytes. */
14339 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14340 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14341
b99bd4ef
NC
14342 p = frag_var (rs_align_code,
14343 MAX_MEM_FOR_RS_ALIGN_CODE,
14344 1,
14345 (relax_substateT) max,
14346 (symbolS *) NULL,
14347 (offsetT) n,
14348 (char *) NULL);
14349 *p = 0;
14350
14351}
14352
14353/* Perform target specific initialisation of a frag. */
14354
14355void
14356arm_init_frag (fragP)
14357 fragS *fragP;
14358{
14359 /* Record whether this frag is in an ARM or a THUMB area. */
14360 fragP->tc_frag_data = thumb_mode;
14361}
This page took 1.14197 seconds and 4 git commands to generate.