Remove redundant returns in void functions.
[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 4033 end_of_line (str);
b99bd4ef
NC
4034}
4035
4036static void
f2b7cb0a 4037do_mrs (str)
b99bd4ef 4038 char *str;
b99bd4ef
NC
4039{
4040 int skip = 0;
4041
4042 /* Only one syntax. */
4043 skip_whitespace (str);
4044
4045 if (reg_required_here (&str, 12) == FAIL)
4046 {
4047 inst.error = BAD_ARGS;
4048 return;
4049 }
4050
4051 if (skip_past_comma (&str) == FAIL)
4052 {
4053 inst.error = _("comma expected after register name");
4054 return;
4055 }
4056
4057 skip_whitespace (str);
4058
4059 if ( strcmp (str, "CPSR") == 0
4060 || strcmp (str, "SPSR") == 0
2d2255b5 4061 /* Lower case versions for backwards compatibility. */
b99bd4ef
NC
4062 || strcmp (str, "cpsr") == 0
4063 || strcmp (str, "spsr") == 0)
4064 skip = 4;
4065
2d2255b5 4066 /* This is for backwards compatibility with older toolchains. */
b99bd4ef
NC
4067 else if ( strcmp (str, "cpsr_all") == 0
4068 || strcmp (str, "spsr_all") == 0)
4069 skip = 8;
4070 else
4071 {
f03698e6 4072 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
4073 return;
4074 }
4075
4076 if (* str == 's' || * str == 'S')
4077 inst.instruction |= SPSR_BIT;
4078 str += skip;
4079
b99bd4ef
NC
4080 end_of_line (str);
4081}
4082
4083/* Two possible forms:
4084 "{C|S}PSR_<field>, Rm",
4085 "{C|S}PSR_f, #expression". */
4086
4087static void
f2b7cb0a 4088do_msr (str)
b99bd4ef 4089 char * str;
b99bd4ef
NC
4090{
4091 skip_whitespace (str);
4092
4093 if (psr_required_here (& str) == FAIL)
4094 return;
4095
4096 if (skip_past_comma (& str) == FAIL)
4097 {
4098 inst.error = _("comma missing after psr flags");
4099 return;
4100 }
4101
4102 skip_whitespace (str);
4103
4104 if (reg_required_here (& str, 0) != FAIL)
4105 {
4106 inst.error = NULL;
b99bd4ef
NC
4107 end_of_line (str);
4108 return;
4109 }
4110
4111 if (! is_immediate_prefix (* str))
4112 {
4113 inst.error =
4114 _("only a register or immediate value can follow a psr flag");
4115 return;
4116 }
4117
4118 str ++;
4119 inst.error = NULL;
4120
4121 if (my_get_expression (& inst.reloc.exp, & str))
4122 {
4123 inst.error =
4124 _("only a register or immediate value can follow a psr flag");
4125 return;
4126 }
4127
4128#if 0 /* The first edition of the ARM architecture manual stated that
4129 writing anything other than the flags with an immediate operation
4130 had UNPREDICTABLE effects. This constraint was removed in the
4131 second edition of the specification. */
4132 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4133 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4134 {
4135 inst.error = _("immediate value cannot be used to set this field");
4136 return;
4137 }
4138#endif
4139
f2b7cb0a 4140 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
4141
4142 if (inst.reloc.exp.X_add_symbol)
4143 {
4144 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4145 inst.reloc.pc_rel = 0;
4146 }
4147 else
4148 {
4149 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4150
4151 if (value == (unsigned) FAIL)
4152 {
f03698e6 4153 inst.error = _("invalid constant");
b99bd4ef
NC
4154 return;
4155 }
4156
4157 inst.instruction |= value;
4158 }
4159
4160 inst.error = NULL;
b99bd4ef
NC
4161 end_of_line (str);
4162}
4163
4164/* Long Multiply Parser
4165 UMULL RdLo, RdHi, Rm, Rs
4166 SMULL RdLo, RdHi, Rm, Rs
4167 UMLAL RdLo, RdHi, Rm, Rs
4168 SMLAL RdLo, RdHi, Rm, Rs. */
4169
4170static void
f2b7cb0a 4171do_mull (str)
b99bd4ef 4172 char * str;
b99bd4ef
NC
4173{
4174 int rdlo, rdhi, rm, rs;
4175
4176 /* Only one format "rdlo, rdhi, rm, rs". */
4177 skip_whitespace (str);
4178
4179 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4180 {
4181 inst.error = BAD_ARGS;
4182 return;
4183 }
4184
4185 if (skip_past_comma (&str) == FAIL
4186 || (rdhi = reg_required_here (&str, 16)) == FAIL)
4187 {
4188 inst.error = BAD_ARGS;
4189 return;
4190 }
4191
4192 if (skip_past_comma (&str) == FAIL
4193 || (rm = reg_required_here (&str, 0)) == FAIL)
4194 {
4195 inst.error = BAD_ARGS;
4196 return;
4197 }
4198
4199 /* rdhi, rdlo and rm must all be different. */
4200 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4201 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4202
4203 if (skip_past_comma (&str) == FAIL
4204 || (rs = reg_required_here (&str, 8)) == FAIL)
4205 {
4206 inst.error = BAD_ARGS;
4207 return;
4208 }
4209
4210 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4211 {
4212 inst.error = BAD_PC;
4213 return;
4214 }
4215
b99bd4ef 4216 end_of_line (str);
b99bd4ef
NC
4217}
4218
4219static void
f2b7cb0a 4220do_mul (str)
b99bd4ef 4221 char * str;
b99bd4ef
NC
4222{
4223 int rd, rm;
4224
4225 /* Only one format "rd, rm, rs". */
4226 skip_whitespace (str);
4227
4228 if ((rd = reg_required_here (&str, 16)) == FAIL)
4229 {
4230 inst.error = BAD_ARGS;
4231 return;
4232 }
4233
4234 if (rd == REG_PC)
4235 {
4236 inst.error = BAD_PC;
4237 return;
4238 }
4239
4240 if (skip_past_comma (&str) == FAIL
4241 || (rm = reg_required_here (&str, 0)) == FAIL)
4242 {
4243 inst.error = BAD_ARGS;
4244 return;
4245 }
4246
4247 if (rm == REG_PC)
4248 {
4249 inst.error = BAD_PC;
4250 return;
4251 }
4252
4253 if (rm == rd)
4254 as_tsktsk (_("rd and rm should be different in mul"));
4255
4256 if (skip_past_comma (&str) == FAIL
4257 || (rm = reg_required_here (&str, 8)) == FAIL)
4258 {
4259 inst.error = BAD_ARGS;
4260 return;
4261 }
4262
4263 if (rm == REG_PC)
4264 {
4265 inst.error = BAD_PC;
4266 return;
4267 }
4268
b99bd4ef 4269 end_of_line (str);
b99bd4ef
NC
4270}
4271
4272static void
f2b7cb0a 4273do_mla (str)
b99bd4ef 4274 char * str;
b99bd4ef
NC
4275{
4276 int rd, rm;
4277
4278 /* Only one format "rd, rm, rs, rn". */
4279 skip_whitespace (str);
4280
4281 if ((rd = reg_required_here (&str, 16)) == FAIL)
4282 {
4283 inst.error = BAD_ARGS;
4284 return;
4285 }
4286
4287 if (rd == REG_PC)
4288 {
4289 inst.error = BAD_PC;
4290 return;
4291 }
4292
4293 if (skip_past_comma (&str) == FAIL
4294 || (rm = reg_required_here (&str, 0)) == FAIL)
4295 {
4296 inst.error = BAD_ARGS;
4297 return;
4298 }
4299
4300 if (rm == REG_PC)
4301 {
4302 inst.error = BAD_PC;
4303 return;
4304 }
4305
4306 if (rm == rd)
4307 as_tsktsk (_("rd and rm should be different in mla"));
4308
4309 if (skip_past_comma (&str) == FAIL
4310 || (rd = reg_required_here (&str, 8)) == FAIL
4311 || skip_past_comma (&str) == FAIL
4312 || (rm = reg_required_here (&str, 12)) == FAIL)
4313 {
4314 inst.error = BAD_ARGS;
4315 return;
4316 }
4317
4318 if (rd == REG_PC || rm == REG_PC)
4319 {
4320 inst.error = BAD_PC;
4321 return;
4322 }
4323
b99bd4ef 4324 end_of_line (str);
b99bd4ef
NC
4325}
4326
4327/* Expects *str -> the characters "acc0", possibly with leading blanks.
4328 Advances *str to the next non-alphanumeric.
4329 Returns 0, or else FAIL (in which case sets inst.error).
4330
4331 (In a future XScale, there may be accumulators other than zero.
4332 At that time this routine and its callers can be upgraded to suit.) */
4333
4334static int
4335accum0_required_here (str)
4336 char ** str;
4337{
4338 static char buff [128]; /* Note the address is taken. Hence, static. */
4339 char * p = * str;
4340 char c;
4341 int result = 0; /* The accum number. */
4342
4343 skip_whitespace (p);
4344
4345 *str = p; /* Advance caller's string pointer too. */
4346 c = *p++;
3882b010 4347 while (ISALNUM (c))
b99bd4ef
NC
4348 c = *p++;
4349
4350 *--p = 0; /* Aap nul into input buffer at non-alnum. */
4351
4352 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4353 {
4354 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4355 inst.error = buff;
4356 result = FAIL;
4357 }
4358
4359 *p = c; /* Unzap. */
4360 *str = p; /* Caller's string pointer to after match. */
4361 return result;
4362}
4363
4364/* Expects **str -> after a comma. May be leading blanks.
4365 Advances *str, recognizing a load mode, and setting inst.instruction.
4366 Returns rn, or else FAIL (in which case may set inst.error
4367 and not advance str)
4368
4369 Note: doesn't know Rd, so no err checks that require such knowledge. */
4370
4371static int
4372ld_mode_required_here (string)
4373 char ** string;
4374{
4375 char * str = * string;
4376 int rn;
4377 int pre_inc = 0;
4378
4379 skip_whitespace (str);
4380
4381 if (* str == '[')
4382 {
4383 str++;
4384
4385 skip_whitespace (str);
4386
4387 if ((rn = reg_required_here (& str, 16)) == FAIL)
4388 return FAIL;
4389
4390 skip_whitespace (str);
4391
4392 if (* str == ']')
4393 {
4394 str ++;
4395
4396 if (skip_past_comma (& str) == SUCCESS)
4397 {
4398 /* [Rn],... (post inc) */
90e4755a 4399 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4400 return FAIL;
4401 }
4402 else /* [Rn] */
4403 {
cc8a6dd0 4404 skip_whitespace (str);
b99bd4ef 4405
cc8a6dd0
KH
4406 if (* str == '!')
4407 {
4408 str ++;
4409 inst.instruction |= WRITE_BACK;
4410 }
b99bd4ef
NC
4411
4412 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4413 pre_inc = 1;
4414 }
4415 }
4416 else /* [Rn,...] */
4417 {
4418 if (skip_past_comma (& str) == FAIL)
4419 {
4420 inst.error = _("pre-indexed expression expected");
4421 return FAIL;
4422 }
4423
4424 pre_inc = 1;
4425
90e4755a 4426 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
4427 return FAIL;
4428
4429 skip_whitespace (str);
4430
4431 if (* str ++ != ']')
4432 {
4433 inst.error = _("missing ]");
4434 return FAIL;
4435 }
4436
4437 skip_whitespace (str);
4438
4439 if (* str == '!')
4440 {
4441 str ++;
4442 inst.instruction |= WRITE_BACK;
4443 }
4444 }
4445 }
4446 else if (* str == '=') /* ldr's "r,=label" syntax */
4447 /* We should never reach here, because <text> = <expression> is
4448 caught gas/read.c read_a_source_file() as a .set operation. */
4449 return FAIL;
4450 else /* PC +- 8 bit immediate offset. */
4451 {
4452 if (my_get_expression (& inst.reloc.exp, & str))
4453 return FAIL;
4454
4455 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
4456 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
4457 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
4458 inst.reloc.pc_rel = 1;
4459 inst.instruction |= (REG_PC << 16);
4460
4461 rn = REG_PC;
4462 pre_inc = 1;
4463 }
4464
4465 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4466 * string = str;
4467
4468 return rn;
4469}
4470
4471/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4472 SMLAxy{cond} Rd,Rm,Rs,Rn
4473 SMLAWy{cond} Rd,Rm,Rs,Rn
4474 Error if any register is R15. */
4475
4476static void
f2b7cb0a 4477do_smla (str)
b99bd4ef 4478 char * str;
b99bd4ef
NC
4479{
4480 int rd, rm, rs, rn;
4481
4482 skip_whitespace (str);
4483
4484 if ((rd = reg_required_here (& str, 16)) == FAIL
4485 || skip_past_comma (& str) == FAIL
4486 || (rm = reg_required_here (& str, 0)) == FAIL
4487 || skip_past_comma (& str) == FAIL
4488 || (rs = reg_required_here (& str, 8)) == FAIL
4489 || skip_past_comma (& str) == FAIL
4490 || (rn = reg_required_here (& str, 12)) == FAIL)
4491 inst.error = BAD_ARGS;
4492
4493 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4494 inst.error = BAD_PC;
4495
b99bd4ef
NC
4496 else
4497 end_of_line (str);
4498}
4499
4500/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4501 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4502 Error if any register is R15.
4503 Warning if Rdlo == Rdhi. */
4504
4505static void
f2b7cb0a 4506do_smlal (str)
b99bd4ef 4507 char * str;
b99bd4ef
NC
4508{
4509 int rdlo, rdhi, rm, rs;
4510
4511 skip_whitespace (str);
4512
4513 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4514 || skip_past_comma (& str) == FAIL
4515 || (rdhi = reg_required_here (& str, 16)) == FAIL
4516 || skip_past_comma (& str) == FAIL
4517 || (rm = reg_required_here (& str, 0)) == FAIL
4518 || skip_past_comma (& str) == FAIL
4519 || (rs = reg_required_here (& str, 8)) == FAIL)
4520 {
4521 inst.error = BAD_ARGS;
4522 return;
4523 }
4524
4525 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4526 {
4527 inst.error = BAD_PC;
4528 return;
4529 }
4530
4531 if (rdlo == rdhi)
4532 as_tsktsk (_("rdhi and rdlo must be different"));
4533
f2b7cb0a 4534 end_of_line (str);
b99bd4ef
NC
4535}
4536
4537/* ARM V5E (El Segundo) signed-multiply (argument parse)
4538 SMULxy{cond} Rd,Rm,Rs
4539 Error if any register is R15. */
4540
4541static void
f2b7cb0a 4542do_smul (str)
b99bd4ef 4543 char * str;
b99bd4ef
NC
4544{
4545 int rd, rm, rs;
4546
4547 skip_whitespace (str);
4548
4549 if ((rd = reg_required_here (& str, 16)) == FAIL
4550 || skip_past_comma (& str) == FAIL
4551 || (rm = reg_required_here (& str, 0)) == FAIL
4552 || skip_past_comma (& str) == FAIL
4553 || (rs = reg_required_here (& str, 8)) == FAIL)
4554 inst.error = BAD_ARGS;
4555
4556 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4557 inst.error = BAD_PC;
4558
b99bd4ef
NC
4559 else
4560 end_of_line (str);
4561}
4562
4563/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4564 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4565 Error if any register is R15. */
4566
4567static void
f2b7cb0a 4568do_qadd (str)
b99bd4ef 4569 char * str;
b99bd4ef
NC
4570{
4571 int rd, rm, rn;
4572
4573 skip_whitespace (str);
4574
4575 if ((rd = reg_required_here (& str, 12)) == FAIL
4576 || skip_past_comma (& str) == FAIL
4577 || (rm = reg_required_here (& str, 0)) == FAIL
4578 || skip_past_comma (& str) == FAIL
4579 || (rn = reg_required_here (& str, 16)) == FAIL)
4580 inst.error = BAD_ARGS;
4581
4582 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4583 inst.error = BAD_PC;
4584
b99bd4ef
NC
4585 else
4586 end_of_line (str);
4587}
4588
4589/* ARM V5E (el Segundo)
4590 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4591 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4592
4593 These are equivalent to the XScale instructions MAR and MRA,
4594 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4595
4596 Result unpredicatable if Rd or Rn is R15. */
4597
4598static void
f2b7cb0a 4599do_co_reg2c (str)
b99bd4ef 4600 char * str;
b99bd4ef
NC
4601{
4602 int rd, rn;
4603
4604 skip_whitespace (str);
4605
4606 if (co_proc_number (& str) == FAIL)
4607 {
4608 if (!inst.error)
4609 inst.error = BAD_ARGS;
4610 return;
4611 }
4612
4613 if (skip_past_comma (& str) == FAIL
4614 || cp_opc_expr (& str, 4, 4) == FAIL)
4615 {
4616 if (!inst.error)
4617 inst.error = BAD_ARGS;
4618 return;
4619 }
4620
4621 if (skip_past_comma (& str) == FAIL
4622 || (rd = reg_required_here (& str, 12)) == FAIL)
4623 {
4624 if (!inst.error)
4625 inst.error = BAD_ARGS;
4626 return;
4627 }
4628
4629 if (skip_past_comma (& str) == FAIL
4630 || (rn = reg_required_here (& str, 16)) == FAIL)
4631 {
4632 if (!inst.error)
4633 inst.error = BAD_ARGS;
4634 return;
4635 }
4636
09d92015
MM
4637 /* Unpredictable result if rd or rn is R15. */
4638 if (rd == REG_PC || rn == REG_PC)
4639 as_tsktsk
4640 (_("Warning: instruction unpredictable when using r15"));
4641
4642 if (skip_past_comma (& str) == FAIL
4643 || cp_reg_required_here (& str, 0) == FAIL)
4644 {
4645 if (!inst.error)
4646 inst.error = BAD_ARGS;
4647 return;
4648 }
4649
4650 end_of_line (str);
4651}
4652
4653/* ARM V5 count-leading-zeroes instruction (argument parse)
4654 CLZ{<cond>} <Rd>, <Rm>
4655 Condition defaults to COND_ALWAYS.
4656 Error if Rd or Rm are R15. */
4657
4658static void
4659do_clz (str)
4660 char * str;
4661{
4662 int rd, rm;
4663
4664 skip_whitespace (str);
4665
4666 if (((rd = reg_required_here (& str, 12)) == FAIL)
4667 || (skip_past_comma (& str) == FAIL)
4668 || ((rm = reg_required_here (& str, 0)) == FAIL))
4669 inst.error = BAD_ARGS;
4670
4671 else if (rd == REG_PC || rm == REG_PC )
4672 inst.error = BAD_PC;
4673
4674 else
4675 end_of_line (str);
4676}
4677
4678/* ARM V5 (argument parse)
4679 LDC2{L} <coproc>, <CRd>, <addressing mode>
4680 STC2{L} <coproc>, <CRd>, <addressing mode>
4681 Instruction is not conditional, and has 0xf in the condition field.
4682 Otherwise, it's the same as LDC/STC. */
4683
4684static void
4685do_lstc2 (str)
4686 char * str;
4687{
4688 skip_whitespace (str);
4689
4690 if (co_proc_number (& str) == FAIL)
4691 {
4692 if (!inst.error)
4693 inst.error = BAD_ARGS;
4694 }
4695 else if (skip_past_comma (& str) == FAIL
4696 || cp_reg_required_here (& str, 12) == FAIL)
4697 {
4698 if (!inst.error)
4699 inst.error = BAD_ARGS;
4700 }
4701 else if (skip_past_comma (& str) == FAIL
4702 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4703 {
4704 if (! inst.error)
4705 inst.error = BAD_ARGS;
4706 }
4707 else
4708 end_of_line (str);
4709}
4710
4711/* ARM V5 (argument parse)
4712 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4713 Instruction is not conditional, and has 0xf in the condition field.
4714 Otherwise, it's the same as CDP. */
4715
4716static void
4717do_cdp2 (str)
4718 char * str;
4719{
4720 skip_whitespace (str);
4721
4722 if (co_proc_number (& str) == FAIL)
4723 {
4724 if (!inst.error)
4725 inst.error = BAD_ARGS;
4726 return;
4727 }
4728
4729 if (skip_past_comma (& str) == FAIL
4730 || cp_opc_expr (& str, 20,4) == FAIL)
4731 {
4732 if (!inst.error)
4733 inst.error = BAD_ARGS;
4734 return;
4735 }
4736
4737 if (skip_past_comma (& str) == FAIL
4738 || cp_reg_required_here (& str, 12) == FAIL)
4739 {
4740 if (!inst.error)
4741 inst.error = BAD_ARGS;
4742 return;
4743 }
4744
4745 if (skip_past_comma (& str) == FAIL
4746 || cp_reg_required_here (& str, 16) == FAIL)
4747 {
4748 if (!inst.error)
4749 inst.error = BAD_ARGS;
4750 return;
4751 }
4752
4753 if (skip_past_comma (& str) == FAIL
4754 || cp_reg_required_here (& str, 0) == FAIL)
4755 {
4756 if (!inst.error)
4757 inst.error = BAD_ARGS;
4758 return;
4759 }
4760
4761 if (skip_past_comma (& str) == SUCCESS)
4762 {
4763 if (cp_opc_expr (& str, 5, 3) == FAIL)
4764 {
4765 if (!inst.error)
4766 inst.error = BAD_ARGS;
4767 return;
4768 }
4769 }
4770
4771 end_of_line (str);
4772}
4773
4774/* ARM V5 (argument parse)
4775 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4776 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4777 Instruction is not conditional, and has 0xf in the condition field.
4778 Otherwise, it's the same as MCR/MRC. */
4779
4780static void
4781do_co_reg2 (str)
4782 char * str;
4783{
4784 skip_whitespace (str);
4785
4786 if (co_proc_number (& str) == FAIL)
4787 {
4788 if (!inst.error)
4789 inst.error = BAD_ARGS;
4790 return;
4791 }
4792
4793 if (skip_past_comma (& str) == FAIL
4794 || cp_opc_expr (& str, 21, 3) == FAIL)
4795 {
4796 if (!inst.error)
4797 inst.error = BAD_ARGS;
4798 return;
4799 }
4800
4801 if (skip_past_comma (& str) == FAIL
4802 || reg_required_here (& str, 12) == FAIL)
4803 {
4804 if (!inst.error)
4805 inst.error = BAD_ARGS;
4806 return;
4807 }
4808
4809 if (skip_past_comma (& str) == FAIL
4810 || cp_reg_required_here (& str, 16) == FAIL)
4811 {
4812 if (!inst.error)
4813 inst.error = BAD_ARGS;
4814 return;
4815 }
4816
4817 if (skip_past_comma (& str) == FAIL
4818 || cp_reg_required_here (& str, 0) == FAIL)
4819 {
4820 if (!inst.error)
4821 inst.error = BAD_ARGS;
4822 return;
4823 }
4824
4825 if (skip_past_comma (& str) == SUCCESS)
4826 {
4827 if (cp_opc_expr (& str, 5, 3) == FAIL)
4828 {
4829 if (!inst.error)
4830 inst.error = BAD_ARGS;
4831 return;
4832 }
4833 }
4834
4835 end_of_line (str);
4836}
4837
4838/* ARM v5TEJ. Jump to Jazelle code. */
4839static void
4840do_bxj (str)
4841 char * str;
4842{
4843 int reg;
4844
4845 skip_whitespace (str);
4846
4847 if ((reg = reg_required_here (&str, 0)) == FAIL)
4848 {
4849 inst.error = BAD_ARGS;
4850 return;
4851 }
4852
4853 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4854 if (reg == REG_PC)
4855 as_tsktsk (_("use of r15 in bxj is not really useful"));
4856
4857 end_of_line (str);
4858}
4859
4860/* ARM V6 umaal (argument parse). */
4861
4862static void
4863do_umaal (str)
4864 char *str;
4865{
4866
4867 int rdlo, rdhi, rm, rs;
4868
4869 skip_whitespace (str);
4870 if ((rdlo = reg_required_here (& str, 12)) == FAIL
4871 || skip_past_comma (& str) == FAIL
4872 || (rdhi = reg_required_here (& str, 16)) == FAIL
4873 || skip_past_comma (& str) == FAIL
4874 || (rm = reg_required_here (& str, 0)) == FAIL
4875 || skip_past_comma (& str) == FAIL
5533419b 4876 || (rs = reg_required_here (& str, 8)) == FAIL)
09d92015
MM
4877 {
4878 inst.error = BAD_ARGS;
4879 return;
4880 }
4881
4882 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4883 {
4884 inst.error = BAD_PC;
4885 return;
4886 }
4887
4888 end_of_line (str);
4889}
4890
4891/* ARM V6 strex (argument parse). */
4892
4893static void
4894do_strex (str)
4895 char *str;
4896{
4897 int rd, rm, rn;
4898
4899 /* Parse Rd, Rm,. */
4900 skip_whitespace (str);
4901 if ((rd = reg_required_here (& str, 12)) == FAIL
4902 || skip_past_comma (& str) == FAIL
4903 || (rm = reg_required_here (& str, 0)) == FAIL
4904 || skip_past_comma (& str) == FAIL)
4905 {
4906 inst.error = BAD_ARGS;
4907 return;
4908 }
4909 if (rd == REG_PC || rm == REG_PC)
4910 {
4911 inst.error = BAD_PC;
4912 return;
4913 }
4914 if (rd == rm)
4915 {
4916 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4917 return;
4918 }
4919
4920 /* Skip past '['. */
4921 if ((strlen (str) >= 1)
4922 && strncmp (str, "[", 1) == 0)
4923 str+=1;
4924 skip_whitespace (str);
4925
4926 /* Parse Rn. */
4927 if ((rn = reg_required_here (& str, 16)) == FAIL)
4928 {
4929 inst.error = BAD_ARGS;
4930 return;
4931 }
4932 else if (rn == REG_PC)
4933 {
4934 inst.error = BAD_PC;
4935 return;
4936 }
4937 if (rd == rn)
4938 {
4939 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4940 return;
4941 }
4942 skip_whitespace (str);
4943
4944 /* Skip past ']'. */
4945 if ((strlen (str) >= 1)
4946 && strncmp (str, "]", 1) == 0)
4947 str+=1;
4948
4949 end_of_line (str);
4950}
4951
4952/* ARM V6 ssat (argument parse). */
4953
4954static void
4955do_ssat (str)
4956 char* str;
4957{
4958 do_sat (&str, /*bias=*/-1);
4959 end_of_line (str);
4960}
4961
4962/* ARM V6 usat (argument parse). */
4963
4964static void
4965do_usat (str)
4966 char* str;
4967{
4968 do_sat (&str, /*bias=*/0);
4969 end_of_line (str);
4970}
4971
4972static void
4973do_sat (str, bias)
4974 char **str;
4975 int bias;
4976{
4977 int rd, rm;
4978 expressionS expr;
4979
4980 skip_whitespace (*str);
4981
4982 /* Parse <Rd>, field. */
4983 if ((rd = reg_required_here (str, 12)) == FAIL
4984 || skip_past_comma (str) == FAIL)
4985 {
4986 inst.error = BAD_ARGS;
4987 return;
4988 }
4989 if (rd == REG_PC)
4990 {
4991 inst.error = BAD_PC;
4992 return;
4993 }
4994
4995 /* Parse #<immed>, field. */
4996 if (is_immediate_prefix (**str))
4997 (*str)++;
4998 else
4999 {
5000 inst.error = _("immediate expression expected");
5001 return;
5002 }
5003 if (my_get_expression (&expr, str))
5004 {
5005 inst.error = _("bad expression");
5006 return;
5007 }
5008 if (expr.X_op != O_constant)
5009 {
5010 inst.error = _("constant expression expected");
5011 return;
5012 }
5013 if (expr.X_add_number + bias < 0
5014 || expr.X_add_number + bias > 31)
5015 {
5016 inst.error = _("immediate value out of range");
5017 return;
5018 }
5019 inst.instruction |= (expr.X_add_number + bias) << 16;
5020 if (skip_past_comma (str) == FAIL)
5021 {
5022 inst.error = BAD_ARGS;
5023 return;
5024 }
5025
5026 /* Parse <Rm> field. */
5027 if ((rm = reg_required_here (str, 0)) == FAIL)
5028 {
5029 inst.error = BAD_ARGS;
5030 return;
5031 }
5032 if (rm == REG_PC)
5033 {
5034 inst.error = BAD_PC;
5035 return;
5036 }
5037
5038 if (skip_past_comma (str) == SUCCESS)
5039 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5040}
5041
5042/* ARM V6 ssat16 (argument parse). */
5043
5044static void
5045do_ssat16 (str)
5046 char *str;
5047{
5048 do_sat16 (&str, /*bias=*/-1);
5049 end_of_line (str);
5050}
5051
5052static void
5053do_usat16 (str)
5054 char *str;
5055{
5056 do_sat16 (&str, /*bias=*/0);
5057 end_of_line (str);
5058}
5059
5060static void
5061do_sat16 (str, bias)
5062 char **str;
5063 int bias;
5064{
5065 int rd, rm;
5066 expressionS expr;
5067
5068 skip_whitespace (*str);
5069
5070 /* Parse the <Rd> field. */
5071 if ((rd = reg_required_here (str, 12)) == FAIL
5072 || skip_past_comma (str) == FAIL)
5073 {
5074 inst.error = BAD_ARGS;
5075 return;
5076 }
5077 if (rd == REG_PC)
5078 {
5079 inst.error = BAD_PC;
5080 return;
5081 }
5082
5083 /* Parse #<immed>, field. */
5084 if (is_immediate_prefix (**str))
5085 (*str)++;
5086 else
5087 {
5088 inst.error = _("immediate expression expected");
5089 return;
5090 }
5091 if (my_get_expression (&expr, str))
5092 {
5093 inst.error = _("bad expression");
5094 return;
5095 }
5096 if (expr.X_op != O_constant)
5097 {
5098 inst.error = _("constant expression expected");
5099 return;
5100 }
5101 if (expr.X_add_number + bias < 0
5102 || expr.X_add_number + bias > 15)
5103 {
5104 inst.error = _("immediate value out of range");
5105 return;
5106 }
5107 inst.instruction |= (expr.X_add_number + bias) << 16;
5108 if (skip_past_comma (str) == FAIL)
5109 {
5110 inst.error = BAD_ARGS;
5111 return;
5112 }
5113
5114 /* Parse <Rm> field. */
5115 if ((rm = reg_required_here (str, 0)) == FAIL)
5116 {
5117 inst.error = BAD_ARGS;
5118 return;
5119 }
5120 if (rm == REG_PC)
5121 {
5122 inst.error = BAD_PC;
5123 return;
5124 }
5125}
5126
5127/* ARM V6 srs (argument parse). */
5128
5129static void
5130do_srs (str)
5131 char* str;
5132{
5133 char *exclam;
5134 skip_whitespace (str);
5135 exclam = strchr (str, '!');
5136 if (exclam)
5137 *exclam = '\0';
5138 do_cps_mode (&str);
5139 if (exclam)
5140 *exclam = '!';
5141 if (*str == '!')
5142 {
5143 inst.instruction |= WRITE_BACK;
5144 str++;
5145 }
5146 end_of_line (str);
5147}
5148
5149/* ARM V6 SMMUL (argument parse). */
5150
5151static void
5152do_smmul (str)
5153 char* str;
5154{
5155 int rd, rm, rs;
5156
5157 skip_whitespace (str);
5158 if ((rd = reg_required_here (&str, 16)) == FAIL
5159 || skip_past_comma (&str) == FAIL
5160 || (rm = reg_required_here (&str, 0)) == FAIL
5161 || skip_past_comma (&str) == FAIL
5162 || (rs = reg_required_here (&str, 8)) == FAIL)
5163 {
5164 inst.error = BAD_ARGS;
5165 return;
5166 }
5167
5168 if (rd == REG_PC
5169 || rm == REG_PC
5170 || rs == REG_PC)
5171 {
5172 inst.error = BAD_PC;
5173 return;
5174 }
5175
5176 end_of_line (str);
5177
5178}
5179
5180/* ARM V6 SMLALD (argument parse). */
5181
5182static void
5183do_smlald (str)
5184 char* str;
5185{
5186 int rdlo, rdhi, rm, rs;
5187 skip_whitespace (str);
5188 if ((rdlo = reg_required_here (&str, 12)) == FAIL
5189 || skip_past_comma (&str) == FAIL
5190 || (rdhi = reg_required_here (&str, 16)) == FAIL
5191 || skip_past_comma (&str) == FAIL
5192 || (rm = reg_required_here (&str, 0)) == FAIL
5193 || skip_past_comma (&str) == FAIL
5194 || (rs = reg_required_here (&str, 8)) == FAIL)
5195 {
5196 inst.error = BAD_ARGS;
5197 return;
5198 }
5199
5200 if (rdlo == REG_PC
5201 || rdhi == REG_PC
5202 || rm == REG_PC
5203 || rs == REG_PC)
5204 {
5205 inst.error = BAD_PC;
5206 return;
5207 }
5208
5209 end_of_line (str);
5210}
5211
5212/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5213 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5214
5215static void
5216do_smlad (str)
5217 char *str;
5218{
5219 int rd, rm, rs, rn;
5220
5221 skip_whitespace (str);
5222 if ((rd = reg_required_here (&str, 16)) == FAIL
5223 || skip_past_comma (&str) == FAIL
5224 || (rm = reg_required_here (&str, 0)) == FAIL
5225 || skip_past_comma (&str) == FAIL
5226 || (rs = reg_required_here (&str, 8)) == FAIL
5227 || skip_past_comma (&str) == FAIL
5228 || (rn = reg_required_here (&str, 12)) == FAIL)
5229 {
5230 inst.error = BAD_ARGS;
5231 return;
5232 }
5233
5234 if (rd == REG_PC
5235 || rn == REG_PC
5236 || rs == REG_PC
5237 || rm == REG_PC)
5238 {
5239 inst.error = BAD_PC;
5240 return;
5241 }
5242
5243 end_of_line (str);
5244}
5245
5246/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5247 preserving the other bits.
5248
5249 setend <endian_specifier>, where <endian_specifier> is either
5250 BE or LE. */
5251
5252static void
5253do_setend (str)
5254 char *str;
5255{
5256 if (do_endian_specifier (str))
5257 inst.instruction |= 0x200;
5258}
5259
5260/* Returns true if the endian-specifier indicates big-endianness. */
5261
5262static int
5263do_endian_specifier (str)
5264 char *str;
5265{
5266 int big_endian = 0;
5267
5268 skip_whitespace (str);
5269 if (strlen (str) < 2)
5270 inst.error = _("missing endian specifier");
5271 else if (strncasecmp (str, "BE", 2) == 0)
5272 {
5273 str += 2;
5274 big_endian = 1;
5275 }
5276 else if (strncasecmp (str, "LE", 2) == 0)
5277 str += 2;
5278 else
5279 inst.error = _("valid endian specifiers are be or le");
5280
5281 end_of_line (str);
5282
5283 return big_endian;
5284}
5285
5286/* ARM V6 SXTH.
5287
5288 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5289 Condition defaults to COND_ALWAYS.
5290 Error if any register uses R15. */
5291
5292static void
5293do_sxth (str)
5294 char *str;
5295{
5296 int rd, rm;
5297 expressionS expr;
5298 int rotation_clear_mask = 0xfffff3ff;
5299 int rotation_eight_mask = 0x00000400;
5300 int rotation_sixteen_mask = 0x00000800;
5301 int rotation_twenty_four_mask = 0x00000c00;
5302
5303 skip_whitespace (str);
5304 if ((rd = reg_required_here (&str, 12)) == FAIL
5305 || skip_past_comma (&str) == FAIL
5306 || (rm = reg_required_here (&str, 0)) == FAIL)
5307 {
5308 inst.error = BAD_ARGS;
5309 return;
5310 }
5311
5312 else if (rd == REG_PC || rm == REG_PC)
5313 {
5314 inst.error = BAD_PC;
5315 return;
5316 }
5317
5318 /* Zero out the rotation field. */
5319 inst.instruction &= rotation_clear_mask;
5320
5321 /* Check for lack of optional rotation field. */
5322 if (skip_past_comma (&str) == FAIL)
5323 {
5324 end_of_line (str);
5325 return;
5326 }
5327
5328 /* Move past 'ROR'. */
5329 skip_whitespace (str);
5330 if (strncasecmp (str, "ROR", 3) == 0)
5331 str+=3;
5332 else
5333 {
5334 inst.error = _("missing rotation field after comma");
5335 return;
5336 }
5337
5338 /* Get the immediate constant. */
5339 skip_whitespace (str);
5340 if (is_immediate_prefix (* str))
5341 str++;
5342 else
5343 {
5344 inst.error = _("immediate expression expected");
5345 return;
5346 }
5347
5348 if (my_get_expression (&expr, &str))
5349 {
5350 inst.error = _("bad expression");
5351 return;
5352 }
5353
5354 if (expr.X_op != O_constant)
5355 {
5356 inst.error = _("constant expression expected");
5357 return;
5358 }
5359
5360 switch (expr.X_add_number)
5361 {
5362 case 0:
5363 /* Rotation field has already been zeroed. */
5364 break;
5365 case 8:
5366 inst.instruction |= rotation_eight_mask;
5367 break;
5368
5369 case 16:
5370 inst.instruction |= rotation_sixteen_mask;
5371 break;
5372
5373 case 24:
5374 inst.instruction |= rotation_twenty_four_mask;
5375 break;
5376
5377 default:
5378 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5379 break;
5380 }
5381
5382 end_of_line (str);
5383
5384}
5385
5386/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5387 extends it to 32-bits, and adds the result to a value in another
5388 register. You can specify a rotation by 0, 8, 16, or 24 bits
5389 before extracting the 16-bit value.
5390 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5391 Condition defaults to COND_ALWAYS.
5392 Error if any register uses R15. */
5393
5394static void
5395do_sxtah (str)
5396 char *str;
5397{
5398 int rd, rn, rm;
5399 expressionS expr;
5400 int rotation_clear_mask = 0xfffff3ff;
5401 int rotation_eight_mask = 0x00000400;
5402 int rotation_sixteen_mask = 0x00000800;
5403 int rotation_twenty_four_mask = 0x00000c00;
5404
5405 skip_whitespace (str);
5406 if ((rd = reg_required_here (&str, 12)) == FAIL
5407 || skip_past_comma (&str) == FAIL
5408 || (rn = reg_required_here (&str, 16)) == FAIL
5409 || skip_past_comma (&str) == FAIL
5410 || (rm = reg_required_here (&str, 0)) == FAIL)
5411 {
5412 inst.error = BAD_ARGS;
5413 return;
5414 }
5415
5416 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5417 {
5418 inst.error = BAD_PC;
5419 return;
5420 }
5421
5422 /* Zero out the rotation field. */
5423 inst.instruction &= rotation_clear_mask;
5424
5425 /* Check for lack of optional rotation field. */
5426 if (skip_past_comma (&str) == FAIL)
5427 {
5428 end_of_line (str);
5429 return;
5430 }
5431
5432 /* Move past 'ROR'. */
5433 skip_whitespace (str);
5434 if (strncasecmp (str, "ROR", 3) == 0)
5435 str+=3;
5436 else
5437 {
5438 inst.error = _("missing rotation field after comma");
5439 return;
5440 }
5441
5442 /* Get the immediate constant. */
5443 skip_whitespace (str);
5444 if (is_immediate_prefix (* str))
5445 str++;
5446 else
5447 {
5448 inst.error = _("immediate expression expected");
5449 return;
5450 }
5451
5452 if (my_get_expression (&expr, &str))
5453 {
5454 inst.error = _("bad expression");
5455 return;
5456 }
5457
5458 if (expr.X_op != O_constant)
5459 {
5460 inst.error = _("constant expression expected");
5461 return;
5462 }
5463
5464 switch (expr.X_add_number)
5465 {
5466 case 0:
5467 /* Rotation field has already been zeroed. */
5468 break;
5469
5470 case 8:
5471 inst.instruction |= rotation_eight_mask;
5472 break;
5473
5474 case 16:
5475 inst.instruction |= rotation_sixteen_mask;
5476 break;
5477
5478 case 24:
5479 inst.instruction |= rotation_twenty_four_mask;
5480 break;
5481
5482 default:
5483 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5484 break;
5485 }
5486
5487 end_of_line (str);
5488
5489}
5490
5491
5492/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5493 word at the specified address and the following word
5494 respectively.
5495 Unconditionally executed.
5496 Error if Rn is R15.
5497*/
5498
5499static void
5500do_rfe (str)
5501 char *str;
5502{
5503 int rn;
5504
5505 skip_whitespace (str);
5506
5507 if ((rn = reg_required_here (&str, 16)) == FAIL)
5508 return;
b99bd4ef 5509
09d92015 5510 if (rn == REG_PC)
b99bd4ef 5511 {
09d92015 5512 inst.error = BAD_PC;
b99bd4ef
NC
5513 return;
5514 }
5515
09d92015
MM
5516 skip_whitespace (str);
5517
5518 if (*str == '!')
5519 {
5520 inst.instruction |= WRITE_BACK;
5521 str++;
5522 }
b99bd4ef
NC
5523 end_of_line (str);
5524}
5525
09d92015
MM
5526/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5527 register (argument parse).
5528 REV{<cond>} Rd, Rm.
5529 Condition defaults to COND_ALWAYS.
5530 Error if Rd or Rm are R15. */
b99bd4ef
NC
5531
5532static void
09d92015
MM
5533do_rev (str)
5534 char* str;
b99bd4ef
NC
5535{
5536 int rd, rm;
5537
b99bd4ef
NC
5538 skip_whitespace (str);
5539
09d92015
MM
5540 if ((rd = reg_required_here (&str, 12)) == FAIL
5541 || skip_past_comma (&str) == FAIL
5542 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
5543 inst.error = BAD_ARGS;
5544
09d92015 5545 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
5546 inst.error = BAD_PC;
5547
5548 else
5549 end_of_line (str);
5550}
5551
09d92015
MM
5552/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5553 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5554 Condition defaults to COND_ALWAYS.
5555 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
5556
5557static void
09d92015
MM
5558do_qadd16 (str)
5559 char* str;
b99bd4ef 5560{
09d92015
MM
5561 int rd, rm, rn;
5562
b99bd4ef
NC
5563 skip_whitespace (str);
5564
09d92015
MM
5565 if ((rd = reg_required_here (&str, 12)) == FAIL
5566 || skip_past_comma (&str) == FAIL
5567 || (rn = reg_required_here (&str, 16)) == FAIL
5568 || skip_past_comma (&str) == FAIL
5569 || (rm = reg_required_here (&str, 0)) == FAIL)
5570 inst.error = BAD_ARGS;
5571
5572 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5573 inst.error = BAD_PC;
5574
b99bd4ef
NC
5575 else
5576 end_of_line (str);
5577}
5578
09d92015
MM
5579/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5580 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5581 Condition defaults to COND_ALWAYS.
5582 Error if Rd, Rn or Rm are R15. */
5583
5584static void
5585do_pkhbt (str)
5586 char* str;
5587{
5588 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5589}
5590
5591/* ARM V6 PKHTB (Argument Parse). */
5592
5593static void
5594do_pkhtb (str)
5595 char* str;
5596{
5597 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5598}
b99bd4ef
NC
5599
5600static void
09d92015
MM
5601do_pkh_core (str, shift)
5602 char* str;
5603 int shift;
b99bd4ef 5604{
09d92015 5605 int rd, rn, rm;
b99bd4ef 5606
09d92015
MM
5607 skip_whitespace (str);
5608 if (((rd = reg_required_here (&str, 12)) == FAIL)
5609 || (skip_past_comma (&str) == FAIL)
5610 || ((rn = reg_required_here (&str, 16)) == FAIL)
5611 || (skip_past_comma (&str) == FAIL)
5612 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 5613 {
09d92015 5614 inst.error = BAD_ARGS;
b99bd4ef
NC
5615 return;
5616 }
5617
09d92015 5618 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 5619 {
09d92015 5620 inst.error = BAD_PC;
b99bd4ef
NC
5621 return;
5622 }
5623
09d92015
MM
5624 /* Check for optional shift immediate constant. */
5625 if (skip_past_comma (&str) == FAIL)
b99bd4ef 5626 {
09d92015
MM
5627 if (shift == SHIFT_ASR_IMMEDIATE)
5628 {
5629 /* If the shift specifier is ommited, turn the instruction
5630 into pkhbt rd, rm, rn. First, switch the instruction
5631 code, and clear the rn and rm fields. */
5632 inst.instruction &= 0xfff0f010;
5633 /* Now, re-encode the registers. */
5634 inst.instruction |= (rm << 16) | rn;
5635 }
b99bd4ef
NC
5636 return;
5637 }
5638
09d92015
MM
5639 decode_shift (&str, shift);
5640}
5641
5642/* ARM V6 Load Register Exclusive instruction (argument parse).
5643 LDREX{<cond>} <Rd, [<Rn>]
5644 Condition defaults to COND_ALWAYS.
5645 Error if Rd or Rn are R15.
5646 See ARMARMv6 A4.1.27: LDREX. */
5647
5648
5649static void
5650do_ldrex (str)
5651 char * str;
5652{
5653 int rd, rn;
5654
5655 skip_whitespace (str);
5656
5657 /* Parse Rd. */
5658 if (((rd = reg_required_here (&str, 12)) == FAIL)
5659 || (skip_past_comma (&str) == FAIL))
b99bd4ef 5660 {
09d92015 5661 inst.error = BAD_ARGS;
b99bd4ef
NC
5662 return;
5663 }
09d92015 5664 else if (rd == REG_PC)
b99bd4ef 5665 {
09d92015 5666 inst.error = BAD_PC;
b99bd4ef
NC
5667 return;
5668 }
09d92015 5669 skip_whitespace (str);
b99bd4ef 5670
09d92015
MM
5671 /* Skip past '['. */
5672 if ((strlen (str) >= 1)
5673 &&strncmp (str, "[", 1) == 0)
5674 str+=1;
5675 skip_whitespace (str);
5676
5677 /* Parse Rn. */
5678 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 5679 {
09d92015
MM
5680 inst.error = BAD_ARGS;
5681 return;
b99bd4ef 5682 }
09d92015
MM
5683 else if (rn == REG_PC)
5684 {
5685 inst.error = BAD_PC;
5686 return;
5687 }
5688 skip_whitespace (str);
b99bd4ef 5689
09d92015
MM
5690 /* Skip past ']'. */
5691 if ((strlen (str) >= 1)
5692 && strncmp (str, "]", 1) == 0)
5693 str+=1;
5694
b99bd4ef
NC
5695 end_of_line (str);
5696}
5697
09d92015
MM
5698/* ARM V6 change processor state instruction (argument parse)
5699 CPS, CPSIE, CSPID . */
b99bd4ef
NC
5700
5701static void
09d92015
MM
5702do_cps (str)
5703 char * str;
b99bd4ef 5704{
09d92015
MM
5705 do_cps_mode (&str);
5706 end_of_line (str);
5707}
b99bd4ef 5708
09d92015
MM
5709static void
5710do_cpsi (str)
5711 char * str;
5712{
5713 do_cps_flags (&str, /*thumb_p=*/0);
b99bd4ef 5714
09d92015 5715 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5716 {
09d92015
MM
5717 skip_whitespace (str);
5718 do_cps_mode (&str);
b99bd4ef 5719 }
09d92015
MM
5720 end_of_line (str);
5721}
b99bd4ef 5722
09d92015
MM
5723static void
5724do_cps_mode (str)
5725 char **str;
5726{
5727 expressionS expr;
5728
5729 skip_whitespace (*str);
5730
5731 if (! is_immediate_prefix (**str))
b99bd4ef 5732 {
09d92015 5733 inst.error = _("immediate expression expected");
b99bd4ef
NC
5734 return;
5735 }
5736
09d92015
MM
5737 (*str)++; /* Strip off the immediate signifier. */
5738 if (my_get_expression (&expr, str))
b99bd4ef 5739 {
09d92015 5740 inst.error = _("bad expression");
b99bd4ef
NC
5741 return;
5742 }
5743
09d92015 5744 if (expr.X_op != O_constant)
b99bd4ef 5745 {
09d92015 5746 inst.error = _("constant expression expected");
b99bd4ef
NC
5747 return;
5748 }
09d92015
MM
5749
5750 /* The mode is a 5 bit field. Valid values are 0-31. */
5751 if (((unsigned) expr.X_add_number) > 31
5752 || (inst.reloc.exp.X_add_number) < 0)
b99bd4ef 5753 {
09d92015
MM
5754 inst.error = _("invalid constant");
5755 return;
b99bd4ef 5756 }
09d92015
MM
5757
5758 inst.instruction |= expr.X_add_number;
b99bd4ef
NC
5759}
5760
ea6ef066 5761static void
09d92015
MM
5762do_cps_flags (str, thumb_p)
5763 char **str;
5764 int thumb_p;
ea6ef066 5765{
09d92015
MM
5766 struct cps_flag {
5767 char character;
5768 unsigned long arm_value;
5769 unsigned long thumb_value;
5770 };
5771 static struct cps_flag flag_table[] = {
5772 {'a', 0x100, 0x4 },
5773 {'i', 0x080, 0x2 },
5774 {'f', 0x040, 0x1 }
5775 };
ea6ef066 5776
09d92015 5777 int saw_a_flag = 0;
ea6ef066 5778
09d92015
MM
5779 skip_whitespace (*str);
5780
5781 /* Get the a, f and i flags. */
5782 while (**str && **str != ',')
ea6ef066 5783 {
09d92015
MM
5784 struct cps_flag *p;
5785 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5786 for (p = flag_table; p < q; ++p)
5787 if (strncasecmp (*str, &p->character, 1) == 0)
5788 {
5789 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5790 saw_a_flag = 1;
5791 break;
5792 }
5793 if (p == q)
5794 {
5795 inst.error = _("unrecognized flag");
5796 return;
5797 }
5798 (*str)++;
ea6ef066 5799 }
09d92015
MM
5800 if (!saw_a_flag)
5801 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
ea6ef066
RE
5802}
5803
b99bd4ef
NC
5804/* THUMB V5 breakpoint instruction (argument parse)
5805 BKPT <immed_8>. */
5806
5807static void
5808do_t_bkpt (str)
5809 char * str;
5810{
5811 expressionS expr;
5812 unsigned long number;
5813
5814 skip_whitespace (str);
5815
5816 /* Allow optional leading '#'. */
5817 if (is_immediate_prefix (*str))
5818 str ++;
5819
5820 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
5821 if (my_get_expression (& expr, & str)
5822 || (expr.X_op != O_constant
5823 /* As a convenience we allow 'bkpt' without an operand. */
5824 && expr.X_op != O_absent))
b99bd4ef 5825 {
143c8e19 5826 inst.error = _("bad expression");
b99bd4ef
NC
5827 return;
5828 }
5829
5830 number = expr.X_add_number;
5831
5832 /* Check it fits an 8 bit unsigned. */
5833 if (number != (number & 0xff))
5834 {
5835 inst.error = _("immediate value out of range");
5836 return;
5837 }
5838
5839 inst.instruction |= number;
5840
5841 end_of_line (str);
5842}
5843
5844/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5845 Expects inst.instruction is set for BLX(1).
5846 Note: this is cloned from do_branch, and the reloc changed to be a
5847 new one that can cope with setting one extra bit (the H bit). */
5848
5849static void
f2b7cb0a 5850do_branch25 (str)
b99bd4ef 5851 char * str;
b99bd4ef
NC
5852{
5853 if (my_get_expression (& inst.reloc.exp, & str))
5854 return;
5855
5856#ifdef OBJ_ELF
5857 {
5858 char * save_in;
5859
5860 /* ScottB: February 5, 1998 */
5861 /* Check to see of PLT32 reloc required for the instruction. */
5862
5863 /* arm_parse_reloc() works on input_line_pointer.
5864 We actually want to parse the operands to the branch instruction
5865 passed in 'str'. Save the input pointer and restore it later. */
5866 save_in = input_line_pointer;
5867 input_line_pointer = str;
5868
5869 if (inst.reloc.exp.X_op == O_symbol
5870 && *str == '('
5871 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5872 {
5873 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5874 inst.reloc.pc_rel = 0;
5875 /* Modify str to point to after parsed operands, otherwise
5876 end_of_line() will complain about the (PLT) left in str. */
5877 str = input_line_pointer;
5878 }
5879 else
5880 {
5881 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5882 inst.reloc.pc_rel = 1;
5883 }
5884
5885 input_line_pointer = save_in;
5886 }
5887#else
5888 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
5889 inst.reloc.pc_rel = 1;
5890#endif /* OBJ_ELF */
5891
5892 end_of_line (str);
5893}
5894
5895/* ARM V5 branch-link-exchange instruction (argument parse)
5896 BLX <target_addr> ie BLX(1)
5897 BLX{<condition>} <Rm> ie BLX(2)
5898 Unfortunately, there are two different opcodes for this mnemonic.
5899 So, the insns[].value is not used, and the code here zaps values
5900 into inst.instruction.
5901 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5902
5903static void
f2b7cb0a 5904do_blx (str)
b99bd4ef 5905 char * str;
b99bd4ef
NC
5906{
5907 char * mystr = str;
5908 int rm;
5909
b99bd4ef
NC
5910 skip_whitespace (mystr);
5911 rm = reg_required_here (& mystr, 0);
5912
5913 /* The above may set inst.error. Ignore his opinion. */
5914 inst.error = 0;
5915
5916 if (rm != FAIL)
5917 {
5918 /* Arg is a register.
5919 Use the condition code our caller put in inst.instruction.
5920 Pass ourselves off as a BX with a funny opcode. */
5921 inst.instruction |= 0x012fff30;
f2b7cb0a 5922 do_bx (str);
b99bd4ef
NC
5923 }
5924 else
5925 {
5926 /* This must be is BLX <target address>, no condition allowed. */
5927 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
5928 {
5929 inst.error = BAD_COND;
b99bd4ef 5930 return;
cc8a6dd0 5931 }
b99bd4ef
NC
5932
5933 inst.instruction = 0xfafffffe;
5934
5935 /* Process like a B/BL, but with a different reloc.
5936 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 5937 do_branch25 (str);
b99bd4ef
NC
5938 }
5939}
5940
5941/* ARM V5 Thumb BLX (argument parse)
5942 BLX <target_addr> which is BLX(1)
5943 BLX <Rm> which is BLX(2)
5944 Unfortunately, there are two different opcodes for this mnemonic.
5945 So, the tinsns[].value is not used, and the code here zaps values
5946 into inst.instruction. */
5947
5948static void
5949do_t_blx (str)
5950 char * str;
5951{
5952 char * mystr = str;
5953 int rm;
5954
5955 skip_whitespace (mystr);
5956 inst.instruction = 0x4780;
5957
5958 /* Note that this call is to the ARM register recognizer. BLX(2)
5959 uses the ARM register space, not the Thumb one, so a call to
5960 thumb_reg() would be wrong. */
5961 rm = reg_required_here (& mystr, 3);
5962 inst.error = 0;
5963
5964 if (rm != FAIL)
5965 {
5966 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5967 inst.size = 2;
5968 }
5969 else
5970 {
5971 /* No ARM register. This must be BLX(1). Change the .instruction. */
5972 inst.instruction = 0xf7ffeffe;
5973 inst.size = 4;
5974
5975 if (my_get_expression (& inst.reloc.exp, & mystr))
5976 return;
5977
5978 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5979 inst.reloc.pc_rel = 1;
5980 }
5981
5982 end_of_line (mystr);
5983}
5984
5985/* ARM V5 breakpoint instruction (argument parse)
5986 BKPT <16 bit unsigned immediate>
5987 Instruction is not conditional.
5988 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5989 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5990
5991static void
f2b7cb0a 5992do_bkpt (str)
b99bd4ef 5993 char * str;
b99bd4ef
NC
5994{
5995 expressionS expr;
5996 unsigned long number;
5997
5998 skip_whitespace (str);
5999
6000 /* Allow optional leading '#'. */
6001 if (is_immediate_prefix (* str))
6002 str++;
6003
6004 memset (& expr, '\0', sizeof (expr));
6005
143c8e19
NC
6006 if (my_get_expression (& expr, & str)
6007 || (expr.X_op != O_constant
6008 /* As a convenience we allow 'bkpt' without an operand. */
6009 && expr.X_op != O_absent))
b99bd4ef 6010 {
143c8e19 6011 inst.error = _("bad expression");
b99bd4ef
NC
6012 return;
6013 }
6014
6015 number = expr.X_add_number;
6016
6017 /* Check it fits a 16 bit unsigned. */
6018 if (number != (number & 0xffff))
6019 {
6020 inst.error = _("immediate value out of range");
6021 return;
6022 }
6023
6024 /* Top 12 of 16 bits to bits 19:8. */
6025 inst.instruction |= (number & 0xfff0) << 4;
6026
6027 /* Bottom 4 of 16 bits to bits 3:0. */
6028 inst.instruction |= number & 0xf;
6029
6030 end_of_line (str);
b99bd4ef
NC
6031}
6032
09d92015
MM
6033/* THUMB CPS instruction (argument parse). */
6034
6035static void
6036do_t_cps (str)
6037 char *str;
6038{
6039 do_cps_flags (&str, /*thumb_p=*/1);
6040 end_of_line (str);
6041}
6042
6043/* THUMB CPY instruction (argument parse). */
6044
6045static void
6046do_t_cpy (str)
6047 char *str;
6048{
6049 thumb_mov_compare (str, THUMB_CPY);
6050}
6051
6052/* THUMB SETEND instruction (argument parse). */
6053
6054static void
6055do_t_setend (str)
6056 char *str;
6057{
6058 if (do_endian_specifier (str))
6059 inst.instruction |= 0x8;
6060}
6061
e16bb312
NC
6062static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6063
6064/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6065
6066static unsigned long
6067check_iwmmxt_insn (str, insn_type, immediate_size)
6068 char * str;
6069 enum iwmmxt_insn_type insn_type;
6070 int immediate_size;
6071{
6072 int reg = 0;
6073 const char * inst_error;
6074 expressionS expr;
6075 unsigned long number;
6076
6077 inst_error = inst.error;
6078 if (!inst.error)
6079 inst.error = BAD_ARGS;
6080 skip_whitespace (str);
6081
6082 switch (insn_type)
6083 {
6084 case check_rd:
6085 if ((reg = reg_required_here (&str, 12)) == FAIL)
6086 return FAIL;
6087 break;
6088
6089 case check_wr:
6090 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6091 return FAIL;
6092 break;
6093
6094 case check_wrwr:
6095 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6096 || skip_past_comma (&str) == FAIL
6097 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6098 return FAIL;
6099 break;
6100
6101 case check_wrwrwr:
6102 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6103 || skip_past_comma (&str) == FAIL
6104 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6105 || skip_past_comma (&str) == FAIL
6106 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6107 return FAIL;
6108 break;
6109
6110 case check_wrwrwcg:
6111 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6112 || skip_past_comma (&str) == FAIL
6113 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6114 || skip_past_comma (&str) == FAIL
6115 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6116 return FAIL;
6117 break;
6118
6119 case check_tbcst:
6120 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6121 || skip_past_comma (&str) == FAIL
6122 || reg_required_here (&str, 12) == FAIL))
6123 return FAIL;
6124 break;
6125
6126 case check_tmovmsk:
6127 if ((reg_required_here (&str, 12) == FAIL
6128 || skip_past_comma (&str) == FAIL
6129 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6130 return FAIL;
6131 break;
6132
6133 case check_tmia:
6134 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6135 || skip_past_comma (&str) == FAIL
6136 || reg_required_here (&str, 0) == FAIL
6137 || skip_past_comma (&str) == FAIL
6138 || reg_required_here (&str, 12) == FAIL))
6139 return FAIL;
6140 break;
6141
6142 case check_tmcrr:
6143 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6144 || skip_past_comma (&str) == FAIL
6145 || reg_required_here (&str, 12) == FAIL
6146 || skip_past_comma (&str) == FAIL
6147 || reg_required_here (&str, 16) == FAIL))
6148 return FAIL;
6149 break;
6150
6151 case check_tmrrc:
6152 if ((reg_required_here (&str, 12) == FAIL
6153 || skip_past_comma (&str) == FAIL
6154 || reg_required_here (&str, 16) == FAIL
6155 || skip_past_comma (&str) == FAIL
6156 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6157 return FAIL;
6158 break;
6159
6160 case check_tmcr:
6161 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6162 || skip_past_comma (&str) == FAIL
6163 || reg_required_here (&str, 12) == FAIL))
6164 return FAIL;
6165 break;
6166
6167 case check_tmrc:
6168 if ((reg_required_here (&str, 12) == FAIL
6169 || skip_past_comma (&str) == FAIL
6170 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6171 return FAIL;
6172 break;
6173
6174 case check_tinsr:
6175 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6176 || skip_past_comma (&str) == FAIL
6177 || reg_required_here (&str, 12) == FAIL
6178 || skip_past_comma (&str) == FAIL))
6179 return FAIL;
6180 break;
6181
6182 case check_textrc:
6183 if ((reg_required_here (&str, 12) == FAIL
6184 || skip_past_comma (&str) == FAIL))
6185 return FAIL;
6186 break;
6187
6188 case check_waligni:
6189 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6190 || skip_past_comma (&str) == FAIL
6191 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6192 || skip_past_comma (&str) == FAIL
6193 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6194 || skip_past_comma (&str) == FAIL))
6195 return FAIL;
6196 break;
6197
6198 case check_textrm:
6199 if ((reg_required_here (&str, 12) == FAIL
6200 || skip_past_comma (&str) == FAIL
6201 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6202 || skip_past_comma (&str) == FAIL))
6203 return FAIL;
6204 break;
6205
6206 case check_wshufh:
6207 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6208 || skip_past_comma (&str) == FAIL
6209 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6210 || skip_past_comma (&str) == FAIL))
6211 return FAIL;
6212 break;
6213 }
6214
6215 if (immediate_size == 0)
6216 {
6217 end_of_line (str);
6218 inst.error = inst_error;
6219 return reg;
6220 }
6221 else
6222 {
6223 skip_whitespace (str);
6224
6225 /* Allow optional leading '#'. */
6226 if (is_immediate_prefix (* str))
6227 str++;
6228
6229 memset (& expr, '\0', sizeof (expr));
6230
6231 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6232 {
6233 inst.error = _("bad or missing expression");
6234 return FAIL;
6235 }
6236
6237 number = expr.X_add_number;
6238
6239 if (number != (number & immediate_size))
6240 {
6241 inst.error = _("immediate value out of range");
6242 return FAIL;
6243 }
6244 end_of_line (str);
6245 inst.error = inst_error;
6246 return number;
6247 }
6248}
6249
6250static void
6251do_iwmmxt_byte_addr (str)
6252 char * str;
6253{
6254 int op = (inst.instruction & 0x300) >> 8;
6255 int reg;
6256
6257 inst.instruction &= ~0x300;
6258 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6259
6260 skip_whitespace (str);
6261
6262 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6263 || skip_past_comma (& str) == FAIL
6264 || cp_byte_address_required_here (&str) == FAIL)
6265 {
6266 if (! inst.error)
6267 inst.error = BAD_ARGS;
6268 }
6269 else
6270 end_of_line (str);
6271
6272 if (wc_register (reg))
6273 {
ece01a63 6274 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6275 inst.instruction |= 0xf0000100;
6276 inst.instruction &= ~0x00400000;
6277 }
6278}
6279
6280static void
6281do_iwmmxt_tandc (str)
6282 char * str;
6283{
6284 int reg;
6285
6286 reg = check_iwmmxt_insn (str, check_rd, 0);
6287
6288 if (reg != REG_PC && !inst.error)
6289 inst.error = _("only r15 allowed here");
e16bb312
NC
6290}
6291
6292static void
6293do_iwmmxt_tbcst (str)
6294 char * str;
6295{
6296 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
6297}
6298
6299static void
6300do_iwmmxt_textrc (str)
6301 char * str;
6302{
6303 unsigned long number;
6304
6305 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6306 return;
6307
6308 inst.instruction |= number & 0x7;
e16bb312
NC
6309}
6310
6311static void
6312do_iwmmxt_textrm (str)
6313 char * str;
6314{
6315 unsigned long number;
6316
6317 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6318 return;
6319
6320 inst.instruction |= number & 0x7;
6321}
6322
6323static void
6324do_iwmmxt_tinsr (str)
6325 char * str;
6326{
6327 unsigned long number;
6328
6329 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6330 return;
6331
6332 inst.instruction |= number & 0x7;
e16bb312
NC
6333}
6334
6335static void
6336do_iwmmxt_tmcr (str)
6337 char * str;
6338{
6339 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
6340}
6341
6342static void
6343do_iwmmxt_tmcrr (str)
6344 char * str;
6345{
6346 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
6347}
6348
6349static void
6350do_iwmmxt_tmia (str)
6351 char * str;
6352{
6353 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
6354}
6355
6356static void
6357do_iwmmxt_tmovmsk (str)
6358 char * str;
6359{
6360 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
6361}
6362
6363static void
6364do_iwmmxt_tmrc (str)
6365 char * str;
6366{
6367 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
6368}
6369
6370static void
6371do_iwmmxt_tmrrc (str)
6372 char * str;
6373{
6374 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
6375}
6376
6377static void
6378do_iwmmxt_torc (str)
6379 char * str;
6380{
6381 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
6382}
6383
6384static void
6385do_iwmmxt_waligni (str)
6386 char * str;
6387{
6388 unsigned long number;
6389
6390 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6391 return;
6392
6393 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
6394}
6395
6396static void
6397do_iwmmxt_wmov (str)
6398 char * str;
6399{
6400 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6401 return;
6402
6403 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
6404}
6405
6406static void
6407do_iwmmxt_word_addr (str)
6408 char * str;
6409{
6410 int op = (inst.instruction & 0x300) >> 8;
6411 int reg;
6412
6413 inst.instruction &= ~0x300;
6414 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6415
6416 skip_whitespace (str);
6417
6418 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6419 || skip_past_comma (& str) == FAIL
6420 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6421 {
6422 if (! inst.error)
6423 inst.error = BAD_ARGS;
6424 }
6425 else
6426 end_of_line (str);
6427
6428 if (wc_register (reg))
6429 {
ece01a63
ILT
6430 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6431 as_bad (_("conditional execution not supported with control register"));
6432 if (op != 2)
6433 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
6434 inst.instruction |= 0xf0000100;
6435 inst.instruction &= ~0x00400000;
6436 }
6437}
6438
6439static void
6440do_iwmmxt_wrwr (str)
6441 char * str;
6442{
6443 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
6444}
6445
6446static void
6447do_iwmmxt_wrwrwcg (str)
6448 char * str;
6449{
6450 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
6451}
6452
6453static void
6454do_iwmmxt_wrwrwr (str)
6455 char * str;
6456{
6457 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
6458}
6459
6460static void
6461do_iwmmxt_wshufh (str)
6462 char * str;
6463{
6464 unsigned long number;
6465
6466 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6467 return;
6468
6469 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
6470}
6471
6472static void
6473do_iwmmxt_wzero (str)
6474 char * str;
6475{
6476 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6477 return;
6478
6479 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
6480}
6481
b99bd4ef
NC
6482/* Xscale multiply-accumulate (argument parse)
6483 MIAcc acc0,Rm,Rs
6484 MIAPHcc acc0,Rm,Rs
6485 MIAxycc acc0,Rm,Rs. */
6486
6487static void
63e63b07 6488do_xsc_mia (str)
b99bd4ef 6489 char * str;
b99bd4ef
NC
6490{
6491 int rs;
6492 int rm;
6493
f2b7cb0a 6494 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6495 inst.error = ERR_NO_ACCUM;
6496
6497 else if (skip_past_comma (& str) == FAIL
6498 || (rm = reg_required_here (& str, 0)) == FAIL)
6499 inst.error = BAD_ARGS;
6500
6501 else if (skip_past_comma (& str) == FAIL
6502 || (rs = reg_required_here (& str, 12)) == FAIL)
6503 inst.error = BAD_ARGS;
6504
6505 /* inst.instruction has now been zapped with both rm and rs. */
6506 else if (rm == REG_PC || rs == REG_PC)
6507 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
6508
6509 else
6510 end_of_line (str);
6511}
6512
6513/* Xscale move-accumulator-register (argument parse)
6514
6515 MARcc acc0,RdLo,RdHi. */
6516
6517static void
63e63b07 6518do_xsc_mar (str)
b99bd4ef 6519 char * str;
b99bd4ef
NC
6520{
6521 int rdlo, rdhi;
6522
f2b7cb0a 6523 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
6524 inst.error = ERR_NO_ACCUM;
6525
6526 else if (skip_past_comma (& str) == FAIL
6527 || (rdlo = reg_required_here (& str, 12)) == FAIL)
6528 inst.error = BAD_ARGS;
6529
6530 else if (skip_past_comma (& str) == FAIL
6531 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6532 inst.error = BAD_ARGS;
6533
6534 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6535 else if (rdlo == REG_PC || rdhi == REG_PC)
6536 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6537
6538 else
6539 end_of_line (str);
6540}
6541
6542/* Xscale move-register-accumulator (argument parse)
6543
6544 MRAcc RdLo,RdHi,acc0. */
6545
6546static void
63e63b07 6547do_xsc_mra (str)
b99bd4ef 6548 char * str;
b99bd4ef
NC
6549{
6550 int rdlo;
6551 int rdhi;
6552
b99bd4ef
NC
6553 skip_whitespace (str);
6554
6555 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6556 inst.error = BAD_ARGS;
6557
6558 else if (skip_past_comma (& str) == FAIL
6559 || (rdhi = reg_required_here (& str, 16)) == FAIL)
6560 inst.error = BAD_ARGS;
6561
6562 else if (skip_past_comma (& str) == FAIL
6563 || accum0_required_here (& str) == FAIL)
6564 inst.error = ERR_NO_ACCUM;
6565
6566 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6567 else if (rdlo == rdhi)
6568 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
6569
6570 else if (rdlo == REG_PC || rdhi == REG_PC)
6571 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
6572 else
6573 end_of_line (str);
6574}
6575
c9b604bd 6576/* ARMv5TE: Preload-Cache
b99bd4ef
NC
6577
6578 PLD <addr_mode>
6579
6580 Syntactically, like LDR with B=1, W=0, L=1. */
6581
6582static void
f2b7cb0a 6583do_pld (str)
b99bd4ef 6584 char * str;
b99bd4ef
NC
6585{
6586 int rd;
6587
b99bd4ef
NC
6588 skip_whitespace (str);
6589
6590 if (* str != '[')
6591 {
6592 inst.error = _("'[' expected after PLD mnemonic");
6593 return;
6594 }
6595
90e4755a 6596 ++str;
b99bd4ef
NC
6597 skip_whitespace (str);
6598
6599 if ((rd = reg_required_here (& str, 16)) == FAIL)
6600 return;
6601
6602 skip_whitespace (str);
6603
90e4755a 6604 if (*str == ']')
b99bd4ef
NC
6605 {
6606 /* [Rn], ... ? */
90e4755a 6607 ++str;
b99bd4ef
NC
6608 skip_whitespace (str);
6609
90e4755a
RE
6610 /* Post-indexed addressing is not allowed with PLD. */
6611 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 6612 {
90e4755a
RE
6613 inst.error
6614 = _("post-indexed expression used in preload instruction");
6615 return;
b99bd4ef 6616 }
90e4755a 6617 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
6618 {
6619 inst.error = _("writeback used in preload instruction");
90e4755a 6620 ++str;
b99bd4ef
NC
6621 }
6622 else /* [Rn] */
6623 inst.instruction |= INDEX_UP | PRE_INDEX;
6624 }
6625 else /* [Rn, ...] */
6626 {
6627 if (skip_past_comma (& str) == FAIL)
6628 {
6629 inst.error = _("pre-indexed expression expected");
6630 return;
6631 }
6632
90e4755a 6633 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
6634 return;
6635
6636 skip_whitespace (str);
6637
6638 if (* str != ']')
6639 {
6640 inst.error = _("missing ]");
6641 return;
6642 }
6643
6644 ++ str;
6645 skip_whitespace (str);
6646
6647 if (* str == '!') /* [Rn]! */
6648 {
6649 inst.error = _("writeback used in preload instruction");
6650 ++ str;
6651 }
6652
6653 inst.instruction |= PRE_INDEX;
6654 }
6655
6656 end_of_line (str);
6657}
6658
c9b604bd 6659/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
6660 Mode is like LDRH.
6661
6662 LDRccD R, mode
6663 STRccD R, mode. */
6664
6665static void
f2b7cb0a 6666do_ldrd (str)
b99bd4ef 6667 char * str;
b99bd4ef
NC
6668{
6669 int rd;
6670 int rn;
6671
b99bd4ef
NC
6672 skip_whitespace (str);
6673
6674 if ((rd = reg_required_here (& str, 12)) == FAIL)
6675 {
6676 inst.error = BAD_ARGS;
6677 return;
6678 }
6679
6680 if (skip_past_comma (& str) == FAIL
6681 || (rn = ld_mode_required_here (& str)) == FAIL)
6682 {
6683 if (!inst.error)
cc8a6dd0 6684 inst.error = BAD_ARGS;
b99bd4ef
NC
6685 return;
6686 }
6687
6688 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6689 if (rd & 1) /* Unpredictable result if Rd is odd. */
6690 {
f03698e6 6691 inst.error = _("destination register must be even");
b99bd4ef
NC
6692 return;
6693 }
6694
90e4755a 6695 if (rd == REG_LR)
b99bd4ef 6696 {
f2b7cb0a 6697 inst.error = _("r14 not allowed here");
b99bd4ef
NC
6698 return;
6699 }
6700
6701 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
6702 && ((inst.instruction & WRITE_BACK)
6703 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
6704 as_warn (_("pre/post-indexing used when modified address register is destination"));
6705
90e4755a
RE
6706 /* For an index-register load, the index register must not overlap the
6707 destination (even if not write-back). */
6708 if ((inst.instruction & V4_STR_BIT) == 0
6709 && (inst.instruction & HWOFFSET_IMM) == 0)
6710 {
6711 int rm = inst.instruction & 0x0000000f;
6712
6713 if (rm == rd || (rm == rd + 1))
6714 as_warn (_("ldrd destination registers must not overlap index register"));
6715 }
6716
b99bd4ef
NC
6717 end_of_line (str);
6718}
6719
6720/* Returns the index into fp_values of a floating point number,
6721 or -1 if not in the table. */
6722
6723static int
6724my_get_float_expression (str)
6725 char ** str;
6726{
6727 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6728 char * save_in;
6729 expressionS exp;
6730 int i;
6731 int j;
6732
6733 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6734
6735 /* Look for a raw floating point number. */
6736 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6737 && is_end_of_line[(unsigned char) *save_in])
6738 {
6739 for (i = 0; i < NUM_FLOAT_VALS; i++)
6740 {
6741 for (j = 0; j < MAX_LITTLENUMS; j++)
6742 {
6743 if (words[j] != fp_values[i][j])
6744 break;
6745 }
6746
6747 if (j == MAX_LITTLENUMS)
6748 {
6749 *str = save_in;
6750 return i;
6751 }
6752 }
6753 }
6754
6755 /* Try and parse a more complex expression, this will probably fail
6756 unless the code uses a floating point prefix (eg "0f"). */
6757 save_in = input_line_pointer;
6758 input_line_pointer = *str;
6759 if (expression (&exp) == absolute_section
6760 && exp.X_op == O_big
6761 && exp.X_add_number < 0)
6762 {
6763 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6764 Ditto for 15. */
6765 if (gen_to_words (words, 5, (long) 15) == 0)
6766 {
6767 for (i = 0; i < NUM_FLOAT_VALS; i++)
6768 {
6769 for (j = 0; j < MAX_LITTLENUMS; j++)
6770 {
6771 if (words[j] != fp_values[i][j])
6772 break;
6773 }
6774
6775 if (j == MAX_LITTLENUMS)
6776 {
6777 *str = input_line_pointer;
6778 input_line_pointer = save_in;
6779 return i;
6780 }
6781 }
6782 }
6783 }
6784
6785 *str = input_line_pointer;
6786 input_line_pointer = save_in;
6787 return -1;
6788}
6789
b34976b6 6790/* Return TRUE if anything in the expression is a bignum. */
b99bd4ef
NC
6791
6792static int
6793walk_no_bignums (sp)
6794 symbolS * sp;
6795{
6796 if (symbol_get_value_expression (sp)->X_op == O_big)
6797 return 1;
6798
6799 if (symbol_get_value_expression (sp)->X_add_symbol)
6800 {
6801 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6802 || (symbol_get_value_expression (sp)->X_op_symbol
6803 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6804 }
6805
6806 return 0;
6807}
6808
f03698e6
RE
6809static int in_my_get_expression = 0;
6810
b99bd4ef
NC
6811static int
6812my_get_expression (ep, str)
6813 expressionS * ep;
6814 char ** str;
6815{
6816 char * save_in;
6817 segT seg;
6818
6819 save_in = input_line_pointer;
6820 input_line_pointer = *str;
f03698e6 6821 in_my_get_expression = 1;
b99bd4ef 6822 seg = expression (ep);
f03698e6
RE
6823 in_my_get_expression = 0;
6824
6825 if (ep->X_op == O_illegal)
6826 {
6827 /* We found a bad expression in md_operand(). */
6828 *str = input_line_pointer;
6829 input_line_pointer = save_in;
6830 return 1;
6831 }
b99bd4ef
NC
6832
6833#ifdef OBJ_AOUT
6834 if (seg != absolute_section
6835 && seg != text_section
6836 && seg != data_section
6837 && seg != bss_section
6838 && seg != undefined_section)
6839 {
6840 inst.error = _("bad_segment");
6841 *str = input_line_pointer;
6842 input_line_pointer = save_in;
6843 return 1;
6844 }
6845#endif
6846
6847 /* Get rid of any bignums now, so that we don't generate an error for which
6848 we can't establish a line number later on. Big numbers are never valid
6849 in instructions, which is where this routine is always called. */
6850 if (ep->X_op == O_big
6851 || (ep->X_add_symbol
6852 && (walk_no_bignums (ep->X_add_symbol)
6853 || (ep->X_op_symbol
6854 && walk_no_bignums (ep->X_op_symbol)))))
6855 {
f03698e6 6856 inst.error = _("invalid constant");
b99bd4ef
NC
6857 *str = input_line_pointer;
6858 input_line_pointer = save_in;
6859 return 1;
6860 }
6861
6862 *str = input_line_pointer;
6863 input_line_pointer = save_in;
6864 return 0;
6865}
6866
cc8a6dd0 6867/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
6868 instruction in the error message. */
6869void
ce058b6c 6870md_operand (expr)
f03698e6
RE
6871 expressionS *expr;
6872{
6873 if (in_my_get_expression)
6874 {
6875 expr->X_op = O_illegal;
6876 if (inst.error == NULL)
6877 inst.error = _("bad expression");
6878 }
6879}
6880
09d92015 6881/* KIND indicates what kind of shifts are accepted. */
b99bd4ef
NC
6882
6883static int
09d92015 6884decode_shift (str, kind)
b99bd4ef 6885 char ** str;
09d92015 6886 int kind;
b99bd4ef
NC
6887{
6888 const struct asm_shift_name * shift;
6889 char * p;
6890 char c;
6891
6892 skip_whitespace (* str);
6893
3882b010 6894 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
6895 ;
6896
6897 if (p == * str)
6898 {
f03698e6 6899 inst.error = _("shift expression expected");
b99bd4ef
NC
6900 return FAIL;
6901 }
6902
6903 c = * p;
6904 * p = '\0';
6905 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6906 * p = c;
6907
6908 if (shift == NULL)
6909 {
f03698e6 6910 inst.error = _("shift expression expected");
b99bd4ef
NC
6911 return FAIL;
6912 }
6913
6914 assert (shift->properties->index == shift_properties[shift->properties->index].index);
6915
09d92015
MM
6916 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6917 && shift->properties->index != SHIFT_LSL
6918 && shift->properties->index != SHIFT_ASR)
6919 {
6920 inst.error = _("'LSL' or 'ASR' required");
6921 return FAIL;
6922 }
6923 else if (kind == SHIFT_LSL_IMMEDIATE
6924 && shift->properties->index != SHIFT_LSL)
6925 {
6926 inst.error = _("'LSL' required");
6927 return FAIL;
6928 }
6929 else if (kind == SHIFT_ASR_IMMEDIATE
6930 && shift->properties->index != SHIFT_ASR)
6931 {
6932 inst.error = _("'ASR' required");
6933 return FAIL;
6934 }
6935
b99bd4ef
NC
6936 if (shift->properties->index == SHIFT_RRX)
6937 {
6938 * str = p;
6939 inst.instruction |= shift->properties->bit_field;
6940 return SUCCESS;
6941 }
6942
6943 skip_whitespace (p);
6944
09d92015 6945 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
b99bd4ef
NC
6946 {
6947 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6948 * str = p;
6949 return SUCCESS;
6950 }
6951 else if (! is_immediate_prefix (* p))
6952 {
09d92015 6953 inst.error = (NO_SHIFT_RESTRICT
b99bd4ef
NC
6954 ? _("shift requires register or #expression")
6955 : _("shift requires #expression"));
6956 * str = p;
6957 return FAIL;
6958 }
6959
6960 inst.error = NULL;
6961 p ++;
6962
6963 if (my_get_expression (& inst.reloc.exp, & p))
6964 return FAIL;
6965
6966 /* Validate some simple #expressions. */
6967 if (inst.reloc.exp.X_op == O_constant)
6968 {
6969 unsigned num = inst.reloc.exp.X_add_number;
6970
6971 /* Reject operations greater than 32. */
6972 if (num > 32
6973 /* Reject a shift of 0 unless the mode allows it. */
6974 || (num == 0 && shift->properties->allows_0 == 0)
6975 /* Reject a shift of 32 unless the mode allows it. */
6976 || (num == 32 && shift->properties->allows_32 == 0)
6977 )
6978 {
6979 /* As a special case we allow a shift of zero for
6980 modes that do not support it to be recoded as an
6981 logical shift left of zero (ie nothing). We warn
6982 about this though. */
6983 if (num == 0)
6984 {
f03698e6 6985 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
6986 shift = & shift_names[0];
6987 assert (shift->properties->index == SHIFT_LSL);
6988 }
6989 else
6990 {
f03698e6 6991 inst.error = _("invalid immediate shift");
b99bd4ef
NC
6992 return FAIL;
6993 }
6994 }
6995
6996 /* Shifts of 32 are encoded as 0, for those shifts that
6997 support it. */
6998 if (num == 32)
6999 num = 0;
7000
7001 inst.instruction |= (num << 7) | shift->properties->bit_field;
7002 }
7003 else
7004 {
7005 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
7006 inst.reloc.pc_rel = 0;
7007 inst.instruction |= shift->properties->bit_field;
7008 }
7009
7010 * str = p;
7011 return SUCCESS;
7012}
7013
7014/* Do those data_ops which can take a negative immediate constant
2d2255b5 7015 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
7016 MOV <-> MVN
7017 AND <-> BIC
7018 ADC <-> SBC
7019 by inverting the second operand, and
7020 ADD <-> SUB
7021 CMP <-> CMN
7022 by negating the second operand. */
7023
7024static int
7025negate_data_op (instruction, value)
7026 unsigned long * instruction;
7027 unsigned long value;
7028{
7029 int op, new_inst;
7030 unsigned long negated, inverted;
7031
7032 negated = validate_immediate (-value);
7033 inverted = validate_immediate (~value);
7034
7035 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7036 switch (op)
7037 {
7038 /* First negates. */
7039 case OPCODE_SUB: /* ADD <-> SUB */
7040 new_inst = OPCODE_ADD;
7041 value = negated;
7042 break;
7043
7044 case OPCODE_ADD:
7045 new_inst = OPCODE_SUB;
7046 value = negated;
7047 break;
7048
7049 case OPCODE_CMP: /* CMP <-> CMN */
7050 new_inst = OPCODE_CMN;
7051 value = negated;
7052 break;
7053
7054 case OPCODE_CMN:
7055 new_inst = OPCODE_CMP;
7056 value = negated;
7057 break;
7058
7059 /* Now Inverted ops. */
7060 case OPCODE_MOV: /* MOV <-> MVN */
7061 new_inst = OPCODE_MVN;
7062 value = inverted;
7063 break;
7064
7065 case OPCODE_MVN:
7066 new_inst = OPCODE_MOV;
7067 value = inverted;
7068 break;
7069
7070 case OPCODE_AND: /* AND <-> BIC */
7071 new_inst = OPCODE_BIC;
7072 value = inverted;
7073 break;
7074
7075 case OPCODE_BIC:
7076 new_inst = OPCODE_AND;
7077 value = inverted;
7078 break;
7079
7080 case OPCODE_ADC: /* ADC <-> SBC */
7081 new_inst = OPCODE_SBC;
7082 value = inverted;
7083 break;
7084
7085 case OPCODE_SBC:
7086 new_inst = OPCODE_ADC;
7087 value = inverted;
7088 break;
7089
7090 /* We cannot do anything. */
7091 default:
7092 return FAIL;
7093 }
7094
7095 if (value == (unsigned) FAIL)
7096 return FAIL;
7097
7098 *instruction &= OPCODE_MASK;
7099 *instruction |= new_inst << DATA_OP_SHIFT;
7100 return value;
7101}
7102
7103static int
7104data_op2 (str)
7105 char ** str;
7106{
7107 int value;
7108 expressionS expr;
7109
7110 skip_whitespace (* str);
7111
7112 if (reg_required_here (str, 0) != FAIL)
7113 {
7114 if (skip_past_comma (str) == SUCCESS)
7115 /* Shift operation on register. */
7116 return decode_shift (str, NO_SHIFT_RESTRICT);
7117
7118 return SUCCESS;
7119 }
7120 else
7121 {
7122 /* Immediate expression. */
7123 if (is_immediate_prefix (**str))
7124 {
7125 (*str)++;
7126 inst.error = NULL;
7127
7128 if (my_get_expression (&inst.reloc.exp, str))
7129 return FAIL;
7130
7131 if (inst.reloc.exp.X_add_symbol)
7132 {
7133 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7134 inst.reloc.pc_rel = 0;
7135 }
7136 else
7137 {
7138 if (skip_past_comma (str) == SUCCESS)
7139 {
7140 /* #x, y -- ie explicit rotation by Y. */
7141 if (my_get_expression (&expr, str))
7142 return FAIL;
7143
7144 if (expr.X_op != O_constant)
7145 {
f03698e6 7146 inst.error = _("constant expression expected");
b99bd4ef
NC
7147 return FAIL;
7148 }
7149
7150 /* Rotate must be a multiple of 2. */
7151 if (((unsigned) expr.X_add_number) > 30
7152 || (expr.X_add_number & 1) != 0
7153 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7154 {
f03698e6 7155 inst.error = _("invalid constant");
b99bd4ef
NC
7156 return FAIL;
7157 }
7158 inst.instruction |= INST_IMMEDIATE;
7159 inst.instruction |= inst.reloc.exp.X_add_number;
7160 inst.instruction |= expr.X_add_number << 7;
7161 return SUCCESS;
7162 }
7163
7164 /* Implicit rotation, select a suitable one. */
7165 value = validate_immediate (inst.reloc.exp.X_add_number);
7166
7167 if (value == FAIL)
7168 {
7169 /* Can't be done. Perhaps the code reads something like
7170 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7171 if ((value = negate_data_op (&inst.instruction,
7172 inst.reloc.exp.X_add_number))
7173 == FAIL)
7174 {
f03698e6 7175 inst.error = _("invalid constant");
b99bd4ef
NC
7176 return FAIL;
7177 }
7178 }
7179
7180 inst.instruction |= value;
7181 }
7182
7183 inst.instruction |= INST_IMMEDIATE;
7184 return SUCCESS;
7185 }
7186
7187 (*str)++;
f03698e6 7188 inst.error = _("register or shift expression expected");
b99bd4ef
NC
7189 return FAIL;
7190 }
7191}
7192
7193static int
7194fp_op2 (str)
7195 char ** str;
7196{
7197 skip_whitespace (* str);
7198
7199 if (fp_reg_required_here (str, 0) != FAIL)
7200 return SUCCESS;
7201 else
7202 {
7203 /* Immediate expression. */
7204 if (*((*str)++) == '#')
7205 {
7206 int i;
7207
7208 inst.error = NULL;
7209
7210 skip_whitespace (* str);
7211
7212 /* First try and match exact strings, this is to guarantee
7213 that some formats will work even for cross assembly. */
7214
7215 for (i = 0; fp_const[i]; i++)
7216 {
7217 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7218 {
7219 char *start = *str;
7220
7221 *str += strlen (fp_const[i]);
7222 if (is_end_of_line[(unsigned char) **str])
7223 {
7224 inst.instruction |= i + 8;
7225 return SUCCESS;
7226 }
7227 *str = start;
7228 }
7229 }
7230
7231 /* Just because we didn't get a match doesn't mean that the
7232 constant isn't valid, just that it is in a format that we
7233 don't automatically recognize. Try parsing it with
7234 the standard expression routines. */
7235 if ((i = my_get_float_expression (str)) >= 0)
7236 {
7237 inst.instruction |= i + 8;
7238 return SUCCESS;
7239 }
7240
f03698e6 7241 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
7242 return FAIL;
7243 }
7244 inst.error =
f03698e6 7245 _("floating point register or immediate expression expected");
b99bd4ef
NC
7246 return FAIL;
7247 }
7248}
7249
7250static void
f2b7cb0a 7251do_arit (str)
b99bd4ef 7252 char * str;
b99bd4ef
NC
7253{
7254 skip_whitespace (str);
7255
7256 if (reg_required_here (&str, 12) == FAIL
7257 || skip_past_comma (&str) == FAIL
7258 || reg_required_here (&str, 16) == FAIL
7259 || skip_past_comma (&str) == FAIL
7260 || data_op2 (&str) == FAIL)
7261 {
7262 if (!inst.error)
7263 inst.error = BAD_ARGS;
7264 return;
7265 }
7266
b99bd4ef 7267 end_of_line (str);
b99bd4ef
NC
7268}
7269
7270static void
f2b7cb0a 7271do_adr (str)
b99bd4ef 7272 char * str;
b99bd4ef 7273{
90e4755a
RE
7274 /* This is a pseudo-op of the form "adr rd, label" to be converted
7275 into a relative address of the form "add rd, pc, #label-.-8". */
7276 skip_whitespace (str);
7277
7278 if (reg_required_here (&str, 12) == FAIL
7279 || skip_past_comma (&str) == FAIL
7280 || my_get_expression (&inst.reloc.exp, &str))
7281 {
7282 if (!inst.error)
7283 inst.error = BAD_ARGS;
7284 return;
7285 }
7286
7287 /* Frag hacking will turn this into a sub instruction if the offset turns
7288 out to be negative. */
7289 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7290 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
7291 inst.reloc.pc_rel = 1;
7292
7293 end_of_line (str);
7294}
7295
7296static void
f2b7cb0a 7297do_adrl (str)
90e4755a 7298 char * str;
90e4755a
RE
7299{
7300 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7301 into a relative address of the form:
7302 add rd, pc, #low(label-.-8)"
7303 add rd, rd, #high(label-.-8)" */
7304
7305 skip_whitespace (str);
7306
7307 if (reg_required_here (&str, 12) == FAIL
7308 || skip_past_comma (&str) == FAIL
7309 || my_get_expression (&inst.reloc.exp, &str))
7310 {
7311 if (!inst.error)
7312 inst.error = BAD_ARGS;
7313
7314 return;
7315 }
7316
7317 end_of_line (str);
7318 /* Frag hacking will turn this into a sub instruction if the offset turns
7319 out to be negative. */
7320 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7321 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
7322 inst.reloc.pc_rel = 1;
7323 inst.size = INSN_SIZE * 2;
90e4755a
RE
7324}
7325
7326static void
f2b7cb0a 7327do_cmp (str)
90e4755a 7328 char * str;
90e4755a
RE
7329{
7330 skip_whitespace (str);
7331
7332 if (reg_required_here (&str, 16) == FAIL)
7333 {
7334 if (!inst.error)
7335 inst.error = BAD_ARGS;
7336 return;
7337 }
7338
7339 if (skip_past_comma (&str) == FAIL
7340 || data_op2 (&str) == FAIL)
7341 {
7342 if (!inst.error)
7343 inst.error = BAD_ARGS;
7344 return;
7345 }
7346
90e4755a 7347 end_of_line (str);
90e4755a
RE
7348}
7349
7350static void
f2b7cb0a 7351do_mov (str)
90e4755a 7352 char * str;
90e4755a
RE
7353{
7354 skip_whitespace (str);
7355
7356 if (reg_required_here (&str, 12) == FAIL)
7357 {
7358 if (!inst.error)
7359 inst.error = BAD_ARGS;
7360 return;
7361 }
7362
7363 if (skip_past_comma (&str) == FAIL
7364 || data_op2 (&str) == FAIL)
7365 {
7366 if (!inst.error)
7367 inst.error = BAD_ARGS;
7368 return;
7369 }
7370
90e4755a 7371 end_of_line (str);
90e4755a
RE
7372}
7373
7374static int
7375ldst_extend (str)
7376 char ** str;
7377{
7378 int add = INDEX_UP;
7379
7380 switch (**str)
7381 {
7382 case '#':
7383 case '$':
7384 (*str)++;
7385 if (my_get_expression (& inst.reloc.exp, str))
7386 return FAIL;
7387
7388 if (inst.reloc.exp.X_op == O_constant)
7389 {
7390 int value = inst.reloc.exp.X_add_number;
7391
7392 if (value < -4095 || value > 4095)
7393 {
7394 inst.error = _("address offset too large");
7395 return FAIL;
7396 }
7397
7398 if (value < 0)
7399 {
7400 value = -value;
7401 add = 0;
7402 }
7403
7404 inst.instruction |= add | value;
7405 }
7406 else
7407 {
7408 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7409 inst.reloc.pc_rel = 0;
7410 }
7411 return SUCCESS;
7412
7413 case '-':
7414 add = 0;
7415 /* Fall through. */
7416
7417 case '+':
7418 (*str)++;
7419 /* Fall through. */
7420
7421 default:
7422 if (reg_required_here (str, 0) == FAIL)
7423 return FAIL;
7424
7425 inst.instruction |= add | OFFSET_REG;
7426 if (skip_past_comma (str) == SUCCESS)
09d92015 7427 return decode_shift (str, SHIFT_IMMEDIATE);
90e4755a
RE
7428
7429 return SUCCESS;
7430 }
7431}
7432
7433static void
f2b7cb0a 7434do_ldst (str)
90e4755a 7435 char * str;
90e4755a
RE
7436{
7437 int pre_inc = 0;
7438 int conflict_reg;
7439 int value;
7440
b99bd4ef
NC
7441 skip_whitespace (str);
7442
90e4755a
RE
7443 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7444 {
7445 if (!inst.error)
7446 inst.error = BAD_ARGS;
7447 return;
7448 }
7449
7450 if (skip_past_comma (&str) == FAIL)
7451 {
f03698e6 7452 inst.error = _("address expected");
90e4755a
RE
7453 return;
7454 }
7455
90e4755a
RE
7456 if (*str == '[')
7457 {
7458 int reg;
7459
7460 str++;
7461
7462 skip_whitespace (str);
7463
7464 if ((reg = reg_required_here (&str, 16)) == FAIL)
7465 return;
7466
7467 /* Conflicts can occur on stores as well as loads. */
7468 conflict_reg = (conflict_reg == reg);
7469
7470 skip_whitespace (str);
7471
7472 if (*str == ']')
7473 {
7474 str ++;
7475
7476 if (skip_past_comma (&str) == SUCCESS)
7477 {
7478 /* [Rn],... (post inc) */
7479 if (ldst_extend (&str) == FAIL)
7480 return;
7481 if (conflict_reg)
7482 as_warn (_("%s register same as write-back base"),
7483 ((inst.instruction & LOAD_BIT)
7484 ? _("destination") : _("source")));
7485 }
7486 else
7487 {
7488 /* [Rn] */
7489 skip_whitespace (str);
7490
7491 if (*str == '!')
7492 {
7493 if (conflict_reg)
7494 as_warn (_("%s register same as write-back base"),
7495 ((inst.instruction & LOAD_BIT)
7496 ? _("destination") : _("source")));
7497 str++;
7498 inst.instruction |= WRITE_BACK;
7499 }
7500
7501 inst.instruction |= INDEX_UP;
7502 pre_inc = 1;
7503 }
7504 }
7505 else
7506 {
7507 /* [Rn,...] */
7508 if (skip_past_comma (&str) == FAIL)
7509 {
7510 inst.error = _("pre-indexed expression expected");
7511 return;
7512 }
7513
7514 pre_inc = 1;
7515 if (ldst_extend (&str) == FAIL)
7516 return;
7517
7518 skip_whitespace (str);
7519
7520 if (*str++ != ']')
7521 {
7522 inst.error = _("missing ]");
7523 return;
7524 }
7525
7526 skip_whitespace (str);
7527
7528 if (*str == '!')
7529 {
7530 if (conflict_reg)
7531 as_warn (_("%s register same as write-back base"),
7532 ((inst.instruction & LOAD_BIT)
7533 ? _("destination") : _("source")));
7534 str++;
7535 inst.instruction |= WRITE_BACK;
7536 }
7537 }
7538 }
7539 else if (*str == '=')
7540 {
f03698e6
RE
7541 if ((inst.instruction & LOAD_BIT) == 0)
7542 {
7543 inst.error = _("invalid pseudo operation");
7544 return;
7545 }
7546
90e4755a
RE
7547 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7548 str++;
7549
7550 skip_whitespace (str);
7551
7552 if (my_get_expression (&inst.reloc.exp, &str))
7553 return;
7554
7555 if (inst.reloc.exp.X_op != O_constant
7556 && inst.reloc.exp.X_op != O_symbol)
7557 {
f03698e6 7558 inst.error = _("constant expression expected");
90e4755a
RE
7559 return;
7560 }
7561
e28cd48c 7562 if (inst.reloc.exp.X_op == O_constant)
90e4755a 7563 {
e28cd48c
RE
7564 value = validate_immediate (inst.reloc.exp.X_add_number);
7565
7566 if (value != FAIL)
90e4755a 7567 {
e28cd48c
RE
7568 /* This can be done with a mov instruction. */
7569 inst.instruction &= LITERAL_MASK;
7570 inst.instruction |= (INST_IMMEDIATE
7571 | (OPCODE_MOV << DATA_OP_SHIFT));
7572 inst.instruction |= value & 0xfff;
7573 end_of_line (str);
90e4755a
RE
7574 return;
7575 }
b99bd4ef 7576
e28cd48c
RE
7577 value = validate_immediate (~inst.reloc.exp.X_add_number);
7578
7579 if (value != FAIL)
7580 {
7581 /* This can be done with a mvn instruction. */
7582 inst.instruction &= LITERAL_MASK;
7583 inst.instruction |= (INST_IMMEDIATE
7584 | (OPCODE_MVN << DATA_OP_SHIFT));
7585 inst.instruction |= value & 0xfff;
7586 end_of_line (str);
7587 return;
7588 }
90e4755a 7589 }
e28cd48c
RE
7590
7591 /* Insert into literal pool. */
7592 if (add_to_lit_pool () == FAIL)
7593 {
7594 if (!inst.error)
7595 inst.error = _("literal pool insertion failed");
7596 return;
7597 }
7598
7599 /* Change the instruction exp to point to the pool. */
7600 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7601 inst.reloc.pc_rel = 1;
7602 inst.instruction |= (REG_PC << 16);
7603 pre_inc = 1;
1cac9012
NC
7604 }
7605 else
7606 {
90e4755a
RE
7607 if (my_get_expression (&inst.reloc.exp, &str))
7608 return;
7609
7610 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7611#ifndef TE_WINCE
7612 /* PC rel adjust. */
7613 inst.reloc.exp.X_add_number -= 8;
7614#endif
1cac9012 7615 inst.reloc.pc_rel = 1;
90e4755a
RE
7616 inst.instruction |= (REG_PC << 16);
7617 pre_inc = 1;
b99bd4ef
NC
7618 }
7619
90e4755a 7620 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7621 end_of_line (str);
b99bd4ef
NC
7622}
7623
7624static void
f2b7cb0a 7625do_ldstt (str)
90e4755a 7626 char * str;
b99bd4ef 7627{
90e4755a
RE
7628 int conflict_reg;
7629
b99bd4ef
NC
7630 skip_whitespace (str);
7631
90e4755a 7632 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
7633 {
7634 if (!inst.error)
7635 inst.error = BAD_ARGS;
7636 return;
7637 }
7638
90e4755a 7639 if (skip_past_comma (& str) == FAIL)
b99bd4ef 7640 {
f03698e6 7641 inst.error = _("address expected");
b99bd4ef
NC
7642 return;
7643 }
7644
90e4755a
RE
7645 if (*str == '[')
7646 {
7647 int reg;
b99bd4ef 7648
90e4755a 7649 str++;
b99bd4ef 7650
90e4755a 7651 skip_whitespace (str);
b99bd4ef 7652
90e4755a
RE
7653 if ((reg = reg_required_here (&str, 16)) == FAIL)
7654 return;
b99bd4ef 7655
90e4755a
RE
7656 /* ldrt/strt always use post-indexed addressing, so if the base is
7657 the same as Rd, we warn. */
7658 if (conflict_reg == reg)
7659 as_warn (_("%s register same as write-back base"),
7660 ((inst.instruction & LOAD_BIT)
7661 ? _("destination") : _("source")));
7662
7663 skip_whitespace (str);
7664
7665 if (*str == ']')
7666 {
7667 str ++;
7668
7669 if (skip_past_comma (&str) == SUCCESS)
7670 {
7671 /* [Rn],... (post inc) */
7672 if (ldst_extend (&str) == FAIL)
7673 return;
7674 }
7675 else
7676 {
7677 /* [Rn] */
7678 skip_whitespace (str);
7679
7680 /* Skip a write-back '!'. */
7681 if (*str == '!')
7682 str++;
7683
7684 inst.instruction |= INDEX_UP;
7685 }
7686 }
7687 else
7688 {
7689 inst.error = _("post-indexed expression expected");
7690 return;
7691 }
7692 }
7693 else
b99bd4ef 7694 {
90e4755a 7695 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
7696 return;
7697 }
7698
b99bd4ef 7699 end_of_line (str);
b99bd4ef
NC
7700}
7701
7702static int
90e4755a 7703ldst_extend_v4 (str)
b99bd4ef 7704 char ** str;
b99bd4ef
NC
7705{
7706 int add = INDEX_UP;
7707
7708 switch (**str)
7709 {
7710 case '#':
7711 case '$':
7712 (*str)++;
7713 if (my_get_expression (& inst.reloc.exp, str))
7714 return FAIL;
7715
7716 if (inst.reloc.exp.X_op == O_constant)
7717 {
7718 int value = inst.reloc.exp.X_add_number;
7719
90e4755a 7720 if (value < -255 || value > 255)
b99bd4ef
NC
7721 {
7722 inst.error = _("address offset too large");
7723 return FAIL;
7724 }
7725
7726 if (value < 0)
7727 {
7728 value = -value;
7729 add = 0;
7730 }
7731
7732 /* Halfword and signextension instructions have the
7733 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
7734 inst.instruction |= (add | HWOFFSET_IMM
7735 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
7736 }
7737 else
7738 {
90e4755a
RE
7739 inst.instruction |= HWOFFSET_IMM;
7740 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7741 inst.reloc.pc_rel = 0;
7742 }
7743 return SUCCESS;
7744
7745 case '-':
7746 add = 0;
7747 /* Fall through. */
7748
7749 case '+':
7750 (*str)++;
7751 /* Fall through. */
7752
7753 default:
7754 if (reg_required_here (str, 0) == FAIL)
7755 return FAIL;
7756
90e4755a 7757 inst.instruction |= add;
b99bd4ef
NC
7758 return SUCCESS;
7759 }
7760}
7761
90e4755a 7762/* Halfword and signed-byte load/store operations. */
b99bd4ef 7763static void
f2b7cb0a 7764do_ldstv4 (str)
b99bd4ef 7765 char * str;
b99bd4ef 7766{
b99bd4ef
NC
7767 int pre_inc = 0;
7768 int conflict_reg;
7769 int value;
7770
b99bd4ef
NC
7771 skip_whitespace (str);
7772
7773 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7774 {
7775 if (!inst.error)
7776 inst.error = BAD_ARGS;
7777 return;
7778 }
7779
7780 if (skip_past_comma (& str) == FAIL)
7781 {
f03698e6 7782 inst.error = _("address expected");
b99bd4ef
NC
7783 return;
7784 }
7785
7786 if (*str == '[')
7787 {
7788 int reg;
7789
7790 str++;
7791
7792 skip_whitespace (str);
7793
7794 if ((reg = reg_required_here (&str, 16)) == FAIL)
7795 return;
7796
7797 /* Conflicts can occur on stores as well as loads. */
7798 conflict_reg = (conflict_reg == reg);
7799
7800 skip_whitespace (str);
7801
7802 if (*str == ']')
7803 {
7804 str ++;
7805
7806 if (skip_past_comma (&str) == SUCCESS)
7807 {
7808 /* [Rn],... (post inc) */
90e4755a 7809 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7810 return;
7811 if (conflict_reg)
90e4755a
RE
7812 as_warn (_("%s register same as write-back base"),
7813 ((inst.instruction & LOAD_BIT)
7814 ? _("destination") : _("source")));
b99bd4ef
NC
7815 }
7816 else
7817 {
7818 /* [Rn] */
90e4755a 7819 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
7820
7821 skip_whitespace (str);
7822
7823 if (*str == '!')
7824 {
7825 if (conflict_reg)
7826 as_warn (_("%s register same as write-back base"),
7827 ((inst.instruction & LOAD_BIT)
7828 ? _("destination") : _("source")));
7829 str++;
7830 inst.instruction |= WRITE_BACK;
7831 }
7832
90e4755a
RE
7833 inst.instruction |= INDEX_UP;
7834 pre_inc = 1;
b99bd4ef
NC
7835 }
7836 }
7837 else
7838 {
7839 /* [Rn,...] */
7840 if (skip_past_comma (&str) == FAIL)
7841 {
7842 inst.error = _("pre-indexed expression expected");
7843 return;
7844 }
7845
7846 pre_inc = 1;
90e4755a 7847 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
7848 return;
7849
7850 skip_whitespace (str);
7851
7852 if (*str++ != ']')
7853 {
7854 inst.error = _("missing ]");
7855 return;
7856 }
7857
7858 skip_whitespace (str);
7859
7860 if (*str == '!')
7861 {
7862 if (conflict_reg)
7863 as_warn (_("%s register same as write-back base"),
7864 ((inst.instruction & LOAD_BIT)
7865 ? _("destination") : _("source")));
7866 str++;
7867 inst.instruction |= WRITE_BACK;
7868 }
7869 }
7870 }
7871 else if (*str == '=')
7872 {
f03698e6
RE
7873 if ((inst.instruction & LOAD_BIT) == 0)
7874 {
7875 inst.error = _("invalid pseudo operation");
7876 return;
7877 }
7878
90e4755a 7879 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
7880 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7881 str++;
7882
7883 skip_whitespace (str);
7884
7885 if (my_get_expression (&inst.reloc.exp, &str))
7886 return;
7887
7888 if (inst.reloc.exp.X_op != O_constant
7889 && inst.reloc.exp.X_op != O_symbol)
7890 {
f03698e6 7891 inst.error = _("constant expression expected");
b99bd4ef
NC
7892 return;
7893 }
7894
d8273442 7895 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 7896 {
d8273442
NC
7897 value = validate_immediate (inst.reloc.exp.X_add_number);
7898
7899 if (value != FAIL)
b99bd4ef 7900 {
d8273442
NC
7901 /* This can be done with a mov instruction. */
7902 inst.instruction &= LITERAL_MASK;
7903 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 7904 inst.instruction |= value & 0xfff;
d8273442 7905 end_of_line (str);
b99bd4ef
NC
7906 return;
7907 }
cc8a6dd0 7908
d8273442 7909 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 7910
d8273442 7911 if (value != FAIL)
b99bd4ef 7912 {
d8273442
NC
7913 /* This can be done with a mvn instruction. */
7914 inst.instruction &= LITERAL_MASK;
7915 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 7916 inst.instruction |= value & 0xfff;
d8273442
NC
7917 end_of_line (str);
7918 return;
b99bd4ef 7919 }
b99bd4ef 7920 }
d8273442
NC
7921
7922 /* Insert into literal pool. */
7923 if (add_to_lit_pool () == FAIL)
7924 {
7925 if (!inst.error)
7926 inst.error = _("literal pool insertion failed");
7927 return;
7928 }
7929
7930 /* Change the instruction exp to point to the pool. */
90e4755a
RE
7931 inst.instruction |= HWOFFSET_IMM;
7932 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
7933 inst.reloc.pc_rel = 1;
7934 inst.instruction |= (REG_PC << 16);
7935 pre_inc = 1;
b99bd4ef
NC
7936 }
7937 else
7938 {
7939 if (my_get_expression (&inst.reloc.exp, &str))
7940 return;
7941
90e4755a
RE
7942 inst.instruction |= HWOFFSET_IMM;
7943 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
7944#ifndef TE_WINCE
7945 /* PC rel adjust. */
7946 inst.reloc.exp.X_add_number -= 8;
7947#endif
7948 inst.reloc.pc_rel = 1;
7949 inst.instruction |= (REG_PC << 16);
7950 pre_inc = 1;
7951 }
7952
90e4755a 7953 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 7954 end_of_line (str);
b99bd4ef
NC
7955}
7956
7957static long
7958reg_list (strp)
7959 char ** strp;
7960{
7961 char * str = * strp;
7962 long range = 0;
7963 int another_range;
7964
7965 /* We come back here if we get ranges concatenated by '+' or '|'. */
7966 do
7967 {
7968 another_range = 0;
7969
7970 if (*str == '{')
7971 {
7972 int in_range = 0;
7973 int cur_reg = -1;
7974
7975 str++;
7976 do
7977 {
7978 int reg;
7979
7980 skip_whitespace (str);
7981
7982 if ((reg = reg_required_here (& str, -1)) == FAIL)
7983 return FAIL;
7984
7985 if (in_range)
7986 {
7987 int i;
7988
7989 if (reg <= cur_reg)
7990 {
f03698e6 7991 inst.error = _("bad range in register list");
b99bd4ef
NC
7992 return FAIL;
7993 }
7994
7995 for (i = cur_reg + 1; i < reg; i++)
7996 {
7997 if (range & (1 << i))
7998 as_tsktsk
f03698e6 7999 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8000 i);
8001 else
8002 range |= 1 << i;
8003 }
8004 in_range = 0;
8005 }
8006
8007 if (range & (1 << reg))
f03698e6 8008 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8009 reg);
8010 else if (reg <= cur_reg)
f03698e6 8011 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
8012
8013 range |= 1 << reg;
8014 cur_reg = reg;
8015 }
8016 while (skip_past_comma (&str) != FAIL
8017 || (in_range = 1, *str++ == '-'));
8018 str--;
8019 skip_whitespace (str);
8020
8021 if (*str++ != '}')
8022 {
f03698e6 8023 inst.error = _("missing `}'");
b99bd4ef
NC
8024 return FAIL;
8025 }
8026 }
8027 else
8028 {
8029 expressionS expr;
8030
8031 if (my_get_expression (&expr, &str))
8032 return FAIL;
8033
8034 if (expr.X_op == O_constant)
8035 {
8036 if (expr.X_add_number
8037 != (expr.X_add_number & 0x0000ffff))
8038 {
8039 inst.error = _("invalid register mask");
8040 return FAIL;
8041 }
8042
8043 if ((range & expr.X_add_number) != 0)
8044 {
8045 int regno = range & expr.X_add_number;
8046
8047 regno &= -regno;
8048 regno = (1 << regno) - 1;
8049 as_tsktsk
f03698e6 8050 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
8051 regno);
8052 }
8053
8054 range |= expr.X_add_number;
8055 }
8056 else
8057 {
8058 if (inst.reloc.type != 0)
8059 {
8060 inst.error = _("expression too complex");
8061 return FAIL;
8062 }
8063
8064 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8065 inst.reloc.type = BFD_RELOC_ARM_MULTI;
8066 inst.reloc.pc_rel = 0;
8067 }
8068 }
8069
8070 skip_whitespace (str);
8071
8072 if (*str == '|' || *str == '+')
8073 {
8074 str++;
8075 another_range = 1;
8076 }
8077 }
8078 while (another_range);
8079
8080 *strp = str;
8081 return range;
8082}
8083
8084static void
f2b7cb0a 8085do_ldmstm (str)
b99bd4ef 8086 char * str;
b99bd4ef
NC
8087{
8088 int base_reg;
8089 long range;
8090
8091 skip_whitespace (str);
8092
8093 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8094 return;
8095
8096 if (base_reg == REG_PC)
8097 {
8098 inst.error = _("r15 not allowed as base register");
8099 return;
8100 }
8101
8102 skip_whitespace (str);
8103
8104 if (*str == '!')
8105 {
90e4755a 8106 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
8107 str++;
8108 }
8109
8110 if (skip_past_comma (&str) == FAIL
8111 || (range = reg_list (&str)) == FAIL)
8112 {
8113 if (! inst.error)
8114 inst.error = BAD_ARGS;
8115 return;
8116 }
8117
8118 if (*str == '^')
8119 {
8120 str++;
90e4755a 8121 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
8122 }
8123
6189168b
NC
8124 if (inst.instruction & WRITE_BACK)
8125 {
8126 /* Check for unpredictable uses of writeback. */
8127 if (inst.instruction & LOAD_BIT)
8128 {
8129 /* Not allowed in LDM type 2. */
8130 if ((inst.instruction & LDM_TYPE_2_OR_3)
8131 && ((range & (1 << REG_PC)) == 0))
8132 as_warn (_("writeback of base register is UNPREDICTABLE"));
8133 /* Only allowed if base reg not in list for other types. */
8134 else if (range & (1 << base_reg))
8135 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8136 }
8137 else /* STM. */
8138 {
8139 /* Not allowed for type 2. */
8140 if (inst.instruction & LDM_TYPE_2_OR_3)
8141 as_warn (_("writeback of base register is UNPREDICTABLE"));
8142 /* Only allowed if base reg not in list, or first in list. */
8143 else if ((range & (1 << base_reg))
8144 && (range & ((1 << base_reg) - 1)))
8145 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8146 }
8147 }
61b5f74b 8148
f2b7cb0a 8149 inst.instruction |= range;
b99bd4ef 8150 end_of_line (str);
b99bd4ef
NC
8151}
8152
8153static void
f2b7cb0a 8154do_swi (str)
b99bd4ef 8155 char * str;
b99bd4ef
NC
8156{
8157 skip_whitespace (str);
8158
8159 /* Allow optional leading '#'. */
8160 if (is_immediate_prefix (*str))
8161 str++;
8162
8163 if (my_get_expression (& inst.reloc.exp, & str))
8164 return;
8165
8166 inst.reloc.type = BFD_RELOC_ARM_SWI;
8167 inst.reloc.pc_rel = 0;
b99bd4ef 8168 end_of_line (str);
b99bd4ef
NC
8169}
8170
8171static void
f2b7cb0a 8172do_swap (str)
b99bd4ef 8173 char * str;
b99bd4ef
NC
8174{
8175 int reg;
8176
8177 skip_whitespace (str);
8178
8179 if ((reg = reg_required_here (&str, 12)) == FAIL)
8180 return;
8181
8182 if (reg == REG_PC)
8183 {
8184 inst.error = _("r15 not allowed in swap");
8185 return;
8186 }
8187
8188 if (skip_past_comma (&str) == FAIL
8189 || (reg = reg_required_here (&str, 0)) == FAIL)
8190 {
8191 if (!inst.error)
8192 inst.error = BAD_ARGS;
8193 return;
8194 }
8195
8196 if (reg == REG_PC)
8197 {
8198 inst.error = _("r15 not allowed in swap");
8199 return;
8200 }
8201
8202 if (skip_past_comma (&str) == FAIL
8203 || *str++ != '[')
8204 {
8205 inst.error = BAD_ARGS;
8206 return;
8207 }
8208
8209 skip_whitespace (str);
8210
8211 if ((reg = reg_required_here (&str, 16)) == FAIL)
8212 return;
8213
8214 if (reg == REG_PC)
8215 {
8216 inst.error = BAD_PC;
8217 return;
8218 }
8219
8220 skip_whitespace (str);
8221
8222 if (*str++ != ']')
8223 {
8224 inst.error = _("missing ]");
8225 return;
8226 }
8227
b99bd4ef 8228 end_of_line (str);
b99bd4ef
NC
8229}
8230
8231static void
f2b7cb0a 8232do_branch (str)
b99bd4ef 8233 char * str;
b99bd4ef
NC
8234{
8235 if (my_get_expression (&inst.reloc.exp, &str))
8236 return;
8237
8238#ifdef OBJ_ELF
8239 {
8240 char * save_in;
8241
8242 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8243 required for the instruction. */
8244
8245 /* arm_parse_reloc () works on input_line_pointer.
8246 We actually want to parse the operands to the branch instruction
8247 passed in 'str'. Save the input pointer and restore it later. */
8248 save_in = input_line_pointer;
8249 input_line_pointer = str;
8250 if (inst.reloc.exp.X_op == O_symbol
8251 && *str == '('
8252 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8253 {
8254 inst.reloc.type = BFD_RELOC_ARM_PLT32;
8255 inst.reloc.pc_rel = 0;
8256 /* Modify str to point to after parsed operands, otherwise
8257 end_of_line() will complain about the (PLT) left in str. */
8258 str = input_line_pointer;
8259 }
8260 else
8261 {
8262 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8263 inst.reloc.pc_rel = 1;
8264 }
8265 input_line_pointer = save_in;
8266 }
8267#else
8268 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
8269 inst.reloc.pc_rel = 1;
8270#endif /* OBJ_ELF */
8271
8272 end_of_line (str);
b99bd4ef
NC
8273}
8274
8275static void
f2b7cb0a 8276do_bx (str)
b99bd4ef 8277 char * str;
b99bd4ef
NC
8278{
8279 int reg;
8280
8281 skip_whitespace (str);
8282
8283 if ((reg = reg_required_here (&str, 0)) == FAIL)
8284 {
8285 inst.error = BAD_ARGS;
8286 return;
8287 }
8288
8289 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8290 if (reg == REG_PC)
f03698e6 8291 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
8292
8293 end_of_line (str);
8294}
8295
8296static void
f2b7cb0a 8297do_cdp (str)
b99bd4ef 8298 char * str;
b99bd4ef
NC
8299{
8300 /* Co-processor data operation.
8301 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8302 skip_whitespace (str);
8303
8304 if (co_proc_number (&str) == FAIL)
8305 {
8306 if (!inst.error)
8307 inst.error = BAD_ARGS;
8308 return;
8309 }
8310
8311 if (skip_past_comma (&str) == FAIL
8312 || cp_opc_expr (&str, 20,4) == FAIL)
8313 {
8314 if (!inst.error)
8315 inst.error = BAD_ARGS;
8316 return;
8317 }
8318
8319 if (skip_past_comma (&str) == FAIL
8320 || cp_reg_required_here (&str, 12) == FAIL)
8321 {
8322 if (!inst.error)
8323 inst.error = BAD_ARGS;
8324 return;
8325 }
8326
8327 if (skip_past_comma (&str) == FAIL
8328 || cp_reg_required_here (&str, 16) == FAIL)
8329 {
8330 if (!inst.error)
8331 inst.error = BAD_ARGS;
8332 return;
8333 }
8334
8335 if (skip_past_comma (&str) == FAIL
8336 || cp_reg_required_here (&str, 0) == FAIL)
8337 {
8338 if (!inst.error)
8339 inst.error = BAD_ARGS;
8340 return;
8341 }
8342
8343 if (skip_past_comma (&str) == SUCCESS)
8344 {
8345 if (cp_opc_expr (&str, 5, 3) == FAIL)
8346 {
8347 if (!inst.error)
8348 inst.error = BAD_ARGS;
8349 return;
8350 }
8351 }
8352
8353 end_of_line (str);
b99bd4ef
NC
8354}
8355
8356static void
f2b7cb0a 8357do_lstc (str)
b99bd4ef 8358 char * str;
b99bd4ef
NC
8359{
8360 /* Co-processor register load/store.
8361 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8362
8363 skip_whitespace (str);
8364
8365 if (co_proc_number (&str) == FAIL)
8366 {
8367 if (!inst.error)
8368 inst.error = BAD_ARGS;
8369 return;
8370 }
8371
8372 if (skip_past_comma (&str) == FAIL
8373 || cp_reg_required_here (&str, 12) == FAIL)
8374 {
8375 if (!inst.error)
8376 inst.error = BAD_ARGS;
8377 return;
8378 }
8379
8380 if (skip_past_comma (&str) == FAIL
bfae80f2 8381 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8382 {
8383 if (! inst.error)
8384 inst.error = BAD_ARGS;
8385 return;
8386 }
8387
b99bd4ef 8388 end_of_line (str);
b99bd4ef
NC
8389}
8390
8391static void
f2b7cb0a 8392do_co_reg (str)
b99bd4ef 8393 char * str;
b99bd4ef
NC
8394{
8395 /* Co-processor register transfer.
8396 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8397
8398 skip_whitespace (str);
8399
8400 if (co_proc_number (&str) == FAIL)
8401 {
8402 if (!inst.error)
8403 inst.error = BAD_ARGS;
8404 return;
8405 }
8406
8407 if (skip_past_comma (&str) == FAIL
8408 || cp_opc_expr (&str, 21, 3) == FAIL)
8409 {
8410 if (!inst.error)
8411 inst.error = BAD_ARGS;
8412 return;
8413 }
8414
8415 if (skip_past_comma (&str) == FAIL
8416 || reg_required_here (&str, 12) == FAIL)
8417 {
8418 if (!inst.error)
8419 inst.error = BAD_ARGS;
8420 return;
8421 }
8422
8423 if (skip_past_comma (&str) == FAIL
8424 || cp_reg_required_here (&str, 16) == FAIL)
8425 {
8426 if (!inst.error)
8427 inst.error = BAD_ARGS;
8428 return;
8429 }
8430
8431 if (skip_past_comma (&str) == FAIL
8432 || cp_reg_required_here (&str, 0) == FAIL)
8433 {
8434 if (!inst.error)
8435 inst.error = BAD_ARGS;
8436 return;
8437 }
8438
8439 if (skip_past_comma (&str) == SUCCESS)
8440 {
8441 if (cp_opc_expr (&str, 5, 3) == FAIL)
8442 {
8443 if (!inst.error)
8444 inst.error = BAD_ARGS;
8445 return;
8446 }
8447 }
b99bd4ef
NC
8448
8449 end_of_line (str);
b99bd4ef
NC
8450}
8451
8452static void
f2b7cb0a 8453do_fpa_ctrl (str)
b99bd4ef 8454 char * str;
b99bd4ef
NC
8455{
8456 /* FP control registers.
8457 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8458
8459 skip_whitespace (str);
8460
8461 if (reg_required_here (&str, 12) == FAIL)
8462 {
8463 if (!inst.error)
8464 inst.error = BAD_ARGS;
8465 return;
8466 }
8467
8468 end_of_line (str);
b99bd4ef
NC
8469}
8470
8471static void
f2b7cb0a 8472do_fpa_ldst (str)
b99bd4ef 8473 char * str;
b99bd4ef
NC
8474{
8475 skip_whitespace (str);
8476
b99bd4ef
NC
8477 if (fp_reg_required_here (&str, 12) == FAIL)
8478 {
8479 if (!inst.error)
8480 inst.error = BAD_ARGS;
8481 return;
8482 }
8483
8484 if (skip_past_comma (&str) == FAIL
bfae80f2 8485 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8486 {
8487 if (!inst.error)
8488 inst.error = BAD_ARGS;
8489 return;
8490 }
8491
8492 end_of_line (str);
8493}
8494
8495static void
f2b7cb0a 8496do_fpa_ldmstm (str)
b99bd4ef 8497 char * str;
b99bd4ef
NC
8498{
8499 int num_regs;
8500
8501 skip_whitespace (str);
8502
8503 if (fp_reg_required_here (&str, 12) == FAIL)
8504 {
8505 if (! inst.error)
8506 inst.error = BAD_ARGS;
8507 return;
8508 }
8509
8510 /* Get Number of registers to transfer. */
8511 if (skip_past_comma (&str) == FAIL
8512 || my_get_expression (&inst.reloc.exp, &str))
8513 {
8514 if (! inst.error)
8515 inst.error = _("constant expression expected");
8516 return;
8517 }
8518
8519 if (inst.reloc.exp.X_op != O_constant)
8520 {
f03698e6 8521 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
8522 return;
8523 }
8524
8525 num_regs = inst.reloc.exp.X_add_number;
8526
8527 if (num_regs < 1 || num_regs > 4)
8528 {
8529 inst.error = _("number of registers must be in the range [1:4]");
8530 return;
8531 }
8532
8533 switch (num_regs)
8534 {
8535 case 1:
8536 inst.instruction |= CP_T_X;
8537 break;
8538 case 2:
8539 inst.instruction |= CP_T_Y;
8540 break;
8541 case 3:
8542 inst.instruction |= CP_T_Y | CP_T_X;
8543 break;
8544 case 4:
8545 break;
8546 default:
8547 abort ();
8548 }
8549
e28cd48c 8550 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
8551 {
8552 int reg;
8553 int write_back;
8554 int offset;
8555
8556 /* The instruction specified "ea" or "fd", so we can only accept
8557 [Rn]{!}. The instruction does not really support stacking or
8558 unstacking, so we have to emulate these by setting appropriate
8559 bits and offsets. */
8560 if (skip_past_comma (&str) == FAIL
8561 || *str != '[')
8562 {
8563 if (! inst.error)
8564 inst.error = BAD_ARGS;
8565 return;
8566 }
8567
8568 str++;
8569 skip_whitespace (str);
8570
8571 if ((reg = reg_required_here (&str, 16)) == FAIL)
8572 return;
8573
8574 skip_whitespace (str);
8575
8576 if (*str != ']')
8577 {
8578 inst.error = BAD_ARGS;
8579 return;
8580 }
8581
8582 str++;
8583 if (*str == '!')
8584 {
8585 write_back = 1;
8586 str++;
8587 if (reg == REG_PC)
8588 {
8589 inst.error =
f03698e6 8590 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
8591 return;
8592 }
8593 }
8594 else
8595 write_back = 0;
8596
90e4755a 8597 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
8598 {
8599 /* Pre-decrement. */
8600 offset = 3 * num_regs;
8601 if (write_back)
90e4755a 8602 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8603 }
8604 else
8605 {
8606 /* Post-increment. */
8607 if (write_back)
8608 {
90e4755a 8609 inst.instruction |= CP_T_WB;
b99bd4ef
NC
8610 offset = 3 * num_regs;
8611 }
8612 else
8613 {
8614 /* No write-back, so convert this into a standard pre-increment
8615 instruction -- aesthetically more pleasing. */
90e4755a 8616 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
8617 offset = 0;
8618 }
8619 }
8620
f2b7cb0a 8621 inst.instruction |= offset;
b99bd4ef
NC
8622 }
8623 else if (skip_past_comma (&str) == FAIL
bfae80f2 8624 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
8625 {
8626 if (! inst.error)
8627 inst.error = BAD_ARGS;
8628 return;
8629 }
8630
8631 end_of_line (str);
8632}
8633
8634static void
f2b7cb0a 8635do_fpa_dyadic (str)
b99bd4ef 8636 char * str;
b99bd4ef
NC
8637{
8638 skip_whitespace (str);
8639
b99bd4ef
NC
8640 if (fp_reg_required_here (&str, 12) == FAIL)
8641 {
8642 if (! inst.error)
8643 inst.error = BAD_ARGS;
8644 return;
8645 }
8646
8647 if (skip_past_comma (&str) == FAIL
8648 || fp_reg_required_here (&str, 16) == FAIL)
8649 {
8650 if (! inst.error)
8651 inst.error = BAD_ARGS;
8652 return;
8653 }
8654
8655 if (skip_past_comma (&str) == FAIL
8656 || fp_op2 (&str) == FAIL)
8657 {
8658 if (! inst.error)
8659 inst.error = BAD_ARGS;
8660 return;
8661 }
8662
b99bd4ef 8663 end_of_line (str);
b99bd4ef
NC
8664}
8665
8666static void
f2b7cb0a 8667do_fpa_monadic (str)
b99bd4ef 8668 char * str;
b99bd4ef
NC
8669{
8670 skip_whitespace (str);
8671
b99bd4ef
NC
8672 if (fp_reg_required_here (&str, 12) == FAIL)
8673 {
8674 if (! inst.error)
8675 inst.error = BAD_ARGS;
8676 return;
8677 }
8678
8679 if (skip_past_comma (&str) == FAIL
8680 || fp_op2 (&str) == FAIL)
8681 {
8682 if (! inst.error)
8683 inst.error = BAD_ARGS;
8684 return;
8685 }
8686
b99bd4ef 8687 end_of_line (str);
b99bd4ef
NC
8688}
8689
8690static void
f2b7cb0a 8691do_fpa_cmp (str)
b99bd4ef 8692 char * str;
b99bd4ef
NC
8693{
8694 skip_whitespace (str);
8695
8696 if (fp_reg_required_here (&str, 16) == FAIL)
8697 {
8698 if (! inst.error)
8699 inst.error = BAD_ARGS;
8700 return;
8701 }
8702
8703 if (skip_past_comma (&str) == FAIL
8704 || fp_op2 (&str) == FAIL)
8705 {
8706 if (! inst.error)
8707 inst.error = BAD_ARGS;
8708 return;
8709 }
8710
b99bd4ef 8711 end_of_line (str);
b99bd4ef
NC
8712}
8713
8714static void
f2b7cb0a 8715do_fpa_from_reg (str)
b99bd4ef 8716 char * str;
b99bd4ef
NC
8717{
8718 skip_whitespace (str);
8719
b99bd4ef
NC
8720 if (fp_reg_required_here (&str, 16) == FAIL)
8721 {
8722 if (! inst.error)
8723 inst.error = BAD_ARGS;
8724 return;
8725 }
8726
8727 if (skip_past_comma (&str) == FAIL
8728 || reg_required_here (&str, 12) == FAIL)
8729 {
8730 if (! inst.error)
8731 inst.error = BAD_ARGS;
8732 return;
8733 }
8734
b99bd4ef 8735 end_of_line (str);
b99bd4ef
NC
8736}
8737
8738static void
f2b7cb0a 8739do_fpa_to_reg (str)
b99bd4ef 8740 char * str;
b99bd4ef
NC
8741{
8742 skip_whitespace (str);
8743
8744 if (reg_required_here (&str, 12) == FAIL)
8745 return;
8746
8747 if (skip_past_comma (&str) == FAIL
8748 || fp_reg_required_here (&str, 0) == FAIL)
8749 {
8750 if (! inst.error)
8751 inst.error = BAD_ARGS;
8752 return;
8753 }
8754
b99bd4ef 8755 end_of_line (str);
b99bd4ef
NC
8756}
8757
b99bd4ef 8758static int
bfae80f2
RE
8759vfp_sp_reg_required_here (str, pos)
8760 char **str;
8761 enum vfp_sp_reg_pos pos;
b99bd4ef 8762{
bfae80f2
RE
8763 int reg;
8764 char *start = *str;
b99bd4ef 8765
bfae80f2 8766 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 8767 {
bfae80f2 8768 switch (pos)
b99bd4ef 8769 {
bfae80f2
RE
8770 case VFP_REG_Sd:
8771 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8772 break;
8773
8774 case VFP_REG_Sn:
8775 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8776 break;
8777
8778 case VFP_REG_Sm:
8779 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8780 break;
8781
8782 default:
8783 abort ();
b99bd4ef 8784 }
bfae80f2
RE
8785 return reg;
8786 }
b99bd4ef 8787
bfae80f2
RE
8788 /* In the few cases where we might be able to accept something else
8789 this error can be overridden. */
8790 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8791
8792 /* Restore the start point. */
8793 *str = start;
8794 return FAIL;
8795}
8796
8797static int
8798vfp_dp_reg_required_here (str, pos)
8799 char **str;
f201ccb3 8800 enum vfp_dp_reg_pos pos;
bfae80f2
RE
8801{
8802 int reg;
8803 char *start = *str;
8804
8805 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8806 {
8807 switch (pos)
b99bd4ef 8808 {
bfae80f2
RE
8809 case VFP_REG_Dd:
8810 inst.instruction |= reg << 12;
8811 break;
b99bd4ef 8812
bfae80f2
RE
8813 case VFP_REG_Dn:
8814 inst.instruction |= reg << 16;
8815 break;
8816
8817 case VFP_REG_Dm:
8818 inst.instruction |= reg << 0;
8819 break;
8820
8821 default:
8822 abort ();
8823 }
8824 return reg;
b99bd4ef
NC
8825 }
8826
bfae80f2
RE
8827 /* In the few cases where we might be able to accept something else
8828 this error can be overridden. */
8829 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 8830
bfae80f2
RE
8831 /* Restore the start point. */
8832 *str = start;
8833 return FAIL;
8834}
b99bd4ef
NC
8835
8836static void
bfae80f2
RE
8837do_vfp_sp_monadic (str)
8838 char *str;
b99bd4ef 8839{
b99bd4ef
NC
8840 skip_whitespace (str);
8841
bfae80f2
RE
8842 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8843 return;
8844
8845 if (skip_past_comma (&str) == FAIL
8846 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
8847 {
8848 if (! inst.error)
8849 inst.error = BAD_ARGS;
8850 return;
8851 }
8852
bfae80f2 8853 end_of_line (str);
bfae80f2
RE
8854}
8855
8856static void
8857do_vfp_dp_monadic (str)
8858 char *str;
8859{
8860 skip_whitespace (str);
8861
8862 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8863 return;
8864
8865 if (skip_past_comma (&str) == FAIL
8866 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 8867 {
bfae80f2
RE
8868 if (! inst.error)
8869 inst.error = BAD_ARGS;
8870 return;
b99bd4ef 8871 }
b99bd4ef 8872
bfae80f2 8873 end_of_line (str);
bfae80f2 8874}
b99bd4ef 8875
bfae80f2
RE
8876static void
8877do_vfp_sp_dyadic (str)
8878 char *str;
8879{
8880 skip_whitespace (str);
b99bd4ef 8881
bfae80f2
RE
8882 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8883 return;
b99bd4ef 8884
bfae80f2
RE
8885 if (skip_past_comma (&str) == FAIL
8886 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8887 || skip_past_comma (&str) == FAIL
8888 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 8889 {
bfae80f2
RE
8890 if (! inst.error)
8891 inst.error = BAD_ARGS;
8892 return;
8893 }
b99bd4ef 8894
bfae80f2 8895 end_of_line (str);
bfae80f2 8896}
b99bd4ef 8897
bfae80f2
RE
8898static void
8899do_vfp_dp_dyadic (str)
8900 char *str;
8901{
8902 skip_whitespace (str);
b99bd4ef 8903
bfae80f2
RE
8904 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8905 return;
b99bd4ef 8906
bfae80f2
RE
8907 if (skip_past_comma (&str) == FAIL
8908 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8909 || skip_past_comma (&str) == FAIL
8910 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8911 {
8912 if (! inst.error)
8913 inst.error = BAD_ARGS;
8914 return;
8915 }
b99bd4ef 8916
bfae80f2 8917 end_of_line (str);
bfae80f2 8918}
b99bd4ef 8919
bfae80f2
RE
8920static void
8921do_vfp_reg_from_sp (str)
8922 char *str;
8923{
8924 skip_whitespace (str);
8925
8926 if (reg_required_here (&str, 12) == FAIL)
8927 return;
8928
8929 if (skip_past_comma (&str) == FAIL
8930 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8931 {
8932 if (! inst.error)
8933 inst.error = BAD_ARGS;
8934 return;
8935 }
8936
8937 end_of_line (str);
bfae80f2
RE
8938}
8939
8940static void
8941do_vfp_sp_reg2 (str)
8942 char *str;
8943{
8944 skip_whitespace (str);
8945
8946 if (reg_required_here (&str, 12) == FAIL)
8947 return;
8948
8949 if (skip_past_comma (&str) == FAIL
8950 || reg_required_here (&str, 16) == FAIL
8951 || skip_past_comma (&str) == FAIL)
8952 {
8953 if (! inst.error)
8954 inst.error = BAD_ARGS;
8955 return;
8956 }
8957
8958 /* We require exactly two consecutive SP registers. */
8959 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8960 {
8961 if (! inst.error)
8962 inst.error = _("only two consecutive VFP SP registers allowed here");
8963 }
8964
8965 end_of_line (str);
bfae80f2
RE
8966}
8967
8968static void
8969do_vfp_sp_from_reg (str)
8970 char *str;
8971{
8972 skip_whitespace (str);
8973
8974 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8975 return;
8976
8977 if (skip_past_comma (&str) == FAIL
8978 || reg_required_here (&str, 12) == FAIL)
8979 {
8980 if (! inst.error)
8981 inst.error = BAD_ARGS;
8982 return;
8983 }
8984
8985 end_of_line (str);
bfae80f2
RE
8986}
8987
8988static void
8989do_vfp_reg_from_dp (str)
8990 char *str;
8991{
8992 skip_whitespace (str);
8993
8994 if (reg_required_here (&str, 12) == FAIL)
8995 return;
8996
8997 if (skip_past_comma (&str) == FAIL
8998 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8999 {
9000 if (! inst.error)
9001 inst.error = BAD_ARGS;
9002 return;
9003 }
9004
9005 end_of_line (str);
bfae80f2
RE
9006}
9007
9008static void
9009do_vfp_reg2_from_dp (str)
9010 char *str;
9011{
9012 skip_whitespace (str);
9013
9014 if (reg_required_here (&str, 12) == FAIL)
9015 return;
9016
9017 if (skip_past_comma (&str) == FAIL
9018 || reg_required_here (&str, 16) == FAIL
9019 || skip_past_comma (&str) == FAIL
9020 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9021 {
9022 if (! inst.error)
9023 inst.error = BAD_ARGS;
9024 return;
9025 }
9026
9027 end_of_line (str);
bfae80f2
RE
9028}
9029
9030static void
9031do_vfp_dp_from_reg (str)
9032 char *str;
9033{
9034 skip_whitespace (str);
9035
9036 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9037 return;
9038
9039 if (skip_past_comma (&str) == FAIL
9040 || reg_required_here (&str, 12) == FAIL)
9041 {
9042 if (! inst.error)
9043 inst.error = BAD_ARGS;
9044 return;
9045 }
9046
9047 end_of_line (str);
bfae80f2
RE
9048}
9049
9050static void
9051do_vfp_dp_from_reg2 (str)
9052 char *str;
9053{
9054 skip_whitespace (str);
9055
9056 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9057 return;
9058
9059 if (skip_past_comma (&str) == FAIL
9060 || reg_required_here (&str, 12) == FAIL
9061 || skip_past_comma (&str) == FAIL
9062 || reg_required_here (&str, 16))
9063 {
9064 if (! inst.error)
9065 inst.error = BAD_ARGS;
9066 return;
9067 }
9068
9069 end_of_line (str);
bfae80f2
RE
9070}
9071
9072static const struct vfp_reg *
9073vfp_psr_parse (str)
9074 char **str;
9075{
9076 char *start = *str;
9077 char c;
9078 char *p;
9079 const struct vfp_reg *vreg;
9080
9081 p = start;
9082
9083 /* Find the end of the current token. */
9084 do
9085 {
9086 c = *p++;
9087 }
9088 while (ISALPHA (c));
9089
9090 /* Mark it. */
9091 *--p = 0;
9092
cc8a6dd0 9093 for (vreg = vfp_regs + 0;
bfae80f2
RE
9094 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9095 vreg++)
9096 {
9097 if (strcmp (start, vreg->name) == 0)
9098 {
9099 *p = c;
9100 *str = p;
9101 return vreg;
9102 }
9103 }
9104
9105 *p = c;
9106 return NULL;
9107}
9108
9109static int
9110vfp_psr_required_here (str)
9111 char **str;
9112{
9113 char *start = *str;
9114 const struct vfp_reg *vreg;
9115
9116 vreg = vfp_psr_parse (str);
9117
9118 if (vreg)
9119 {
9120 inst.instruction |= vreg->regno;
9121 return SUCCESS;
9122 }
9123
9124 inst.error = _("VFP system register expected");
9125
9126 *str = start;
9127 return FAIL;
9128}
9129
9130static void
9131do_vfp_reg_from_ctrl (str)
9132 char *str;
9133{
9134 skip_whitespace (str);
9135
9136 if (reg_required_here (&str, 12) == FAIL)
9137 return;
9138
9139 if (skip_past_comma (&str) == FAIL
9140 || vfp_psr_required_here (&str) == FAIL)
9141 {
9142 if (! inst.error)
9143 inst.error = BAD_ARGS;
9144 return;
9145 }
9146
9147 end_of_line (str);
bfae80f2
RE
9148}
9149
9150static void
9151do_vfp_ctrl_from_reg (str)
9152 char *str;
9153{
9154 skip_whitespace (str);
9155
9156 if (vfp_psr_required_here (&str) == FAIL)
9157 return;
9158
9159 if (skip_past_comma (&str) == FAIL
9160 || reg_required_here (&str, 12) == FAIL)
9161 {
9162 if (! inst.error)
9163 inst.error = BAD_ARGS;
9164 return;
9165 }
9166
9167 end_of_line (str);
bfae80f2
RE
9168}
9169
9170static void
9171do_vfp_sp_ldst (str)
9172 char *str;
9173{
9174 skip_whitespace (str);
9175
9176 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9177 {
9178 if (!inst.error)
9179 inst.error = BAD_ARGS;
9180 return;
9181 }
9182
9183 if (skip_past_comma (&str) == FAIL
9184 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9185 {
9186 if (!inst.error)
9187 inst.error = BAD_ARGS;
9188 return;
9189 }
9190
9191 end_of_line (str);
bfae80f2
RE
9192}
9193
9194static void
9195do_vfp_dp_ldst (str)
9196 char *str;
9197{
9198 skip_whitespace (str);
9199
9200 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9201 {
9202 if (!inst.error)
9203 inst.error = BAD_ARGS;
9204 return;
9205 }
9206
9207 if (skip_past_comma (&str) == FAIL
9208 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9209 {
9210 if (!inst.error)
9211 inst.error = BAD_ARGS;
9212 return;
9213 }
9214
9215 end_of_line (str);
bfae80f2
RE
9216}
9217
9218/* Parse and encode a VFP SP register list, storing the initial
9219 register in position POS and returning the range as the result. If
9220 the string is invalid return FAIL (an invalid range). */
9221static long
9222vfp_sp_reg_list (str, pos)
9223 char **str;
9224 enum vfp_sp_reg_pos pos;
9225{
9226 long range = 0;
9227 int base_reg = 0;
9228 int new_base;
9229 long base_bits = 0;
9230 int count = 0;
9231 long tempinst;
9232 unsigned long mask = 0;
9233 int warned = 0;
9234
9235 if (**str != '{')
9236 return FAIL;
9237
9238 (*str)++;
9239 skip_whitespace (*str);
9240
9241 tempinst = inst.instruction;
9242
9243 do
9244 {
9245 inst.instruction = 0;
9246
9247 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9248 return FAIL;
9249
9250 if (count == 0 || base_reg > new_base)
9251 {
9252 base_reg = new_base;
9253 base_bits = inst.instruction;
9254 }
9255
9256 if (mask & (1 << new_base))
9257 {
9258 inst.error = _("invalid register list");
9259 return FAIL;
9260 }
9261
9262 if ((mask >> new_base) != 0 && ! warned)
9263 {
9264 as_tsktsk (_("register list not in ascending order"));
9265 warned = 1;
9266 }
9267
9268 mask |= 1 << new_base;
9269 count++;
9270
9271 skip_whitespace (*str);
9272
9273 if (**str == '-') /* We have the start of a range expression */
9274 {
9275 int high_range;
9276
9277 (*str)++;
9278
9279 if ((high_range
9280 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9281 == FAIL)
9282 {
9283 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9284 return FAIL;
9285 }
9286
9287 if (high_range <= new_base)
9288 {
9289 inst.error = _("register range not in ascending order");
9290 return FAIL;
9291 }
9292
9293 for (new_base++; new_base <= high_range; new_base++)
9294 {
9295 if (mask & (1 << new_base))
9296 {
9297 inst.error = _("invalid register list");
9298 return FAIL;
9299 }
9300
9301 mask |= 1 << new_base;
9302 count++;
9303 }
9304 }
9305 }
9306 while (skip_past_comma (str) != FAIL);
9307
9308 if (**str != '}')
9309 {
9310 inst.error = _("invalid register list");
9311 return FAIL;
9312 }
9313
9314 (*str)++;
9315
9316 range = count;
9317
9318 /* Sanity check -- should have raised a parse error above. */
9319 if (count == 0 || count > 32)
c62e1cc3 9320 abort ();
bfae80f2
RE
9321
9322 /* Final test -- the registers must be consecutive. */
9323 while (count--)
9324 {
9325 if ((mask & (1 << base_reg++)) == 0)
9326 {
9327 inst.error = _("non-contiguous register range");
9328 return FAIL;
9329 }
9330 }
9331
9332 inst.instruction = tempinst | base_bits;
9333 return range;
9334}
9335
9336static long
9337vfp_dp_reg_list (str)
9338 char **str;
9339{
9340 long range = 0;
9341 int base_reg = 0;
9342 int new_base;
9343 int count = 0;
9344 long tempinst;
9345 unsigned long mask = 0;
9346 int warned = 0;
9347
9348 if (**str != '{')
9349 return FAIL;
9350
9351 (*str)++;
9352 skip_whitespace (*str);
9353
9354 tempinst = inst.instruction;
9355
9356 do
9357 {
9358 inst.instruction = 0;
9359
9360 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9361 return FAIL;
9362
9363 if (count == 0 || base_reg > new_base)
9364 {
9365 base_reg = new_base;
9366 range = inst.instruction;
9367 }
9368
9369 if (mask & (1 << new_base))
9370 {
9371 inst.error = _("invalid register list");
9372 return FAIL;
9373 }
9374
9375 if ((mask >> new_base) != 0 && ! warned)
9376 {
9377 as_tsktsk (_("register list not in ascending order"));
9378 warned = 1;
9379 }
9380
9381 mask |= 1 << new_base;
9382 count++;
9383
9384 skip_whitespace (*str);
9385
9386 if (**str == '-') /* We have the start of a range expression */
9387 {
9388 int high_range;
9389
9390 (*str)++;
9391
9392 if ((high_range
9393 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9394 == FAIL)
9395 {
9396 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9397 return FAIL;
9398 }
9399
9400 if (high_range <= new_base)
9401 {
9402 inst.error = _("register range not in ascending order");
9403 return FAIL;
9404 }
9405
9406 for (new_base++; new_base <= high_range; new_base++)
9407 {
9408 if (mask & (1 << new_base))
9409 {
9410 inst.error = _("invalid register list");
9411 return FAIL;
9412 }
9413
9414 mask |= 1 << new_base;
9415 count++;
9416 }
9417 }
9418 }
9419 while (skip_past_comma (str) != FAIL);
9420
9421 if (**str != '}')
9422 {
9423 inst.error = _("invalid register list");
9424 return FAIL;
9425 }
9426
9427 (*str)++;
9428
9429 range |= 2 * count;
9430
9431 /* Sanity check -- should have raised a parse error above. */
9432 if (count == 0 || count > 16)
c62e1cc3 9433 abort ();
bfae80f2
RE
9434
9435 /* Final test -- the registers must be consecutive. */
9436 while (count--)
9437 {
9438 if ((mask & (1 << base_reg++)) == 0)
9439 {
9440 inst.error = _("non-contiguous register range");
9441 return FAIL;
9442 }
9443 }
9444
9445 inst.instruction = tempinst;
9446 return range;
9447}
9448
9449static void
c62e1cc3 9450vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
9451 char *str;
9452 enum vfp_ldstm_type ldstm_type;
9453{
9454 long range;
9455
9456 skip_whitespace (str);
9457
9458 if (reg_required_here (&str, 16) == FAIL)
9459 return;
9460
9461 skip_whitespace (str);
9462
9463 if (*str == '!')
9464 {
9465 inst.instruction |= WRITE_BACK;
9466 str++;
9467 }
9468 else if (ldstm_type != VFP_LDSTMIA)
9469 {
9470 inst.error = _("this addressing mode requires base-register writeback");
9471 return;
9472 }
9473
9474 if (skip_past_comma (&str) == FAIL
9475 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9476 {
9477 if (!inst.error)
9478 inst.error = BAD_ARGS;
9479 return;
9480 }
9481
9482 inst.instruction |= range;
9483 end_of_line (str);
9484}
9485
9486static void
c62e1cc3 9487vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
9488 char *str;
9489 enum vfp_ldstm_type ldstm_type;
9490{
9491 long range;
9492
9493 skip_whitespace (str);
9494
9495 if (reg_required_here (&str, 16) == FAIL)
9496 return;
9497
9498 skip_whitespace (str);
9499
9500 if (*str == '!')
9501 {
9502 inst.instruction |= WRITE_BACK;
9503 str++;
9504 }
9505 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9506 {
9507 inst.error = _("this addressing mode requires base-register writeback");
9508 return;
9509 }
9510
9511 if (skip_past_comma (&str) == FAIL
9512 || (range = vfp_dp_reg_list (&str)) == FAIL)
9513 {
9514 if (!inst.error)
9515 inst.error = BAD_ARGS;
9516 return;
9517 }
9518
9519 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9520 range += 1;
9521
9522 inst.instruction |= range;
9523 end_of_line (str);
9524}
9525
9526static void
9527do_vfp_sp_ldstmia (str)
9528 char *str;
9529{
9530 vfp_sp_ldstm (str, VFP_LDSTMIA);
9531}
9532
9533static void
9534do_vfp_sp_ldstmdb (str)
9535 char *str;
9536{
9537 vfp_sp_ldstm (str, VFP_LDSTMDB);
9538}
9539
9540static void
9541do_vfp_dp_ldstmia (str)
9542 char *str;
9543{
9544 vfp_dp_ldstm (str, VFP_LDSTMIA);
9545}
9546
9547static void
9548do_vfp_dp_ldstmdb (str)
9549 char *str;
9550{
9551 vfp_dp_ldstm (str, VFP_LDSTMDB);
9552}
9553
9554static void
9555do_vfp_xp_ldstmia (str)
9556 char *str;
9557{
9558 vfp_dp_ldstm (str, VFP_LDSTMIAX);
9559}
9560
9561static void
9562do_vfp_xp_ldstmdb (str)
9563 char *str;
9564{
9565 vfp_dp_ldstm (str, VFP_LDSTMDBX);
9566}
9567
9568static void
9569do_vfp_sp_compare_z (str)
9570 char *str;
9571{
9572 skip_whitespace (str);
9573
9574 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9575 {
9576 if (!inst.error)
9577 inst.error = BAD_ARGS;
9578 return;
9579 }
9580
9581 end_of_line (str);
bfae80f2
RE
9582}
9583
9584static void
9585do_vfp_dp_compare_z (str)
9586 char *str;
9587{
9588 skip_whitespace (str);
9589
9590 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9591 {
9592 if (!inst.error)
9593 inst.error = BAD_ARGS;
9594 return;
9595 }
9596
9597 end_of_line (str);
bfae80f2
RE
9598}
9599
9600static void
9601do_vfp_dp_sp_cvt (str)
9602 char *str;
9603{
9604 skip_whitespace (str);
9605
9606 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9607 return;
9608
9609 if (skip_past_comma (&str) == FAIL
9610 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9611 {
9612 if (! inst.error)
9613 inst.error = BAD_ARGS;
9614 return;
9615 }
9616
9617 end_of_line (str);
bfae80f2
RE
9618}
9619
9620static void
9621do_vfp_sp_dp_cvt (str)
9622 char *str;
9623{
9624 skip_whitespace (str);
9625
9626 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9627 return;
9628
9629 if (skip_past_comma (&str) == FAIL
9630 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9631 {
9632 if (! inst.error)
9633 inst.error = BAD_ARGS;
9634 return;
9635 }
9636
9637 end_of_line (str);
bfae80f2
RE
9638}
9639
9640/* Thumb specific routines. */
9641
9642/* Parse and validate that a register is of the right form, this saves
9643 repeated checking of this information in many similar cases.
9644 Unlike the 32-bit case we do not insert the register into the opcode
9645 here, since the position is often unknown until the full instruction
9646 has been parsed. */
9647
9648static int
9649thumb_reg (strp, hi_lo)
9650 char ** strp;
9651 int hi_lo;
9652{
9653 int reg;
9654
9655 if ((reg = reg_required_here (strp, -1)) == FAIL)
9656 return FAIL;
9657
9658 switch (hi_lo)
9659 {
9660 case THUMB_REG_LO:
9661 if (reg > 7)
9662 {
9663 inst.error = _("lo register required");
9664 return FAIL;
9665 }
9666 break;
9667
9668 case THUMB_REG_HI:
9669 if (reg < 8)
9670 {
9671 inst.error = _("hi register required");
9672 return FAIL;
9673 }
9674 break;
9675
9676 default:
9677 break;
9678 }
9679
9680 return reg;
9681}
9682
9683/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9684 was SUB. */
9685
9686static void
9687thumb_add_sub (str, subtract)
9688 char * str;
9689 int subtract;
9690{
9691 int Rd, Rs, Rn = FAIL;
9692
9693 skip_whitespace (str);
9694
9695 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9696 || skip_past_comma (&str) == FAIL)
9697 {
9698 if (! inst.error)
9699 inst.error = BAD_ARGS;
9700 return;
9701 }
9702
9703 if (is_immediate_prefix (*str))
9704 {
9705 Rs = Rd;
9706 str++;
9707 if (my_get_expression (&inst.reloc.exp, &str))
9708 return;
9709 }
9710 else
9711 {
9712 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9713 return;
9714
9715 if (skip_past_comma (&str) == FAIL)
9716 {
9717 /* Two operand format, shuffle the registers
9718 and pretend there are 3. */
9719 Rn = Rs;
9720 Rs = Rd;
9721 }
9722 else if (is_immediate_prefix (*str))
9723 {
9724 str++;
9725 if (my_get_expression (&inst.reloc.exp, &str))
9726 return;
9727 }
9728 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9729 return;
9730 }
9731
9732 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9733 for the latter case, EXPR contains the immediate that was found. */
9734 if (Rn != FAIL)
9735 {
9736 /* All register format. */
9737 if (Rd > 7 || Rs > 7 || Rn > 7)
9738 {
9739 if (Rs != Rd)
9740 {
9741 inst.error = _("dest and source1 must be the same register");
9742 return;
9743 }
9744
9745 /* Can't do this for SUB. */
9746 if (subtract)
9747 {
9748 inst.error = _("subtract valid only on lo regs");
9749 return;
9750 }
9751
9752 inst.instruction = (T_OPCODE_ADD_HI
9753 | (Rd > 7 ? THUMB_H1 : 0)
9754 | (Rn > 7 ? THUMB_H2 : 0));
9755 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9756 }
9757 else
9758 {
9759 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9760 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9761 }
9762 }
9763 else
9764 {
9765 /* Immediate expression, now things start to get nasty. */
9766
9767 /* First deal with HI regs, only very restricted cases allowed:
9768 Adjusting SP, and using PC or SP to get an address. */
9769 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9770 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9771 {
9772 inst.error = _("invalid Hi register with immediate");
9773 return;
9774 }
9775
9776 if (inst.reloc.exp.X_op != O_constant)
9777 {
9778 /* Value isn't known yet, all we can do is store all the fragments
9779 we know about in the instruction and let the reloc hacking
9780 work it all out. */
9781 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9782 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9783 }
9784 else
9785 {
9786 int offset = inst.reloc.exp.X_add_number;
9787
9788 if (subtract)
358b94bd 9789 offset = - offset;
bfae80f2
RE
9790
9791 if (offset < 0)
9792 {
358b94bd 9793 offset = - offset;
bfae80f2
RE
9794 subtract = 1;
9795
9796 /* Quick check, in case offset is MIN_INT. */
9797 if (offset < 0)
9798 {
9799 inst.error = _("immediate value out of range");
9800 return;
9801 }
9802 }
358b94bd
NC
9803 /* Note - you cannot convert a subtract of 0 into an
9804 add of 0 because the carry flag is set differently. */
9805 else if (offset > 0)
bfae80f2
RE
9806 subtract = 0;
9807
9808 if (Rd == REG_SP)
9809 {
9810 if (offset & ~0x1fc)
9811 {
9812 inst.error = _("invalid immediate value for stack adjust");
9813 return;
b99bd4ef
NC
9814 }
9815 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9816 inst.instruction |= offset >> 2;
9817 }
9818 else if (Rs == REG_PC || Rs == REG_SP)
9819 {
9820 if (subtract
9821 || (offset & ~0x3fc))
9822 {
9823 inst.error = _("invalid immediate for address calculation");
9824 return;
9825 }
9826 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9827 : T_OPCODE_ADD_SP);
9828 inst.instruction |= (Rd << 8) | (offset >> 2);
9829 }
9830 else if (Rs == Rd)
9831 {
9832 if (offset & ~0xff)
9833 {
9834 inst.error = _("immediate value out of range");
9835 return;
9836 }
9837 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9838 inst.instruction |= (Rd << 8) | offset;
9839 }
9840 else
9841 {
9842 if (offset & ~0x7)
9843 {
9844 inst.error = _("immediate value out of range");
9845 return;
9846 }
9847 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9848 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9849 }
9850 }
9851 }
9852
9853 end_of_line (str);
9854}
9855
9856static void
9857thumb_shift (str, shift)
9858 char * str;
9859 int shift;
9860{
9861 int Rd, Rs, Rn = FAIL;
9862
9863 skip_whitespace (str);
9864
9865 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9866 || skip_past_comma (&str) == FAIL)
9867 {
9868 if (! inst.error)
9869 inst.error = BAD_ARGS;
9870 return;
9871 }
9872
9873 if (is_immediate_prefix (*str))
9874 {
9875 /* Two operand immediate format, set Rs to Rd. */
9876 Rs = Rd;
9877 str ++;
9878 if (my_get_expression (&inst.reloc.exp, &str))
9879 return;
9880 }
9881 else
9882 {
9883 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9884 return;
9885
9886 if (skip_past_comma (&str) == FAIL)
9887 {
9888 /* Two operand format, shuffle the registers
9889 and pretend there are 3. */
9890 Rn = Rs;
9891 Rs = Rd;
9892 }
9893 else if (is_immediate_prefix (*str))
9894 {
9895 str++;
9896 if (my_get_expression (&inst.reloc.exp, &str))
9897 return;
9898 }
9899 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9900 return;
9901 }
9902
9903 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9904 for the latter case, EXPR contains the immediate that was found. */
9905
9906 if (Rn != FAIL)
9907 {
9908 if (Rs != Rd)
9909 {
9910 inst.error = _("source1 and dest must be same register");
9911 return;
9912 }
9913
9914 switch (shift)
9915 {
9916 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9917 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9918 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9919 }
9920
9921 inst.instruction |= Rd | (Rn << 3);
9922 }
9923 else
9924 {
9925 switch (shift)
9926 {
9927 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9928 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9929 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9930 }
9931
9932 if (inst.reloc.exp.X_op != O_constant)
9933 {
9934 /* Value isn't known yet, create a dummy reloc and let reloc
9935 hacking fix it up. */
9936 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9937 }
9938 else
9939 {
9940 unsigned shift_value = inst.reloc.exp.X_add_number;
9941
9942 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9943 {
f03698e6 9944 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
9945 return;
9946 }
9947
9948 /* Shifts of zero are handled by converting to LSL. */
9949 if (shift_value == 0)
9950 inst.instruction = T_OPCODE_LSL_I;
9951
9952 /* Shifts of 32 are encoded as a shift of zero. */
9953 if (shift_value == 32)
9954 shift_value = 0;
9955
9956 inst.instruction |= shift_value << 6;
9957 }
9958
9959 inst.instruction |= Rd | (Rs << 3);
9960 }
9961
9962 end_of_line (str);
9963}
9964
9965static void
9966thumb_mov_compare (str, move)
9967 char * str;
9968 int move;
9969{
9970 int Rd, Rs = FAIL;
9971
9972 skip_whitespace (str);
9973
9974 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9975 || skip_past_comma (&str) == FAIL)
9976 {
9977 if (! inst.error)
9978 inst.error = BAD_ARGS;
9979 return;
9980 }
9981
09d92015 9982 if (move != THUMB_CPY && is_immediate_prefix (*str))
b99bd4ef
NC
9983 {
9984 str++;
9985 if (my_get_expression (&inst.reloc.exp, &str))
9986 return;
9987 }
9988 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9989 return;
9990
9991 if (Rs != FAIL)
9992 {
09d92015 9993 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
b99bd4ef
NC
9994 {
9995 if (move == THUMB_MOVE)
9996 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
9997 since a MOV instruction produces unpredictable results. */
9998 inst.instruction = T_OPCODE_ADD_I3;
9999 else
10000 inst.instruction = T_OPCODE_CMP_LR;
10001 inst.instruction |= Rd | (Rs << 3);
10002 }
10003 else
10004 {
10005 if (move == THUMB_MOVE)
10006 inst.instruction = T_OPCODE_MOV_HR;
09d92015 10007 else if (move != THUMB_CPY)
b99bd4ef
NC
10008 inst.instruction = T_OPCODE_CMP_HR;
10009
10010 if (Rd > 7)
10011 inst.instruction |= THUMB_H1;
10012
10013 if (Rs > 7)
10014 inst.instruction |= THUMB_H2;
10015
10016 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10017 }
10018 }
10019 else
10020 {
10021 if (Rd > 7)
10022 {
10023 inst.error = _("only lo regs allowed with immediate");
10024 return;
10025 }
10026
10027 if (move == THUMB_MOVE)
10028 inst.instruction = T_OPCODE_MOV_I8;
10029 else
10030 inst.instruction = T_OPCODE_CMP_I8;
10031
10032 inst.instruction |= Rd << 8;
10033
10034 if (inst.reloc.exp.X_op != O_constant)
10035 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10036 else
10037 {
10038 unsigned value = inst.reloc.exp.X_add_number;
10039
10040 if (value > 255)
10041 {
10042 inst.error = _("invalid immediate");
10043 return;
10044 }
10045
10046 inst.instruction |= value;
10047 }
10048 }
10049
10050 end_of_line (str);
10051}
10052
10053static void
10054thumb_load_store (str, load_store, size)
10055 char * str;
10056 int load_store;
10057 int size;
10058{
10059 int Rd, Rb, Ro = FAIL;
10060
10061 skip_whitespace (str);
10062
10063 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10064 || skip_past_comma (&str) == FAIL)
10065 {
10066 if (! inst.error)
10067 inst.error = BAD_ARGS;
10068 return;
10069 }
10070
10071 if (*str == '[')
10072 {
10073 str++;
10074 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10075 return;
10076
10077 if (skip_past_comma (&str) != FAIL)
10078 {
10079 if (is_immediate_prefix (*str))
10080 {
10081 str++;
10082 if (my_get_expression (&inst.reloc.exp, &str))
10083 return;
10084 }
10085 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10086 return;
10087 }
10088 else
10089 {
10090 inst.reloc.exp.X_op = O_constant;
10091 inst.reloc.exp.X_add_number = 0;
10092 }
10093
10094 if (*str != ']')
10095 {
10096 inst.error = _("expected ']'");
10097 return;
10098 }
10099 str++;
10100 }
10101 else if (*str == '=')
10102 {
f03698e6
RE
10103 if (load_store != THUMB_LOAD)
10104 {
10105 inst.error = _("invalid pseudo operation");
10106 return;
10107 }
10108
b99bd4ef
NC
10109 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10110 str++;
10111
10112 skip_whitespace (str);
10113
10114 if (my_get_expression (& inst.reloc.exp, & str))
10115 return;
10116
10117 end_of_line (str);
10118
10119 if ( inst.reloc.exp.X_op != O_constant
10120 && inst.reloc.exp.X_op != O_symbol)
10121 {
10122 inst.error = "Constant expression expected";
10123 return;
10124 }
10125
10126 if (inst.reloc.exp.X_op == O_constant
10127 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10128 {
10129 /* This can be done with a mov instruction. */
10130
10131 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
10132 inst.instruction |= inst.reloc.exp.X_add_number;
10133 return;
10134 }
10135
10136 /* Insert into literal pool. */
10137 if (add_to_lit_pool () == FAIL)
10138 {
10139 if (!inst.error)
10140 inst.error = "literal pool insertion failed";
10141 return;
10142 }
10143
10144 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10145 inst.reloc.pc_rel = 1;
10146 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10147 /* Adjust ARM pipeline offset to Thumb. */
10148 inst.reloc.exp.X_add_number += 4;
10149
10150 return;
10151 }
10152 else
10153 {
10154 if (my_get_expression (&inst.reloc.exp, &str))
10155 return;
10156
10157 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10158 inst.reloc.pc_rel = 1;
10159 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
10160 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10161 end_of_line (str);
10162 return;
10163 }
10164
10165 if (Rb == REG_PC || Rb == REG_SP)
10166 {
10167 if (size != THUMB_WORD)
10168 {
10169 inst.error = _("byte or halfword not valid for base register");
10170 return;
10171 }
10172 else if (Rb == REG_PC && load_store != THUMB_LOAD)
10173 {
f03698e6 10174 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
10175 return;
10176 }
10177 else if (Ro != FAIL)
10178 {
f03698e6 10179 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
10180 return;
10181 }
10182
10183 if (Rb == REG_PC)
10184 inst.instruction = T_OPCODE_LDR_PC;
10185 else if (load_store == THUMB_LOAD)
10186 inst.instruction = T_OPCODE_LDR_SP;
10187 else
10188 inst.instruction = T_OPCODE_STR_SP;
10189
10190 inst.instruction |= Rd << 8;
10191 if (inst.reloc.exp.X_op == O_constant)
10192 {
10193 unsigned offset = inst.reloc.exp.X_add_number;
10194
10195 if (offset & ~0x3fc)
10196 {
10197 inst.error = _("invalid offset");
10198 return;
10199 }
10200
10201 inst.instruction |= offset >> 2;
10202 }
10203 else
10204 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10205 }
10206 else if (Rb > 7)
10207 {
10208 inst.error = _("invalid base register in load/store");
10209 return;
10210 }
10211 else if (Ro == FAIL)
10212 {
10213 /* Immediate offset. */
10214 if (size == THUMB_WORD)
10215 inst.instruction = (load_store == THUMB_LOAD
10216 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10217 else if (size == THUMB_HALFWORD)
10218 inst.instruction = (load_store == THUMB_LOAD
10219 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10220 else
10221 inst.instruction = (load_store == THUMB_LOAD
10222 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10223
10224 inst.instruction |= Rd | (Rb << 3);
10225
10226 if (inst.reloc.exp.X_op == O_constant)
10227 {
10228 unsigned offset = inst.reloc.exp.X_add_number;
10229
10230 if (offset & ~(0x1f << size))
10231 {
f03698e6 10232 inst.error = _("invalid offset");
b99bd4ef
NC
10233 return;
10234 }
10235 inst.instruction |= (offset >> size) << 6;
10236 }
10237 else
10238 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10239 }
10240 else
10241 {
10242 /* Register offset. */
10243 if (size == THUMB_WORD)
10244 inst.instruction = (load_store == THUMB_LOAD
10245 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10246 else if (size == THUMB_HALFWORD)
10247 inst.instruction = (load_store == THUMB_LOAD
10248 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10249 else
10250 inst.instruction = (load_store == THUMB_LOAD
10251 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10252
10253 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10254 }
10255
10256 end_of_line (str);
10257}
10258
404ff6b5
AH
10259/* A register must be given at this point.
10260
404ff6b5
AH
10261 Shift is the place to put it in inst.instruction.
10262
404ff6b5
AH
10263 Restores input start point on err.
10264 Returns the reg#, or FAIL. */
10265
10266static int
63e63b07 10267mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
10268 char ** str;
10269 int shift;
6c43fab6 10270 enum arm_reg_type regtype;
404ff6b5 10271{
6c43fab6
RE
10272 int reg;
10273 char *start = *str;
404ff6b5 10274
6c43fab6 10275 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 10276 {
404ff6b5
AH
10277 if (shift >= 0)
10278 inst.instruction |= reg << shift;
10279
6c43fab6 10280 return reg;
404ff6b5
AH
10281 }
10282
6c43fab6 10283 /* Restore the start point. */
404ff6b5 10284 *str = start;
cc8a6dd0 10285
404ff6b5
AH
10286 /* In the few cases where we might be able to accept something else
10287 this error can be overridden. */
6c43fab6 10288 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 10289
404ff6b5
AH
10290 return FAIL;
10291}
10292
63e63b07 10293/* Cirrus Maverick Instructions. */
404ff6b5
AH
10294
10295/* Wrapper functions. */
10296
10297static void
63e63b07 10298do_mav_binops_1a (str)
6c43fab6
RE
10299 char * str;
10300{
63e63b07 10301 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
10302}
10303
10304static void
63e63b07 10305do_mav_binops_1b (str)
6c43fab6
RE
10306 char * str;
10307{
63e63b07 10308 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
10309}
10310
10311static void
63e63b07 10312do_mav_binops_1c (str)
404ff6b5 10313 char * str;
404ff6b5 10314{
63e63b07 10315 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
10316}
10317
10318static void
63e63b07 10319do_mav_binops_1d (str)
404ff6b5 10320 char * str;
404ff6b5 10321{
63e63b07 10322 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
10323}
10324
10325static void
63e63b07 10326do_mav_binops_1e (str)
404ff6b5 10327 char * str;
404ff6b5 10328{
63e63b07 10329 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
10330}
10331
10332static void
63e63b07 10333do_mav_binops_1f (str)
404ff6b5 10334 char * str;
404ff6b5 10335{
63e63b07 10336 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
10337}
10338
10339static void
63e63b07 10340do_mav_binops_1g (str)
404ff6b5 10341 char * str;
404ff6b5 10342{
63e63b07 10343 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
10344}
10345
10346static void
63e63b07 10347do_mav_binops_1h (str)
404ff6b5 10348 char * str;
404ff6b5 10349{
63e63b07 10350 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
10351}
10352
6c43fab6 10353static void
63e63b07 10354do_mav_binops_1i (str)
6c43fab6
RE
10355 char * str;
10356{
63e63b07 10357 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
10358}
10359
10360static void
63e63b07 10361do_mav_binops_1j (str)
6c43fab6
RE
10362 char * str;
10363{
63e63b07 10364 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
10365}
10366
10367static void
63e63b07 10368do_mav_binops_1k (str)
6c43fab6
RE
10369 char * str;
10370{
63e63b07 10371 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
10372}
10373
10374static void
63e63b07 10375do_mav_binops_1l (str)
6c43fab6
RE
10376 char * str;
10377{
63e63b07 10378 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
10379}
10380
10381static void
63e63b07 10382do_mav_binops_1m (str)
6c43fab6
RE
10383 char * str;
10384{
63e63b07 10385 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
10386}
10387
10388static void
63e63b07 10389do_mav_binops_1n (str)
6c43fab6
RE
10390 char * str;
10391{
63e63b07 10392 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10393}
10394
10395static void
63e63b07 10396do_mav_binops_1o (str)
6c43fab6
RE
10397 char * str;
10398{
63e63b07 10399 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10400}
10401
10402static void
63e63b07 10403do_mav_binops_2a (str)
6c43fab6
RE
10404 char * str;
10405{
63e63b07 10406 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
10407}
10408
10409static void
63e63b07 10410do_mav_binops_2b (str)
6c43fab6
RE
10411 char * str;
10412{
63e63b07 10413 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
10414}
10415
10416static void
63e63b07 10417do_mav_binops_2c (str)
6c43fab6
RE
10418 char * str;
10419{
63e63b07 10420 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10421}
10422
10423static void
63e63b07 10424do_mav_binops_3a (str)
6c43fab6
RE
10425 char * str;
10426{
63e63b07 10427 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
10428}
10429
10430static void
63e63b07 10431do_mav_binops_3b (str)
6c43fab6
RE
10432 char * str;
10433{
63e63b07 10434 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
10435}
10436
10437static void
63e63b07 10438do_mav_binops_3c (str)
6c43fab6
RE
10439 char * str;
10440{
63e63b07 10441 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
10442}
10443
10444static void
63e63b07 10445do_mav_binops_3d (str)
6c43fab6
RE
10446 char * str;
10447{
63e63b07 10448 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
10449}
10450
10451static void
63e63b07 10452do_mav_triple_4a (str)
6c43fab6
RE
10453 char * str;
10454{
63e63b07 10455 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
10456}
10457
10458static void
63e63b07 10459do_mav_triple_4b (str)
6c43fab6
RE
10460 char * str;
10461{
63e63b07 10462 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
10463}
10464
10465static void
63e63b07 10466do_mav_triple_5a (str)
6c43fab6
RE
10467 char * str;
10468{
63e63b07 10469 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10470}
10471
10472static void
63e63b07 10473do_mav_triple_5b (str)
6c43fab6
RE
10474 char * str;
10475{
63e63b07 10476 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10477}
10478
10479static void
63e63b07 10480do_mav_triple_5c (str)
6c43fab6
RE
10481 char * str;
10482{
63e63b07 10483 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10484}
10485
10486static void
63e63b07 10487do_mav_triple_5d (str)
6c43fab6
RE
10488 char * str;
10489{
63e63b07 10490 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10491}
10492
10493static void
63e63b07 10494do_mav_triple_5e (str)
6c43fab6
RE
10495 char * str;
10496{
63e63b07 10497 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
10498}
10499
10500static void
63e63b07 10501do_mav_triple_5f (str)
6c43fab6
RE
10502 char * str;
10503{
63e63b07 10504 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
10505}
10506
10507static void
63e63b07 10508do_mav_triple_5g (str)
6c43fab6
RE
10509 char * str;
10510{
63e63b07 10511 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
10512}
10513
10514static void
63e63b07 10515do_mav_triple_5h (str)
6c43fab6
RE
10516 char * str;
10517{
63e63b07 10518 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
10519}
10520
10521static void
63e63b07 10522do_mav_quad_6a (str)
6c43fab6
RE
10523 char * str;
10524{
63e63b07 10525 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
10526 REG_TYPE_MVFX);
10527}
10528
10529static void
63e63b07 10530do_mav_quad_6b (str)
6c43fab6
RE
10531 char * str;
10532{
63e63b07 10533 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
10534 REG_TYPE_MVFX);
10535}
10536
cc8a6dd0 10537/* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
404ff6b5 10538static void
63e63b07 10539do_mav_dspsc_1 (str)
404ff6b5 10540 char * str;
404ff6b5 10541{
6c43fab6
RE
10542 skip_whitespace (str);
10543
10544 /* cfmvsc32. */
63e63b07 10545 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 10546 || skip_past_comma (&str) == FAIL
63e63b07 10547 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
6c43fab6
RE
10548 {
10549 if (!inst.error)
10550 inst.error = BAD_ARGS;
10551
10552 return;
10553 }
10554
10555 end_of_line (str);
404ff6b5
AH
10556}
10557
6c43fab6 10558/* cfmv32sc<cond> MVFX[15:0],DSPSC. */
404ff6b5 10559static void
63e63b07 10560do_mav_dspsc_2 (str)
404ff6b5 10561 char * str;
404ff6b5 10562{
6c43fab6
RE
10563 skip_whitespace (str);
10564
10565 /* cfmv32sc. */
63e63b07 10566 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
6c43fab6 10567 || skip_past_comma (&str) == FAIL
63e63b07 10568 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
10569 {
10570 if (!inst.error)
10571 inst.error = BAD_ARGS;
10572
10573 return;
10574 }
10575
10576 end_of_line (str);
404ff6b5
AH
10577}
10578
10579static void
63e63b07 10580do_mav_shift_1 (str)
404ff6b5 10581 char * str;
404ff6b5 10582{
63e63b07 10583 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
10584}
10585
10586static void
63e63b07 10587do_mav_shift_2 (str)
404ff6b5 10588 char * str;
404ff6b5 10589{
63e63b07 10590 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
10591}
10592
10593static void
63e63b07 10594do_mav_ldst_1 (str)
404ff6b5 10595 char * str;
404ff6b5 10596{
63e63b07 10597 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
10598}
10599
10600static void
63e63b07 10601do_mav_ldst_2 (str)
404ff6b5 10602 char * str;
404ff6b5 10603{
63e63b07 10604 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
10605}
10606
10607static void
63e63b07 10608do_mav_ldst_3 (str)
404ff6b5 10609 char * str;
404ff6b5 10610{
63e63b07 10611 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
10612}
10613
10614static void
63e63b07 10615do_mav_ldst_4 (str)
404ff6b5 10616 char * str;
404ff6b5 10617{
63e63b07 10618 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
10619}
10620
10621/* Isnsn like "foo X,Y". */
10622
10623static void
63e63b07 10624do_mav_binops (str, mode, reg0, reg1)
404ff6b5 10625 char * str;
404ff6b5 10626 int mode;
6c43fab6
RE
10627 enum arm_reg_type reg0;
10628 enum arm_reg_type reg1;
404ff6b5 10629{
6c43fab6 10630 int shift0, shift1;
404ff6b5 10631
6c43fab6
RE
10632 shift0 = mode & 0xff;
10633 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
10634
10635 skip_whitespace (str);
10636
63e63b07 10637 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10638 || skip_past_comma (&str) == FAIL
63e63b07 10639 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
404ff6b5
AH
10640 {
10641 if (!inst.error)
10642 inst.error = BAD_ARGS;
10643 }
10644 else
10645 end_of_line (str);
404ff6b5
AH
10646}
10647
10648/* Isnsn like "foo X,Y,Z". */
10649
10650static void
63e63b07 10651do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 10652 char * str;
404ff6b5 10653 int mode;
6c43fab6
RE
10654 enum arm_reg_type reg0;
10655 enum arm_reg_type reg1;
10656 enum arm_reg_type reg2;
404ff6b5 10657{
6c43fab6 10658 int shift0, shift1, shift2;
404ff6b5 10659
6c43fab6
RE
10660 shift0 = mode & 0xff;
10661 shift1 = (mode >> 8) & 0xff;
10662 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
10663
10664 skip_whitespace (str);
10665
63e63b07 10666 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10667 || skip_past_comma (&str) == FAIL
63e63b07 10668 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10669 || skip_past_comma (&str) == FAIL
63e63b07 10670 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
10671 {
10672 if (!inst.error)
10673 inst.error = BAD_ARGS;
10674 }
10675 else
10676 end_of_line (str);
404ff6b5
AH
10677}
10678
10679/* Isnsn like "foo W,X,Y,Z".
10680 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10681
10682static void
63e63b07 10683do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 10684 char * str;
404ff6b5 10685 int mode;
6c43fab6
RE
10686 enum arm_reg_type reg0;
10687 enum arm_reg_type reg1;
10688 enum arm_reg_type reg2;
10689 enum arm_reg_type reg3;
404ff6b5 10690{
6c43fab6 10691 int shift0, shift1, shift2, shift3;
404ff6b5 10692
6c43fab6
RE
10693 shift0= mode & 0xff;
10694 shift1 = (mode >> 8) & 0xff;
10695 shift2 = (mode >> 16) & 0xff;
10696 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
10697
10698 skip_whitespace (str);
10699
63e63b07 10700 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 10701 || skip_past_comma (&str) == FAIL
63e63b07 10702 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 10703 || skip_past_comma (&str) == FAIL
63e63b07 10704 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 10705 || skip_past_comma (&str) == FAIL
63e63b07 10706 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
10707 {
10708 if (!inst.error)
10709 inst.error = BAD_ARGS;
10710 }
10711 else
10712 end_of_line (str);
404ff6b5
AH
10713}
10714
63e63b07 10715/* Maverick shift immediate instructions.
404ff6b5
AH
10716 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10717 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10718
10719static void
63e63b07 10720do_mav_shift (str, reg0, reg1)
404ff6b5 10721 char * str;
6c43fab6
RE
10722 enum arm_reg_type reg0;
10723 enum arm_reg_type reg1;
404ff6b5
AH
10724{
10725 int error;
10726 int imm, neg = 0;
10727
10728 skip_whitespace (str);
10729
10730 error = 0;
10731
63e63b07 10732 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 10733 || skip_past_comma (&str) == FAIL
63e63b07 10734 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
10735 || skip_past_comma (&str) == FAIL)
10736 {
10737 if (!inst.error)
10738 inst.error = BAD_ARGS;
10739 return;
10740 }
10741
10742 /* Calculate the immediate operand.
10743 The operand is a 7bit signed number. */
10744 skip_whitespace (str);
10745
10746 if (*str == '#')
10747 ++str;
10748
8420dfca 10749 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
10750 {
10751 inst.error = _("expecting immediate, 7bit operand");
10752 return;
10753 }
10754
10755 if (*str == '-')
10756 {
10757 neg = 1;
10758 ++str;
10759 }
10760
8420dfca 10761 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
10762 imm = imm * 10 + *str - '0';
10763
10764 if (imm > 64)
10765 {
10766 inst.error = _("immediate out of range");
10767 return;
10768 }
10769
10770 /* Make negative imm's into 7bit signed numbers. */
10771 if (neg)
10772 {
10773 imm = -imm;
10774 imm &= 0x0000007f;
10775 }
10776
10777 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10778 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10779 Bit 4 should be 0. */
10780 imm = (imm & 0xf) | ((imm & 0x70) << 1);
10781
10782 inst.instruction |= imm;
404ff6b5 10783 end_of_line (str);
404ff6b5
AH
10784}
10785
10786static int
63e63b07 10787mav_parse_offset (str, negative)
404ff6b5
AH
10788 char ** str;
10789 int *negative;
10790{
10791 char * p = *str;
10792 int offset;
10793
10794 *negative = 0;
10795
10796 skip_whitespace (p);
10797
10798 if (*p == '#')
10799 ++p;
10800
10801 if (*p == '-')
10802 {
10803 *negative = 1;
10804 ++p;
10805 }
10806
8420dfca 10807 if (!ISDIGIT (*p))
404ff6b5
AH
10808 {
10809 inst.error = _("offset expected");
10810 return 0;
10811 }
10812
8420dfca 10813 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
10814 offset = offset * 10 + *p - '0';
10815
10816 if (offset > 0xff)
10817 {
10818 inst.error = _("offset out of range");
10819 return 0;
10820 }
10821
10822 *str = p;
10823
10824 return *negative ? -offset : offset;
10825}
10826
63e63b07 10827/* Maverick load/store instructions.
404ff6b5
AH
10828 <insn><cond> CRd,[Rn,<offset>]{!}.
10829 <insn><cond> CRd,[Rn],<offset>. */
10830
10831static void
63e63b07 10832do_mav_ldst (str, reg0)
404ff6b5 10833 char * str;
6c43fab6 10834 enum arm_reg_type reg0;
404ff6b5
AH
10835{
10836 int offset, negative;
404ff6b5
AH
10837
10838 skip_whitespace (str);
10839
63e63b07 10840 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 10841 || skip_past_comma (&str) == FAIL
404ff6b5 10842 || *str++ != '['
6c43fab6 10843 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
10844 goto fail_ldst;
10845
6c43fab6 10846 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
10847 {
10848 /* You are here: "<offset>]{!}". */
10849 inst.instruction |= PRE_INDEX;
10850
63e63b07 10851 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
10852
10853 if (inst.error)
10854 return;
10855
10856 if (*str++ != ']')
10857 {
10858 inst.error = _("missing ]");
10859 return;
10860 }
10861
10862 if (*str == '!')
10863 {
10864 inst.instruction |= WRITE_BACK;
10865 ++str;
10866 }
10867 }
10868 else
10869 {
10870 /* You are here: "], <offset>". */
10871 if (*str++ != ']')
10872 {
10873 inst.error = _("missing ]");
10874 return;
10875 }
10876
10877 if (skip_past_comma (&str) == FAIL
63e63b07 10878 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
10879 goto fail_ldst;
10880
10881 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
10882 }
10883
10884 if (negative)
10885 offset = -offset;
10886 else
2d2255b5 10887 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
404ff6b5
AH
10888
10889 inst.instruction |= offset >> 2;
404ff6b5
AH
10890 end_of_line (str);
10891 return;
10892
10893fail_ldst:
10894 if (!inst.error)
10895 inst.error = BAD_ARGS;
404ff6b5
AH
10896}
10897
b99bd4ef
NC
10898static void
10899do_t_nop (str)
10900 char * str;
10901{
10902 /* Do nothing. */
10903 end_of_line (str);
b99bd4ef
NC
10904}
10905
10906/* Handle the Format 4 instructions that do not have equivalents in other
10907 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10908 BIC and MVN. */
10909
10910static void
10911do_t_arit (str)
10912 char * str;
10913{
10914 int Rd, Rs, Rn;
10915
10916 skip_whitespace (str);
10917
10918 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10919 || skip_past_comma (&str) == FAIL
10920 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10921 {
10922 inst.error = BAD_ARGS;
10923 return;
10924 }
10925
10926 if (skip_past_comma (&str) != FAIL)
10927 {
10928 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10929 (It isn't allowed for CMP either, but that isn't handled by this
10930 function.) */
10931 if (inst.instruction == T_OPCODE_TST
10932 || inst.instruction == T_OPCODE_CMN
10933 || inst.instruction == T_OPCODE_NEG
10934 || inst.instruction == T_OPCODE_MVN)
10935 {
10936 inst.error = BAD_ARGS;
10937 return;
10938 }
10939
10940 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10941 return;
10942
10943 if (Rs != Rd)
10944 {
10945 inst.error = _("dest and source1 must be the same register");
10946 return;
10947 }
10948 Rs = Rn;
10949 }
10950
10951 if (inst.instruction == T_OPCODE_MUL
10952 && Rs == Rd)
10953 as_tsktsk (_("Rs and Rd must be different in MUL"));
10954
10955 inst.instruction |= Rd | (Rs << 3);
10956 end_of_line (str);
10957}
10958
10959static void
10960do_t_add (str)
10961 char * str;
10962{
10963 thumb_add_sub (str, 0);
10964}
10965
10966static void
10967do_t_asr (str)
10968 char * str;
10969{
10970 thumb_shift (str, THUMB_ASR);
10971}
10972
10973static void
10974do_t_branch9 (str)
10975 char * str;
10976{
10977 if (my_get_expression (&inst.reloc.exp, &str))
10978 return;
10979 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
10980 inst.reloc.pc_rel = 1;
10981 end_of_line (str);
10982}
10983
10984static void
10985do_t_branch12 (str)
10986 char * str;
10987{
10988 if (my_get_expression (&inst.reloc.exp, &str))
10989 return;
10990 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
10991 inst.reloc.pc_rel = 1;
10992 end_of_line (str);
10993}
10994
10995/* Find the real, Thumb encoded start of a Thumb function. */
10996
10997static symbolS *
10998find_real_start (symbolP)
10999 symbolS * symbolP;
11000{
11001 char * real_start;
11002 const char * name = S_GET_NAME (symbolP);
11003 symbolS * new_target;
11004
2d2255b5 11005 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
b99bd4ef
NC
11006#define STUB_NAME ".real_start_of"
11007
11008 if (name == NULL)
11009 abort ();
11010
11011 /* Names that start with '.' are local labels, not function entry points.
11012 The compiler may generate BL instructions to these labels because it
11013 needs to perform a branch to a far away location. */
11014 if (name[0] == '.')
11015 return symbolP;
11016
11017 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11018 sprintf (real_start, "%s%s", STUB_NAME, name);
11019
11020 new_target = symbol_find (real_start);
11021
11022 if (new_target == NULL)
11023 {
11024 as_warn ("Failed to find real start of function: %s\n", name);
11025 new_target = symbolP;
11026 }
11027
11028 free (real_start);
11029
11030 return new_target;
11031}
11032
11033static void
11034do_t_branch23 (str)
11035 char * str;
11036{
11037 if (my_get_expression (& inst.reloc.exp, & str))
11038 return;
11039
11040 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
11041 inst.reloc.pc_rel = 1;
11042 end_of_line (str);
11043
11044 /* If the destination of the branch is a defined symbol which does not have
11045 the THUMB_FUNC attribute, then we must be calling a function which has
11046 the (interfacearm) attribute. We look for the Thumb entry point to that
11047 function and change the branch to refer to that function instead. */
11048 if ( inst.reloc.exp.X_op == O_symbol
11049 && inst.reloc.exp.X_add_symbol != NULL
11050 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11051 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11052 inst.reloc.exp.X_add_symbol =
11053 find_real_start (inst.reloc.exp.X_add_symbol);
11054}
11055
11056static void
11057do_t_bx (str)
11058 char * str;
11059{
11060 int reg;
11061
11062 skip_whitespace (str);
11063
11064 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11065 return;
11066
11067 /* This sets THUMB_H2 from the top bit of reg. */
11068 inst.instruction |= reg << 3;
11069
11070 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11071 should cause the alignment to be checked once it is known. This is
11072 because BX PC only works if the instruction is word aligned. */
11073
11074 end_of_line (str);
11075}
11076
11077static void
11078do_t_compare (str)
11079 char * str;
11080{
11081 thumb_mov_compare (str, THUMB_COMPARE);
11082}
11083
11084static void
11085do_t_ldmstm (str)
11086 char * str;
11087{
11088 int Rb;
11089 long range;
11090
11091 skip_whitespace (str);
11092
11093 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11094 return;
11095
11096 if (*str != '!')
f03698e6 11097 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
11098 else
11099 str++;
11100
11101 if (skip_past_comma (&str) == FAIL
11102 || (range = reg_list (&str)) == FAIL)
11103 {
11104 if (! inst.error)
11105 inst.error = BAD_ARGS;
11106 return;
11107 }
11108
11109 if (inst.reloc.type != BFD_RELOC_NONE)
11110 {
11111 /* This really doesn't seem worth it. */
11112 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11113 inst.error = _("expression too complex");
b99bd4ef
NC
11114 return;
11115 }
11116
11117 if (range & ~0xff)
11118 {
11119 inst.error = _("only lo-regs valid in load/store multiple");
11120 return;
11121 }
11122
11123 inst.instruction |= (Rb << 8) | range;
11124 end_of_line (str);
11125}
11126
11127static void
11128do_t_ldr (str)
11129 char * str;
11130{
11131 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11132}
11133
11134static void
11135do_t_ldrb (str)
11136 char * str;
11137{
11138 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11139}
11140
11141static void
11142do_t_ldrh (str)
11143 char * str;
11144{
11145 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11146}
11147
11148static void
11149do_t_lds (str)
11150 char * str;
11151{
11152 int Rd, Rb, Ro;
11153
11154 skip_whitespace (str);
11155
11156 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11157 || skip_past_comma (&str) == FAIL
11158 || *str++ != '['
11159 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11160 || skip_past_comma (&str) == FAIL
11161 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11162 || *str++ != ']')
11163 {
11164 if (! inst.error)
f03698e6 11165 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
11166 return;
11167 }
11168
11169 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11170 end_of_line (str);
11171}
11172
11173static void
11174do_t_lsl (str)
11175 char * str;
11176{
11177 thumb_shift (str, THUMB_LSL);
11178}
11179
11180static void
11181do_t_lsr (str)
11182 char * str;
11183{
11184 thumb_shift (str, THUMB_LSR);
11185}
11186
11187static void
11188do_t_mov (str)
11189 char * str;
11190{
11191 thumb_mov_compare (str, THUMB_MOVE);
11192}
11193
11194static void
11195do_t_push_pop (str)
11196 char * str;
11197{
11198 long range;
11199
11200 skip_whitespace (str);
11201
11202 if ((range = reg_list (&str)) == FAIL)
11203 {
11204 if (! inst.error)
11205 inst.error = BAD_ARGS;
11206 return;
11207 }
11208
11209 if (inst.reloc.type != BFD_RELOC_NONE)
11210 {
11211 /* This really doesn't seem worth it. */
11212 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 11213 inst.error = _("expression too complex");
b99bd4ef
NC
11214 return;
11215 }
11216
11217 if (range & ~0xff)
11218 {
11219 if ((inst.instruction == T_OPCODE_PUSH
11220 && (range & ~0xff) == 1 << REG_LR)
11221 || (inst.instruction == T_OPCODE_POP
11222 && (range & ~0xff) == 1 << REG_PC))
11223 {
11224 inst.instruction |= THUMB_PP_PC_LR;
11225 range &= 0xff;
11226 }
11227 else
11228 {
11229 inst.error = _("invalid register list to push/pop instruction");
11230 return;
11231 }
11232 }
11233
11234 inst.instruction |= range;
11235 end_of_line (str);
11236}
11237
11238static void
11239do_t_str (str)
11240 char * str;
11241{
11242 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11243}
11244
11245static void
11246do_t_strb (str)
11247 char * str;
11248{
11249 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11250}
11251
11252static void
11253do_t_strh (str)
11254 char * str;
11255{
11256 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11257}
11258
11259static void
11260do_t_sub (str)
11261 char * str;
11262{
11263 thumb_add_sub (str, 1);
11264}
11265
11266static void
11267do_t_swi (str)
11268 char * str;
11269{
11270 skip_whitespace (str);
11271
11272 if (my_get_expression (&inst.reloc.exp, &str))
11273 return;
11274
11275 inst.reloc.type = BFD_RELOC_ARM_SWI;
11276 end_of_line (str);
b99bd4ef
NC
11277}
11278
11279static void
11280do_t_adr (str)
11281 char * str;
11282{
11283 int reg;
11284
11285 /* This is a pseudo-op of the form "adr rd, label" to be converted
11286 into a relative address of the form "add rd, pc, #label-.-4". */
11287 skip_whitespace (str);
11288
11289 /* Store Rd in temporary location inside instruction. */
11290 if ((reg = reg_required_here (&str, 4)) == FAIL
11291 || (reg > 7) /* For Thumb reg must be r0..r7. */
11292 || skip_past_comma (&str) == FAIL
11293 || my_get_expression (&inst.reloc.exp, &str))
11294 {
11295 if (!inst.error)
11296 inst.error = BAD_ARGS;
11297 return;
11298 }
11299
11300 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11301 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
11302 inst.reloc.pc_rel = 1;
11303 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
11304
11305 end_of_line (str);
11306}
11307
11308static void
6c43fab6
RE
11309insert_reg (r, htab)
11310 const struct reg_entry *r;
11311 struct hash_control *htab;
b99bd4ef 11312{
6c43fab6 11313 int len = strlen (r->name) + 2;
b99bd4ef
NC
11314 char * buf = (char *) xmalloc (len);
11315 char * buf2 = (char *) xmalloc (len);
11316 int i = 0;
11317
11318#ifdef REGISTER_PREFIX
11319 buf[i++] = REGISTER_PREFIX;
11320#endif
11321
6c43fab6 11322 strcpy (buf + i, r->name);
b99bd4ef
NC
11323
11324 for (i = 0; buf[i]; i++)
3882b010 11325 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
11326
11327 buf2[i] = '\0';
11328
6c43fab6
RE
11329 hash_insert (htab, buf, (PTR) r);
11330 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
11331}
11332
11333static void
6c43fab6
RE
11334build_reg_hsh (map)
11335 struct reg_map *map;
11336{
11337 const struct reg_entry *r;
11338
11339 if ((map->htab = hash_new ()) == NULL)
f03698e6 11340 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
11341
11342 for (r = map->names; r->name != NULL; r++)
11343 insert_reg (r, map->htab);
11344}
11345
11346static void
11347insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
11348 char *str;
11349 int regnum;
6c43fab6 11350 struct hash_control *htab;
b99bd4ef 11351{
0bbf2aa4
NC
11352 const char *error;
11353 struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11354 const char *name = xmalloc (strlen (str) + 1);
11355
11356 strcpy ((char *) name, str);
11357
b99bd4ef
NC
11358 new->name = name;
11359 new->number = regnum;
0bbf2aa4 11360 new->builtin = FALSE;
b99bd4ef 11361
0bbf2aa4
NC
11362 error = hash_insert (htab, name, (PTR) new);
11363 if (error)
11364 {
11365 as_bad (_("failed to create an alias for %s, reason: %s"),
11366 str, error);
11367 free ((char *) name);
11368 free (new);
11369 }
b99bd4ef
NC
11370}
11371
6c43fab6
RE
11372/* Look for the .req directive. This is of the form:
11373
0bbf2aa4 11374 new_register_name .req existing_register_name
6c43fab6
RE
11375
11376 If we find one, or if it looks sufficiently like one that we want to
11377 handle any error here, return non-zero. Otherwise return zero. */
11378static int
11379create_register_alias (newname, p)
11380 char *newname;
11381 char *p;
11382{
11383 char *q;
11384 char c;
11385
11386 q = p;
11387 skip_whitespace (q);
11388
11389 c = *p;
11390 *p = '\0';
11391
11392 if (*q && !strncmp (q, ".req ", 5))
11393 {
11394 char *copy_of_str;
11395 char *r;
11396
11397#ifdef IGNORE_OPCODE_CASE
11398 newname = original_case_string;
11399#endif
11400 copy_of_str = newname;
11401
11402 q += 4;
11403 skip_whitespace (q);
11404
11405 for (r = q; *r != '\0'; r++)
11406 if (*r == ' ')
11407 break;
11408
11409 if (r != q)
11410 {
11411 enum arm_reg_type new_type, old_type;
11412 int old_regno;
11413 char d = *r;
11414
11415 *r = '\0';
11416 old_type = arm_reg_parse_any (q);
11417 *r = d;
11418
11419 new_type = arm_reg_parse_any (newname);
11420
11421 if (new_type == REG_TYPE_MAX)
11422 {
11423 if (old_type != REG_TYPE_MAX)
11424 {
11425 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11426 insert_reg_alias (newname, old_regno,
11427 all_reg_maps[old_type].htab);
11428 }
11429 else
11430 as_warn (_("register '%s' does not exist\n"), q);
11431 }
11432 else if (old_type == REG_TYPE_MAX)
11433 {
11434 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11435 copy_of_str, q);
11436 }
11437 else
11438 {
11439 /* Do not warn about redefinitions to the same alias. */
11440 if (new_type != old_type
11441 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11442 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11443 as_warn (_("ignoring redefinition of register alias '%s'"),
11444 copy_of_str);
11445
11446 }
11447 }
11448 else
11449 as_warn (_("ignoring incomplete .req pseuso op"));
11450
11451 *p = c;
11452 return 1;
11453 }
0bbf2aa4 11454
6c43fab6
RE
11455 *p = c;
11456 return 0;
11457}
cc8a6dd0 11458
b99bd4ef
NC
11459static void
11460set_constant_flonums ()
11461{
11462 int i;
11463
11464 for (i = 0; i < NUM_FLOAT_VALS; i++)
11465 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11466 abort ();
11467}
11468
90e4755a
RE
11469/* Iterate over the base tables to create the instruction patterns. */
11470static void
11471build_arm_ops_hsh ()
11472{
11473 unsigned int i;
11474 unsigned int j;
11475 static struct obstack insn_obstack;
11476
11477 obstack_begin (&insn_obstack, 4000);
11478
11479 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11480 {
6c43fab6 11481 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11482
11483 if (insn->cond_offset != 0)
11484 {
11485 /* Insn supports conditional execution. Build the varaints
11486 and insert them in the hash table. */
11487 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11488 {
11489 unsigned len = strlen (insn->template);
11490 struct asm_opcode *new;
11491 char *template;
11492
11493 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11494 /* All condition codes are two characters. */
11495 template = obstack_alloc (&insn_obstack, len + 3);
11496
11497 strncpy (template, insn->template, insn->cond_offset);
11498 strcpy (template + insn->cond_offset, conds[j].template);
11499 if (len > insn->cond_offset)
11500 strcpy (template + insn->cond_offset + 2,
11501 insn->template + insn->cond_offset);
11502 new->template = template;
11503 new->cond_offset = 0;
11504 new->variant = insn->variant;
11505 new->parms = insn->parms;
11506 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11507
11508 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11509 }
11510 }
11511 /* Finally, insert the unconditional insn in the table directly;
11512 no need to build a copy. */
11513 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11514 }
11515}
11516
0bbf2aa4 11517#if 0 /* Suppressed - for now. */
5a6c6817
NC
11518#if defined OBJ_ELF || defined OBJ_COFF
11519
11520#ifdef OBJ_ELF
11521#define arm_Note Elf_External_Note
11522#else
11523typedef struct
11524{
11525 unsigned char namesz[4]; /* Size of entry's owner string. */
11526 unsigned char descsz[4]; /* Size of the note descriptor. */
11527 unsigned char type[4]; /* Interpretation of the descriptor. */
11528 char name[1]; /* Start of the name+desc data. */
11529} arm_Note;
11530#endif
11531
11532/* The description is kept to a fix sized in order to make updating
11533 it and merging it easier. */
11534#define ARM_NOTE_DESCRIPTION_LENGTH 8
11535
11536static void
11537arm_add_note (name, description, type)
11538 const char * name;
11539 const char * description;
11540 unsigned int type;
11541{
11542 arm_Note note ATTRIBUTE_UNUSED;
11543 char * p;
11544 unsigned int name_len;
11545
11546 name_len = (strlen (name) + 1 + 3) & ~3;
11547
11548 p = frag_more (sizeof (note.namesz));
11549 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11550
11551 p = frag_more (sizeof (note.descsz));
11552 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11553
11554 p = frag_more (sizeof (note.type));
11555 md_number_to_chars (p, (valueT) type, sizeof (note.type));
11556
11557 p = frag_more (name_len);
11558 strcpy (p, name);
11559
11560 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11561 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11562 frag_align (2, 0, 0);
11563}
11564#endif
0bbf2aa4 11565#endif
5a6c6817 11566
b99bd4ef
NC
11567void
11568md_begin ()
11569{
11570 unsigned mach;
11571 unsigned int i;
11572
11573 if ( (arm_ops_hsh = hash_new ()) == NULL
11574 || (arm_tops_hsh = hash_new ()) == NULL
11575 || (arm_cond_hsh = hash_new ()) == NULL
11576 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11577 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11578 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11579
90e4755a 11580 build_arm_ops_hsh ();
b99bd4ef
NC
11581 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11582 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11583 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11584 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11585 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11586 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11587 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11588 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11589
6c43fab6
RE
11590 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11591 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11592
11593 set_constant_flonums ();
11594
03b1477f
RE
11595 /* Set the cpu variant based on the command-line options. We prefer
11596 -mcpu= over -march= if both are set (as for GCC); and we prefer
11597 -mfpu= over any other way of setting the floating point unit.
11598 Use of legacy options with new options are faulted. */
11599 if (legacy_cpu != -1)
11600 {
11601 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11602 as_bad (_("use of old and new-style options to set CPU type"));
11603
11604 mcpu_cpu_opt = legacy_cpu;
11605 }
11606 else if (mcpu_cpu_opt == -1)
11607 mcpu_cpu_opt = march_cpu_opt;
11608
11609 if (legacy_fpu != -1)
11610 {
11611 if (mfpu_opt != -1)
11612 as_bad (_("use of old and new-style options to set FPU type"));
11613
11614 mfpu_opt = legacy_fpu;
11615 }
11616 else if (mfpu_opt == -1)
11617 {
39c2da32
RE
11618#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11619 /* Some environments specify a default FPU. If they don't, infer it
11620 from the processor. */
03b1477f
RE
11621 if (mcpu_fpu_opt != -1)
11622 mfpu_opt = mcpu_fpu_opt;
11623 else
11624 mfpu_opt = march_fpu_opt;
39c2da32
RE
11625#else
11626 mfpu_opt = FPU_DEFAULT;
11627#endif
03b1477f
RE
11628 }
11629
11630 if (mfpu_opt == -1)
11631 {
11632 if (mcpu_cpu_opt == -1)
11633 mfpu_opt = FPU_DEFAULT;
11634 else if (mcpu_cpu_opt & ARM_EXT_V5)
11635 mfpu_opt = FPU_ARCH_VFP_V2;
11636 else
11637 mfpu_opt = FPU_ARCH_FPA;
11638 }
11639
11640 if (mcpu_cpu_opt == -1)
11641 mcpu_cpu_opt = CPU_DEFAULT;
11642
11643 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11644
b99bd4ef
NC
11645#if defined OBJ_COFF || defined OBJ_ELF
11646 {
11647 unsigned int flags = 0;
11648
11649 /* Set the flags in the private structure. */
11650 if (uses_apcs_26) flags |= F_APCS26;
11651 if (support_interwork) flags |= F_INTERWORK;
11652 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11653 if (pic_code) flags |= F_PIC;
bfae80f2 11654 if ((cpu_variant & FPU_ANY) == FPU_NONE
03b1477f 11655 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
bfae80f2 11656 flags |= F_SOFT_FLOAT;
03b1477f
RE
11657 /* Using VFP conventions (even if soft-float). */
11658 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11659
fde78edd
NC
11660#if defined OBJ_ELF
11661 if (cpu_variant & ARM_CEXT_MAVERICK)
11662 {
5a21e886 11663 flags &= ~ F_SOFT_FLOAT;
fde78edd
NC
11664 flags |= EF_ARM_MAVERICK_FLOAT;
11665 }
11666#endif
b99bd4ef
NC
11667
11668 bfd_set_private_flags (stdoutput, flags);
11669
11670 /* We have run out flags in the COFF header to encode the
11671 status of ATPCS support, so instead we create a dummy,
11672 empty, debug section called .arm.atpcs. */
11673 if (atpcs)
11674 {
11675 asection * sec;
11676
11677 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11678
11679 if (sec != NULL)
11680 {
11681 bfd_set_section_flags
11682 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11683 bfd_set_section_size (stdoutput, sec, 0);
11684 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11685 }
11686 }
11687 }
11688#endif
11689
11690 /* Record the CPU type as well. */
11691 switch (cpu_variant & ARM_CPU_MASK)
11692 {
11693 case ARM_2:
11694 mach = bfd_mach_arm_2;
11695 break;
11696
11697 case ARM_3: /* Also ARM_250. */
11698 mach = bfd_mach_arm_2a;
11699 break;
11700
b89dddec
RE
11701 case ARM_6: /* Also ARM_7. */
11702 mach = bfd_mach_arm_3;
11703 break;
11704
b99bd4ef 11705 default:
5a6c6817 11706 mach = bfd_mach_arm_unknown;
b99bd4ef 11707 break;
b99bd4ef
NC
11708 }
11709
11710 /* Catch special cases. */
e16bb312
NC
11711 if (cpu_variant & ARM_CEXT_IWMMXT)
11712 mach = bfd_mach_arm_iWMMXt;
11713 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11714 mach = bfd_mach_arm_XScale;
fde78edd
NC
11715 else if (cpu_variant & ARM_CEXT_MAVERICK)
11716 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11717 else if (cpu_variant & ARM_EXT_V5E)
11718 mach = bfd_mach_arm_5TE;
11719 else if (cpu_variant & ARM_EXT_V5)
11720 {
b89dddec 11721 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11722 mach = bfd_mach_arm_5T;
11723 else
11724 mach = bfd_mach_arm_5;
11725 }
b89dddec 11726 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11727 {
b89dddec 11728 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11729 mach = bfd_mach_arm_4T;
11730 else
11731 mach = bfd_mach_arm_4;
11732 }
b89dddec 11733 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11734 mach = bfd_mach_arm_3M;
11735
5a6c6817 11736#if 0 /* Suppressed - for now. */
e16bb312 11737#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11738
11739 /* Create a .note section to fully identify this arm binary. */
11740
11741#define NOTE_ARCH_STRING "arch: "
11742
11743#if defined OBJ_COFF && ! defined NT_VERSION
11744#define NT_VERSION 1
11745#define NT_ARCH 2
11746#endif
11747
e16bb312 11748 {
e16bb312
NC
11749 segT current_seg = now_seg;
11750 subsegT current_subseg = now_subseg;
11751 asection * arm_arch;
5a6c6817
NC
11752 const char * arch_string;
11753
e16bb312
NC
11754 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11755
11756#ifdef OBJ_COFF
11757 bfd_set_section_flags (stdoutput, arm_arch,
11758 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11759 | SEC_HAS_CONTENTS);
11760#endif
11761 arm_arch->output_section = arm_arch;
11762 subseg_set (arm_arch, 0);
e16bb312 11763
5a6c6817
NC
11764 switch (mach)
11765 {
11766 default:
11767 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11768 case bfd_mach_arm_2: arch_string = "armv2"; break;
11769 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11770 case bfd_mach_arm_3: arch_string = "armv3"; break;
11771 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11772 case bfd_mach_arm_4: arch_string = "armv4"; break;
11773 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11774 case bfd_mach_arm_5: arch_string = "armv5"; break;
11775 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11776 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11777 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11778 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
11779 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
11780 }
11781
11782 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11783
11784 subseg_set (current_seg, current_subseg);
11785 }
11786#endif
5a6c6817
NC
11787#endif /* Suppressed code. */
11788
b99bd4ef
NC
11789 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11790}
11791
11792/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11793 for use in the a.out file, and stores them in the array pointed to by buf.
11794 This knows about the endian-ness of the target machine and does
11795 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11796 2 (short) and 4 (long) Floating numbers are put out as a series of
11797 LITTLENUMS (shorts, here at least). */
11798
11799void
11800md_number_to_chars (buf, val, n)
11801 char * buf;
11802 valueT val;
11803 int n;
11804{
11805 if (target_big_endian)
11806 number_to_chars_bigendian (buf, val, n);
11807 else
11808 number_to_chars_littleendian (buf, val, n);
11809}
11810
11811static valueT
11812md_chars_to_number (buf, n)
11813 char * buf;
11814 int n;
11815{
11816 valueT result = 0;
11817 unsigned char * where = (unsigned char *) buf;
11818
11819 if (target_big_endian)
11820 {
11821 while (n--)
11822 {
11823 result <<= 8;
11824 result |= (*where++ & 255);
11825 }
11826 }
11827 else
11828 {
11829 while (n--)
11830 {
11831 result <<= 8;
11832 result |= (where[n] & 255);
11833 }
11834 }
11835
11836 return result;
11837}
11838
11839/* Turn a string in input_line_pointer into a floating point constant
11840 of type TYPE, and store the appropriate bytes in *LITP. The number
11841 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11842 returned, or NULL on OK.
11843
11844 Note that fp constants aren't represent in the normal way on the ARM.
11845 In big endian mode, things are as expected. However, in little endian
11846 mode fp constants are big-endian word-wise, and little-endian byte-wise
11847 within the words. For example, (double) 1.1 in big endian mode is
11848 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11849 the byte sequence 99 99 f1 3f 9a 99 99 99.
11850
11851 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11852
11853char *
11854md_atof (type, litP, sizeP)
11855 char type;
11856 char * litP;
11857 int * sizeP;
11858{
11859 int prec;
11860 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11861 char *t;
11862 int i;
11863
11864 switch (type)
11865 {
11866 case 'f':
11867 case 'F':
11868 case 's':
11869 case 'S':
11870 prec = 2;
11871 break;
11872
11873 case 'd':
11874 case 'D':
11875 case 'r':
11876 case 'R':
11877 prec = 4;
11878 break;
11879
11880 case 'x':
11881 case 'X':
11882 prec = 6;
11883 break;
11884
11885 case 'p':
11886 case 'P':
11887 prec = 6;
11888 break;
11889
11890 default:
11891 *sizeP = 0;
f03698e6 11892 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11893 }
11894
11895 t = atof_ieee (input_line_pointer, type, words);
11896 if (t)
11897 input_line_pointer = t;
11898 *sizeP = prec * 2;
11899
11900 if (target_big_endian)
11901 {
11902 for (i = 0; i < prec; i++)
11903 {
11904 md_number_to_chars (litP, (valueT) words[i], 2);
11905 litP += 2;
11906 }
11907 }
11908 else
11909 {
bfae80f2
RE
11910 if (cpu_variant & FPU_ARCH_VFP)
11911 for (i = prec - 1; i >= 0; i--)
11912 {
11913 md_number_to_chars (litP, (valueT) words[i], 2);
11914 litP += 2;
11915 }
11916 else
11917 /* For a 4 byte float the order of elements in `words' is 1 0.
11918 For an 8 byte float the order is 1 0 3 2. */
11919 for (i = 0; i < prec; i += 2)
11920 {
11921 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11922 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11923 litP += 4;
11924 }
b99bd4ef
NC
11925 }
11926
11927 return 0;
11928}
11929
11930/* The knowledge of the PC's pipeline offset is built into the insns
11931 themselves. */
11932
11933long
11934md_pcrel_from (fixP)
11935 fixS * fixP;
11936{
11937 if (fixP->fx_addsy
11938 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11939 && fixP->fx_subsy == NULL)
11940 return 0;
11941
11942 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11943 {
11944 /* PC relative addressing on the Thumb is slightly odd
11945 as the bottom two bits of the PC are forced to zero
11946 for the calculation. */
11947 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11948 }
11949
11950#ifdef TE_WINCE
2d2255b5
KH
11951 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11952 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11953 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11954#else
11955 return fixP->fx_where + fixP->fx_frag->fr_address;
11956#endif
11957}
11958
11959/* Round up a section size to the appropriate boundary. */
11960
11961valueT
11962md_section_align (segment, size)
11963 segT segment ATTRIBUTE_UNUSED;
11964 valueT size;
11965{
11966#ifdef OBJ_ELF
11967 return size;
11968#else
11969 /* Round all sects to multiple of 4. */
11970 return (size + 3) & ~3;
11971#endif
11972}
11973
11974/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11975 Otherwise we have no need to default values of symbols. */
11976
11977symbolS *
11978md_undefined_symbol (name)
11979 char * name ATTRIBUTE_UNUSED;
11980{
11981#ifdef OBJ_ELF
11982 if (name[0] == '_' && name[1] == 'G'
11983 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11984 {
11985 if (!GOT_symbol)
11986 {
11987 if (symbol_find (name))
11988 as_bad ("GOT already in the symbol table");
11989
11990 GOT_symbol = symbol_new (name, undefined_section,
11991 (valueT) 0, & zero_address_frag);
11992 }
11993
11994 return GOT_symbol;
11995 }
11996#endif
11997
11998 return 0;
11999}
12000
12001/* arm_reg_parse () := if it looks like a register, return its token and
12002 advance the pointer. */
12003
12004static int
6c43fab6 12005arm_reg_parse (ccp, htab)
b99bd4ef 12006 register char ** ccp;
6c43fab6 12007 struct hash_control *htab;
b99bd4ef
NC
12008{
12009 char * start = * ccp;
12010 char c;
12011 char * p;
12012 struct reg_entry * reg;
12013
12014#ifdef REGISTER_PREFIX
12015 if (*start != REGISTER_PREFIX)
12016 return FAIL;
12017 p = start + 1;
12018#else
12019 p = start;
12020#ifdef OPTIONAL_REGISTER_PREFIX
12021 if (*p == OPTIONAL_REGISTER_PREFIX)
12022 p++, start++;
12023#endif
12024#endif
3882b010 12025 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
12026 return FAIL;
12027
12028 c = *p++;
3882b010 12029 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
12030 c = *p++;
12031
12032 *--p = 0;
6c43fab6 12033 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
12034 *p = c;
12035
12036 if (reg)
12037 {
12038 *ccp = p;
12039 return reg->number;
12040 }
12041
12042 return FAIL;
12043}
12044
6c43fab6
RE
12045/* Search for the following register name in each of the possible reg name
12046 tables. Return the classification if found, or REG_TYPE_MAX if not
12047 present. */
12048static enum arm_reg_type
12049arm_reg_parse_any (cp)
12050 char *cp;
12051{
12052 int i;
12053
12054 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12055 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12056 return (enum arm_reg_type) i;
12057
12058 return REG_TYPE_MAX;
12059}
12060
94f592af
NC
12061void
12062md_apply_fix3 (fixP, valP, seg)
b99bd4ef 12063 fixS * fixP;
94f592af 12064 valueT * valP;
b99bd4ef
NC
12065 segT seg;
12066{
94f592af 12067 offsetT value = * valP;
b99bd4ef
NC
12068 offsetT newval;
12069 unsigned int newimm;
12070 unsigned long temp;
12071 int sign;
12072 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12073 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12074
12075 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12076
12077 /* Note whether this will delete the relocation. */
12078#if 0
12079 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12080 doesn't work fully.) */
12081 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12082 && !fixP->fx_pcrel)
12083#else
12084 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12085#endif
12086 fixP->fx_done = 1;
12087
12088 /* If this symbol is in a different section then we need to leave it for
12089 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12090 so we have to undo it's effects here. */
12091 if (fixP->fx_pcrel)
12092 {
12093 if (fixP->fx_addsy != NULL
12094 && S_IS_DEFINED (fixP->fx_addsy)
12095 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12096 {
12097 if (target_oabi
12098 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12099 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12100 ))
12101 value = 0;
12102 else
12103 value += md_pcrel_from (fixP);
12104 }
12105 }
12106
12107 /* Remember value for emit_reloc. */
12108 fixP->fx_addnumber = value;
12109
12110 switch (fixP->fx_r_type)
12111 {
12112 case BFD_RELOC_ARM_IMMEDIATE:
12113 newimm = validate_immediate (value);
12114 temp = md_chars_to_number (buf, INSN_SIZE);
12115
12116 /* If the instruction will fail, see if we can fix things up by
12117 changing the opcode. */
12118 if (newimm == (unsigned int) FAIL
12119 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12120 {
12121 as_bad_where (fixP->fx_file, fixP->fx_line,
12122 _("invalid constant (%lx) after fixup"),
12123 (unsigned long) value);
12124 break;
12125 }
12126
12127 newimm |= (temp & 0xfffff000);
12128 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
6189168b 12129 fixP->fx_done = 1;
b99bd4ef
NC
12130 break;
12131
12132 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12133 {
12134 unsigned int highpart = 0;
12135 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 12136
b99bd4ef
NC
12137 newimm = validate_immediate (value);
12138 temp = md_chars_to_number (buf, INSN_SIZE);
12139
12140 /* If the instruction will fail, see if we can fix things up by
12141 changing the opcode. */
12142 if (newimm == (unsigned int) FAIL
12143 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12144 {
12145 /* No ? OK - try using two ADD instructions to generate
12146 the value. */
12147 newimm = validate_immediate_twopart (value, & highpart);
12148
12149 /* Yes - then make sure that the second instruction is
12150 also an add. */
12151 if (newimm != (unsigned int) FAIL)
12152 newinsn = temp;
12153 /* Still No ? Try using a negated value. */
12154 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12155 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12156 /* Otherwise - give up. */
12157 else
12158 {
12159 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12160 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 12161 (long) value);
b99bd4ef
NC
12162 break;
12163 }
12164
12165 /* Replace the first operand in the 2nd instruction (which
12166 is the PC) with the destination register. We have
12167 already added in the PC in the first instruction and we
12168 do not want to do it again. */
12169 newinsn &= ~ 0xf0000;
12170 newinsn |= ((newinsn & 0x0f000) << 4);
12171 }
12172
12173 newimm |= (temp & 0xfffff000);
12174 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12175
12176 highpart |= (newinsn & 0xfffff000);
12177 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12178 }
12179 break;
12180
12181 case BFD_RELOC_ARM_OFFSET_IMM:
12182 sign = value >= 0;
12183
12184 if (value < 0)
12185 value = - value;
12186
12187 if (validate_offset_imm (value, 0) == FAIL)
12188 {
12189 as_bad_where (fixP->fx_file, fixP->fx_line,
12190 _("bad immediate value for offset (%ld)"),
12191 (long) value);
12192 break;
12193 }
12194
12195 newval = md_chars_to_number (buf, INSN_SIZE);
12196 newval &= 0xff7ff000;
12197 newval |= value | (sign ? INDEX_UP : 0);
12198 md_number_to_chars (buf, newval, INSN_SIZE);
12199 break;
12200
12201 case BFD_RELOC_ARM_OFFSET_IMM8:
12202 case BFD_RELOC_ARM_HWLITERAL:
12203 sign = value >= 0;
12204
12205 if (value < 0)
12206 value = - value;
12207
12208 if (validate_offset_imm (value, 1) == FAIL)
12209 {
12210 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12211 as_bad_where (fixP->fx_file, fixP->fx_line,
12212 _("invalid literal constant: pool needs to be closer"));
12213 else
12214 as_bad (_("bad immediate value for half-word offset (%ld)"),
12215 (long) value);
12216 break;
12217 }
12218
12219 newval = md_chars_to_number (buf, INSN_SIZE);
12220 newval &= 0xff7ff0f0;
12221 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12222 md_number_to_chars (buf, newval, INSN_SIZE);
12223 break;
12224
12225 case BFD_RELOC_ARM_LITERAL:
12226 sign = value >= 0;
12227
12228 if (value < 0)
12229 value = - value;
12230
12231 if (validate_offset_imm (value, 0) == FAIL)
12232 {
12233 as_bad_where (fixP->fx_file, fixP->fx_line,
12234 _("invalid literal constant: pool needs to be closer"));
12235 break;
12236 }
12237
12238 newval = md_chars_to_number (buf, INSN_SIZE);
12239 newval &= 0xff7ff000;
12240 newval |= value | (sign ? INDEX_UP : 0);
12241 md_number_to_chars (buf, newval, INSN_SIZE);
12242 break;
12243
12244 case BFD_RELOC_ARM_SHIFT_IMM:
12245 newval = md_chars_to_number (buf, INSN_SIZE);
12246 if (((unsigned long) value) > 32
12247 || (value == 32
12248 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12249 {
12250 as_bad_where (fixP->fx_file, fixP->fx_line,
12251 _("shift expression is too large"));
12252 break;
12253 }
12254
12255 if (value == 0)
12256 /* Shifts of zero must be done as lsl. */
12257 newval &= ~0x60;
12258 else if (value == 32)
12259 value = 0;
12260 newval &= 0xfffff07f;
12261 newval |= (value & 0x1f) << 7;
12262 md_number_to_chars (buf, newval, INSN_SIZE);
12263 break;
12264
12265 case BFD_RELOC_ARM_SWI:
12266 if (arm_data->thumb_mode)
12267 {
12268 if (((unsigned long) value) > 0xff)
12269 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12270 _("invalid swi expression"));
b99bd4ef
NC
12271 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12272 newval |= value;
12273 md_number_to_chars (buf, newval, THUMB_SIZE);
12274 }
12275 else
12276 {
12277 if (((unsigned long) value) > 0x00ffffff)
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12279 _("invalid swi expression"));
b99bd4ef
NC
12280 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12281 newval |= value;
12282 md_number_to_chars (buf, newval, INSN_SIZE);
12283 }
12284 break;
12285
12286 case BFD_RELOC_ARM_MULTI:
12287 if (((unsigned long) value) > 0xffff)
12288 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12289 _("invalid expression in load/store multiple"));
b99bd4ef
NC
12290 newval = value | md_chars_to_number (buf, INSN_SIZE);
12291 md_number_to_chars (buf, newval, INSN_SIZE);
12292 break;
12293
12294 case BFD_RELOC_ARM_PCREL_BRANCH:
12295 newval = md_chars_to_number (buf, INSN_SIZE);
12296
12297 /* Sign-extend a 24-bit number. */
12298#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12299
12300#ifdef OBJ_ELF
12301 if (! target_oabi)
12302 value = fixP->fx_offset;
12303#endif
12304
12305 /* We are going to store value (shifted right by two) in the
12306 instruction, in a 24 bit, signed field. Thus we need to check
12307 that none of the top 8 bits of the shifted value (top 7 bits of
12308 the unshifted, unsigned value) are set, or that they are all set. */
12309 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12310 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12311 {
12312#ifdef OBJ_ELF
12313 /* Normally we would be stuck at this point, since we cannot store
12314 the absolute address that is the destination of the branch in the
12315 24 bits of the branch instruction. If however, we happen to know
12316 that the destination of the branch is in the same section as the
2d2255b5 12317 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12318 ourselves and not have to bother the linker with it.
12319
12320 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12321 because I have not worked out how to do this for OBJ_COFF or
12322 target_oabi. */
12323 if (! target_oabi
12324 && fixP->fx_addsy != NULL
12325 && S_IS_DEFINED (fixP->fx_addsy)
12326 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12327 {
12328 /* Get pc relative value to go into the branch. */
94f592af 12329 value = * valP;
b99bd4ef
NC
12330
12331 /* Permit a backward branch provided that enough bits
12332 are set. Allow a forwards branch, provided that
12333 enough bits are clear. */
12334 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12335 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12336 fixP->fx_done = 1;
12337 }
12338
12339 if (! fixP->fx_done)
12340#endif
12341 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12342 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12343 }
12344
12345 value >>= 2;
12346 value += SEXT24 (newval);
12347
12348 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12349 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12350 as_bad_where (fixP->fx_file, fixP->fx_line,
12351 _("out of range branch"));
12352
12353 newval = (value & 0x00ffffff) | (newval & 0xff000000);
12354 md_number_to_chars (buf, newval, INSN_SIZE);
12355 break;
12356
12357 case BFD_RELOC_ARM_PCREL_BLX:
12358 {
12359 offsetT hbit;
12360 newval = md_chars_to_number (buf, INSN_SIZE);
12361
12362#ifdef OBJ_ELF
12363 if (! target_oabi)
12364 value = fixP->fx_offset;
12365#endif
12366 hbit = (value >> 1) & 1;
12367 value = (value >> 2) & 0x00ffffff;
12368 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12369 newval = value | (newval & 0xfe000000) | (hbit << 24);
12370 md_number_to_chars (buf, newval, INSN_SIZE);
12371 }
12372 break;
12373
12374 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12375 newval = md_chars_to_number (buf, THUMB_SIZE);
12376 {
12377 addressT diff = (newval & 0xff) << 1;
12378 if (diff & 0x100)
12379 diff |= ~0xff;
12380
12381 value += diff;
12382 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12383 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12384 _("branch out of range"));
b99bd4ef
NC
12385 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12386 }
12387 md_number_to_chars (buf, newval, THUMB_SIZE);
12388 break;
12389
12390 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12391 newval = md_chars_to_number (buf, THUMB_SIZE);
12392 {
12393 addressT diff = (newval & 0x7ff) << 1;
12394 if (diff & 0x800)
12395 diff |= ~0x7ff;
12396
12397 value += diff;
12398 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12399 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12400 _("branch out of range"));
b99bd4ef
NC
12401 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12402 }
12403 md_number_to_chars (buf, newval, THUMB_SIZE);
12404 break;
12405
12406 case BFD_RELOC_THUMB_PCREL_BLX:
12407 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12408 {
12409 offsetT newval2;
12410 addressT diff;
12411
12412 newval = md_chars_to_number (buf, THUMB_SIZE);
12413 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12414 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12415 if (diff & 0x400000)
12416 diff |= ~0x3fffff;
12417#ifdef OBJ_ELF
12418 value = fixP->fx_offset;
12419#endif
12420 value += diff;
c62e1cc3 12421
b99bd4ef
NC
12422 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12423 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12424 _("branch with link out of range"));
b99bd4ef
NC
12425
12426 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12427 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12428 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12429 /* For a BLX instruction, make sure that the relocation is rounded up
12430 to a word boundary. This follows the semantics of the instruction
12431 which specifies that bit 1 of the target address will come from bit
12432 1 of the base address. */
12433 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
12434 md_number_to_chars (buf, newval, THUMB_SIZE);
12435 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12436 }
12437 break;
12438
12439 case BFD_RELOC_8:
12440 if (fixP->fx_done || fixP->fx_pcrel)
12441 md_number_to_chars (buf, value, 1);
12442#ifdef OBJ_ELF
12443 else if (!target_oabi)
12444 {
12445 value = fixP->fx_offset;
12446 md_number_to_chars (buf, value, 1);
12447 }
12448#endif
12449 break;
12450
12451 case BFD_RELOC_16:
12452 if (fixP->fx_done || fixP->fx_pcrel)
12453 md_number_to_chars (buf, value, 2);
12454#ifdef OBJ_ELF
12455 else if (!target_oabi)
12456 {
12457 value = fixP->fx_offset;
12458 md_number_to_chars (buf, value, 2);
12459 }
12460#endif
12461 break;
12462
12463#ifdef OBJ_ELF
12464 case BFD_RELOC_ARM_GOT32:
12465 case BFD_RELOC_ARM_GOTOFF:
12466 md_number_to_chars (buf, 0, 4);
12467 break;
12468#endif
12469
12470 case BFD_RELOC_RVA:
12471 case BFD_RELOC_32:
12472 if (fixP->fx_done || fixP->fx_pcrel)
12473 md_number_to_chars (buf, value, 4);
12474#ifdef OBJ_ELF
12475 else if (!target_oabi)
12476 {
12477 value = fixP->fx_offset;
12478 md_number_to_chars (buf, value, 4);
12479 }
12480#endif
12481 break;
12482
12483#ifdef OBJ_ELF
12484 case BFD_RELOC_ARM_PLT32:
12485 /* It appears the instruction is fully prepared at this point. */
12486 break;
12487#endif
12488
b99bd4ef
NC
12489 case BFD_RELOC_ARM_CP_OFF_IMM:
12490 sign = value >= 0;
12491 if (value < -1023 || value > 1023 || (value & 3))
12492 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12493 _("illegal value for co-processor offset"));
b99bd4ef
NC
12494 if (value < 0)
12495 value = -value;
12496 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12497 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12498 md_number_to_chars (buf, newval, INSN_SIZE);
12499 break;
12500
e16bb312
NC
12501 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12502 sign = value >= 0;
12503 if (value < -255 || value > 255)
12504 as_bad_where (fixP->fx_file, fixP->fx_line,
12505 _("Illegal value for co-processor offset"));
12506 if (value < 0)
12507 value = -value;
12508 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12509 newval |= value | (sign ? INDEX_UP : 0);
12510 md_number_to_chars (buf, newval , INSN_SIZE);
12511 break;
12512
b99bd4ef
NC
12513 case BFD_RELOC_ARM_THUMB_OFFSET:
12514 newval = md_chars_to_number (buf, THUMB_SIZE);
12515 /* Exactly what ranges, and where the offset is inserted depends
12516 on the type of instruction, we can establish this from the
12517 top 4 bits. */
12518 switch (newval >> 12)
12519 {
12520 case 4: /* PC load. */
12521 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12522 forced to zero for these loads, so we will need to round
12523 up the offset if the instruction address is not word
12524 aligned (since the final address produced must be, and
12525 we can only describe word-aligned immediate offsets). */
12526
12527 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12528 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12529 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12530 (unsigned int) (fixP->fx_frag->fr_address
12531 + fixP->fx_where + value));
12532
12533 if ((value + 2) & ~0x3fe)
12534 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12535 _("invalid offset, value too big (0x%08lX)"),
12536 (long) value);
b99bd4ef
NC
12537
12538 /* Round up, since pc will be rounded down. */
12539 newval |= (value + 2) >> 2;
12540 break;
12541
12542 case 9: /* SP load/store. */
12543 if (value & ~0x3fc)
12544 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12545 _("invalid offset, value too big (0x%08lX)"),
12546 (long) value);
b99bd4ef
NC
12547 newval |= value >> 2;
12548 break;
12549
12550 case 6: /* Word load/store. */
12551 if (value & ~0x7c)
12552 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12553 _("invalid offset, value too big (0x%08lX)"),
12554 (long) value);
b99bd4ef
NC
12555 newval |= value << 4; /* 6 - 2. */
12556 break;
12557
12558 case 7: /* Byte load/store. */
12559 if (value & ~0x1f)
12560 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12561 _("invalid offset, value too big (0x%08lX)"),
12562 (long) value);
b99bd4ef
NC
12563 newval |= value << 6;
12564 break;
12565
12566 case 8: /* Halfword load/store. */
12567 if (value & ~0x3e)
12568 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12569 _("invalid offset, value too big (0x%08lX)"),
12570 (long) value);
b99bd4ef
NC
12571 newval |= value << 5; /* 6 - 1. */
12572 break;
12573
12574 default:
12575 as_bad_where (fixP->fx_file, fixP->fx_line,
12576 "Unable to process relocation for thumb opcode: %lx",
12577 (unsigned long) newval);
12578 break;
12579 }
12580 md_number_to_chars (buf, newval, THUMB_SIZE);
12581 break;
12582
12583 case BFD_RELOC_ARM_THUMB_ADD:
12584 /* This is a complicated relocation, since we use it for all of
12585 the following immediate relocations:
12586
12587 3bit ADD/SUB
12588 8bit ADD/SUB
12589 9bit ADD/SUB SP word-aligned
12590 10bit ADD PC/SP word-aligned
12591
12592 The type of instruction being processed is encoded in the
12593 instruction field:
12594
12595 0x8000 SUB
12596 0x00F0 Rd
12597 0x000F Rs
12598 */
12599 newval = md_chars_to_number (buf, THUMB_SIZE);
12600 {
12601 int rd = (newval >> 4) & 0xf;
12602 int rs = newval & 0xf;
12603 int subtract = newval & 0x8000;
12604
12605 if (rd == REG_SP)
12606 {
12607 if (value & ~0x1fc)
12608 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12609 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12610 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12611 newval |= value >> 2;
12612 }
12613 else if (rs == REG_PC || rs == REG_SP)
12614 {
12615 if (subtract ||
12616 value & ~0x3fc)
12617 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12618 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12619 (unsigned long) value);
12620 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12621 newval |= rd << 8;
12622 newval |= value >> 2;
12623 }
12624 else if (rs == rd)
12625 {
12626 if (value & ~0xff)
12627 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12628 _("invalid 8bit immediate"));
b99bd4ef
NC
12629 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12630 newval |= (rd << 8) | value;
12631 }
12632 else
12633 {
12634 if (value & ~0x7)
12635 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12636 _("invalid 3bit immediate"));
b99bd4ef
NC
12637 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12638 newval |= rd | (rs << 3) | (value << 6);
12639 }
12640 }
12641 md_number_to_chars (buf, newval, THUMB_SIZE);
12642 break;
12643
12644 case BFD_RELOC_ARM_THUMB_IMM:
12645 newval = md_chars_to_number (buf, THUMB_SIZE);
12646 switch (newval >> 11)
12647 {
12648 case 0x04: /* 8bit immediate MOV. */
12649 case 0x05: /* 8bit immediate CMP. */
12650 if (value < 0 || value > 255)
12651 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12652 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12653 (long) value);
12654 newval |= value;
12655 break;
12656
12657 default:
12658 abort ();
12659 }
12660 md_number_to_chars (buf, newval, THUMB_SIZE);
12661 break;
12662
12663 case BFD_RELOC_ARM_THUMB_SHIFT:
12664 /* 5bit shift value (0..31). */
12665 if (value < 0 || value > 31)
12666 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12667 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12668 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12669 newval |= value << 6;
12670 md_number_to_chars (buf, newval, THUMB_SIZE);
12671 break;
12672
12673 case BFD_RELOC_VTABLE_INHERIT:
12674 case BFD_RELOC_VTABLE_ENTRY:
12675 fixP->fx_done = 0;
94f592af 12676 return;
b99bd4ef
NC
12677
12678 case BFD_RELOC_NONE:
12679 default:
12680 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12681 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12682 }
b99bd4ef
NC
12683}
12684
12685/* Translate internal representation of relocation info to BFD target
12686 format. */
12687
12688arelent *
12689tc_gen_reloc (section, fixp)
12690 asection * section ATTRIBUTE_UNUSED;
12691 fixS * fixp;
12692{
12693 arelent * reloc;
12694 bfd_reloc_code_real_type code;
12695
12696 reloc = (arelent *) xmalloc (sizeof (arelent));
12697
12698 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12699 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12700 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12701
12702 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12703#ifndef OBJ_ELF
12704 if (fixp->fx_pcrel == 0)
12705 reloc->addend = fixp->fx_offset;
12706 else
12707 reloc->addend = fixp->fx_offset = reloc->address;
12708#else /* OBJ_ELF */
12709 reloc->addend = fixp->fx_offset;
12710#endif
12711
12712 switch (fixp->fx_r_type)
12713 {
12714 case BFD_RELOC_8:
12715 if (fixp->fx_pcrel)
12716 {
12717 code = BFD_RELOC_8_PCREL;
12718 break;
12719 }
12720
12721 case BFD_RELOC_16:
12722 if (fixp->fx_pcrel)
12723 {
12724 code = BFD_RELOC_16_PCREL;
12725 break;
12726 }
12727
12728 case BFD_RELOC_32:
12729 if (fixp->fx_pcrel)
12730 {
12731 code = BFD_RELOC_32_PCREL;
12732 break;
12733 }
12734
12735 case BFD_RELOC_ARM_PCREL_BRANCH:
12736 case BFD_RELOC_ARM_PCREL_BLX:
12737 case BFD_RELOC_RVA:
12738 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12739 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12740 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12741 case BFD_RELOC_THUMB_PCREL_BLX:
12742 case BFD_RELOC_VTABLE_ENTRY:
12743 case BFD_RELOC_VTABLE_INHERIT:
12744 code = fixp->fx_r_type;
12745 break;
12746
12747 case BFD_RELOC_ARM_LITERAL:
12748 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12749 /* If this is called then the a literal has
12750 been referenced across a section boundary. */
b99bd4ef 12751 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12752 _("literal referenced across section boundary"));
b99bd4ef
NC
12753 return NULL;
12754
12755#ifdef OBJ_ELF
12756 case BFD_RELOC_ARM_GOT32:
12757 case BFD_RELOC_ARM_GOTOFF:
12758 case BFD_RELOC_ARM_PLT32:
12759 code = fixp->fx_r_type;
12760 break;
12761#endif
12762
12763 case BFD_RELOC_ARM_IMMEDIATE:
12764 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12765 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12766 return NULL;
12767
12768 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12769 as_bad_where (fixp->fx_file, fixp->fx_line,
12770 _("ADRL used for a symbol not defined in the same file"));
12771 return NULL;
12772
12773 case BFD_RELOC_ARM_OFFSET_IMM:
12774 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12775 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12776 return NULL;
12777
12778 default:
12779 {
12780 char * type;
12781
12782 switch (fixp->fx_r_type)
12783 {
b99bd4ef
NC
12784 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12785 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
12786 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12787 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12788 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12789 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12790 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12791 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12792 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12793 default: type = _("<unknown>"); break;
12794 }
12795 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12796 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12797 type);
12798 return NULL;
12799 }
12800 }
12801
12802#ifdef OBJ_ELF
8df7094c 12803 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12804 && GOT_symbol
12805 && fixp->fx_addsy == GOT_symbol)
12806 {
12807 code = BFD_RELOC_ARM_GOTPC;
12808 reloc->addend = fixp->fx_offset = reloc->address;
12809 }
12810#endif
12811
12812 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12813
12814 if (reloc->howto == NULL)
12815 {
12816 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12817 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12818 bfd_get_reloc_code_name (code));
12819 return NULL;
12820 }
12821
12822 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12823 vtable entry to be used in the relocation's section offset. */
12824 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12825 reloc->address = fixp->fx_offset;
12826
12827 return reloc;
12828}
12829
12830int
12831md_estimate_size_before_relax (fragP, segtype)
12832 fragS * fragP ATTRIBUTE_UNUSED;
12833 segT segtype ATTRIBUTE_UNUSED;
12834{
12835 as_fatal (_("md_estimate_size_before_relax\n"));
12836 return 1;
12837}
12838
12839static void
f03698e6
RE
12840output_inst (str)
12841 const char *str;
b99bd4ef
NC
12842{
12843 char * to = NULL;
12844
12845 if (inst.error)
12846 {
f03698e6 12847 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12848 return;
12849 }
12850
12851 to = frag_more (inst.size);
12852
12853 if (thumb_mode && (inst.size > THUMB_SIZE))
12854 {
12855 assert (inst.size == (2 * THUMB_SIZE));
12856 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12857 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12858 }
12859 else if (inst.size > INSN_SIZE)
12860 {
12861 assert (inst.size == (2 * INSN_SIZE));
12862 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12863 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12864 }
12865 else
12866 md_number_to_chars (to, inst.instruction, inst.size);
12867
12868 if (inst.reloc.type != BFD_RELOC_NONE)
12869 fix_new_arm (frag_now, to - frag_now->fr_literal,
12870 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12871 inst.reloc.type);
12872
12873#ifdef OBJ_ELF
12874 dwarf2_emit_insn (inst.size);
12875#endif
12876}
12877
12878void
12879md_assemble (str)
12880 char * str;
12881{
6c43fab6
RE
12882 char c;
12883 char *p;
12884 char *start;
b99bd4ef
NC
12885
12886 /* Align the instruction.
12887 This may not be the right thing to do but ... */
12888#if 0
12889 arm_align (2, 0);
12890#endif
b99bd4ef
NC
12891
12892 /* Align the previous label if needed. */
12893 if (last_label_seen != NULL)
12894 {
12895 symbol_set_frag (last_label_seen, frag_now);
12896 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12897 S_SET_SEGMENT (last_label_seen, now_seg);
12898 }
12899
12900 memset (&inst, '\0', sizeof (inst));
12901 inst.reloc.type = BFD_RELOC_NONE;
12902
12903 skip_whitespace (str);
12904
12905 /* Scan up to the end of the op-code, which must end in white space or
12906 end of string. */
12907 for (start = p = str; *p != '\0'; p++)
12908 if (*p == ' ')
12909 break;
12910
12911 if (p == str)
12912 {
f03698e6 12913 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12914 return;
12915 }
12916
12917 if (thumb_mode)
12918 {
05d2d07e 12919 const struct thumb_opcode * opcode;
b99bd4ef
NC
12920
12921 c = *p;
12922 *p = '\0';
05d2d07e 12923 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12924 *p = c;
12925
12926 if (opcode)
12927 {
12928 /* Check that this instruction is supported for this CPU. */
90e4755a 12929 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12930 {
f03698e6 12931 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12932 return;
12933 }
12934
6057a28f 12935 mapping_state (MAP_THUMB);
b99bd4ef
NC
12936 inst.instruction = opcode->value;
12937 inst.size = opcode->size;
12938 (*opcode->parms) (p);
f03698e6 12939 output_inst (str);
b99bd4ef
NC
12940 return;
12941 }
12942 }
12943 else
12944 {
05d2d07e 12945 const struct asm_opcode * opcode;
b99bd4ef 12946
90e4755a
RE
12947 c = *p;
12948 *p = '\0';
6c43fab6 12949 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12950 *p = c;
b99bd4ef 12951
90e4755a 12952 if (opcode)
b99bd4ef 12953 {
90e4755a
RE
12954 /* Check that this instruction is supported for this CPU. */
12955 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12956 {
f03698e6 12957 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12958 return;
12959 }
12960
6057a28f 12961 mapping_state (MAP_ARM);
90e4755a
RE
12962 inst.instruction = opcode->value;
12963 inst.size = INSN_SIZE;
f2b7cb0a 12964 (*opcode->parms) (p);
f03698e6 12965 output_inst (str);
90e4755a 12966 return;
b99bd4ef
NC
12967 }
12968 }
12969
12970 /* It wasn't an instruction, but it might be a register alias of the form
12971 alias .req reg. */
6c43fab6
RE
12972 if (create_register_alias (str, p))
12973 return;
b99bd4ef 12974
b99bd4ef
NC
12975 as_bad (_("bad instruction `%s'"), start);
12976}
12977
12978/* md_parse_option
12979 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12980 See if it's a processor-specific option.
03b1477f
RE
12981
12982 This routine is somewhat complicated by the need for backwards
12983 compatibility (since older releases of gcc can't be changed).
12984 The new options try to make the interface as compatible as
12985 possible with GCC.
12986
12987 New options (supported) are:
12988
12989 -mcpu=<cpu name> Assemble for selected processor
12990 -march=<architecture name> Assemble for selected architecture
12991 -mfpu=<fpu architecture> Assemble for selected FPU.
12992 -EB/-mbig-endian Big-endian
12993 -EL/-mlittle-endian Little-endian
12994 -k Generate PIC code
12995 -mthumb Start in Thumb mode
12996 -mthumb-interwork Code supports ARM/Thumb interworking
12997
3d0c9500 12998 For now we will also provide support for:
03b1477f
RE
12999
13000 -mapcs-32 32-bit Program counter
13001 -mapcs-26 26-bit Program counter
13002 -macps-float Floats passed in FP registers
13003 -mapcs-reentrant Reentrant code
13004 -matpcs
13005 (sometime these will probably be replaced with -mapcs=<list of options>
13006 and -matpcs=<list of options>)
13007
13008 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
13009 Cpu variants, the arm part is optional:
13010 -m[arm]1 Currently not supported.
13011 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13012 -m[arm]3 Arm 3 processor
13013 -m[arm]6[xx], Arm 6 processors
13014 -m[arm]7[xx][t][[d]m] Arm 7 processors
13015 -m[arm]8[10] Arm 8 processors
13016 -m[arm]9[20][tdmi] Arm 9 processors
13017 -mstrongarm[110[0]] StrongARM processors
13018 -mxscale XScale processors
13019 -m[arm]v[2345[t[e]]] Arm architectures
13020 -mall All (except the ARM1)
13021 FP variants:
13022 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13023 -mfpe-old (No float load/store multiples)
bfae80f2
RE
13024 -mvfpxd VFP Single precision
13025 -mvfp All VFP
b99bd4ef 13026 -mno-fpu Disable all floating point instructions
b99bd4ef 13027
03b1477f
RE
13028 The following CPU names are recognized:
13029 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13030 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13031 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13032 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13033 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13034 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13035 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13036
13037 */
13038
5a38dc70 13039const char * md_shortopts = "m:k";
03b1477f 13040
b99bd4ef
NC
13041#ifdef ARM_BI_ENDIAN
13042#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 13043#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13044#else
21f0f23a
RE
13045#if TARGET_BYTES_BIG_ENDIAN
13046#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
13047#else
13048#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 13049#endif
ce058b6c 13050#endif
03b1477f
RE
13051
13052struct option md_longopts[] =
13053{
13054#ifdef OPTION_EB
13055 {"EB", no_argument, NULL, OPTION_EB},
13056#endif
13057#ifdef OPTION_EL
13058 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
13059#endif
13060 {NULL, no_argument, NULL, 0}
13061};
13062
13063size_t md_longopts_size = sizeof (md_longopts);
13064
03b1477f 13065struct arm_option_table
b99bd4ef 13066{
03b1477f
RE
13067 char *option; /* Option name to match. */
13068 char *help; /* Help information. */
13069 int *var; /* Variable to change. */
13070 int value; /* What to change it to. */
13071 char *deprecated; /* If non-null, print this message. */
13072};
b99bd4ef 13073
cc8a6dd0 13074struct arm_option_table arm_opts[] =
03b1477f
RE
13075{
13076 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
13077 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
13078 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13079 &support_interwork, 1, NULL},
13080 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13081 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13082 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13083 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13084 1, NULL},
13085 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13086 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13087 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13088 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13089 NULL},
13090
13091 /* These are recognized by the assembler, but have no affect on code. */
13092 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13093 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13094
13095 /* DON'T add any new processors to this list -- we want the whole list
13096 to go away... Add them to the processors table instead. */
13097 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13098 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
13099 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13100 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
13101 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13102 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13103 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13104 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13105 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13106 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
13107 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13108 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
13109 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13110 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
13111 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13112 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
13113 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13114 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
13115 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13116 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
13117 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13118 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
13119 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13120 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
13121 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13122 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
13123 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13124 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
13125 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13126 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
13127 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13128 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
13129 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13130 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
13131 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13132 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13133 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13134 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13135 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13136 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13137 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13138 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
13139 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13140 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
13141 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13142 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
13143 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13144 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13145 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13146 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13147 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13148 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13149 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13150 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13151 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13152 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13153 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13154 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
13155 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13156 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
13157 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13158 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13159 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13160 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13161 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13162 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13163 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13164 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13165 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
13166 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13167 N_("use -mcpu=strongarm110")},
13168 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13169 N_("use -mcpu=strongarm1100")},
13170 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13171 N_("use -mcpu=strongarm1110")},
13172 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13173 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13174 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13175
13176 /* Architecture variants -- don't add any more to this list either. */
13177 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13178 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13179 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13180 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13181 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13182 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13183 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13184 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13185 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13186 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13187 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13188 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13189 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13190 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13191 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13192 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13193 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13194 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13195
13196 /* Floating point variants -- don't add any more to this list either. */
13197 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13198 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13199 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13200 {"mno-fpu", NULL, &legacy_fpu, 0,
13201 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13202
13203 {NULL, NULL, NULL, 0, NULL}
13204};
21f0f23a 13205
03b1477f
RE
13206struct arm_cpu_option_table
13207{
13208 char *name;
13209 int value;
13210 /* For some CPUs we assume an FPU unless the user explicitly sets
13211 -mfpu=... */
13212 int default_fpu;
13213};
13214
13215/* This list should, at a minimum, contain all the cpu names
13216 recognized by GCC. */
13217static struct arm_cpu_option_table arm_cpus[] =
13218{
13219 {"all", ARM_ANY, FPU_ARCH_FPA},
13220 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13221 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13222 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13223 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13224 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13225 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13226 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13227 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13228 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13229 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13230 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13231 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13232 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13233 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13234 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13235 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13236 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13237 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13238 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13239 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13240 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13241 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13242 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13243 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13244 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13245 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13246 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13247 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13248 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13249 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13250 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13251 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13252 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13253 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13254 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13255 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13256 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13257 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13258 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13259 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13260 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13261 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13262 /* For V5 or later processors we default to using VFP; but the user
13263 should really set the FPU type explicitly. */
13264 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13265 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13266 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13267 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13268 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13269 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13270 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13271 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13272 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13273 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13274 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13275 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015
MM
13276 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
13277 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
03b1477f
RE
13278 /* ??? XSCALE is really an architecture. */
13279 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13280 /* ??? iwmmxt is not a processor. */
e16bb312 13281 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13282 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13283 /* Maverick */
13284 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
13285 {NULL, 0, 0}
13286};
cc8a6dd0 13287
03b1477f
RE
13288struct arm_arch_option_table
13289{
13290 char *name;
13291 int value;
13292 int default_fpu;
13293};
13294
13295/* This list should, at a minimum, contain all the architecture names
13296 recognized by GCC. */
13297static struct arm_arch_option_table arm_archs[] =
13298{
13299 {"all", ARM_ANY, FPU_ARCH_FPA},
13300 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13301 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13302 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13303 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13304 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13305 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13306 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13307 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13308 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13309 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13310 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13311 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13312 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13313 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13314 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13315 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
09d92015 13316 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
03b1477f 13317 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13318 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13319 {NULL, 0, 0}
13320};
13321
13322/* ISA extensions in the co-processor space. */
13323struct arm_arch_extension_table
13324{
13325 char *name;
13326 int value;
13327};
13328
13329static struct arm_arch_extension_table arm_extensions[] =
13330{
13331 {"maverick", ARM_CEXT_MAVERICK},
13332 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13333 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13334 {NULL, 0}
13335};
b99bd4ef 13336
03b1477f
RE
13337struct arm_fpu_option_table
13338{
13339 char *name;
13340 int value;
13341};
13342
13343/* This list should, at a minimum, contain all the fpu names
13344 recognized by GCC. */
13345static struct arm_fpu_option_table arm_fpus[] =
13346{
13347 {"softfpa", FPU_NONE},
13348 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13349 {"fpe2", FPU_ARCH_FPE},
13350 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13351 {"fpa", FPU_ARCH_FPA},
13352 {"fpa10", FPU_ARCH_FPA},
13353 {"fpa11", FPU_ARCH_FPA},
13354 {"arm7500fe", FPU_ARCH_FPA},
13355 {"softvfp", FPU_ARCH_VFP},
13356 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13357 {"vfp", FPU_ARCH_VFP_V2},
13358 {"vfp9", FPU_ARCH_VFP_V2},
13359 {"vfp10", FPU_ARCH_VFP_V2},
13360 {"vfp10-r0", FPU_ARCH_VFP_V1},
13361 {"vfpxd", FPU_ARCH_VFP_V1xD},
13362 {"arm1020t", FPU_ARCH_VFP_V1},
13363 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13364 {"arm1136jfs", FPU_ARCH_VFP_V2},
03b1477f
RE
13365 {NULL, 0}
13366};
13367
13368struct arm_long_option_table
13369{
13370 char *option; /* Substring to match. */
13371 char *help; /* Help information. */
13372 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
13373 char *deprecated; /* If non-null, print this message. */
13374};
13375
13376static int
13377arm_parse_extension (str, opt_p)
13378 char *str;
13379 int *opt_p;
13380{
13381 while (str != NULL && *str != 0)
13382 {
13383 struct arm_arch_extension_table *opt;
13384 char *ext;
13385 int optlen;
13386
13387 if (*str != '+')
b99bd4ef 13388 {
03b1477f
RE
13389 as_bad (_("invalid architectural extension"));
13390 return 0;
13391 }
b99bd4ef 13392
03b1477f
RE
13393 str++;
13394 ext = strchr (str, '+');
b99bd4ef 13395
03b1477f
RE
13396 if (ext != NULL)
13397 optlen = ext - str;
13398 else
13399 optlen = strlen (str);
b99bd4ef 13400
03b1477f
RE
13401 if (optlen == 0)
13402 {
13403 as_bad (_("missing architectural extension"));
13404 return 0;
13405 }
b99bd4ef 13406
03b1477f
RE
13407 for (opt = arm_extensions; opt->name != NULL; opt++)
13408 if (strncmp (opt->name, str, optlen) == 0)
13409 {
13410 *opt_p |= opt->value;
13411 break;
13412 }
bfae80f2 13413
03b1477f
RE
13414 if (opt->name == NULL)
13415 {
13416 as_bad (_("unknown architectural extnsion `%s'"), str);
13417 return 0;
13418 }
b99bd4ef 13419
03b1477f
RE
13420 str = ext;
13421 };
b99bd4ef 13422
03b1477f
RE
13423 return 1;
13424}
b99bd4ef 13425
03b1477f
RE
13426static int
13427arm_parse_cpu (str)
13428 char *str;
13429{
13430 struct arm_cpu_option_table *opt;
13431 char *ext = strchr (str, '+');
13432 int optlen;
b99bd4ef 13433
03b1477f
RE
13434 if (ext != NULL)
13435 optlen = ext - str;
13436 else
13437 optlen = strlen (str);
b99bd4ef 13438
03b1477f
RE
13439 if (optlen == 0)
13440 {
13441 as_bad (_("missing cpu name `%s'"), str);
13442 return 0;
13443 }
b99bd4ef 13444
03b1477f
RE
13445 for (opt = arm_cpus; opt->name != NULL; opt++)
13446 if (strncmp (opt->name, str, optlen) == 0)
13447 {
13448 mcpu_cpu_opt = opt->value;
13449 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13450
03b1477f
RE
13451 if (ext != NULL)
13452 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13453
03b1477f
RE
13454 return 1;
13455 }
b99bd4ef 13456
03b1477f
RE
13457 as_bad (_("unknown cpu `%s'"), str);
13458 return 0;
13459}
b99bd4ef 13460
03b1477f
RE
13461static int
13462arm_parse_arch (str)
13463 char *str;
13464{
13465 struct arm_arch_option_table *opt;
13466 char *ext = strchr (str, '+');
13467 int optlen;
b99bd4ef 13468
03b1477f
RE
13469 if (ext != NULL)
13470 optlen = ext - str;
13471 else
13472 optlen = strlen (str);
b99bd4ef 13473
03b1477f
RE
13474 if (optlen == 0)
13475 {
13476 as_bad (_("missing architecture name `%s'"), str);
13477 return 0;
13478 }
b99bd4ef 13479
b99bd4ef 13480
03b1477f
RE
13481 for (opt = arm_archs; opt->name != NULL; opt++)
13482 if (strcmp (opt->name, str) == 0)
13483 {
13484 march_cpu_opt = opt->value;
13485 march_fpu_opt = opt->default_fpu;
b99bd4ef 13486
03b1477f
RE
13487 if (ext != NULL)
13488 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13489
03b1477f
RE
13490 return 1;
13491 }
b99bd4ef 13492
03b1477f
RE
13493 as_bad (_("unknown architecture `%s'\n"), str);
13494 return 0;
13495}
13496
13497static int
13498arm_parse_fpu (str)
13499 char *str;
13500{
13501 struct arm_fpu_option_table *opt;
b99bd4ef 13502
03b1477f
RE
13503 for (opt = arm_fpus; opt->name != NULL; opt++)
13504 if (strcmp (opt->name, str) == 0)
13505 {
13506 mfpu_opt = opt->value;
13507 return 1;
13508 }
b99bd4ef 13509
03b1477f
RE
13510 as_bad (_("unknown floating point format `%s'\n"), str);
13511 return 0;
13512}
b99bd4ef 13513
03b1477f
RE
13514struct arm_long_option_table arm_long_opts[] =
13515{
13516 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13517 arm_parse_cpu, NULL},
13518 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13519 arm_parse_arch, NULL},
13520 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13521 arm_parse_fpu, NULL},
13522 {NULL, NULL, 0, NULL}
13523};
b99bd4ef 13524
03b1477f
RE
13525int
13526md_parse_option (c, arg)
13527 int c;
13528 char * arg;
13529{
13530 struct arm_option_table *opt;
13531 struct arm_long_option_table *lopt;
b99bd4ef 13532
03b1477f
RE
13533 switch (c)
13534 {
13535#ifdef OPTION_EB
13536 case OPTION_EB:
13537 target_big_endian = 1;
b99bd4ef 13538 break;
03b1477f 13539#endif
b99bd4ef 13540
03b1477f
RE
13541#ifdef OPTION_EL
13542 case OPTION_EL:
13543 target_big_endian = 0;
b99bd4ef
NC
13544 break;
13545#endif
13546
03b1477f 13547 case 'a':
cc8a6dd0 13548 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13549 ones. */
13550 return 0;
13551
b99bd4ef 13552 default:
03b1477f
RE
13553 for (opt = arm_opts; opt->option != NULL; opt++)
13554 {
13555 if (c == opt->option[0]
13556 && ((arg == NULL && opt->option[1] == 0)
13557 || strcmp (arg, opt->option + 1) == 0))
13558 {
13559#if WARN_DEPRECATED
13560 /* If the option is deprecated, tell the user. */
13561 if (opt->deprecated != NULL)
13562 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13563 arg ? arg : "", _(opt->deprecated));
13564#endif
13565
13566 if (opt->var != NULL)
13567 *opt->var = opt->value;
13568
13569 return 1;
13570 }
13571 }
13572
13573 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13574 {
cc8a6dd0 13575 /* These options are expected to have an argument. */
03b1477f
RE
13576 if (c == lopt->option[0]
13577 && arg != NULL
cc8a6dd0 13578 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13579 strlen (lopt->option + 1)) == 0)
13580 {
13581#if WARN_DEPRECATED
13582 /* If the option is deprecated, tell the user. */
13583 if (lopt->deprecated != NULL)
13584 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13585 _(lopt->deprecated));
13586#endif
13587
13588 /* Call the sup-option parser. */
13589 return (*lopt->func)(arg + strlen (lopt->option) - 1);
13590 }
13591 }
13592
13593 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
13594 return 0;
13595 }
13596
13597 return 1;
13598}
13599
13600void
13601md_show_usage (fp)
13602 FILE * fp;
13603{
03b1477f
RE
13604 struct arm_option_table *opt;
13605 struct arm_long_option_table *lopt;
13606
13607 fprintf (fp, _(" ARM-specific assembler options:\n"));
13608
13609 for (opt = arm_opts; opt->option != NULL; opt++)
13610 if (opt->help != NULL)
13611 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13612
13613 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13614 if (lopt->help != NULL)
13615 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13616
13617#ifdef OPTION_EB
b99bd4ef 13618 fprintf (fp, _("\
03b1477f 13619 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13620#endif
03b1477f
RE
13621
13622#ifdef OPTION_EL
b99bd4ef 13623 fprintf (fp, _("\
03b1477f 13624 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13625#endif
13626}
13627
13628/* We need to be able to fix up arbitrary expressions in some statements.
13629 This is so that we can handle symbols that are an arbitrary distance from
13630 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13631 which returns part of an address in a form which will be valid for
13632 a data instruction. We do this by pushing the expression into a symbol
13633 in the expr_section, and creating a fix for that. */
13634
13635static void
13636fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13637 fragS * frag;
13638 int where;
13639 short int size;
13640 expressionS * exp;
13641 int pc_rel;
13642 int reloc;
13643{
13644 fixS * new_fix;
13645 arm_fix_data * arm_data;
13646
13647 switch (exp->X_op)
13648 {
13649 case O_constant:
13650 case O_symbol:
13651 case O_add:
13652 case O_subtract:
13653 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13654 break;
13655
13656 default:
13657 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13658 pc_rel, reloc);
13659 break;
13660 }
13661
13662 /* Mark whether the fix is to a THUMB instruction, or an ARM
13663 instruction. */
13664 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13665 new_fix->tc_fix_data = (PTR) arm_data;
13666 arm_data->thumb_mode = thumb_mode;
b99bd4ef
NC
13667}
13668
13669/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13670
13671void
13672cons_fix_new_arm (frag, where, size, exp)
13673 fragS * frag;
13674 int where;
13675 int size;
13676 expressionS * exp;
13677{
13678 bfd_reloc_code_real_type type;
13679 int pcrel = 0;
13680
13681 /* Pick a reloc.
13682 FIXME: @@ Should look at CPU word size. */
13683 switch (size)
13684 {
13685 case 1:
13686 type = BFD_RELOC_8;
13687 break;
13688 case 2:
13689 type = BFD_RELOC_16;
13690 break;
13691 case 4:
13692 default:
13693 type = BFD_RELOC_32;
13694 break;
13695 case 8:
13696 type = BFD_RELOC_64;
13697 break;
13698 }
13699
13700 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13701}
13702
13703/* A good place to do this, although this was probably not intended
13704 for this kind of use. We need to dump the literal pool before
13705 references are made to a null symbol pointer. */
13706
13707void
13708arm_cleanup ()
13709{
3d0c9500 13710 literal_pool * pool;
b99bd4ef 13711
3d0c9500
NC
13712 for (pool = list_of_pools; pool; pool = pool->next)
13713 {
13714 /* Put it at the end of the relevent section. */
13715 subseg_set (pool->section, pool->sub_section);
13716 s_ltorg (0);
13717 }
b99bd4ef
NC
13718}
13719
13720void
13721arm_start_line_hook ()
13722{
13723 last_label_seen = NULL;
13724}
13725
13726void
13727arm_frob_label (sym)
13728 symbolS * sym;
13729{
13730 last_label_seen = sym;
13731
13732 ARM_SET_THUMB (sym, thumb_mode);
13733
13734#if defined OBJ_COFF || defined OBJ_ELF
13735 ARM_SET_INTERWORK (sym, support_interwork);
13736#endif
13737
13738 /* Note - do not allow local symbols (.Lxxx) to be labeled
13739 as Thumb functions. This is because these labels, whilst
13740 they exist inside Thumb code, are not the entry points for
13741 possible ARM->Thumb calls. Also, these labels can be used
13742 as part of a computed goto or switch statement. eg gcc
13743 can generate code that looks like this:
13744
13745 ldr r2, [pc, .Laaa]
13746 lsl r3, r3, #2
13747 ldr r2, [r3, r2]
13748 mov pc, r2
cc8a6dd0 13749
b99bd4ef
NC
13750 .Lbbb: .word .Lxxx
13751 .Lccc: .word .Lyyy
13752 ..etc...
13753 .Laaa: .word Lbbb
13754
13755 The first instruction loads the address of the jump table.
13756 The second instruction converts a table index into a byte offset.
13757 The third instruction gets the jump address out of the table.
13758 The fourth instruction performs the jump.
cc8a6dd0 13759
b99bd4ef
NC
13760 If the address stored at .Laaa is that of a symbol which has the
13761 Thumb_Func bit set, then the linker will arrange for this address
13762 to have the bottom bit set, which in turn would mean that the
13763 address computation performed by the third instruction would end
13764 up with the bottom bit set. Since the ARM is capable of unaligned
13765 word loads, the instruction would then load the incorrect address
13766 out of the jump table, and chaos would ensue. */
13767 if (label_is_thumb_function_name
13768 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13769 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13770 {
13771 /* When the address of a Thumb function is taken the bottom
13772 bit of that address should be set. This will allow
13773 interworking between Arm and Thumb functions to work
13774 correctly. */
13775
13776 THUMB_SET_FUNC (sym, 1);
13777
b34976b6 13778 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13779 }
13780}
13781
13782/* Adjust the symbol table. This marks Thumb symbols as distinct from
13783 ARM ones. */
13784
13785void
13786arm_adjust_symtab ()
13787{
13788#ifdef OBJ_COFF
13789 symbolS * sym;
13790
13791 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13792 {
13793 if (ARM_IS_THUMB (sym))
13794 {
13795 if (THUMB_IS_FUNC (sym))
13796 {
13797 /* Mark the symbol as a Thumb function. */
13798 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13799 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13800 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13801
13802 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13803 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13804 else
13805 as_bad (_("%s: unexpected function type: %d"),
13806 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13807 }
cc8a6dd0 13808 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13809 {
13810 case C_EXT:
13811 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13812 break;
13813 case C_STAT:
13814 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13815 break;
13816 case C_LABEL:
13817 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13818 break;
13819 default:
13820 /* Do nothing. */
13821 break;
13822 }
13823 }
13824
13825 if (ARM_IS_INTERWORK (sym))
13826 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13827 }
13828#endif
13829#ifdef OBJ_ELF
13830 symbolS * sym;
13831 char bind;
13832
13833 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13834 {
13835 if (ARM_IS_THUMB (sym))
13836 {
13837 elf_symbol_type * elf_sym;
13838
13839 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13840 bind = ELF_ST_BIND (elf_sym);
13841
13842 /* If it's a .thumb_func, declare it as so,
13843 otherwise tag label as .code 16. */
13844 if (THUMB_IS_FUNC (sym))
13845 elf_sym->internal_elf_sym.st_info =
13846 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13847 else
13848 elf_sym->internal_elf_sym.st_info =
13849 ELF_ST_INFO (bind, STT_ARM_16BIT);
13850 }
13851 }
13852#endif
13853}
13854
13855int
13856arm_data_in_code ()
13857{
13858 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13859 {
13860 *input_line_pointer = '/';
13861 input_line_pointer += 5;
13862 *input_line_pointer = 0;
13863 return 1;
13864 }
13865
13866 return 0;
13867}
13868
13869char *
13870arm_canonicalize_symbol_name (name)
13871 char * name;
13872{
13873 int len;
13874
13875 if (thumb_mode && (len = strlen (name)) > 5
13876 && streq (name + len - 5, "/data"))
13877 *(name + len - 5) = 0;
13878
13879 return name;
13880}
13881
bfc866a6 13882#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13883void
b99bd4ef
NC
13884arm_validate_fix (fixP)
13885 fixS * fixP;
13886{
13887 /* If the destination of the branch is a defined symbol which does not have
13888 the THUMB_FUNC attribute, then we must be calling a function which has
13889 the (interfacearm) attribute. We look for the Thumb entry point to that
13890 function and change the branch to refer to that function instead. */
13891 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13892 && fixP->fx_addsy != NULL
13893 && S_IS_DEFINED (fixP->fx_addsy)
13894 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13895 {
13896 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13897 }
b99bd4ef 13898}
bfc866a6 13899#endif
b99bd4ef 13900
114424c6
AM
13901int
13902arm_force_relocation (fixp)
13903 struct fix * fixp;
13904{
13905#if defined (OBJ_COFF) && defined (TE_PE)
13906 if (fixp->fx_r_type == BFD_RELOC_RVA)
13907 return 1;
13908#endif
13909#ifdef OBJ_ELF
ae6063d4 13910 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13911 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13912 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13913 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13914 return 1;
13915#endif
13916
13917 /* Resolve these relocations even if the symbol is extern or weak. */
13918 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13919 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13920 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13921 return 0;
13922
ae6063d4 13923 return generic_force_reloc (fixp);
114424c6
AM
13924}
13925
b99bd4ef
NC
13926#ifdef OBJ_COFF
13927/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13928 local labels from being added to the output symbol table when they
13929 are used with the ADRL pseudo op. The ADRL relocation should always
13930 be resolved before the binbary is emitted, so it is safe to say that
13931 it is adjustable. */
13932
b34976b6 13933bfd_boolean
b99bd4ef
NC
13934arm_fix_adjustable (fixP)
13935 fixS * fixP;
13936{
13937 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13938 return 1;
13939 return 0;
13940}
13941#endif
114424c6 13942
b99bd4ef
NC
13943#ifdef OBJ_ELF
13944/* Relocations against Thumb function names must be left unadjusted,
13945 so that the linker can use this information to correctly set the
13946 bottom bit of their addresses. The MIPS version of this function
13947 also prevents relocations that are mips-16 specific, but I do not
13948 know why it does this.
13949
13950 FIXME:
13951 There is one other problem that ought to be addressed here, but
13952 which currently is not: Taking the address of a label (rather
13953 than a function) and then later jumping to that address. Such
13954 addresses also ought to have their bottom bit set (assuming that
13955 they reside in Thumb code), but at the moment they will not. */
13956
b34976b6 13957bfd_boolean
b99bd4ef
NC
13958arm_fix_adjustable (fixP)
13959 fixS * fixP;
13960{
13961 if (fixP->fx_addsy == NULL)
13962 return 1;
13963
b99bd4ef
NC
13964 if (THUMB_IS_FUNC (fixP->fx_addsy)
13965 && fixP->fx_subsy == NULL)
13966 return 0;
13967
13968 /* We need the symbol name for the VTABLE entries. */
13969 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13970 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13971 return 0;
13972
a161fe53
AM
13973 /* Don't allow symbols to be discarded on GOT related relocs. */
13974 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13975 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
13976 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
13977 return 0;
13978
b99bd4ef
NC
13979 return 1;
13980}
13981
13982const char *
13983elf32_arm_target_format ()
13984{
13985 if (target_big_endian)
13986 {
13987 if (target_oabi)
13988 return "elf32-bigarm-oabi";
13989 else
13990 return "elf32-bigarm";
13991 }
13992 else
13993 {
13994 if (target_oabi)
13995 return "elf32-littlearm-oabi";
13996 else
13997 return "elf32-littlearm";
13998 }
13999}
14000
14001void
14002armelf_frob_symbol (symp, puntp)
14003 symbolS * symp;
14004 int * puntp;
14005{
14006 elf_frob_symbol (symp, puntp);
14007}
14008
b99bd4ef
NC
14009static bfd_reloc_code_real_type
14010arm_parse_reloc ()
14011{
14012 char id [16];
14013 char * ip;
14014 unsigned int i;
14015 static struct
14016 {
14017 char * str;
14018 int len;
14019 bfd_reloc_code_real_type reloc;
14020 }
14021 reloc_map[] =
14022 {
14023#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14024 MAP ("(got)", BFD_RELOC_ARM_GOT32),
14025 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14026 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14027 branch instructions generated by GCC for PLT relocs. */
14028 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
14029 { NULL, 0, BFD_RELOC_UNUSED }
14030#undef MAP
14031 };
14032
14033 for (i = 0, ip = input_line_pointer;
3882b010 14034 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 14035 i++, ip++)
3882b010 14036 id[i] = TOLOWER (*ip);
b99bd4ef
NC
14037
14038 for (i = 0; reloc_map[i].str; i++)
14039 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14040 break;
14041
14042 input_line_pointer += reloc_map[i].len;
14043
14044 return reloc_map[i].reloc;
14045}
14046
14047static void
14048s_arm_elf_cons (nbytes)
14049 int nbytes;
14050{
14051 expressionS exp;
14052
14053#ifdef md_flush_pending_output
14054 md_flush_pending_output ();
14055#endif
14056
14057 if (is_it_end_of_statement ())
14058 {
14059 demand_empty_rest_of_line ();
14060 return;
14061 }
14062
14063#ifdef md_cons_align
14064 md_cons_align (nbytes);
14065#endif
14066
6057a28f 14067 mapping_state (MAP_DATA);
b99bd4ef
NC
14068 do
14069 {
14070 bfd_reloc_code_real_type reloc;
14071
14072 expression (& exp);
14073
14074 if (exp.X_op == O_symbol
14075 && * input_line_pointer == '('
14076 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14077 {
14078 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14079 int size = bfd_get_reloc_size (howto);
14080
14081 if (size > nbytes)
14082 as_bad ("%s relocations do not fit in %d bytes",
14083 howto->name, nbytes);
14084 else
14085 {
14086 register char *p = frag_more ((int) nbytes);
14087 int offset = nbytes - size;
14088
14089 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14090 &exp, 0, reloc);
14091 }
14092 }
14093 else
14094 emit_expr (&exp, (unsigned int) nbytes);
14095 }
14096 while (*input_line_pointer++ == ',');
14097
14098 /* Put terminator back into stream. */
14099 input_line_pointer --;
14100 demand_empty_rest_of_line ();
14101}
14102
14103#endif /* OBJ_ELF */
14104
14105/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14106 of an rs_align_code fragment. */
14107
14108void
14109arm_handle_align (fragP)
14110 fragS *fragP;
14111{
14112 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14113 static char const thumb_noop[2] = { 0xc0, 0x46 };
14114 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14115 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14116
14117 int bytes, fix, noop_size;
14118 char * p;
14119 const char * noop;
cc8a6dd0 14120
b99bd4ef
NC
14121 if (fragP->fr_type != rs_align_code)
14122 return;
14123
14124 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14125 p = fragP->fr_literal + fragP->fr_fix;
14126 fix = 0;
cc8a6dd0 14127
b99bd4ef
NC
14128 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14129 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14130
b99bd4ef
NC
14131 if (fragP->tc_frag_data)
14132 {
14133 if (target_big_endian)
14134 noop = thumb_bigend_noop;
14135 else
14136 noop = thumb_noop;
14137 noop_size = sizeof (thumb_noop);
14138 }
14139 else
14140 {
14141 if (target_big_endian)
14142 noop = arm_bigend_noop;
14143 else
14144 noop = arm_noop;
14145 noop_size = sizeof (arm_noop);
14146 }
cc8a6dd0 14147
b99bd4ef
NC
14148 if (bytes & (noop_size - 1))
14149 {
14150 fix = bytes & (noop_size - 1);
14151 memset (p, 0, fix);
14152 p += fix;
14153 bytes -= fix;
14154 }
14155
14156 while (bytes >= noop_size)
14157 {
14158 memcpy (p, noop, noop_size);
14159 p += noop_size;
14160 bytes -= noop_size;
14161 fix += noop_size;
14162 }
cc8a6dd0 14163
b99bd4ef
NC
14164 fragP->fr_fix += fix;
14165 fragP->fr_var = noop_size;
14166}
14167
14168/* Called from md_do_align. Used to create an alignment
14169 frag in a code section. */
14170
14171void
14172arm_frag_align_code (n, max)
14173 int n;
14174 int max;
14175{
14176 char * p;
14177
2d2255b5 14178 /* We assume that there will never be a requirement
b99bd4ef
NC
14179 to support alignments greater than 32 bytes. */
14180 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14181 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14182
b99bd4ef
NC
14183 p = frag_var (rs_align_code,
14184 MAX_MEM_FOR_RS_ALIGN_CODE,
14185 1,
14186 (relax_substateT) max,
14187 (symbolS *) NULL,
14188 (offsetT) n,
14189 (char *) NULL);
14190 *p = 0;
14191
14192}
14193
14194/* Perform target specific initialisation of a frag. */
14195
14196void
14197arm_init_frag (fragP)
14198 fragS *fragP;
14199{
14200 /* Record whether this frag is in an ARM or a THUMB area. */
14201 fragP->tc_frag_data = thumb_mode;
14202}
This page took 0.867898 seconds and 4 git commands to generate.