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