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