* gas/arm/arm.exp: Add archv6 and thumbv6.
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
ae6063d4 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
b99bd4ef
NC
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
22d9c8c5 6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
b99bd4ef
NC
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA. */
24
b99bd4ef
NC
25#include <string.h>
26#define NO_RELOC 0
27#include "as.h"
3882b010 28#include "safe-ctype.h"
b99bd4ef
NC
29
30/* Need TARGET_CPU. */
31#include "config.h"
32#include "subsegs.h"
33#include "obstack.h"
34#include "symbols.h"
35#include "listing.h"
36
37#ifdef OBJ_ELF
38#include "elf/arm.h"
39#include "dwarf2dbg.h"
40#endif
41
03b1477f
RE
42/* XXX Set this to 1 after the next binutils release */
43#define WARN_DEPRECATED 0
44
b89dddec
RE
45/* The following bitmasks control CPU extensions: */
46#define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47#define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48#define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49#define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50#define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51#define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52#define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54#define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
ea6ef066 57#define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
09d92015 58#define ARM_EXT_V6 0x00001000 /* ARM V6. */
03b1477f
RE
59
60/* Co-processor space extensions. */
61#define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
62#define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
5a6c6817 63#define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
b89dddec
RE
64
65/* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
66 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
67 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
68 three more to cover cores prior to ARM6. Finally, there are cores which
69 implement further extensions in the co-processor space. */
70#define ARM_ARCH_V1 ARM_EXT_V1
71#define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
72#define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
73#define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
74#define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
75#define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
76#define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
77#define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
78#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
79#define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
80#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
81#define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
82#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
83#define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
84#define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
ea6ef066 85#define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
09d92015 86#define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
03b1477f 87
b89dddec 88/* Processors with specific extensions in the co-processor space. */
03b1477f 89#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
5a6c6817 90#define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
b99bd4ef
NC
91
92/* Some useful combinations: */
03b1477f
RE
93#define ARM_ANY 0x0000ffff /* Any basic core. */
94#define ARM_ALL 0x00ffffff /* Any core + co-processor */
95#define CPROC_ANY 0x00ff0000 /* Any co-processor */
96#define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97
b99bd4ef 98
bfae80f2
RE
99#define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
100#define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
101#define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
102#define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
103#define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
104#define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105#define FPU_NONE 0
b99bd4ef 106
b89dddec
RE
107#define FPU_ARCH_FPE FPU_FPA_EXT_V1
108#define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
109
bfae80f2
RE
110#define FPU_ARCH_VFP FPU_VFP_EXT_NONE
111#define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
112#define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
113#define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
114
b89dddec
RE
115/* Types of processor to assemble for. */
116#define ARM_1 ARM_ARCH_V1
117#define ARM_2 ARM_ARCH_V2
118#define ARM_3 ARM_ARCH_V2S
119#define ARM_250 ARM_ARCH_V2S
120#define ARM_6 ARM_ARCH_V3
121#define ARM_7 ARM_ARCH_V3
122#define ARM_8 ARM_ARCH_V4
123#define ARM_9 ARM_ARCH_V4T
124#define ARM_STRONG ARM_ARCH_V4
125#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
126
127#ifndef CPU_DEFAULT
128#if defined __XSCALE__
b89dddec 129#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
130#else
131#if defined __thumb__
b89dddec 132#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 133#else
03b1477f 134#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
135#endif
136#endif
137#endif
138
39c2da32
RE
139#ifdef TE_LINUX
140#define FPU_DEFAULT FPU_ARCH_FPA
141#endif
142
143#ifdef TE_NetBSD
144#ifdef OBJ_ELF
145#define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
146#else
147/* Legacy a.out format. */
148#define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
149#endif
150#endif
151
bfae80f2 152/* For backwards compatibility we default to the FPA. */
b99bd4ef 153#ifndef FPU_DEFAULT
b89dddec 154#define FPU_DEFAULT FPU_ARCH_FPA
b99bd4ef
NC
155#endif
156
157#define streq(a, b) (strcmp (a, b) == 0)
158#define skip_whitespace(str) while (*(str) == ' ') ++(str)
159
03b1477f 160static unsigned long cpu_variant;
b99bd4ef
NC
161static int target_oabi = 0;
162
b99bd4ef 163/* Flags stored in private area of BFD structure. */
b34976b6
AM
164static int uses_apcs_26 = FALSE;
165static int atpcs = FALSE;
166static int support_interwork = FALSE;
167static int uses_apcs_float = FALSE;
168static int pic_code = FALSE;
03b1477f
RE
169
170/* Variables that we set while parsing command-line options. Once all
171 options have been read we re-process these values to set the real
172 assembly flags. */
173static int legacy_cpu = -1;
174static int legacy_fpu = -1;
175
176static int mcpu_cpu_opt = -1;
177static int mcpu_fpu_opt = -1;
178static int march_cpu_opt = -1;
179static int march_fpu_opt = -1;
180static int mfpu_opt = -1;
b99bd4ef
NC
181
182/* This array holds the chars that always start a comment. If the
183 pre-processor is disabled, these aren't very useful. */
f57c81f6 184const char comment_chars[] = "@";
b99bd4ef
NC
185
186/* This array holds the chars that only start a comment at the beginning of
187 a line. If the line seems to have the form '# 123 filename'
188 .line and .file directives will appear in the pre-processed output. */
189/* Note that input_file.c hand checks for '#' at the beginning of the
190 first line of the input file. This is because the compiler outputs
191 #NO_APP at the beginning of its output. */
192/* Also note that comments like this one will always work. */
05d2d07e 193const char line_comment_chars[] = "#";
b99bd4ef 194
da89cce1 195const char line_separator_chars[] = ";";
b99bd4ef
NC
196
197/* Chars that can be used to separate mant
198 from exp in floating point numbers. */
05d2d07e 199const char EXP_CHARS[] = "eE";
b99bd4ef
NC
200
201/* Chars that mean this number is a floating point constant. */
202/* As in 0f12.456 */
203/* or 0d1.2345e12 */
204
05d2d07e 205const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
206
207/* Prefix characters that indicate the start of an immediate
208 value. */
209#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
210
211#ifdef OBJ_ELF
212/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
213symbolS * GOT_symbol;
214#endif
215
216/* Size of relocation record. */
05d2d07e 217const int md_reloc_size = 8;
b99bd4ef
NC
218
219/* 0: assemble for ARM,
220 1: assemble for Thumb,
221 2: assemble for Thumb even though target CPU does not support thumb
222 instructions. */
223static int thumb_mode = 0;
224
225typedef struct arm_fix
226{
227 int thumb_mode;
228} arm_fix_data;
229
230struct arm_it
231{
05d2d07e 232 const char * error;
b99bd4ef 233 unsigned long instruction;
b99bd4ef
NC
234 int size;
235 struct
236 {
237 bfd_reloc_code_real_type type;
238 expressionS exp;
239 int pc_rel;
240 } reloc;
241};
242
243struct arm_it inst;
244
245enum asm_shift_index
246{
247 SHIFT_LSL = 0,
248 SHIFT_LSR,
249 SHIFT_ASR,
250 SHIFT_ROR,
251 SHIFT_RRX
252};
253
254struct asm_shift_properties
255{
256 enum asm_shift_index index;
257 unsigned long bit_field;
258 unsigned int allows_0 : 1;
259 unsigned int allows_32 : 1;
260};
261
262static const struct asm_shift_properties shift_properties [] =
263{
264 { SHIFT_LSL, 0, 1, 0},
265 { SHIFT_LSR, 0x20, 0, 1},
266 { SHIFT_ASR, 0x40, 0, 1},
267 { SHIFT_ROR, 0x60, 0, 0},
268 { SHIFT_RRX, 0x60, 0, 0}
269};
270
271struct asm_shift_name
272{
273 const char * name;
274 const struct asm_shift_properties * properties;
275};
276
277static const struct asm_shift_name shift_names [] =
278{
279 { "asl", shift_properties + SHIFT_LSL },
280 { "lsl", shift_properties + SHIFT_LSL },
281 { "lsr", shift_properties + SHIFT_LSR },
282 { "asr", shift_properties + SHIFT_ASR },
283 { "ror", shift_properties + SHIFT_ROR },
284 { "rrx", shift_properties + SHIFT_RRX },
285 { "ASL", shift_properties + SHIFT_LSL },
286 { "LSL", shift_properties + SHIFT_LSL },
287 { "LSR", shift_properties + SHIFT_LSR },
288 { "ASR", shift_properties + SHIFT_ASR },
289 { "ROR", shift_properties + SHIFT_ROR },
290 { "RRX", shift_properties + SHIFT_RRX }
291};
292
09d92015 293/* Any kind of shift is accepted. */
b99bd4ef 294#define NO_SHIFT_RESTRICT 1
09d92015
MM
295/* The shift operand must be an immediate value, not a register. */
296#define SHIFT_IMMEDIATE 0
297/* The shift must be LSL or ASR and the operand must be an immediate. */
298#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
299/* The shift must be ASR and the operand must be an immediate. */
300#define SHIFT_ASR_IMMEDIATE 3
301/* The shift must be LSL and the operand must be an immediate. */
302#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
303
304#define NUM_FLOAT_VALS 8
305
05d2d07e 306const char * fp_const[] =
b99bd4ef
NC
307{
308 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
309};
310
311/* Number of littlenums required to hold an extended precision number. */
312#define MAX_LITTLENUMS 6
313
314LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
315
316#define FAIL (-1)
317#define SUCCESS (0)
318
bfae80f2
RE
319/* Whether a Co-processor load/store operation accepts write-back forms. */
320#define CP_WB_OK 1
321#define CP_NO_WB 0
322
b99bd4ef
NC
323#define SUFF_S 1
324#define SUFF_D 2
325#define SUFF_E 3
326#define SUFF_P 4
327
328#define CP_T_X 0x00008000
329#define CP_T_Y 0x00400000
330#define CP_T_Pre 0x01000000
331#define CP_T_UD 0x00800000
332#define CP_T_WB 0x00200000
333
334#define CONDS_BIT 0x00100000
335#define LOAD_BIT 0x00100000
b99bd4ef
NC
336
337#define DOUBLE_LOAD_FLAG 0x00000001
338
339struct asm_cond
340{
05d2d07e 341 const char * template;
b99bd4ef
NC
342 unsigned long value;
343};
344
b99bd4ef 345#define COND_ALWAYS 0xe0000000
90e4755a 346#define COND_MASK 0xf0000000
b99bd4ef 347
05d2d07e 348static const struct asm_cond conds[] =
b99bd4ef
NC
349{
350 {"eq", 0x00000000},
351 {"ne", 0x10000000},
352 {"cs", 0x20000000}, {"hs", 0x20000000},
353 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
354 {"mi", 0x40000000},
355 {"pl", 0x50000000},
356 {"vs", 0x60000000},
357 {"vc", 0x70000000},
358 {"hi", 0x80000000},
359 {"ls", 0x90000000},
360 {"ge", 0xa0000000},
361 {"lt", 0xb0000000},
362 {"gt", 0xc0000000},
363 {"le", 0xd0000000},
364 {"al", 0xe0000000},
365 {"nv", 0xf0000000}
366};
367
b99bd4ef
NC
368struct asm_psr
369{
b34976b6
AM
370 const char *template;
371 bfd_boolean cpsr;
b99bd4ef
NC
372 unsigned long field;
373};
374
2d2255b5 375/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
376#define SPSR_BIT (1 << 22)
377
378/* How many bits to shift the PSR_xxx bits up by. */
379#define PSR_SHIFT 16
380
381#define PSR_c (1 << 0)
382#define PSR_x (1 << 1)
383#define PSR_s (1 << 2)
384#define PSR_f (1 << 3)
385
05d2d07e 386static const struct asm_psr psrs[] =
b99bd4ef 387{
b34976b6
AM
388 {"CPSR", TRUE, PSR_c | PSR_f},
389 {"CPSR_all", TRUE, PSR_c | PSR_f},
390 {"SPSR", FALSE, PSR_c | PSR_f},
391 {"SPSR_all", FALSE, PSR_c | PSR_f},
392 {"CPSR_flg", TRUE, PSR_f},
393 {"CPSR_f", TRUE, PSR_f},
394 {"SPSR_flg", FALSE, PSR_f},
395 {"SPSR_f", FALSE, PSR_f},
396 {"CPSR_c", TRUE, PSR_c},
397 {"CPSR_ctl", TRUE, PSR_c},
398 {"SPSR_c", FALSE, PSR_c},
399 {"SPSR_ctl", FALSE, PSR_c},
400 {"CPSR_x", TRUE, PSR_x},
401 {"CPSR_s", TRUE, PSR_s},
402 {"SPSR_x", FALSE, PSR_x},
403 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 404 /* Combinations of flags. */
b34976b6
AM
405 {"CPSR_fs", TRUE, PSR_f | PSR_s},
406 {"CPSR_fx", TRUE, PSR_f | PSR_x},
407 {"CPSR_fc", TRUE, PSR_f | PSR_c},
408 {"CPSR_sf", TRUE, PSR_s | PSR_f},
409 {"CPSR_sx", TRUE, PSR_s | PSR_x},
410 {"CPSR_sc", TRUE, PSR_s | PSR_c},
411 {"CPSR_xf", TRUE, PSR_x | PSR_f},
412 {"CPSR_xs", TRUE, PSR_x | PSR_s},
413 {"CPSR_xc", TRUE, PSR_x | PSR_c},
414 {"CPSR_cf", TRUE, PSR_c | PSR_f},
415 {"CPSR_cs", TRUE, PSR_c | PSR_s},
416 {"CPSR_cx", TRUE, PSR_c | PSR_x},
417 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
418 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
419 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
420 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
421 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
422 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
423 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
424 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
425 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
426 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
427 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
428 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
429 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
430 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
431 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
432 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
433 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
434 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
435 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
436 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
437 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
438 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
439 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
440 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
441 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
442 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
443 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
444 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
445 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
446 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
447 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
448 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
449 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
450 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
451 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
452 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
453 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
454 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
455 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
456 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
457 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
458 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
459 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
460 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
461 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
462 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
463 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
464 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
465 {"SPSR_fs", FALSE, PSR_f | PSR_s},
466 {"SPSR_fx", FALSE, PSR_f | PSR_x},
467 {"SPSR_fc", FALSE, PSR_f | PSR_c},
468 {"SPSR_sf", FALSE, PSR_s | PSR_f},
469 {"SPSR_sx", FALSE, PSR_s | PSR_x},
470 {"SPSR_sc", FALSE, PSR_s | PSR_c},
471 {"SPSR_xf", FALSE, PSR_x | PSR_f},
472 {"SPSR_xs", FALSE, PSR_x | PSR_s},
473 {"SPSR_xc", FALSE, PSR_x | PSR_c},
474 {"SPSR_cf", FALSE, PSR_c | PSR_f},
475 {"SPSR_cs", FALSE, PSR_c | PSR_s},
476 {"SPSR_cx", FALSE, PSR_c | PSR_x},
477 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
478 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
479 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
480 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
481 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
482 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
483 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
484 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
485 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
486 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
487 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
488 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
489 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
490 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
491 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
492 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
493 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
494 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
495 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
496 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
497 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
498 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
499 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
500 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
501 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
502 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
503 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
504 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
505 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
506 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
507 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
508 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
509 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
510 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
511 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
512 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
513 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
514 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
515 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
516 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
517 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
518 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
519 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
520 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
521 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
522 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
523 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
524 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
525};
526
e16bb312
NC
527enum wreg_type
528 {
529 IWMMXT_REG_WR = 0,
530 IWMMXT_REG_WC = 1,
531 IWMMXT_REG_WR_OR_WC = 2,
532 IWMMXT_REG_WCG
533 };
534
535enum iwmmxt_insn_type
536{
537 check_rd,
538 check_wr,
539 check_wrwr,
540 check_wrwrwr,
541 check_wrwrwcg,
542 check_tbcst,
543 check_tmovmsk,
544 check_tmia,
545 check_tmcrr,
546 check_tmrrc,
547 check_tmcr,
548 check_tmrc,
549 check_tinsr,
550 check_textrc,
551 check_waligni,
552 check_textrm,
553 check_wshufh
554};
555
bfae80f2
RE
556enum vfp_dp_reg_pos
557{
558 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
559};
560
561enum vfp_sp_reg_pos
562{
563 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
564};
565
566enum vfp_ldstm_type
567{
568 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
569};
570
571/* VFP system registers. */
572struct vfp_reg
573{
574 const char *name;
575 unsigned long regno;
576};
577
cc8a6dd0 578static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
579{
580 {"fpsid", 0x00000000},
581 {"FPSID", 0x00000000},
582 {"fpscr", 0x00010000},
583 {"FPSCR", 0x00010000},
584 {"fpexc", 0x00080000},
585 {"FPEXC", 0x00080000}
586};
587
6c43fab6
RE
588/* Structure for a hash table entry for a register. */
589struct reg_entry
590{
591 const char * name;
592 int number;
0bbf2aa4 593 bfd_boolean builtin;
6c43fab6
RE
594};
595
e28cd48c 596/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
597#define REG_SP 13
598#define REG_LR 14
599#define REG_PC 15
600
e16bb312
NC
601#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
602#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
603#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
604
0bbf2aa4
NC
605/* These are the standard names. Users can add aliases with .req.
606 and delete them with .unreq. */
607
6c43fab6
RE
608/* Integer Register Numbers. */
609static const struct reg_entry rn_table[] =
610{
0bbf2aa4
NC
611 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
612 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
613 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
614 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 615 /* ATPCS Synonyms. */
0bbf2aa4
NC
616 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
617 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
618 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 619 /* Well-known aliases. */
0bbf2aa4
NC
620 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
621 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
622 {NULL, 0, TRUE}
6c43fab6
RE
623};
624
e16bb312
NC
625#define WR_PREFIX 0x200
626#define WC_PREFIX 0x400
627
628static const struct reg_entry iwmmxt_table[] =
629{
5a6c6817 630 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
631 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
632 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
633 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
634 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
635 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
636 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
637 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
638 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
639 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
640 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
641 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
642 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
643
644 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
645 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
646 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
647 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
648 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
649 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
650 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
651 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
652 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
653 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
654 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
655 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
656 {NULL, 0, TRUE}
e16bb312
NC
657};
658
6c43fab6
RE
659/* Co-processor Numbers. */
660static const struct reg_entry cp_table[] =
661{
0bbf2aa4
NC
662 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
663 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
664 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
665 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
666 {NULL, 0, TRUE}
6c43fab6
RE
667};
668
669/* Co-processor Register Numbers. */
670static const struct reg_entry cn_table[] =
671{
0bbf2aa4
NC
672 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
673 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
674 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
675 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 676 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
677 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
678 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
679 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
680 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
681 {NULL, 0, TRUE}
6c43fab6
RE
682};
683
684/* FPA Registers. */
685static const struct reg_entry fn_table[] =
686{
0bbf2aa4
NC
687 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
688 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
689 {NULL, 0, TRUE}
6c43fab6
RE
690};
691
bfae80f2
RE
692/* VFP SP Registers. */
693static const struct reg_entry sn_table[] =
694{
0bbf2aa4
NC
695 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
696 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
697 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
698 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
699 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
700 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
701 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
702 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
703 {NULL, 0, TRUE}
bfae80f2
RE
704};
705
706/* VFP DP Registers. */
707static const struct reg_entry dn_table[] =
708{
0bbf2aa4
NC
709 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
710 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
711 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
712 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
713 {NULL, 0, TRUE}
bfae80f2
RE
714};
715
63e63b07 716/* Maverick DSP coprocessor registers. */
6c43fab6
RE
717static const struct reg_entry mav_mvf_table[] =
718{
0bbf2aa4
NC
719 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
720 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
721 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
722 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
723 {NULL, 0, TRUE}
6c43fab6
RE
724};
725
726static const struct reg_entry mav_mvd_table[] =
727{
0bbf2aa4
NC
728 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
729 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
730 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
731 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
732 {NULL, 0, TRUE}
6c43fab6
RE
733};
734
735static const struct reg_entry mav_mvfx_table[] =
736{
0bbf2aa4
NC
737 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
738 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
739 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
740 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
741 {NULL, 0, TRUE}
6c43fab6
RE
742};
743
744static const struct reg_entry mav_mvdx_table[] =
745{
0bbf2aa4
NC
746 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
747 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
748 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
749 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
750 {NULL, 0, TRUE}
6c43fab6
RE
751};
752
753static const struct reg_entry mav_mvax_table[] =
754{
0bbf2aa4
NC
755 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
756 {NULL, 0, TRUE}
6c43fab6
RE
757};
758
759static const struct reg_entry mav_dspsc_table[] =
760{
0bbf2aa4
NC
761 {"dspsc", 0, TRUE},
762 {NULL, 0, TRUE}
6c43fab6
RE
763};
764
765struct reg_map
766{
767 const struct reg_entry *names;
768 int max_regno;
769 struct hash_control *htab;
770 const char *expected;
771};
772
773struct reg_map all_reg_maps[] =
774{
775 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
776 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
777 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 778 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
779 {sn_table, 31, NULL, N_("VFP single precision register expected")},
780 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
781 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
782 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
783 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 784 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
785 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
786 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 787 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
788};
789
790/* Enumeration matching entries in table above. */
791enum arm_reg_type
792{
793 REG_TYPE_RN = 0,
794#define REG_TYPE_FIRST REG_TYPE_RN
795 REG_TYPE_CP = 1,
796 REG_TYPE_CN = 2,
797 REG_TYPE_FN = 3,
bfae80f2
RE
798 REG_TYPE_SN = 4,
799 REG_TYPE_DN = 5,
800 REG_TYPE_MVF = 6,
801 REG_TYPE_MVD = 7,
802 REG_TYPE_MVFX = 8,
803 REG_TYPE_MVDX = 9,
804 REG_TYPE_MVAX = 10,
805 REG_TYPE_DSPSC = 11,
e16bb312 806 REG_TYPE_IWMMXT = 12,
bfae80f2 807
e16bb312 808 REG_TYPE_MAX = 13
6c43fab6 809};
404ff6b5 810
b99bd4ef
NC
811/* Functions called by parser. */
812/* ARM instructions. */
f2b7cb0a
RE
813static void do_arit PARAMS ((char *));
814static void do_cmp PARAMS ((char *));
815static void do_mov PARAMS ((char *));
816static void do_ldst PARAMS ((char *));
817static void do_ldstt PARAMS ((char *));
818static void do_ldmstm PARAMS ((char *));
819static void do_branch PARAMS ((char *));
820static void do_swi PARAMS ((char *));
c9b604bd 821
b99bd4ef 822/* Pseudo Op codes. */
f2b7cb0a
RE
823static void do_adr PARAMS ((char *));
824static void do_adrl PARAMS ((char *));
825static void do_empty PARAMS ((char *));
c9b604bd
RE
826
827/* ARM v2. */
f2b7cb0a
RE
828static void do_mul PARAMS ((char *));
829static void do_mla PARAMS ((char *));
c9b604bd
RE
830
831/* ARM v2S. */
f2b7cb0a 832static void do_swap PARAMS ((char *));
c9b604bd
RE
833
834/* ARM v3. */
f2b7cb0a
RE
835static void do_msr PARAMS ((char *));
836static void do_mrs PARAMS ((char *));
c9b604bd
RE
837
838/* ARM v3M. */
f2b7cb0a 839static void do_mull PARAMS ((char *));
b99bd4ef 840
90e4755a 841/* ARM v4. */
f2b7cb0a 842static void do_ldstv4 PARAMS ((char *));
90e4755a 843
c9b604bd 844/* ARM v4T. */
f2b7cb0a 845static void do_bx PARAMS ((char *));
b99bd4ef 846
ea6ef066 847/* ARM v5T. */
f2b7cb0a
RE
848static void do_blx PARAMS ((char *));
849static void do_bkpt PARAMS ((char *));
850static void do_clz PARAMS ((char *));
851static void do_lstc2 PARAMS ((char *));
852static void do_cdp2 PARAMS ((char *));
853static void do_co_reg2 PARAMS ((char *));
b99bd4ef 854
ea6ef066 855/* ARM v5TExP. */
f2b7cb0a
RE
856static void do_smla PARAMS ((char *));
857static void do_smlal PARAMS ((char *));
858static void do_smul PARAMS ((char *));
859static void do_qadd PARAMS ((char *));
c9b604bd 860
ea6ef066 861/* ARM v5TE. */
f2b7cb0a
RE
862static void do_pld PARAMS ((char *));
863static void do_ldrd PARAMS ((char *));
864static void do_co_reg2c PARAMS ((char *));
b99bd4ef 865
ea6ef066
RE
866/* ARM v5TEJ. */
867static void do_bxj PARAMS ((char *));
868
09d92015
MM
869/* ARM V6. */
870static void do_cps PARAMS ((char *));
871static void do_cpsi PARAMS ((char *));
872static void do_ldrex PARAMS ((char *));
873static void do_pkhbt PARAMS ((char *));
874static void do_pkhtb PARAMS ((char *));
875static void do_qadd16 PARAMS ((char *));
876static void do_rev PARAMS ((char *));
877static void do_rfe PARAMS ((char *));
878static void do_sxtah PARAMS ((char *));
879static void do_sxth PARAMS ((char *));
880static void do_setend PARAMS ((char *));
881static void do_smlad PARAMS ((char *));
882static void do_smlald PARAMS ((char *));
883static void do_smmul PARAMS ((char *));
884static void do_ssat PARAMS ((char *));
885static void do_usat PARAMS ((char *));
886static void do_srs PARAMS ((char *));
887static void do_ssat16 PARAMS ((char *));
888static void do_usat16 PARAMS ((char *));
889static void do_strex PARAMS ((char *));
890static void do_umaal PARAMS ((char *));
891
892static void do_cps_mode PARAMS ((char **));
893static void do_cps_flags PARAMS ((char **, int));
894static int do_endian_specifier PARAMS ((char *));
895static void do_pkh_core PARAMS ((char *, int));
896static void do_sat PARAMS ((char **, int));
897static void do_sat16 PARAMS ((char **, int));
898
b99bd4ef 899/* Coprocessor Instructions. */
f2b7cb0a
RE
900static void do_cdp PARAMS ((char *));
901static void do_lstc PARAMS ((char *));
902static void do_co_reg PARAMS ((char *));
c9b604bd
RE
903
904/* FPA instructions. */
f2b7cb0a
RE
905static void do_fpa_ctrl PARAMS ((char *));
906static void do_fpa_ldst PARAMS ((char *));
907static void do_fpa_ldmstm PARAMS ((char *));
908static void do_fpa_dyadic PARAMS ((char *));
909static void do_fpa_monadic PARAMS ((char *));
910static void do_fpa_cmp PARAMS ((char *));
911static void do_fpa_from_reg PARAMS ((char *));
912static void do_fpa_to_reg PARAMS ((char *));
c9b604bd 913
bfae80f2
RE
914/* VFP instructions. */
915static void do_vfp_sp_monadic PARAMS ((char *));
916static void do_vfp_dp_monadic PARAMS ((char *));
917static void do_vfp_sp_dyadic PARAMS ((char *));
918static void do_vfp_dp_dyadic PARAMS ((char *));
919static void do_vfp_reg_from_sp PARAMS ((char *));
920static void do_vfp_sp_from_reg PARAMS ((char *));
921static void do_vfp_sp_reg2 PARAMS ((char *));
922static void do_vfp_reg_from_dp PARAMS ((char *));
923static void do_vfp_reg2_from_dp PARAMS ((char *));
924static void do_vfp_dp_from_reg PARAMS ((char *));
925static void do_vfp_dp_from_reg2 PARAMS ((char *));
926static void do_vfp_reg_from_ctrl PARAMS ((char *));
927static void do_vfp_ctrl_from_reg PARAMS ((char *));
928static void do_vfp_sp_ldst PARAMS ((char *));
929static void do_vfp_dp_ldst PARAMS ((char *));
930static void do_vfp_sp_ldstmia PARAMS ((char *));
931static void do_vfp_sp_ldstmdb PARAMS ((char *));
932static void do_vfp_dp_ldstmia PARAMS ((char *));
933static void do_vfp_dp_ldstmdb PARAMS ((char *));
934static void do_vfp_xp_ldstmia PARAMS ((char *));
935static void do_vfp_xp_ldstmdb PARAMS ((char *));
936static void do_vfp_sp_compare_z PARAMS ((char *));
937static void do_vfp_dp_compare_z PARAMS ((char *));
938static void do_vfp_dp_sp_cvt PARAMS ((char *));
939static void do_vfp_sp_dp_cvt PARAMS ((char *));
940
c9b604bd 941/* XScale. */
63e63b07
RE
942static void do_xsc_mia PARAMS ((char *));
943static void do_xsc_mar PARAMS ((char *));
944static void do_xsc_mra PARAMS ((char *));
f2b7cb0a
RE
945
946/* Maverick. */
63e63b07 947static void do_mav_binops PARAMS ((char *, int, enum arm_reg_type,
6c43fab6 948 enum arm_reg_type));
63e63b07
RE
949static void do_mav_binops_1a PARAMS ((char *));
950static void do_mav_binops_1b PARAMS ((char *));
951static void do_mav_binops_1c PARAMS ((char *));
952static void do_mav_binops_1d PARAMS ((char *));
953static void do_mav_binops_1e PARAMS ((char *));
954static void do_mav_binops_1f PARAMS ((char *));
955static void do_mav_binops_1g PARAMS ((char *));
956static void do_mav_binops_1h PARAMS ((char *));
957static void do_mav_binops_1i PARAMS ((char *));
958static void do_mav_binops_1j PARAMS ((char *));
959static void do_mav_binops_1k PARAMS ((char *));
960static void do_mav_binops_1l PARAMS ((char *));
961static void do_mav_binops_1m PARAMS ((char *));
962static void do_mav_binops_1n PARAMS ((char *));
963static void do_mav_binops_1o PARAMS ((char *));
964static void do_mav_binops_2a PARAMS ((char *));
965static void do_mav_binops_2b PARAMS ((char *));
966static void do_mav_binops_2c PARAMS ((char *));
967static void do_mav_binops_3a PARAMS ((char *));
968static void do_mav_binops_3b PARAMS ((char *));
969static void do_mav_binops_3c PARAMS ((char *));
970static void do_mav_binops_3d PARAMS ((char *));
cc8a6dd0 971static void do_mav_triple PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
972 enum arm_reg_type,
973 enum arm_reg_type));
63e63b07
RE
974static void do_mav_triple_4a PARAMS ((char *));
975static void do_mav_triple_4b PARAMS ((char *));
976static void do_mav_triple_5a PARAMS ((char *));
977static void do_mav_triple_5b PARAMS ((char *));
978static void do_mav_triple_5c PARAMS ((char *));
979static void do_mav_triple_5d PARAMS ((char *));
980static void do_mav_triple_5e PARAMS ((char *));
981static void do_mav_triple_5f PARAMS ((char *));
982static void do_mav_triple_5g PARAMS ((char *));
983static void do_mav_triple_5h PARAMS ((char *));
cc8a6dd0 984static void do_mav_quad PARAMS ((char *, int, enum arm_reg_type,
6c43fab6
RE
985 enum arm_reg_type,
986 enum arm_reg_type,
987 enum arm_reg_type));
63e63b07
RE
988static void do_mav_quad_6a PARAMS ((char *));
989static void do_mav_quad_6b PARAMS ((char *));
990static void do_mav_dspsc_1 PARAMS ((char *));
991static void do_mav_dspsc_2 PARAMS ((char *));
992static void do_mav_shift PARAMS ((char *, enum arm_reg_type,
6c43fab6 993 enum arm_reg_type));
63e63b07
RE
994static void do_mav_shift_1 PARAMS ((char *));
995static void do_mav_shift_2 PARAMS ((char *));
996static void do_mav_ldst PARAMS ((char *, enum arm_reg_type));
997static void do_mav_ldst_1 PARAMS ((char *));
998static void do_mav_ldst_2 PARAMS ((char *));
999static void do_mav_ldst_3 PARAMS ((char *));
1000static void do_mav_ldst_4 PARAMS ((char *));
1001
1002static int mav_reg_required_here PARAMS ((char **, int,
6c43fab6 1003 enum arm_reg_type));
63e63b07 1004static int mav_parse_offset PARAMS ((char **, int *));
404ff6b5 1005
90e4755a
RE
1006static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *,
1007 int, int));
6c43fab6
RE
1008static int arm_reg_parse PARAMS ((char **, struct hash_control *));
1009static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
05d2d07e 1010static const struct asm_psr * arm_psr_parse PARAMS ((char **));
90e4755a
RE
1011static void symbol_locate PARAMS ((symbolS *, const char *, segT, valueT,
1012 fragS *));
b99bd4ef
NC
1013static int add_to_lit_pool PARAMS ((void));
1014static unsigned validate_immediate PARAMS ((unsigned));
90e4755a
RE
1015static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1016 unsigned int *));
b99bd4ef
NC
1017static int validate_offset_imm PARAMS ((unsigned int, int));
1018static void opcode_select PARAMS ((int));
1019static void end_of_line PARAMS ((char *));
1020static int reg_required_here PARAMS ((char **, int));
1021static int psr_required_here PARAMS ((char **));
1022static int co_proc_number PARAMS ((char **));
1023static int cp_opc_expr PARAMS ((char **, int, int));
1024static int cp_reg_required_here PARAMS ((char **, int));
1025static int fp_reg_required_here PARAMS ((char **, int));
bfae80f2
RE
1026static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1027static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1028static void vfp_sp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1029static void vfp_dp_ldstm PARAMS ((char *, enum vfp_ldstm_type));
1030static long vfp_sp_reg_list PARAMS ((char **, enum vfp_sp_reg_pos));
1031static long vfp_dp_reg_list PARAMS ((char **));
1032static int vfp_psr_required_here PARAMS ((char **str));
1033static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
b99bd4ef 1034static int cp_address_offset PARAMS ((char **));
bfae80f2 1035static int cp_address_required_here PARAMS ((char **, int));
b99bd4ef
NC
1036static int my_get_float_expression PARAMS ((char **));
1037static int skip_past_comma PARAMS ((char **));
1038static int walk_no_bignums PARAMS ((symbolS *));
1039static int negate_data_op PARAMS ((unsigned long *, unsigned long));
1040static int data_op2 PARAMS ((char **));
1041static int fp_op2 PARAMS ((char **));
1042static long reg_list PARAMS ((char **));
1043static void thumb_load_store PARAMS ((char *, int, int));
1044static int decode_shift PARAMS ((char **, int));
90e4755a
RE
1045static int ldst_extend PARAMS ((char **));
1046static int ldst_extend_v4 PARAMS ((char **));
b99bd4ef 1047static void thumb_add_sub PARAMS ((char *, int));
6c43fab6
RE
1048static void insert_reg PARAMS ((const struct reg_entry *,
1049 struct hash_control *));
b99bd4ef
NC
1050static void thumb_shift PARAMS ((char *, int));
1051static void thumb_mov_compare PARAMS ((char *, int));
f2b7cb0a 1052static void build_arm_ops_hsh PARAMS ((void));
b99bd4ef
NC
1053static void set_constant_flonums PARAMS ((void));
1054static valueT md_chars_to_number PARAMS ((char *, int));
6c43fab6
RE
1055static void build_reg_hsh PARAMS ((struct reg_map *));
1056static void insert_reg_alias PARAMS ((char *, int, struct hash_control *));
1057static int create_register_alias PARAMS ((char *, char *));
f03698e6 1058static void output_inst PARAMS ((const char *));
2c20dfb2
NC
1059static int accum0_required_here PARAMS ((char **));
1060static int ld_mode_required_here PARAMS ((char **));
f2b7cb0a 1061static void do_branch25 PARAMS ((char *));
2c20dfb2 1062static symbolS * find_real_start PARAMS ((symbolS *));
b99bd4ef
NC
1063#ifdef OBJ_ELF
1064static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1065#endif
1066
e16bb312
NC
1067static int wreg_required_here PARAMS ((char **, int, enum wreg_type));
1068static void do_iwmmxt_byte_addr PARAMS ((char *));
1069static void do_iwmmxt_tandc PARAMS ((char *));
1070static void do_iwmmxt_tbcst PARAMS ((char *));
1071static void do_iwmmxt_textrc PARAMS ((char *));
1072static void do_iwmmxt_textrm PARAMS ((char *));
1073static void do_iwmmxt_tinsr PARAMS ((char *));
1074static void do_iwmmxt_tmcr PARAMS ((char *));
1075static void do_iwmmxt_tmcrr PARAMS ((char *));
1076static void do_iwmmxt_tmia PARAMS ((char *));
1077static void do_iwmmxt_tmovmsk PARAMS ((char *));
1078static void do_iwmmxt_tmrc PARAMS ((char *));
1079static void do_iwmmxt_tmrrc PARAMS ((char *));
1080static void do_iwmmxt_torc PARAMS ((char *));
1081static void do_iwmmxt_waligni PARAMS ((char *));
1082static void do_iwmmxt_wmov PARAMS ((char *));
1083static void do_iwmmxt_word_addr PARAMS ((char *));
1084static void do_iwmmxt_wrwr PARAMS ((char *));
1085static void do_iwmmxt_wrwrwcg PARAMS ((char *));
1086static void do_iwmmxt_wrwrwr PARAMS ((char *));
1087static void do_iwmmxt_wshufh PARAMS ((char *));
1088static void do_iwmmxt_wzero PARAMS ((char *));
1089static int cp_byte_address_offset PARAMS ((char **));
1090static int cp_byte_address_required_here PARAMS ((char **));
1091
b99bd4ef
NC
1092/* ARM instructions take 4bytes in the object file, Thumb instructions
1093 take 2: */
1094#define INSN_SIZE 4
1095
404ff6b5 1096/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 1097#define MAV_MODE1 0x100c
404ff6b5
AH
1098
1099/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 1100#define MAV_MODE2 0x0c10
404ff6b5
AH
1101
1102/* "INSN<cond> X,Y" where X:0, Y:bit16. */
63e63b07 1103#define MAV_MODE3 0x1000
404ff6b5
AH
1104
1105/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 1106#define MAV_MODE4 0x0c0010
404ff6b5
AH
1107
1108/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 1109#define MAV_MODE5 0x00100c
404ff6b5
AH
1110
1111/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 1112#define MAV_MODE6 0x00100c05
b99bd4ef
NC
1113
1114struct asm_opcode
1115{
1116 /* Basic string to match. */
05d2d07e 1117 const char * template;
b99bd4ef
NC
1118
1119 /* Basic instruction code. */
1120 unsigned long value;
1121
90e4755a
RE
1122 /* Offset into the template where the condition code (if any) will be.
1123 If zero, then the instruction is never conditional. */
1124 unsigned cond_offset;
b99bd4ef 1125
90e4755a
RE
1126 /* Which architecture variant provides this instruction. */
1127 unsigned long variant;
b99bd4ef
NC
1128
1129 /* Function to call to parse args. */
f2b7cb0a 1130 void (* parms) PARAMS ((char *));
b99bd4ef
NC
1131};
1132
05d2d07e 1133static const struct asm_opcode insns[] =
b99bd4ef 1134{
c9b604bd 1135 /* Core ARM Instructions. */
90e4755a
RE
1136 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
1137 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
1138 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
1139 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
1140 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
1141 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
1142 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
1143 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
1144 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
1145 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
1146 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
1147 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
1148 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
1149 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
1150 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
1151 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
1152 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
1153 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
1154 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
1155 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
1156
1157 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1158 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
1159 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
1160 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1161 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
1162 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
1163 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1164 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
1165 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
1166 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1167 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
1168 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
1169
1170 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
1171 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
1172 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
1173 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
1174
1175 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
1176 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
1177 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
1178 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
1179 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
1180 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
1181 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
1182 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
1183
1184 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1185 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1186 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1187 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1188 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
1189 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
1190 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
1191 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
1192
1193 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1194 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1195 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1196 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1197 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
1198 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
1199 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
1200 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
1201
1202 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
b99bd4ef 1203#ifdef TE_WINCE
c9b604bd 1204 /* XXX This is the wrong place to do this. Think multi-arch. */
90e4755a
RE
1205 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
1206 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
b99bd4ef 1207#else
90e4755a
RE
1208 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
1209 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
b99bd4ef
NC
1210#endif
1211
c9b604bd 1212 /* Pseudo ops. */
90e4755a
RE
1213 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
1214 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
1215 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_empty},
b99bd4ef 1216
c9b604bd 1217 /* ARM 2 multiplies. */
90e4755a
RE
1218 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
1219 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
1220 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
1221 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 1222
67c1ffbe 1223 /* Generic coprocessor instructions. */
90e4755a
RE
1224 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
1225 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
1226 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
1227 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
1228 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
1229 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
1230 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
c9b604bd
RE
1231
1232 /* ARM 3 - swp instructions. */
90e4755a
RE
1233 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
1234 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 1235
c9b604bd 1236 /* ARM 6 Status register instructions. */
90e4755a
RE
1237 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
1238 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
1239 /* ScottB: our code uses 0xe128f000 for msr.
c9b604bd 1240 NickC: but this is wrong because the bits 16 through 19 are
90e4755a 1241 handled by the PSR_xxx defines above. */
b99bd4ef 1242
f2b7cb0a 1243 /* ARM 7M long multiplies. */
90e4755a
RE
1244 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
1245 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
1246 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
1247 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
1248 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
1249 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
1250 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
1251 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
1252
1253 /* ARM Architecture 4. */
1254 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
1255 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
1256 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
1257 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 1258
c9b604bd 1259 /* ARM Architecture 4T. */
cc8a6dd0 1260 /* Note: bx (and blx) are required on V5, even if the processor does
90e4755a
RE
1261 not support Thumb. */
1262 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1263
ea6ef066 1264 /* ARM Architecture 5T. */
90e4755a
RE
1265 /* Note: blx has 2 variants, so the .value is set dynamically.
1266 Only one of the variants has conditional execution. */
1267 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
1268 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
1269 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
1270 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
1271 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
1272 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
1273 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
1274 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
1275 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
1276 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
1277
ea6ef066 1278 /* ARM Architecture 5TExP. */
90e4755a
RE
1279 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
1280 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
1281 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
1282 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
1283
1284 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
1285 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
1286
1287 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
1288 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
1289 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
1290 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
1291
1292 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
1293 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
1294 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
1295 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
1296
1297 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
1298 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
1299
1300 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
1301 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
1302 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
1303 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
c9b604bd 1304
ea6ef066 1305 /* ARM Architecture 5TE. */
90e4755a
RE
1306 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
1307 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
1308 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
1309
1310 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
1311 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
404ff6b5 1312
ea6ef066
RE
1313 /* ARM Architecture 5TEJ. */
1314 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
1315
09d92015
MM
1316 /* ARM V6. */
1317 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
1318 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
1319 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
1320 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
1321 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
1322 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
1323 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
1324 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
1325 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
1326 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
1327 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
1328 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
1329 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
1330 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
1331 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
1332 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
1333 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
1334 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
1335 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
1336 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
1337 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
1338 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
1339 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
1340 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
1341 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
1342 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
1343 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
1344 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
1345 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
1346 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
1347 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
1348 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
1349 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
1350 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
1351 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
1352 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
1353 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
1354 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
1355 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
1356 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
1357 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
1358 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
1359 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
1360 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
1361 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
1362 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
1363 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
1364 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1365 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1366 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1367 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1368 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
1369 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
1370 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
1371 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
1372 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
1373 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
1374 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
1375 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
1376 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
1377 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
1378 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
1379 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
1380 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
1381 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
1382 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
1383 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
1384 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
1385 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
1386 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
1387 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
1388 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
1389 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
1390 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
1391 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
1392 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
1393 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
1394 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
1395 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
1396 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
1397 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
1398 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
1399 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
1400 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
1401 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
1402 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
1403 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
1404 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
1405 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
1406 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
1407 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
1408 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
1409 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
1410 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
1411 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
1412 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
1413 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
1414 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
1415 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
1416
c9b604bd 1417 /* Core FPA instruction set (V1). */
90e4755a
RE
1418 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1419 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1420 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1421 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
1422
1423 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1424 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1425 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1426 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1427
1428 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1429 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1430 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1431 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
1432
1433 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1434 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1435 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1436 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1437 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1438 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1439 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1440 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1441 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1442 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1443 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1444 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1445
1446 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1447 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1448 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1449 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1450 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1451 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1452 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1453 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1454 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1455 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1456 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1457 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1458
1459 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1460 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1461 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1462 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1463 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1464 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1465 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1466 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1467 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1468 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1469 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1470 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1471
1472 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1473 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1474 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1475 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1476 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1477 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1478 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1479 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1480 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1481 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1482 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1483 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1484
1485 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1486 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1487 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1488 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1489 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1490 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1491 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1492 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1493 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1494 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1495 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1496 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1497
1498 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1499 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1500 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1501 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1502 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1503 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1504 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1505 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1506 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1507 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1508 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1509 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1510
1511 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1512 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1513 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1514 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1515 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1516 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1517 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1518 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1519 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1520 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1521 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1522 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1523
1524 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1525 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1526 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1527 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1528 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1529 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1530 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1531 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1532 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1533 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1534 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1535 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1536
1537 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1538 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1539 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1540 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1541 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1542 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1543 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1544 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1545 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1546 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1547 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1548 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1549
1550 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1551 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1552 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1553 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1554 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1555 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1556 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1557 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1558 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1559 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1560 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1561 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1562
1563 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1564 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1565 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1566 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1567 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1568 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1569 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1570 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1571 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1572 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1573 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1574 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1575
1576 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1577 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1578 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1579 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1580 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1581 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1582 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1583 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1584 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1585 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1586 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1587 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1588
1589 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1590 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1591 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1592 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1593 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1594 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1595 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1596 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1597 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1598 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1599 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1600 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1601
1602 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1603 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1604 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1605 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1606 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1607 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1608 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1609 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1610 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1611 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1612 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1613 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1614
1615 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1616 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1617 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1618 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1619 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1620 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1621 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1622 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1623 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1624 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1625 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1626 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1627
1628 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1629 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1630 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1631 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1632 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1633 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1634 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1635 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1636 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1637 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1638 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1639 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
1640
1641 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1642 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1643 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1644 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1645 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1646 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1647 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1648 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1649 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1650 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1651 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1652 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1653
1654 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1655 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1656 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1657 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1658 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1659 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1660 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1661 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1662 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1663 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1664 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1665 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1666
1667 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1668 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1669 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1670 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1671 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1672 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1673 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1674 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1675 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1676 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1677 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1678 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1679
1680 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1681 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1682 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1683 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1684 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1685 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1686 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1687 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1688 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1689 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1690 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1691 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1692
1693 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1694 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1695 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1696 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1697 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1698 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1699 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1700 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1701 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1702 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1703 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1704 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1705
1706 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1707 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1708 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1709 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1710 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1711 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1712 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1713 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1714 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1715 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1716 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1717 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1718
1719 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1720 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1721 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1722 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1723 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1724 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1725 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1726 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1727 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1728 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1729 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1730 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1731
1732 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1733 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1734 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1735 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1736 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1737 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1738 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1739 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1740 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1741 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1742 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1743 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1744
1745 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1746 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1747 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1748 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1749 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1750 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1751 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1752 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1753 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1754 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1755 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1756 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1757
1758 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1759 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1760 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1761 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1762 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1763 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1764 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1765 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1766 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1767 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1768 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1769 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1770
1771 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1772 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1773 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1774 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1775 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1776 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1777 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1778 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1779 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1780 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1781 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1782 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1783
1784 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1785 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1786 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1787 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1788 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1789 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1790 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1791 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1792 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1793 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1794 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1795 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1796
1797 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1798 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1799 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1800 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1801 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1802 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1803 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1804 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1805 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1806 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1807 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1808 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
1809
1810 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1811 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1812 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1813 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
1814 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1815 not be an optional suffix, but part of the instruction. To be
1816 compatible, we accept either. */
1817 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1818 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
1819
1820 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1821 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1822 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1823 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1824 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1825 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1826 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1827 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1828 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1829 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1830 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1831 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
1832
1833 /* The implementation of the FIX instruction is broken on some
1834 assemblers, in that it accepts a precision specifier as well as a
1835 rounding specifier, despite the fact that this is meaningless.
1836 To be more compatible, we accept it as well, though of course it
1837 does not set any bits. */
1838 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1839 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1840 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1841 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1842 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1843 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1844 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1845 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1846 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1847 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1848 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1849 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
1850 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
c9b604bd
RE
1851
1852 /* Instructions that were new with the real FPA, call them V2. */
90e4755a
RE
1853 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1854 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1855 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1856 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1857 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
1858 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
c9b604bd 1859
bfae80f2
RE
1860 /* VFP V1xD (single precision). */
1861 /* Moves and type conversions. */
1862 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1863 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1864 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1865 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1866 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1867 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1868 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1869 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1870 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1871 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1872 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1873 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1874
1875 /* Memory operations. */
1876 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1877 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1878 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1879 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1880 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1881 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1882 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1883 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1884 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1885 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1886 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1887 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1888 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1889 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1890 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1891 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1892 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1893 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1894
1895 /* Monadic operations. */
1896 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1897 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1898 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1899
1900 /* Dyadic operations. */
1901 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1902 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1903 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1904 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1905 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1906 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1907 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1908 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1909 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1910
1911 /* Comparisons. */
1912 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1914 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1915 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1916
1917 /* VFP V1 (Double precision). */
1918 /* Moves and type conversions. */
1919 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1920 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1921 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1922 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1923 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
1924 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1925 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
1926 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1927 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
1928 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1929 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1930 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1931 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
1932
1933 /* Memory operations. */
1934 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1935 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
1936 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1937 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1938 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1939 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1940 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1941 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
1942 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1943 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
1944
1945 /* Monadic operations. */
1946 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1947 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1948 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1949
1950 /* Dyadic operations. */
1951 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1952 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1953 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1954 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1955 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1956 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1957 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1958 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1959 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
1960
1961 /* Comparisons. */
1962 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1963 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1964 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
1965 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
1966
1967 /* VFP V2. */
1968 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1969 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2},
1970 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
1971 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
1972
c9b604bd 1973 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
63e63b07
RE
1974 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
1975 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1976 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1977 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1978 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1979 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
1980 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
1981 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
1982
5a6c6817
NC
1983 /* Intel Wireless MMX technology instructions. */
1984 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1985 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1986 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1987 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1988 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1989 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1990 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1991 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1992 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1993 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1994 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1995 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1996 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1997 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1998 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1999 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2000 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2001 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2002 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2003 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2004 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2005 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2006 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2007 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2008 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2009 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2010 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2011 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2012 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2013 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2014 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2015 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2016 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2017 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2018 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2019 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2020 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2021 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2022 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2023 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2024 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2025 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2026 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2027 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2028 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2029 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2030 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2031 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2032 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2033 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2034 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2035 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2045 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2051 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2052 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2053 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2054 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2065 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2066 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2067 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2068 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2073 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2086 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2087 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2088 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2090 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2095 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2097 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2099 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2100 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2101 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2102 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2103 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2104 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2105 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2107 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2109 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2114 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2115 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2116 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2117 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2119 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2121 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2123 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2125 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2126 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2127 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2128 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2129 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2130 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2131 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2132 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2136 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2137 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2138 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2139 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2140 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2142 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2143 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2144 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2145 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2146
63e63b07
RE
2147 /* Cirrus Maverick instructions. */
2148 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2149 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2150 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2151 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2152 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
2153 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
2154 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
2155 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
2156 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
2157 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
2158 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2159 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2160 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
2161 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
2162 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2163 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2164 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
2165 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
2166 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2167 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2168 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2169 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2170 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2171 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2172 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
2173 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
2174 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
2175 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
2176 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2177 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2178 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2179 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2180 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
2181 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
2182 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
2183 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
2184 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
2185 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
2186 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2187 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2188 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2189 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2190 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
2191 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
2192 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
2193 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
2194 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
2195 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
2196 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
2197 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
2198 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2199 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2200 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
2201 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
2202 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2203 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2204 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2205 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2206 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
2207 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
2208 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2209 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2210 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
2211 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
2212 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2213 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2214 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2215 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2216 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2217 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
2218 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2219 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
2220 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2221 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
2222 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
2223 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
b99bd4ef
NC
2224};
2225
2226/* Defines for various bits that we will want to toggle. */
2227#define INST_IMMEDIATE 0x02000000
2228#define OFFSET_REG 0x02000000
2229#define HWOFFSET_IMM 0x00400000
2230#define SHIFT_BY_REG 0x00000010
2231#define PRE_INDEX 0x01000000
2232#define INDEX_UP 0x00800000
2233#define WRITE_BACK 0x00200000
2234#define LDM_TYPE_2_OR_3 0x00400000
2235
2236#define LITERAL_MASK 0xf000f000
b99bd4ef 2237#define OPCODE_MASK 0xfe1fffff
90e4755a
RE
2238#define V4_STR_BIT 0x00000020
2239
b99bd4ef
NC
2240#define DATA_OP_SHIFT 21
2241
2242/* Codes to distinguish the arithmetic instructions. */
2243#define OPCODE_AND 0
2244#define OPCODE_EOR 1
2245#define OPCODE_SUB 2
2246#define OPCODE_RSB 3
2247#define OPCODE_ADD 4
2248#define OPCODE_ADC 5
2249#define OPCODE_SBC 6
2250#define OPCODE_RSC 7
2251#define OPCODE_TST 8
2252#define OPCODE_TEQ 9
2253#define OPCODE_CMP 10
2254#define OPCODE_CMN 11
2255#define OPCODE_ORR 12
2256#define OPCODE_MOV 13
2257#define OPCODE_BIC 14
2258#define OPCODE_MVN 15
2259
c9b604bd 2260/* Thumb v1 (ARMv4T). */
b99bd4ef
NC
2261static void do_t_nop PARAMS ((char *));
2262static void do_t_arit PARAMS ((char *));
2263static void do_t_add PARAMS ((char *));
2264static void do_t_asr PARAMS ((char *));
2265static void do_t_branch9 PARAMS ((char *));
2266static void do_t_branch12 PARAMS ((char *));
2267static void do_t_branch23 PARAMS ((char *));
2268static void do_t_bx PARAMS ((char *));
2269static void do_t_compare PARAMS ((char *));
2270static void do_t_ldmstm PARAMS ((char *));
2271static void do_t_ldr PARAMS ((char *));
2272static void do_t_ldrb PARAMS ((char *));
2273static void do_t_ldrh PARAMS ((char *));
2274static void do_t_lds PARAMS ((char *));
2275static void do_t_lsl PARAMS ((char *));
2276static void do_t_lsr PARAMS ((char *));
2277static void do_t_mov PARAMS ((char *));
2278static void do_t_push_pop PARAMS ((char *));
2279static void do_t_str PARAMS ((char *));
2280static void do_t_strb PARAMS ((char *));
2281static void do_t_strh PARAMS ((char *));
2282static void do_t_sub PARAMS ((char *));
2283static void do_t_swi PARAMS ((char *));
2284static void do_t_adr PARAMS ((char *));
2285
c9b604bd
RE
2286/* Thumb v2 (ARMv5T). */
2287static void do_t_blx PARAMS ((char *));
2288static void do_t_bkpt PARAMS ((char *));
2289
09d92015
MM
2290/* ARM V6. */
2291static void do_t_cps PARAMS ((char *));
2292static void do_t_cpy PARAMS ((char *));
2293static void do_t_setend PARAMS ((char *));;
2294
b99bd4ef
NC
2295#define T_OPCODE_MUL 0x4340
2296#define T_OPCODE_TST 0x4200
2297#define T_OPCODE_CMN 0x42c0
2298#define T_OPCODE_NEG 0x4240
2299#define T_OPCODE_MVN 0x43c0
2300
2301#define T_OPCODE_ADD_R3 0x1800
2302#define T_OPCODE_SUB_R3 0x1a00
2303#define T_OPCODE_ADD_HI 0x4400
2304#define T_OPCODE_ADD_ST 0xb000
2305#define T_OPCODE_SUB_ST 0xb080
2306#define T_OPCODE_ADD_SP 0xa800
2307#define T_OPCODE_ADD_PC 0xa000
2308#define T_OPCODE_ADD_I8 0x3000
2309#define T_OPCODE_SUB_I8 0x3800
2310#define T_OPCODE_ADD_I3 0x1c00
2311#define T_OPCODE_SUB_I3 0x1e00
2312
2313#define T_OPCODE_ASR_R 0x4100
2314#define T_OPCODE_LSL_R 0x4080
2315#define T_OPCODE_LSR_R 0x40c0
2316#define T_OPCODE_ASR_I 0x1000
2317#define T_OPCODE_LSL_I 0x0000
2318#define T_OPCODE_LSR_I 0x0800
2319
2320#define T_OPCODE_MOV_I8 0x2000
2321#define T_OPCODE_CMP_I8 0x2800
2322#define T_OPCODE_CMP_LR 0x4280
2323#define T_OPCODE_MOV_HR 0x4600
2324#define T_OPCODE_CMP_HR 0x4500
2325
2326#define T_OPCODE_LDR_PC 0x4800
2327#define T_OPCODE_LDR_SP 0x9800
2328#define T_OPCODE_STR_SP 0x9000
2329#define T_OPCODE_LDR_IW 0x6800
2330#define T_OPCODE_STR_IW 0x6000
2331#define T_OPCODE_LDR_IH 0x8800
2332#define T_OPCODE_STR_IH 0x8000
2333#define T_OPCODE_LDR_IB 0x7800
2334#define T_OPCODE_STR_IB 0x7000
2335#define T_OPCODE_LDR_RW 0x5800
2336#define T_OPCODE_STR_RW 0x5000
2337#define T_OPCODE_LDR_RH 0x5a00
2338#define T_OPCODE_STR_RH 0x5200
2339#define T_OPCODE_LDR_RB 0x5c00
2340#define T_OPCODE_STR_RB 0x5400
2341
2342#define T_OPCODE_PUSH 0xb400
2343#define T_OPCODE_POP 0xbc00
2344
2345#define T_OPCODE_BRANCH 0xe7fe
2346
2347static int thumb_reg PARAMS ((char ** str, int hi_lo));
2348
2349#define THUMB_SIZE 2 /* Size of thumb instruction. */
2350#define THUMB_REG_LO 0x1
2351#define THUMB_REG_HI 0x2
2352#define THUMB_REG_ANY 0x3
2353
2354#define THUMB_H1 0x0080
2355#define THUMB_H2 0x0040
2356
2357#define THUMB_ASR 0
2358#define THUMB_LSL 1
2359#define THUMB_LSR 2
2360
2361#define THUMB_MOVE 0
2362#define THUMB_COMPARE 1
09d92015 2363#define THUMB_CPY 2
b99bd4ef
NC
2364
2365#define THUMB_LOAD 0
2366#define THUMB_STORE 1
2367
2368#define THUMB_PP_PC_LR 0x0100
2369
2370/* These three are used for immediate shifts, do not alter. */
2371#define THUMB_WORD 2
2372#define THUMB_HALFWORD 1
2373#define THUMB_BYTE 0
2374
2375struct thumb_opcode
2376{
2377 /* Basic string to match. */
05d2d07e 2378 const char * template;
b99bd4ef
NC
2379
2380 /* Basic instruction code. */
2381 unsigned long value;
2382
2383 int size;
2384
2385 /* Which CPU variants this exists for. */
90e4755a 2386 unsigned long variant;
b99bd4ef
NC
2387
2388 /* Function to call to parse args. */
2389 void (* parms) PARAMS ((char *));
2390};
2391
05d2d07e 2392static const struct thumb_opcode tinsns[] =
b99bd4ef 2393{
c9b604bd 2394 /* Thumb v1 (ARMv4T). */
b89dddec
RE
2395 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
2396 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
2397 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
2398 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
2399 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
2400 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
2401 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
2402 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2403 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
2404 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2405 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2406 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
2407 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
2408 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
2409 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
2410 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
2411 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
2412 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
2413 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
2414 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
2415 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
2416 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
2417 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
2418 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
2419 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
b89dddec
RE
2420 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
2421 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
2422 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
2423 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
2424 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
2425 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
2426 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
2427 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
2428 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2429 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2430 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
2431 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
2432 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
2433 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
2434 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
2435 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
2436 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
2437 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
2438 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
2439 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
2440 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
2441 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
2442 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
2443 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
2444 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
2445 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
2446 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
2447 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
2448 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
2449 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
b99bd4ef 2450 /* Pseudo ops: */
b89dddec
RE
2451 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
2452 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
c9b604bd
RE
2453 /* Thumb v2 (ARMv5T). */
2454 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
2455 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
09d92015
MM
2456
2457 /* ARM V6. */
2458 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
2459 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
2460 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
2461 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
2462 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
2463 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
2464 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
2465 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
2466 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
2467 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
2468 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
b99bd4ef
NC
2469};
2470
f03698e6 2471#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 2472#define BAD_PC _("r15 not allowed here")
f03698e6 2473#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
2474#define ERR_NO_ACCUM _("acc0 expected")
2475
2476static struct hash_control * arm_ops_hsh = NULL;
2477static struct hash_control * arm_tops_hsh = NULL;
2478static struct hash_control * arm_cond_hsh = NULL;
2479static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
2480static struct hash_control * arm_psr_hsh = NULL;
2481
2482/* This table describes all the machine specific pseudo-ops the assembler
2483 has to support. The fields are:
2484 pseudo-op name without dot
2485 function to call to execute this pseudo-op
2486 Integer arg to pass to the function. */
2487
2488static void s_req PARAMS ((int));
0bbf2aa4 2489static void s_unreq PARAMS ((int));
b99bd4ef
NC
2490static void s_align PARAMS ((int));
2491static void s_bss PARAMS ((int));
2492static void s_even PARAMS ((int));
2493static void s_ltorg PARAMS ((int));
2494static void s_arm PARAMS ((int));
2495static void s_thumb PARAMS ((int));
2496static void s_code PARAMS ((int));
2497static void s_force_thumb PARAMS ((int));
2498static void s_thumb_func PARAMS ((int));
2499static void s_thumb_set PARAMS ((int));
76feaaf3 2500#ifdef OBJ_ELF
b99bd4ef
NC
2501static void s_arm_elf_cons PARAMS ((int));
2502#endif
2503
2504static int my_get_expression PARAMS ((expressionS *, char **));
2505
05d2d07e 2506const pseudo_typeS md_pseudo_table[] =
b99bd4ef 2507{
0bbf2aa4 2508 /* Never called because '.req' does not start a line. */
b99bd4ef 2509 { "req", s_req, 0 },
0bbf2aa4 2510 { "unreq", s_unreq, 0 },
b99bd4ef
NC
2511 { "bss", s_bss, 0 },
2512 { "align", s_align, 0 },
2513 { "arm", s_arm, 0 },
2514 { "thumb", s_thumb, 0 },
2515 { "code", s_code, 0 },
2516 { "force_thumb", s_force_thumb, 0 },
2517 { "thumb_func", s_thumb_func, 0 },
2518 { "thumb_set", s_thumb_set, 0 },
2519 { "even", s_even, 0 },
2520 { "ltorg", s_ltorg, 0 },
2521 { "pool", s_ltorg, 0 },
76feaaf3 2522#ifdef OBJ_ELF
b99bd4ef
NC
2523 { "word", s_arm_elf_cons, 4 },
2524 { "long", s_arm_elf_cons, 4 },
b99bd4ef
NC
2525#else
2526 { "word", cons, 4},
2527#endif
2528 { "extend", float_cons, 'x' },
2529 { "ldouble", float_cons, 'x' },
2530 { "packed", float_cons, 'p' },
2531 { 0, 0, 0 }
2532};
2533
03b1477f
RE
2534/* Other internal functions. */
2535static int arm_parse_extension PARAMS ((char *, int *));
2536static int arm_parse_cpu PARAMS ((char *));
2537static int arm_parse_arch PARAMS ((char *));
2538static int arm_parse_fpu PARAMS ((char *));
0bbf2aa4 2539#if 0 /* Suppressed - for now. */
5a6c6817
NC
2540#if defined OBJ_COFF || defined OBJ_ELF
2541static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2542#endif
0bbf2aa4 2543#endif
03b1477f 2544
b99bd4ef
NC
2545/* Stuff needed to resolve the label ambiguity
2546 As:
2547 ...
2548 label: <insn>
2549 may differ from:
2550 ...
2551 label:
2552 <insn>
2553*/
2554
2555symbolS * last_label_seen;
b34976b6 2556static int label_is_thumb_function_name = FALSE;
b99bd4ef 2557
3d0c9500 2558/* Literal Pool stuff. */
b99bd4ef
NC
2559
2560#define MAX_LITERAL_POOL_SIZE 1024
2561
3d0c9500
NC
2562/* Literal pool structure. Held on a per-section
2563 and per-sub-section basis. */
2564typedef struct literal_pool
b99bd4ef 2565{
3d0c9500
NC
2566 expressionS literals [MAX_LITERAL_POOL_SIZE];
2567 unsigned int next_free_entry;
2568 unsigned int id;
2569 symbolS * symbol;
2570 segT section;
2571 subsegT sub_section;
61b5f74b 2572 struct literal_pool * next;
3d0c9500 2573} literal_pool;
b99bd4ef 2574
3d0c9500
NC
2575/* Pointer to a linked list of literal pools. */
2576literal_pool * list_of_pools = NULL;
b99bd4ef 2577
3d0c9500
NC
2578static literal_pool * find_literal_pool PARAMS ((void));
2579static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2580
3d0c9500
NC
2581static literal_pool *
2582find_literal_pool ()
2583{
2584 literal_pool * pool;
2585
2586 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2587 {
2588 if (pool->section == now_seg
2589 && pool->sub_section == now_subseg)
2590 break;
2591 }
2592
2593 return pool;
2594}
b99bd4ef 2595
3d0c9500
NC
2596static literal_pool *
2597find_or_make_literal_pool ()
2598{
2599 /* Next literal pool ID number. */
2600 static unsigned int latest_pool_num = 1;
2601 literal_pool * pool;
2602
2603 pool = find_literal_pool ();
b99bd4ef 2604
3d0c9500
NC
2605 if (pool == NULL)
2606 {
2607 /* Create a new pool. */
2608 pool = (literal_pool *) xmalloc (sizeof (* pool));
2609 if (! pool)
2610 return NULL;
2611
2612 pool->next_free_entry = 0;
2613 pool->section = now_seg;
2614 pool->sub_section = now_subseg;
2615 pool->next = list_of_pools;
2616 pool->symbol = NULL;
2617
2618 /* Add it to the list. */
2619 list_of_pools = pool;
2620 }
2621
2622 /* New pools, and emptied pools, will have a NULL symbol. */
2623 if (pool->symbol == NULL)
2624 {
2625 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2626 (valueT) 0, &zero_address_frag);
2627 pool->id = latest_pool_num ++;
2628 }
2629
2630 /* Done. */
2631 return pool;
2632}
2633
2634/* Add the literal in the global 'inst'
2635 structure to the relevent literal pool. */
b99bd4ef
NC
2636static int
2637add_to_lit_pool ()
2638{
61b5f74b 2639 literal_pool * pool;
3d0c9500 2640 unsigned int entry;
b99bd4ef 2641
3d0c9500 2642 pool = find_or_make_literal_pool ();
b99bd4ef 2643
3d0c9500
NC
2644 /* Check if this literal value is already in the pool. */
2645 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2646 {
3d0c9500
NC
2647 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2648 && (inst.reloc.exp.X_op == O_constant)
2649 && (pool->literals[entry].X_add_number
b99bd4ef 2650 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2651 && (pool->literals[entry].X_unsigned
2652 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2653 break;
2654
3d0c9500
NC
2655 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2656 && (inst.reloc.exp.X_op == O_symbol)
2657 && (pool->literals[entry].X_add_number
b99bd4ef 2658 == inst.reloc.exp.X_add_number)
3d0c9500 2659 && (pool->literals[entry].X_add_symbol
b99bd4ef 2660 == inst.reloc.exp.X_add_symbol)
3d0c9500 2661 && (pool->literals[entry].X_op_symbol
b99bd4ef 2662 == inst.reloc.exp.X_op_symbol))
3d0c9500 2663 break;
b99bd4ef
NC
2664 }
2665
3d0c9500
NC
2666 /* Do we need to create a new entry? */
2667 if (entry == pool->next_free_entry)
b99bd4ef 2668 {
3d0c9500 2669 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2670 {
ed71e111 2671 inst.error = _("literal pool overflow");
b99bd4ef
NC
2672 return FAIL;
2673 }
2674
3d0c9500
NC
2675 pool->literals[entry] = inst.reloc.exp;
2676 pool->next_free_entry += 1;
b99bd4ef
NC
2677 }
2678
3d0c9500 2679 inst.reloc.exp.X_op = O_symbol;
08df2379 2680 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2681 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2682
2683 return SUCCESS;
2684}
2685
2686/* Can't use symbol_new here, so have to create a symbol and then at
2687 a later date assign it a value. Thats what these functions do. */
2688
2689static void
2690symbol_locate (symbolP, name, segment, valu, frag)
2691 symbolS * symbolP;
05d2d07e 2692 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2693 segT segment; /* Segment identifier (SEG_<something>). */
2694 valueT valu; /* Symbol value. */
2695 fragS * frag; /* Associated fragment. */
2696{
2697 unsigned int name_length;
2698 char * preserved_copy_of_name;
2699
2700 name_length = strlen (name) + 1; /* +1 for \0. */
2701 obstack_grow (&notes, name, name_length);
2702 preserved_copy_of_name = obstack_finish (&notes);
2703#ifdef STRIP_UNDERSCORE
2704 if (preserved_copy_of_name[0] == '_')
2705 preserved_copy_of_name++;
2706#endif
2707
2708#ifdef tc_canonicalize_symbol_name
2709 preserved_copy_of_name =
2710 tc_canonicalize_symbol_name (preserved_copy_of_name);
2711#endif
2712
2713 S_SET_NAME (symbolP, preserved_copy_of_name);
2714
2715 S_SET_SEGMENT (symbolP, segment);
2716 S_SET_VALUE (symbolP, valu);
c62e1cc3 2717 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2718
2719 symbol_set_frag (symbolP, frag);
2720
2721 /* Link to end of symbol chain. */
2722 {
2723 extern int symbol_table_frozen;
2724 if (symbol_table_frozen)
2725 abort ();
2726 }
2727
2728 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2729
2730 obj_symbol_new_hook (symbolP);
2731
2732#ifdef tc_symbol_new_hook
2733 tc_symbol_new_hook (symbolP);
2734#endif
2735
2736#ifdef DEBUG_SYMS
2737 verify_symbol_chain (symbol_rootP, symbol_lastP);
2738#endif /* DEBUG_SYMS */
2739}
2740
2741/* Check that an immediate is valid.
2742 If so, convert it to the right format. */
2743
2744static unsigned int
2745validate_immediate (val)
2746 unsigned int val;
2747{
2748 unsigned int a;
2749 unsigned int i;
2750
2751#define rotate_left(v, n) (v << n | v >> (32 - n))
2752
2753 for (i = 0; i < 32; i += 2)
2754 if ((a = rotate_left (val, i)) <= 0xff)
2755 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2756
2757 return FAIL;
2758}
2759
2d2255b5 2760/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
2761 values, added together. We already know that this value cannot be
2762 computed by just one ARM instruction. */
2763
2764static unsigned int
2765validate_immediate_twopart (val, highpart)
2766 unsigned int val;
2767 unsigned int * highpart;
2768{
2769 unsigned int a;
2770 unsigned int i;
2771
2772 for (i = 0; i < 32; i += 2)
2773 if (((a = rotate_left (val, i)) & 0xff) != 0)
2774 {
2775 if (a & 0xff00)
2776 {
2777 if (a & ~ 0xffff)
2778 continue;
2779 * highpart = (a >> 8) | ((i + 24) << 7);
2780 }
2781 else if (a & 0xff0000)
2782 {
2783 if (a & 0xff000000)
2784 continue;
2785 * highpart = (a >> 16) | ((i + 16) << 7);
2786 }
2787 else
2788 {
2789 assert (a & 0xff000000);
2790 * highpart = (a >> 24) | ((i + 8) << 7);
2791 }
2792
2793 return (a & 0xff) | (i << 7);
2794 }
2795
2796 return FAIL;
2797}
2798
2799static int
2800validate_offset_imm (val, hwse)
2801 unsigned int val;
2802 int hwse;
2803{
2804 if ((hwse && val > 255) || val > 4095)
2805 return FAIL;
2806 return val;
2807}
2808
6057a28f
NC
2809\f
2810#ifdef OBJ_ELF
2811enum mstate
2812{
2813 MAP_DATA,
2814 MAP_ARM,
2815 MAP_THUMB
2816};
2817
2818/* This code is to handle mapping symbols as defined in the ARM ELF spec.
2819 (This text is taken from version B-02 of the spec):
2820
2821 4.4.7 Mapping and tagging symbols
2822
2823 A section of an ARM ELF file can contain a mixture of ARM code,
2824 Thumb code, and data. There are inline transitions between code
2825 and data at literal pool boundaries. There can also be inline
2826 transitions between ARM code and Thumb code, for example in
2827 ARM-Thumb inter-working veneers. Linkers, machine-level
2828 debuggers, profiling tools, and disassembly tools need to map
2829 images accurately. For example, setting an ARM breakpoint on a
2830 Thumb location, or in a literal pool, can crash the program
2831 being debugged, ruining the debugging session.
2832
2833 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2834 tagged (see section 4.4.7.2 below) using local symbols (with
2835 binding STB_LOCAL). To assist consumers, mapping and tagging
2836 symbols should be collated first in the symbol table, before
2837 other symbols with binding STB_LOCAL.
2838
2839 To allow properly collated mapping and tagging symbols to be
2840 skipped by consumers that have no interest in them, the first
2841 such symbol should have the name $m and its st_value field equal
2842 to the total number of mapping and tagging symbols (including
2843 the $m) in the symbol table.
2844
2845 4.4.7.1 Mapping symbols
2846
2847 $a Labels the first byte of a sequence of ARM instructions.
2848 Its type is STT_FUNC.
2849
2850 $d Labels the first byte of a sequence of data items.
2851 Its type is STT_OBJECT.
2852
2853 $t Labels the first byte of a sequence of Thumb instructions.
2854 Its type is STT_FUNC.
2855
2856 This list of mapping symbols may be extended in the future.
2857
2858 Section-relative mapping symbols
2859
2860 Mapping symbols defined in a section define a sequence of
2861 half-open address intervals that cover the address range of the
2862 section. Each interval starts at the address defined by a
2863 mapping symbol, and continues up to, but not including, the
2864 address defined by the next (in address order) mapping symbol or
2865 the end of the section. A corollary is that there must be a
2866 mapping symbol defined at the beginning of each section.
2867 Consumers can ignore the size of a section-relative mapping
2868 symbol. Producers can set it to 0.
2869
2870 Absolute mapping symbols
2871
2872 Because of the need to crystallize a Thumb address with the
2873 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2874 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2875 or $t.
2876
2877 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2878 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2879 where [x, y) denotes the half-open address range from x,
2880 inclusive, to y, exclusive.
2881
2882 In the absence of a mapping symbol, a consumer can interpret a
2883 function symbol with an odd value as the Thumb code address
2884 obtained by clearing the least significant bit of the
2885 value. This interpretation is deprecated, and it may not work in
2886 the future.
2887
2888 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2889 the EABI (which is still under development), so they are not
2890 implemented here. */
2891
2892static void
2893mapping_state (enum mstate state)
2894{
2895 static enum mstate mapstate = MAP_DATA;
2896 symbolS * symbolP;
2897 const char * symname;
2898 int type;
2899
2900 if (mapstate == state)
2901 /* The mapping symbol has already been emitted.
2902 There is nothing else to do. */
2903 return;
2904
2905 mapstate = state;
2906
2907 switch (state)
2908 {
2909 case MAP_DATA:
2910 symname = "$d";
2911 type = BSF_OBJECT;
2912 break;
2913 case MAP_ARM:
2914 symname = "$a";
2915 type = BSF_FUNCTION;
2916 break;
2917 case MAP_THUMB:
2918 symname = "$t";
2919 type = BSF_FUNCTION;
2920 break;
2921 default:
2922 abort ();
2923 }
2924
2925 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2926 symbol_table_insert (symbolP);
2927 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2928
2929 switch (state)
2930 {
2931 case MAP_ARM:
2932 THUMB_SET_FUNC (symbolP, 0);
2933 ARM_SET_THUMB (symbolP, 0);
2934 ARM_SET_INTERWORK (symbolP, support_interwork);
2935 break;
2936
2937 case MAP_THUMB:
2938 THUMB_SET_FUNC (symbolP, 1);
2939 ARM_SET_THUMB (symbolP, 1);
2940 ARM_SET_INTERWORK (symbolP, support_interwork);
2941 break;
2942
2943 case MAP_DATA:
2944 default:
2945 return;
2946 }
2947}
2948
2949/* When we change sections we need to issue a new mapping symbol. */
2950
9ce887a1 2951void
6057a28f
NC
2952arm_elf_change_section (void)
2953{
2954 flagword flags;
2955
2956 if (!SEG_NORMAL (now_seg))
2957 return;
2958
2959 flags = bfd_get_section_flags (stdoutput, now_seg);
2960
2961 /* We can ignore sections that only contain debug info. */
2962 if ((flags & SEC_ALLOC) == 0)
2963 return;
2964
2965 if (flags & SEC_CODE)
2966 {
2967 if (thumb_mode)
2968 mapping_state (MAP_THUMB);
2969 else
2970 mapping_state (MAP_ARM);
2971 }
2972 else
2973 /* This section does not contain code. Therefore it must contain data. */
2974 mapping_state (MAP_DATA);
2975}
2976#else
2977#define mapping_state(a)
2978#endif /* OBJ_ELF */
2979\f
2980
b99bd4ef
NC
2981static void
2982s_req (a)
2983 int a ATTRIBUTE_UNUSED;
2984{
f03698e6 2985 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
2986}
2987
0bbf2aa4
NC
2988/* The .unreq directive deletes an alias which was previously defined
2989 by .req. For example:
2990
2991 my_alias .req r11
2992 .unreq my_alias */
2993
2994static void
2995s_unreq (int a ATTRIBUTE_UNUSED)
2996{
2997 char *name;
2998 char saved_char;
2999
3000 skip_whitespace (input_line_pointer);
3001 name = input_line_pointer;
3002
3003 while (*input_line_pointer != 0
3004 && *input_line_pointer != ' '
3005 && *input_line_pointer != '\n')
3006 ++input_line_pointer;
3007
3008 saved_char = *input_line_pointer;
3009 *input_line_pointer = 0;
3010
3011 if (*name)
3012 {
3013 enum arm_reg_type req_type = arm_reg_parse_any (name);
3014
3015 if (req_type != REG_TYPE_MAX)
3016 {
3017 char *temp_name = name;
3018 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3019
3020 if (req_no != FAIL)
3021 {
3022 struct reg_entry *req_entry;
3023
3024 /* Check to see if this alias is a builtin one. */
3025 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3026
3027 if (!req_entry)
3028 as_bad (_("unreq: missing hash entry for \"%s\""), name);
3029 else if (req_entry->builtin)
67c1ffbe 3030 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
3031 points to a const data structure, so we only need to
3032 free up the memory used by the key in the hash table.
3033 Unfortunately we have not recorded this value, so this
3034 is a memory leak. */
3035 /* FIXME: Should we issue a warning message ? */
3036 ;
3037 else
3038 {
67c1ffbe 3039 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
3040 key and the value, but fortunately the key is the same
3041 as the value->name field. */
3042 free ((char *) req_entry->name);
3043 free (req_entry);
3044 }
3045 }
3046 else
3047 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3048 }
3049 else
3050 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3051 }
3052 else
3053 as_bad (_("invalid syntax for .unreq directive"));
3054
3055 *input_line_pointer = saved_char;
3056 demand_empty_rest_of_line ();
3057}
3058
b99bd4ef
NC
3059static void
3060s_bss (ignore)
3061 int ignore ATTRIBUTE_UNUSED;
3062{
3063 /* We don't support putting frags in the BSS segment, we fake it by
3064 marking in_bss, then looking at s_skip for clues. */
3065 subseg_set (bss_section, 0);
3066 demand_empty_rest_of_line ();
6057a28f 3067 mapping_state (MAP_DATA);
b99bd4ef
NC
3068}
3069
3070static void
3071s_even (ignore)
3072 int ignore ATTRIBUTE_UNUSED;
3073{
3074 /* Never make frag if expect extra pass. */
3075 if (!need_pass_2)
3076 frag_align (1, 0, 0);
3077
3078 record_alignment (now_seg, 1);
3079
3080 demand_empty_rest_of_line ();
3081}
3082
3083static void
3084s_ltorg (ignored)
3085 int ignored ATTRIBUTE_UNUSED;
3086{
3d0c9500
NC
3087 unsigned int entry;
3088 literal_pool * pool;
b99bd4ef
NC
3089 char sym_name[20];
3090
3d0c9500
NC
3091 pool = find_literal_pool ();
3092 if (pool == NULL
3093 || pool->symbol == NULL
3094 || pool->next_free_entry == 0)
b99bd4ef
NC
3095 return;
3096
3097 /* Align pool as you have word accesses.
3098 Only make a frag if we have to. */
3099 if (!need_pass_2)
3100 frag_align (2, 0, 0);
3101
3102 record_alignment (now_seg, 2);
3103
3d0c9500 3104 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 3105
3d0c9500 3106 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 3107 (valueT) frag_now_fix (), frag_now);
3d0c9500 3108 symbol_table_insert (pool->symbol);
b99bd4ef 3109
3d0c9500 3110 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
3111
3112#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 3113 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
3114#endif
3115
3d0c9500 3116 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 3117 /* First output the expression in the instruction to the pool. */
3d0c9500 3118 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 3119
3d0c9500
NC
3120 /* Mark the pool as empty. */
3121 pool->next_free_entry = 0;
3122 pool->symbol = NULL;
b99bd4ef
NC
3123}
3124
3125/* Same as s_align_ptwo but align 0 => align 2. */
3126
3127static void
3128s_align (unused)
3129 int unused ATTRIBUTE_UNUSED;
3130{
3131 register int temp;
3132 register long temp_fill;
3133 long max_alignment = 15;
3134
3135 temp = get_absolute_expression ();
3136 if (temp > max_alignment)
f03698e6 3137 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
3138 else if (temp < 0)
3139 {
f03698e6 3140 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
3141 temp = 0;
3142 }
3143
3144 if (*input_line_pointer == ',')
3145 {
3146 input_line_pointer++;
3147 temp_fill = get_absolute_expression ();
3148 }
3149 else
3150 temp_fill = 0;
3151
3152 if (!temp)
3153 temp = 2;
3154
3155 /* Only make a frag if we HAVE to. */
3156 if (temp && !need_pass_2)
3157 frag_align (temp, (int) temp_fill, 0);
3158 demand_empty_rest_of_line ();
3159
3160 record_alignment (now_seg, temp);
3161}
3162
3163static void
3164s_force_thumb (ignore)
3165 int ignore ATTRIBUTE_UNUSED;
3166{
3167 /* If we are not already in thumb mode go into it, EVEN if
3168 the target processor does not support thumb instructions.
3169 This is used by gcc/config/arm/lib1funcs.asm for example
3170 to compile interworking support functions even if the
3171 target processor should not support interworking. */
3172 if (! thumb_mode)
3173 {
3174 thumb_mode = 2;
3175
3176 record_alignment (now_seg, 1);
3177 }
3178
3179 demand_empty_rest_of_line ();
3180}
3181
3182static void
3183s_thumb_func (ignore)
3184 int ignore ATTRIBUTE_UNUSED;
3185{
3186 if (! thumb_mode)
3187 opcode_select (16);
3188
3189 /* The following label is the name/address of the start of a Thumb function.
3190 We need to know this for the interworking support. */
b34976b6 3191 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
3192
3193 demand_empty_rest_of_line ();
3194}
3195
3196/* Perform a .set directive, but also mark the alias as
3197 being a thumb function. */
3198
3199static void
3200s_thumb_set (equiv)
3201 int equiv;
3202{
3203 /* XXX the following is a duplicate of the code for s_set() in read.c
3204 We cannot just call that code as we need to get at the symbol that
3205 is created. */
3206 register char * name;
3207 register char delim;
3208 register char * end_name;
3209 register symbolS * symbolP;
3210
3211 /* Especial apologies for the random logic:
3212 This just grew, and could be parsed much more simply!
3213 Dean - in haste. */
3214 name = input_line_pointer;
3215 delim = get_symbol_end ();
3216 end_name = input_line_pointer;
3217 *end_name = delim;
3218
3219 SKIP_WHITESPACE ();
3220
3221 if (*input_line_pointer != ',')
3222 {
3223 *end_name = 0;
f03698e6 3224 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
3225 *end_name = delim;
3226 ignore_rest_of_line ();
3227 return;
3228 }
3229
3230 input_line_pointer++;
3231 *end_name = 0;
3232
3233 if (name[0] == '.' && name[1] == '\0')
3234 {
3235 /* XXX - this should not happen to .thumb_set. */
3236 abort ();
3237 }
3238
3239 if ((symbolP = symbol_find (name)) == NULL
3240 && (symbolP = md_undefined_symbol (name)) == NULL)
3241 {
3242#ifndef NO_LISTING
3243 /* When doing symbol listings, play games with dummy fragments living
3244 outside the normal fragment chain to record the file and line info
3245 for this symbol. */
3246 if (listing & LISTING_SYMBOLS)
3247 {
3248 extern struct list_info_struct * listing_tail;
3249 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3250
3251 memset (dummy_frag, 0, sizeof (fragS));
3252 dummy_frag->fr_type = rs_fill;
3253 dummy_frag->line = listing_tail;
3254 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3255 dummy_frag->fr_symbol = symbolP;
3256 }
3257 else
3258#endif
3259 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3260
3261#ifdef OBJ_COFF
3262 /* "set" symbols are local unless otherwise specified. */
3263 SF_SET_LOCAL (symbolP);
3264#endif /* OBJ_COFF */
3265 } /* Make a new symbol. */
3266
3267 symbol_table_insert (symbolP);
3268
3269 * end_name = delim;
3270
3271 if (equiv
3272 && S_IS_DEFINED (symbolP)
3273 && S_GET_SEGMENT (symbolP) != reg_section)
3274 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3275
3276 pseudo_set (symbolP);
3277
3278 demand_empty_rest_of_line ();
3279
3280 /* XXX Now we come to the Thumb specific bit of code. */
3281
3282 THUMB_SET_FUNC (symbolP, 1);
3283 ARM_SET_THUMB (symbolP, 1);
3284#if defined OBJ_ELF || defined OBJ_COFF
3285 ARM_SET_INTERWORK (symbolP, support_interwork);
3286#endif
3287}
3288
b99bd4ef
NC
3289static void
3290opcode_select (width)
3291 int width;
3292{
3293 switch (width)
3294 {
3295 case 16:
3296 if (! thumb_mode)
3297 {
b89dddec 3298 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
3299 as_bad (_("selected processor does not support THUMB opcodes"));
3300
3301 thumb_mode = 1;
3302 /* No need to force the alignment, since we will have been
3303 coming from ARM mode, which is word-aligned. */
3304 record_alignment (now_seg, 1);
3305 }
6057a28f 3306 mapping_state (MAP_THUMB);
b99bd4ef
NC
3307 break;
3308
3309 case 32:
3310 if (thumb_mode)
3311 {
03b1477f 3312 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
3313 as_bad (_("selected processor does not support ARM opcodes"));
3314
3315 thumb_mode = 0;
3316
3317 if (!need_pass_2)
cc8a6dd0 3318 frag_align (2, 0, 0);
b99bd4ef 3319
cc8a6dd0 3320 record_alignment (now_seg, 1);
b99bd4ef 3321 }
6057a28f 3322 mapping_state (MAP_ARM);
b99bd4ef
NC
3323 break;
3324
3325 default:
3326 as_bad (_("invalid instruction size selected (%d)"), width);
3327 }
3328}
3329
3330static void
3331s_arm (ignore)
3332 int ignore ATTRIBUTE_UNUSED;
3333{
3334 opcode_select (32);
3335 demand_empty_rest_of_line ();
3336}
3337
3338static void
3339s_thumb (ignore)
3340 int ignore ATTRIBUTE_UNUSED;
3341{
3342 opcode_select (16);
3343 demand_empty_rest_of_line ();
3344}
3345
3346static void
3347s_code (unused)
3348 int unused ATTRIBUTE_UNUSED;
3349{
3350 register int temp;
3351
3352 temp = get_absolute_expression ();
3353 switch (temp)
3354 {
3355 case 16:
3356 case 32:
3357 opcode_select (temp);
3358 break;
3359
3360 default:
3361 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3362 }
3363}
3364
3365static void
3366end_of_line (str)
f03698e6 3367 char *str;
b99bd4ef
NC
3368{
3369 skip_whitespace (str);
3370
f03698e6
RE
3371 if (*str != '\0' && !inst.error)
3372 inst.error = _("garbage following instruction");
b99bd4ef
NC
3373}
3374
3375static int
3376skip_past_comma (str)
3377 char ** str;
3378{
3379 char * p = * str, c;
3380 int comma = 0;
3381
3382 while ((c = *p) == ' ' || c == ',')
3383 {
3384 p++;
3385 if (c == ',' && comma++)
3386 return FAIL;
3387 }
3388
3389 if (c == '\0')
3390 return FAIL;
3391
3392 *str = p;
3393 return comma ? SUCCESS : FAIL;
3394}
3395
3396/* A standard register must be given at this point.
3397 SHIFT is the place to put it in inst.instruction.
3398 Restores input start point on error.
3399 Returns the reg#, or FAIL. */
3400
3401static int
3402reg_required_here (str, shift)
3403 char ** str;
3404 int shift;
3405{
3406 static char buff [128]; /* XXX */
3407 int reg;
3408 char * start = * str;
3409
6c43fab6 3410 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
3411 {
3412 if (shift >= 0)
3413 inst.instruction |= reg << shift;
3414 return reg;
3415 }
3416
3417 /* Restore the start point, we may have got a reg of the wrong class. */
3418 *str = start;
3419
3420 /* In the few cases where we might be able to accept something else
3421 this error can be overridden. */
f03698e6 3422 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
3423 inst.error = buff;
3424
3425 return FAIL;
3426}
3427
5a6c6817 3428/* A Intel Wireless MMX technology register
e16bb312
NC
3429 must be given at this point.
3430 Shift is the place to put it in inst.instruction.
3431 Restores input start point on err.
3432 Returns the reg#, or FAIL. */
3433
3434static int
3435wreg_required_here (str, shift, reg_type)
3436 char ** str;
3437 int shift;
3438 enum wreg_type reg_type;
3439{
3440 static char buff [128];
3441 int reg;
3442 char * start = *str;
3443
3444 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3445 {
3446 if (wr_register (reg)
3447 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3448 {
3449 if (shift >= 0)
3450 inst.instruction |= (reg ^ WR_PREFIX) << shift;
3451 return reg;
3452 }
3453 else if (wc_register (reg)
3454 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3455 {
3456 if (shift >= 0)
3457 inst.instruction |= (reg ^ WC_PREFIX) << shift;
3458 return reg;
3459 }
3460 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3461 {
3462 if (shift >= 0)
3463 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3464 return reg;
3465 }
3466 }
3467
3468 /* Restore the start point, we may have got a reg of the wrong class. */
3469 *str = start;
3470
3471 /* In the few cases where we might be able to accept
3472 something else this error can be overridden. */
5a6c6817 3473 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
3474 inst.error = buff;
3475
3476 return FAIL;
3477}
3478
05d2d07e 3479static const struct asm_psr *
b99bd4ef
NC
3480arm_psr_parse (ccp)
3481 register char ** ccp;
3482{
3483 char * start = * ccp;
3484 char c;
3485 char * p;
05d2d07e 3486 const struct asm_psr * psr;
b99bd4ef
NC
3487
3488 p = start;
3489
3490 /* Skip to the end of the next word in the input stream. */
3491 do
3492 {
3493 c = *p++;
3494 }
3882b010 3495 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
3496
3497 /* Terminate the word. */
3498 *--p = 0;
3499
3500 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3501 feature for ease of use and backwards compatibility. */
3502 if (!strncmp (start, "cpsr", 4))
3503 strncpy (start, "CPSR", 4);
3504 else if (!strncmp (start, "spsr", 4))
3505 strncpy (start, "SPSR", 4);
3506
3507 /* Now locate the word in the psr hash table. */
05d2d07e 3508 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
3509
3510 /* Restore the input stream. */
3511 *p = c;
3512
3513 /* If we found a valid match, advance the
3514 stream pointer past the end of the word. */
3515 *ccp = p;
3516
3517 return psr;
3518}
3519
3520/* Parse the input looking for a PSR flag. */
3521
3522static int
3523psr_required_here (str)
3524 char ** str;
3525{
3526 char * start = * str;
05d2d07e 3527 const struct asm_psr * psr;
b99bd4ef
NC
3528
3529 psr = arm_psr_parse (str);
3530
3531 if (psr)
3532 {
3533 /* If this is the SPSR that is being modified, set the R bit. */
3534 if (! psr->cpsr)
3535 inst.instruction |= SPSR_BIT;
3536
3537 /* Set the psr flags in the MSR instruction. */
3538 inst.instruction |= psr->field << PSR_SHIFT;
3539
3540 return SUCCESS;
3541 }
3542
3543 /* In the few cases where we might be able to accept
3544 something else this error can be overridden. */
3545 inst.error = _("flag for {c}psr instruction expected");
3546
3547 /* Restore the start point. */
3548 *str = start;
3549 return FAIL;
3550}
3551
3552static int
3553co_proc_number (str)
6c43fab6 3554 char **str;
b99bd4ef
NC
3555{
3556 int processor, pchar;
6c43fab6 3557 char *start;
b99bd4ef 3558
6c43fab6
RE
3559 skip_whitespace (*str);
3560 start = *str;
b99bd4ef
NC
3561
3562 /* The data sheet seems to imply that just a number on its own is valid
3563 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3564 accept either. */
6c43fab6
RE
3565 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3566 == FAIL)
b99bd4ef 3567 {
6c43fab6
RE
3568 *str = start;
3569
3570 pchar = *(*str)++;
3571 if (pchar >= '0' && pchar <= '9')
b99bd4ef 3572 {
6c43fab6
RE
3573 processor = pchar - '0';
3574 if (**str >= '0' && **str <= '9')
b99bd4ef 3575 {
6c43fab6
RE
3576 processor = processor * 10 + *(*str)++ - '0';
3577 if (processor > 15)
3578 {
f03698e6 3579 inst.error = _("illegal co-processor number");
6c43fab6
RE
3580 return FAIL;
3581 }
b99bd4ef
NC
3582 }
3583 }
6c43fab6
RE
3584 else
3585 {
f03698e6 3586 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
3587 return FAIL;
3588 }
b99bd4ef
NC
3589 }
3590
3591 inst.instruction |= processor << 8;
3592 return SUCCESS;
3593}
3594
3595static int
3596cp_opc_expr (str, where, length)
3597 char ** str;
3598 int where;
3599 int length;
3600{
3601 expressionS expr;
3602
3603 skip_whitespace (* str);
3604
3605 memset (&expr, '\0', sizeof (expr));
3606
3607 if (my_get_expression (&expr, str))
3608 return FAIL;
3609 if (expr.X_op != O_constant)
3610 {
3611 inst.error = _("bad or missing expression");
3612 return FAIL;
3613 }
3614
3615 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3616 {
3617 inst.error = _("immediate co-processor expression too large");
3618 return FAIL;
3619 }
3620
3621 inst.instruction |= expr.X_add_number << where;
3622 return SUCCESS;
3623}
3624
3625static int
3626cp_reg_required_here (str, where)
3627 char ** str;
3628 int where;
3629{
3630 int reg;
3631 char * start = *str;
3632
6c43fab6 3633 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 3634 {
b99bd4ef
NC
3635 inst.instruction |= reg << where;
3636 return reg;
3637 }
3638
3639 /* In the few cases where we might be able to accept something else
3640 this error can be overridden. */
f03698e6 3641 inst.error = _("co-processor register expected");
b99bd4ef
NC
3642
3643 /* Restore the start point. */
3644 *str = start;
3645 return FAIL;
3646}
3647
3648static int
3649fp_reg_required_here (str, where)
3650 char ** str;
3651 int where;
3652{
3653 int reg;
3654 char * start = * str;
3655
6c43fab6 3656 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 3657 {
b99bd4ef
NC
3658 inst.instruction |= reg << where;
3659 return reg;
3660 }
3661
3662 /* In the few cases where we might be able to accept something else
3663 this error can be overridden. */
f03698e6 3664 inst.error = _("floating point register expected");
b99bd4ef
NC
3665
3666 /* Restore the start point. */
3667 *str = start;
3668 return FAIL;
3669}
3670
3671static int
3672cp_address_offset (str)
3673 char ** str;
3674{
3675 int offset;
3676
3677 skip_whitespace (* str);
3678
3679 if (! is_immediate_prefix (**str))
3680 {
3681 inst.error = _("immediate expression expected");
3682 return FAIL;
3683 }
3684
3685 (*str)++;
3686
3687 if (my_get_expression (& inst.reloc.exp, str))
3688 return FAIL;
3689
3690 if (inst.reloc.exp.X_op == O_constant)
3691 {
3692 offset = inst.reloc.exp.X_add_number;
3693
3694 if (offset & 3)
3695 {
3696 inst.error = _("co-processor address must be word aligned");
3697 return FAIL;
3698 }
3699
3700 if (offset > 1023 || offset < -1023)
3701 {
3702 inst.error = _("offset too large");
3703 return FAIL;
3704 }
3705
3706 if (offset >= 0)
3707 inst.instruction |= INDEX_UP;
3708 else
3709 offset = -offset;
3710
3711 inst.instruction |= offset >> 2;
3712 }
3713 else
3714 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3715
3716 return SUCCESS;
3717}
3718
3719static int
bfae80f2 3720cp_address_required_here (str, wb_ok)
b99bd4ef 3721 char ** str;
bfae80f2 3722 int wb_ok;
b99bd4ef
NC
3723{
3724 char * p = * str;
3725 int pre_inc = 0;
3726 int write_back = 0;
3727
3728 if (*p == '[')
3729 {
3730 int reg;
3731
3732 p++;
3733 skip_whitespace (p);
3734
3735 if ((reg = reg_required_here (& p, 16)) == FAIL)
3736 return FAIL;
3737
3738 skip_whitespace (p);
3739
3740 if (*p == ']')
3741 {
3742 p++;
3743
f02232aa
NC
3744 skip_whitespace (p);
3745
3746 if (*p == '\0')
b99bd4ef 3747 {
f02232aa
NC
3748 /* As an extension to the official ARM syntax we allow:
3749
3750 [Rn]
3751
3752 as a short hand for:
3753
3754 [Rn,#0] */
3755 inst.instruction |= PRE_INDEX | INDEX_UP;
3756 *str = p;
3757 return SUCCESS;
3758 }
3759
3760 if (skip_past_comma (& p) == FAIL)
3761 {
3762 inst.error = _("comma expected after closing square bracket");
3763 return FAIL;
3764 }
b99bd4ef 3765
f02232aa
NC
3766 skip_whitespace (p);
3767
3768 if (*p == '#')
3769 {
3770 if (wb_ok)
b99bd4ef 3771 {
f02232aa
NC
3772 /* [Rn], #expr */
3773 write_back = WRITE_BACK;
3774
3775 if (reg == REG_PC)
3776 {
3777 inst.error = _("pc may not be used in post-increment");
3778 return FAIL;
3779 }
3780
3781 if (cp_address_offset (& p) == FAIL)
3782 return FAIL;
b99bd4ef 3783 }
f02232aa
NC
3784 else
3785 pre_inc = PRE_INDEX | INDEX_UP;
3786 }
3787 else if (*p == '{')
3788 {
3789 int option;
b99bd4ef 3790
f02232aa
NC
3791 /* [Rn], {<expr>} */
3792 p++;
3793
3794 skip_whitespace (p);
3795
3796 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 3797 return FAIL;
f02232aa
NC
3798
3799 if (inst.reloc.exp.X_op == O_constant)
3800 {
3801 option = inst.reloc.exp.X_add_number;
3802
3803 if (option > 255 || option < 0)
3804 {
3805 inst.error = _("'option' field too large");
3806 return FAIL;
3807 }
3808
3809 skip_whitespace (p);
3810
3811 if (*p != '}')
3812 {
3813 inst.error = _("'}' expected at end of 'option' field");
3814 return FAIL;
3815 }
3816 else
3817 {
3818 p++;
3819 inst.instruction |= option;
3820 inst.instruction |= INDEX_UP;
3821 }
3822 }
3823 else
3824 {
3825 inst.error = _("non-constant expressions for 'option' field not supported");
3826 return FAIL;
3827 }
b99bd4ef
NC
3828 }
3829 else
f02232aa
NC
3830 {
3831 inst.error = _("# or { expected after comma");
3832 return FAIL;
3833 }
b99bd4ef
NC
3834 }
3835 else
3836 {
3837 /* '['Rn, #expr']'[!] */
3838
3839 if (skip_past_comma (& p) == FAIL)
3840 {
3841 inst.error = _("pre-indexed expression expected");
3842 return FAIL;
3843 }
3844
3845 pre_inc = PRE_INDEX;
3846
3847 if (cp_address_offset (& p) == FAIL)
3848 return FAIL;
3849
3850 skip_whitespace (p);
3851
3852 if (*p++ != ']')
3853 {
3854 inst.error = _("missing ]");
3855 return FAIL;
3856 }
3857
3858 skip_whitespace (p);
3859
bfae80f2 3860 if (wb_ok && *p == '!')
b99bd4ef
NC
3861 {
3862 if (reg == REG_PC)
3863 {
3864 inst.error = _("pc may not be used with write-back");
3865 return FAIL;
3866 }
3867
3868 p++;
3869 write_back = WRITE_BACK;
3870 }
3871 }
3872 }
3873 else
3874 {
3875 if (my_get_expression (&inst.reloc.exp, &p))
3876 return FAIL;
3877
3878 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3879 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3880 inst.reloc.pc_rel = 1;
3881 inst.instruction |= (REG_PC << 16);
3882 pre_inc = PRE_INDEX;
3883 }
3884
3885 inst.instruction |= write_back | pre_inc;
3886 *str = p;
3887 return SUCCESS;
3888}
3889
e16bb312
NC
3890static int
3891cp_byte_address_offset (str)
3892 char ** str;
3893{
3894 int offset;
3895
3896 skip_whitespace (* str);
3897
3898 if (! is_immediate_prefix (**str))
3899 {
3900 inst.error = _("immediate expression expected");
3901 return FAIL;
3902 }
3903
3904 (*str)++;
3905
3906 if (my_get_expression (& inst.reloc.exp, str))
3907 return FAIL;
3908
3909 if (inst.reloc.exp.X_op == O_constant)
3910 {
3911 offset = inst.reloc.exp.X_add_number;
3912
3913 if (offset > 255 || offset < -255)
3914 {
3915 inst.error = _("offset too large");
3916 return FAIL;
3917 }
3918
3919 if (offset >= 0)
3920 inst.instruction |= INDEX_UP;
3921 else
3922 offset = -offset;
3923
3924 inst.instruction |= offset;
3925 }
3926 else
3927 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3928
3929 return SUCCESS;
3930}
3931
3932static int
3933cp_byte_address_required_here (str)
3934 char ** str;
3935{
3936 char * p = * str;
3937 int pre_inc = 0;
3938 int write_back = 0;
3939
3940 if (*p == '[')
3941 {
3942 int reg;
3943
3944 p++;
3945 skip_whitespace (p);
3946
3947 if ((reg = reg_required_here (& p, 16)) == FAIL)
3948 return FAIL;
3949
3950 skip_whitespace (p);
3951
3952 if (*p == ']')
3953 {
3954 p++;
3955
3956 if (skip_past_comma (& p) == SUCCESS)
3957 {
3958 /* [Rn], #expr */
3959 write_back = WRITE_BACK;
3960
3961 if (reg == REG_PC)
3962 {
3963 inst.error = _("pc may not be used in post-increment");
3964 return FAIL;
3965 }
3966
3967 if (cp_byte_address_offset (& p) == FAIL)
3968 return FAIL;
3969 }
3970 else
3971 pre_inc = PRE_INDEX | INDEX_UP;
3972 }
3973 else
3974 {
3975 /* '['Rn, #expr']'[!] */
3976
3977 if (skip_past_comma (& p) == FAIL)
3978 {
3979 inst.error = _("pre-indexed expression expected");
3980 return FAIL;
3981 }
3982
3983 pre_inc = PRE_INDEX;
3984
3985 if (cp_byte_address_offset (& p) == FAIL)
3986 return FAIL;
3987
3988 skip_whitespace (p);
3989
3990 if (*p++ != ']')
3991 {
3992 inst.error = _("missing ]");
3993 return FAIL;
3994 }
3995
3996 skip_whitespace (p);
3997
3998 if (*p == '!')
3999 {
4000 if (reg == REG_PC)
4001 {
4002 inst.error = _("pc may not be used with write-back");
4003 return FAIL;
4004 }
4005
4006 p++;
4007 write_back = WRITE_BACK;
4008 }
4009 }
4010 }
4011 else
4012 {
4013 if (my_get_expression (&inst.reloc.exp, &p))
4014 return FAIL;
4015
4016 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4017 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4018 inst.reloc.pc_rel = 1;
4019 inst.instruction |= (REG_PC << 16);
4020 pre_inc = PRE_INDEX;
4021 }
4022
4023 inst.instruction |= write_back | pre_inc;
4024 *str = p;
4025 return SUCCESS;
4026}
4027
b99bd4ef 4028static void
f2b7cb0a 4029do_empty (str)
b99bd4ef 4030 char * str;
b99bd4ef
NC
4031{
4032 /* Do nothing really. */
b99bd4ef
NC
4033 end_of_line (str);
4034 return;
4035}
4036
4037static void
f2b7cb0a 4038do_mrs (str)
b99bd4ef 4039 char *str;
b99bd4ef
NC
4040{
4041 int skip = 0;
4042
4043 /* Only one syntax. */
4044 skip_whitespace (str);
4045
4046 if (reg_required_here (&str, 12) == FAIL)
4047 {
4048 inst.error = BAD_ARGS;
4049 return;
4050 }
4051
4052 if (skip_past_comma (&str) == FAIL)
4053 {
4054 inst.error = _("comma expected after register name");
4055 return;
4056 }
4057
4058 skip_whitespace (str);
4059
4060 if ( strcmp (str, "CPSR") == 0
4061 || strcmp (str, "SPSR") == 0
2d2255b5 4062 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4063 || strcmp (str, "cpsr") == 0
4064 || strcmp (str, "spsr") == 0)
4065 skip = 4;
4066
2d2255b5 4067 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4068 else if ( strcmp (str, "cpsr_all") == 0
4069 || strcmp (str, "spsr_all") == 0)
4070 skip = 8;
4071 else
4072 {
f03698e6 4073 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4074 return;
4075 }
4076
4077 if (* str == 's' || * str == 'S')
4078 inst.instruction |= SPSR_BIT;
4079 str += skip;
4080
b99bd4ef
NC
4081 end_of_line (str);
4082}
4083
4084/* Two possible forms:
4085 "{C|S}PSR_<field>, Rm",
4086 "{C|S}PSR_f, #expression". */
4087
4088static void
f2b7cb0a 4089do_msr (str)
b99bd4ef 4090 char * str;
b99bd4ef
NC
4091{
4092 skip_whitespace (str);
4093
4094 if (psr_required_here (& str) == FAIL)
4095 return;
4096
4097 if (skip_past_comma (& str) == FAIL)
4098 {
4099 inst.error = _("comma missing after psr flags");
4100 return;
4101 }
4102
4103 skip_whitespace (str);
4104
4105 if (reg_required_here (& str, 0) != FAIL)
4106 {
4107 inst.error = NULL;
b99bd4ef
NC
4108 end_of_line (str);
4109 return;
4110 }
4111
4112 if (! is_immediate_prefix (* str))
4113 {
4114 inst.error =
4115 _("only a register or immediate value can follow a psr flag");
4116 return;
4117 }
4118
4119 str ++;
4120 inst.error = NULL;
4121
4122 if (my_get_expression (& inst.reloc.exp, & str))
4123 {
4124 inst.error =
4125 _("only a register or immediate value can follow a psr flag");
4126 return;
4127 }
4128
4129#if 0 /* The first edition of the ARM architecture manual stated that
4130 writing anything other than the flags with an immediate operation
4131 had UNPREDICTABLE effects. This constraint was removed in the
4132 second edition of the specification. */
4133 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4134 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4135 {
4136 inst.error = _("immediate value cannot be used to set this field");
4137 return;
4138 }
4139#endif
4140
f2b7cb0a 4141 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4142
4143 if (inst.reloc.exp.X_add_symbol)
4144 {
4145 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4146 inst.reloc.pc_rel = 0;
4147 }
4148 else
4149 {
4150 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4151
4152 if (value == (unsigned) FAIL)
4153 {
f03698e6 4154 inst.error = _("invalid constant");
b99bd4ef
NC
4155 return;
4156 }
4157
4158 inst.instruction |= value;
4159 }
4160
4161 inst.error = NULL;
b99bd4ef
NC
4162 end_of_line (str);
4163}
4164
4165/* Long Multiply Parser
4166 UMULL RdLo, RdHi, Rm, Rs
4167 SMULL RdLo, RdHi, Rm, Rs
4168 UMLAL RdLo, RdHi, Rm, Rs
4169 SMLAL RdLo, RdHi, Rm, Rs. */
4170
4171static void
f2b7cb0a 4172do_mull (str)
b99bd4ef 4173 char * str;
b99bd4ef
NC
4174{
4175 int rdlo, rdhi, rm, rs;
4176
4177 /* Only one format "rdlo, rdhi, rm, rs". */
4178 skip_whitespace (str);
4179
4180 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4181 {
4182 inst.error = BAD_ARGS;
4183 return;
4184 }
4185
4186 if (skip_past_comma (&str) == FAIL
4187 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4188 {
4189 inst.error = BAD_ARGS;
4190 return;
4191 }
4192
4193 if (skip_past_comma (&str) == FAIL
4194 || (rm = reg_required_here (&str, 0)) == FAIL)
4195 {
4196 inst.error = BAD_ARGS;
4197 return;
4198 }
4199
4200 /* rdhi, rdlo and rm must all be different. */
4201 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4202 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4203
4204 if (skip_past_comma (&str) == FAIL
4205 || (rs = reg_required_here (&str, 8)) == FAIL)
4206 {
4207 inst.error = BAD_ARGS;
4208 return;
4209 }
4210
4211 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4212 {
4213 inst.error = BAD_PC;
4214 return;
4215 }
4216
b99bd4ef
NC
4217 end_of_line (str);
4218 return;
4219}
4220
4221static void
f2b7cb0a 4222do_mul (str)
b99bd4ef 4223 char * str;
b99bd4ef
NC
4224{
4225 int rd, rm;
4226
4227 /* Only one format "rd, rm, rs". */
4228 skip_whitespace (str);
4229
4230 if ((rd = reg_required_here (&str, 16)) == FAIL)
4231 {
4232 inst.error = BAD_ARGS;
4233 return;
4234 }
4235
4236 if (rd == REG_PC)
4237 {
4238 inst.error = BAD_PC;
4239 return;
4240 }
4241
4242 if (skip_past_comma (&str) == FAIL
4243 || (rm = reg_required_here (&str, 0)) == FAIL)
4244 {
4245 inst.error = BAD_ARGS;
4246 return;
4247 }
4248
4249 if (rm == REG_PC)
4250 {
4251 inst.error = BAD_PC;
4252 return;
4253 }
4254
4255 if (rm == rd)
4256 as_tsktsk (_("rd and rm should be different in mul"));
4257
4258 if (skip_past_comma (&str) == FAIL
4259 || (rm = reg_required_here (&str, 8)) == FAIL)
4260 {
4261 inst.error = BAD_ARGS;
4262 return;
4263 }
4264
4265 if (rm == REG_PC)
4266 {
4267 inst.error = BAD_PC;
4268 return;
4269 }
4270
b99bd4ef
NC
4271 end_of_line (str);
4272 return;
4273}
4274
4275static void
f2b7cb0a 4276do_mla (str)
b99bd4ef 4277 char * str;
b99bd4ef
NC
4278{
4279 int rd, rm;
4280
4281 /* Only one format "rd, rm, rs, rn". */
4282 skip_whitespace (str);
4283
4284 if ((rd = reg_required_here (&str, 16)) == FAIL)
4285 {
4286 inst.error = BAD_ARGS;
4287 return;
4288 }
4289
4290 if (rd == REG_PC)
4291 {
4292 inst.error = BAD_PC;
4293 return;
4294 }
4295
4296 if (skip_past_comma (&str) == FAIL
4297 || (rm = reg_required_here (&str, 0)) == FAIL)
4298 {
4299 inst.error = BAD_ARGS;
4300 return;
4301 }
4302
4303 if (rm == REG_PC)
4304 {
4305 inst.error = BAD_PC;
4306 return;
4307 }
4308
4309 if (rm == rd)
4310 as_tsktsk (_("rd and rm should be different in mla"));
4311
4312 if (skip_past_comma (&str) == FAIL
4313 || (rd = reg_required_here (&str, 8)) == FAIL
4314 || skip_past_comma (&str) == FAIL
4315 || (rm = reg_required_here (&str, 12)) == FAIL)
4316 {
4317 inst.error = BAD_ARGS;
4318 return;
4319 }
4320
4321 if (rd == REG_PC || rm == REG_PC)
4322 {
4323 inst.error = BAD_PC;
4324 return;
4325 }
4326
b99bd4ef
NC
4327 end_of_line (str);
4328 return;
4329}
4330
4331/* Expects *str -> the characters "acc0", possibly with leading blanks.
4332 Advances *str to the next non-alphanumeric.
4333 Returns 0, or else FAIL (in which case sets inst.error).
4334
4335 (In a future XScale, there may be accumulators other than zero.
4336 At that time this routine and its callers can be upgraded to suit.) */
4337
4338static int
4339accum0_required_here (str)
4340 char ** str;
4341{
4342 static char buff [128]; /* Note the address is taken. Hence, static. */
4343 char * p = * str;
4344 char c;
4345 int result = 0; /* The accum number. */
4346
4347 skip_whitespace (p);
4348
4349 *str = p; /* Advance caller's string pointer too. */
4350 c = *p++;
3882b010 4351 while (ISALNUM (c))
b99bd4ef
NC
4352 c = *p++;
4353
4354 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4355
4356 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4357 {
4358 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4359 inst.error = buff;
4360 result = FAIL;
4361 }
4362
4363 *p = c; /* Unzap. */
4364 *str = p; /* Caller's string pointer to after match. */
4365 return result;
4366}
4367
4368/* Expects **str -> after a comma. May be leading blanks.
4369 Advances *str, recognizing a load mode, and setting inst.instruction.
4370 Returns rn, or else FAIL (in which case may set inst.error
4371 and not advance str)
4372
4373 Note: doesn't know Rd, so no err checks that require such knowledge. */
4374
4375static int
4376ld_mode_required_here (string)
4377 char ** string;
4378{
4379 char * str = * string;
4380 int rn;
4381 int pre_inc = 0;
4382
4383 skip_whitespace (str);
4384
4385 if (* str == '[')
4386 {
4387 str++;
4388
4389 skip_whitespace (str);
4390
4391 if ((rn = reg_required_here (& str, 16)) == FAIL)
4392 return FAIL;
4393
4394 skip_whitespace (str);
4395
4396 if (* str == ']')
4397 {
4398 str ++;
4399
4400 if (skip_past_comma (& str) == SUCCESS)
4401 {
4402 /* [Rn],... (post inc) */
90e4755a 4403 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4404 return FAIL;
4405 }
4406 else /* [Rn] */
4407 {
cc8a6dd0 4408 skip_whitespace (str);
b99bd4ef 4409
cc8a6dd0
KH
4410 if (* str == '!')
4411 {
4412 str ++;
4413 inst.instruction |= WRITE_BACK;
4414 }
b99bd4ef
NC
4415
4416 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4417 pre_inc = 1;
4418 }
4419 }
4420 else /* [Rn,...] */
4421 {
4422 if (skip_past_comma (& str) == FAIL)
4423 {
4424 inst.error = _("pre-indexed expression expected");
4425 return FAIL;
4426 }
4427
4428 pre_inc = 1;
4429
90e4755a 4430 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4431 return FAIL;
4432
4433 skip_whitespace (str);
4434
4435 if (* str ++ != ']')
4436 {
4437 inst.error = _("missing ]");
4438 return FAIL;
4439 }
4440
4441 skip_whitespace (str);
4442
4443 if (* str == '!')
4444 {
4445 str ++;
4446 inst.instruction |= WRITE_BACK;
4447 }
4448 }
4449 }
4450 else if (* str == '=') /* ldr's "r,=label" syntax */
4451 /* We should never reach here, because <text> = <expression> is
4452 caught gas/read.c read_a_source_file() as a .set operation. */
4453 return FAIL;
4454 else /* PC +- 8 bit immediate offset. */
4455 {
4456 if (my_get_expression (& inst.reloc.exp, & str))
4457 return FAIL;
4458
4459 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4460 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4461 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4462 inst.reloc.pc_rel = 1;
4463 inst.instruction |= (REG_PC << 16);
4464
4465 rn = REG_PC;
4466 pre_inc = 1;
4467 }
4468
4469 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4470 * string = str;
4471
4472 return rn;
4473}
4474
4475/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4476 SMLAxy{cond} Rd,Rm,Rs,Rn
4477 SMLAWy{cond} Rd,Rm,Rs,Rn
4478 Error if any register is R15. */
4479
4480static void
f2b7cb0a 4481do_smla (str)
b99bd4ef 4482 char * str;
b99bd4ef
NC
4483{
4484 int rd, rm, rs, rn;
4485
4486 skip_whitespace (str);
4487
4488 if ((rd = reg_required_here (& str, 16)) == FAIL
4489 || skip_past_comma (& str) == FAIL
4490 || (rm = reg_required_here (& str, 0)) == FAIL
4491 || skip_past_comma (& str) == FAIL
4492 || (rs = reg_required_here (& str, 8)) == FAIL
4493 || skip_past_comma (& str) == FAIL
4494 || (rn = reg_required_here (& str, 12)) == FAIL)
4495 inst.error = BAD_ARGS;
4496
4497 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4498 inst.error = BAD_PC;
4499
b99bd4ef
NC
4500 else
4501 end_of_line (str);
4502}
4503
4504/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4505 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4506 Error if any register is R15.
4507 Warning if Rdlo == Rdhi. */
4508
4509static void
f2b7cb0a 4510do_smlal (str)
b99bd4ef 4511 char * str;
b99bd4ef
NC
4512{
4513 int rdlo, rdhi, rm, rs;
4514
4515 skip_whitespace (str);
4516
4517 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4518 || skip_past_comma (& str) == FAIL
4519 || (rdhi = reg_required_here (& str, 16)) == FAIL
4520 || skip_past_comma (& str) == FAIL
4521 || (rm = reg_required_here (& str, 0)) == FAIL
4522 || skip_past_comma (& str) == FAIL
4523 || (rs = reg_required_here (& str, 8)) == FAIL)
4524 {
4525 inst.error = BAD_ARGS;
4526 return;
4527 }
4528
4529 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4530 {
4531 inst.error = BAD_PC;
4532 return;
4533 }
4534
4535 if (rdlo == rdhi)
4536 as_tsktsk (_("rdhi and rdlo must be different"));
4537
f2b7cb0a 4538 end_of_line (str);
b99bd4ef
NC
4539}
4540
4541/* ARM V5E (El Segundo) signed-multiply (argument parse)
4542 SMULxy{cond} Rd,Rm,Rs
4543 Error if any register is R15. */
4544
4545static void
f2b7cb0a 4546do_smul (str)
b99bd4ef 4547 char * str;
b99bd4ef
NC
4548{
4549 int rd, rm, rs;
4550
4551 skip_whitespace (str);
4552
4553 if ((rd = reg_required_here (& str, 16)) == FAIL
4554 || skip_past_comma (& str) == FAIL
4555 || (rm = reg_required_here (& str, 0)) == FAIL
4556 || skip_past_comma (& str) == FAIL
4557 || (rs = reg_required_here (& str, 8)) == FAIL)
4558 inst.error = BAD_ARGS;
4559
4560 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4561 inst.error = BAD_PC;
4562
b99bd4ef
NC
4563 else
4564 end_of_line (str);
4565}
4566
4567/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4568 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4569 Error if any register is R15. */
4570
4571static void
f2b7cb0a 4572do_qadd (str)
b99bd4ef 4573 char * str;
b99bd4ef
NC
4574{
4575 int rd, rm, rn;
4576
4577 skip_whitespace (str);
4578
4579 if ((rd = reg_required_here (& str, 12)) == FAIL
4580 || skip_past_comma (& str) == FAIL
4581 || (rm = reg_required_here (& str, 0)) == FAIL
4582 || skip_past_comma (& str) == FAIL
4583 || (rn = reg_required_here (& str, 16)) == FAIL)
4584 inst.error = BAD_ARGS;
4585
4586 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4587 inst.error = BAD_PC;
4588
b99bd4ef
NC
4589 else
4590 end_of_line (str);
4591}
4592
4593/* ARM V5E (el Segundo)
4594 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4595 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4596
4597 These are equivalent to the XScale instructions MAR and MRA,
4598 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4599
4600 Result unpredicatable if Rd or Rn is R15. */
4601
4602static void
f2b7cb0a 4603do_co_reg2c (str)
b99bd4ef 4604 char * str;
b99bd4ef
NC
4605{
4606 int rd, rn;
4607
4608 skip_whitespace (str);
4609
4610 if (co_proc_number (& str) == FAIL)
4611 {
4612 if (!inst.error)
4613 inst.error = BAD_ARGS;
4614 return;
4615 }
4616
4617 if (skip_past_comma (& str) == FAIL
4618 || cp_opc_expr (& str, 4, 4) == FAIL)
4619 {
4620 if (!inst.error)
4621 inst.error = BAD_ARGS;
4622 return;
4623 }
4624
4625 if (skip_past_comma (& str) == FAIL
4626 || (rd = reg_required_here (& str, 12)) == FAIL)
4627 {
4628 if (!inst.error)
4629 inst.error = BAD_ARGS;
4630 return;
4631 }
4632
4633 if (skip_past_comma (& str) == FAIL
4634 || (rn = reg_required_here (& str, 16)) == FAIL)
4635 {
4636 if (!inst.error)
4637 inst.error = BAD_ARGS;
4638 return;
4639 }
4640
09d92015
MM
4641 /* Unpredictable result if rd or rn is R15. */
4642 if (rd == REG_PC || rn == REG_PC)
4643 as_tsktsk
4644 (_("Warning: instruction unpredictable when using r15"));
4645
4646 if (skip_past_comma (& str) == FAIL
4647 || cp_reg_required_here (& str, 0) == FAIL)
4648 {
4649 if (!inst.error)
4650 inst.error = BAD_ARGS;
4651 return;
4652 }
4653
4654 end_of_line (str);
4655}
4656
4657/* ARM V5 count-leading-zeroes instruction (argument parse)
4658 CLZ{<cond>} <Rd>, <Rm>
4659 Condition defaults to COND_ALWAYS.
4660 Error if Rd or Rm are R15. */
4661
4662static void
4663do_clz (str)
4664 char * str;
4665{
4666 int rd, rm;
4667
4668 skip_whitespace (str);
4669
4670 if (((rd = reg_required_here (& str, 12)) == FAIL)
4671 || (skip_past_comma (& str) == FAIL)
4672 || ((rm = reg_required_here (& str, 0)) == FAIL))
4673 inst.error = BAD_ARGS;
4674
4675 else if (rd == REG_PC || rm == REG_PC )
4676 inst.error = BAD_PC;
4677
4678 else
4679 end_of_line (str);
4680}
4681
4682/* ARM V5 (argument parse)
4683 LDC2{L} <coproc>, <CRd>, <addressing mode>
4684 STC2{L} <coproc>, <CRd>, <addressing mode>
4685 Instruction is not conditional, and has 0xf in the condition field.
4686 Otherwise, it's the same as LDC/STC. */
4687
4688static void
4689do_lstc2 (str)
4690 char * str;
4691{
4692 skip_whitespace (str);
4693
4694 if (co_proc_number (& str) == FAIL)
4695 {
4696 if (!inst.error)
4697 inst.error = BAD_ARGS;
4698 }
4699 else if (skip_past_comma (& str) == FAIL
4700 || cp_reg_required_here (& str, 12) == FAIL)
4701 {
4702 if (!inst.error)
4703 inst.error = BAD_ARGS;
4704 }
4705 else if (skip_past_comma (& str) == FAIL
4706 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4707 {
4708 if (! inst.error)
4709 inst.error = BAD_ARGS;
4710 }
4711 else
4712 end_of_line (str);
4713}
4714
4715/* ARM V5 (argument parse)
4716 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4717 Instruction is not conditional, and has 0xf in the condition field.
4718 Otherwise, it's the same as CDP. */
4719
4720static void
4721do_cdp2 (str)
4722 char * str;
4723{
4724 skip_whitespace (str);
4725
4726 if (co_proc_number (& str) == FAIL)
4727 {
4728 if (!inst.error)
4729 inst.error = BAD_ARGS;
4730 return;
4731 }
4732
4733 if (skip_past_comma (& str) == FAIL
4734 || cp_opc_expr (& str, 20,4) == FAIL)
4735 {
4736 if (!inst.error)
4737 inst.error = BAD_ARGS;
4738 return;
4739 }
4740
4741 if (skip_past_comma (& str) == FAIL
4742 || cp_reg_required_here (& str, 12) == 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, 16) == 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, 0) == FAIL)
4759 {
4760 if (!inst.error)
4761 inst.error = BAD_ARGS;
4762 return;
4763 }
4764
4765 if (skip_past_comma (& str) == SUCCESS)
4766 {
4767 if (cp_opc_expr (& str, 5, 3) == FAIL)
4768 {
4769 if (!inst.error)
4770 inst.error = BAD_ARGS;
4771 return;
4772 }
4773 }
4774
4775 end_of_line (str);
4776}
4777
4778/* ARM V5 (argument parse)
4779 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4780 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4781 Instruction is not conditional, and has 0xf in the condition field.
4782 Otherwise, it's the same as MCR/MRC. */
4783
4784static void
4785do_co_reg2 (str)
4786 char * str;
4787{
4788 skip_whitespace (str);
4789
4790 if (co_proc_number (& str) == FAIL)
4791 {
4792 if (!inst.error)
4793 inst.error = BAD_ARGS;
4794 return;
4795 }
4796
4797 if (skip_past_comma (& str) == FAIL
4798 || cp_opc_expr (& str, 21, 3) == FAIL)
4799 {
4800 if (!inst.error)
4801 inst.error = BAD_ARGS;
4802 return;
4803 }
4804
4805 if (skip_past_comma (& str) == FAIL
4806 || reg_required_here (& str, 12) == FAIL)
4807 {
4808 if (!inst.error)
4809 inst.error = BAD_ARGS;
4810 return;
4811 }
4812
4813 if (skip_past_comma (& str) == FAIL
4814 || cp_reg_required_here (& str, 16) == 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, 0) == FAIL)
4823 {
4824 if (!inst.error)
4825 inst.error = BAD_ARGS;
4826 return;
4827 }
4828
4829 if (skip_past_comma (& str) == SUCCESS)
4830 {
4831 if (cp_opc_expr (& str, 5, 3) == FAIL)
4832 {
4833 if (!inst.error)
4834 inst.error = BAD_ARGS;
4835 return;
4836 }
4837 }
4838
4839 end_of_line (str);
4840}
4841
4842/* ARM v5TEJ. Jump to Jazelle code. */
4843static void
4844do_bxj (str)
4845 char * str;
4846{
4847 int reg;
4848
4849 skip_whitespace (str);
4850
4851 if ((reg = reg_required_here (&str, 0)) == FAIL)
4852 {
4853 inst.error = BAD_ARGS;
4854 return;
4855 }
4856
4857 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4858 if (reg == REG_PC)
4859 as_tsktsk (_("use of r15 in bxj is not really useful"));
4860
4861 end_of_line (str);
4862}
4863
4864/* ARM V6 umaal (argument parse). */
4865
4866static void
4867do_umaal (str)
4868 char *str;
4869{
4870
4871 int rdlo, rdhi, rm, rs;
4872
4873 skip_whitespace (str);
4874 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4875 || skip_past_comma (& str) == FAIL
4876 || (rdhi = reg_required_here (& str, 16)) == FAIL
4877 || skip_past_comma (& str) == FAIL
4878 || (rm = reg_required_here (& str, 0)) == FAIL
4879 || skip_past_comma (& str) == FAIL
4880 || (rm = reg_required_here (& str, 8)) == FAIL)
4881 {
4882 inst.error = BAD_ARGS;
4883 return;
4884 }
4885
4886 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4887 {
4888 inst.error = BAD_PC;
4889 return;
4890 }
4891
4892 end_of_line (str);
4893}
4894
4895/* ARM V6 strex (argument parse). */
4896
4897static void
4898do_strex (str)
4899 char *str;
4900{
4901 int rd, rm, rn;
4902
4903 /* Parse Rd, Rm,. */
4904 skip_whitespace (str);
4905 if ((rd = reg_required_here (& str, 12)) == FAIL
4906 || skip_past_comma (& str) == FAIL
4907 || (rm = reg_required_here (& str, 0)) == FAIL
4908 || skip_past_comma (& str) == FAIL)
4909 {
4910 inst.error = BAD_ARGS;
4911 return;
4912 }
4913 if (rd == REG_PC || rm == REG_PC)
4914 {
4915 inst.error = BAD_PC;
4916 return;
4917 }
4918 if (rd == rm)
4919 {
4920 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4921 return;
4922 }
4923
4924 /* Skip past '['. */
4925 if ((strlen (str) >= 1)
4926 && strncmp (str, "[", 1) == 0)
4927 str+=1;
4928 skip_whitespace (str);
4929
4930 /* Parse Rn. */
4931 if ((rn = reg_required_here (& str, 16)) == FAIL)
4932 {
4933 inst.error = BAD_ARGS;
4934 return;
4935 }
4936 else if (rn == REG_PC)
4937 {
4938 inst.error = BAD_PC;
4939 return;
4940 }
4941 if (rd == rn)
4942 {
4943 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4944 return;
4945 }
4946 skip_whitespace (str);
4947
4948 /* Skip past ']'. */
4949 if ((strlen (str) >= 1)
4950 && strncmp (str, "]", 1) == 0)
4951 str+=1;
4952
4953 end_of_line (str);
4954}
4955
4956/* ARM V6 ssat (argument parse). */
4957
4958static void
4959do_ssat (str)
4960 char* str;
4961{
4962 do_sat (&str, /*bias=*/-1);
4963 end_of_line (str);
4964}
4965
4966/* ARM V6 usat (argument parse). */
4967
4968static void
4969do_usat (str)
4970 char* str;
4971{
4972 do_sat (&str, /*bias=*/0);
4973 end_of_line (str);
4974}
4975
4976static void
4977do_sat (str, bias)
4978 char **str;
4979 int bias;
4980{
4981 int rd, rm;
4982 expressionS expr;
4983
4984 skip_whitespace (*str);
4985
4986 /* Parse <Rd>, field. */
4987 if ((rd = reg_required_here (str, 12)) == FAIL
4988 || skip_past_comma (str) == FAIL)
4989 {
4990 inst.error = BAD_ARGS;
4991 return;
4992 }
4993 if (rd == REG_PC)
4994 {
4995 inst.error = BAD_PC;
4996 return;
4997 }
4998
4999 /* Parse #<immed>, field. */
5000 if (is_immediate_prefix (**str))
5001 (*str)++;
5002 else
5003 {
5004 inst.error = _("immediate expression expected");
5005 return;
5006 }
5007 if (my_get_expression (&expr, str))
5008 {
5009 inst.error = _("bad expression");
5010 return;
5011 }
5012 if (expr.X_op != O_constant)
5013 {
5014 inst.error = _("constant expression expected");
5015 return;
5016 }
5017 if (expr.X_add_number + bias < 0
5018 || expr.X_add_number + bias > 31)
5019 {
5020 inst.error = _("immediate value out of range");
5021 return;
5022 }
5023 inst.instruction |= (expr.X_add_number + bias) << 16;
5024 if (skip_past_comma (str) == FAIL)
5025 {
5026 inst.error = BAD_ARGS;
5027 return;
5028 }
5029
5030 /* Parse <Rm> field. */
5031 if ((rm = reg_required_here (str, 0)) == FAIL)
5032 {
5033 inst.error = BAD_ARGS;
5034 return;
5035 }
5036 if (rm == REG_PC)
5037 {
5038 inst.error = BAD_PC;
5039 return;
5040 }
5041
5042 if (skip_past_comma (str) == SUCCESS)
5043 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5044}
5045
5046/* ARM V6 ssat16 (argument parse). */
5047
5048static void
5049do_ssat16 (str)
5050 char *str;
5051{
5052 do_sat16 (&str, /*bias=*/-1);
5053 end_of_line (str);
5054}
5055
5056static void
5057do_usat16 (str)
5058 char *str;
5059{
5060 do_sat16 (&str, /*bias=*/0);
5061 end_of_line (str);
5062}
5063
5064static void
5065do_sat16 (str, bias)
5066 char **str;
5067 int bias;
5068{
5069 int rd, rm;
5070 expressionS expr;
5071
5072 skip_whitespace (*str);
5073
5074 /* Parse the <Rd> field. */
5075 if ((rd = reg_required_here (str, 12)) == FAIL
5076 || skip_past_comma (str) == FAIL)
5077 {
5078 inst.error = BAD_ARGS;
5079 return;
5080 }
5081 if (rd == REG_PC)
5082 {
5083 inst.error = BAD_PC;
5084 return;
5085 }
5086
5087 /* Parse #<immed>, field. */
5088 if (is_immediate_prefix (**str))
5089 (*str)++;
5090 else
5091 {
5092 inst.error = _("immediate expression expected");
5093 return;
5094 }
5095 if (my_get_expression (&expr, str))
5096 {
5097 inst.error = _("bad expression");
5098 return;
5099 }
5100 if (expr.X_op != O_constant)
5101 {
5102 inst.error = _("constant expression expected");
5103 return;
5104 }
5105 if (expr.X_add_number + bias < 0
5106 || expr.X_add_number + bias > 15)
5107 {
5108 inst.error = _("immediate value out of range");
5109 return;
5110 }
5111 inst.instruction |= (expr.X_add_number + bias) << 16;
5112 if (skip_past_comma (str) == FAIL)
5113 {
5114 inst.error = BAD_ARGS;
5115 return;
5116 }
5117
5118 /* Parse <Rm> field. */
5119 if ((rm = reg_required_here (str, 0)) == FAIL)
5120 {
5121 inst.error = BAD_ARGS;
5122 return;
5123 }
5124 if (rm == REG_PC)
5125 {
5126 inst.error = BAD_PC;
5127 return;
5128 }
5129}
5130
5131/* ARM V6 srs (argument parse). */
5132
5133static void
5134do_srs (str)
5135 char* str;
5136{
5137 char *exclam;
5138 skip_whitespace (str);
5139 exclam = strchr (str, '!');
5140 if (exclam)
5141 *exclam = '\0';
5142 do_cps_mode (&str);
5143 if (exclam)
5144 *exclam = '!';
5145 if (*str == '!')
5146 {
5147 inst.instruction |= WRITE_BACK;
5148 str++;
5149 }
5150 end_of_line (str);
5151}
5152
5153/* ARM V6 SMMUL (argument parse). */
5154
5155static void
5156do_smmul (str)
5157 char* str;
5158{
5159 int rd, rm, rs;
5160
5161 skip_whitespace (str);
5162 if ((rd = reg_required_here (&str, 16)) == FAIL
5163 || skip_past_comma (&str) == FAIL
5164 || (rm = reg_required_here (&str, 0)) == FAIL
5165 || skip_past_comma (&str) == FAIL
5166 || (rs = reg_required_here (&str, 8)) == FAIL)
5167 {
5168 inst.error = BAD_ARGS;
5169 return;
5170 }
5171
5172 if (rd == REG_PC
5173 || rm == REG_PC
5174 || rs == REG_PC)
5175 {
5176 inst.error = BAD_PC;
5177 return;
5178 }
5179
5180 end_of_line (str);
5181
5182}
5183
5184/* ARM V6 SMLALD (argument parse). */
5185
5186static void
5187do_smlald (str)
5188 char* str;
5189{
5190 int rdlo, rdhi, rm, rs;
5191 skip_whitespace (str);
5192 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5193 || skip_past_comma (&str) == FAIL
5194 || (rdhi = reg_required_here (&str, 16)) == FAIL
5195 || skip_past_comma (&str) == FAIL
5196 || (rm = reg_required_here (&str, 0)) == FAIL
5197 || skip_past_comma (&str) == FAIL
5198 || (rs = reg_required_here (&str, 8)) == FAIL)
5199 {
5200 inst.error = BAD_ARGS;
5201 return;
5202 }
5203
5204 if (rdlo == REG_PC
5205 || rdhi == REG_PC
5206 || rm == REG_PC
5207 || rs == REG_PC)
5208 {
5209 inst.error = BAD_PC;
5210 return;
5211 }
5212
5213 end_of_line (str);
5214}
5215
5216/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5217 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5218
5219static void
5220do_smlad (str)
5221 char *str;
5222{
5223 int rd, rm, rs, rn;
5224
5225 skip_whitespace (str);
5226 if ((rd = reg_required_here (&str, 16)) == FAIL
5227 || skip_past_comma (&str) == FAIL
5228 || (rm = reg_required_here (&str, 0)) == FAIL
5229 || skip_past_comma (&str) == FAIL
5230 || (rs = reg_required_here (&str, 8)) == FAIL
5231 || skip_past_comma (&str) == FAIL
5232 || (rn = reg_required_here (&str, 12)) == FAIL)
5233 {
5234 inst.error = BAD_ARGS;
5235 return;
5236 }
5237
5238 if (rd == REG_PC
5239 || rn == REG_PC
5240 || rs == REG_PC
5241 || rm == REG_PC)
5242 {
5243 inst.error = BAD_PC;
5244 return;
5245 }
5246
5247 end_of_line (str);
5248}
5249
5250/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5251 preserving the other bits.
5252
5253 setend <endian_specifier>, where <endian_specifier> is either
5254 BE or LE. */
5255
5256static void
5257do_setend (str)
5258 char *str;
5259{
5260 if (do_endian_specifier (str))
5261 inst.instruction |= 0x200;
5262}
5263
5264/* Returns true if the endian-specifier indicates big-endianness. */
5265
5266static int
5267do_endian_specifier (str)
5268 char *str;
5269{
5270 int big_endian = 0;
5271
5272 skip_whitespace (str);
5273 if (strlen (str) < 2)
5274 inst.error = _("missing endian specifier");
5275 else if (strncasecmp (str, "BE", 2) == 0)
5276 {
5277 str += 2;
5278 big_endian = 1;
5279 }
5280 else if (strncasecmp (str, "LE", 2) == 0)
5281 str += 2;
5282 else
5283 inst.error = _("valid endian specifiers are be or le");
5284
5285 end_of_line (str);
5286
5287 return big_endian;
5288}
5289
5290/* ARM V6 SXTH.
5291
5292 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5293 Condition defaults to COND_ALWAYS.
5294 Error if any register uses R15. */
5295
5296static void
5297do_sxth (str)
5298 char *str;
5299{
5300 int rd, rm;
5301 expressionS expr;
5302 int rotation_clear_mask = 0xfffff3ff;
5303 int rotation_eight_mask = 0x00000400;
5304 int rotation_sixteen_mask = 0x00000800;
5305 int rotation_twenty_four_mask = 0x00000c00;
5306
5307 skip_whitespace (str);
5308 if ((rd = reg_required_here (&str, 12)) == FAIL
5309 || skip_past_comma (&str) == FAIL
5310 || (rm = reg_required_here (&str, 0)) == FAIL)
5311 {
5312 inst.error = BAD_ARGS;
5313 return;
5314 }
5315
5316 else if (rd == REG_PC || rm == REG_PC)
5317 {
5318 inst.error = BAD_PC;
5319 return;
5320 }
5321
5322 /* Zero out the rotation field. */
5323 inst.instruction &= rotation_clear_mask;
5324
5325 /* Check for lack of optional rotation field. */
5326 if (skip_past_comma (&str) == FAIL)
5327 {
5328 end_of_line (str);
5329 return;
5330 }
5331
5332 /* Move past 'ROR'. */
5333 skip_whitespace (str);
5334 if (strncasecmp (str, "ROR", 3) == 0)
5335 str+=3;
5336 else
5337 {
5338 inst.error = _("missing rotation field after comma");
5339 return;
5340 }
5341
5342 /* Get the immediate constant. */
5343 skip_whitespace (str);
5344 if (is_immediate_prefix (* str))
5345 str++;
5346 else
5347 {
5348 inst.error = _("immediate expression expected");
5349 return;
5350 }
5351
5352 if (my_get_expression (&expr, &str))
5353 {
5354 inst.error = _("bad expression");
5355 return;
5356 }
5357
5358 if (expr.X_op != O_constant)
5359 {
5360 inst.error = _("constant expression expected");
5361 return;
5362 }
5363
5364 switch (expr.X_add_number)
5365 {
5366 case 0:
5367 /* Rotation field has already been zeroed. */
5368 break;
5369 case 8:
5370 inst.instruction |= rotation_eight_mask;
5371 break;
5372
5373 case 16:
5374 inst.instruction |= rotation_sixteen_mask;
5375 break;
5376
5377 case 24:
5378 inst.instruction |= rotation_twenty_four_mask;
5379 break;
5380
5381 default:
5382 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5383 break;
5384 }
5385
5386 end_of_line (str);
5387
5388}
5389
5390/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5391 extends it to 32-bits, and adds the result to a value in another
5392 register. You can specify a rotation by 0, 8, 16, or 24 bits
5393 before extracting the 16-bit value.
5394 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5395 Condition defaults to COND_ALWAYS.
5396 Error if any register uses R15. */
5397
5398static void
5399do_sxtah (str)
5400 char *str;
5401{
5402 int rd, rn, rm;
5403 expressionS expr;
5404 int rotation_clear_mask = 0xfffff3ff;
5405 int rotation_eight_mask = 0x00000400;
5406 int rotation_sixteen_mask = 0x00000800;
5407 int rotation_twenty_four_mask = 0x00000c00;
5408
5409 skip_whitespace (str);
5410 if ((rd = reg_required_here (&str, 12)) == FAIL
5411 || skip_past_comma (&str) == FAIL
5412 || (rn = reg_required_here (&str, 16)) == FAIL
5413 || skip_past_comma (&str) == FAIL
5414 || (rm = reg_required_here (&str, 0)) == FAIL)
5415 {
5416 inst.error = BAD_ARGS;
5417 return;
5418 }
5419
5420 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5421 {
5422 inst.error = BAD_PC;
5423 return;
5424 }
5425
5426 /* Zero out the rotation field. */
5427 inst.instruction &= rotation_clear_mask;
5428
5429 /* Check for lack of optional rotation field. */
5430 if (skip_past_comma (&str) == FAIL)
5431 {
5432 end_of_line (str);
5433 return;
5434 }
5435
5436 /* Move past 'ROR'. */
5437 skip_whitespace (str);
5438 if (strncasecmp (str, "ROR", 3) == 0)
5439 str+=3;
5440 else
5441 {
5442 inst.error = _("missing rotation field after comma");
5443 return;
5444 }
5445
5446 /* Get the immediate constant. */
5447 skip_whitespace (str);
5448 if (is_immediate_prefix (* str))
5449 str++;
5450 else
5451 {
5452 inst.error = _("immediate expression expected");
5453 return;
5454 }
5455
5456 if (my_get_expression (&expr, &str))
5457 {
5458 inst.error = _("bad expression");
5459 return;
5460 }
5461
5462 if (expr.X_op != O_constant)
5463 {
5464 inst.error = _("constant expression expected");
5465 return;
5466 }
5467
5468 switch (expr.X_add_number)
5469 {
5470 case 0:
5471 /* Rotation field has already been zeroed. */
5472 break;
5473
5474 case 8:
5475 inst.instruction |= rotation_eight_mask;
5476 break;
5477
5478 case 16:
5479 inst.instruction |= rotation_sixteen_mask;
5480 break;
5481
5482 case 24:
5483 inst.instruction |= rotation_twenty_four_mask;
5484 break;
5485
5486 default:
5487 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5488 break;
5489 }
5490
5491 end_of_line (str);
5492
5493}
5494
5495
5496/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5497 word at the specified address and the following word
5498 respectively.
5499 Unconditionally executed.
5500 Error if Rn is R15.
5501*/
5502
5503static void
5504do_rfe (str)
5505 char *str;
5506{
5507 int rn;
5508
5509 skip_whitespace (str);
5510
5511 if ((rn = reg_required_here (&str, 16)) == FAIL)
5512 return;
b99bd4ef 5513
09d92015 5514 if (rn == REG_PC)
b99bd4ef 5515 {
09d92015 5516 inst.error = BAD_PC;
b99bd4ef
NC
5517 return;
5518 }
5519
09d92015
MM
5520 skip_whitespace (str);
5521
5522 if (*str == '!')
5523 {
5524 inst.instruction |= WRITE_BACK;
5525 str++;
5526 }
b99bd4ef
NC
5527 end_of_line (str);
5528}
5529
09d92015
MM
5530/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5531 register (argument parse).
5532 REV{<cond>} Rd, Rm.
5533 Condition defaults to COND_ALWAYS.
5534 Error if Rd or Rm are R15. */
b99bd4ef
NC
5535
5536static void
09d92015
MM
5537do_rev (str)
5538 char* str;
b99bd4ef
NC
5539{
5540 int rd, rm;
5541
b99bd4ef
NC
5542 skip_whitespace (str);
5543
09d92015
MM
5544 if ((rd = reg_required_here (&str, 12)) == FAIL
5545 || skip_past_comma (&str) == FAIL
5546 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5547 inst.error = BAD_ARGS;
5548
09d92015 5549 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5550 inst.error = BAD_PC;
5551
5552 else
5553 end_of_line (str);
5554}
5555
09d92015
MM
5556/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5557 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5558 Condition defaults to COND_ALWAYS.
5559 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5560
5561static void
09d92015
MM
5562do_qadd16 (str)
5563 char* str;
b99bd4ef 5564{
09d92015
MM
5565 int rd, rm, rn;
5566
b99bd4ef
NC
5567 skip_whitespace (str);
5568
09d92015
MM
5569 if ((rd = reg_required_here (&str, 12)) == FAIL
5570 || skip_past_comma (&str) == FAIL
5571 || (rn = reg_required_here (&str, 16)) == FAIL
5572 || skip_past_comma (&str) == FAIL
5573 || (rm = reg_required_here (&str, 0)) == FAIL)
5574 inst.error = BAD_ARGS;
5575
5576 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5577 inst.error = BAD_PC;
5578
b99bd4ef
NC
5579 else
5580 end_of_line (str);
5581}
5582
09d92015
MM
5583/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5584 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5585 Condition defaults to COND_ALWAYS.
5586 Error if Rd, Rn or Rm are R15. */
5587
5588static void
5589do_pkhbt (str)
5590 char* str;
5591{
5592 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5593}
5594
5595/* ARM V6 PKHTB (Argument Parse). */
5596
5597static void
5598do_pkhtb (str)
5599 char* str;
5600{
5601 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5602}
b99bd4ef
NC
5603
5604static void
09d92015
MM
5605do_pkh_core (str, shift)
5606 char* str;
5607 int shift;
b99bd4ef 5608{
09d92015 5609 int rd, rn, rm;
b99bd4ef 5610
09d92015
MM
5611 skip_whitespace (str);
5612 if (((rd = reg_required_here (&str, 12)) == FAIL)
5613 || (skip_past_comma (&str) == FAIL)
5614 || ((rn = reg_required_here (&str, 16)) == FAIL)
5615 || (skip_past_comma (&str) == FAIL)
5616 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5617 {
09d92015 5618 inst.error = BAD_ARGS;
b99bd4ef
NC
5619 return;
5620 }
5621
09d92015 5622 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5623 {
09d92015 5624 inst.error = BAD_PC;
b99bd4ef
NC
5625 return;
5626 }
5627
09d92015
MM
5628 /* Check for optional shift immediate constant. */
5629 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5630 {
09d92015
MM
5631 if (shift == SHIFT_ASR_IMMEDIATE)
5632 {
5633 /* If the shift specifier is ommited, turn the instruction
5634 into pkhbt rd, rm, rn. First, switch the instruction
5635 code, and clear the rn and rm fields. */
5636 inst.instruction &= 0xfff0f010;
5637 /* Now, re-encode the registers. */
5638 inst.instruction |= (rm << 16) | rn;
5639 }
b99bd4ef
NC
5640 return;
5641 }
5642
09d92015
MM
5643 decode_shift (&str, shift);
5644}
5645
5646/* ARM V6 Load Register Exclusive instruction (argument parse).
5647 LDREX{<cond>} <Rd, [<Rn>]
5648 Condition defaults to COND_ALWAYS.
5649 Error if Rd or Rn are R15.
5650 See ARMARMv6 A4.1.27: LDREX. */
5651
5652
5653static void
5654do_ldrex (str)
5655 char * str;
5656{
5657 int rd, rn;
5658
5659 skip_whitespace (str);
5660
5661 /* Parse Rd. */
5662 if (((rd = reg_required_here (&str, 12)) == FAIL)
5663 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5664 {
09d92015 5665 inst.error = BAD_ARGS;
b99bd4ef
NC
5666 return;
5667 }
09d92015 5668 else if (rd == REG_PC)
b99bd4ef 5669 {
09d92015 5670 inst.error = BAD_PC;
b99bd4ef
NC
5671 return;
5672 }
09d92015 5673 skip_whitespace (str);
b99bd4ef 5674
09d92015
MM
5675 /* Skip past '['. */
5676 if ((strlen (str) >= 1)
5677 &&strncmp (str, "[", 1) == 0)
5678 str+=1;
5679 skip_whitespace (str);
5680
5681 /* Parse Rn. */
5682 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5683 {
09d92015
MM
5684 inst.error = BAD_ARGS;
5685 return;
b99bd4ef 5686 }
09d92015
MM
5687 else if (rn == REG_PC)
5688 {
5689 inst.error = BAD_PC;
5690 return;
5691 }
5692 skip_whitespace (str);
b99bd4ef 5693
09d92015
MM
5694 /* Skip past ']'. */
5695 if ((strlen (str) >= 1)
5696 && strncmp (str, "]", 1) == 0)
5697 str+=1;
5698
b99bd4ef
NC
5699 end_of_line (str);
5700}
5701
09d92015
MM
5702/* ARM V6 change processor state instruction (argument parse)
5703 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5704
5705static void
09d92015
MM
5706do_cps (str)
5707 char * str;
b99bd4ef 5708{
09d92015
MM
5709 do_cps_mode (&str);
5710 end_of_line (str);
5711}
b99bd4ef 5712
09d92015
MM
5713static void
5714do_cpsi (str)
5715 char * str;
5716{
5717 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5718
09d92015 5719 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5720 {
09d92015
MM
5721 skip_whitespace (str);
5722 do_cps_mode (&str);
b99bd4ef 5723 }
09d92015
MM
5724 end_of_line (str);
5725}
b99bd4ef 5726
09d92015
MM
5727static void
5728do_cps_mode (str)
5729 char **str;
5730{
5731 expressionS expr;
5732
5733 skip_whitespace (*str);
5734
5735 if (! is_immediate_prefix (**str))
b99bd4ef 5736 {
09d92015 5737 inst.error = _("immediate expression expected");
b99bd4ef
NC
5738 return;
5739 }
5740
09d92015
MM
5741 (*str)++; /* Strip off the immediate signifier. */
5742 if (my_get_expression (&expr, str))
b99bd4ef 5743 {
09d92015 5744 inst.error = _("bad expression");
b99bd4ef
NC
5745 return;
5746 }
5747
09d92015 5748 if (expr.X_op != O_constant)
b99bd4ef 5749 {
09d92015 5750 inst.error = _("constant expression expected");
b99bd4ef
NC
5751 return;
5752 }
09d92015
MM
5753
5754 /* The mode is a 5 bit field. Valid values are 0-31. */
5755 if (((unsigned) expr.X_add_number) > 31
5756 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5757 {
09d92015
MM
5758 inst.error = _("invalid constant");
5759 return;
b99bd4ef 5760 }
09d92015
MM
5761
5762 inst.instruction |= expr.X_add_number;
5763 return;
b99bd4ef
NC
5764}
5765
ea6ef066 5766static void
09d92015
MM
5767do_cps_flags (str, thumb_p)
5768 char **str;
5769 int thumb_p;
ea6ef066 5770{
09d92015
MM
5771 struct cps_flag {
5772 char character;
5773 unsigned long arm_value;
5774 unsigned long thumb_value;
5775 };
5776 static struct cps_flag flag_table[] = {
5777 {'a', 0x100, 0x4 },
5778 {'i', 0x080, 0x2 },
5779 {'f', 0x040, 0x1 }
5780 };
ea6ef066 5781
09d92015 5782 int saw_a_flag = 0;
ea6ef066 5783
09d92015
MM
5784 skip_whitespace (*str);
5785
5786 /* Get the a, f and i flags. */
5787 while (**str && **str != ',')
ea6ef066 5788 {
09d92015
MM
5789 struct cps_flag *p;
5790 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5791 for (p = flag_table; p < q; ++p)
5792 if (strncasecmp (*str, &p->character, 1) == 0)
5793 {
5794 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5795 saw_a_flag = 1;
5796 break;
5797 }
5798 if (p == q)
5799 {
5800 inst.error = _("unrecognized flag");
5801 return;
5802 }
5803 (*str)++;
ea6ef066 5804 }
09d92015
MM
5805 if (!saw_a_flag)
5806 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5807}
5808
b99bd4ef
NC
5809/* THUMB V5 breakpoint instruction (argument parse)
5810 BKPT <immed_8>. */
5811
5812static void
5813do_t_bkpt (str)
5814 char * str;
5815{
5816 expressionS expr;
5817 unsigned long number;
5818
5819 skip_whitespace (str);
5820
5821 /* Allow optional leading '#'. */
5822 if (is_immediate_prefix (*str))
5823 str ++;
5824
5825 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5826 if (my_get_expression (& expr, & str)
5827 || (expr.X_op != O_constant
5828 /* As a convenience we allow 'bkpt' without an operand. */
5829 && expr.X_op != O_absent))
b99bd4ef 5830 {
143c8e19 5831 inst.error = _("bad expression");
b99bd4ef
NC
5832 return;
5833 }
5834
5835 number = expr.X_add_number;
5836
5837 /* Check it fits an 8 bit unsigned. */
5838 if (number != (number & 0xff))
5839 {
5840 inst.error = _("immediate value out of range");
5841 return;
5842 }
5843
5844 inst.instruction |= number;
5845
5846 end_of_line (str);
5847}
5848
5849/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5850 Expects inst.instruction is set for BLX(1).
5851 Note: this is cloned from do_branch, and the reloc changed to be a
5852 new one that can cope with setting one extra bit (the H bit). */
5853
5854static void
f2b7cb0a 5855do_branch25 (str)
b99bd4ef 5856 char * str;
b99bd4ef
NC
5857{
5858 if (my_get_expression (& inst.reloc.exp, & str))
5859 return;
5860
5861#ifdef OBJ_ELF
5862 {
5863 char * save_in;
5864
5865 /* ScottB: February 5, 1998 */
5866 /* Check to see of PLT32 reloc required for the instruction. */
5867
5868 /* arm_parse_reloc() works on input_line_pointer.
5869 We actually want to parse the operands to the branch instruction
5870 passed in 'str'. Save the input pointer and restore it later. */
5871 save_in = input_line_pointer;
5872 input_line_pointer = str;
5873
5874 if (inst.reloc.exp.X_op == O_symbol
5875 && *str == '('
5876 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5877 {
5878 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5879 inst.reloc.pc_rel = 0;
5880 /* Modify str to point to after parsed operands, otherwise
5881 end_of_line() will complain about the (PLT) left in str. */
5882 str = input_line_pointer;
5883 }
5884 else
5885 {
5886 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5887 inst.reloc.pc_rel = 1;
5888 }
5889
5890 input_line_pointer = save_in;
5891 }
5892#else
5893 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5894 inst.reloc.pc_rel = 1;
5895#endif /* OBJ_ELF */
5896
5897 end_of_line (str);
5898}
5899
5900/* ARM V5 branch-link-exchange instruction (argument parse)
5901 BLX <target_addr> ie BLX(1)
5902 BLX{<condition>} <Rm> ie BLX(2)
5903 Unfortunately, there are two different opcodes for this mnemonic.
5904 So, the insns[].value is not used, and the code here zaps values
5905 into inst.instruction.
5906 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5907
5908static void
f2b7cb0a 5909do_blx (str)
b99bd4ef 5910 char * str;
b99bd4ef
NC
5911{
5912 char * mystr = str;
5913 int rm;
5914
b99bd4ef
NC
5915 skip_whitespace (mystr);
5916 rm = reg_required_here (& mystr, 0);
5917
5918 /* The above may set inst.error. Ignore his opinion. */
5919 inst.error = 0;
5920
5921 if (rm != FAIL)
5922 {
5923 /* Arg is a register.
5924 Use the condition code our caller put in inst.instruction.
5925 Pass ourselves off as a BX with a funny opcode. */
5926 inst.instruction |= 0x012fff30;
f2b7cb0a 5927 do_bx (str);
b99bd4ef
NC
5928 }
5929 else
5930 {
5931 /* This must be is BLX <target address>, no condition allowed. */
5932 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5933 {
5934 inst.error = BAD_COND;
b99bd4ef 5935 return;
cc8a6dd0 5936 }
b99bd4ef
NC
5937
5938 inst.instruction = 0xfafffffe;
5939
5940 /* Process like a B/BL, but with a different reloc.
5941 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5942 do_branch25 (str);
b99bd4ef
NC
5943 }
5944}
5945
5946/* ARM V5 Thumb BLX (argument parse)
5947 BLX <target_addr> which is BLX(1)
5948 BLX <Rm> which is BLX(2)
5949 Unfortunately, there are two different opcodes for this mnemonic.
5950 So, the tinsns[].value is not used, and the code here zaps values
5951 into inst.instruction. */
5952
5953static void
5954do_t_blx (str)
5955 char * str;
5956{
5957 char * mystr = str;
5958 int rm;
5959
5960 skip_whitespace (mystr);
5961 inst.instruction = 0x4780;
5962
5963 /* Note that this call is to the ARM register recognizer. BLX(2)
5964 uses the ARM register space, not the Thumb one, so a call to
5965 thumb_reg() would be wrong. */
5966 rm = reg_required_here (& mystr, 3);
5967 inst.error = 0;
5968
5969 if (rm != FAIL)
5970 {
5971 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5972 inst.size = 2;
5973 }
5974 else
5975 {
5976 /* No ARM register. This must be BLX(1). Change the .instruction. */
5977 inst.instruction = 0xf7ffeffe;
5978 inst.size = 4;
5979
5980 if (my_get_expression (& inst.reloc.exp, & mystr))
5981 return;
5982
5983 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5984 inst.reloc.pc_rel = 1;
5985 }
5986
5987 end_of_line (mystr);
5988}
5989
5990/* ARM V5 breakpoint instruction (argument parse)
5991 BKPT <16 bit unsigned immediate>
5992 Instruction is not conditional.
5993 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5994 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5995
5996static void
f2b7cb0a 5997do_bkpt (str)
b99bd4ef 5998 char * str;
b99bd4ef
NC
5999{
6000 expressionS expr;
6001 unsigned long number;
6002
6003 skip_whitespace (str);
6004
6005 /* Allow optional leading '#'. */
6006 if (is_immediate_prefix (* str))
6007 str++;
6008
6009 memset (& expr, '\0', sizeof (expr));
6010
143c8e19
NC
6011 if (my_get_expression (& expr, & str)
6012 || (expr.X_op != O_constant
6013 /* As a convenience we allow 'bkpt' without an operand. */
6014 && expr.X_op != O_absent))
b99bd4ef 6015 {
143c8e19 6016 inst.error = _("bad expression");
b99bd4ef
NC
6017 return;
6018 }
6019
6020 number = expr.X_add_number;
6021
6022 /* Check it fits a 16 bit unsigned. */
6023 if (number != (number & 0xffff))
6024 {
6025 inst.error = _("immediate value out of range");
6026 return;
6027 }
6028
6029 /* Top 12 of 16 bits to bits 19:8. */
6030 inst.instruction |= (number & 0xfff0) << 4;
6031
6032 /* Bottom 4 of 16 bits to bits 3:0. */
6033 inst.instruction |= number & 0xf;
6034
6035 end_of_line (str);
b99bd4ef
NC
6036}
6037
09d92015
MM
6038/* THUMB CPS instruction (argument parse). */
6039
6040static void
6041do_t_cps (str)
6042 char *str;
6043{
6044 do_cps_flags (&str, /*thumb_p=*/1);
6045 end_of_line (str);
6046}
6047
6048/* THUMB CPY instruction (argument parse). */
6049
6050static void
6051do_t_cpy (str)
6052 char *str;
6053{
6054 thumb_mov_compare (str, THUMB_CPY);
6055}
6056
6057/* THUMB SETEND instruction (argument parse). */
6058
6059static void
6060do_t_setend (str)
6061 char *str;
6062{
6063 if (do_endian_specifier (str))
6064 inst.instruction |= 0x8;
6065}
6066
e16bb312
NC
6067static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6068
6069/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6070
6071static unsigned long
6072check_iwmmxt_insn (str, insn_type, immediate_size)
6073 char * str;
6074 enum iwmmxt_insn_type insn_type;
6075 int immediate_size;
6076{
6077 int reg = 0;
6078 const char * inst_error;
6079 expressionS expr;
6080 unsigned long number;
6081
6082 inst_error = inst.error;
6083 if (!inst.error)
6084 inst.error = BAD_ARGS;
6085 skip_whitespace (str);
6086
6087 switch (insn_type)
6088 {
6089 case check_rd:
6090 if ((reg = reg_required_here (&str, 12)) == FAIL)
6091 return FAIL;
6092 break;
6093
6094 case check_wr:
6095 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6096 return FAIL;
6097 break;
6098
6099 case check_wrwr:
6100 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6101 || skip_past_comma (&str) == FAIL
6102 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6103 return FAIL;
6104 break;
6105
6106 case check_wrwrwr:
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 || skip_past_comma (&str) == FAIL
6111 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6112 return FAIL;
6113 break;
6114
6115 case check_wrwrwcg:
6116 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6117 || skip_past_comma (&str) == FAIL
6118 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6119 || skip_past_comma (&str) == FAIL
6120 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6121 return FAIL;
6122 break;
6123
6124 case check_tbcst:
6125 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6126 || skip_past_comma (&str) == FAIL
6127 || reg_required_here (&str, 12) == FAIL))
6128 return FAIL;
6129 break;
6130
6131 case check_tmovmsk:
6132 if ((reg_required_here (&str, 12) == FAIL
6133 || skip_past_comma (&str) == FAIL
6134 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6135 return FAIL;
6136 break;
6137
6138 case check_tmia:
6139 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6140 || skip_past_comma (&str) == FAIL
6141 || reg_required_here (&str, 0) == FAIL
6142 || skip_past_comma (&str) == FAIL
6143 || reg_required_here (&str, 12) == FAIL))
6144 return FAIL;
6145 break;
6146
6147 case check_tmcrr:
6148 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6149 || skip_past_comma (&str) == FAIL
6150 || reg_required_here (&str, 12) == FAIL
6151 || skip_past_comma (&str) == FAIL
6152 || reg_required_here (&str, 16) == FAIL))
6153 return FAIL;
6154 break;
6155
6156 case check_tmrrc:
6157 if ((reg_required_here (&str, 12) == FAIL
6158 || skip_past_comma (&str) == FAIL
6159 || reg_required_here (&str, 16) == FAIL
6160 || skip_past_comma (&str) == FAIL
6161 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6162 return FAIL;
6163 break;
6164
6165 case check_tmcr:
6166 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6167 || skip_past_comma (&str) == FAIL
6168 || reg_required_here (&str, 12) == FAIL))
6169 return FAIL;
6170 break;
6171
6172 case check_tmrc:
6173 if ((reg_required_here (&str, 12) == FAIL
6174 || skip_past_comma (&str) == FAIL
6175 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6176 return FAIL;
6177 break;
6178
6179 case check_tinsr:
6180 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6181 || skip_past_comma (&str) == FAIL
6182 || reg_required_here (&str, 12) == FAIL
6183 || skip_past_comma (&str) == FAIL))
6184 return FAIL;
6185 break;
6186
6187 case check_textrc:
6188 if ((reg_required_here (&str, 12) == FAIL
6189 || skip_past_comma (&str) == FAIL))
6190 return FAIL;
6191 break;
6192
6193 case check_waligni:
6194 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6195 || skip_past_comma (&str) == FAIL
6196 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6197 || skip_past_comma (&str) == FAIL
6198 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6199 || skip_past_comma (&str) == FAIL))
6200 return FAIL;
6201 break;
6202
6203 case check_textrm:
6204 if ((reg_required_here (&str, 12) == FAIL
6205 || skip_past_comma (&str) == FAIL
6206 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6207 || skip_past_comma (&str) == FAIL))
6208 return FAIL;
6209 break;
6210
6211 case check_wshufh:
6212 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6213 || skip_past_comma (&str) == FAIL
6214 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6215 || skip_past_comma (&str) == FAIL))
6216 return FAIL;
6217 break;
6218 }
6219
6220 if (immediate_size == 0)
6221 {
6222 end_of_line (str);
6223 inst.error = inst_error;
6224 return reg;
6225 }
6226 else
6227 {
6228 skip_whitespace (str);
6229
6230 /* Allow optional leading '#'. */
6231 if (is_immediate_prefix (* str))
6232 str++;
6233
6234 memset (& expr, '\0', sizeof (expr));
6235
6236 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6237 {
6238 inst.error = _("bad or missing expression");
6239 return FAIL;
6240 }
6241
6242 number = expr.X_add_number;
6243
6244 if (number != (number & immediate_size))
6245 {
6246 inst.error = _("immediate value out of range");
6247 return FAIL;
6248 }
6249 end_of_line (str);
6250 inst.error = inst_error;
6251 return number;
6252 }
6253}
6254
6255static void
6256do_iwmmxt_byte_addr (str)
6257 char * str;
6258{
6259 int op = (inst.instruction & 0x300) >> 8;
6260 int reg;
6261
6262 inst.instruction &= ~0x300;
6263 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6264
6265 skip_whitespace (str);
6266
6267 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6268 || skip_past_comma (& str) == FAIL
6269 || cp_byte_address_required_here (&str) == FAIL)
6270 {
6271 if (! inst.error)
6272 inst.error = BAD_ARGS;
6273 }
6274 else
6275 end_of_line (str);
6276
6277 if (wc_register (reg))
6278 {
ece01a63 6279 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6280 inst.instruction |= 0xf0000100;
6281 inst.instruction &= ~0x00400000;
6282 }
6283}
6284
6285static void
6286do_iwmmxt_tandc (str)
6287 char * str;
6288{
6289 int reg;
6290
6291 reg = check_iwmmxt_insn (str, check_rd, 0);
6292
6293 if (reg != REG_PC && !inst.error)
6294 inst.error = _("only r15 allowed here");
6295 return;
6296}
6297
6298static void
6299do_iwmmxt_tbcst (str)
6300 char * str;
6301{
6302 check_iwmmxt_insn (str, check_tbcst, 0);
6303
6304 return;
6305}
6306
6307static void
6308do_iwmmxt_textrc (str)
6309 char * str;
6310{
6311 unsigned long number;
6312
6313 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6314 return;
6315
6316 inst.instruction |= number & 0x7;
6317 return;
6318}
6319
6320static void
6321do_iwmmxt_textrm (str)
6322 char * str;
6323{
6324 unsigned long number;
6325
6326 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6327 return;
6328
6329 inst.instruction |= number & 0x7;
6330}
6331
6332static void
6333do_iwmmxt_tinsr (str)
6334 char * str;
6335{
6336 unsigned long number;
6337
6338 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6339 return;
6340
6341 inst.instruction |= number & 0x7;
6342 return;
6343}
6344
6345static void
6346do_iwmmxt_tmcr (str)
6347 char * str;
6348{
6349 check_iwmmxt_insn (str, check_tmcr, 0);
6350
6351 return;
6352}
6353
6354static void
6355do_iwmmxt_tmcrr (str)
6356 char * str;
6357{
6358 check_iwmmxt_insn (str, check_tmcrr, 0);
6359
6360 return;
6361}
6362
6363static void
6364do_iwmmxt_tmia (str)
6365 char * str;
6366{
6367 check_iwmmxt_insn (str, check_tmia, 0);
6368
6369 return;
6370}
6371
6372static void
6373do_iwmmxt_tmovmsk (str)
6374 char * str;
6375{
6376 check_iwmmxt_insn (str, check_tmovmsk, 0);
6377
6378 return;
6379}
6380
6381static void
6382do_iwmmxt_tmrc (str)
6383 char * str;
6384{
6385 check_iwmmxt_insn (str, check_tmrc, 0);
6386
6387 return;
6388}
6389
6390static void
6391do_iwmmxt_tmrrc (str)
6392 char * str;
6393{
6394 check_iwmmxt_insn (str, check_tmrrc, 0);
6395
6396 return;
6397}
6398
6399static void
6400do_iwmmxt_torc (str)
6401 char * str;
6402{
6403 check_iwmmxt_insn (str, check_rd, 0);
6404 return;
6405}
6406
6407static void
6408do_iwmmxt_waligni (str)
6409 char * str;
6410{
6411 unsigned long number;
6412
6413 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6414 return;
6415
6416 inst.instruction |= ((number & 0x7) << 20);
6417 return;
6418}
6419
6420static void
6421do_iwmmxt_wmov (str)
6422 char * str;
6423{
6424 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6425 return;
6426
6427 inst.instruction |= ((inst.instruction >> 16) & 0xf);
6428 return;
6429}
6430
6431static void
6432do_iwmmxt_word_addr (str)
6433 char * str;
6434{
6435 int op = (inst.instruction & 0x300) >> 8;
6436 int reg;
6437
6438 inst.instruction &= ~0x300;
6439 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6440
6441 skip_whitespace (str);
6442
6443 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6444 || skip_past_comma (& str) == FAIL
6445 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6446 {
6447 if (! inst.error)
6448 inst.error = BAD_ARGS;
6449 }
6450 else
6451 end_of_line (str);
6452
6453 if (wc_register (reg))
6454 {
ece01a63
ILT
6455 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6456 as_bad (_("conditional execution not supported with control register"));
6457 if (op != 2)
6458 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6459 inst.instruction |= 0xf0000100;
6460 inst.instruction &= ~0x00400000;
6461 }
6462}
6463
6464static void
6465do_iwmmxt_wrwr (str)
6466 char * str;
6467{
6468 check_iwmmxt_insn (str, check_wrwr, 0);
6469
6470 return;
6471}
6472
6473static void
6474do_iwmmxt_wrwrwcg (str)
6475 char * str;
6476{
6477 check_iwmmxt_insn (str, check_wrwrwcg, 0);
6478
6479 return;
6480}
6481
6482static void
6483do_iwmmxt_wrwrwr (str)
6484 char * str;
6485{
6486 check_iwmmxt_insn (str, check_wrwrwr, 0);
6487
6488 return;
6489}
6490
6491static void
6492do_iwmmxt_wshufh (str)
6493 char * str;
6494{
6495 unsigned long number;
6496
6497 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6498 return;
6499
6500 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6501 return;
6502}
6503
6504static void
6505do_iwmmxt_wzero (str)
6506 char * str;
6507{
6508 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6509 return;
6510
6511 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6512 return;
6513}
6514
b99bd4ef
NC
6515/* Xscale multiply-accumulate (argument parse)
6516 MIAcc acc0,Rm,Rs
6517 MIAPHcc acc0,Rm,Rs
6518 MIAxycc acc0,Rm,Rs. */
6519
6520static void
63e63b07 6521do_xsc_mia (str)
b99bd4ef 6522 char * str;
b99bd4ef
NC
6523{
6524 int rs;
6525 int rm;
6526
f2b7cb0a 6527 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6528 inst.error = ERR_NO_ACCUM;
6529
6530 else if (skip_past_comma (& str) == FAIL
6531 || (rm = reg_required_here (& str, 0)) == FAIL)
6532 inst.error = BAD_ARGS;
6533
6534 else if (skip_past_comma (& str) == FAIL
6535 || (rs = reg_required_here (& str, 12)) == FAIL)
6536 inst.error = BAD_ARGS;
6537
6538 /* inst.instruction has now been zapped with both rm and rs. */
6539 else if (rm == REG_PC || rs == REG_PC)
6540 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6541
6542 else
6543 end_of_line (str);
6544}
6545
6546/* Xscale move-accumulator-register (argument parse)
6547
6548 MARcc acc0,RdLo,RdHi. */
6549
6550static void
63e63b07 6551do_xsc_mar (str)
b99bd4ef 6552 char * str;
b99bd4ef
NC
6553{
6554 int rdlo, rdhi;
6555
f2b7cb0a 6556 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6557 inst.error = ERR_NO_ACCUM;
6558
6559 else if (skip_past_comma (& str) == FAIL
6560 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6561 inst.error = BAD_ARGS;
6562
6563 else if (skip_past_comma (& str) == FAIL
6564 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6565 inst.error = BAD_ARGS;
6566
6567 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6568 else if (rdlo == REG_PC || rdhi == REG_PC)
6569 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6570
6571 else
6572 end_of_line (str);
6573}
6574
6575/* Xscale move-register-accumulator (argument parse)
6576
6577 MRAcc RdLo,RdHi,acc0. */
6578
6579static void
63e63b07 6580do_xsc_mra (str)
b99bd4ef 6581 char * str;
b99bd4ef
NC
6582{
6583 int rdlo;
6584 int rdhi;
6585
b99bd4ef
NC
6586 skip_whitespace (str);
6587
6588 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6589 inst.error = BAD_ARGS;
6590
6591 else if (skip_past_comma (& str) == FAIL
6592 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6593 inst.error = BAD_ARGS;
6594
6595 else if (skip_past_comma (& str) == FAIL
6596 || accum0_required_here (& str) == FAIL)
6597 inst.error = ERR_NO_ACCUM;
6598
6599 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6600 else if (rdlo == rdhi)
6601 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6602
6603 else if (rdlo == REG_PC || rdhi == REG_PC)
6604 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6605 else
6606 end_of_line (str);
6607}
6608
c9b604bd 6609/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6610
6611 PLD <addr_mode>
6612
6613 Syntactically, like LDR with B=1, W=0, L=1. */
6614
6615static void
f2b7cb0a 6616do_pld (str)
b99bd4ef 6617 char * str;
b99bd4ef
NC
6618{
6619 int rd;
6620
b99bd4ef
NC
6621 skip_whitespace (str);
6622
6623 if (* str != '[')
6624 {
6625 inst.error = _("'[' expected after PLD mnemonic");
6626 return;
6627 }
6628
90e4755a 6629 ++str;
b99bd4ef
NC
6630 skip_whitespace (str);
6631
6632 if ((rd = reg_required_here (& str, 16)) == FAIL)
6633 return;
6634
6635 skip_whitespace (str);
6636
90e4755a 6637 if (*str == ']')
b99bd4ef
NC
6638 {
6639 /* [Rn], ... ? */
90e4755a 6640 ++str;
b99bd4ef
NC
6641 skip_whitespace (str);
6642
90e4755a
RE
6643 /* Post-indexed addressing is not allowed with PLD. */
6644 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6645 {
90e4755a
RE
6646 inst.error
6647 = _("post-indexed expression used in preload instruction");
6648 return;
b99bd4ef 6649 }
90e4755a 6650 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6651 {
6652 inst.error = _("writeback used in preload instruction");
90e4755a 6653 ++str;
b99bd4ef
NC
6654 }
6655 else /* [Rn] */
6656 inst.instruction |= INDEX_UP | PRE_INDEX;
6657 }
6658 else /* [Rn, ...] */
6659 {
6660 if (skip_past_comma (& str) == FAIL)
6661 {
6662 inst.error = _("pre-indexed expression expected");
6663 return;
6664 }
6665
90e4755a 6666 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6667 return;
6668
6669 skip_whitespace (str);
6670
6671 if (* str != ']')
6672 {
6673 inst.error = _("missing ]");
6674 return;
6675 }
6676
6677 ++ str;
6678 skip_whitespace (str);
6679
6680 if (* str == '!') /* [Rn]! */
6681 {
6682 inst.error = _("writeback used in preload instruction");
6683 ++ str;
6684 }
6685
6686 inst.instruction |= PRE_INDEX;
6687 }
6688
6689 end_of_line (str);
6690}
6691
c9b604bd 6692/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6693 Mode is like LDRH.
6694
6695 LDRccD R, mode
6696 STRccD R, mode. */
6697
6698static void
f2b7cb0a 6699do_ldrd (str)
b99bd4ef 6700 char * str;
b99bd4ef
NC
6701{
6702 int rd;
6703 int rn;
6704
b99bd4ef
NC
6705 skip_whitespace (str);
6706
6707 if ((rd = reg_required_here (& str, 12)) == FAIL)
6708 {
6709 inst.error = BAD_ARGS;
6710 return;
6711 }
6712
6713 if (skip_past_comma (& str) == FAIL
6714 || (rn = ld_mode_required_here (& str)) == FAIL)
6715 {
6716 if (!inst.error)
cc8a6dd0 6717 inst.error = BAD_ARGS;
b99bd4ef
NC
6718 return;
6719 }
6720
6721 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6722 if (rd & 1) /* Unpredictable result if Rd is odd. */
6723 {
f03698e6 6724 inst.error = _("destination register must be even");
b99bd4ef
NC
6725 return;
6726 }
6727
90e4755a 6728 if (rd == REG_LR)
b99bd4ef 6729 {
f2b7cb0a 6730 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6731 return;
6732 }
6733
6734 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6735 && ((inst.instruction & WRITE_BACK)
6736 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6737 as_warn (_("pre/post-indexing used when modified address register is destination"));
6738
90e4755a
RE
6739 /* For an index-register load, the index register must not overlap the
6740 destination (even if not write-back). */
6741 if ((inst.instruction & V4_STR_BIT) == 0
6742 && (inst.instruction & HWOFFSET_IMM) == 0)
6743 {
6744 int rm = inst.instruction & 0x0000000f;
6745
6746 if (rm == rd || (rm == rd + 1))
6747 as_warn (_("ldrd destination registers must not overlap index register"));
6748 }
6749
b99bd4ef
NC
6750 end_of_line (str);
6751}
6752
6753/* Returns the index into fp_values of a floating point number,
6754 or -1 if not in the table. */
6755
6756static int
6757my_get_float_expression (str)
6758 char ** str;
6759{
6760 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6761 char * save_in;
6762 expressionS exp;
6763 int i;
6764 int j;
6765
6766 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6767
6768 /* Look for a raw floating point number. */
6769 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6770 && is_end_of_line[(unsigned char) *save_in])
6771 {
6772 for (i = 0; i < NUM_FLOAT_VALS; i++)
6773 {
6774 for (j = 0; j < MAX_LITTLENUMS; j++)
6775 {
6776 if (words[j] != fp_values[i][j])
6777 break;
6778 }
6779
6780 if (j == MAX_LITTLENUMS)
6781 {
6782 *str = save_in;
6783 return i;
6784 }
6785 }
6786 }
6787
6788 /* Try and parse a more complex expression, this will probably fail
6789 unless the code uses a floating point prefix (eg "0f"). */
6790 save_in = input_line_pointer;
6791 input_line_pointer = *str;
6792 if (expression (&exp) == absolute_section
6793 && exp.X_op == O_big
6794 && exp.X_add_number < 0)
6795 {
6796 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6797 Ditto for 15. */
6798 if (gen_to_words (words, 5, (long) 15) == 0)
6799 {
6800 for (i = 0; i < NUM_FLOAT_VALS; i++)
6801 {
6802 for (j = 0; j < MAX_LITTLENUMS; j++)
6803 {
6804 if (words[j] != fp_values[i][j])
6805 break;
6806 }
6807
6808 if (j == MAX_LITTLENUMS)
6809 {
6810 *str = input_line_pointer;
6811 input_line_pointer = save_in;
6812 return i;
6813 }
6814 }
6815 }
6816 }
6817
6818 *str = input_line_pointer;
6819 input_line_pointer = save_in;
6820 return -1;
6821}
6822
b34976b6 6823/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6824
6825static int
6826walk_no_bignums (sp)
6827 symbolS * sp;
6828{
6829 if (symbol_get_value_expression (sp)->X_op == O_big)
6830 return 1;
6831
6832 if (symbol_get_value_expression (sp)->X_add_symbol)
6833 {
6834 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6835 || (symbol_get_value_expression (sp)->X_op_symbol
6836 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6837 }
6838
6839 return 0;
6840}
6841
f03698e6
RE
6842static int in_my_get_expression = 0;
6843
b99bd4ef
NC
6844static int
6845my_get_expression (ep, str)
6846 expressionS * ep;
6847 char ** str;
6848{
6849 char * save_in;
6850 segT seg;
6851
6852 save_in = input_line_pointer;
6853 input_line_pointer = *str;
f03698e6 6854 in_my_get_expression = 1;
b99bd4ef 6855 seg = expression (ep);
f03698e6
RE
6856 in_my_get_expression = 0;
6857
6858 if (ep->X_op == O_illegal)
6859 {
6860 /* We found a bad expression in md_operand(). */
6861 *str = input_line_pointer;
6862 input_line_pointer = save_in;
6863 return 1;
6864 }
b99bd4ef
NC
6865
6866#ifdef OBJ_AOUT
6867 if (seg != absolute_section
6868 && seg != text_section
6869 && seg != data_section
6870 && seg != bss_section
6871 && seg != undefined_section)
6872 {
6873 inst.error = _("bad_segment");
6874 *str = input_line_pointer;
6875 input_line_pointer = save_in;
6876 return 1;
6877 }
6878#endif
6879
6880 /* Get rid of any bignums now, so that we don't generate an error for which
6881 we can't establish a line number later on. Big numbers are never valid
6882 in instructions, which is where this routine is always called. */
6883 if (ep->X_op == O_big
6884 || (ep->X_add_symbol
6885 && (walk_no_bignums (ep->X_add_symbol)
6886 || (ep->X_op_symbol
6887 && walk_no_bignums (ep->X_op_symbol)))))
6888 {
f03698e6 6889 inst.error = _("invalid constant");
b99bd4ef
NC
6890 *str = input_line_pointer;
6891 input_line_pointer = save_in;
6892 return 1;
6893 }
6894
6895 *str = input_line_pointer;
6896 input_line_pointer = save_in;
6897 return 0;
6898}
6899
cc8a6dd0 6900/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6901 instruction in the error message. */
6902void
ce058b6c 6903md_operand (expr)
f03698e6
RE
6904 expressionS *expr;
6905{
6906 if (in_my_get_expression)
6907 {
6908 expr->X_op = O_illegal;
6909 if (inst.error == NULL)
6910 inst.error = _("bad expression");
6911 }
6912}
6913
09d92015 6914/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6915
6916static int
09d92015 6917decode_shift (str, kind)
b99bd4ef 6918 char ** str;
09d92015 6919 int kind;
b99bd4ef
NC
6920{
6921 const struct asm_shift_name * shift;
6922 char * p;
6923 char c;
6924
6925 skip_whitespace (* str);
6926
3882b010 6927 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6928 ;
6929
6930 if (p == * str)
6931 {
f03698e6 6932 inst.error = _("shift expression expected");
b99bd4ef
NC
6933 return FAIL;
6934 }
6935
6936 c = * p;
6937 * p = '\0';
6938 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6939 * p = c;
6940
6941 if (shift == NULL)
6942 {
f03698e6 6943 inst.error = _("shift expression expected");
b99bd4ef
NC
6944 return FAIL;
6945 }
6946
6947 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6948
09d92015
MM
6949 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6950 && shift->properties->index != SHIFT_LSL
6951 && shift->properties->index != SHIFT_ASR)
6952 {
6953 inst.error = _("'LSL' or 'ASR' required");
6954 return FAIL;
6955 }
6956 else if (kind == SHIFT_LSL_IMMEDIATE
6957 && shift->properties->index != SHIFT_LSL)
6958 {
6959 inst.error = _("'LSL' required");
6960 return FAIL;
6961 }
6962 else if (kind == SHIFT_ASR_IMMEDIATE
6963 && shift->properties->index != SHIFT_ASR)
6964 {
6965 inst.error = _("'ASR' required");
6966 return FAIL;
6967 }
6968
b99bd4ef
NC
6969 if (shift->properties->index == SHIFT_RRX)
6970 {
6971 * str = p;
6972 inst.instruction |= shift->properties->bit_field;
6973 return SUCCESS;
6974 }
6975
6976 skip_whitespace (p);
6977
09d92015 6978 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6979 {
6980 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6981 * str = p;
6982 return SUCCESS;
6983 }
6984 else if (! is_immediate_prefix (* p))
6985 {
09d92015 6986 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6987 ? _("shift requires register or #expression")
6988 : _("shift requires #expression"));
6989 * str = p;
6990 return FAIL;
6991 }
6992
6993 inst.error = NULL;
6994 p ++;
6995
6996 if (my_get_expression (& inst.reloc.exp, & p))
6997 return FAIL;
6998
6999 /* Validate some simple #expressions. */
7000 if (inst.reloc.exp.X_op == O_constant)
7001 {
7002 unsigned num = inst.reloc.exp.X_add_number;
7003
7004 /* Reject operations greater than 32. */
7005 if (num > 32
7006 /* Reject a shift of 0 unless the mode allows it. */
7007 || (num == 0 && shift->properties->allows_0 == 0)
7008 /* Reject a shift of 32 unless the mode allows it. */
7009 || (num == 32 && shift->properties->allows_32 == 0)
7010 )
7011 {
7012 /* As a special case we allow a shift of zero for
7013 modes that do not support it to be recoded as an
7014 logical shift left of zero (ie nothing). We warn
7015 about this though. */
7016 if (num == 0)
7017 {
f03698e6 7018 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
7019 shift = & shift_names[0];
7020 assert (shift->properties->index == SHIFT_LSL);
7021 }
7022 else
7023 {
f03698e6 7024 inst.error = _("invalid immediate shift");
b99bd4ef
NC
7025 return FAIL;
7026 }
7027 }
7028
7029 /* Shifts of 32 are encoded as 0, for those shifts that
7030 support it. */
7031 if (num == 32)
7032 num = 0;
7033
7034 inst.instruction |= (num << 7) | shift->properties->bit_field;
7035 }
7036 else
7037 {
7038 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7039 inst.reloc.pc_rel = 0;
7040 inst.instruction |= shift->properties->bit_field;
7041 }
7042
7043 * str = p;
7044 return SUCCESS;
7045}
7046
7047/* Do those data_ops which can take a negative immediate constant
2d2255b5 7048 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
7049 MOV <-> MVN
7050 AND <-> BIC
7051 ADC <-> SBC
7052 by inverting the second operand, and
7053 ADD <-> SUB
7054 CMP <-> CMN
7055 by negating the second operand. */
7056
7057static int
7058negate_data_op (instruction, value)
7059 unsigned long * instruction;
7060 unsigned long value;
7061{
7062 int op, new_inst;
7063 unsigned long negated, inverted;
7064
7065 negated = validate_immediate (-value);
7066 inverted = validate_immediate (~value);
7067
7068 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7069 switch (op)
7070 {
7071 /* First negates. */
7072 case OPCODE_SUB: /* ADD <-> SUB */
7073 new_inst = OPCODE_ADD;
7074 value = negated;
7075 break;
7076
7077 case OPCODE_ADD:
7078 new_inst = OPCODE_SUB;
7079 value = negated;
7080 break;
7081
7082 case OPCODE_CMP: /* CMP <-> CMN */
7083 new_inst = OPCODE_CMN;
7084 value = negated;
7085 break;
7086
7087 case OPCODE_CMN:
7088 new_inst = OPCODE_CMP;
7089 value = negated;
7090 break;
7091
7092 /* Now Inverted ops. */
7093 case OPCODE_MOV: /* MOV <-> MVN */
7094 new_inst = OPCODE_MVN;
7095 value = inverted;
7096 break;
7097
7098 case OPCODE_MVN:
7099 new_inst = OPCODE_MOV;
7100 value = inverted;
7101 break;
7102
7103 case OPCODE_AND: /* AND <-> BIC */
7104 new_inst = OPCODE_BIC;
7105 value = inverted;
7106 break;
7107
7108 case OPCODE_BIC:
7109 new_inst = OPCODE_AND;
7110 value = inverted;
7111 break;
7112
7113 case OPCODE_ADC: /* ADC <-> SBC */
7114 new_inst = OPCODE_SBC;
7115 value = inverted;
7116 break;
7117
7118 case OPCODE_SBC:
7119 new_inst = OPCODE_ADC;
7120 value = inverted;
7121 break;
7122
7123 /* We cannot do anything. */
7124 default:
7125 return FAIL;
7126 }
7127
7128 if (value == (unsigned) FAIL)
7129 return FAIL;
7130
7131 *instruction &= OPCODE_MASK;
7132 *instruction |= new_inst << DATA_OP_SHIFT;
7133 return value;
7134}
7135
7136static int
7137data_op2 (str)
7138 char ** str;
7139{
7140 int value;
7141 expressionS expr;
7142
7143 skip_whitespace (* str);
7144
7145 if (reg_required_here (str, 0) != FAIL)
7146 {
7147 if (skip_past_comma (str) == SUCCESS)
7148 /* Shift operation on register. */
7149 return decode_shift (str, NO_SHIFT_RESTRICT);
7150
7151 return SUCCESS;
7152 }
7153 else
7154 {
7155 /* Immediate expression. */
7156 if (is_immediate_prefix (**str))
7157 {
7158 (*str)++;
7159 inst.error = NULL;
7160
7161 if (my_get_expression (&inst.reloc.exp, str))
7162 return FAIL;
7163
7164 if (inst.reloc.exp.X_add_symbol)
7165 {
7166 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7167 inst.reloc.pc_rel = 0;
7168 }
7169 else
7170 {
7171 if (skip_past_comma (str) == SUCCESS)
7172 {
7173 /* #x, y -- ie explicit rotation by Y. */
7174 if (my_get_expression (&expr, str))
7175 return FAIL;
7176
7177 if (expr.X_op != O_constant)
7178 {
f03698e6 7179 inst.error = _("constant expression expected");
b99bd4ef
NC
7180 return FAIL;
7181 }
7182
7183 /* Rotate must be a multiple of 2. */
7184 if (((unsigned) expr.X_add_number) > 30
7185 || (expr.X_add_number & 1) != 0
7186 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7187 {
f03698e6 7188 inst.error = _("invalid constant");
b99bd4ef
NC
7189 return FAIL;
7190 }
7191 inst.instruction |= INST_IMMEDIATE;
7192 inst.instruction |= inst.reloc.exp.X_add_number;
7193 inst.instruction |= expr.X_add_number << 7;
7194 return SUCCESS;
7195 }
7196
7197 /* Implicit rotation, select a suitable one. */
7198 value = validate_immediate (inst.reloc.exp.X_add_number);
7199
7200 if (value == FAIL)
7201 {
7202 /* Can't be done. Perhaps the code reads something like
7203 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7204 if ((value = negate_data_op (&inst.instruction,
7205 inst.reloc.exp.X_add_number))
7206 == FAIL)
7207 {
f03698e6 7208 inst.error = _("invalid constant");
b99bd4ef
NC
7209 return FAIL;
7210 }
7211 }
7212
7213 inst.instruction |= value;
7214 }
7215
7216 inst.instruction |= INST_IMMEDIATE;
7217 return SUCCESS;
7218 }
7219
7220 (*str)++;
f03698e6 7221 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7222 return FAIL;
7223 }
7224}
7225
7226static int
7227fp_op2 (str)
7228 char ** str;
7229{
7230 skip_whitespace (* str);
7231
7232 if (fp_reg_required_here (str, 0) != FAIL)
7233 return SUCCESS;
7234 else
7235 {
7236 /* Immediate expression. */
7237 if (*((*str)++) == '#')
7238 {
7239 int i;
7240
7241 inst.error = NULL;
7242
7243 skip_whitespace (* str);
7244
7245 /* First try and match exact strings, this is to guarantee
7246 that some formats will work even for cross assembly. */
7247
7248 for (i = 0; fp_const[i]; i++)
7249 {
7250 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7251 {
7252 char *start = *str;
7253
7254 *str += strlen (fp_const[i]);
7255 if (is_end_of_line[(unsigned char) **str])
7256 {
7257 inst.instruction |= i + 8;
7258 return SUCCESS;
7259 }
7260 *str = start;
7261 }
7262 }
7263
7264 /* Just because we didn't get a match doesn't mean that the
7265 constant isn't valid, just that it is in a format that we
7266 don't automatically recognize. Try parsing it with
7267 the standard expression routines. */
7268 if ((i = my_get_float_expression (str)) >= 0)
7269 {
7270 inst.instruction |= i + 8;
7271 return SUCCESS;
7272 }
7273
f03698e6 7274 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7275 return FAIL;
7276 }
7277 inst.error =
f03698e6 7278 _("floating point register or immediate expression expected");
b99bd4ef
NC
7279 return FAIL;
7280 }
7281}
7282
7283static void
f2b7cb0a 7284do_arit (str)
b99bd4ef 7285 char * str;
b99bd4ef
NC
7286{
7287 skip_whitespace (str);
7288
7289 if (reg_required_here (&str, 12) == FAIL
7290 || skip_past_comma (&str) == FAIL
7291 || reg_required_here (&str, 16) == FAIL
7292 || skip_past_comma (&str) == FAIL
7293 || data_op2 (&str) == FAIL)
7294 {
7295 if (!inst.error)
7296 inst.error = BAD_ARGS;
7297 return;
7298 }
7299
b99bd4ef
NC
7300 end_of_line (str);
7301 return;
7302}
7303
7304static void
f2b7cb0a 7305do_adr (str)
b99bd4ef 7306 char * str;
b99bd4ef 7307{
90e4755a
RE
7308 /* This is a pseudo-op of the form "adr rd, label" to be converted
7309 into a relative address of the form "add rd, pc, #label-.-8". */
7310 skip_whitespace (str);
7311
7312 if (reg_required_here (&str, 12) == FAIL
7313 || skip_past_comma (&str) == FAIL
7314 || my_get_expression (&inst.reloc.exp, &str))
7315 {
7316 if (!inst.error)
7317 inst.error = BAD_ARGS;
7318 return;
7319 }
7320
7321 /* Frag hacking will turn this into a sub instruction if the offset turns
7322 out to be negative. */
7323 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7324 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7325 inst.reloc.pc_rel = 1;
7326
7327 end_of_line (str);
7328}
7329
7330static void
f2b7cb0a 7331do_adrl (str)
90e4755a 7332 char * str;
90e4755a
RE
7333{
7334 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7335 into a relative address of the form:
7336 add rd, pc, #low(label-.-8)"
7337 add rd, rd, #high(label-.-8)" */
7338
7339 skip_whitespace (str);
7340
7341 if (reg_required_here (&str, 12) == FAIL
7342 || skip_past_comma (&str) == FAIL
7343 || my_get_expression (&inst.reloc.exp, &str))
7344 {
7345 if (!inst.error)
7346 inst.error = BAD_ARGS;
7347
7348 return;
7349 }
7350
7351 end_of_line (str);
7352 /* Frag hacking will turn this into a sub instruction if the offset turns
7353 out to be negative. */
7354 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7355 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7356 inst.reloc.pc_rel = 1;
7357 inst.size = INSN_SIZE * 2;
7358
7359 return;
7360}
7361
7362static void
f2b7cb0a 7363do_cmp (str)
90e4755a 7364 char * str;
90e4755a
RE
7365{
7366 skip_whitespace (str);
7367
7368 if (reg_required_here (&str, 16) == FAIL)
7369 {
7370 if (!inst.error)
7371 inst.error = BAD_ARGS;
7372 return;
7373 }
7374
7375 if (skip_past_comma (&str) == FAIL
7376 || data_op2 (&str) == FAIL)
7377 {
7378 if (!inst.error)
7379 inst.error = BAD_ARGS;
7380 return;
7381 }
7382
90e4755a
RE
7383 end_of_line (str);
7384 return;
7385}
7386
7387static void
f2b7cb0a 7388do_mov (str)
90e4755a 7389 char * str;
90e4755a
RE
7390{
7391 skip_whitespace (str);
7392
7393 if (reg_required_here (&str, 12) == FAIL)
7394 {
7395 if (!inst.error)
7396 inst.error = BAD_ARGS;
7397 return;
7398 }
7399
7400 if (skip_past_comma (&str) == FAIL
7401 || data_op2 (&str) == FAIL)
7402 {
7403 if (!inst.error)
7404 inst.error = BAD_ARGS;
7405 return;
7406 }
7407
90e4755a
RE
7408 end_of_line (str);
7409 return;
7410}
7411
7412static int
7413ldst_extend (str)
7414 char ** str;
7415{
7416 int add = INDEX_UP;
7417
7418 switch (**str)
7419 {
7420 case '#':
7421 case '$':
7422 (*str)++;
7423 if (my_get_expression (& inst.reloc.exp, str))
7424 return FAIL;
7425
7426 if (inst.reloc.exp.X_op == O_constant)
7427 {
7428 int value = inst.reloc.exp.X_add_number;
7429
7430 if (value < -4095 || value > 4095)
7431 {
7432 inst.error = _("address offset too large");
7433 return FAIL;
7434 }
7435
7436 if (value < 0)
7437 {
7438 value = -value;
7439 add = 0;
7440 }
7441
7442 inst.instruction |= add | value;
7443 }
7444 else
7445 {
7446 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7447 inst.reloc.pc_rel = 0;
7448 }
7449 return SUCCESS;
7450
7451 case '-':
7452 add = 0;
7453 /* Fall through. */
7454
7455 case '+':
7456 (*str)++;
7457 /* Fall through. */
7458
7459 default:
7460 if (reg_required_here (str, 0) == FAIL)
7461 return FAIL;
7462
7463 inst.instruction |= add | OFFSET_REG;
7464 if (skip_past_comma (str) == SUCCESS)
09d92015 7465 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7466
7467 return SUCCESS;
7468 }
7469}
7470
7471static void
f2b7cb0a 7472do_ldst (str)
90e4755a 7473 char * str;
90e4755a
RE
7474{
7475 int pre_inc = 0;
7476 int conflict_reg;
7477 int value;
7478
b99bd4ef
NC
7479 skip_whitespace (str);
7480
90e4755a
RE
7481 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7482 {
7483 if (!inst.error)
7484 inst.error = BAD_ARGS;
7485 return;
7486 }
7487
7488 if (skip_past_comma (&str) == FAIL)
7489 {
f03698e6 7490 inst.error = _("address expected");
90e4755a
RE
7491 return;
7492 }
7493
90e4755a
RE
7494 if (*str == '[')
7495 {
7496 int reg;
7497
7498 str++;
7499
7500 skip_whitespace (str);
7501
7502 if ((reg = reg_required_here (&str, 16)) == FAIL)
7503 return;
7504
7505 /* Conflicts can occur on stores as well as loads. */
7506 conflict_reg = (conflict_reg == reg);
7507
7508 skip_whitespace (str);
7509
7510 if (*str == ']')
7511 {
7512 str ++;
7513
7514 if (skip_past_comma (&str) == SUCCESS)
7515 {
7516 /* [Rn],... (post inc) */
7517 if (ldst_extend (&str) == FAIL)
7518 return;
7519 if (conflict_reg)
7520 as_warn (_("%s register same as write-back base"),
7521 ((inst.instruction & LOAD_BIT)
7522 ? _("destination") : _("source")));
7523 }
7524 else
7525 {
7526 /* [Rn] */
7527 skip_whitespace (str);
7528
7529 if (*str == '!')
7530 {
7531 if (conflict_reg)
7532 as_warn (_("%s register same as write-back base"),
7533 ((inst.instruction & LOAD_BIT)
7534 ? _("destination") : _("source")));
7535 str++;
7536 inst.instruction |= WRITE_BACK;
7537 }
7538
7539 inst.instruction |= INDEX_UP;
7540 pre_inc = 1;
7541 }
7542 }
7543 else
7544 {
7545 /* [Rn,...] */
7546 if (skip_past_comma (&str) == FAIL)
7547 {
7548 inst.error = _("pre-indexed expression expected");
7549 return;
7550 }
7551
7552 pre_inc = 1;
7553 if (ldst_extend (&str) == FAIL)
7554 return;
7555
7556 skip_whitespace (str);
7557
7558 if (*str++ != ']')
7559 {
7560 inst.error = _("missing ]");
7561 return;
7562 }
7563
7564 skip_whitespace (str);
7565
7566 if (*str == '!')
7567 {
7568 if (conflict_reg)
7569 as_warn (_("%s register same as write-back base"),
7570 ((inst.instruction & LOAD_BIT)
7571 ? _("destination") : _("source")));
7572 str++;
7573 inst.instruction |= WRITE_BACK;
7574 }
7575 }
7576 }
7577 else if (*str == '=')
7578 {
f03698e6
RE
7579 if ((inst.instruction & LOAD_BIT) == 0)
7580 {
7581 inst.error = _("invalid pseudo operation");
7582 return;
7583 }
7584
90e4755a
RE
7585 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7586 str++;
7587
7588 skip_whitespace (str);
7589
7590 if (my_get_expression (&inst.reloc.exp, &str))
7591 return;
7592
7593 if (inst.reloc.exp.X_op != O_constant
7594 && inst.reloc.exp.X_op != O_symbol)
7595 {
f03698e6 7596 inst.error = _("constant expression expected");
90e4755a
RE
7597 return;
7598 }
7599
e28cd48c 7600 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7601 {
e28cd48c
RE
7602 value = validate_immediate (inst.reloc.exp.X_add_number);
7603
7604 if (value != FAIL)
90e4755a 7605 {
e28cd48c
RE
7606 /* This can be done with a mov instruction. */
7607 inst.instruction &= LITERAL_MASK;
7608 inst.instruction |= (INST_IMMEDIATE
7609 | (OPCODE_MOV << DATA_OP_SHIFT));
7610 inst.instruction |= value & 0xfff;
7611 end_of_line (str);
90e4755a
RE
7612 return;
7613 }
b99bd4ef 7614
e28cd48c
RE
7615 value = validate_immediate (~inst.reloc.exp.X_add_number);
7616
7617 if (value != FAIL)
7618 {
7619 /* This can be done with a mvn instruction. */
7620 inst.instruction &= LITERAL_MASK;
7621 inst.instruction |= (INST_IMMEDIATE
7622 | (OPCODE_MVN << DATA_OP_SHIFT));
7623 inst.instruction |= value & 0xfff;
7624 end_of_line (str);
7625 return;
7626 }
90e4755a 7627 }
e28cd48c
RE
7628
7629 /* Insert into literal pool. */
7630 if (add_to_lit_pool () == FAIL)
7631 {
7632 if (!inst.error)
7633 inst.error = _("literal pool insertion failed");
7634 return;
7635 }
7636
7637 /* Change the instruction exp to point to the pool. */
7638 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7639 inst.reloc.pc_rel = 1;
7640 inst.instruction |= (REG_PC << 16);
7641 pre_inc = 1;
1cac9012
NC
7642 }
7643 else
7644 {
90e4755a
RE
7645 if (my_get_expression (&inst.reloc.exp, &str))
7646 return;
7647
7648 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7649#ifndef TE_WINCE
7650 /* PC rel adjust. */
7651 inst.reloc.exp.X_add_number -= 8;
7652#endif
1cac9012 7653 inst.reloc.pc_rel = 1;
90e4755a
RE
7654 inst.instruction |= (REG_PC << 16);
7655 pre_inc = 1;
b99bd4ef
NC
7656 }
7657
90e4755a 7658 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7659 end_of_line (str);
90e4755a 7660 return;
b99bd4ef
NC
7661}
7662
7663static void
f2b7cb0a 7664do_ldstt (str)
90e4755a 7665 char * str;
b99bd4ef 7666{
90e4755a
RE
7667 int conflict_reg;
7668
b99bd4ef
NC
7669 skip_whitespace (str);
7670
90e4755a 7671 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7672 {
7673 if (!inst.error)
7674 inst.error = BAD_ARGS;
7675 return;
7676 }
7677
90e4755a 7678 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7679 {
f03698e6 7680 inst.error = _("address expected");
b99bd4ef
NC
7681 return;
7682 }
7683
90e4755a
RE
7684 if (*str == '[')
7685 {
7686 int reg;
b99bd4ef 7687
90e4755a 7688 str++;
b99bd4ef 7689
90e4755a 7690 skip_whitespace (str);
b99bd4ef 7691
90e4755a
RE
7692 if ((reg = reg_required_here (&str, 16)) == FAIL)
7693 return;
b99bd4ef 7694
90e4755a
RE
7695 /* ldrt/strt always use post-indexed addressing, so if the base is
7696 the same as Rd, we warn. */
7697 if (conflict_reg == reg)
7698 as_warn (_("%s register same as write-back base"),
7699 ((inst.instruction & LOAD_BIT)
7700 ? _("destination") : _("source")));
7701
7702 skip_whitespace (str);
7703
7704 if (*str == ']')
7705 {
7706 str ++;
7707
7708 if (skip_past_comma (&str) == SUCCESS)
7709 {
7710 /* [Rn],... (post inc) */
7711 if (ldst_extend (&str) == FAIL)
7712 return;
7713 }
7714 else
7715 {
7716 /* [Rn] */
7717 skip_whitespace (str);
7718
7719 /* Skip a write-back '!'. */
7720 if (*str == '!')
7721 str++;
7722
7723 inst.instruction |= INDEX_UP;
7724 }
7725 }
7726 else
7727 {
7728 inst.error = _("post-indexed expression expected");
7729 return;
7730 }
7731 }
7732 else
b99bd4ef 7733 {
90e4755a 7734 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7735 return;
7736 }
7737
b99bd4ef
NC
7738 end_of_line (str);
7739 return;
7740}
7741
7742static int
90e4755a 7743ldst_extend_v4 (str)
b99bd4ef 7744 char ** str;
b99bd4ef
NC
7745{
7746 int add = INDEX_UP;
7747
7748 switch (**str)
7749 {
7750 case '#':
7751 case '$':
7752 (*str)++;
7753 if (my_get_expression (& inst.reloc.exp, str))
7754 return FAIL;
7755
7756 if (inst.reloc.exp.X_op == O_constant)
7757 {
7758 int value = inst.reloc.exp.X_add_number;
7759
90e4755a 7760 if (value < -255 || value > 255)
b99bd4ef
NC
7761 {
7762 inst.error = _("address offset too large");
7763 return FAIL;
7764 }
7765
7766 if (value < 0)
7767 {
7768 value = -value;
7769 add = 0;
7770 }
7771
7772 /* Halfword and signextension instructions have the
7773 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7774 inst.instruction |= (add | HWOFFSET_IMM
7775 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7776 }
7777 else
7778 {
90e4755a
RE
7779 inst.instruction |= HWOFFSET_IMM;
7780 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7781 inst.reloc.pc_rel = 0;
7782 }
7783 return SUCCESS;
7784
7785 case '-':
7786 add = 0;
7787 /* Fall through. */
7788
7789 case '+':
7790 (*str)++;
7791 /* Fall through. */
7792
7793 default:
7794 if (reg_required_here (str, 0) == FAIL)
7795 return FAIL;
7796
90e4755a 7797 inst.instruction |= add;
b99bd4ef
NC
7798 return SUCCESS;
7799 }
7800}
7801
90e4755a 7802/* Halfword and signed-byte load/store operations. */
b99bd4ef 7803static void
f2b7cb0a 7804do_ldstv4 (str)
b99bd4ef 7805 char * str;
b99bd4ef 7806{
b99bd4ef
NC
7807 int pre_inc = 0;
7808 int conflict_reg;
7809 int value;
7810
b99bd4ef
NC
7811 skip_whitespace (str);
7812
7813 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7814 {
7815 if (!inst.error)
7816 inst.error = BAD_ARGS;
7817 return;
7818 }
7819
7820 if (skip_past_comma (& str) == FAIL)
7821 {
f03698e6 7822 inst.error = _("address expected");
b99bd4ef
NC
7823 return;
7824 }
7825
7826 if (*str == '[')
7827 {
7828 int reg;
7829
7830 str++;
7831
7832 skip_whitespace (str);
7833
7834 if ((reg = reg_required_here (&str, 16)) == FAIL)
7835 return;
7836
7837 /* Conflicts can occur on stores as well as loads. */
7838 conflict_reg = (conflict_reg == reg);
7839
7840 skip_whitespace (str);
7841
7842 if (*str == ']')
7843 {
7844 str ++;
7845
7846 if (skip_past_comma (&str) == SUCCESS)
7847 {
7848 /* [Rn],... (post inc) */
90e4755a 7849 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7850 return;
7851 if (conflict_reg)
90e4755a
RE
7852 as_warn (_("%s register same as write-back base"),
7853 ((inst.instruction & LOAD_BIT)
7854 ? _("destination") : _("source")));
b99bd4ef
NC
7855 }
7856 else
7857 {
7858 /* [Rn] */
90e4755a 7859 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7860
7861 skip_whitespace (str);
7862
7863 if (*str == '!')
7864 {
7865 if (conflict_reg)
7866 as_warn (_("%s register same as write-back base"),
7867 ((inst.instruction & LOAD_BIT)
7868 ? _("destination") : _("source")));
7869 str++;
7870 inst.instruction |= WRITE_BACK;
7871 }
7872
90e4755a
RE
7873 inst.instruction |= INDEX_UP;
7874 pre_inc = 1;
b99bd4ef
NC
7875 }
7876 }
7877 else
7878 {
7879 /* [Rn,...] */
7880 if (skip_past_comma (&str) == FAIL)
7881 {
7882 inst.error = _("pre-indexed expression expected");
7883 return;
7884 }
7885
7886 pre_inc = 1;
90e4755a 7887 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7888 return;
7889
7890 skip_whitespace (str);
7891
7892 if (*str++ != ']')
7893 {
7894 inst.error = _("missing ]");
7895 return;
7896 }
7897
7898 skip_whitespace (str);
7899
7900 if (*str == '!')
7901 {
7902 if (conflict_reg)
7903 as_warn (_("%s register same as write-back base"),
7904 ((inst.instruction & LOAD_BIT)
7905 ? _("destination") : _("source")));
7906 str++;
7907 inst.instruction |= WRITE_BACK;
7908 }
7909 }
7910 }
7911 else if (*str == '=')
7912 {
f03698e6
RE
7913 if ((inst.instruction & LOAD_BIT) == 0)
7914 {
7915 inst.error = _("invalid pseudo operation");
7916 return;
7917 }
7918
90e4755a 7919 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7920 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7921 str++;
7922
7923 skip_whitespace (str);
7924
7925 if (my_get_expression (&inst.reloc.exp, &str))
7926 return;
7927
7928 if (inst.reloc.exp.X_op != O_constant
7929 && inst.reloc.exp.X_op != O_symbol)
7930 {
f03698e6 7931 inst.error = _("constant expression expected");
b99bd4ef
NC
7932 return;
7933 }
7934
d8273442 7935 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7936 {
d8273442
NC
7937 value = validate_immediate (inst.reloc.exp.X_add_number);
7938
7939 if (value != FAIL)
b99bd4ef 7940 {
d8273442
NC
7941 /* This can be done with a mov instruction. */
7942 inst.instruction &= LITERAL_MASK;
7943 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7944 inst.instruction |= value & 0xfff;
d8273442 7945 end_of_line (str);
b99bd4ef
NC
7946 return;
7947 }
cc8a6dd0 7948
d8273442 7949 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7950
d8273442 7951 if (value != FAIL)
b99bd4ef 7952 {
d8273442
NC
7953 /* This can be done with a mvn instruction. */
7954 inst.instruction &= LITERAL_MASK;
7955 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7956 inst.instruction |= value & 0xfff;
d8273442
NC
7957 end_of_line (str);
7958 return;
b99bd4ef 7959 }
b99bd4ef 7960 }
d8273442
NC
7961
7962 /* Insert into literal pool. */
7963 if (add_to_lit_pool () == FAIL)
7964 {
7965 if (!inst.error)
7966 inst.error = _("literal pool insertion failed");
7967 return;
7968 }
7969
7970 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7971 inst.instruction |= HWOFFSET_IMM;
7972 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7973 inst.reloc.pc_rel = 1;
7974 inst.instruction |= (REG_PC << 16);
7975 pre_inc = 1;
b99bd4ef
NC
7976 }
7977 else
7978 {
7979 if (my_get_expression (&inst.reloc.exp, &str))
7980 return;
7981
90e4755a
RE
7982 inst.instruction |= HWOFFSET_IMM;
7983 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7984#ifndef TE_WINCE
7985 /* PC rel adjust. */
7986 inst.reloc.exp.X_add_number -= 8;
7987#endif
7988 inst.reloc.pc_rel = 1;
7989 inst.instruction |= (REG_PC << 16);
7990 pre_inc = 1;
7991 }
7992
90e4755a 7993 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef
NC
7994 end_of_line (str);
7995 return;
7996}
7997
7998static long
7999reg_list (strp)
8000 char ** strp;
8001{
8002 char * str = * strp;
8003 long range = 0;
8004 int another_range;
8005
8006 /* We come back here if we get ranges concatenated by '+' or '|'. */
8007 do
8008 {
8009 another_range = 0;
8010
8011 if (*str == '{')
8012 {
8013 int in_range = 0;
8014 int cur_reg = -1;
8015
8016 str++;
8017 do
8018 {
8019 int reg;
8020
8021 skip_whitespace (str);
8022
8023 if ((reg = reg_required_here (& str, -1)) == FAIL)
8024 return FAIL;
8025
8026 if (in_range)
8027 {
8028 int i;
8029
8030 if (reg <= cur_reg)
8031 {
f03698e6 8032 inst.error = _("bad range in register list");
b99bd4ef
NC
8033 return FAIL;
8034 }
8035
8036 for (i = cur_reg + 1; i < reg; i++)
8037 {
8038 if (range & (1 << i))
8039 as_tsktsk
f03698e6 8040 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8041 i);
8042 else
8043 range |= 1 << i;
8044 }
8045 in_range = 0;
8046 }
8047
8048 if (range & (1 << reg))
f03698e6 8049 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8050 reg);
8051 else if (reg <= cur_reg)
f03698e6 8052 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
8053
8054 range |= 1 << reg;
8055 cur_reg = reg;
8056 }
8057 while (skip_past_comma (&str) != FAIL
8058 || (in_range = 1, *str++ == '-'));
8059 str--;
8060 skip_whitespace (str);
8061
8062 if (*str++ != '}')
8063 {
f03698e6 8064 inst.error = _("missing `}'");
b99bd4ef
NC
8065 return FAIL;
8066 }
8067 }
8068 else
8069 {
8070 expressionS expr;
8071
8072 if (my_get_expression (&expr, &str))
8073 return FAIL;
8074
8075 if (expr.X_op == O_constant)
8076 {
8077 if (expr.X_add_number
8078 != (expr.X_add_number & 0x0000ffff))
8079 {
8080 inst.error = _("invalid register mask");
8081 return FAIL;
8082 }
8083
8084 if ((range & expr.X_add_number) != 0)
8085 {
8086 int regno = range & expr.X_add_number;
8087
8088 regno &= -regno;
8089 regno = (1 << regno) - 1;
8090 as_tsktsk
f03698e6 8091 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8092 regno);
8093 }
8094
8095 range |= expr.X_add_number;
8096 }
8097 else
8098 {
8099 if (inst.reloc.type != 0)
8100 {
8101 inst.error = _("expression too complex");
8102 return FAIL;
8103 }
8104
8105 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8106 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8107 inst.reloc.pc_rel = 0;
8108 }
8109 }
8110
8111 skip_whitespace (str);
8112
8113 if (*str == '|' || *str == '+')
8114 {
8115 str++;
8116 another_range = 1;
8117 }
8118 }
8119 while (another_range);
8120
8121 *strp = str;
8122 return range;
8123}
8124
8125static void
f2b7cb0a 8126do_ldmstm (str)
b99bd4ef 8127 char * str;
b99bd4ef
NC
8128{
8129 int base_reg;
8130 long range;
8131
8132 skip_whitespace (str);
8133
8134 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8135 return;
8136
8137 if (base_reg == REG_PC)
8138 {
8139 inst.error = _("r15 not allowed as base register");
8140 return;
8141 }
8142
8143 skip_whitespace (str);
8144
8145 if (*str == '!')
8146 {
90e4755a 8147 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8148 str++;
8149 }
8150
8151 if (skip_past_comma (&str) == FAIL
8152 || (range = reg_list (&str)) == FAIL)
8153 {
8154 if (! inst.error)
8155 inst.error = BAD_ARGS;
8156 return;
8157 }
8158
8159 if (*str == '^')
8160 {
8161 str++;
90e4755a 8162 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8163 }
8164
6189168b
NC
8165 if (inst.instruction & WRITE_BACK)
8166 {
8167 /* Check for unpredictable uses of writeback. */
8168 if (inst.instruction & LOAD_BIT)
8169 {
8170 /* Not allowed in LDM type 2. */
8171 if ((inst.instruction & LDM_TYPE_2_OR_3)
8172 && ((range & (1 << REG_PC)) == 0))
8173 as_warn (_("writeback of base register is UNPREDICTABLE"));
8174 /* Only allowed if base reg not in list for other types. */
8175 else if (range & (1 << base_reg))
8176 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8177 }
8178 else /* STM. */
8179 {
8180 /* Not allowed for type 2. */
8181 if (inst.instruction & LDM_TYPE_2_OR_3)
8182 as_warn (_("writeback of base register is UNPREDICTABLE"));
8183 /* Only allowed if base reg not in list, or first in list. */
8184 else if ((range & (1 << base_reg))
8185 && (range & ((1 << base_reg) - 1)))
8186 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8187 }
8188 }
61b5f74b 8189
f2b7cb0a 8190 inst.instruction |= range;
b99bd4ef
NC
8191 end_of_line (str);
8192 return;
8193}
8194
8195static void
f2b7cb0a 8196do_swi (str)
b99bd4ef 8197 char * str;
b99bd4ef
NC
8198{
8199 skip_whitespace (str);
8200
8201 /* Allow optional leading '#'. */
8202 if (is_immediate_prefix (*str))
8203 str++;
8204
8205 if (my_get_expression (& inst.reloc.exp, & str))
8206 return;
8207
8208 inst.reloc.type = BFD_RELOC_ARM_SWI;
8209 inst.reloc.pc_rel = 0;
b99bd4ef
NC
8210 end_of_line (str);
8211
8212 return;
8213}
8214
8215static void
f2b7cb0a 8216do_swap (str)
b99bd4ef 8217 char * str;
b99bd4ef
NC
8218{
8219 int reg;
8220
8221 skip_whitespace (str);
8222
8223 if ((reg = reg_required_here (&str, 12)) == FAIL)
8224 return;
8225
8226 if (reg == REG_PC)
8227 {
8228 inst.error = _("r15 not allowed in swap");
8229 return;
8230 }
8231
8232 if (skip_past_comma (&str) == FAIL
8233 || (reg = reg_required_here (&str, 0)) == FAIL)
8234 {
8235 if (!inst.error)
8236 inst.error = BAD_ARGS;
8237 return;
8238 }
8239
8240 if (reg == REG_PC)
8241 {
8242 inst.error = _("r15 not allowed in swap");
8243 return;
8244 }
8245
8246 if (skip_past_comma (&str) == FAIL
8247 || *str++ != '[')
8248 {
8249 inst.error = BAD_ARGS;
8250 return;
8251 }
8252
8253 skip_whitespace (str);
8254
8255 if ((reg = reg_required_here (&str, 16)) == FAIL)
8256 return;
8257
8258 if (reg == REG_PC)
8259 {
8260 inst.error = BAD_PC;
8261 return;
8262 }
8263
8264 skip_whitespace (str);
8265
8266 if (*str++ != ']')
8267 {
8268 inst.error = _("missing ]");
8269 return;
8270 }
8271
b99bd4ef
NC
8272 end_of_line (str);
8273 return;
8274}
8275
8276static void
f2b7cb0a 8277do_branch (str)
b99bd4ef 8278 char * str;
b99bd4ef
NC
8279{
8280 if (my_get_expression (&inst.reloc.exp, &str))
8281 return;
8282
8283#ifdef OBJ_ELF
8284 {
8285 char * save_in;
8286
8287 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8288 required for the instruction. */
8289
8290 /* arm_parse_reloc () works on input_line_pointer.
8291 We actually want to parse the operands to the branch instruction
8292 passed in 'str'. Save the input pointer and restore it later. */
8293 save_in = input_line_pointer;
8294 input_line_pointer = str;
8295 if (inst.reloc.exp.X_op == O_symbol
8296 && *str == '('
8297 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8298 {
8299 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8300 inst.reloc.pc_rel = 0;
8301 /* Modify str to point to after parsed operands, otherwise
8302 end_of_line() will complain about the (PLT) left in str. */
8303 str = input_line_pointer;
8304 }
8305 else
8306 {
8307 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8308 inst.reloc.pc_rel = 1;
8309 }
8310 input_line_pointer = save_in;
8311 }
8312#else
8313 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8314 inst.reloc.pc_rel = 1;
8315#endif /* OBJ_ELF */
8316
8317 end_of_line (str);
8318 return;
8319}
8320
8321static void
f2b7cb0a 8322do_bx (str)
b99bd4ef 8323 char * str;
b99bd4ef
NC
8324{
8325 int reg;
8326
8327 skip_whitespace (str);
8328
8329 if ((reg = reg_required_here (&str, 0)) == FAIL)
8330 {
8331 inst.error = BAD_ARGS;
8332 return;
8333 }
8334
8335 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8336 if (reg == REG_PC)
f03698e6 8337 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8338
8339 end_of_line (str);
8340}
8341
8342static void
f2b7cb0a 8343do_cdp (str)
b99bd4ef 8344 char * str;
b99bd4ef
NC
8345{
8346 /* Co-processor data operation.
8347 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8348 skip_whitespace (str);
8349
8350 if (co_proc_number (&str) == FAIL)
8351 {
8352 if (!inst.error)
8353 inst.error = BAD_ARGS;
8354 return;
8355 }
8356
8357 if (skip_past_comma (&str) == FAIL
8358 || cp_opc_expr (&str, 20,4) == FAIL)
8359 {
8360 if (!inst.error)
8361 inst.error = BAD_ARGS;
8362 return;
8363 }
8364
8365 if (skip_past_comma (&str) == FAIL
8366 || cp_reg_required_here (&str, 12) == FAIL)
8367 {
8368 if (!inst.error)
8369 inst.error = BAD_ARGS;
8370 return;
8371 }
8372
8373 if (skip_past_comma (&str) == FAIL
8374 || cp_reg_required_here (&str, 16) == FAIL)
8375 {
8376 if (!inst.error)
8377 inst.error = BAD_ARGS;
8378 return;
8379 }
8380
8381 if (skip_past_comma (&str) == FAIL
8382 || cp_reg_required_here (&str, 0) == FAIL)
8383 {
8384 if (!inst.error)
8385 inst.error = BAD_ARGS;
8386 return;
8387 }
8388
8389 if (skip_past_comma (&str) == SUCCESS)
8390 {
8391 if (cp_opc_expr (&str, 5, 3) == FAIL)
8392 {
8393 if (!inst.error)
8394 inst.error = BAD_ARGS;
8395 return;
8396 }
8397 }
8398
8399 end_of_line (str);
8400 return;
8401}
8402
8403static void
f2b7cb0a 8404do_lstc (str)
b99bd4ef 8405 char * str;
b99bd4ef
NC
8406{
8407 /* Co-processor register load/store.
8408 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8409
8410 skip_whitespace (str);
8411
8412 if (co_proc_number (&str) == FAIL)
8413 {
8414 if (!inst.error)
8415 inst.error = BAD_ARGS;
8416 return;
8417 }
8418
8419 if (skip_past_comma (&str) == FAIL
8420 || cp_reg_required_here (&str, 12) == FAIL)
8421 {
8422 if (!inst.error)
8423 inst.error = BAD_ARGS;
8424 return;
8425 }
8426
8427 if (skip_past_comma (&str) == FAIL
bfae80f2 8428 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8429 {
8430 if (! inst.error)
8431 inst.error = BAD_ARGS;
8432 return;
8433 }
8434
b99bd4ef
NC
8435 end_of_line (str);
8436 return;
8437}
8438
8439static void
f2b7cb0a 8440do_co_reg (str)
b99bd4ef 8441 char * str;
b99bd4ef
NC
8442{
8443 /* Co-processor register transfer.
8444 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8445
8446 skip_whitespace (str);
8447
8448 if (co_proc_number (&str) == FAIL)
8449 {
8450 if (!inst.error)
8451 inst.error = BAD_ARGS;
8452 return;
8453 }
8454
8455 if (skip_past_comma (&str) == FAIL
8456 || cp_opc_expr (&str, 21, 3) == FAIL)
8457 {
8458 if (!inst.error)
8459 inst.error = BAD_ARGS;
8460 return;
8461 }
8462
8463 if (skip_past_comma (&str) == FAIL
8464 || reg_required_here (&str, 12) == FAIL)
8465 {
8466 if (!inst.error)
8467 inst.error = BAD_ARGS;
8468 return;
8469 }
8470
8471 if (skip_past_comma (&str) == FAIL
8472 || cp_reg_required_here (&str, 16) == FAIL)
8473 {
8474 if (!inst.error)
8475 inst.error = BAD_ARGS;
8476 return;
8477 }
8478
8479 if (skip_past_comma (&str) == FAIL
8480 || cp_reg_required_here (&str, 0) == FAIL)
8481 {
8482 if (!inst.error)
8483 inst.error = BAD_ARGS;
8484 return;
8485 }
8486
8487 if (skip_past_comma (&str) == SUCCESS)
8488 {
8489 if (cp_opc_expr (&str, 5, 3) == FAIL)
8490 {
8491 if (!inst.error)
8492 inst.error = BAD_ARGS;
8493 return;
8494 }
8495 }
b99bd4ef
NC
8496
8497 end_of_line (str);
8498 return;
8499}
8500
8501static void
f2b7cb0a 8502do_fpa_ctrl (str)
b99bd4ef 8503 char * str;
b99bd4ef
NC
8504{
8505 /* FP control registers.
8506 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8507
8508 skip_whitespace (str);
8509
8510 if (reg_required_here (&str, 12) == FAIL)
8511 {
8512 if (!inst.error)
8513 inst.error = BAD_ARGS;
8514 return;
8515 }
8516
8517 end_of_line (str);
8518 return;
8519}
8520
8521static void
f2b7cb0a 8522do_fpa_ldst (str)
b99bd4ef 8523 char * str;
b99bd4ef
NC
8524{
8525 skip_whitespace (str);
8526
b99bd4ef
NC
8527 if (fp_reg_required_here (&str, 12) == FAIL)
8528 {
8529 if (!inst.error)
8530 inst.error = BAD_ARGS;
8531 return;
8532 }
8533
8534 if (skip_past_comma (&str) == FAIL
bfae80f2 8535 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8536 {
8537 if (!inst.error)
8538 inst.error = BAD_ARGS;
8539 return;
8540 }
8541
8542 end_of_line (str);
8543}
8544
8545static void
f2b7cb0a 8546do_fpa_ldmstm (str)
b99bd4ef 8547 char * str;
b99bd4ef
NC
8548{
8549 int num_regs;
8550
8551 skip_whitespace (str);
8552
8553 if (fp_reg_required_here (&str, 12) == FAIL)
8554 {
8555 if (! inst.error)
8556 inst.error = BAD_ARGS;
8557 return;
8558 }
8559
8560 /* Get Number of registers to transfer. */
8561 if (skip_past_comma (&str) == FAIL
8562 || my_get_expression (&inst.reloc.exp, &str))
8563 {
8564 if (! inst.error)
8565 inst.error = _("constant expression expected");
8566 return;
8567 }
8568
8569 if (inst.reloc.exp.X_op != O_constant)
8570 {
f03698e6 8571 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8572 return;
8573 }
8574
8575 num_regs = inst.reloc.exp.X_add_number;
8576
8577 if (num_regs < 1 || num_regs > 4)
8578 {
8579 inst.error = _("number of registers must be in the range [1:4]");
8580 return;
8581 }
8582
8583 switch (num_regs)
8584 {
8585 case 1:
8586 inst.instruction |= CP_T_X;
8587 break;
8588 case 2:
8589 inst.instruction |= CP_T_Y;
8590 break;
8591 case 3:
8592 inst.instruction |= CP_T_Y | CP_T_X;
8593 break;
8594 case 4:
8595 break;
8596 default:
8597 abort ();
8598 }
8599
e28cd48c 8600 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8601 {
8602 int reg;
8603 int write_back;
8604 int offset;
8605
8606 /* The instruction specified "ea" or "fd", so we can only accept
8607 [Rn]{!}. The instruction does not really support stacking or
8608 unstacking, so we have to emulate these by setting appropriate
8609 bits and offsets. */
8610 if (skip_past_comma (&str) == FAIL
8611 || *str != '[')
8612 {
8613 if (! inst.error)
8614 inst.error = BAD_ARGS;
8615 return;
8616 }
8617
8618 str++;
8619 skip_whitespace (str);
8620
8621 if ((reg = reg_required_here (&str, 16)) == FAIL)
8622 return;
8623
8624 skip_whitespace (str);
8625
8626 if (*str != ']')
8627 {
8628 inst.error = BAD_ARGS;
8629 return;
8630 }
8631
8632 str++;
8633 if (*str == '!')
8634 {
8635 write_back = 1;
8636 str++;
8637 if (reg == REG_PC)
8638 {
8639 inst.error =
f03698e6 8640 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8641 return;
8642 }
8643 }
8644 else
8645 write_back = 0;
8646
90e4755a 8647 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8648 {
8649 /* Pre-decrement. */
8650 offset = 3 * num_regs;
8651 if (write_back)
90e4755a 8652 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8653 }
8654 else
8655 {
8656 /* Post-increment. */
8657 if (write_back)
8658 {
90e4755a 8659 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8660 offset = 3 * num_regs;
8661 }
8662 else
8663 {
8664 /* No write-back, so convert this into a standard pre-increment
8665 instruction -- aesthetically more pleasing. */
90e4755a 8666 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8667 offset = 0;
8668 }
8669 }
8670
f2b7cb0a 8671 inst.instruction |= offset;
b99bd4ef
NC
8672 }
8673 else if (skip_past_comma (&str) == FAIL
bfae80f2 8674 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8675 {
8676 if (! inst.error)
8677 inst.error = BAD_ARGS;
8678 return;
8679 }
8680
8681 end_of_line (str);
8682}
8683
8684static void
f2b7cb0a 8685do_fpa_dyadic (str)
b99bd4ef 8686 char * str;
b99bd4ef
NC
8687{
8688 skip_whitespace (str);
8689
b99bd4ef
NC
8690 if (fp_reg_required_here (&str, 12) == FAIL)
8691 {
8692 if (! inst.error)
8693 inst.error = BAD_ARGS;
8694 return;
8695 }
8696
8697 if (skip_past_comma (&str) == FAIL
8698 || fp_reg_required_here (&str, 16) == FAIL)
8699 {
8700 if (! inst.error)
8701 inst.error = BAD_ARGS;
8702 return;
8703 }
8704
8705 if (skip_past_comma (&str) == FAIL
8706 || fp_op2 (&str) == FAIL)
8707 {
8708 if (! inst.error)
8709 inst.error = BAD_ARGS;
8710 return;
8711 }
8712
b99bd4ef
NC
8713 end_of_line (str);
8714 return;
8715}
8716
8717static void
f2b7cb0a 8718do_fpa_monadic (str)
b99bd4ef 8719 char * str;
b99bd4ef
NC
8720{
8721 skip_whitespace (str);
8722
b99bd4ef
NC
8723 if (fp_reg_required_here (&str, 12) == FAIL)
8724 {
8725 if (! inst.error)
8726 inst.error = BAD_ARGS;
8727 return;
8728 }
8729
8730 if (skip_past_comma (&str) == FAIL
8731 || fp_op2 (&str) == FAIL)
8732 {
8733 if (! inst.error)
8734 inst.error = BAD_ARGS;
8735 return;
8736 }
8737
b99bd4ef
NC
8738 end_of_line (str);
8739 return;
8740}
8741
8742static void
f2b7cb0a 8743do_fpa_cmp (str)
b99bd4ef 8744 char * str;
b99bd4ef
NC
8745{
8746 skip_whitespace (str);
8747
8748 if (fp_reg_required_here (&str, 16) == FAIL)
8749 {
8750 if (! inst.error)
8751 inst.error = BAD_ARGS;
8752 return;
8753 }
8754
8755 if (skip_past_comma (&str) == FAIL
8756 || fp_op2 (&str) == FAIL)
8757 {
8758 if (! inst.error)
8759 inst.error = BAD_ARGS;
8760 return;
8761 }
8762
b99bd4ef
NC
8763 end_of_line (str);
8764 return;
8765}
8766
8767static void
f2b7cb0a 8768do_fpa_from_reg (str)
b99bd4ef 8769 char * str;
b99bd4ef
NC
8770{
8771 skip_whitespace (str);
8772
b99bd4ef
NC
8773 if (fp_reg_required_here (&str, 16) == FAIL)
8774 {
8775 if (! inst.error)
8776 inst.error = BAD_ARGS;
8777 return;
8778 }
8779
8780 if (skip_past_comma (&str) == FAIL
8781 || reg_required_here (&str, 12) == FAIL)
8782 {
8783 if (! inst.error)
8784 inst.error = BAD_ARGS;
8785 return;
8786 }
8787
b99bd4ef
NC
8788 end_of_line (str);
8789 return;
8790}
8791
8792static void
f2b7cb0a 8793do_fpa_to_reg (str)
b99bd4ef 8794 char * str;
b99bd4ef
NC
8795{
8796 skip_whitespace (str);
8797
8798 if (reg_required_here (&str, 12) == FAIL)
8799 return;
8800
8801 if (skip_past_comma (&str) == FAIL
8802 || fp_reg_required_here (&str, 0) == FAIL)
8803 {
8804 if (! inst.error)
8805 inst.error = BAD_ARGS;
8806 return;
8807 }
8808
b99bd4ef
NC
8809 end_of_line (str);
8810 return;
8811}
8812
b99bd4ef 8813static int
bfae80f2
RE
8814vfp_sp_reg_required_here (str, pos)
8815 char **str;
8816 enum vfp_sp_reg_pos pos;
b99bd4ef 8817{
bfae80f2
RE
8818 int reg;
8819 char *start = *str;
b99bd4ef 8820
bfae80f2 8821 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8822 {
bfae80f2 8823 switch (pos)
b99bd4ef 8824 {
bfae80f2
RE
8825 case VFP_REG_Sd:
8826 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8827 break;
8828
8829 case VFP_REG_Sn:
8830 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8831 break;
8832
8833 case VFP_REG_Sm:
8834 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8835 break;
8836
8837 default:
8838 abort ();
b99bd4ef 8839 }
bfae80f2
RE
8840 return reg;
8841 }
b99bd4ef 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_SN].expected);
8846
8847 /* Restore the start point. */
8848 *str = start;
8849 return FAIL;
8850}
8851
8852static int
8853vfp_dp_reg_required_here (str, pos)
8854 char **str;
f201ccb3 8855 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8856{
8857 int reg;
8858 char *start = *str;
8859
8860 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8861 {
8862 switch (pos)
b99bd4ef 8863 {
bfae80f2
RE
8864 case VFP_REG_Dd:
8865 inst.instruction |= reg << 12;
8866 break;
b99bd4ef 8867
bfae80f2
RE
8868 case VFP_REG_Dn:
8869 inst.instruction |= reg << 16;
8870 break;
8871
8872 case VFP_REG_Dm:
8873 inst.instruction |= reg << 0;
8874 break;
8875
8876 default:
8877 abort ();
8878 }
8879 return reg;
b99bd4ef
NC
8880 }
8881
bfae80f2
RE
8882 /* In the few cases where we might be able to accept something else
8883 this error can be overridden. */
8884 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8885
bfae80f2
RE
8886 /* Restore the start point. */
8887 *str = start;
8888 return FAIL;
8889}
b99bd4ef
NC
8890
8891static void
bfae80f2
RE
8892do_vfp_sp_monadic (str)
8893 char *str;
b99bd4ef 8894{
b99bd4ef
NC
8895 skip_whitespace (str);
8896
bfae80f2
RE
8897 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8898 return;
8899
8900 if (skip_past_comma (&str) == FAIL
8901 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8902 {
8903 if (! inst.error)
8904 inst.error = BAD_ARGS;
8905 return;
8906 }
8907
bfae80f2
RE
8908 end_of_line (str);
8909 return;
8910}
8911
8912static void
8913do_vfp_dp_monadic (str)
8914 char *str;
8915{
8916 skip_whitespace (str);
8917
8918 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8919 return;
8920
8921 if (skip_past_comma (&str) == FAIL
8922 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8923 {
bfae80f2
RE
8924 if (! inst.error)
8925 inst.error = BAD_ARGS;
8926 return;
b99bd4ef 8927 }
b99bd4ef 8928
bfae80f2
RE
8929 end_of_line (str);
8930 return;
8931}
b99bd4ef 8932
bfae80f2
RE
8933static void
8934do_vfp_sp_dyadic (str)
8935 char *str;
8936{
8937 skip_whitespace (str);
b99bd4ef 8938
bfae80f2
RE
8939 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8940 return;
b99bd4ef 8941
bfae80f2
RE
8942 if (skip_past_comma (&str) == FAIL
8943 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8944 || skip_past_comma (&str) == FAIL
8945 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8946 {
bfae80f2
RE
8947 if (! inst.error)
8948 inst.error = BAD_ARGS;
8949 return;
8950 }
b99bd4ef 8951
bfae80f2
RE
8952 end_of_line (str);
8953 return;
8954}
b99bd4ef 8955
bfae80f2
RE
8956static void
8957do_vfp_dp_dyadic (str)
8958 char *str;
8959{
8960 skip_whitespace (str);
b99bd4ef 8961
bfae80f2
RE
8962 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8963 return;
b99bd4ef 8964
bfae80f2
RE
8965 if (skip_past_comma (&str) == FAIL
8966 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8967 || skip_past_comma (&str) == FAIL
8968 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8969 {
8970 if (! inst.error)
8971 inst.error = BAD_ARGS;
8972 return;
8973 }
b99bd4ef 8974
bfae80f2
RE
8975 end_of_line (str);
8976 return;
8977}
b99bd4ef 8978
bfae80f2
RE
8979static void
8980do_vfp_reg_from_sp (str)
8981 char *str;
8982{
8983 skip_whitespace (str);
8984
8985 if (reg_required_here (&str, 12) == FAIL)
8986 return;
8987
8988 if (skip_past_comma (&str) == FAIL
8989 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8990 {
8991 if (! inst.error)
8992 inst.error = BAD_ARGS;
8993 return;
8994 }
8995
8996 end_of_line (str);
8997 return;
8998}
8999
9000static void
9001do_vfp_sp_reg2 (str)
9002 char *str;
9003{
9004 skip_whitespace (str);
9005
9006 if (reg_required_here (&str, 12) == FAIL)
9007 return;
9008
9009 if (skip_past_comma (&str) == FAIL
9010 || reg_required_here (&str, 16) == FAIL
9011 || skip_past_comma (&str) == FAIL)
9012 {
9013 if (! inst.error)
9014 inst.error = BAD_ARGS;
9015 return;
9016 }
9017
9018 /* We require exactly two consecutive SP registers. */
9019 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9020 {
9021 if (! inst.error)
9022 inst.error = _("only two consecutive VFP SP registers allowed here");
9023 }
9024
9025 end_of_line (str);
9026 return;
9027}
9028
9029static void
9030do_vfp_sp_from_reg (str)
9031 char *str;
9032{
9033 skip_whitespace (str);
9034
9035 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
9036 return;
9037
9038 if (skip_past_comma (&str) == FAIL
9039 || reg_required_here (&str, 12) == FAIL)
9040 {
9041 if (! inst.error)
9042 inst.error = BAD_ARGS;
9043 return;
9044 }
9045
9046 end_of_line (str);
9047 return;
9048}
9049
9050static void
9051do_vfp_reg_from_dp (str)
9052 char *str;
9053{
9054 skip_whitespace (str);
9055
9056 if (reg_required_here (&str, 12) == FAIL)
9057 return;
9058
9059 if (skip_past_comma (&str) == FAIL
9060 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9061 {
9062 if (! inst.error)
9063 inst.error = BAD_ARGS;
9064 return;
9065 }
9066
9067 end_of_line (str);
9068 return;
9069}
9070
9071static void
9072do_vfp_reg2_from_dp (str)
9073 char *str;
9074{
9075 skip_whitespace (str);
9076
9077 if (reg_required_here (&str, 12) == FAIL)
9078 return;
9079
9080 if (skip_past_comma (&str) == FAIL
9081 || reg_required_here (&str, 16) == FAIL
9082 || skip_past_comma (&str) == FAIL
9083 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9084 {
9085 if (! inst.error)
9086 inst.error = BAD_ARGS;
9087 return;
9088 }
9089
9090 end_of_line (str);
9091 return;
9092}
9093
9094static void
9095do_vfp_dp_from_reg (str)
9096 char *str;
9097{
9098 skip_whitespace (str);
9099
9100 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9101 return;
9102
9103 if (skip_past_comma (&str) == FAIL
9104 || reg_required_here (&str, 12) == FAIL)
9105 {
9106 if (! inst.error)
9107 inst.error = BAD_ARGS;
9108 return;
9109 }
9110
9111 end_of_line (str);
9112 return;
9113}
9114
9115static void
9116do_vfp_dp_from_reg2 (str)
9117 char *str;
9118{
9119 skip_whitespace (str);
9120
9121 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9122 return;
9123
9124 if (skip_past_comma (&str) == FAIL
9125 || reg_required_here (&str, 12) == FAIL
9126 || skip_past_comma (&str) == FAIL
9127 || reg_required_here (&str, 16))
9128 {
9129 if (! inst.error)
9130 inst.error = BAD_ARGS;
9131 return;
9132 }
9133
9134 end_of_line (str);
9135 return;
9136}
9137
9138static const struct vfp_reg *
9139vfp_psr_parse (str)
9140 char **str;
9141{
9142 char *start = *str;
9143 char c;
9144 char *p;
9145 const struct vfp_reg *vreg;
9146
9147 p = start;
9148
9149 /* Find the end of the current token. */
9150 do
9151 {
9152 c = *p++;
9153 }
9154 while (ISALPHA (c));
9155
9156 /* Mark it. */
9157 *--p = 0;
9158
cc8a6dd0 9159 for (vreg = vfp_regs + 0;
bfae80f2
RE
9160 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9161 vreg++)
9162 {
9163 if (strcmp (start, vreg->name) == 0)
9164 {
9165 *p = c;
9166 *str = p;
9167 return vreg;
9168 }
9169 }
9170
9171 *p = c;
9172 return NULL;
9173}
9174
9175static int
9176vfp_psr_required_here (str)
9177 char **str;
9178{
9179 char *start = *str;
9180 const struct vfp_reg *vreg;
9181
9182 vreg = vfp_psr_parse (str);
9183
9184 if (vreg)
9185 {
9186 inst.instruction |= vreg->regno;
9187 return SUCCESS;
9188 }
9189
9190 inst.error = _("VFP system register expected");
9191
9192 *str = start;
9193 return FAIL;
9194}
9195
9196static void
9197do_vfp_reg_from_ctrl (str)
9198 char *str;
9199{
9200 skip_whitespace (str);
9201
9202 if (reg_required_here (&str, 12) == FAIL)
9203 return;
9204
9205 if (skip_past_comma (&str) == FAIL
9206 || vfp_psr_required_here (&str) == FAIL)
9207 {
9208 if (! inst.error)
9209 inst.error = BAD_ARGS;
9210 return;
9211 }
9212
9213 end_of_line (str);
9214 return;
9215}
9216
9217static void
9218do_vfp_ctrl_from_reg (str)
9219 char *str;
9220{
9221 skip_whitespace (str);
9222
9223 if (vfp_psr_required_here (&str) == FAIL)
9224 return;
9225
9226 if (skip_past_comma (&str) == FAIL
9227 || reg_required_here (&str, 12) == FAIL)
9228 {
9229 if (! inst.error)
9230 inst.error = BAD_ARGS;
9231 return;
9232 }
9233
9234 end_of_line (str);
9235 return;
9236}
9237
9238static void
9239do_vfp_sp_ldst (str)
9240 char *str;
9241{
9242 skip_whitespace (str);
9243
9244 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9245 {
9246 if (!inst.error)
9247 inst.error = BAD_ARGS;
9248 return;
9249 }
9250
9251 if (skip_past_comma (&str) == FAIL
9252 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9253 {
9254 if (!inst.error)
9255 inst.error = BAD_ARGS;
9256 return;
9257 }
9258
9259 end_of_line (str);
9260 return;
9261}
9262
9263static void
9264do_vfp_dp_ldst (str)
9265 char *str;
9266{
9267 skip_whitespace (str);
9268
9269 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9270 {
9271 if (!inst.error)
9272 inst.error = BAD_ARGS;
9273 return;
9274 }
9275
9276 if (skip_past_comma (&str) == FAIL
9277 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9278 {
9279 if (!inst.error)
9280 inst.error = BAD_ARGS;
9281 return;
9282 }
9283
9284 end_of_line (str);
9285 return;
9286}
9287
9288/* Parse and encode a VFP SP register list, storing the initial
9289 register in position POS and returning the range as the result. If
9290 the string is invalid return FAIL (an invalid range). */
9291static long
9292vfp_sp_reg_list (str, pos)
9293 char **str;
9294 enum vfp_sp_reg_pos pos;
9295{
9296 long range = 0;
9297 int base_reg = 0;
9298 int new_base;
9299 long base_bits = 0;
9300 int count = 0;
9301 long tempinst;
9302 unsigned long mask = 0;
9303 int warned = 0;
9304
9305 if (**str != '{')
9306 return FAIL;
9307
9308 (*str)++;
9309 skip_whitespace (*str);
9310
9311 tempinst = inst.instruction;
9312
9313 do
9314 {
9315 inst.instruction = 0;
9316
9317 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9318 return FAIL;
9319
9320 if (count == 0 || base_reg > new_base)
9321 {
9322 base_reg = new_base;
9323 base_bits = inst.instruction;
9324 }
9325
9326 if (mask & (1 << new_base))
9327 {
9328 inst.error = _("invalid register list");
9329 return FAIL;
9330 }
9331
9332 if ((mask >> new_base) != 0 && ! warned)
9333 {
9334 as_tsktsk (_("register list not in ascending order"));
9335 warned = 1;
9336 }
9337
9338 mask |= 1 << new_base;
9339 count++;
9340
9341 skip_whitespace (*str);
9342
9343 if (**str == '-') /* We have the start of a range expression */
9344 {
9345 int high_range;
9346
9347 (*str)++;
9348
9349 if ((high_range
9350 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9351 == FAIL)
9352 {
9353 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9354 return FAIL;
9355 }
9356
9357 if (high_range <= new_base)
9358 {
9359 inst.error = _("register range not in ascending order");
9360 return FAIL;
9361 }
9362
9363 for (new_base++; new_base <= high_range; new_base++)
9364 {
9365 if (mask & (1 << new_base))
9366 {
9367 inst.error = _("invalid register list");
9368 return FAIL;
9369 }
9370
9371 mask |= 1 << new_base;
9372 count++;
9373 }
9374 }
9375 }
9376 while (skip_past_comma (str) != FAIL);
9377
9378 if (**str != '}')
9379 {
9380 inst.error = _("invalid register list");
9381 return FAIL;
9382 }
9383
9384 (*str)++;
9385
9386 range = count;
9387
9388 /* Sanity check -- should have raised a parse error above. */
9389 if (count == 0 || count > 32)
c62e1cc3 9390 abort ();
bfae80f2
RE
9391
9392 /* Final test -- the registers must be consecutive. */
9393 while (count--)
9394 {
9395 if ((mask & (1 << base_reg++)) == 0)
9396 {
9397 inst.error = _("non-contiguous register range");
9398 return FAIL;
9399 }
9400 }
9401
9402 inst.instruction = tempinst | base_bits;
9403 return range;
9404}
9405
9406static long
9407vfp_dp_reg_list (str)
9408 char **str;
9409{
9410 long range = 0;
9411 int base_reg = 0;
9412 int new_base;
9413 int count = 0;
9414 long tempinst;
9415 unsigned long mask = 0;
9416 int warned = 0;
9417
9418 if (**str != '{')
9419 return FAIL;
9420
9421 (*str)++;
9422 skip_whitespace (*str);
9423
9424 tempinst = inst.instruction;
9425
9426 do
9427 {
9428 inst.instruction = 0;
9429
9430 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9431 return FAIL;
9432
9433 if (count == 0 || base_reg > new_base)
9434 {
9435 base_reg = new_base;
9436 range = inst.instruction;
9437 }
9438
9439 if (mask & (1 << new_base))
9440 {
9441 inst.error = _("invalid register list");
9442 return FAIL;
9443 }
9444
9445 if ((mask >> new_base) != 0 && ! warned)
9446 {
9447 as_tsktsk (_("register list not in ascending order"));
9448 warned = 1;
9449 }
9450
9451 mask |= 1 << new_base;
9452 count++;
9453
9454 skip_whitespace (*str);
9455
9456 if (**str == '-') /* We have the start of a range expression */
9457 {
9458 int high_range;
9459
9460 (*str)++;
9461
9462 if ((high_range
9463 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9464 == FAIL)
9465 {
9466 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9467 return FAIL;
9468 }
9469
9470 if (high_range <= new_base)
9471 {
9472 inst.error = _("register range not in ascending order");
9473 return FAIL;
9474 }
9475
9476 for (new_base++; new_base <= high_range; new_base++)
9477 {
9478 if (mask & (1 << new_base))
9479 {
9480 inst.error = _("invalid register list");
9481 return FAIL;
9482 }
9483
9484 mask |= 1 << new_base;
9485 count++;
9486 }
9487 }
9488 }
9489 while (skip_past_comma (str) != FAIL);
9490
9491 if (**str != '}')
9492 {
9493 inst.error = _("invalid register list");
9494 return FAIL;
9495 }
9496
9497 (*str)++;
9498
9499 range |= 2 * count;
9500
9501 /* Sanity check -- should have raised a parse error above. */
9502 if (count == 0 || count > 16)
c62e1cc3 9503 abort ();
bfae80f2
RE
9504
9505 /* Final test -- the registers must be consecutive. */
9506 while (count--)
9507 {
9508 if ((mask & (1 << base_reg++)) == 0)
9509 {
9510 inst.error = _("non-contiguous register range");
9511 return FAIL;
9512 }
9513 }
9514
9515 inst.instruction = tempinst;
9516 return range;
9517}
9518
9519static void
c62e1cc3 9520vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9521 char *str;
9522 enum vfp_ldstm_type ldstm_type;
9523{
9524 long range;
9525
9526 skip_whitespace (str);
9527
9528 if (reg_required_here (&str, 16) == FAIL)
9529 return;
9530
9531 skip_whitespace (str);
9532
9533 if (*str == '!')
9534 {
9535 inst.instruction |= WRITE_BACK;
9536 str++;
9537 }
9538 else if (ldstm_type != VFP_LDSTMIA)
9539 {
9540 inst.error = _("this addressing mode requires base-register writeback");
9541 return;
9542 }
9543
9544 if (skip_past_comma (&str) == FAIL
9545 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9546 {
9547 if (!inst.error)
9548 inst.error = BAD_ARGS;
9549 return;
9550 }
9551
9552 inst.instruction |= range;
9553 end_of_line (str);
9554}
9555
9556static void
c62e1cc3 9557vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9558 char *str;
9559 enum vfp_ldstm_type ldstm_type;
9560{
9561 long range;
9562
9563 skip_whitespace (str);
9564
9565 if (reg_required_here (&str, 16) == FAIL)
9566 return;
9567
9568 skip_whitespace (str);
9569
9570 if (*str == '!')
9571 {
9572 inst.instruction |= WRITE_BACK;
9573 str++;
9574 }
9575 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9576 {
9577 inst.error = _("this addressing mode requires base-register writeback");
9578 return;
9579 }
9580
9581 if (skip_past_comma (&str) == FAIL
9582 || (range = vfp_dp_reg_list (&str)) == FAIL)
9583 {
9584 if (!inst.error)
9585 inst.error = BAD_ARGS;
9586 return;
9587 }
9588
9589 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9590 range += 1;
9591
9592 inst.instruction |= range;
9593 end_of_line (str);
9594}
9595
9596static void
9597do_vfp_sp_ldstmia (str)
9598 char *str;
9599{
9600 vfp_sp_ldstm (str, VFP_LDSTMIA);
9601}
9602
9603static void
9604do_vfp_sp_ldstmdb (str)
9605 char *str;
9606{
9607 vfp_sp_ldstm (str, VFP_LDSTMDB);
9608}
9609
9610static void
9611do_vfp_dp_ldstmia (str)
9612 char *str;
9613{
9614 vfp_dp_ldstm (str, VFP_LDSTMIA);
9615}
9616
9617static void
9618do_vfp_dp_ldstmdb (str)
9619 char *str;
9620{
9621 vfp_dp_ldstm (str, VFP_LDSTMDB);
9622}
9623
9624static void
9625do_vfp_xp_ldstmia (str)
9626 char *str;
9627{
9628 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9629}
9630
9631static void
9632do_vfp_xp_ldstmdb (str)
9633 char *str;
9634{
9635 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9636}
9637
9638static void
9639do_vfp_sp_compare_z (str)
9640 char *str;
9641{
9642 skip_whitespace (str);
9643
9644 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9645 {
9646 if (!inst.error)
9647 inst.error = BAD_ARGS;
9648 return;
9649 }
9650
9651 end_of_line (str);
9652 return;
9653}
9654
9655static void
9656do_vfp_dp_compare_z (str)
9657 char *str;
9658{
9659 skip_whitespace (str);
9660
9661 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9662 {
9663 if (!inst.error)
9664 inst.error = BAD_ARGS;
9665 return;
9666 }
9667
9668 end_of_line (str);
9669 return;
9670}
9671
9672static void
9673do_vfp_dp_sp_cvt (str)
9674 char *str;
9675{
9676 skip_whitespace (str);
9677
9678 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9679 return;
9680
9681 if (skip_past_comma (&str) == FAIL
9682 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9683 {
9684 if (! inst.error)
9685 inst.error = BAD_ARGS;
9686 return;
9687 }
9688
9689 end_of_line (str);
9690 return;
9691}
9692
9693static void
9694do_vfp_sp_dp_cvt (str)
9695 char *str;
9696{
9697 skip_whitespace (str);
9698
9699 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9700 return;
9701
9702 if (skip_past_comma (&str) == FAIL
9703 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9704 {
9705 if (! inst.error)
9706 inst.error = BAD_ARGS;
9707 return;
9708 }
9709
9710 end_of_line (str);
9711 return;
9712}
9713
9714/* Thumb specific routines. */
9715
9716/* Parse and validate that a register is of the right form, this saves
9717 repeated checking of this information in many similar cases.
9718 Unlike the 32-bit case we do not insert the register into the opcode
9719 here, since the position is often unknown until the full instruction
9720 has been parsed. */
9721
9722static int
9723thumb_reg (strp, hi_lo)
9724 char ** strp;
9725 int hi_lo;
9726{
9727 int reg;
9728
9729 if ((reg = reg_required_here (strp, -1)) == FAIL)
9730 return FAIL;
9731
9732 switch (hi_lo)
9733 {
9734 case THUMB_REG_LO:
9735 if (reg > 7)
9736 {
9737 inst.error = _("lo register required");
9738 return FAIL;
9739 }
9740 break;
9741
9742 case THUMB_REG_HI:
9743 if (reg < 8)
9744 {
9745 inst.error = _("hi register required");
9746 return FAIL;
9747 }
9748 break;
9749
9750 default:
9751 break;
9752 }
9753
9754 return reg;
9755}
9756
9757/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9758 was SUB. */
9759
9760static void
9761thumb_add_sub (str, subtract)
9762 char * str;
9763 int subtract;
9764{
9765 int Rd, Rs, Rn = FAIL;
9766
9767 skip_whitespace (str);
9768
9769 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9770 || skip_past_comma (&str) == FAIL)
9771 {
9772 if (! inst.error)
9773 inst.error = BAD_ARGS;
9774 return;
9775 }
9776
9777 if (is_immediate_prefix (*str))
9778 {
9779 Rs = Rd;
9780 str++;
9781 if (my_get_expression (&inst.reloc.exp, &str))
9782 return;
9783 }
9784 else
9785 {
9786 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9787 return;
9788
9789 if (skip_past_comma (&str) == FAIL)
9790 {
9791 /* Two operand format, shuffle the registers
9792 and pretend there are 3. */
9793 Rn = Rs;
9794 Rs = Rd;
9795 }
9796 else if (is_immediate_prefix (*str))
9797 {
9798 str++;
9799 if (my_get_expression (&inst.reloc.exp, &str))
9800 return;
9801 }
9802 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9803 return;
9804 }
9805
9806 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9807 for the latter case, EXPR contains the immediate that was found. */
9808 if (Rn != FAIL)
9809 {
9810 /* All register format. */
9811 if (Rd > 7 || Rs > 7 || Rn > 7)
9812 {
9813 if (Rs != Rd)
9814 {
9815 inst.error = _("dest and source1 must be the same register");
9816 return;
9817 }
9818
9819 /* Can't do this for SUB. */
9820 if (subtract)
9821 {
9822 inst.error = _("subtract valid only on lo regs");
9823 return;
9824 }
9825
9826 inst.instruction = (T_OPCODE_ADD_HI
9827 | (Rd > 7 ? THUMB_H1 : 0)
9828 | (Rn > 7 ? THUMB_H2 : 0));
9829 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9830 }
9831 else
9832 {
9833 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9834 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9835 }
9836 }
9837 else
9838 {
9839 /* Immediate expression, now things start to get nasty. */
9840
9841 /* First deal with HI regs, only very restricted cases allowed:
9842 Adjusting SP, and using PC or SP to get an address. */
9843 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9844 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9845 {
9846 inst.error = _("invalid Hi register with immediate");
9847 return;
9848 }
9849
9850 if (inst.reloc.exp.X_op != O_constant)
9851 {
9852 /* Value isn't known yet, all we can do is store all the fragments
9853 we know about in the instruction and let the reloc hacking
9854 work it all out. */
9855 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9856 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9857 }
9858 else
9859 {
9860 int offset = inst.reloc.exp.X_add_number;
9861
9862 if (subtract)
358b94bd 9863 offset = - offset;
bfae80f2
RE
9864
9865 if (offset < 0)
9866 {
358b94bd 9867 offset = - offset;
bfae80f2
RE
9868 subtract = 1;
9869
9870 /* Quick check, in case offset is MIN_INT. */
9871 if (offset < 0)
9872 {
9873 inst.error = _("immediate value out of range");
9874 return;
9875 }
9876 }
358b94bd
NC
9877 /* Note - you cannot convert a subtract of 0 into an
9878 add of 0 because the carry flag is set differently. */
9879 else if (offset > 0)
bfae80f2
RE
9880 subtract = 0;
9881
9882 if (Rd == REG_SP)
9883 {
9884 if (offset & ~0x1fc)
9885 {
9886 inst.error = _("invalid immediate value for stack adjust");
9887 return;
b99bd4ef
NC
9888 }
9889 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9890 inst.instruction |= offset >> 2;
9891 }
9892 else if (Rs == REG_PC || Rs == REG_SP)
9893 {
9894 if (subtract
9895 || (offset & ~0x3fc))
9896 {
9897 inst.error = _("invalid immediate for address calculation");
9898 return;
9899 }
9900 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9901 : T_OPCODE_ADD_SP);
9902 inst.instruction |= (Rd << 8) | (offset >> 2);
9903 }
9904 else if (Rs == Rd)
9905 {
9906 if (offset & ~0xff)
9907 {
9908 inst.error = _("immediate value out of range");
9909 return;
9910 }
9911 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9912 inst.instruction |= (Rd << 8) | offset;
9913 }
9914 else
9915 {
9916 if (offset & ~0x7)
9917 {
9918 inst.error = _("immediate value out of range");
9919 return;
9920 }
9921 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9922 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9923 }
9924 }
9925 }
9926
9927 end_of_line (str);
9928}
9929
9930static void
9931thumb_shift (str, shift)
9932 char * str;
9933 int shift;
9934{
9935 int Rd, Rs, Rn = FAIL;
9936
9937 skip_whitespace (str);
9938
9939 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9940 || skip_past_comma (&str) == FAIL)
9941 {
9942 if (! inst.error)
9943 inst.error = BAD_ARGS;
9944 return;
9945 }
9946
9947 if (is_immediate_prefix (*str))
9948 {
9949 /* Two operand immediate format, set Rs to Rd. */
9950 Rs = Rd;
9951 str ++;
9952 if (my_get_expression (&inst.reloc.exp, &str))
9953 return;
9954 }
9955 else
9956 {
9957 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9958 return;
9959
9960 if (skip_past_comma (&str) == FAIL)
9961 {
9962 /* Two operand format, shuffle the registers
9963 and pretend there are 3. */
9964 Rn = Rs;
9965 Rs = Rd;
9966 }
9967 else if (is_immediate_prefix (*str))
9968 {
9969 str++;
9970 if (my_get_expression (&inst.reloc.exp, &str))
9971 return;
9972 }
9973 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9974 return;
9975 }
9976
9977 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9978 for the latter case, EXPR contains the immediate that was found. */
9979
9980 if (Rn != FAIL)
9981 {
9982 if (Rs != Rd)
9983 {
9984 inst.error = _("source1 and dest must be same register");
9985 return;
9986 }
9987
9988 switch (shift)
9989 {
9990 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9991 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9992 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9993 }
9994
9995 inst.instruction |= Rd | (Rn << 3);
9996 }
9997 else
9998 {
9999 switch (shift)
10000 {
10001 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
10002 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
10003 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
10004 }
10005
10006 if (inst.reloc.exp.X_op != O_constant)
10007 {
10008 /* Value isn't known yet, create a dummy reloc and let reloc
10009 hacking fix it up. */
10010 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
10011 }
10012 else
10013 {
10014 unsigned shift_value = inst.reloc.exp.X_add_number;
10015
10016 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
10017 {
f03698e6 10018 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
10019 return;
10020 }
10021
10022 /* Shifts of zero are handled by converting to LSL. */
10023 if (shift_value == 0)
10024 inst.instruction = T_OPCODE_LSL_I;
10025
10026 /* Shifts of 32 are encoded as a shift of zero. */
10027 if (shift_value == 32)
10028 shift_value = 0;
10029
10030 inst.instruction |= shift_value << 6;
10031 }
10032
10033 inst.instruction |= Rd | (Rs << 3);
10034 }
10035
10036 end_of_line (str);
10037}
10038
10039static void
10040thumb_mov_compare (str, move)
10041 char * str;
10042 int move;
10043{
10044 int Rd, Rs = FAIL;
10045
10046 skip_whitespace (str);
10047
10048 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10049 || skip_past_comma (&str) == FAIL)
10050 {
10051 if (! inst.error)
10052 inst.error = BAD_ARGS;
10053 return;
10054 }
10055
09d92015 10056 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
10057 {
10058 str++;
10059 if (my_get_expression (&inst.reloc.exp, &str))
10060 return;
10061 }
10062 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10063 return;
10064
10065 if (Rs != FAIL)
10066 {
09d92015 10067 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
10068 {
10069 if (move == THUMB_MOVE)
10070 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10071 since a MOV instruction produces unpredictable results. */
10072 inst.instruction = T_OPCODE_ADD_I3;
10073 else
10074 inst.instruction = T_OPCODE_CMP_LR;
10075 inst.instruction |= Rd | (Rs << 3);
10076 }
10077 else
10078 {
10079 if (move == THUMB_MOVE)
10080 inst.instruction = T_OPCODE_MOV_HR;
09d92015 10081 else if (move != THUMB_CPY)
b99bd4ef
NC
10082 inst.instruction = T_OPCODE_CMP_HR;
10083
10084 if (Rd > 7)
10085 inst.instruction |= THUMB_H1;
10086
10087 if (Rs > 7)
10088 inst.instruction |= THUMB_H2;
10089
10090 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10091 }
10092 }
10093 else
10094 {
10095 if (Rd > 7)
10096 {
10097 inst.error = _("only lo regs allowed with immediate");
10098 return;
10099 }
10100
10101 if (move == THUMB_MOVE)
10102 inst.instruction = T_OPCODE_MOV_I8;
10103 else
10104 inst.instruction = T_OPCODE_CMP_I8;
10105
10106 inst.instruction |= Rd << 8;
10107
10108 if (inst.reloc.exp.X_op != O_constant)
10109 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10110 else
10111 {
10112 unsigned value = inst.reloc.exp.X_add_number;
10113
10114 if (value > 255)
10115 {
10116 inst.error = _("invalid immediate");
10117 return;
10118 }
10119
10120 inst.instruction |= value;
10121 }
10122 }
10123
10124 end_of_line (str);
10125}
10126
10127static void
10128thumb_load_store (str, load_store, size)
10129 char * str;
10130 int load_store;
10131 int size;
10132{
10133 int Rd, Rb, Ro = FAIL;
10134
10135 skip_whitespace (str);
10136
10137 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10138 || skip_past_comma (&str) == FAIL)
10139 {
10140 if (! inst.error)
10141 inst.error = BAD_ARGS;
10142 return;
10143 }
10144
10145 if (*str == '[')
10146 {
10147 str++;
10148 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10149 return;
10150
10151 if (skip_past_comma (&str) != FAIL)
10152 {
10153 if (is_immediate_prefix (*str))
10154 {
10155 str++;
10156 if (my_get_expression (&inst.reloc.exp, &str))
10157 return;
10158 }
10159 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10160 return;
10161 }
10162 else
10163 {
10164 inst.reloc.exp.X_op = O_constant;
10165 inst.reloc.exp.X_add_number = 0;
10166 }
10167
10168 if (*str != ']')
10169 {
10170 inst.error = _("expected ']'");
10171 return;
10172 }
10173 str++;
10174 }
10175 else if (*str == '=')
10176 {
f03698e6
RE
10177 if (load_store != THUMB_LOAD)
10178 {
10179 inst.error = _("invalid pseudo operation");
10180 return;
10181 }
10182
b99bd4ef
NC
10183 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10184 str++;
10185
10186 skip_whitespace (str);
10187
10188 if (my_get_expression (& inst.reloc.exp, & str))
10189 return;
10190
10191 end_of_line (str);
10192
10193 if ( inst.reloc.exp.X_op != O_constant
10194 && inst.reloc.exp.X_op != O_symbol)
10195 {
10196 inst.error = "Constant expression expected";
10197 return;
10198 }
10199
10200 if (inst.reloc.exp.X_op == O_constant
10201 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10202 {
10203 /* This can be done with a mov instruction. */
10204
10205 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10206 inst.instruction |= inst.reloc.exp.X_add_number;
10207 return;
10208 }
10209
10210 /* Insert into literal pool. */
10211 if (add_to_lit_pool () == FAIL)
10212 {
10213 if (!inst.error)
10214 inst.error = "literal pool insertion failed";
10215 return;
10216 }
10217
10218 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10219 inst.reloc.pc_rel = 1;
10220 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10221 /* Adjust ARM pipeline offset to Thumb. */
10222 inst.reloc.exp.X_add_number += 4;
10223
10224 return;
10225 }
10226 else
10227 {
10228 if (my_get_expression (&inst.reloc.exp, &str))
10229 return;
10230
10231 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10232 inst.reloc.pc_rel = 1;
10233 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10234 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10235 end_of_line (str);
10236 return;
10237 }
10238
10239 if (Rb == REG_PC || Rb == REG_SP)
10240 {
10241 if (size != THUMB_WORD)
10242 {
10243 inst.error = _("byte or halfword not valid for base register");
10244 return;
10245 }
10246 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10247 {
f03698e6 10248 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10249 return;
10250 }
10251 else if (Ro != FAIL)
10252 {
f03698e6 10253 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10254 return;
10255 }
10256
10257 if (Rb == REG_PC)
10258 inst.instruction = T_OPCODE_LDR_PC;
10259 else if (load_store == THUMB_LOAD)
10260 inst.instruction = T_OPCODE_LDR_SP;
10261 else
10262 inst.instruction = T_OPCODE_STR_SP;
10263
10264 inst.instruction |= Rd << 8;
10265 if (inst.reloc.exp.X_op == O_constant)
10266 {
10267 unsigned offset = inst.reloc.exp.X_add_number;
10268
10269 if (offset & ~0x3fc)
10270 {
10271 inst.error = _("invalid offset");
10272 return;
10273 }
10274
10275 inst.instruction |= offset >> 2;
10276 }
10277 else
10278 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10279 }
10280 else if (Rb > 7)
10281 {
10282 inst.error = _("invalid base register in load/store");
10283 return;
10284 }
10285 else if (Ro == FAIL)
10286 {
10287 /* Immediate offset. */
10288 if (size == THUMB_WORD)
10289 inst.instruction = (load_store == THUMB_LOAD
10290 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10291 else if (size == THUMB_HALFWORD)
10292 inst.instruction = (load_store == THUMB_LOAD
10293 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10294 else
10295 inst.instruction = (load_store == THUMB_LOAD
10296 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10297
10298 inst.instruction |= Rd | (Rb << 3);
10299
10300 if (inst.reloc.exp.X_op == O_constant)
10301 {
10302 unsigned offset = inst.reloc.exp.X_add_number;
10303
10304 if (offset & ~(0x1f << size))
10305 {
f03698e6 10306 inst.error = _("invalid offset");
b99bd4ef
NC
10307 return;
10308 }
10309 inst.instruction |= (offset >> size) << 6;
10310 }
10311 else
10312 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10313 }
10314 else
10315 {
10316 /* Register offset. */
10317 if (size == THUMB_WORD)
10318 inst.instruction = (load_store == THUMB_LOAD
10319 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10320 else if (size == THUMB_HALFWORD)
10321 inst.instruction = (load_store == THUMB_LOAD
10322 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10323 else
10324 inst.instruction = (load_store == THUMB_LOAD
10325 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10326
10327 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10328 }
10329
10330 end_of_line (str);
10331}
10332
404ff6b5
AH
10333/* A register must be given at this point.
10334
404ff6b5
AH
10335 Shift is the place to put it in inst.instruction.
10336
404ff6b5
AH
10337 Restores input start point on err.
10338 Returns the reg#, or FAIL. */
10339
10340static int
63e63b07 10341mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10342 char ** str;
10343 int shift;
6c43fab6 10344 enum arm_reg_type regtype;
404ff6b5 10345{
6c43fab6
RE
10346 int reg;
10347 char *start = *str;
404ff6b5 10348
6c43fab6 10349 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10350 {
404ff6b5
AH
10351 if (shift >= 0)
10352 inst.instruction |= reg << shift;
10353
6c43fab6 10354 return reg;
404ff6b5
AH
10355 }
10356
6c43fab6 10357 /* Restore the start point. */
404ff6b5 10358 *str = start;
cc8a6dd0 10359
404ff6b5
AH
10360 /* In the few cases where we might be able to accept something else
10361 this error can be overridden. */
6c43fab6 10362 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10363
404ff6b5
AH
10364 return FAIL;
10365}
10366
63e63b07 10367/* Cirrus Maverick Instructions. */
404ff6b5
AH
10368
10369/* Wrapper functions. */
10370
10371static void
63e63b07 10372do_mav_binops_1a (str)
6c43fab6
RE
10373 char * str;
10374{
63e63b07 10375 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10376}
10377
10378static void
63e63b07 10379do_mav_binops_1b (str)
6c43fab6
RE
10380 char * str;
10381{
63e63b07 10382 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10383}
10384
10385static void
63e63b07 10386do_mav_binops_1c (str)
404ff6b5 10387 char * str;
404ff6b5 10388{
63e63b07 10389 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10390}
10391
10392static void
63e63b07 10393do_mav_binops_1d (str)
404ff6b5 10394 char * str;
404ff6b5 10395{
63e63b07 10396 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10397}
10398
10399static void
63e63b07 10400do_mav_binops_1e (str)
404ff6b5 10401 char * str;
404ff6b5 10402{
63e63b07 10403 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10404}
10405
10406static void
63e63b07 10407do_mav_binops_1f (str)
404ff6b5 10408 char * str;
404ff6b5 10409{
63e63b07 10410 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10411}
10412
10413static void
63e63b07 10414do_mav_binops_1g (str)
404ff6b5 10415 char * str;
404ff6b5 10416{
63e63b07 10417 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10418}
10419
10420static void
63e63b07 10421do_mav_binops_1h (str)
404ff6b5 10422 char * str;
404ff6b5 10423{
63e63b07 10424 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10425}
10426
6c43fab6 10427static void
63e63b07 10428do_mav_binops_1i (str)
6c43fab6
RE
10429 char * str;
10430{
63e63b07 10431 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10432}
10433
10434static void
63e63b07 10435do_mav_binops_1j (str)
6c43fab6
RE
10436 char * str;
10437{
63e63b07 10438 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10439}
10440
10441static void
63e63b07 10442do_mav_binops_1k (str)
6c43fab6
RE
10443 char * str;
10444{
63e63b07 10445 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10446}
10447
10448static void
63e63b07 10449do_mav_binops_1l (str)
6c43fab6
RE
10450 char * str;
10451{
63e63b07 10452 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10453}
10454
10455static void
63e63b07 10456do_mav_binops_1m (str)
6c43fab6
RE
10457 char * str;
10458{
63e63b07 10459 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10460}
10461
10462static void
63e63b07 10463do_mav_binops_1n (str)
6c43fab6
RE
10464 char * str;
10465{
63e63b07 10466 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10467}
10468
10469static void
63e63b07 10470do_mav_binops_1o (str)
6c43fab6
RE
10471 char * str;
10472{
63e63b07 10473 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10474}
10475
10476static void
63e63b07 10477do_mav_binops_2a (str)
6c43fab6
RE
10478 char * str;
10479{
63e63b07 10480 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10481}
10482
10483static void
63e63b07 10484do_mav_binops_2b (str)
6c43fab6
RE
10485 char * str;
10486{
63e63b07 10487 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10488}
10489
10490static void
63e63b07 10491do_mav_binops_2c (str)
6c43fab6
RE
10492 char * str;
10493{
63e63b07 10494 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10495}
10496
10497static void
63e63b07 10498do_mav_binops_3a (str)
6c43fab6
RE
10499 char * str;
10500{
63e63b07 10501 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10502}
10503
10504static void
63e63b07 10505do_mav_binops_3b (str)
6c43fab6
RE
10506 char * str;
10507{
63e63b07 10508 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10509}
10510
10511static void
63e63b07 10512do_mav_binops_3c (str)
6c43fab6
RE
10513 char * str;
10514{
63e63b07 10515 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10516}
10517
10518static void
63e63b07 10519do_mav_binops_3d (str)
6c43fab6
RE
10520 char * str;
10521{
63e63b07 10522 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10523}
10524
10525static void
63e63b07 10526do_mav_triple_4a (str)
6c43fab6
RE
10527 char * str;
10528{
63e63b07 10529 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10530}
10531
10532static void
63e63b07 10533do_mav_triple_4b (str)
6c43fab6
RE
10534 char * str;
10535{
63e63b07 10536 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10537}
10538
10539static void
63e63b07 10540do_mav_triple_5a (str)
6c43fab6
RE
10541 char * str;
10542{
63e63b07 10543 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10544}
10545
10546static void
63e63b07 10547do_mav_triple_5b (str)
6c43fab6
RE
10548 char * str;
10549{
63e63b07 10550 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10551}
10552
10553static void
63e63b07 10554do_mav_triple_5c (str)
6c43fab6
RE
10555 char * str;
10556{
63e63b07 10557 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10558}
10559
10560static void
63e63b07 10561do_mav_triple_5d (str)
6c43fab6
RE
10562 char * str;
10563{
63e63b07 10564 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10565}
10566
10567static void
63e63b07 10568do_mav_triple_5e (str)
6c43fab6
RE
10569 char * str;
10570{
63e63b07 10571 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10572}
10573
10574static void
63e63b07 10575do_mav_triple_5f (str)
6c43fab6
RE
10576 char * str;
10577{
63e63b07 10578 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10579}
10580
10581static void
63e63b07 10582do_mav_triple_5g (str)
6c43fab6
RE
10583 char * str;
10584{
63e63b07 10585 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10586}
10587
10588static void
63e63b07 10589do_mav_triple_5h (str)
6c43fab6
RE
10590 char * str;
10591{
63e63b07 10592 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10593}
10594
10595static void
63e63b07 10596do_mav_quad_6a (str)
6c43fab6
RE
10597 char * str;
10598{
63e63b07 10599 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10600 REG_TYPE_MVFX);
10601}
10602
10603static void
63e63b07 10604do_mav_quad_6b (str)
6c43fab6
RE
10605 char * str;
10606{
63e63b07 10607 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10608 REG_TYPE_MVFX);
10609}
10610
cc8a6dd0 10611/* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
404ff6b5 10612static void
63e63b07 10613do_mav_dspsc_1 (str)
404ff6b5 10614 char * str;
404ff6b5 10615{
6c43fab6
RE
10616 skip_whitespace (str);
10617
10618 /* cfmvsc32. */
63e63b07 10619 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10620 || skip_past_comma (&str) == FAIL
63e63b07 10621 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
6c43fab6
RE
10622 {
10623 if (!inst.error)
10624 inst.error = BAD_ARGS;
10625
10626 return;
10627 }
10628
10629 end_of_line (str);
404ff6b5
AH
10630}
10631
6c43fab6 10632/* cfmv32sc<cond> MVFX[15:0],DSPSC. */
404ff6b5 10633static void
63e63b07 10634do_mav_dspsc_2 (str)
404ff6b5 10635 char * str;
404ff6b5 10636{
6c43fab6
RE
10637 skip_whitespace (str);
10638
10639 /* cfmv32sc. */
63e63b07 10640 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
6c43fab6 10641 || skip_past_comma (&str) == FAIL
63e63b07 10642 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10643 {
10644 if (!inst.error)
10645 inst.error = BAD_ARGS;
10646
10647 return;
10648 }
10649
10650 end_of_line (str);
404ff6b5
AH
10651}
10652
10653static void
63e63b07 10654do_mav_shift_1 (str)
404ff6b5 10655 char * str;
404ff6b5 10656{
63e63b07 10657 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10658}
10659
10660static void
63e63b07 10661do_mav_shift_2 (str)
404ff6b5 10662 char * str;
404ff6b5 10663{
63e63b07 10664 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10665}
10666
10667static void
63e63b07 10668do_mav_ldst_1 (str)
404ff6b5 10669 char * str;
404ff6b5 10670{
63e63b07 10671 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10672}
10673
10674static void
63e63b07 10675do_mav_ldst_2 (str)
404ff6b5 10676 char * str;
404ff6b5 10677{
63e63b07 10678 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10679}
10680
10681static void
63e63b07 10682do_mav_ldst_3 (str)
404ff6b5 10683 char * str;
404ff6b5 10684{
63e63b07 10685 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10686}
10687
10688static void
63e63b07 10689do_mav_ldst_4 (str)
404ff6b5 10690 char * str;
404ff6b5 10691{
63e63b07 10692 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10693}
10694
10695/* Isnsn like "foo X,Y". */
10696
10697static void
63e63b07 10698do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10699 char * str;
404ff6b5 10700 int mode;
6c43fab6
RE
10701 enum arm_reg_type reg0;
10702 enum arm_reg_type reg1;
404ff6b5 10703{
6c43fab6 10704 int shift0, shift1;
404ff6b5 10705
6c43fab6
RE
10706 shift0 = mode & 0xff;
10707 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10708
10709 skip_whitespace (str);
10710
63e63b07 10711 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10712 || skip_past_comma (&str) == FAIL
63e63b07 10713 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10714 {
10715 if (!inst.error)
10716 inst.error = BAD_ARGS;
10717 }
10718 else
10719 end_of_line (str);
404ff6b5
AH
10720}
10721
10722/* Isnsn like "foo X,Y,Z". */
10723
10724static void
63e63b07 10725do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10726 char * str;
404ff6b5 10727 int mode;
6c43fab6
RE
10728 enum arm_reg_type reg0;
10729 enum arm_reg_type reg1;
10730 enum arm_reg_type reg2;
404ff6b5 10731{
6c43fab6 10732 int shift0, shift1, shift2;
404ff6b5 10733
6c43fab6
RE
10734 shift0 = mode & 0xff;
10735 shift1 = (mode >> 8) & 0xff;
10736 shift2 = (mode >> 16) & 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
AH
10745 {
10746 if (!inst.error)
10747 inst.error = BAD_ARGS;
10748 }
10749 else
10750 end_of_line (str);
404ff6b5
AH
10751}
10752
10753/* Isnsn like "foo W,X,Y,Z".
10754 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10755
10756static void
63e63b07 10757do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10758 char * str;
404ff6b5 10759 int mode;
6c43fab6
RE
10760 enum arm_reg_type reg0;
10761 enum arm_reg_type reg1;
10762 enum arm_reg_type reg2;
10763 enum arm_reg_type reg3;
404ff6b5 10764{
6c43fab6 10765 int shift0, shift1, shift2, shift3;
404ff6b5 10766
6c43fab6
RE
10767 shift0= mode & 0xff;
10768 shift1 = (mode >> 8) & 0xff;
10769 shift2 = (mode >> 16) & 0xff;
10770 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10771
10772 skip_whitespace (str);
10773
63e63b07 10774 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10775 || skip_past_comma (&str) == FAIL
63e63b07 10776 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10777 || skip_past_comma (&str) == FAIL
63e63b07 10778 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10779 || skip_past_comma (&str) == FAIL
63e63b07 10780 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10781 {
10782 if (!inst.error)
10783 inst.error = BAD_ARGS;
10784 }
10785 else
10786 end_of_line (str);
404ff6b5
AH
10787}
10788
63e63b07 10789/* Maverick shift immediate instructions.
404ff6b5
AH
10790 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10791 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10792
10793static void
63e63b07 10794do_mav_shift (str, reg0, reg1)
404ff6b5 10795 char * str;
6c43fab6
RE
10796 enum arm_reg_type reg0;
10797 enum arm_reg_type reg1;
404ff6b5
AH
10798{
10799 int error;
10800 int imm, neg = 0;
10801
10802 skip_whitespace (str);
10803
10804 error = 0;
10805
63e63b07 10806 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10807 || skip_past_comma (&str) == FAIL
63e63b07 10808 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10809 || skip_past_comma (&str) == FAIL)
10810 {
10811 if (!inst.error)
10812 inst.error = BAD_ARGS;
10813 return;
10814 }
10815
10816 /* Calculate the immediate operand.
10817 The operand is a 7bit signed number. */
10818 skip_whitespace (str);
10819
10820 if (*str == '#')
10821 ++str;
10822
8420dfca 10823 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10824 {
10825 inst.error = _("expecting immediate, 7bit operand");
10826 return;
10827 }
10828
10829 if (*str == '-')
10830 {
10831 neg = 1;
10832 ++str;
10833 }
10834
8420dfca 10835 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10836 imm = imm * 10 + *str - '0';
10837
10838 if (imm > 64)
10839 {
10840 inst.error = _("immediate out of range");
10841 return;
10842 }
10843
10844 /* Make negative imm's into 7bit signed numbers. */
10845 if (neg)
10846 {
10847 imm = -imm;
10848 imm &= 0x0000007f;
10849 }
10850
10851 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10852 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10853 Bit 4 should be 0. */
10854 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10855
10856 inst.instruction |= imm;
404ff6b5 10857 end_of_line (str);
404ff6b5
AH
10858}
10859
10860static int
63e63b07 10861mav_parse_offset (str, negative)
404ff6b5
AH
10862 char ** str;
10863 int *negative;
10864{
10865 char * p = *str;
10866 int offset;
10867
10868 *negative = 0;
10869
10870 skip_whitespace (p);
10871
10872 if (*p == '#')
10873 ++p;
10874
10875 if (*p == '-')
10876 {
10877 *negative = 1;
10878 ++p;
10879 }
10880
8420dfca 10881 if (!ISDIGIT (*p))
404ff6b5
AH
10882 {
10883 inst.error = _("offset expected");
10884 return 0;
10885 }
10886
8420dfca 10887 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10888 offset = offset * 10 + *p - '0';
10889
10890 if (offset > 0xff)
10891 {
10892 inst.error = _("offset out of range");
10893 return 0;
10894 }
10895
10896 *str = p;
10897
10898 return *negative ? -offset : offset;
10899}
10900
63e63b07 10901/* Maverick load/store instructions.
404ff6b5
AH
10902 <insn><cond> CRd,[Rn,<offset>]{!}.
10903 <insn><cond> CRd,[Rn],<offset>. */
10904
10905static void
63e63b07 10906do_mav_ldst (str, reg0)
404ff6b5 10907 char * str;
6c43fab6 10908 enum arm_reg_type reg0;
404ff6b5
AH
10909{
10910 int offset, negative;
404ff6b5
AH
10911
10912 skip_whitespace (str);
10913
63e63b07 10914 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10915 || skip_past_comma (&str) == FAIL
404ff6b5 10916 || *str++ != '['
6c43fab6 10917 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10918 goto fail_ldst;
10919
6c43fab6 10920 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10921 {
10922 /* You are here: "<offset>]{!}". */
10923 inst.instruction |= PRE_INDEX;
10924
63e63b07 10925 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10926
10927 if (inst.error)
10928 return;
10929
10930 if (*str++ != ']')
10931 {
10932 inst.error = _("missing ]");
10933 return;
10934 }
10935
10936 if (*str == '!')
10937 {
10938 inst.instruction |= WRITE_BACK;
10939 ++str;
10940 }
10941 }
10942 else
10943 {
10944 /* You are here: "], <offset>". */
10945 if (*str++ != ']')
10946 {
10947 inst.error = _("missing ]");
10948 return;
10949 }
10950
10951 if (skip_past_comma (&str) == FAIL
63e63b07 10952 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10953 goto fail_ldst;
10954
10955 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10956 }
10957
10958 if (negative)
10959 offset = -offset;
10960 else
2d2255b5 10961 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10962
10963 inst.instruction |= offset >> 2;
404ff6b5
AH
10964 end_of_line (str);
10965 return;
10966
10967fail_ldst:
10968 if (!inst.error)
10969 inst.error = BAD_ARGS;
10970 return;
10971}
10972
b99bd4ef
NC
10973static void
10974do_t_nop (str)
10975 char * str;
10976{
10977 /* Do nothing. */
10978 end_of_line (str);
10979 return;
10980}
10981
10982/* Handle the Format 4 instructions that do not have equivalents in other
10983 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10984 BIC and MVN. */
10985
10986static void
10987do_t_arit (str)
10988 char * str;
10989{
10990 int Rd, Rs, Rn;
10991
10992 skip_whitespace (str);
10993
10994 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10995 || skip_past_comma (&str) == FAIL
10996 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10997 {
10998 inst.error = BAD_ARGS;
10999 return;
11000 }
11001
11002 if (skip_past_comma (&str) != FAIL)
11003 {
11004 /* Three operand format not allowed for TST, CMN, NEG and MVN.
11005 (It isn't allowed for CMP either, but that isn't handled by this
11006 function.) */
11007 if (inst.instruction == T_OPCODE_TST
11008 || inst.instruction == T_OPCODE_CMN
11009 || inst.instruction == T_OPCODE_NEG
11010 || inst.instruction == T_OPCODE_MVN)
11011 {
11012 inst.error = BAD_ARGS;
11013 return;
11014 }
11015
11016 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11017 return;
11018
11019 if (Rs != Rd)
11020 {
11021 inst.error = _("dest and source1 must be the same register");
11022 return;
11023 }
11024 Rs = Rn;
11025 }
11026
11027 if (inst.instruction == T_OPCODE_MUL
11028 && Rs == Rd)
11029 as_tsktsk (_("Rs and Rd must be different in MUL"));
11030
11031 inst.instruction |= Rd | (Rs << 3);
11032 end_of_line (str);
11033}
11034
11035static void
11036do_t_add (str)
11037 char * str;
11038{
11039 thumb_add_sub (str, 0);
11040}
11041
11042static void
11043do_t_asr (str)
11044 char * str;
11045{
11046 thumb_shift (str, THUMB_ASR);
11047}
11048
11049static void
11050do_t_branch9 (str)
11051 char * str;
11052{
11053 if (my_get_expression (&inst.reloc.exp, &str))
11054 return;
11055 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11056 inst.reloc.pc_rel = 1;
11057 end_of_line (str);
11058}
11059
11060static void
11061do_t_branch12 (str)
11062 char * str;
11063{
11064 if (my_get_expression (&inst.reloc.exp, &str))
11065 return;
11066 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11067 inst.reloc.pc_rel = 1;
11068 end_of_line (str);
11069}
11070
11071/* Find the real, Thumb encoded start of a Thumb function. */
11072
11073static symbolS *
11074find_real_start (symbolP)
11075 symbolS * symbolP;
11076{
11077 char * real_start;
11078 const char * name = S_GET_NAME (symbolP);
11079 symbolS * new_target;
11080
2d2255b5 11081 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11082#define STUB_NAME ".real_start_of"
11083
11084 if (name == NULL)
11085 abort ();
11086
11087 /* Names that start with '.' are local labels, not function entry points.
11088 The compiler may generate BL instructions to these labels because it
11089 needs to perform a branch to a far away location. */
11090 if (name[0] == '.')
11091 return symbolP;
11092
11093 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11094 sprintf (real_start, "%s%s", STUB_NAME, name);
11095
11096 new_target = symbol_find (real_start);
11097
11098 if (new_target == NULL)
11099 {
11100 as_warn ("Failed to find real start of function: %s\n", name);
11101 new_target = symbolP;
11102 }
11103
11104 free (real_start);
11105
11106 return new_target;
11107}
11108
11109static void
11110do_t_branch23 (str)
11111 char * str;
11112{
11113 if (my_get_expression (& inst.reloc.exp, & str))
11114 return;
11115
11116 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11117 inst.reloc.pc_rel = 1;
11118 end_of_line (str);
11119
11120 /* If the destination of the branch is a defined symbol which does not have
11121 the THUMB_FUNC attribute, then we must be calling a function which has
11122 the (interfacearm) attribute. We look for the Thumb entry point to that
11123 function and change the branch to refer to that function instead. */
11124 if ( inst.reloc.exp.X_op == O_symbol
11125 && inst.reloc.exp.X_add_symbol != NULL
11126 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11127 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11128 inst.reloc.exp.X_add_symbol =
11129 find_real_start (inst.reloc.exp.X_add_symbol);
11130}
11131
11132static void
11133do_t_bx (str)
11134 char * str;
11135{
11136 int reg;
11137
11138 skip_whitespace (str);
11139
11140 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11141 return;
11142
11143 /* This sets THUMB_H2 from the top bit of reg. */
11144 inst.instruction |= reg << 3;
11145
11146 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11147 should cause the alignment to be checked once it is known. This is
11148 because BX PC only works if the instruction is word aligned. */
11149
11150 end_of_line (str);
11151}
11152
11153static void
11154do_t_compare (str)
11155 char * str;
11156{
11157 thumb_mov_compare (str, THUMB_COMPARE);
11158}
11159
11160static void
11161do_t_ldmstm (str)
11162 char * str;
11163{
11164 int Rb;
11165 long range;
11166
11167 skip_whitespace (str);
11168
11169 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11170 return;
11171
11172 if (*str != '!')
f03698e6 11173 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11174 else
11175 str++;
11176
11177 if (skip_past_comma (&str) == FAIL
11178 || (range = reg_list (&str)) == FAIL)
11179 {
11180 if (! inst.error)
11181 inst.error = BAD_ARGS;
11182 return;
11183 }
11184
11185 if (inst.reloc.type != BFD_RELOC_NONE)
11186 {
11187 /* This really doesn't seem worth it. */
11188 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11189 inst.error = _("expression too complex");
b99bd4ef
NC
11190 return;
11191 }
11192
11193 if (range & ~0xff)
11194 {
11195 inst.error = _("only lo-regs valid in load/store multiple");
11196 return;
11197 }
11198
11199 inst.instruction |= (Rb << 8) | range;
11200 end_of_line (str);
11201}
11202
11203static void
11204do_t_ldr (str)
11205 char * str;
11206{
11207 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11208}
11209
11210static void
11211do_t_ldrb (str)
11212 char * str;
11213{
11214 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11215}
11216
11217static void
11218do_t_ldrh (str)
11219 char * str;
11220{
11221 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11222}
11223
11224static void
11225do_t_lds (str)
11226 char * str;
11227{
11228 int Rd, Rb, Ro;
11229
11230 skip_whitespace (str);
11231
11232 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11233 || skip_past_comma (&str) == FAIL
11234 || *str++ != '['
11235 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11236 || skip_past_comma (&str) == FAIL
11237 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11238 || *str++ != ']')
11239 {
11240 if (! inst.error)
f03698e6 11241 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11242 return;
11243 }
11244
11245 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11246 end_of_line (str);
11247}
11248
11249static void
11250do_t_lsl (str)
11251 char * str;
11252{
11253 thumb_shift (str, THUMB_LSL);
11254}
11255
11256static void
11257do_t_lsr (str)
11258 char * str;
11259{
11260 thumb_shift (str, THUMB_LSR);
11261}
11262
11263static void
11264do_t_mov (str)
11265 char * str;
11266{
11267 thumb_mov_compare (str, THUMB_MOVE);
11268}
11269
11270static void
11271do_t_push_pop (str)
11272 char * str;
11273{
11274 long range;
11275
11276 skip_whitespace (str);
11277
11278 if ((range = reg_list (&str)) == FAIL)
11279 {
11280 if (! inst.error)
11281 inst.error = BAD_ARGS;
11282 return;
11283 }
11284
11285 if (inst.reloc.type != BFD_RELOC_NONE)
11286 {
11287 /* This really doesn't seem worth it. */
11288 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11289 inst.error = _("expression too complex");
b99bd4ef
NC
11290 return;
11291 }
11292
11293 if (range & ~0xff)
11294 {
11295 if ((inst.instruction == T_OPCODE_PUSH
11296 && (range & ~0xff) == 1 << REG_LR)
11297 || (inst.instruction == T_OPCODE_POP
11298 && (range & ~0xff) == 1 << REG_PC))
11299 {
11300 inst.instruction |= THUMB_PP_PC_LR;
11301 range &= 0xff;
11302 }
11303 else
11304 {
11305 inst.error = _("invalid register list to push/pop instruction");
11306 return;
11307 }
11308 }
11309
11310 inst.instruction |= range;
11311 end_of_line (str);
11312}
11313
11314static void
11315do_t_str (str)
11316 char * str;
11317{
11318 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11319}
11320
11321static void
11322do_t_strb (str)
11323 char * str;
11324{
11325 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11326}
11327
11328static void
11329do_t_strh (str)
11330 char * str;
11331{
11332 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11333}
11334
11335static void
11336do_t_sub (str)
11337 char * str;
11338{
11339 thumb_add_sub (str, 1);
11340}
11341
11342static void
11343do_t_swi (str)
11344 char * str;
11345{
11346 skip_whitespace (str);
11347
11348 if (my_get_expression (&inst.reloc.exp, &str))
11349 return;
11350
11351 inst.reloc.type = BFD_RELOC_ARM_SWI;
11352 end_of_line (str);
11353 return;
11354}
11355
11356static void
11357do_t_adr (str)
11358 char * str;
11359{
11360 int reg;
11361
11362 /* This is a pseudo-op of the form "adr rd, label" to be converted
11363 into a relative address of the form "add rd, pc, #label-.-4". */
11364 skip_whitespace (str);
11365
11366 /* Store Rd in temporary location inside instruction. */
11367 if ((reg = reg_required_here (&str, 4)) == FAIL
11368 || (reg > 7) /* For Thumb reg must be r0..r7. */
11369 || skip_past_comma (&str) == FAIL
11370 || my_get_expression (&inst.reloc.exp, &str))
11371 {
11372 if (!inst.error)
11373 inst.error = BAD_ARGS;
11374 return;
11375 }
11376
11377 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11378 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11379 inst.reloc.pc_rel = 1;
11380 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11381
11382 end_of_line (str);
11383}
11384
11385static void
6c43fab6
RE
11386insert_reg (r, htab)
11387 const struct reg_entry *r;
11388 struct hash_control *htab;
b99bd4ef 11389{
6c43fab6 11390 int len = strlen (r->name) + 2;
b99bd4ef
NC
11391 char * buf = (char *) xmalloc (len);
11392 char * buf2 = (char *) xmalloc (len);
11393 int i = 0;
11394
11395#ifdef REGISTER_PREFIX
11396 buf[i++] = REGISTER_PREFIX;
11397#endif
11398
6c43fab6 11399 strcpy (buf + i, r->name);
b99bd4ef
NC
11400
11401 for (i = 0; buf[i]; i++)
3882b010 11402 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11403
11404 buf2[i] = '\0';
11405
6c43fab6
RE
11406 hash_insert (htab, buf, (PTR) r);
11407 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11408}
11409
11410static void
6c43fab6
RE
11411build_reg_hsh (map)
11412 struct reg_map *map;
11413{
11414 const struct reg_entry *r;
11415
11416 if ((map->htab = hash_new ()) == NULL)
f03698e6 11417 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11418
11419 for (r = map->names; r->name != NULL; r++)
11420 insert_reg (r, map->htab);
11421}
11422
11423static void
11424insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11425 char *str;
11426 int regnum;
6c43fab6 11427 struct hash_control *htab;
b99bd4ef 11428{
0bbf2aa4
NC
11429 const char *error;
11430 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11431 const char *name = xmalloc (strlen (str) + 1);
11432
11433 strcpy ((char *) name, str);
11434
b99bd4ef
NC
11435 new->name = name;
11436 new->number = regnum;
0bbf2aa4 11437 new->builtin = FALSE;
b99bd4ef 11438
0bbf2aa4
NC
11439 error = hash_insert (htab, name, (PTR) new);
11440 if (error)
11441 {
11442 as_bad (_("failed to create an alias for %s, reason: %s"),
11443 str, error);
11444 free ((char *) name);
11445 free (new);
11446 }
b99bd4ef
NC
11447}
11448
6c43fab6
RE
11449/* Look for the .req directive. This is of the form:
11450
0bbf2aa4 11451 new_register_name .req existing_register_name
6c43fab6
RE
11452
11453 If we find one, or if it looks sufficiently like one that we want to
11454 handle any error here, return non-zero. Otherwise return zero. */
11455static int
11456create_register_alias (newname, p)
11457 char *newname;
11458 char *p;
11459{
11460 char *q;
11461 char c;
11462
11463 q = p;
11464 skip_whitespace (q);
11465
11466 c = *p;
11467 *p = '\0';
11468
11469 if (*q && !strncmp (q, ".req ", 5))
11470 {
11471 char *copy_of_str;
11472 char *r;
11473
11474#ifdef IGNORE_OPCODE_CASE
11475 newname = original_case_string;
11476#endif
11477 copy_of_str = newname;
11478
11479 q += 4;
11480 skip_whitespace (q);
11481
11482 for (r = q; *r != '\0'; r++)
11483 if (*r == ' ')
11484 break;
11485
11486 if (r != q)
11487 {
11488 enum arm_reg_type new_type, old_type;
11489 int old_regno;
11490 char d = *r;
11491
11492 *r = '\0';
11493 old_type = arm_reg_parse_any (q);
11494 *r = d;
11495
11496 new_type = arm_reg_parse_any (newname);
11497
11498 if (new_type == REG_TYPE_MAX)
11499 {
11500 if (old_type != REG_TYPE_MAX)
11501 {
11502 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11503 insert_reg_alias (newname, old_regno,
11504 all_reg_maps[old_type].htab);
11505 }
11506 else
11507 as_warn (_("register '%s' does not exist\n"), q);
11508 }
11509 else if (old_type == REG_TYPE_MAX)
11510 {
11511 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11512 copy_of_str, q);
11513 }
11514 else
11515 {
11516 /* Do not warn about redefinitions to the same alias. */
11517 if (new_type != old_type
11518 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11519 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11520 as_warn (_("ignoring redefinition of register alias '%s'"),
11521 copy_of_str);
11522
11523 }
11524 }
11525 else
11526 as_warn (_("ignoring incomplete .req pseuso op"));
11527
11528 *p = c;
11529 return 1;
11530 }
0bbf2aa4 11531
6c43fab6
RE
11532 *p = c;
11533 return 0;
11534}
cc8a6dd0 11535
b99bd4ef
NC
11536static void
11537set_constant_flonums ()
11538{
11539 int i;
11540
11541 for (i = 0; i < NUM_FLOAT_VALS; i++)
11542 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11543 abort ();
11544}
11545
90e4755a
RE
11546/* Iterate over the base tables to create the instruction patterns. */
11547static void
11548build_arm_ops_hsh ()
11549{
11550 unsigned int i;
11551 unsigned int j;
11552 static struct obstack insn_obstack;
11553
11554 obstack_begin (&insn_obstack, 4000);
11555
11556 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11557 {
6c43fab6 11558 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11559
11560 if (insn->cond_offset != 0)
11561 {
11562 /* Insn supports conditional execution. Build the varaints
11563 and insert them in the hash table. */
11564 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11565 {
11566 unsigned len = strlen (insn->template);
11567 struct asm_opcode *new;
11568 char *template;
11569
11570 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11571 /* All condition codes are two characters. */
11572 template = obstack_alloc (&insn_obstack, len + 3);
11573
11574 strncpy (template, insn->template, insn->cond_offset);
11575 strcpy (template + insn->cond_offset, conds[j].template);
11576 if (len > insn->cond_offset)
11577 strcpy (template + insn->cond_offset + 2,
11578 insn->template + insn->cond_offset);
11579 new->template = template;
11580 new->cond_offset = 0;
11581 new->variant = insn->variant;
11582 new->parms = insn->parms;
11583 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11584
11585 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11586 }
11587 }
11588 /* Finally, insert the unconditional insn in the table directly;
11589 no need to build a copy. */
11590 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11591 }
11592}
11593
0bbf2aa4 11594#if 0 /* Suppressed - for now. */
5a6c6817
NC
11595#if defined OBJ_ELF || defined OBJ_COFF
11596
11597#ifdef OBJ_ELF
11598#define arm_Note Elf_External_Note
11599#else
11600typedef struct
11601{
11602 unsigned char namesz[4]; /* Size of entry's owner string. */
11603 unsigned char descsz[4]; /* Size of the note descriptor. */
11604 unsigned char type[4]; /* Interpretation of the descriptor. */
11605 char name[1]; /* Start of the name+desc data. */
11606} arm_Note;
11607#endif
11608
11609/* The description is kept to a fix sized in order to make updating
11610 it and merging it easier. */
11611#define ARM_NOTE_DESCRIPTION_LENGTH 8
11612
11613static void
11614arm_add_note (name, description, type)
11615 const char * name;
11616 const char * description;
11617 unsigned int type;
11618{
11619 arm_Note note ATTRIBUTE_UNUSED;
11620 char * p;
11621 unsigned int name_len;
11622
11623 name_len = (strlen (name) + 1 + 3) & ~3;
11624
11625 p = frag_more (sizeof (note.namesz));
11626 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11627
11628 p = frag_more (sizeof (note.descsz));
11629 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11630
11631 p = frag_more (sizeof (note.type));
11632 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11633
11634 p = frag_more (name_len);
11635 strcpy (p, name);
11636
11637 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11638 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11639 frag_align (2, 0, 0);
11640}
11641#endif
0bbf2aa4 11642#endif
5a6c6817 11643
b99bd4ef
NC
11644void
11645md_begin ()
11646{
11647 unsigned mach;
11648 unsigned int i;
11649
11650 if ( (arm_ops_hsh = hash_new ()) == NULL
11651 || (arm_tops_hsh = hash_new ()) == NULL
11652 || (arm_cond_hsh = hash_new ()) == NULL
11653 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11654 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11655 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11656
90e4755a 11657 build_arm_ops_hsh ();
b99bd4ef
NC
11658 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11659 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11660 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11661 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11662 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11663 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11664 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11665 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11666
6c43fab6
RE
11667 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11668 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11669
11670 set_constant_flonums ();
11671
03b1477f
RE
11672 /* Set the cpu variant based on the command-line options. We prefer
11673 -mcpu= over -march= if both are set (as for GCC); and we prefer
11674 -mfpu= over any other way of setting the floating point unit.
11675 Use of legacy options with new options are faulted. */
11676 if (legacy_cpu != -1)
11677 {
11678 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11679 as_bad (_("use of old and new-style options to set CPU type"));
11680
11681 mcpu_cpu_opt = legacy_cpu;
11682 }
11683 else if (mcpu_cpu_opt == -1)
11684 mcpu_cpu_opt = march_cpu_opt;
11685
11686 if (legacy_fpu != -1)
11687 {
11688 if (mfpu_opt != -1)
11689 as_bad (_("use of old and new-style options to set FPU type"));
11690
11691 mfpu_opt = legacy_fpu;
11692 }
11693 else if (mfpu_opt == -1)
11694 {
39c2da32
RE
11695#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11696 /* Some environments specify a default FPU. If they don't, infer it
11697 from the processor. */
03b1477f
RE
11698 if (mcpu_fpu_opt != -1)
11699 mfpu_opt = mcpu_fpu_opt;
11700 else
11701 mfpu_opt = march_fpu_opt;
39c2da32
RE
11702#else
11703 mfpu_opt = FPU_DEFAULT;
11704#endif
03b1477f
RE
11705 }
11706
11707 if (mfpu_opt == -1)
11708 {
11709 if (mcpu_cpu_opt == -1)
11710 mfpu_opt = FPU_DEFAULT;
11711 else if (mcpu_cpu_opt & ARM_EXT_V5)
11712 mfpu_opt = FPU_ARCH_VFP_V2;
11713 else
11714 mfpu_opt = FPU_ARCH_FPA;
11715 }
11716
11717 if (mcpu_cpu_opt == -1)
11718 mcpu_cpu_opt = CPU_DEFAULT;
11719
11720 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11721
b99bd4ef
NC
11722#if defined OBJ_COFF || defined OBJ_ELF
11723 {
11724 unsigned int flags = 0;
11725
11726 /* Set the flags in the private structure. */
11727 if (uses_apcs_26) flags |= F_APCS26;
11728 if (support_interwork) flags |= F_INTERWORK;
11729 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11730 if (pic_code) flags |= F_PIC;
bfae80f2 11731 if ((cpu_variant & FPU_ANY) == FPU_NONE
03b1477f 11732 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
bfae80f2 11733 flags |= F_SOFT_FLOAT;
03b1477f
RE
11734 /* Using VFP conventions (even if soft-float). */
11735 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11736
fde78edd
NC
11737#if defined OBJ_ELF
11738 if (cpu_variant & ARM_CEXT_MAVERICK)
11739 {
5a21e886 11740 flags &= ~ F_SOFT_FLOAT;
fde78edd
NC
11741 flags |= EF_ARM_MAVERICK_FLOAT;
11742 }
11743#endif
b99bd4ef
NC
11744
11745 bfd_set_private_flags (stdoutput, flags);
11746
11747 /* We have run out flags in the COFF header to encode the
11748 status of ATPCS support, so instead we create a dummy,
11749 empty, debug section called .arm.atpcs. */
11750 if (atpcs)
11751 {
11752 asection * sec;
11753
11754 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11755
11756 if (sec != NULL)
11757 {
11758 bfd_set_section_flags
11759 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11760 bfd_set_section_size (stdoutput, sec, 0);
11761 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11762 }
11763 }
11764 }
11765#endif
11766
11767 /* Record the CPU type as well. */
11768 switch (cpu_variant & ARM_CPU_MASK)
11769 {
11770 case ARM_2:
11771 mach = bfd_mach_arm_2;
11772 break;
11773
11774 case ARM_3: /* Also ARM_250. */
11775 mach = bfd_mach_arm_2a;
11776 break;
11777
b89dddec
RE
11778 case ARM_6: /* Also ARM_7. */
11779 mach = bfd_mach_arm_3;
11780 break;
11781
b99bd4ef 11782 default:
5a6c6817 11783 mach = bfd_mach_arm_unknown;
b99bd4ef 11784 break;
b99bd4ef
NC
11785 }
11786
11787 /* Catch special cases. */
e16bb312
NC
11788 if (cpu_variant & ARM_CEXT_IWMMXT)
11789 mach = bfd_mach_arm_iWMMXt;
11790 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11791 mach = bfd_mach_arm_XScale;
fde78edd
NC
11792 else if (cpu_variant & ARM_CEXT_MAVERICK)
11793 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11794 else if (cpu_variant & ARM_EXT_V5E)
11795 mach = bfd_mach_arm_5TE;
11796 else if (cpu_variant & ARM_EXT_V5)
11797 {
b89dddec 11798 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11799 mach = bfd_mach_arm_5T;
11800 else
11801 mach = bfd_mach_arm_5;
11802 }
b89dddec 11803 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11804 {
b89dddec 11805 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11806 mach = bfd_mach_arm_4T;
11807 else
11808 mach = bfd_mach_arm_4;
11809 }
b89dddec 11810 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11811 mach = bfd_mach_arm_3M;
11812
5a6c6817 11813#if 0 /* Suppressed - for now. */
e16bb312 11814#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11815
11816 /* Create a .note section to fully identify this arm binary. */
11817
11818#define NOTE_ARCH_STRING "arch: "
11819
11820#if defined OBJ_COFF && ! defined NT_VERSION
11821#define NT_VERSION 1
11822#define NT_ARCH 2
11823#endif
11824
e16bb312 11825 {
e16bb312
NC
11826 segT current_seg = now_seg;
11827 subsegT current_subseg = now_subseg;
11828 asection * arm_arch;
5a6c6817
NC
11829 const char * arch_string;
11830
e16bb312
NC
11831 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11832
11833#ifdef OBJ_COFF
11834 bfd_set_section_flags (stdoutput, arm_arch,
11835 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11836 | SEC_HAS_CONTENTS);
11837#endif
11838 arm_arch->output_section = arm_arch;
11839 subseg_set (arm_arch, 0);
e16bb312 11840
5a6c6817
NC
11841 switch (mach)
11842 {
11843 default:
11844 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11845 case bfd_mach_arm_2: arch_string = "armv2"; break;
11846 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11847 case bfd_mach_arm_3: arch_string = "armv3"; break;
11848 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11849 case bfd_mach_arm_4: arch_string = "armv4"; break;
11850 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11851 case bfd_mach_arm_5: arch_string = "armv5"; break;
11852 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11853 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11854 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11855 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11856 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11857 }
11858
11859 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11860
11861 subseg_set (current_seg, current_subseg);
11862 }
11863#endif
5a6c6817
NC
11864#endif /* Suppressed code. */
11865
b99bd4ef
NC
11866 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11867}
11868
11869/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11870 for use in the a.out file, and stores them in the array pointed to by buf.
11871 This knows about the endian-ness of the target machine and does
11872 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11873 2 (short) and 4 (long) Floating numbers are put out as a series of
11874 LITTLENUMS (shorts, here at least). */
11875
11876void
11877md_number_to_chars (buf, val, n)
11878 char * buf;
11879 valueT val;
11880 int n;
11881{
11882 if (target_big_endian)
11883 number_to_chars_bigendian (buf, val, n);
11884 else
11885 number_to_chars_littleendian (buf, val, n);
11886}
11887
11888static valueT
11889md_chars_to_number (buf, n)
11890 char * buf;
11891 int n;
11892{
11893 valueT result = 0;
11894 unsigned char * where = (unsigned char *) buf;
11895
11896 if (target_big_endian)
11897 {
11898 while (n--)
11899 {
11900 result <<= 8;
11901 result |= (*where++ & 255);
11902 }
11903 }
11904 else
11905 {
11906 while (n--)
11907 {
11908 result <<= 8;
11909 result |= (where[n] & 255);
11910 }
11911 }
11912
11913 return result;
11914}
11915
11916/* Turn a string in input_line_pointer into a floating point constant
11917 of type TYPE, and store the appropriate bytes in *LITP. The number
11918 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11919 returned, or NULL on OK.
11920
11921 Note that fp constants aren't represent in the normal way on the ARM.
11922 In big endian mode, things are as expected. However, in little endian
11923 mode fp constants are big-endian word-wise, and little-endian byte-wise
11924 within the words. For example, (double) 1.1 in big endian mode is
11925 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11926 the byte sequence 99 99 f1 3f 9a 99 99 99.
11927
11928 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11929
11930char *
11931md_atof (type, litP, sizeP)
11932 char type;
11933 char * litP;
11934 int * sizeP;
11935{
11936 int prec;
11937 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11938 char *t;
11939 int i;
11940
11941 switch (type)
11942 {
11943 case 'f':
11944 case 'F':
11945 case 's':
11946 case 'S':
11947 prec = 2;
11948 break;
11949
11950 case 'd':
11951 case 'D':
11952 case 'r':
11953 case 'R':
11954 prec = 4;
11955 break;
11956
11957 case 'x':
11958 case 'X':
11959 prec = 6;
11960 break;
11961
11962 case 'p':
11963 case 'P':
11964 prec = 6;
11965 break;
11966
11967 default:
11968 *sizeP = 0;
f03698e6 11969 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11970 }
11971
11972 t = atof_ieee (input_line_pointer, type, words);
11973 if (t)
11974 input_line_pointer = t;
11975 *sizeP = prec * 2;
11976
11977 if (target_big_endian)
11978 {
11979 for (i = 0; i < prec; i++)
11980 {
11981 md_number_to_chars (litP, (valueT) words[i], 2);
11982 litP += 2;
11983 }
11984 }
11985 else
11986 {
bfae80f2
RE
11987 if (cpu_variant & FPU_ARCH_VFP)
11988 for (i = prec - 1; i >= 0; i--)
11989 {
11990 md_number_to_chars (litP, (valueT) words[i], 2);
11991 litP += 2;
11992 }
11993 else
11994 /* For a 4 byte float the order of elements in `words' is 1 0.
11995 For an 8 byte float the order is 1 0 3 2. */
11996 for (i = 0; i < prec; i += 2)
11997 {
11998 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11999 md_number_to_chars (litP + 2, (valueT) words[i], 2);
12000 litP += 4;
12001 }
b99bd4ef
NC
12002 }
12003
12004 return 0;
12005}
12006
12007/* The knowledge of the PC's pipeline offset is built into the insns
12008 themselves. */
12009
12010long
12011md_pcrel_from (fixP)
12012 fixS * fixP;
12013{
12014 if (fixP->fx_addsy
12015 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
12016 && fixP->fx_subsy == NULL)
12017 return 0;
12018
12019 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
12020 {
12021 /* PC relative addressing on the Thumb is slightly odd
12022 as the bottom two bits of the PC are forced to zero
12023 for the calculation. */
12024 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
12025 }
12026
12027#ifdef TE_WINCE
2d2255b5
KH
12028 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12029 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
12030 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12031#else
12032 return fixP->fx_where + fixP->fx_frag->fr_address;
12033#endif
12034}
12035
12036/* Round up a section size to the appropriate boundary. */
12037
12038valueT
12039md_section_align (segment, size)
12040 segT segment ATTRIBUTE_UNUSED;
12041 valueT size;
12042{
12043#ifdef OBJ_ELF
12044 return size;
12045#else
12046 /* Round all sects to multiple of 4. */
12047 return (size + 3) & ~3;
12048#endif
12049}
12050
12051/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12052 Otherwise we have no need to default values of symbols. */
12053
12054symbolS *
12055md_undefined_symbol (name)
12056 char * name ATTRIBUTE_UNUSED;
12057{
12058#ifdef OBJ_ELF
12059 if (name[0] == '_' && name[1] == 'G'
12060 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12061 {
12062 if (!GOT_symbol)
12063 {
12064 if (symbol_find (name))
12065 as_bad ("GOT already in the symbol table");
12066
12067 GOT_symbol = symbol_new (name, undefined_section,
12068 (valueT) 0, & zero_address_frag);
12069 }
12070
12071 return GOT_symbol;
12072 }
12073#endif
12074
12075 return 0;
12076}
12077
12078/* arm_reg_parse () := if it looks like a register, return its token and
12079 advance the pointer. */
12080
12081static int
6c43fab6 12082arm_reg_parse (ccp, htab)
b99bd4ef 12083 register char ** ccp;
6c43fab6 12084 struct hash_control *htab;
b99bd4ef
NC
12085{
12086 char * start = * ccp;
12087 char c;
12088 char * p;
12089 struct reg_entry * reg;
12090
12091#ifdef REGISTER_PREFIX
12092 if (*start != REGISTER_PREFIX)
12093 return FAIL;
12094 p = start + 1;
12095#else
12096 p = start;
12097#ifdef OPTIONAL_REGISTER_PREFIX
12098 if (*p == OPTIONAL_REGISTER_PREFIX)
12099 p++, start++;
12100#endif
12101#endif
3882b010 12102 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12103 return FAIL;
12104
12105 c = *p++;
3882b010 12106 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12107 c = *p++;
12108
12109 *--p = 0;
6c43fab6 12110 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12111 *p = c;
12112
12113 if (reg)
12114 {
12115 *ccp = p;
12116 return reg->number;
12117 }
12118
12119 return FAIL;
12120}
12121
6c43fab6
RE
12122/* Search for the following register name in each of the possible reg name
12123 tables. Return the classification if found, or REG_TYPE_MAX if not
12124 present. */
12125static enum arm_reg_type
12126arm_reg_parse_any (cp)
12127 char *cp;
12128{
12129 int i;
12130
12131 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12132 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12133 return (enum arm_reg_type) i;
12134
12135 return REG_TYPE_MAX;
12136}
12137
94f592af
NC
12138void
12139md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12140 fixS * fixP;
94f592af 12141 valueT * valP;
b99bd4ef
NC
12142 segT seg;
12143{
94f592af 12144 offsetT value = * valP;
b99bd4ef
NC
12145 offsetT newval;
12146 unsigned int newimm;
12147 unsigned long temp;
12148 int sign;
12149 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12150 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12151
12152 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12153
12154 /* Note whether this will delete the relocation. */
12155#if 0
12156 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12157 doesn't work fully.) */
12158 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12159 && !fixP->fx_pcrel)
12160#else
12161 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12162#endif
12163 fixP->fx_done = 1;
12164
12165 /* If this symbol is in a different section then we need to leave it for
12166 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12167 so we have to undo it's effects here. */
12168 if (fixP->fx_pcrel)
12169 {
12170 if (fixP->fx_addsy != NULL
12171 && S_IS_DEFINED (fixP->fx_addsy)
12172 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12173 {
12174 if (target_oabi
12175 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12176 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12177 ))
12178 value = 0;
12179 else
12180 value += md_pcrel_from (fixP);
12181 }
12182 }
12183
12184 /* Remember value for emit_reloc. */
12185 fixP->fx_addnumber = value;
12186
12187 switch (fixP->fx_r_type)
12188 {
12189 case BFD_RELOC_ARM_IMMEDIATE:
12190 newimm = validate_immediate (value);
12191 temp = md_chars_to_number (buf, INSN_SIZE);
12192
12193 /* If the instruction will fail, see if we can fix things up by
12194 changing the opcode. */
12195 if (newimm == (unsigned int) FAIL
12196 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12197 {
12198 as_bad_where (fixP->fx_file, fixP->fx_line,
12199 _("invalid constant (%lx) after fixup"),
12200 (unsigned long) value);
12201 break;
12202 }
12203
12204 newimm |= (temp & 0xfffff000);
12205 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
6189168b 12206 fixP->fx_done = 1;
b99bd4ef
NC
12207 break;
12208
12209 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12210 {
12211 unsigned int highpart = 0;
12212 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12213
b99bd4ef
NC
12214 newimm = validate_immediate (value);
12215 temp = md_chars_to_number (buf, INSN_SIZE);
12216
12217 /* If the instruction will fail, see if we can fix things up by
12218 changing the opcode. */
12219 if (newimm == (unsigned int) FAIL
12220 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12221 {
12222 /* No ? OK - try using two ADD instructions to generate
12223 the value. */
12224 newimm = validate_immediate_twopart (value, & highpart);
12225
12226 /* Yes - then make sure that the second instruction is
12227 also an add. */
12228 if (newimm != (unsigned int) FAIL)
12229 newinsn = temp;
12230 /* Still No ? Try using a negated value. */
12231 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12232 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12233 /* Otherwise - give up. */
12234 else
12235 {
12236 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12237 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12238 (long) value);
b99bd4ef
NC
12239 break;
12240 }
12241
12242 /* Replace the first operand in the 2nd instruction (which
12243 is the PC) with the destination register. We have
12244 already added in the PC in the first instruction and we
12245 do not want to do it again. */
12246 newinsn &= ~ 0xf0000;
12247 newinsn |= ((newinsn & 0x0f000) << 4);
12248 }
12249
12250 newimm |= (temp & 0xfffff000);
12251 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12252
12253 highpart |= (newinsn & 0xfffff000);
12254 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12255 }
12256 break;
12257
12258 case BFD_RELOC_ARM_OFFSET_IMM:
12259 sign = value >= 0;
12260
12261 if (value < 0)
12262 value = - value;
12263
12264 if (validate_offset_imm (value, 0) == FAIL)
12265 {
12266 as_bad_where (fixP->fx_file, fixP->fx_line,
12267 _("bad immediate value for offset (%ld)"),
12268 (long) value);
12269 break;
12270 }
12271
12272 newval = md_chars_to_number (buf, INSN_SIZE);
12273 newval &= 0xff7ff000;
12274 newval |= value | (sign ? INDEX_UP : 0);
12275 md_number_to_chars (buf, newval, INSN_SIZE);
12276 break;
12277
12278 case BFD_RELOC_ARM_OFFSET_IMM8:
12279 case BFD_RELOC_ARM_HWLITERAL:
12280 sign = value >= 0;
12281
12282 if (value < 0)
12283 value = - value;
12284
12285 if (validate_offset_imm (value, 1) == FAIL)
12286 {
12287 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12288 as_bad_where (fixP->fx_file, fixP->fx_line,
12289 _("invalid literal constant: pool needs to be closer"));
12290 else
12291 as_bad (_("bad immediate value for half-word offset (%ld)"),
12292 (long) value);
12293 break;
12294 }
12295
12296 newval = md_chars_to_number (buf, INSN_SIZE);
12297 newval &= 0xff7ff0f0;
12298 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12299 md_number_to_chars (buf, newval, INSN_SIZE);
12300 break;
12301
12302 case BFD_RELOC_ARM_LITERAL:
12303 sign = value >= 0;
12304
12305 if (value < 0)
12306 value = - value;
12307
12308 if (validate_offset_imm (value, 0) == FAIL)
12309 {
12310 as_bad_where (fixP->fx_file, fixP->fx_line,
12311 _("invalid literal constant: pool needs to be closer"));
12312 break;
12313 }
12314
12315 newval = md_chars_to_number (buf, INSN_SIZE);
12316 newval &= 0xff7ff000;
12317 newval |= value | (sign ? INDEX_UP : 0);
12318 md_number_to_chars (buf, newval, INSN_SIZE);
12319 break;
12320
12321 case BFD_RELOC_ARM_SHIFT_IMM:
12322 newval = md_chars_to_number (buf, INSN_SIZE);
12323 if (((unsigned long) value) > 32
12324 || (value == 32
12325 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12326 {
12327 as_bad_where (fixP->fx_file, fixP->fx_line,
12328 _("shift expression is too large"));
12329 break;
12330 }
12331
12332 if (value == 0)
12333 /* Shifts of zero must be done as lsl. */
12334 newval &= ~0x60;
12335 else if (value == 32)
12336 value = 0;
12337 newval &= 0xfffff07f;
12338 newval |= (value & 0x1f) << 7;
12339 md_number_to_chars (buf, newval, INSN_SIZE);
12340 break;
12341
12342 case BFD_RELOC_ARM_SWI:
12343 if (arm_data->thumb_mode)
12344 {
12345 if (((unsigned long) value) > 0xff)
12346 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12347 _("invalid swi expression"));
b99bd4ef
NC
12348 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12349 newval |= value;
12350 md_number_to_chars (buf, newval, THUMB_SIZE);
12351 }
12352 else
12353 {
12354 if (((unsigned long) value) > 0x00ffffff)
12355 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12356 _("invalid swi expression"));
b99bd4ef
NC
12357 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12358 newval |= value;
12359 md_number_to_chars (buf, newval, INSN_SIZE);
12360 }
12361 break;
12362
12363 case BFD_RELOC_ARM_MULTI:
12364 if (((unsigned long) value) > 0xffff)
12365 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12366 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12367 newval = value | md_chars_to_number (buf, INSN_SIZE);
12368 md_number_to_chars (buf, newval, INSN_SIZE);
12369 break;
12370
12371 case BFD_RELOC_ARM_PCREL_BRANCH:
12372 newval = md_chars_to_number (buf, INSN_SIZE);
12373
12374 /* Sign-extend a 24-bit number. */
12375#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12376
12377#ifdef OBJ_ELF
12378 if (! target_oabi)
12379 value = fixP->fx_offset;
12380#endif
12381
12382 /* We are going to store value (shifted right by two) in the
12383 instruction, in a 24 bit, signed field. Thus we need to check
12384 that none of the top 8 bits of the shifted value (top 7 bits of
12385 the unshifted, unsigned value) are set, or that they are all set. */
12386 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12387 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12388 {
12389#ifdef OBJ_ELF
12390 /* Normally we would be stuck at this point, since we cannot store
12391 the absolute address that is the destination of the branch in the
12392 24 bits of the branch instruction. If however, we happen to know
12393 that the destination of the branch is in the same section as the
2d2255b5 12394 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12395 ourselves and not have to bother the linker with it.
12396
12397 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12398 because I have not worked out how to do this for OBJ_COFF or
12399 target_oabi. */
12400 if (! target_oabi
12401 && fixP->fx_addsy != NULL
12402 && S_IS_DEFINED (fixP->fx_addsy)
12403 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12404 {
12405 /* Get pc relative value to go into the branch. */
94f592af 12406 value = * valP;
b99bd4ef
NC
12407
12408 /* Permit a backward branch provided that enough bits
12409 are set. Allow a forwards branch, provided that
12410 enough bits are clear. */
12411 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12412 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12413 fixP->fx_done = 1;
12414 }
12415
12416 if (! fixP->fx_done)
12417#endif
12418 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12419 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12420 }
12421
12422 value >>= 2;
12423 value += SEXT24 (newval);
12424
12425 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12426 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12427 as_bad_where (fixP->fx_file, fixP->fx_line,
12428 _("out of range branch"));
12429
12430 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12431 md_number_to_chars (buf, newval, INSN_SIZE);
12432 break;
12433
12434 case BFD_RELOC_ARM_PCREL_BLX:
12435 {
12436 offsetT hbit;
12437 newval = md_chars_to_number (buf, INSN_SIZE);
12438
12439#ifdef OBJ_ELF
12440 if (! target_oabi)
12441 value = fixP->fx_offset;
12442#endif
12443 hbit = (value >> 1) & 1;
12444 value = (value >> 2) & 0x00ffffff;
12445 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12446 newval = value | (newval & 0xfe000000) | (hbit << 24);
12447 md_number_to_chars (buf, newval, INSN_SIZE);
12448 }
12449 break;
12450
12451 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12452 newval = md_chars_to_number (buf, THUMB_SIZE);
12453 {
12454 addressT diff = (newval & 0xff) << 1;
12455 if (diff & 0x100)
12456 diff |= ~0xff;
12457
12458 value += diff;
12459 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12460 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12461 _("branch out of range"));
b99bd4ef
NC
12462 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12463 }
12464 md_number_to_chars (buf, newval, THUMB_SIZE);
12465 break;
12466
12467 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12468 newval = md_chars_to_number (buf, THUMB_SIZE);
12469 {
12470 addressT diff = (newval & 0x7ff) << 1;
12471 if (diff & 0x800)
12472 diff |= ~0x7ff;
12473
12474 value += diff;
12475 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12476 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12477 _("branch out of range"));
b99bd4ef
NC
12478 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12479 }
12480 md_number_to_chars (buf, newval, THUMB_SIZE);
12481 break;
12482
12483 case BFD_RELOC_THUMB_PCREL_BLX:
12484 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12485 {
12486 offsetT newval2;
12487 addressT diff;
12488
12489 newval = md_chars_to_number (buf, THUMB_SIZE);
12490 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12491 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12492 if (diff & 0x400000)
12493 diff |= ~0x3fffff;
12494#ifdef OBJ_ELF
12495 value = fixP->fx_offset;
12496#endif
12497 value += diff;
c62e1cc3 12498
b99bd4ef
NC
12499 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12500 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12501 _("branch with link out of range"));
b99bd4ef
NC
12502
12503 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12504 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12505 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12506 /* For a BLX instruction, make sure that the relocation is rounded up
12507 to a word boundary. This follows the semantics of the instruction
12508 which specifies that bit 1 of the target address will come from bit
12509 1 of the base address. */
12510 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12511 md_number_to_chars (buf, newval, THUMB_SIZE);
12512 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12513 }
12514 break;
12515
12516 case BFD_RELOC_8:
12517 if (fixP->fx_done || fixP->fx_pcrel)
12518 md_number_to_chars (buf, value, 1);
12519#ifdef OBJ_ELF
12520 else if (!target_oabi)
12521 {
12522 value = fixP->fx_offset;
12523 md_number_to_chars (buf, value, 1);
12524 }
12525#endif
12526 break;
12527
12528 case BFD_RELOC_16:
12529 if (fixP->fx_done || fixP->fx_pcrel)
12530 md_number_to_chars (buf, value, 2);
12531#ifdef OBJ_ELF
12532 else if (!target_oabi)
12533 {
12534 value = fixP->fx_offset;
12535 md_number_to_chars (buf, value, 2);
12536 }
12537#endif
12538 break;
12539
12540#ifdef OBJ_ELF
12541 case BFD_RELOC_ARM_GOT32:
12542 case BFD_RELOC_ARM_GOTOFF:
12543 md_number_to_chars (buf, 0, 4);
12544 break;
12545#endif
12546
12547 case BFD_RELOC_RVA:
12548 case BFD_RELOC_32:
12549 if (fixP->fx_done || fixP->fx_pcrel)
12550 md_number_to_chars (buf, value, 4);
12551#ifdef OBJ_ELF
12552 else if (!target_oabi)
12553 {
12554 value = fixP->fx_offset;
12555 md_number_to_chars (buf, value, 4);
12556 }
12557#endif
12558 break;
12559
12560#ifdef OBJ_ELF
12561 case BFD_RELOC_ARM_PLT32:
12562 /* It appears the instruction is fully prepared at this point. */
12563 break;
12564#endif
12565
b99bd4ef
NC
12566 case BFD_RELOC_ARM_CP_OFF_IMM:
12567 sign = value >= 0;
12568 if (value < -1023 || value > 1023 || (value & 3))
12569 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12570 _("illegal value for co-processor offset"));
b99bd4ef
NC
12571 if (value < 0)
12572 value = -value;
12573 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12574 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12575 md_number_to_chars (buf, newval, INSN_SIZE);
12576 break;
12577
e16bb312
NC
12578 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12579 sign = value >= 0;
12580 if (value < -255 || value > 255)
12581 as_bad_where (fixP->fx_file, fixP->fx_line,
12582 _("Illegal value for co-processor offset"));
12583 if (value < 0)
12584 value = -value;
12585 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12586 newval |= value | (sign ? INDEX_UP : 0);
12587 md_number_to_chars (buf, newval , INSN_SIZE);
12588 break;
12589
b99bd4ef
NC
12590 case BFD_RELOC_ARM_THUMB_OFFSET:
12591 newval = md_chars_to_number (buf, THUMB_SIZE);
12592 /* Exactly what ranges, and where the offset is inserted depends
12593 on the type of instruction, we can establish this from the
12594 top 4 bits. */
12595 switch (newval >> 12)
12596 {
12597 case 4: /* PC load. */
12598 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12599 forced to zero for these loads, so we will need to round
12600 up the offset if the instruction address is not word
12601 aligned (since the final address produced must be, and
12602 we can only describe word-aligned immediate offsets). */
12603
12604 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12605 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12606 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12607 (unsigned int) (fixP->fx_frag->fr_address
12608 + fixP->fx_where + value));
12609
12610 if ((value + 2) & ~0x3fe)
12611 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12612 _("invalid offset, value too big (0x%08lX)"),
12613 (long) value);
b99bd4ef
NC
12614
12615 /* Round up, since pc will be rounded down. */
12616 newval |= (value + 2) >> 2;
12617 break;
12618
12619 case 9: /* SP load/store. */
12620 if (value & ~0x3fc)
12621 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12622 _("invalid offset, value too big (0x%08lX)"),
12623 (long) value);
b99bd4ef
NC
12624 newval |= value >> 2;
12625 break;
12626
12627 case 6: /* Word load/store. */
12628 if (value & ~0x7c)
12629 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12630 _("invalid offset, value too big (0x%08lX)"),
12631 (long) value);
b99bd4ef
NC
12632 newval |= value << 4; /* 6 - 2. */
12633 break;
12634
12635 case 7: /* Byte load/store. */
12636 if (value & ~0x1f)
12637 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12638 _("invalid offset, value too big (0x%08lX)"),
12639 (long) value);
b99bd4ef
NC
12640 newval |= value << 6;
12641 break;
12642
12643 case 8: /* Halfword load/store. */
12644 if (value & ~0x3e)
12645 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12646 _("invalid offset, value too big (0x%08lX)"),
12647 (long) value);
b99bd4ef
NC
12648 newval |= value << 5; /* 6 - 1. */
12649 break;
12650
12651 default:
12652 as_bad_where (fixP->fx_file, fixP->fx_line,
12653 "Unable to process relocation for thumb opcode: %lx",
12654 (unsigned long) newval);
12655 break;
12656 }
12657 md_number_to_chars (buf, newval, THUMB_SIZE);
12658 break;
12659
12660 case BFD_RELOC_ARM_THUMB_ADD:
12661 /* This is a complicated relocation, since we use it for all of
12662 the following immediate relocations:
12663
12664 3bit ADD/SUB
12665 8bit ADD/SUB
12666 9bit ADD/SUB SP word-aligned
12667 10bit ADD PC/SP word-aligned
12668
12669 The type of instruction being processed is encoded in the
12670 instruction field:
12671
12672 0x8000 SUB
12673 0x00F0 Rd
12674 0x000F Rs
12675 */
12676 newval = md_chars_to_number (buf, THUMB_SIZE);
12677 {
12678 int rd = (newval >> 4) & 0xf;
12679 int rs = newval & 0xf;
12680 int subtract = newval & 0x8000;
12681
12682 if (rd == REG_SP)
12683 {
12684 if (value & ~0x1fc)
12685 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12686 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12687 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12688 newval |= value >> 2;
12689 }
12690 else if (rs == REG_PC || rs == REG_SP)
12691 {
12692 if (subtract ||
12693 value & ~0x3fc)
12694 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12695 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12696 (unsigned long) value);
12697 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12698 newval |= rd << 8;
12699 newval |= value >> 2;
12700 }
12701 else if (rs == rd)
12702 {
12703 if (value & ~0xff)
12704 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12705 _("invalid 8bit immediate"));
b99bd4ef
NC
12706 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12707 newval |= (rd << 8) | value;
12708 }
12709 else
12710 {
12711 if (value & ~0x7)
12712 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12713 _("invalid 3bit immediate"));
b99bd4ef
NC
12714 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12715 newval |= rd | (rs << 3) | (value << 6);
12716 }
12717 }
12718 md_number_to_chars (buf, newval, THUMB_SIZE);
12719 break;
12720
12721 case BFD_RELOC_ARM_THUMB_IMM:
12722 newval = md_chars_to_number (buf, THUMB_SIZE);
12723 switch (newval >> 11)
12724 {
12725 case 0x04: /* 8bit immediate MOV. */
12726 case 0x05: /* 8bit immediate CMP. */
12727 if (value < 0 || value > 255)
12728 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12729 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12730 (long) value);
12731 newval |= value;
12732 break;
12733
12734 default:
12735 abort ();
12736 }
12737 md_number_to_chars (buf, newval, THUMB_SIZE);
12738 break;
12739
12740 case BFD_RELOC_ARM_THUMB_SHIFT:
12741 /* 5bit shift value (0..31). */
12742 if (value < 0 || value > 31)
12743 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12744 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12745 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12746 newval |= value << 6;
12747 md_number_to_chars (buf, newval, THUMB_SIZE);
12748 break;
12749
12750 case BFD_RELOC_VTABLE_INHERIT:
12751 case BFD_RELOC_VTABLE_ENTRY:
12752 fixP->fx_done = 0;
94f592af 12753 return;
b99bd4ef
NC
12754
12755 case BFD_RELOC_NONE:
12756 default:
12757 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12758 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12759 }
b99bd4ef
NC
12760}
12761
12762/* Translate internal representation of relocation info to BFD target
12763 format. */
12764
12765arelent *
12766tc_gen_reloc (section, fixp)
12767 asection * section ATTRIBUTE_UNUSED;
12768 fixS * fixp;
12769{
12770 arelent * reloc;
12771 bfd_reloc_code_real_type code;
12772
12773 reloc = (arelent *) xmalloc (sizeof (arelent));
12774
12775 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12776 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12777 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12778
12779 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12780#ifndef OBJ_ELF
12781 if (fixp->fx_pcrel == 0)
12782 reloc->addend = fixp->fx_offset;
12783 else
12784 reloc->addend = fixp->fx_offset = reloc->address;
12785#else /* OBJ_ELF */
12786 reloc->addend = fixp->fx_offset;
12787#endif
12788
12789 switch (fixp->fx_r_type)
12790 {
12791 case BFD_RELOC_8:
12792 if (fixp->fx_pcrel)
12793 {
12794 code = BFD_RELOC_8_PCREL;
12795 break;
12796 }
12797
12798 case BFD_RELOC_16:
12799 if (fixp->fx_pcrel)
12800 {
12801 code = BFD_RELOC_16_PCREL;
12802 break;
12803 }
12804
12805 case BFD_RELOC_32:
12806 if (fixp->fx_pcrel)
12807 {
12808 code = BFD_RELOC_32_PCREL;
12809 break;
12810 }
12811
12812 case BFD_RELOC_ARM_PCREL_BRANCH:
12813 case BFD_RELOC_ARM_PCREL_BLX:
12814 case BFD_RELOC_RVA:
12815 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12816 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12817 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12818 case BFD_RELOC_THUMB_PCREL_BLX:
12819 case BFD_RELOC_VTABLE_ENTRY:
12820 case BFD_RELOC_VTABLE_INHERIT:
12821 code = fixp->fx_r_type;
12822 break;
12823
12824 case BFD_RELOC_ARM_LITERAL:
12825 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12826 /* If this is called then the a literal has
12827 been referenced across a section boundary. */
b99bd4ef 12828 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12829 _("literal referenced across section boundary"));
b99bd4ef
NC
12830 return NULL;
12831
12832#ifdef OBJ_ELF
12833 case BFD_RELOC_ARM_GOT32:
12834 case BFD_RELOC_ARM_GOTOFF:
12835 case BFD_RELOC_ARM_PLT32:
12836 code = fixp->fx_r_type;
12837 break;
12838#endif
12839
12840 case BFD_RELOC_ARM_IMMEDIATE:
12841 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12842 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12843 return NULL;
12844
12845 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12846 as_bad_where (fixp->fx_file, fixp->fx_line,
12847 _("ADRL used for a symbol not defined in the same file"));
12848 return NULL;
12849
12850 case BFD_RELOC_ARM_OFFSET_IMM:
12851 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12852 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12853 return NULL;
12854
12855 default:
12856 {
12857 char * type;
12858
12859 switch (fixp->fx_r_type)
12860 {
b99bd4ef
NC
12861 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12862 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12863 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12864 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12865 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12866 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12867 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12868 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12869 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12870 default: type = _("<unknown>"); break;
12871 }
12872 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12873 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12874 type);
12875 return NULL;
12876 }
12877 }
12878
12879#ifdef OBJ_ELF
8df7094c 12880 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12881 && GOT_symbol
12882 && fixp->fx_addsy == GOT_symbol)
12883 {
12884 code = BFD_RELOC_ARM_GOTPC;
12885 reloc->addend = fixp->fx_offset = reloc->address;
12886 }
12887#endif
12888
12889 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12890
12891 if (reloc->howto == NULL)
12892 {
12893 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12894 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12895 bfd_get_reloc_code_name (code));
12896 return NULL;
12897 }
12898
12899 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12900 vtable entry to be used in the relocation's section offset. */
12901 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12902 reloc->address = fixp->fx_offset;
12903
12904 return reloc;
12905}
12906
12907int
12908md_estimate_size_before_relax (fragP, segtype)
12909 fragS * fragP ATTRIBUTE_UNUSED;
12910 segT segtype ATTRIBUTE_UNUSED;
12911{
12912 as_fatal (_("md_estimate_size_before_relax\n"));
12913 return 1;
12914}
12915
12916static void
f03698e6
RE
12917output_inst (str)
12918 const char *str;
b99bd4ef
NC
12919{
12920 char * to = NULL;
12921
12922 if (inst.error)
12923 {
f03698e6 12924 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12925 return;
12926 }
12927
12928 to = frag_more (inst.size);
12929
12930 if (thumb_mode && (inst.size > THUMB_SIZE))
12931 {
12932 assert (inst.size == (2 * THUMB_SIZE));
12933 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12934 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12935 }
12936 else if (inst.size > INSN_SIZE)
12937 {
12938 assert (inst.size == (2 * INSN_SIZE));
12939 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12940 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12941 }
12942 else
12943 md_number_to_chars (to, inst.instruction, inst.size);
12944
12945 if (inst.reloc.type != BFD_RELOC_NONE)
12946 fix_new_arm (frag_now, to - frag_now->fr_literal,
12947 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12948 inst.reloc.type);
12949
12950#ifdef OBJ_ELF
12951 dwarf2_emit_insn (inst.size);
12952#endif
12953}
12954
12955void
12956md_assemble (str)
12957 char * str;
12958{
6c43fab6
RE
12959 char c;
12960 char *p;
12961 char *start;
b99bd4ef
NC
12962
12963 /* Align the instruction.
12964 This may not be the right thing to do but ... */
12965#if 0
12966 arm_align (2, 0);
12967#endif
b99bd4ef
NC
12968
12969 /* Align the previous label if needed. */
12970 if (last_label_seen != NULL)
12971 {
12972 symbol_set_frag (last_label_seen, frag_now);
12973 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12974 S_SET_SEGMENT (last_label_seen, now_seg);
12975 }
12976
12977 memset (&inst, '\0', sizeof (inst));
12978 inst.reloc.type = BFD_RELOC_NONE;
12979
12980 skip_whitespace (str);
12981
12982 /* Scan up to the end of the op-code, which must end in white space or
12983 end of string. */
12984 for (start = p = str; *p != '\0'; p++)
12985 if (*p == ' ')
12986 break;
12987
12988 if (p == str)
12989 {
f03698e6 12990 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12991 return;
12992 }
12993
12994 if (thumb_mode)
12995 {
05d2d07e 12996 const struct thumb_opcode * opcode;
b99bd4ef
NC
12997
12998 c = *p;
12999 *p = '\0';
05d2d07e 13000 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
13001 *p = c;
13002
13003 if (opcode)
13004 {
13005 /* Check that this instruction is supported for this CPU. */
90e4755a 13006 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 13007 {
f03698e6 13008 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13009 return;
13010 }
13011
6057a28f 13012 mapping_state (MAP_THUMB);
b99bd4ef
NC
13013 inst.instruction = opcode->value;
13014 inst.size = opcode->size;
13015 (*opcode->parms) (p);
f03698e6 13016 output_inst (str);
b99bd4ef
NC
13017 return;
13018 }
13019 }
13020 else
13021 {
05d2d07e 13022 const struct asm_opcode * opcode;
b99bd4ef 13023
90e4755a
RE
13024 c = *p;
13025 *p = '\0';
6c43fab6 13026 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 13027 *p = c;
b99bd4ef 13028
90e4755a 13029 if (opcode)
b99bd4ef 13030 {
90e4755a
RE
13031 /* Check that this instruction is supported for this CPU. */
13032 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 13033 {
f03698e6 13034 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
13035 return;
13036 }
13037
6057a28f 13038 mapping_state (MAP_ARM);
90e4755a
RE
13039 inst.instruction = opcode->value;
13040 inst.size = INSN_SIZE;
f2b7cb0a 13041 (*opcode->parms) (p);
f03698e6 13042 output_inst (str);
90e4755a 13043 return;
b99bd4ef
NC
13044 }
13045 }
13046
13047 /* It wasn't an instruction, but it might be a register alias of the form
13048 alias .req reg. */
6c43fab6
RE
13049 if (create_register_alias (str, p))
13050 return;
b99bd4ef 13051
b99bd4ef
NC
13052 as_bad (_("bad instruction `%s'"), start);
13053}
13054
13055/* md_parse_option
13056 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 13057 See if it's a processor-specific option.
03b1477f
RE
13058
13059 This routine is somewhat complicated by the need for backwards
13060 compatibility (since older releases of gcc can't be changed).
13061 The new options try to make the interface as compatible as
13062 possible with GCC.
13063
13064 New options (supported) are:
13065
13066 -mcpu=<cpu name> Assemble for selected processor
13067 -march=<architecture name> Assemble for selected architecture
13068 -mfpu=<fpu architecture> Assemble for selected FPU.
13069 -EB/-mbig-endian Big-endian
13070 -EL/-mlittle-endian Little-endian
13071 -k Generate PIC code
13072 -mthumb Start in Thumb mode
13073 -mthumb-interwork Code supports ARM/Thumb interworking
13074
3d0c9500 13075 For now we will also provide support for:
03b1477f
RE
13076
13077 -mapcs-32 32-bit Program counter
13078 -mapcs-26 26-bit Program counter
13079 -macps-float Floats passed in FP registers
13080 -mapcs-reentrant Reentrant code
13081 -matpcs
13082 (sometime these will probably be replaced with -mapcs=<list of options>
13083 and -matpcs=<list of options>)
13084
13085 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13086 Cpu variants, the arm part is optional:
13087 -m[arm]1 Currently not supported.
13088 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13089 -m[arm]3 Arm 3 processor
13090 -m[arm]6[xx], Arm 6 processors
13091 -m[arm]7[xx][t][[d]m] Arm 7 processors
13092 -m[arm]8[10] Arm 8 processors
13093 -m[arm]9[20][tdmi] Arm 9 processors
13094 -mstrongarm[110[0]] StrongARM processors
13095 -mxscale XScale processors
13096 -m[arm]v[2345[t[e]]] Arm architectures
13097 -mall All (except the ARM1)
13098 FP variants:
13099 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13100 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13101 -mvfpxd VFP Single precision
13102 -mvfp All VFP
b99bd4ef 13103 -mno-fpu Disable all floating point instructions
b99bd4ef 13104
03b1477f
RE
13105 The following CPU names are recognized:
13106 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13107 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13108 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13109 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13110 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13111 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13112 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13113
13114 */
13115
5a38dc70 13116const char * md_shortopts = "m:k";
03b1477f 13117
b99bd4ef
NC
13118#ifdef ARM_BI_ENDIAN
13119#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13120#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13121#else
21f0f23a
RE
13122#if TARGET_BYTES_BIG_ENDIAN
13123#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13124#else
13125#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13126#endif
ce058b6c 13127#endif
03b1477f
RE
13128
13129struct option md_longopts[] =
13130{
13131#ifdef OPTION_EB
13132 {"EB", no_argument, NULL, OPTION_EB},
13133#endif
13134#ifdef OPTION_EL
13135 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13136#endif
13137 {NULL, no_argument, NULL, 0}
13138};
13139
13140size_t md_longopts_size = sizeof (md_longopts);
13141
03b1477f 13142struct arm_option_table
b99bd4ef 13143{
03b1477f
RE
13144 char *option; /* Option name to match. */
13145 char *help; /* Help information. */
13146 int *var; /* Variable to change. */
13147 int value; /* What to change it to. */
13148 char *deprecated; /* If non-null, print this message. */
13149};
b99bd4ef 13150
cc8a6dd0 13151struct arm_option_table arm_opts[] =
03b1477f
RE
13152{
13153 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13154 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13155 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13156 &support_interwork, 1, NULL},
13157 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13158 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13159 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13160 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13161 1, NULL},
13162 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13163 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13164 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13165 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13166 NULL},
13167
13168 /* These are recognized by the assembler, but have no affect on code. */
13169 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13170 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13171
13172 /* DON'T add any new processors to this list -- we want the whole list
13173 to go away... Add them to the processors table instead. */
13174 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13175 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13176 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13177 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13178 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13179 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13180 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13181 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13182 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13183 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13184 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13185 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13186 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13187 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13188 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13189 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13190 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13191 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13192 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13193 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13194 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13195 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13196 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13197 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13198 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13199 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13200 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13201 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13202 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13203 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13204 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13205 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13206 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13207 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13208 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13209 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13210 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13211 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13212 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13213 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13214 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13215 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13216 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13217 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13218 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13219 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13220 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13221 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13222 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13223 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13224 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13225 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13226 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13227 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13228 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13229 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13230 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13231 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13232 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13233 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13234 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13235 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13236 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13237 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13238 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13239 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13240 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13241 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13242 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13243 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13244 N_("use -mcpu=strongarm110")},
13245 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13246 N_("use -mcpu=strongarm1100")},
13247 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13248 N_("use -mcpu=strongarm1110")},
13249 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13250 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13251 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13252
13253 /* Architecture variants -- don't add any more to this list either. */
13254 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13255 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13256 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13257 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13258 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13259 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13260 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13261 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13262 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13263 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13264 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13265 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13266 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13267 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13268 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13269 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13270 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13271 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13272
13273 /* Floating point variants -- don't add any more to this list either. */
13274 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13275 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13276 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13277 {"mno-fpu", NULL, &legacy_fpu, 0,
13278 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13279
13280 {NULL, NULL, NULL, 0, NULL}
13281};
21f0f23a 13282
03b1477f
RE
13283struct arm_cpu_option_table
13284{
13285 char *name;
13286 int value;
13287 /* For some CPUs we assume an FPU unless the user explicitly sets
13288 -mfpu=... */
13289 int default_fpu;
13290};
13291
13292/* This list should, at a minimum, contain all the cpu names
13293 recognized by GCC. */
13294static struct arm_cpu_option_table arm_cpus[] =
13295{
13296 {"all", ARM_ANY, FPU_ARCH_FPA},
13297 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13298 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13299 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13300 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13301 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13302 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13303 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13304 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13305 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13306 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13307 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13308 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13309 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13310 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13311 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13312 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13313 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13314 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13315 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13316 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13317 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13318 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13319 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13320 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13321 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13322 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13323 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13324 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13325 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13326 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13327 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13328 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13329 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13330 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13331 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13332 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13333 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13334 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13335 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13336 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13337 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13338 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13339 /* For V5 or later processors we default to using VFP; but the user
13340 should really set the FPU type explicitly. */
13341 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13342 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13343 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13344 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13345 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13346 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13347 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13348 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13349 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13350 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13351 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13352 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015
MM
13353 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13354 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13355 /* ??? XSCALE is really an architecture. */
13356 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13357 /* ??? iwmmxt is not a processor. */
e16bb312 13358 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13359 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13360 /* Maverick */
13361 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
13362 {NULL, 0, 0}
13363};
cc8a6dd0 13364
03b1477f
RE
13365struct arm_arch_option_table
13366{
13367 char *name;
13368 int value;
13369 int default_fpu;
13370};
13371
13372/* This list should, at a minimum, contain all the architecture names
13373 recognized by GCC. */
13374static struct arm_arch_option_table arm_archs[] =
13375{
13376 {"all", ARM_ANY, FPU_ARCH_FPA},
13377 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13378 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13379 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13380 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13381 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13382 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13383 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13384 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13385 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13386 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13387 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13388 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13389 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13390 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13391 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13392 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
09d92015 13393 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13394 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13395 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13396 {NULL, 0, 0}
13397};
13398
13399/* ISA extensions in the co-processor space. */
13400struct arm_arch_extension_table
13401{
13402 char *name;
13403 int value;
13404};
13405
13406static struct arm_arch_extension_table arm_extensions[] =
13407{
13408 {"maverick", ARM_CEXT_MAVERICK},
13409 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13410 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13411 {NULL, 0}
13412};
b99bd4ef 13413
03b1477f
RE
13414struct arm_fpu_option_table
13415{
13416 char *name;
13417 int value;
13418};
13419
13420/* This list should, at a minimum, contain all the fpu names
13421 recognized by GCC. */
13422static struct arm_fpu_option_table arm_fpus[] =
13423{
13424 {"softfpa", FPU_NONE},
13425 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13426 {"fpe2", FPU_ARCH_FPE},
13427 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13428 {"fpa", FPU_ARCH_FPA},
13429 {"fpa10", FPU_ARCH_FPA},
13430 {"fpa11", FPU_ARCH_FPA},
13431 {"arm7500fe", FPU_ARCH_FPA},
13432 {"softvfp", FPU_ARCH_VFP},
13433 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13434 {"vfp", FPU_ARCH_VFP_V2},
13435 {"vfp9", FPU_ARCH_VFP_V2},
13436 {"vfp10", FPU_ARCH_VFP_V2},
13437 {"vfp10-r0", FPU_ARCH_VFP_V1},
13438 {"vfpxd", FPU_ARCH_VFP_V1xD},
13439 {"arm1020t", FPU_ARCH_VFP_V1},
13440 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13441 {"arm1136jfs", FPU_ARCH_VFP_V2},
03b1477f
RE
13442 {NULL, 0}
13443};
13444
13445struct arm_long_option_table
13446{
13447 char *option; /* Substring to match. */
13448 char *help; /* Help information. */
13449 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13450 char *deprecated; /* If non-null, print this message. */
13451};
13452
13453static int
13454arm_parse_extension (str, opt_p)
13455 char *str;
13456 int *opt_p;
13457{
13458 while (str != NULL && *str != 0)
13459 {
13460 struct arm_arch_extension_table *opt;
13461 char *ext;
13462 int optlen;
13463
13464 if (*str != '+')
b99bd4ef 13465 {
03b1477f
RE
13466 as_bad (_("invalid architectural extension"));
13467 return 0;
13468 }
b99bd4ef 13469
03b1477f
RE
13470 str++;
13471 ext = strchr (str, '+');
b99bd4ef 13472
03b1477f
RE
13473 if (ext != NULL)
13474 optlen = ext - str;
13475 else
13476 optlen = strlen (str);
b99bd4ef 13477
03b1477f
RE
13478 if (optlen == 0)
13479 {
13480 as_bad (_("missing architectural extension"));
13481 return 0;
13482 }
b99bd4ef 13483
03b1477f
RE
13484 for (opt = arm_extensions; opt->name != NULL; opt++)
13485 if (strncmp (opt->name, str, optlen) == 0)
13486 {
13487 *opt_p |= opt->value;
13488 break;
13489 }
bfae80f2 13490
03b1477f
RE
13491 if (opt->name == NULL)
13492 {
13493 as_bad (_("unknown architectural extnsion `%s'"), str);
13494 return 0;
13495 }
b99bd4ef 13496
03b1477f
RE
13497 str = ext;
13498 };
b99bd4ef 13499
03b1477f
RE
13500 return 1;
13501}
b99bd4ef 13502
03b1477f
RE
13503static int
13504arm_parse_cpu (str)
13505 char *str;
13506{
13507 struct arm_cpu_option_table *opt;
13508 char *ext = strchr (str, '+');
13509 int optlen;
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 cpu name `%s'"), str);
13519 return 0;
13520 }
b99bd4ef 13521
03b1477f
RE
13522 for (opt = arm_cpus; opt->name != NULL; opt++)
13523 if (strncmp (opt->name, str, optlen) == 0)
13524 {
13525 mcpu_cpu_opt = opt->value;
13526 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13527
03b1477f
RE
13528 if (ext != NULL)
13529 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13530
03b1477f
RE
13531 return 1;
13532 }
b99bd4ef 13533
03b1477f
RE
13534 as_bad (_("unknown cpu `%s'"), str);
13535 return 0;
13536}
b99bd4ef 13537
03b1477f
RE
13538static int
13539arm_parse_arch (str)
13540 char *str;
13541{
13542 struct arm_arch_option_table *opt;
13543 char *ext = strchr (str, '+');
13544 int optlen;
b99bd4ef 13545
03b1477f
RE
13546 if (ext != NULL)
13547 optlen = ext - str;
13548 else
13549 optlen = strlen (str);
b99bd4ef 13550
03b1477f
RE
13551 if (optlen == 0)
13552 {
13553 as_bad (_("missing architecture name `%s'"), str);
13554 return 0;
13555 }
b99bd4ef 13556
b99bd4ef 13557
03b1477f
RE
13558 for (opt = arm_archs; opt->name != NULL; opt++)
13559 if (strcmp (opt->name, str) == 0)
13560 {
13561 march_cpu_opt = opt->value;
13562 march_fpu_opt = opt->default_fpu;
b99bd4ef 13563
03b1477f
RE
13564 if (ext != NULL)
13565 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13566
03b1477f
RE
13567 return 1;
13568 }
b99bd4ef 13569
03b1477f
RE
13570 as_bad (_("unknown architecture `%s'\n"), str);
13571 return 0;
13572}
13573
13574static int
13575arm_parse_fpu (str)
13576 char *str;
13577{
13578 struct arm_fpu_option_table *opt;
b99bd4ef 13579
03b1477f
RE
13580 for (opt = arm_fpus; opt->name != NULL; opt++)
13581 if (strcmp (opt->name, str) == 0)
13582 {
13583 mfpu_opt = opt->value;
13584 return 1;
13585 }
b99bd4ef 13586
03b1477f
RE
13587 as_bad (_("unknown floating point format `%s'\n"), str);
13588 return 0;
13589}
b99bd4ef 13590
03b1477f
RE
13591struct arm_long_option_table arm_long_opts[] =
13592{
13593 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13594 arm_parse_cpu, NULL},
13595 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13596 arm_parse_arch, NULL},
13597 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13598 arm_parse_fpu, NULL},
13599 {NULL, NULL, 0, NULL}
13600};
b99bd4ef 13601
03b1477f
RE
13602int
13603md_parse_option (c, arg)
13604 int c;
13605 char * arg;
13606{
13607 struct arm_option_table *opt;
13608 struct arm_long_option_table *lopt;
b99bd4ef 13609
03b1477f
RE
13610 switch (c)
13611 {
13612#ifdef OPTION_EB
13613 case OPTION_EB:
13614 target_big_endian = 1;
b99bd4ef 13615 break;
03b1477f 13616#endif
b99bd4ef 13617
03b1477f
RE
13618#ifdef OPTION_EL
13619 case OPTION_EL:
13620 target_big_endian = 0;
b99bd4ef
NC
13621 break;
13622#endif
13623
03b1477f 13624 case 'a':
cc8a6dd0 13625 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13626 ones. */
13627 return 0;
13628
b99bd4ef 13629 default:
03b1477f
RE
13630 for (opt = arm_opts; opt->option != NULL; opt++)
13631 {
13632 if (c == opt->option[0]
13633 && ((arg == NULL && opt->option[1] == 0)
13634 || strcmp (arg, opt->option + 1) == 0))
13635 {
13636#if WARN_DEPRECATED
13637 /* If the option is deprecated, tell the user. */
13638 if (opt->deprecated != NULL)
13639 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13640 arg ? arg : "", _(opt->deprecated));
13641#endif
13642
13643 if (opt->var != NULL)
13644 *opt->var = opt->value;
13645
13646 return 1;
13647 }
13648 }
13649
13650 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13651 {
cc8a6dd0 13652 /* These options are expected to have an argument. */
03b1477f
RE
13653 if (c == lopt->option[0]
13654 && arg != NULL
cc8a6dd0 13655 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13656 strlen (lopt->option + 1)) == 0)
13657 {
13658#if WARN_DEPRECATED
13659 /* If the option is deprecated, tell the user. */
13660 if (lopt->deprecated != NULL)
13661 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13662 _(lopt->deprecated));
13663#endif
13664
13665 /* Call the sup-option parser. */
13666 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13667 }
13668 }
13669
13670 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
13671 return 0;
13672 }
13673
13674 return 1;
13675}
13676
13677void
13678md_show_usage (fp)
13679 FILE * fp;
13680{
03b1477f
RE
13681 struct arm_option_table *opt;
13682 struct arm_long_option_table *lopt;
13683
13684 fprintf (fp, _(" ARM-specific assembler options:\n"));
13685
13686 for (opt = arm_opts; opt->option != NULL; opt++)
13687 if (opt->help != NULL)
13688 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13689
13690 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13691 if (lopt->help != NULL)
13692 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13693
13694#ifdef OPTION_EB
b99bd4ef 13695 fprintf (fp, _("\
03b1477f 13696 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13697#endif
03b1477f
RE
13698
13699#ifdef OPTION_EL
b99bd4ef 13700 fprintf (fp, _("\
03b1477f 13701 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13702#endif
13703}
13704
13705/* We need to be able to fix up arbitrary expressions in some statements.
13706 This is so that we can handle symbols that are an arbitrary distance from
13707 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13708 which returns part of an address in a form which will be valid for
13709 a data instruction. We do this by pushing the expression into a symbol
13710 in the expr_section, and creating a fix for that. */
13711
13712static void
13713fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13714 fragS * frag;
13715 int where;
13716 short int size;
13717 expressionS * exp;
13718 int pc_rel;
13719 int reloc;
13720{
13721 fixS * new_fix;
13722 arm_fix_data * arm_data;
13723
13724 switch (exp->X_op)
13725 {
13726 case O_constant:
13727 case O_symbol:
13728 case O_add:
13729 case O_subtract:
13730 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13731 break;
13732
13733 default:
13734 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13735 pc_rel, reloc);
13736 break;
13737 }
13738
13739 /* Mark whether the fix is to a THUMB instruction, or an ARM
13740 instruction. */
13741 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13742 new_fix->tc_fix_data = (PTR) arm_data;
13743 arm_data->thumb_mode = thumb_mode;
13744
13745 return;
13746}
13747
13748/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13749
13750void
13751cons_fix_new_arm (frag, where, size, exp)
13752 fragS * frag;
13753 int where;
13754 int size;
13755 expressionS * exp;
13756{
13757 bfd_reloc_code_real_type type;
13758 int pcrel = 0;
13759
13760 /* Pick a reloc.
13761 FIXME: @@ Should look at CPU word size. */
13762 switch (size)
13763 {
13764 case 1:
13765 type = BFD_RELOC_8;
13766 break;
13767 case 2:
13768 type = BFD_RELOC_16;
13769 break;
13770 case 4:
13771 default:
13772 type = BFD_RELOC_32;
13773 break;
13774 case 8:
13775 type = BFD_RELOC_64;
13776 break;
13777 }
13778
13779 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13780}
13781
13782/* A good place to do this, although this was probably not intended
13783 for this kind of use. We need to dump the literal pool before
13784 references are made to a null symbol pointer. */
13785
13786void
13787arm_cleanup ()
13788{
3d0c9500 13789 literal_pool * pool;
b99bd4ef 13790
3d0c9500
NC
13791 for (pool = list_of_pools; pool; pool = pool->next)
13792 {
13793 /* Put it at the end of the relevent section. */
13794 subseg_set (pool->section, pool->sub_section);
13795 s_ltorg (0);
13796 }
b99bd4ef
NC
13797}
13798
13799void
13800arm_start_line_hook ()
13801{
13802 last_label_seen = NULL;
13803}
13804
13805void
13806arm_frob_label (sym)
13807 symbolS * sym;
13808{
13809 last_label_seen = sym;
13810
13811 ARM_SET_THUMB (sym, thumb_mode);
13812
13813#if defined OBJ_COFF || defined OBJ_ELF
13814 ARM_SET_INTERWORK (sym, support_interwork);
13815#endif
13816
13817 /* Note - do not allow local symbols (.Lxxx) to be labeled
13818 as Thumb functions. This is because these labels, whilst
13819 they exist inside Thumb code, are not the entry points for
13820 possible ARM->Thumb calls. Also, these labels can be used
13821 as part of a computed goto or switch statement. eg gcc
13822 can generate code that looks like this:
13823
13824 ldr r2, [pc, .Laaa]
13825 lsl r3, r3, #2
13826 ldr r2, [r3, r2]
13827 mov pc, r2
cc8a6dd0 13828
b99bd4ef
NC
13829 .Lbbb: .word .Lxxx
13830 .Lccc: .word .Lyyy
13831 ..etc...
13832 .Laaa: .word Lbbb
13833
13834 The first instruction loads the address of the jump table.
13835 The second instruction converts a table index into a byte offset.
13836 The third instruction gets the jump address out of the table.
13837 The fourth instruction performs the jump.
cc8a6dd0 13838
b99bd4ef
NC
13839 If the address stored at .Laaa is that of a symbol which has the
13840 Thumb_Func bit set, then the linker will arrange for this address
13841 to have the bottom bit set, which in turn would mean that the
13842 address computation performed by the third instruction would end
13843 up with the bottom bit set. Since the ARM is capable of unaligned
13844 word loads, the instruction would then load the incorrect address
13845 out of the jump table, and chaos would ensue. */
13846 if (label_is_thumb_function_name
13847 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13848 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13849 {
13850 /* When the address of a Thumb function is taken the bottom
13851 bit of that address should be set. This will allow
13852 interworking between Arm and Thumb functions to work
13853 correctly. */
13854
13855 THUMB_SET_FUNC (sym, 1);
13856
b34976b6 13857 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13858 }
13859}
13860
13861/* Adjust the symbol table. This marks Thumb symbols as distinct from
13862 ARM ones. */
13863
13864void
13865arm_adjust_symtab ()
13866{
13867#ifdef OBJ_COFF
13868 symbolS * sym;
13869
13870 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13871 {
13872 if (ARM_IS_THUMB (sym))
13873 {
13874 if (THUMB_IS_FUNC (sym))
13875 {
13876 /* Mark the symbol as a Thumb function. */
13877 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13878 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13879 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13880
13881 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13882 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13883 else
13884 as_bad (_("%s: unexpected function type: %d"),
13885 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13886 }
cc8a6dd0 13887 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13888 {
13889 case C_EXT:
13890 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13891 break;
13892 case C_STAT:
13893 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13894 break;
13895 case C_LABEL:
13896 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13897 break;
13898 default:
13899 /* Do nothing. */
13900 break;
13901 }
13902 }
13903
13904 if (ARM_IS_INTERWORK (sym))
13905 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13906 }
13907#endif
13908#ifdef OBJ_ELF
13909 symbolS * sym;
13910 char bind;
13911
13912 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13913 {
13914 if (ARM_IS_THUMB (sym))
13915 {
13916 elf_symbol_type * elf_sym;
13917
13918 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13919 bind = ELF_ST_BIND (elf_sym);
13920
13921 /* If it's a .thumb_func, declare it as so,
13922 otherwise tag label as .code 16. */
13923 if (THUMB_IS_FUNC (sym))
13924 elf_sym->internal_elf_sym.st_info =
13925 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13926 else
13927 elf_sym->internal_elf_sym.st_info =
13928 ELF_ST_INFO (bind, STT_ARM_16BIT);
13929 }
13930 }
13931#endif
13932}
13933
13934int
13935arm_data_in_code ()
13936{
13937 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13938 {
13939 *input_line_pointer = '/';
13940 input_line_pointer += 5;
13941 *input_line_pointer = 0;
13942 return 1;
13943 }
13944
13945 return 0;
13946}
13947
13948char *
13949arm_canonicalize_symbol_name (name)
13950 char * name;
13951{
13952 int len;
13953
13954 if (thumb_mode && (len = strlen (name)) > 5
13955 && streq (name + len - 5, "/data"))
13956 *(name + len - 5) = 0;
13957
13958 return name;
13959}
13960
bfc866a6 13961#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13962void
b99bd4ef
NC
13963arm_validate_fix (fixP)
13964 fixS * fixP;
13965{
13966 /* If the destination of the branch is a defined symbol which does not have
13967 the THUMB_FUNC attribute, then we must be calling a function which has
13968 the (interfacearm) attribute. We look for the Thumb entry point to that
13969 function and change the branch to refer to that function instead. */
13970 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13971 && fixP->fx_addsy != NULL
13972 && S_IS_DEFINED (fixP->fx_addsy)
13973 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13974 {
13975 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13976 }
b99bd4ef 13977}
bfc866a6 13978#endif
b99bd4ef 13979
114424c6
AM
13980int
13981arm_force_relocation (fixp)
13982 struct fix * fixp;
13983{
13984#if defined (OBJ_COFF) && defined (TE_PE)
13985 if (fixp->fx_r_type == BFD_RELOC_RVA)
13986 return 1;
13987#endif
13988#ifdef OBJ_ELF
ae6063d4 13989 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13990 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13991 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13992 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13993 return 1;
13994#endif
13995
13996 /* Resolve these relocations even if the symbol is extern or weak. */
13997 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13998 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13999 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14000 return 0;
14001
ae6063d4 14002 return generic_force_reloc (fixp);
114424c6
AM
14003}
14004
b99bd4ef
NC
14005#ifdef OBJ_COFF
14006/* This is a little hack to help the gas/arm/adrl.s test. It prevents
14007 local labels from being added to the output symbol table when they
14008 are used with the ADRL pseudo op. The ADRL relocation should always
14009 be resolved before the binbary is emitted, so it is safe to say that
14010 it is adjustable. */
14011
b34976b6 14012bfd_boolean
b99bd4ef
NC
14013arm_fix_adjustable (fixP)
14014 fixS * fixP;
14015{
14016 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14017 return 1;
14018 return 0;
14019}
14020#endif
114424c6 14021
b99bd4ef
NC
14022#ifdef OBJ_ELF
14023/* Relocations against Thumb function names must be left unadjusted,
14024 so that the linker can use this information to correctly set the
14025 bottom bit of their addresses. The MIPS version of this function
14026 also prevents relocations that are mips-16 specific, but I do not
14027 know why it does this.
14028
14029 FIXME:
14030 There is one other problem that ought to be addressed here, but
14031 which currently is not: Taking the address of a label (rather
14032 than a function) and then later jumping to that address. Such
14033 addresses also ought to have their bottom bit set (assuming that
14034 they reside in Thumb code), but at the moment they will not. */
14035
b34976b6 14036bfd_boolean
b99bd4ef
NC
14037arm_fix_adjustable (fixP)
14038 fixS * fixP;
14039{
14040 if (fixP->fx_addsy == NULL)
14041 return 1;
14042
b99bd4ef
NC
14043 if (THUMB_IS_FUNC (fixP->fx_addsy)
14044 && fixP->fx_subsy == NULL)
14045 return 0;
14046
14047 /* We need the symbol name for the VTABLE entries. */
14048 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14049 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14050 return 0;
14051
a161fe53
AM
14052 /* Don't allow symbols to be discarded on GOT related relocs. */
14053 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14054 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14055 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14056 return 0;
14057
b99bd4ef
NC
14058 return 1;
14059}
14060
14061const char *
14062elf32_arm_target_format ()
14063{
14064 if (target_big_endian)
14065 {
14066 if (target_oabi)
14067 return "elf32-bigarm-oabi";
14068 else
14069 return "elf32-bigarm";
14070 }
14071 else
14072 {
14073 if (target_oabi)
14074 return "elf32-littlearm-oabi";
14075 else
14076 return "elf32-littlearm";
14077 }
14078}
14079
14080void
14081armelf_frob_symbol (symp, puntp)
14082 symbolS * symp;
14083 int * puntp;
14084{
14085 elf_frob_symbol (symp, puntp);
14086}
14087
b99bd4ef
NC
14088static bfd_reloc_code_real_type
14089arm_parse_reloc ()
14090{
14091 char id [16];
14092 char * ip;
14093 unsigned int i;
14094 static struct
14095 {
14096 char * str;
14097 int len;
14098 bfd_reloc_code_real_type reloc;
14099 }
14100 reloc_map[] =
14101 {
14102#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14103 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14104 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14105 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14106 branch instructions generated by GCC for PLT relocs. */
14107 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14108 { NULL, 0, BFD_RELOC_UNUSED }
14109#undef MAP
14110 };
14111
14112 for (i = 0, ip = input_line_pointer;
3882b010 14113 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14114 i++, ip++)
3882b010 14115 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14116
14117 for (i = 0; reloc_map[i].str; i++)
14118 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14119 break;
14120
14121 input_line_pointer += reloc_map[i].len;
14122
14123 return reloc_map[i].reloc;
14124}
14125
14126static void
14127s_arm_elf_cons (nbytes)
14128 int nbytes;
14129{
14130 expressionS exp;
14131
14132#ifdef md_flush_pending_output
14133 md_flush_pending_output ();
14134#endif
14135
14136 if (is_it_end_of_statement ())
14137 {
14138 demand_empty_rest_of_line ();
14139 return;
14140 }
14141
14142#ifdef md_cons_align
14143 md_cons_align (nbytes);
14144#endif
14145
6057a28f 14146 mapping_state (MAP_DATA);
b99bd4ef
NC
14147 do
14148 {
14149 bfd_reloc_code_real_type reloc;
14150
14151 expression (& exp);
14152
14153 if (exp.X_op == O_symbol
14154 && * input_line_pointer == '('
14155 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14156 {
14157 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14158 int size = bfd_get_reloc_size (howto);
14159
14160 if (size > nbytes)
14161 as_bad ("%s relocations do not fit in %d bytes",
14162 howto->name, nbytes);
14163 else
14164 {
14165 register char *p = frag_more ((int) nbytes);
14166 int offset = nbytes - size;
14167
14168 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14169 &exp, 0, reloc);
14170 }
14171 }
14172 else
14173 emit_expr (&exp, (unsigned int) nbytes);
14174 }
14175 while (*input_line_pointer++ == ',');
14176
14177 /* Put terminator back into stream. */
14178 input_line_pointer --;
14179 demand_empty_rest_of_line ();
14180}
14181
14182#endif /* OBJ_ELF */
14183
14184/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14185 of an rs_align_code fragment. */
14186
14187void
14188arm_handle_align (fragP)
14189 fragS *fragP;
14190{
14191 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14192 static char const thumb_noop[2] = { 0xc0, 0x46 };
14193 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14194 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14195
14196 int bytes, fix, noop_size;
14197 char * p;
14198 const char * noop;
cc8a6dd0 14199
b99bd4ef
NC
14200 if (fragP->fr_type != rs_align_code)
14201 return;
14202
14203 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14204 p = fragP->fr_literal + fragP->fr_fix;
14205 fix = 0;
cc8a6dd0 14206
b99bd4ef
NC
14207 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14208 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14209
b99bd4ef
NC
14210 if (fragP->tc_frag_data)
14211 {
14212 if (target_big_endian)
14213 noop = thumb_bigend_noop;
14214 else
14215 noop = thumb_noop;
14216 noop_size = sizeof (thumb_noop);
14217 }
14218 else
14219 {
14220 if (target_big_endian)
14221 noop = arm_bigend_noop;
14222 else
14223 noop = arm_noop;
14224 noop_size = sizeof (arm_noop);
14225 }
cc8a6dd0 14226
b99bd4ef
NC
14227 if (bytes & (noop_size - 1))
14228 {
14229 fix = bytes & (noop_size - 1);
14230 memset (p, 0, fix);
14231 p += fix;
14232 bytes -= fix;
14233 }
14234
14235 while (bytes >= noop_size)
14236 {
14237 memcpy (p, noop, noop_size);
14238 p += noop_size;
14239 bytes -= noop_size;
14240 fix += noop_size;
14241 }
cc8a6dd0 14242
b99bd4ef
NC
14243 fragP->fr_fix += fix;
14244 fragP->fr_var = noop_size;
14245}
14246
14247/* Called from md_do_align. Used to create an alignment
14248 frag in a code section. */
14249
14250void
14251arm_frag_align_code (n, max)
14252 int n;
14253 int max;
14254{
14255 char * p;
14256
2d2255b5 14257 /* We assume that there will never be a requirement
b99bd4ef
NC
14258 to support alignments greater than 32 bytes. */
14259 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14260 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14261
b99bd4ef
NC
14262 p = frag_var (rs_align_code,
14263 MAX_MEM_FOR_RS_ALIGN_CODE,
14264 1,
14265 (relax_substateT) max,
14266 (symbolS *) NULL,
14267 (offsetT) n,
14268 (char *) NULL);
14269 *p = 0;
14270
14271}
14272
14273/* Perform target specific initialisation of a frag. */
14274
14275void
14276arm_init_frag (fragP)
14277 fragS *fragP;
14278{
14279 /* Record whether this frag is in an ARM or a THUMB area. */
14280 fragP->tc_frag_data = thumb_mode;
14281}
This page took 0.804746 seconds and 4 git commands to generate.