]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
* m68hc11-tdep.c (m68hc11_register_raw_size): Remove.
[thirdparty/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));
76feaaf3 2064#ifdef OBJ_ELF
b99bd4ef
NC
2065static void s_arm_elf_cons PARAMS ((int));
2066#endif
2067
2068static int my_get_expression PARAMS ((expressionS *, char **));
2069
05d2d07e 2070const pseudo_typeS md_pseudo_table[] =
b99bd4ef
NC
2071{
2072 /* Never called becasue '.req' does not start line. */
2073 { "req", s_req, 0 },
2074 { "bss", s_bss, 0 },
2075 { "align", s_align, 0 },
2076 { "arm", s_arm, 0 },
2077 { "thumb", s_thumb, 0 },
2078 { "code", s_code, 0 },
2079 { "force_thumb", s_force_thumb, 0 },
2080 { "thumb_func", s_thumb_func, 0 },
2081 { "thumb_set", s_thumb_set, 0 },
2082 { "even", s_even, 0 },
2083 { "ltorg", s_ltorg, 0 },
2084 { "pool", s_ltorg, 0 },
76feaaf3 2085#ifdef OBJ_ELF
b99bd4ef
NC
2086 { "word", s_arm_elf_cons, 4 },
2087 { "long", s_arm_elf_cons, 4 },
3d0c9500 2088 { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
b99bd4ef
NC
2089 { "loc", dwarf2_directive_loc, 0 },
2090#else
2091 { "word", cons, 4},
2092#endif
2093 { "extend", float_cons, 'x' },
2094 { "ldouble", float_cons, 'x' },
2095 { "packed", float_cons, 'p' },
2096 { 0, 0, 0 }
2097};
2098
03b1477f
RE
2099/* Other internal functions. */
2100static int arm_parse_extension PARAMS ((char *, int *));
2101static int arm_parse_cpu PARAMS ((char *));
2102static int arm_parse_arch PARAMS ((char *));
2103static int arm_parse_fpu PARAMS ((char *));
2104
b99bd4ef
NC
2105/* Stuff needed to resolve the label ambiguity
2106 As:
2107 ...
2108 label: <insn>
2109 may differ from:
2110 ...
2111 label:
2112 <insn>
2113*/
2114
2115symbolS * last_label_seen;
2116static int label_is_thumb_function_name = false;
2117
3d0c9500 2118/* Literal Pool stuff. */
b99bd4ef
NC
2119
2120#define MAX_LITERAL_POOL_SIZE 1024
2121
3d0c9500
NC
2122/* Literal pool structure. Held on a per-section
2123 and per-sub-section basis. */
2124typedef struct literal_pool
b99bd4ef 2125{
3d0c9500
NC
2126 expressionS literals [MAX_LITERAL_POOL_SIZE];
2127 unsigned int next_free_entry;
2128 unsigned int id;
2129 symbolS * symbol;
2130 segT section;
2131 subsegT sub_section;
2132 struct literal_pool * next;
2133} literal_pool;
b99bd4ef 2134
3d0c9500
NC
2135/* Pointer to a linked list of literal pools. */
2136literal_pool * list_of_pools = NULL;
b99bd4ef 2137
3d0c9500
NC
2138static literal_pool * find_literal_pool PARAMS ((void));
2139static literal_pool * find_or_make_literal_pool PARAMS ((void));
b99bd4ef 2140
3d0c9500
NC
2141static literal_pool *
2142find_literal_pool ()
2143{
2144 literal_pool * pool;
2145
2146 for (pool = list_of_pools; pool != NULL; pool = pool->next)
2147 {
2148 if (pool->section == now_seg
2149 && pool->sub_section == now_subseg)
2150 break;
2151 }
2152
2153 return pool;
2154}
b99bd4ef 2155
3d0c9500
NC
2156static literal_pool *
2157find_or_make_literal_pool ()
2158{
2159 /* Next literal pool ID number. */
2160 static unsigned int latest_pool_num = 1;
2161 literal_pool * pool;
2162
2163 pool = find_literal_pool ();
b99bd4ef 2164
3d0c9500
NC
2165 if (pool == NULL)
2166 {
2167 /* Create a new pool. */
2168 pool = (literal_pool *) xmalloc (sizeof (* pool));
2169 if (! pool)
2170 return NULL;
2171
2172 pool->next_free_entry = 0;
2173 pool->section = now_seg;
2174 pool->sub_section = now_subseg;
2175 pool->next = list_of_pools;
2176 pool->symbol = NULL;
2177
2178 /* Add it to the list. */
2179 list_of_pools = pool;
2180 }
2181
2182 /* New pools, and emptied pools, will have a NULL symbol. */
2183 if (pool->symbol == NULL)
2184 {
2185 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2186 (valueT) 0, &zero_address_frag);
2187 pool->id = latest_pool_num ++;
2188 }
2189
2190 /* Done. */
2191 return pool;
2192}
2193
2194/* Add the literal in the global 'inst'
2195 structure to the relevent literal pool. */
b99bd4ef
NC
2196static int
2197add_to_lit_pool ()
2198{
3d0c9500
NC
2199 literal_pool * pool;
2200 unsigned int entry;
b99bd4ef 2201
3d0c9500 2202 pool = find_or_make_literal_pool ();
b99bd4ef 2203
3d0c9500
NC
2204 /* Check if this literal value is already in the pool. */
2205 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2206 {
3d0c9500
NC
2207 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2208 && (inst.reloc.exp.X_op == O_constant)
2209 && (pool->literals[entry].X_add_number
b99bd4ef 2210 == inst.reloc.exp.X_add_number)
3d0c9500
NC
2211 && (pool->literals[entry].X_unsigned
2212 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
2213 break;
2214
3d0c9500
NC
2215 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2216 && (inst.reloc.exp.X_op == O_symbol)
2217 && (pool->literals[entry].X_add_number
b99bd4ef 2218 == inst.reloc.exp.X_add_number)
3d0c9500 2219 && (pool->literals[entry].X_add_symbol
b99bd4ef 2220 == inst.reloc.exp.X_add_symbol)
3d0c9500 2221 && (pool->literals[entry].X_op_symbol
b99bd4ef 2222 == inst.reloc.exp.X_op_symbol))
3d0c9500 2223 break;
b99bd4ef
NC
2224 }
2225
3d0c9500
NC
2226 /* Do we need to create a new entry? */
2227 if (entry == pool->next_free_entry)
b99bd4ef 2228 {
3d0c9500 2229 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 2230 {
ed71e111 2231 inst.error = _("literal pool overflow");
b99bd4ef
NC
2232 return FAIL;
2233 }
2234
3d0c9500
NC
2235 pool->literals[entry] = inst.reloc.exp;
2236 pool->next_free_entry += 1;
b99bd4ef
NC
2237 }
2238
3d0c9500 2239 inst.reloc.exp.X_op = O_symbol;
08df2379 2240 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 2241 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
2242
2243 return SUCCESS;
2244}
2245
2246/* Can't use symbol_new here, so have to create a symbol and then at
2247 a later date assign it a value. Thats what these functions do. */
2248
2249static void
2250symbol_locate (symbolP, name, segment, valu, frag)
2251 symbolS * symbolP;
05d2d07e 2252 const char * name; /* It is copied, the caller can modify. */
b99bd4ef
NC
2253 segT segment; /* Segment identifier (SEG_<something>). */
2254 valueT valu; /* Symbol value. */
2255 fragS * frag; /* Associated fragment. */
2256{
2257 unsigned int name_length;
2258 char * preserved_copy_of_name;
2259
2260 name_length = strlen (name) + 1; /* +1 for \0. */
2261 obstack_grow (&notes, name, name_length);
2262 preserved_copy_of_name = obstack_finish (&notes);
2263#ifdef STRIP_UNDERSCORE
2264 if (preserved_copy_of_name[0] == '_')
2265 preserved_copy_of_name++;
2266#endif
2267
2268#ifdef tc_canonicalize_symbol_name
2269 preserved_copy_of_name =
2270 tc_canonicalize_symbol_name (preserved_copy_of_name);
2271#endif
2272
2273 S_SET_NAME (symbolP, preserved_copy_of_name);
2274
2275 S_SET_SEGMENT (symbolP, segment);
2276 S_SET_VALUE (symbolP, valu);
c62e1cc3 2277 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
2278
2279 symbol_set_frag (symbolP, frag);
2280
2281 /* Link to end of symbol chain. */
2282 {
2283 extern int symbol_table_frozen;
2284 if (symbol_table_frozen)
2285 abort ();
2286 }
2287
2288 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2289
2290 obj_symbol_new_hook (symbolP);
2291
2292#ifdef tc_symbol_new_hook
2293 tc_symbol_new_hook (symbolP);
2294#endif
2295
2296#ifdef DEBUG_SYMS
2297 verify_symbol_chain (symbol_rootP, symbol_lastP);
2298#endif /* DEBUG_SYMS */
2299}
2300
2301/* Check that an immediate is valid.
2302 If so, convert it to the right format. */
2303
2304static unsigned int
2305validate_immediate (val)
2306 unsigned int val;
2307{
2308 unsigned int a;
2309 unsigned int i;
2310
2311#define rotate_left(v, n) (v << n | v >> (32 - n))
2312
2313 for (i = 0; i < 32; i += 2)
2314 if ((a = rotate_left (val, i)) <= 0xff)
2315 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
2316
2317 return FAIL;
2318}
2319
2320/* Check to see if an immediate can be computed as two seperate immediate
2321 values, added together. We already know that this value cannot be
2322 computed by just one ARM instruction. */
2323
2324static unsigned int
2325validate_immediate_twopart (val, highpart)
2326 unsigned int val;
2327 unsigned int * highpart;
2328{
2329 unsigned int a;
2330 unsigned int i;
2331
2332 for (i = 0; i < 32; i += 2)
2333 if (((a = rotate_left (val, i)) & 0xff) != 0)
2334 {
2335 if (a & 0xff00)
2336 {
2337 if (a & ~ 0xffff)
2338 continue;
2339 * highpart = (a >> 8) | ((i + 24) << 7);
2340 }
2341 else if (a & 0xff0000)
2342 {
2343 if (a & 0xff000000)
2344 continue;
2345 * highpart = (a >> 16) | ((i + 16) << 7);
2346 }
2347 else
2348 {
2349 assert (a & 0xff000000);
2350 * highpart = (a >> 24) | ((i + 8) << 7);
2351 }
2352
2353 return (a & 0xff) | (i << 7);
2354 }
2355
2356 return FAIL;
2357}
2358
2359static int
2360validate_offset_imm (val, hwse)
2361 unsigned int val;
2362 int hwse;
2363{
2364 if ((hwse && val > 255) || val > 4095)
2365 return FAIL;
2366 return val;
2367}
2368
2369static void
2370s_req (a)
2371 int a ATTRIBUTE_UNUSED;
2372{
f03698e6 2373 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
2374}
2375
2376static void
2377s_bss (ignore)
2378 int ignore ATTRIBUTE_UNUSED;
2379{
2380 /* We don't support putting frags in the BSS segment, we fake it by
2381 marking in_bss, then looking at s_skip for clues. */
2382 subseg_set (bss_section, 0);
2383 demand_empty_rest_of_line ();
2384}
2385
2386static void
2387s_even (ignore)
2388 int ignore ATTRIBUTE_UNUSED;
2389{
2390 /* Never make frag if expect extra pass. */
2391 if (!need_pass_2)
2392 frag_align (1, 0, 0);
2393
2394 record_alignment (now_seg, 1);
2395
2396 demand_empty_rest_of_line ();
2397}
2398
2399static void
2400s_ltorg (ignored)
2401 int ignored ATTRIBUTE_UNUSED;
2402{
3d0c9500
NC
2403 unsigned int entry;
2404 literal_pool * pool;
b99bd4ef
NC
2405 char sym_name[20];
2406
3d0c9500
NC
2407 pool = find_literal_pool ();
2408 if (pool == NULL
2409 || pool->symbol == NULL
2410 || pool->next_free_entry == 0)
b99bd4ef
NC
2411 return;
2412
2413 /* Align pool as you have word accesses.
2414 Only make a frag if we have to. */
2415 if (!need_pass_2)
2416 frag_align (2, 0, 0);
2417
2418 record_alignment (now_seg, 2);
2419
3d0c9500 2420 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 2421
3d0c9500 2422 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 2423 (valueT) frag_now_fix (), frag_now);
3d0c9500 2424 symbol_table_insert (pool->symbol);
b99bd4ef 2425
3d0c9500 2426 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
2427
2428#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 2429 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
2430#endif
2431
3d0c9500 2432 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 2433 /* First output the expression in the instruction to the pool. */
3d0c9500 2434 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 2435
3d0c9500
NC
2436 /* Mark the pool as empty. */
2437 pool->next_free_entry = 0;
2438 pool->symbol = NULL;
b99bd4ef
NC
2439}
2440
2441/* Same as s_align_ptwo but align 0 => align 2. */
2442
2443static void
2444s_align (unused)
2445 int unused ATTRIBUTE_UNUSED;
2446{
2447 register int temp;
2448 register long temp_fill;
2449 long max_alignment = 15;
2450
2451 temp = get_absolute_expression ();
2452 if (temp > max_alignment)
f03698e6 2453 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
2454 else if (temp < 0)
2455 {
f03698e6 2456 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
2457 temp = 0;
2458 }
2459
2460 if (*input_line_pointer == ',')
2461 {
2462 input_line_pointer++;
2463 temp_fill = get_absolute_expression ();
2464 }
2465 else
2466 temp_fill = 0;
2467
2468 if (!temp)
2469 temp = 2;
2470
2471 /* Only make a frag if we HAVE to. */
2472 if (temp && !need_pass_2)
2473 frag_align (temp, (int) temp_fill, 0);
2474 demand_empty_rest_of_line ();
2475
2476 record_alignment (now_seg, temp);
2477}
2478
2479static void
2480s_force_thumb (ignore)
2481 int ignore ATTRIBUTE_UNUSED;
2482{
2483 /* If we are not already in thumb mode go into it, EVEN if
2484 the target processor does not support thumb instructions.
2485 This is used by gcc/config/arm/lib1funcs.asm for example
2486 to compile interworking support functions even if the
2487 target processor should not support interworking. */
2488 if (! thumb_mode)
2489 {
2490 thumb_mode = 2;
2491
2492 record_alignment (now_seg, 1);
2493 }
2494
2495 demand_empty_rest_of_line ();
2496}
2497
2498static void
2499s_thumb_func (ignore)
2500 int ignore ATTRIBUTE_UNUSED;
2501{
2502 if (! thumb_mode)
2503 opcode_select (16);
2504
2505 /* The following label is the name/address of the start of a Thumb function.
2506 We need to know this for the interworking support. */
2507 label_is_thumb_function_name = true;
2508
2509 demand_empty_rest_of_line ();
2510}
2511
2512/* Perform a .set directive, but also mark the alias as
2513 being a thumb function. */
2514
2515static void
2516s_thumb_set (equiv)
2517 int equiv;
2518{
2519 /* XXX the following is a duplicate of the code for s_set() in read.c
2520 We cannot just call that code as we need to get at the symbol that
2521 is created. */
2522 register char * name;
2523 register char delim;
2524 register char * end_name;
2525 register symbolS * symbolP;
2526
2527 /* Especial apologies for the random logic:
2528 This just grew, and could be parsed much more simply!
2529 Dean - in haste. */
2530 name = input_line_pointer;
2531 delim = get_symbol_end ();
2532 end_name = input_line_pointer;
2533 *end_name = delim;
2534
2535 SKIP_WHITESPACE ();
2536
2537 if (*input_line_pointer != ',')
2538 {
2539 *end_name = 0;
f03698e6 2540 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
2541 *end_name = delim;
2542 ignore_rest_of_line ();
2543 return;
2544 }
2545
2546 input_line_pointer++;
2547 *end_name = 0;
2548
2549 if (name[0] == '.' && name[1] == '\0')
2550 {
2551 /* XXX - this should not happen to .thumb_set. */
2552 abort ();
2553 }
2554
2555 if ((symbolP = symbol_find (name)) == NULL
2556 && (symbolP = md_undefined_symbol (name)) == NULL)
2557 {
2558#ifndef NO_LISTING
2559 /* When doing symbol listings, play games with dummy fragments living
2560 outside the normal fragment chain to record the file and line info
2561 for this symbol. */
2562 if (listing & LISTING_SYMBOLS)
2563 {
2564 extern struct list_info_struct * listing_tail;
2565 fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2566
2567 memset (dummy_frag, 0, sizeof (fragS));
2568 dummy_frag->fr_type = rs_fill;
2569 dummy_frag->line = listing_tail;
2570 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2571 dummy_frag->fr_symbol = symbolP;
2572 }
2573 else
2574#endif
2575 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2576
2577#ifdef OBJ_COFF
2578 /* "set" symbols are local unless otherwise specified. */
2579 SF_SET_LOCAL (symbolP);
2580#endif /* OBJ_COFF */
2581 } /* Make a new symbol. */
2582
2583 symbol_table_insert (symbolP);
2584
2585 * end_name = delim;
2586
2587 if (equiv
2588 && S_IS_DEFINED (symbolP)
2589 && S_GET_SEGMENT (symbolP) != reg_section)
2590 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2591
2592 pseudo_set (symbolP);
2593
2594 demand_empty_rest_of_line ();
2595
2596 /* XXX Now we come to the Thumb specific bit of code. */
2597
2598 THUMB_SET_FUNC (symbolP, 1);
2599 ARM_SET_THUMB (symbolP, 1);
2600#if defined OBJ_ELF || defined OBJ_COFF
2601 ARM_SET_INTERWORK (symbolP, support_interwork);
2602#endif
2603}
2604
b99bd4ef
NC
2605static void
2606opcode_select (width)
2607 int width;
2608{
2609 switch (width)
2610 {
2611 case 16:
2612 if (! thumb_mode)
2613 {
b89dddec 2614 if (! (cpu_variant & ARM_EXT_V4T))
b99bd4ef
NC
2615 as_bad (_("selected processor does not support THUMB opcodes"));
2616
2617 thumb_mode = 1;
2618 /* No need to force the alignment, since we will have been
2619 coming from ARM mode, which is word-aligned. */
2620 record_alignment (now_seg, 1);
2621 }
2622 break;
2623
2624 case 32:
2625 if (thumb_mode)
2626 {
03b1477f 2627 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
b99bd4ef
NC
2628 as_bad (_("selected processor does not support ARM opcodes"));
2629
2630 thumb_mode = 0;
2631
2632 if (!need_pass_2)
cc8a6dd0 2633 frag_align (2, 0, 0);
b99bd4ef 2634
cc8a6dd0 2635 record_alignment (now_seg, 1);
b99bd4ef
NC
2636 }
2637 break;
2638
2639 default:
2640 as_bad (_("invalid instruction size selected (%d)"), width);
2641 }
2642}
2643
2644static void
2645s_arm (ignore)
2646 int ignore ATTRIBUTE_UNUSED;
2647{
2648 opcode_select (32);
2649 demand_empty_rest_of_line ();
2650}
2651
2652static void
2653s_thumb (ignore)
2654 int ignore ATTRIBUTE_UNUSED;
2655{
2656 opcode_select (16);
2657 demand_empty_rest_of_line ();
2658}
2659
2660static void
2661s_code (unused)
2662 int unused ATTRIBUTE_UNUSED;
2663{
2664 register int temp;
2665
2666 temp = get_absolute_expression ();
2667 switch (temp)
2668 {
2669 case 16:
2670 case 32:
2671 opcode_select (temp);
2672 break;
2673
2674 default:
2675 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2676 }
2677}
2678
2679static void
2680end_of_line (str)
f03698e6 2681 char *str;
b99bd4ef
NC
2682{
2683 skip_whitespace (str);
2684
f03698e6
RE
2685 if (*str != '\0' && !inst.error)
2686 inst.error = _("garbage following instruction");
b99bd4ef
NC
2687}
2688
2689static int
2690skip_past_comma (str)
2691 char ** str;
2692{
2693 char * p = * str, c;
2694 int comma = 0;
2695
2696 while ((c = *p) == ' ' || c == ',')
2697 {
2698 p++;
2699 if (c == ',' && comma++)
2700 return FAIL;
2701 }
2702
2703 if (c == '\0')
2704 return FAIL;
2705
2706 *str = p;
2707 return comma ? SUCCESS : FAIL;
2708}
2709
2710/* A standard register must be given at this point.
2711 SHIFT is the place to put it in inst.instruction.
2712 Restores input start point on error.
2713 Returns the reg#, or FAIL. */
2714
2715static int
2716reg_required_here (str, shift)
2717 char ** str;
2718 int shift;
2719{
2720 static char buff [128]; /* XXX */
2721 int reg;
2722 char * start = * str;
2723
6c43fab6 2724 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
2725 {
2726 if (shift >= 0)
2727 inst.instruction |= reg << shift;
2728 return reg;
2729 }
2730
2731 /* Restore the start point, we may have got a reg of the wrong class. */
2732 *str = start;
2733
2734 /* In the few cases where we might be able to accept something else
2735 this error can be overridden. */
f03698e6 2736 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
2737 inst.error = buff;
2738
2739 return FAIL;
2740}
2741
05d2d07e 2742static const struct asm_psr *
b99bd4ef
NC
2743arm_psr_parse (ccp)
2744 register char ** ccp;
2745{
2746 char * start = * ccp;
2747 char c;
2748 char * p;
05d2d07e 2749 const struct asm_psr * psr;
b99bd4ef
NC
2750
2751 p = start;
2752
2753 /* Skip to the end of the next word in the input stream. */
2754 do
2755 {
2756 c = *p++;
2757 }
3882b010 2758 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2759
2760 /* Terminate the word. */
2761 *--p = 0;
2762
2763 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2764 feature for ease of use and backwards compatibility. */
2765 if (!strncmp (start, "cpsr", 4))
2766 strncpy (start, "CPSR", 4);
2767 else if (!strncmp (start, "spsr", 4))
2768 strncpy (start, "SPSR", 4);
2769
2770 /* Now locate the word in the psr hash table. */
05d2d07e 2771 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
2772
2773 /* Restore the input stream. */
2774 *p = c;
2775
2776 /* If we found a valid match, advance the
2777 stream pointer past the end of the word. */
2778 *ccp = p;
2779
2780 return psr;
2781}
2782
2783/* Parse the input looking for a PSR flag. */
2784
2785static int
2786psr_required_here (str)
2787 char ** str;
2788{
2789 char * start = * str;
05d2d07e 2790 const struct asm_psr * psr;
b99bd4ef
NC
2791
2792 psr = arm_psr_parse (str);
2793
2794 if (psr)
2795 {
2796 /* If this is the SPSR that is being modified, set the R bit. */
2797 if (! psr->cpsr)
2798 inst.instruction |= SPSR_BIT;
2799
2800 /* Set the psr flags in the MSR instruction. */
2801 inst.instruction |= psr->field << PSR_SHIFT;
2802
2803 return SUCCESS;
2804 }
2805
2806 /* In the few cases where we might be able to accept
2807 something else this error can be overridden. */
2808 inst.error = _("flag for {c}psr instruction expected");
2809
2810 /* Restore the start point. */
2811 *str = start;
2812 return FAIL;
2813}
2814
2815static int
2816co_proc_number (str)
6c43fab6 2817 char **str;
b99bd4ef
NC
2818{
2819 int processor, pchar;
6c43fab6 2820 char *start;
b99bd4ef 2821
6c43fab6
RE
2822 skip_whitespace (*str);
2823 start = *str;
b99bd4ef
NC
2824
2825 /* The data sheet seems to imply that just a number on its own is valid
2826 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2827 accept either. */
6c43fab6
RE
2828 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2829 == FAIL)
b99bd4ef 2830 {
6c43fab6
RE
2831 *str = start;
2832
2833 pchar = *(*str)++;
2834 if (pchar >= '0' && pchar <= '9')
b99bd4ef 2835 {
6c43fab6
RE
2836 processor = pchar - '0';
2837 if (**str >= '0' && **str <= '9')
b99bd4ef 2838 {
6c43fab6
RE
2839 processor = processor * 10 + *(*str)++ - '0';
2840 if (processor > 15)
2841 {
f03698e6 2842 inst.error = _("illegal co-processor number");
6c43fab6
RE
2843 return FAIL;
2844 }
b99bd4ef
NC
2845 }
2846 }
6c43fab6
RE
2847 else
2848 {
f03698e6 2849 inst.error = _("bad or missing co-processor number");
6c43fab6
RE
2850 return FAIL;
2851 }
b99bd4ef
NC
2852 }
2853
2854 inst.instruction |= processor << 8;
2855 return SUCCESS;
2856}
2857
2858static int
2859cp_opc_expr (str, where, length)
2860 char ** str;
2861 int where;
2862 int length;
2863{
2864 expressionS expr;
2865
2866 skip_whitespace (* str);
2867
2868 memset (&expr, '\0', sizeof (expr));
2869
2870 if (my_get_expression (&expr, str))
2871 return FAIL;
2872 if (expr.X_op != O_constant)
2873 {
2874 inst.error = _("bad or missing expression");
2875 return FAIL;
2876 }
2877
2878 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2879 {
2880 inst.error = _("immediate co-processor expression too large");
2881 return FAIL;
2882 }
2883
2884 inst.instruction |= expr.X_add_number << where;
2885 return SUCCESS;
2886}
2887
2888static int
2889cp_reg_required_here (str, where)
2890 char ** str;
2891 int where;
2892{
2893 int reg;
2894 char * start = *str;
2895
6c43fab6 2896 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 2897 {
b99bd4ef
NC
2898 inst.instruction |= reg << where;
2899 return reg;
2900 }
2901
2902 /* In the few cases where we might be able to accept something else
2903 this error can be overridden. */
f03698e6 2904 inst.error = _("co-processor register expected");
b99bd4ef
NC
2905
2906 /* Restore the start point. */
2907 *str = start;
2908 return FAIL;
2909}
2910
2911static int
2912fp_reg_required_here (str, where)
2913 char ** str;
2914 int where;
2915{
2916 int reg;
2917 char * start = * str;
2918
6c43fab6 2919 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 2920 {
b99bd4ef
NC
2921 inst.instruction |= reg << where;
2922 return reg;
2923 }
2924
2925 /* In the few cases where we might be able to accept something else
2926 this error can be overridden. */
f03698e6 2927 inst.error = _("floating point register expected");
b99bd4ef
NC
2928
2929 /* Restore the start point. */
2930 *str = start;
2931 return FAIL;
2932}
2933
2934static int
2935cp_address_offset (str)
2936 char ** str;
2937{
2938 int offset;
2939
2940 skip_whitespace (* str);
2941
2942 if (! is_immediate_prefix (**str))
2943 {
2944 inst.error = _("immediate expression expected");
2945 return FAIL;
2946 }
2947
2948 (*str)++;
2949
2950 if (my_get_expression (& inst.reloc.exp, str))
2951 return FAIL;
2952
2953 if (inst.reloc.exp.X_op == O_constant)
2954 {
2955 offset = inst.reloc.exp.X_add_number;
2956
2957 if (offset & 3)
2958 {
2959 inst.error = _("co-processor address must be word aligned");
2960 return FAIL;
2961 }
2962
2963 if (offset > 1023 || offset < -1023)
2964 {
2965 inst.error = _("offset too large");
2966 return FAIL;
2967 }
2968
2969 if (offset >= 0)
2970 inst.instruction |= INDEX_UP;
2971 else
2972 offset = -offset;
2973
2974 inst.instruction |= offset >> 2;
2975 }
2976 else
2977 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2978
2979 return SUCCESS;
2980}
2981
2982static int
bfae80f2 2983cp_address_required_here (str, wb_ok)
b99bd4ef 2984 char ** str;
bfae80f2 2985 int wb_ok;
b99bd4ef
NC
2986{
2987 char * p = * str;
2988 int pre_inc = 0;
2989 int write_back = 0;
2990
2991 if (*p == '[')
2992 {
2993 int reg;
2994
2995 p++;
2996 skip_whitespace (p);
2997
2998 if ((reg = reg_required_here (& p, 16)) == FAIL)
2999 return FAIL;
3000
3001 skip_whitespace (p);
3002
3003 if (*p == ']')
3004 {
3005 p++;
3006
bfae80f2 3007 if (wb_ok && skip_past_comma (& p) == SUCCESS)
b99bd4ef
NC
3008 {
3009 /* [Rn], #expr */
3010 write_back = WRITE_BACK;
3011
3012 if (reg == REG_PC)
3013 {
3014 inst.error = _("pc may not be used in post-increment");
3015 return FAIL;
3016 }
3017
3018 if (cp_address_offset (& p) == FAIL)
3019 return FAIL;
3020 }
3021 else
3022 pre_inc = PRE_INDEX | INDEX_UP;
3023 }
3024 else
3025 {
3026 /* '['Rn, #expr']'[!] */
3027
3028 if (skip_past_comma (& p) == FAIL)
3029 {
3030 inst.error = _("pre-indexed expression expected");
3031 return FAIL;
3032 }
3033
3034 pre_inc = PRE_INDEX;
3035
3036 if (cp_address_offset (& p) == FAIL)
3037 return FAIL;
3038
3039 skip_whitespace (p);
3040
3041 if (*p++ != ']')
3042 {
3043 inst.error = _("missing ]");
3044 return FAIL;
3045 }
3046
3047 skip_whitespace (p);
3048
bfae80f2 3049 if (wb_ok && *p == '!')
b99bd4ef
NC
3050 {
3051 if (reg == REG_PC)
3052 {
3053 inst.error = _("pc may not be used with write-back");
3054 return FAIL;
3055 }
3056
3057 p++;
3058 write_back = WRITE_BACK;
3059 }
3060 }
3061 }
3062 else
3063 {
3064 if (my_get_expression (&inst.reloc.exp, &p))
3065 return FAIL;
3066
3067 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3068 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3069 inst.reloc.pc_rel = 1;
3070 inst.instruction |= (REG_PC << 16);
3071 pre_inc = PRE_INDEX;
3072 }
3073
3074 inst.instruction |= write_back | pre_inc;
3075 *str = p;
3076 return SUCCESS;
3077}
3078
3079static void
f2b7cb0a 3080do_empty (str)
b99bd4ef 3081 char * str;
b99bd4ef
NC
3082{
3083 /* Do nothing really. */
b99bd4ef
NC
3084 end_of_line (str);
3085 return;
3086}
3087
3088static void
f2b7cb0a 3089do_mrs (str)
b99bd4ef 3090 char *str;
b99bd4ef
NC
3091{
3092 int skip = 0;
3093
3094 /* Only one syntax. */
3095 skip_whitespace (str);
3096
3097 if (reg_required_here (&str, 12) == FAIL)
3098 {
3099 inst.error = BAD_ARGS;
3100 return;
3101 }
3102
3103 if (skip_past_comma (&str) == FAIL)
3104 {
3105 inst.error = _("comma expected after register name");
3106 return;
3107 }
3108
3109 skip_whitespace (str);
3110
3111 if ( strcmp (str, "CPSR") == 0
3112 || strcmp (str, "SPSR") == 0
3113 /* Lower case versions for backwards compatability. */
3114 || strcmp (str, "cpsr") == 0
3115 || strcmp (str, "spsr") == 0)
3116 skip = 4;
3117
3118 /* This is for backwards compatability with older toolchains. */
3119 else if ( strcmp (str, "cpsr_all") == 0
3120 || strcmp (str, "spsr_all") == 0)
3121 skip = 8;
3122 else
3123 {
f03698e6 3124 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
3125 return;
3126 }
3127
3128 if (* str == 's' || * str == 'S')
3129 inst.instruction |= SPSR_BIT;
3130 str += skip;
3131
b99bd4ef
NC
3132 end_of_line (str);
3133}
3134
3135/* Two possible forms:
3136 "{C|S}PSR_<field>, Rm",
3137 "{C|S}PSR_f, #expression". */
3138
3139static void
f2b7cb0a 3140do_msr (str)
b99bd4ef 3141 char * str;
b99bd4ef
NC
3142{
3143 skip_whitespace (str);
3144
3145 if (psr_required_here (& str) == FAIL)
3146 return;
3147
3148 if (skip_past_comma (& str) == FAIL)
3149 {
3150 inst.error = _("comma missing after psr flags");
3151 return;
3152 }
3153
3154 skip_whitespace (str);
3155
3156 if (reg_required_here (& str, 0) != FAIL)
3157 {
3158 inst.error = NULL;
b99bd4ef
NC
3159 end_of_line (str);
3160 return;
3161 }
3162
3163 if (! is_immediate_prefix (* str))
3164 {
3165 inst.error =
3166 _("only a register or immediate value can follow a psr flag");
3167 return;
3168 }
3169
3170 str ++;
3171 inst.error = NULL;
3172
3173 if (my_get_expression (& inst.reloc.exp, & str))
3174 {
3175 inst.error =
3176 _("only a register or immediate value can follow a psr flag");
3177 return;
3178 }
3179
3180#if 0 /* The first edition of the ARM architecture manual stated that
3181 writing anything other than the flags with an immediate operation
3182 had UNPREDICTABLE effects. This constraint was removed in the
3183 second edition of the specification. */
3184 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3185 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3186 {
3187 inst.error = _("immediate value cannot be used to set this field");
3188 return;
3189 }
3190#endif
3191
f2b7cb0a 3192 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
3193
3194 if (inst.reloc.exp.X_add_symbol)
3195 {
3196 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3197 inst.reloc.pc_rel = 0;
3198 }
3199 else
3200 {
3201 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3202
3203 if (value == (unsigned) FAIL)
3204 {
f03698e6 3205 inst.error = _("invalid constant");
b99bd4ef
NC
3206 return;
3207 }
3208
3209 inst.instruction |= value;
3210 }
3211
3212 inst.error = NULL;
b99bd4ef
NC
3213 end_of_line (str);
3214}
3215
3216/* Long Multiply Parser
3217 UMULL RdLo, RdHi, Rm, Rs
3218 SMULL RdLo, RdHi, Rm, Rs
3219 UMLAL RdLo, RdHi, Rm, Rs
3220 SMLAL RdLo, RdHi, Rm, Rs. */
3221
3222static void
f2b7cb0a 3223do_mull (str)
b99bd4ef 3224 char * str;
b99bd4ef
NC
3225{
3226 int rdlo, rdhi, rm, rs;
3227
3228 /* Only one format "rdlo, rdhi, rm, rs". */
3229 skip_whitespace (str);
3230
3231 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3232 {
3233 inst.error = BAD_ARGS;
3234 return;
3235 }
3236
3237 if (skip_past_comma (&str) == FAIL
3238 || (rdhi = reg_required_here (&str, 16)) == FAIL)
3239 {
3240 inst.error = BAD_ARGS;
3241 return;
3242 }
3243
3244 if (skip_past_comma (&str) == FAIL
3245 || (rm = reg_required_here (&str, 0)) == FAIL)
3246 {
3247 inst.error = BAD_ARGS;
3248 return;
3249 }
3250
3251 /* rdhi, rdlo and rm must all be different. */
3252 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3253 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3254
3255 if (skip_past_comma (&str) == FAIL
3256 || (rs = reg_required_here (&str, 8)) == FAIL)
3257 {
3258 inst.error = BAD_ARGS;
3259 return;
3260 }
3261
3262 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3263 {
3264 inst.error = BAD_PC;
3265 return;
3266 }
3267
b99bd4ef
NC
3268 end_of_line (str);
3269 return;
3270}
3271
3272static void
f2b7cb0a 3273do_mul (str)
b99bd4ef 3274 char * str;
b99bd4ef
NC
3275{
3276 int rd, rm;
3277
3278 /* Only one format "rd, rm, rs". */
3279 skip_whitespace (str);
3280
3281 if ((rd = reg_required_here (&str, 16)) == FAIL)
3282 {
3283 inst.error = BAD_ARGS;
3284 return;
3285 }
3286
3287 if (rd == REG_PC)
3288 {
3289 inst.error = BAD_PC;
3290 return;
3291 }
3292
3293 if (skip_past_comma (&str) == FAIL
3294 || (rm = reg_required_here (&str, 0)) == FAIL)
3295 {
3296 inst.error = BAD_ARGS;
3297 return;
3298 }
3299
3300 if (rm == REG_PC)
3301 {
3302 inst.error = BAD_PC;
3303 return;
3304 }
3305
3306 if (rm == rd)
3307 as_tsktsk (_("rd and rm should be different in mul"));
3308
3309 if (skip_past_comma (&str) == FAIL
3310 || (rm = reg_required_here (&str, 8)) == FAIL)
3311 {
3312 inst.error = BAD_ARGS;
3313 return;
3314 }
3315
3316 if (rm == REG_PC)
3317 {
3318 inst.error = BAD_PC;
3319 return;
3320 }
3321
b99bd4ef
NC
3322 end_of_line (str);
3323 return;
3324}
3325
3326static void
f2b7cb0a 3327do_mla (str)
b99bd4ef 3328 char * str;
b99bd4ef
NC
3329{
3330 int rd, rm;
3331
3332 /* Only one format "rd, rm, rs, rn". */
3333 skip_whitespace (str);
3334
3335 if ((rd = reg_required_here (&str, 16)) == FAIL)
3336 {
3337 inst.error = BAD_ARGS;
3338 return;
3339 }
3340
3341 if (rd == REG_PC)
3342 {
3343 inst.error = BAD_PC;
3344 return;
3345 }
3346
3347 if (skip_past_comma (&str) == FAIL
3348 || (rm = reg_required_here (&str, 0)) == FAIL)
3349 {
3350 inst.error = BAD_ARGS;
3351 return;
3352 }
3353
3354 if (rm == REG_PC)
3355 {
3356 inst.error = BAD_PC;
3357 return;
3358 }
3359
3360 if (rm == rd)
3361 as_tsktsk (_("rd and rm should be different in mla"));
3362
3363 if (skip_past_comma (&str) == FAIL
3364 || (rd = reg_required_here (&str, 8)) == FAIL
3365 || skip_past_comma (&str) == FAIL
3366 || (rm = reg_required_here (&str, 12)) == FAIL)
3367 {
3368 inst.error = BAD_ARGS;
3369 return;
3370 }
3371
3372 if (rd == REG_PC || rm == REG_PC)
3373 {
3374 inst.error = BAD_PC;
3375 return;
3376 }
3377
b99bd4ef
NC
3378 end_of_line (str);
3379 return;
3380}
3381
3382/* Expects *str -> the characters "acc0", possibly with leading blanks.
3383 Advances *str to the next non-alphanumeric.
3384 Returns 0, or else FAIL (in which case sets inst.error).
3385
3386 (In a future XScale, there may be accumulators other than zero.
3387 At that time this routine and its callers can be upgraded to suit.) */
3388
3389static int
3390accum0_required_here (str)
3391 char ** str;
3392{
3393 static char buff [128]; /* Note the address is taken. Hence, static. */
3394 char * p = * str;
3395 char c;
3396 int result = 0; /* The accum number. */
3397
3398 skip_whitespace (p);
3399
3400 *str = p; /* Advance caller's string pointer too. */
3401 c = *p++;
3882b010 3402 while (ISALNUM (c))
b99bd4ef
NC
3403 c = *p++;
3404
3405 *--p = 0; /* Aap nul into input buffer at non-alnum. */
3406
3407 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3408 {
3409 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3410 inst.error = buff;
3411 result = FAIL;
3412 }
3413
3414 *p = c; /* Unzap. */
3415 *str = p; /* Caller's string pointer to after match. */
3416 return result;
3417}
3418
3419/* Expects **str -> after a comma. May be leading blanks.
3420 Advances *str, recognizing a load mode, and setting inst.instruction.
3421 Returns rn, or else FAIL (in which case may set inst.error
3422 and not advance str)
3423
3424 Note: doesn't know Rd, so no err checks that require such knowledge. */
3425
3426static int
3427ld_mode_required_here (string)
3428 char ** string;
3429{
3430 char * str = * string;
3431 int rn;
3432 int pre_inc = 0;
3433
3434 skip_whitespace (str);
3435
3436 if (* str == '[')
3437 {
3438 str++;
3439
3440 skip_whitespace (str);
3441
3442 if ((rn = reg_required_here (& str, 16)) == FAIL)
3443 return FAIL;
3444
3445 skip_whitespace (str);
3446
3447 if (* str == ']')
3448 {
3449 str ++;
3450
3451 if (skip_past_comma (& str) == SUCCESS)
3452 {
3453 /* [Rn],... (post inc) */
90e4755a 3454 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3455 return FAIL;
3456 }
3457 else /* [Rn] */
3458 {
cc8a6dd0 3459 skip_whitespace (str);
b99bd4ef 3460
cc8a6dd0
KH
3461 if (* str == '!')
3462 {
3463 str ++;
3464 inst.instruction |= WRITE_BACK;
3465 }
b99bd4ef
NC
3466
3467 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3468 pre_inc = 1;
3469 }
3470 }
3471 else /* [Rn,...] */
3472 {
3473 if (skip_past_comma (& str) == FAIL)
3474 {
3475 inst.error = _("pre-indexed expression expected");
3476 return FAIL;
3477 }
3478
3479 pre_inc = 1;
3480
90e4755a 3481 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3482 return FAIL;
3483
3484 skip_whitespace (str);
3485
3486 if (* str ++ != ']')
3487 {
3488 inst.error = _("missing ]");
3489 return FAIL;
3490 }
3491
3492 skip_whitespace (str);
3493
3494 if (* str == '!')
3495 {
3496 str ++;
3497 inst.instruction |= WRITE_BACK;
3498 }
3499 }
3500 }
3501 else if (* str == '=') /* ldr's "r,=label" syntax */
3502 /* We should never reach here, because <text> = <expression> is
3503 caught gas/read.c read_a_source_file() as a .set operation. */
3504 return FAIL;
3505 else /* PC +- 8 bit immediate offset. */
3506 {
3507 if (my_get_expression (& inst.reloc.exp, & str))
3508 return FAIL;
3509
3510 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3511 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3512 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3513 inst.reloc.pc_rel = 1;
3514 inst.instruction |= (REG_PC << 16);
3515
3516 rn = REG_PC;
3517 pre_inc = 1;
3518 }
3519
3520 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3521 * string = str;
3522
3523 return rn;
3524}
3525
3526/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3527 SMLAxy{cond} Rd,Rm,Rs,Rn
3528 SMLAWy{cond} Rd,Rm,Rs,Rn
3529 Error if any register is R15. */
3530
3531static void
f2b7cb0a 3532do_smla (str)
b99bd4ef 3533 char * str;
b99bd4ef
NC
3534{
3535 int rd, rm, rs, rn;
3536
3537 skip_whitespace (str);
3538
3539 if ((rd = reg_required_here (& str, 16)) == FAIL
3540 || skip_past_comma (& str) == FAIL
3541 || (rm = reg_required_here (& str, 0)) == FAIL
3542 || skip_past_comma (& str) == FAIL
3543 || (rs = reg_required_here (& str, 8)) == FAIL
3544 || skip_past_comma (& str) == FAIL
3545 || (rn = reg_required_here (& str, 12)) == FAIL)
3546 inst.error = BAD_ARGS;
3547
3548 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3549 inst.error = BAD_PC;
3550
b99bd4ef
NC
3551 else
3552 end_of_line (str);
3553}
3554
3555/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3556 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3557 Error if any register is R15.
3558 Warning if Rdlo == Rdhi. */
3559
3560static void
f2b7cb0a 3561do_smlal (str)
b99bd4ef 3562 char * str;
b99bd4ef
NC
3563{
3564 int rdlo, rdhi, rm, rs;
3565
3566 skip_whitespace (str);
3567
3568 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3569 || skip_past_comma (& str) == FAIL
3570 || (rdhi = reg_required_here (& str, 16)) == FAIL
3571 || skip_past_comma (& str) == FAIL
3572 || (rm = reg_required_here (& str, 0)) == FAIL
3573 || skip_past_comma (& str) == FAIL
3574 || (rs = reg_required_here (& str, 8)) == FAIL)
3575 {
3576 inst.error = BAD_ARGS;
3577 return;
3578 }
3579
3580 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3581 {
3582 inst.error = BAD_PC;
3583 return;
3584 }
3585
3586 if (rdlo == rdhi)
3587 as_tsktsk (_("rdhi and rdlo must be different"));
3588
f2b7cb0a 3589 end_of_line (str);
b99bd4ef
NC
3590}
3591
3592/* ARM V5E (El Segundo) signed-multiply (argument parse)
3593 SMULxy{cond} Rd,Rm,Rs
3594 Error if any register is R15. */
3595
3596static void
f2b7cb0a 3597do_smul (str)
b99bd4ef 3598 char * str;
b99bd4ef
NC
3599{
3600 int rd, rm, rs;
3601
3602 skip_whitespace (str);
3603
3604 if ((rd = reg_required_here (& str, 16)) == FAIL
3605 || skip_past_comma (& str) == FAIL
3606 || (rm = reg_required_here (& str, 0)) == FAIL
3607 || skip_past_comma (& str) == FAIL
3608 || (rs = reg_required_here (& str, 8)) == FAIL)
3609 inst.error = BAD_ARGS;
3610
3611 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3612 inst.error = BAD_PC;
3613
b99bd4ef
NC
3614 else
3615 end_of_line (str);
3616}
3617
3618/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3619 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3620 Error if any register is R15. */
3621
3622static void
f2b7cb0a 3623do_qadd (str)
b99bd4ef 3624 char * str;
b99bd4ef
NC
3625{
3626 int rd, rm, rn;
3627
3628 skip_whitespace (str);
3629
3630 if ((rd = reg_required_here (& str, 12)) == FAIL
3631 || skip_past_comma (& str) == FAIL
3632 || (rm = reg_required_here (& str, 0)) == FAIL
3633 || skip_past_comma (& str) == FAIL
3634 || (rn = reg_required_here (& str, 16)) == FAIL)
3635 inst.error = BAD_ARGS;
3636
3637 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3638 inst.error = BAD_PC;
3639
b99bd4ef
NC
3640 else
3641 end_of_line (str);
3642}
3643
3644/* ARM V5E (el Segundo)
3645 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3646 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3647
3648 These are equivalent to the XScale instructions MAR and MRA,
3649 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3650
3651 Result unpredicatable if Rd or Rn is R15. */
3652
3653static void
f2b7cb0a 3654do_co_reg2c (str)
b99bd4ef 3655 char * str;
b99bd4ef
NC
3656{
3657 int rd, rn;
3658
3659 skip_whitespace (str);
3660
3661 if (co_proc_number (& str) == FAIL)
3662 {
3663 if (!inst.error)
3664 inst.error = BAD_ARGS;
3665 return;
3666 }
3667
3668 if (skip_past_comma (& str) == FAIL
3669 || cp_opc_expr (& str, 4, 4) == FAIL)
3670 {
3671 if (!inst.error)
3672 inst.error = BAD_ARGS;
3673 return;
3674 }
3675
3676 if (skip_past_comma (& str) == FAIL
3677 || (rd = reg_required_here (& str, 12)) == FAIL)
3678 {
3679 if (!inst.error)
3680 inst.error = BAD_ARGS;
3681 return;
3682 }
3683
3684 if (skip_past_comma (& str) == FAIL
3685 || (rn = reg_required_here (& str, 16)) == FAIL)
3686 {
3687 if (!inst.error)
3688 inst.error = BAD_ARGS;
3689 return;
3690 }
3691
3692 /* Unpredictable result if rd or rn is R15. */
3693 if (rd == REG_PC || rn == REG_PC)
3694 as_tsktsk
f03698e6 3695 (_("Warning: instruction unpredictable when using r15"));
b99bd4ef
NC
3696
3697 if (skip_past_comma (& str) == FAIL
3698 || cp_reg_required_here (& str, 0) == FAIL)
3699 {
3700 if (!inst.error)
3701 inst.error = BAD_ARGS;
3702 return;
3703 }
3704
b99bd4ef
NC
3705 end_of_line (str);
3706}
3707
3708/* ARM V5 count-leading-zeroes instruction (argument parse)
3709 CLZ{<cond>} <Rd>, <Rm>
3710 Condition defaults to COND_ALWAYS.
3711 Error if Rd or Rm are R15. */
3712
3713static void
f2b7cb0a 3714do_clz (str)
b99bd4ef 3715 char * str;
b99bd4ef
NC
3716{
3717 int rd, rm;
3718
b99bd4ef
NC
3719 skip_whitespace (str);
3720
3721 if (((rd = reg_required_here (& str, 12)) == FAIL)
3722 || (skip_past_comma (& str) == FAIL)
3723 || ((rm = reg_required_here (& str, 0)) == FAIL))
3724 inst.error = BAD_ARGS;
3725
3726 else if (rd == REG_PC || rm == REG_PC )
3727 inst.error = BAD_PC;
3728
3729 else
3730 end_of_line (str);
3731}
3732
3733/* ARM V5 (argument parse)
3734 LDC2{L} <coproc>, <CRd>, <addressing mode>
3735 STC2{L} <coproc>, <CRd>, <addressing mode>
3736 Instruction is not conditional, and has 0xf in the codition field.
3737 Otherwise, it's the same as LDC/STC. */
3738
3739static void
f2b7cb0a 3740do_lstc2 (str)
b99bd4ef 3741 char * str;
b99bd4ef 3742{
b99bd4ef
NC
3743 skip_whitespace (str);
3744
3745 if (co_proc_number (& str) == FAIL)
3746 {
3747 if (!inst.error)
3748 inst.error = BAD_ARGS;
3749 }
3750 else if (skip_past_comma (& str) == FAIL
3751 || cp_reg_required_here (& str, 12) == FAIL)
3752 {
3753 if (!inst.error)
3754 inst.error = BAD_ARGS;
3755 }
3756 else if (skip_past_comma (& str) == FAIL
bfae80f2 3757 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
3758 {
3759 if (! inst.error)
3760 inst.error = BAD_ARGS;
3761 }
3762 else
3763 end_of_line (str);
3764}
3765
3766/* ARM V5 (argument parse)
3767 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3768 Instruction is not conditional, and has 0xf in the condition field.
3769 Otherwise, it's the same as CDP. */
3770
3771static void
f2b7cb0a 3772do_cdp2 (str)
b99bd4ef 3773 char * str;
b99bd4ef
NC
3774{
3775 skip_whitespace (str);
3776
3777 if (co_proc_number (& str) == FAIL)
3778 {
3779 if (!inst.error)
3780 inst.error = BAD_ARGS;
3781 return;
3782 }
3783
3784 if (skip_past_comma (& str) == FAIL
3785 || cp_opc_expr (& str, 20,4) == FAIL)
3786 {
3787 if (!inst.error)
3788 inst.error = BAD_ARGS;
3789 return;
3790 }
3791
3792 if (skip_past_comma (& str) == FAIL
3793 || cp_reg_required_here (& str, 12) == FAIL)
3794 {
3795 if (!inst.error)
3796 inst.error = BAD_ARGS;
3797 return;
3798 }
3799
3800 if (skip_past_comma (& str) == FAIL
3801 || cp_reg_required_here (& str, 16) == FAIL)
3802 {
3803 if (!inst.error)
3804 inst.error = BAD_ARGS;
3805 return;
3806 }
3807
3808 if (skip_past_comma (& str) == FAIL
3809 || cp_reg_required_here (& str, 0) == FAIL)
3810 {
3811 if (!inst.error)
3812 inst.error = BAD_ARGS;
3813 return;
3814 }
3815
3816 if (skip_past_comma (& str) == SUCCESS)
3817 {
3818 if (cp_opc_expr (& str, 5, 3) == FAIL)
3819 {
3820 if (!inst.error)
3821 inst.error = BAD_ARGS;
3822 return;
3823 }
3824 }
3825
b99bd4ef
NC
3826 end_of_line (str);
3827}
3828
3829/* ARM V5 (argument parse)
3830 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3831 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3832 Instruction is not conditional, and has 0xf in the condition field.
3833 Otherwise, it's the same as MCR/MRC. */
3834
3835static void
f2b7cb0a 3836do_co_reg2 (str)
b99bd4ef 3837 char * str;
b99bd4ef
NC
3838{
3839 skip_whitespace (str);
3840
3841 if (co_proc_number (& str) == FAIL)
3842 {
3843 if (!inst.error)
3844 inst.error = BAD_ARGS;
3845 return;
3846 }
3847
3848 if (skip_past_comma (& str) == FAIL
3849 || cp_opc_expr (& str, 21, 3) == FAIL)
3850 {
3851 if (!inst.error)
3852 inst.error = BAD_ARGS;
3853 return;
3854 }
3855
3856 if (skip_past_comma (& str) == FAIL
3857 || reg_required_here (& str, 12) == FAIL)
3858 {
3859 if (!inst.error)
3860 inst.error = BAD_ARGS;
3861 return;
3862 }
3863
3864 if (skip_past_comma (& str) == FAIL
3865 || cp_reg_required_here (& str, 16) == FAIL)
3866 {
3867 if (!inst.error)
3868 inst.error = BAD_ARGS;
3869 return;
3870 }
3871
3872 if (skip_past_comma (& str) == FAIL
3873 || cp_reg_required_here (& str, 0) == FAIL)
3874 {
3875 if (!inst.error)
3876 inst.error = BAD_ARGS;
3877 return;
3878 }
3879
3880 if (skip_past_comma (& str) == SUCCESS)
3881 {
3882 if (cp_opc_expr (& str, 5, 3) == FAIL)
3883 {
3884 if (!inst.error)
3885 inst.error = BAD_ARGS;
3886 return;
3887 }
3888 }
3889
b99bd4ef
NC
3890 end_of_line (str);
3891}
3892
ea6ef066
RE
3893/* ARM v5TEJ. Jump to Jazelle code. */
3894static void
3895do_bxj (str)
3896 char * str;
3897{
3898 int reg;
3899
3900 skip_whitespace (str);
3901
3902 if ((reg = reg_required_here (&str, 0)) == FAIL)
3903 {
3904 inst.error = BAD_ARGS;
3905 return;
3906 }
3907
3908 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3909 if (reg == REG_PC)
3910 as_tsktsk (_("use of r15 in bxj is not really useful"));
3911
3912 end_of_line (str);
3913}
3914
b99bd4ef
NC
3915/* THUMB V5 breakpoint instruction (argument parse)
3916 BKPT <immed_8>. */
3917
3918static void
3919do_t_bkpt (str)
3920 char * str;
3921{
3922 expressionS expr;
3923 unsigned long number;
3924
3925 skip_whitespace (str);
3926
3927 /* Allow optional leading '#'. */
3928 if (is_immediate_prefix (*str))
3929 str ++;
3930
3931 memset (& expr, '\0', sizeof (expr));
3932 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
3933 {
3934 inst.error = _("bad or missing expression");
3935 return;
3936 }
3937
3938 number = expr.X_add_number;
3939
3940 /* Check it fits an 8 bit unsigned. */
3941 if (number != (number & 0xff))
3942 {
3943 inst.error = _("immediate value out of range");
3944 return;
3945 }
3946
3947 inst.instruction |= number;
3948
3949 end_of_line (str);
3950}
3951
3952/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3953 Expects inst.instruction is set for BLX(1).
3954 Note: this is cloned from do_branch, and the reloc changed to be a
3955 new one that can cope with setting one extra bit (the H bit). */
3956
3957static void
f2b7cb0a 3958do_branch25 (str)
b99bd4ef 3959 char * str;
b99bd4ef
NC
3960{
3961 if (my_get_expression (& inst.reloc.exp, & str))
3962 return;
3963
3964#ifdef OBJ_ELF
3965 {
3966 char * save_in;
3967
3968 /* ScottB: February 5, 1998 */
3969 /* Check to see of PLT32 reloc required for the instruction. */
3970
3971 /* arm_parse_reloc() works on input_line_pointer.
3972 We actually want to parse the operands to the branch instruction
3973 passed in 'str'. Save the input pointer and restore it later. */
3974 save_in = input_line_pointer;
3975 input_line_pointer = str;
3976
3977 if (inst.reloc.exp.X_op == O_symbol
3978 && *str == '('
3979 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
3980 {
3981 inst.reloc.type = BFD_RELOC_ARM_PLT32;
3982 inst.reloc.pc_rel = 0;
3983 /* Modify str to point to after parsed operands, otherwise
3984 end_of_line() will complain about the (PLT) left in str. */
3985 str = input_line_pointer;
3986 }
3987 else
3988 {
3989 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3990 inst.reloc.pc_rel = 1;
3991 }
3992
3993 input_line_pointer = save_in;
3994 }
3995#else
3996 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
3997 inst.reloc.pc_rel = 1;
3998#endif /* OBJ_ELF */
3999
4000 end_of_line (str);
4001}
4002
4003/* ARM V5 branch-link-exchange instruction (argument parse)
4004 BLX <target_addr> ie BLX(1)
4005 BLX{<condition>} <Rm> ie BLX(2)
4006 Unfortunately, there are two different opcodes for this mnemonic.
4007 So, the insns[].value is not used, and the code here zaps values
4008 into inst.instruction.
4009 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4010
4011static void
f2b7cb0a 4012do_blx (str)
b99bd4ef 4013 char * str;
b99bd4ef
NC
4014{
4015 char * mystr = str;
4016 int rm;
4017
b99bd4ef
NC
4018 skip_whitespace (mystr);
4019 rm = reg_required_here (& mystr, 0);
4020
4021 /* The above may set inst.error. Ignore his opinion. */
4022 inst.error = 0;
4023
4024 if (rm != FAIL)
4025 {
4026 /* Arg is a register.
4027 Use the condition code our caller put in inst.instruction.
4028 Pass ourselves off as a BX with a funny opcode. */
4029 inst.instruction |= 0x012fff30;
f2b7cb0a 4030 do_bx (str);
b99bd4ef
NC
4031 }
4032 else
4033 {
4034 /* This must be is BLX <target address>, no condition allowed. */
4035 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4036 {
4037 inst.error = BAD_COND;
b99bd4ef 4038 return;
cc8a6dd0 4039 }
b99bd4ef
NC
4040
4041 inst.instruction = 0xfafffffe;
4042
4043 /* Process like a B/BL, but with a different reloc.
4044 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4045 do_branch25 (str);
b99bd4ef
NC
4046 }
4047}
4048
4049/* ARM V5 Thumb BLX (argument parse)
4050 BLX <target_addr> which is BLX(1)
4051 BLX <Rm> which is BLX(2)
4052 Unfortunately, there are two different opcodes for this mnemonic.
4053 So, the tinsns[].value is not used, and the code here zaps values
4054 into inst.instruction. */
4055
4056static void
4057do_t_blx (str)
4058 char * str;
4059{
4060 char * mystr = str;
4061 int rm;
4062
4063 skip_whitespace (mystr);
4064 inst.instruction = 0x4780;
4065
4066 /* Note that this call is to the ARM register recognizer. BLX(2)
4067 uses the ARM register space, not the Thumb one, so a call to
4068 thumb_reg() would be wrong. */
4069 rm = reg_required_here (& mystr, 3);
4070 inst.error = 0;
4071
4072 if (rm != FAIL)
4073 {
4074 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4075 inst.size = 2;
4076 }
4077 else
4078 {
4079 /* No ARM register. This must be BLX(1). Change the .instruction. */
4080 inst.instruction = 0xf7ffeffe;
4081 inst.size = 4;
4082
4083 if (my_get_expression (& inst.reloc.exp, & mystr))
4084 return;
4085
4086 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4087 inst.reloc.pc_rel = 1;
4088 }
4089
4090 end_of_line (mystr);
4091}
4092
4093/* ARM V5 breakpoint instruction (argument parse)
4094 BKPT <16 bit unsigned immediate>
4095 Instruction is not conditional.
4096 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 4097 and it is an error if the caller tried to override that. */
b99bd4ef
NC
4098
4099static void
f2b7cb0a 4100do_bkpt (str)
b99bd4ef 4101 char * str;
b99bd4ef
NC
4102{
4103 expressionS expr;
4104 unsigned long number;
4105
4106 skip_whitespace (str);
4107
4108 /* Allow optional leading '#'. */
4109 if (is_immediate_prefix (* str))
4110 str++;
4111
4112 memset (& expr, '\0', sizeof (expr));
4113
4114 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4115 {
4116 inst.error = _("bad or missing expression");
4117 return;
4118 }
4119
4120 number = expr.X_add_number;
4121
4122 /* Check it fits a 16 bit unsigned. */
4123 if (number != (number & 0xffff))
4124 {
4125 inst.error = _("immediate value out of range");
4126 return;
4127 }
4128
4129 /* Top 12 of 16 bits to bits 19:8. */
4130 inst.instruction |= (number & 0xfff0) << 4;
4131
4132 /* Bottom 4 of 16 bits to bits 3:0. */
4133 inst.instruction |= number & 0xf;
4134
4135 end_of_line (str);
b99bd4ef
NC
4136}
4137
4138/* Xscale multiply-accumulate (argument parse)
4139 MIAcc acc0,Rm,Rs
4140 MIAPHcc acc0,Rm,Rs
4141 MIAxycc acc0,Rm,Rs. */
4142
4143static void
63e63b07 4144do_xsc_mia (str)
b99bd4ef 4145 char * str;
b99bd4ef
NC
4146{
4147 int rs;
4148 int rm;
4149
f2b7cb0a 4150 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
4151 inst.error = ERR_NO_ACCUM;
4152
4153 else if (skip_past_comma (& str) == FAIL
4154 || (rm = reg_required_here (& str, 0)) == FAIL)
4155 inst.error = BAD_ARGS;
4156
4157 else if (skip_past_comma (& str) == FAIL
4158 || (rs = reg_required_here (& str, 12)) == FAIL)
4159 inst.error = BAD_ARGS;
4160
4161 /* inst.instruction has now been zapped with both rm and rs. */
4162 else if (rm == REG_PC || rs == REG_PC)
4163 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
4164
4165 else
4166 end_of_line (str);
4167}
4168
4169/* Xscale move-accumulator-register (argument parse)
4170
4171 MARcc acc0,RdLo,RdHi. */
4172
4173static void
63e63b07 4174do_xsc_mar (str)
b99bd4ef 4175 char * str;
b99bd4ef
NC
4176{
4177 int rdlo, rdhi;
4178
f2b7cb0a 4179 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
4180 inst.error = ERR_NO_ACCUM;
4181
4182 else if (skip_past_comma (& str) == FAIL
4183 || (rdlo = reg_required_here (& str, 12)) == FAIL)
4184 inst.error = BAD_ARGS;
4185
4186 else if (skip_past_comma (& str) == FAIL
4187 || (rdhi = reg_required_here (& str, 16)) == FAIL)
4188 inst.error = BAD_ARGS;
4189
4190 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4191 else if (rdlo == REG_PC || rdhi == REG_PC)
4192 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
4193
4194 else
4195 end_of_line (str);
4196}
4197
4198/* Xscale move-register-accumulator (argument parse)
4199
4200 MRAcc RdLo,RdHi,acc0. */
4201
4202static void
63e63b07 4203do_xsc_mra (str)
b99bd4ef 4204 char * str;
b99bd4ef
NC
4205{
4206 int rdlo;
4207 int rdhi;
4208
b99bd4ef
NC
4209 skip_whitespace (str);
4210
4211 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
4212 inst.error = BAD_ARGS;
4213
4214 else if (skip_past_comma (& str) == FAIL
4215 || (rdhi = reg_required_here (& str, 16)) == FAIL)
4216 inst.error = BAD_ARGS;
4217
4218 else if (skip_past_comma (& str) == FAIL
4219 || accum0_required_here (& str) == FAIL)
4220 inst.error = ERR_NO_ACCUM;
4221
4222 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4223 else if (rdlo == rdhi)
4224 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
4225
4226 else if (rdlo == REG_PC || rdhi == REG_PC)
4227 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
4228 else
4229 end_of_line (str);
4230}
4231
c9b604bd 4232/* ARMv5TE: Preload-Cache
b99bd4ef
NC
4233
4234 PLD <addr_mode>
4235
4236 Syntactically, like LDR with B=1, W=0, L=1. */
4237
4238static void
f2b7cb0a 4239do_pld (str)
b99bd4ef 4240 char * str;
b99bd4ef
NC
4241{
4242 int rd;
4243
b99bd4ef
NC
4244 skip_whitespace (str);
4245
4246 if (* str != '[')
4247 {
4248 inst.error = _("'[' expected after PLD mnemonic");
4249 return;
4250 }
4251
90e4755a 4252 ++str;
b99bd4ef
NC
4253 skip_whitespace (str);
4254
4255 if ((rd = reg_required_here (& str, 16)) == FAIL)
4256 return;
4257
4258 skip_whitespace (str);
4259
90e4755a 4260 if (*str == ']')
b99bd4ef
NC
4261 {
4262 /* [Rn], ... ? */
90e4755a 4263 ++str;
b99bd4ef
NC
4264 skip_whitespace (str);
4265
90e4755a
RE
4266 /* Post-indexed addressing is not allowed with PLD. */
4267 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 4268 {
90e4755a
RE
4269 inst.error
4270 = _("post-indexed expression used in preload instruction");
4271 return;
b99bd4ef 4272 }
90e4755a 4273 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
4274 {
4275 inst.error = _("writeback used in preload instruction");
90e4755a 4276 ++str;
b99bd4ef
NC
4277 }
4278 else /* [Rn] */
4279 inst.instruction |= INDEX_UP | PRE_INDEX;
4280 }
4281 else /* [Rn, ...] */
4282 {
4283 if (skip_past_comma (& str) == FAIL)
4284 {
4285 inst.error = _("pre-indexed expression expected");
4286 return;
4287 }
4288
90e4755a 4289 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
4290 return;
4291
4292 skip_whitespace (str);
4293
4294 if (* str != ']')
4295 {
4296 inst.error = _("missing ]");
4297 return;
4298 }
4299
4300 ++ str;
4301 skip_whitespace (str);
4302
4303 if (* str == '!') /* [Rn]! */
4304 {
4305 inst.error = _("writeback used in preload instruction");
4306 ++ str;
4307 }
4308
4309 inst.instruction |= PRE_INDEX;
4310 }
4311
4312 end_of_line (str);
4313}
4314
c9b604bd 4315/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
4316 Mode is like LDRH.
4317
4318 LDRccD R, mode
4319 STRccD R, mode. */
4320
4321static void
f2b7cb0a 4322do_ldrd (str)
b99bd4ef 4323 char * str;
b99bd4ef
NC
4324{
4325 int rd;
4326 int rn;
4327
b99bd4ef
NC
4328 skip_whitespace (str);
4329
4330 if ((rd = reg_required_here (& str, 12)) == FAIL)
4331 {
4332 inst.error = BAD_ARGS;
4333 return;
4334 }
4335
4336 if (skip_past_comma (& str) == FAIL
4337 || (rn = ld_mode_required_here (& str)) == FAIL)
4338 {
4339 if (!inst.error)
cc8a6dd0 4340 inst.error = BAD_ARGS;
b99bd4ef
NC
4341 return;
4342 }
4343
4344 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4345 if (rd & 1) /* Unpredictable result if Rd is odd. */
4346 {
f03698e6 4347 inst.error = _("destination register must be even");
b99bd4ef
NC
4348 return;
4349 }
4350
90e4755a 4351 if (rd == REG_LR)
b99bd4ef 4352 {
f2b7cb0a 4353 inst.error = _("r14 not allowed here");
b99bd4ef
NC
4354 return;
4355 }
4356
4357 if (((rd == rn) || (rd + 1 == rn))
90e4755a
RE
4358 && ((inst.instruction & WRITE_BACK)
4359 || (!(inst.instruction & PRE_INDEX))))
b99bd4ef
NC
4360 as_warn (_("pre/post-indexing used when modified address register is destination"));
4361
90e4755a
RE
4362 /* For an index-register load, the index register must not overlap the
4363 destination (even if not write-back). */
4364 if ((inst.instruction & V4_STR_BIT) == 0
4365 && (inst.instruction & HWOFFSET_IMM) == 0)
4366 {
4367 int rm = inst.instruction & 0x0000000f;
4368
4369 if (rm == rd || (rm == rd + 1))
4370 as_warn (_("ldrd destination registers must not overlap index register"));
4371 }
4372
b99bd4ef
NC
4373 end_of_line (str);
4374}
4375
4376/* Returns the index into fp_values of a floating point number,
4377 or -1 if not in the table. */
4378
4379static int
4380my_get_float_expression (str)
4381 char ** str;
4382{
4383 LITTLENUM_TYPE words[MAX_LITTLENUMS];
4384 char * save_in;
4385 expressionS exp;
4386 int i;
4387 int j;
4388
4389 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
4390
4391 /* Look for a raw floating point number. */
4392 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
4393 && is_end_of_line[(unsigned char) *save_in])
4394 {
4395 for (i = 0; i < NUM_FLOAT_VALS; i++)
4396 {
4397 for (j = 0; j < MAX_LITTLENUMS; j++)
4398 {
4399 if (words[j] != fp_values[i][j])
4400 break;
4401 }
4402
4403 if (j == MAX_LITTLENUMS)
4404 {
4405 *str = save_in;
4406 return i;
4407 }
4408 }
4409 }
4410
4411 /* Try and parse a more complex expression, this will probably fail
4412 unless the code uses a floating point prefix (eg "0f"). */
4413 save_in = input_line_pointer;
4414 input_line_pointer = *str;
4415 if (expression (&exp) == absolute_section
4416 && exp.X_op == O_big
4417 && exp.X_add_number < 0)
4418 {
4419 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4420 Ditto for 15. */
4421 if (gen_to_words (words, 5, (long) 15) == 0)
4422 {
4423 for (i = 0; i < NUM_FLOAT_VALS; i++)
4424 {
4425 for (j = 0; j < MAX_LITTLENUMS; j++)
4426 {
4427 if (words[j] != fp_values[i][j])
4428 break;
4429 }
4430
4431 if (j == MAX_LITTLENUMS)
4432 {
4433 *str = input_line_pointer;
4434 input_line_pointer = save_in;
4435 return i;
4436 }
4437 }
4438 }
4439 }
4440
4441 *str = input_line_pointer;
4442 input_line_pointer = save_in;
4443 return -1;
4444}
4445
4446/* Return true if anything in the expression is a bignum. */
4447
4448static int
4449walk_no_bignums (sp)
4450 symbolS * sp;
4451{
4452 if (symbol_get_value_expression (sp)->X_op == O_big)
4453 return 1;
4454
4455 if (symbol_get_value_expression (sp)->X_add_symbol)
4456 {
4457 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
4458 || (symbol_get_value_expression (sp)->X_op_symbol
4459 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
4460 }
4461
4462 return 0;
4463}
4464
f03698e6
RE
4465static int in_my_get_expression = 0;
4466
b99bd4ef
NC
4467static int
4468my_get_expression (ep, str)
4469 expressionS * ep;
4470 char ** str;
4471{
4472 char * save_in;
4473 segT seg;
4474
4475 save_in = input_line_pointer;
4476 input_line_pointer = *str;
f03698e6 4477 in_my_get_expression = 1;
b99bd4ef 4478 seg = expression (ep);
f03698e6
RE
4479 in_my_get_expression = 0;
4480
4481 if (ep->X_op == O_illegal)
4482 {
4483 /* We found a bad expression in md_operand(). */
4484 *str = input_line_pointer;
4485 input_line_pointer = save_in;
4486 return 1;
4487 }
b99bd4ef
NC
4488
4489#ifdef OBJ_AOUT
4490 if (seg != absolute_section
4491 && seg != text_section
4492 && seg != data_section
4493 && seg != bss_section
4494 && seg != undefined_section)
4495 {
4496 inst.error = _("bad_segment");
4497 *str = input_line_pointer;
4498 input_line_pointer = save_in;
4499 return 1;
4500 }
4501#endif
4502
4503 /* Get rid of any bignums now, so that we don't generate an error for which
4504 we can't establish a line number later on. Big numbers are never valid
4505 in instructions, which is where this routine is always called. */
4506 if (ep->X_op == O_big
4507 || (ep->X_add_symbol
4508 && (walk_no_bignums (ep->X_add_symbol)
4509 || (ep->X_op_symbol
4510 && walk_no_bignums (ep->X_op_symbol)))))
4511 {
f03698e6 4512 inst.error = _("invalid constant");
b99bd4ef
NC
4513 *str = input_line_pointer;
4514 input_line_pointer = save_in;
4515 return 1;
4516 }
4517
4518 *str = input_line_pointer;
4519 input_line_pointer = save_in;
4520 return 0;
4521}
4522
cc8a6dd0 4523/* We handle all bad expressions here, so that we can report the faulty
f03698e6
RE
4524 instruction in the error message. */
4525void
ce058b6c 4526md_operand (expr)
f03698e6
RE
4527 expressionS *expr;
4528{
4529 if (in_my_get_expression)
4530 {
4531 expr->X_op = O_illegal;
4532 if (inst.error == NULL)
4533 inst.error = _("bad expression");
4534 }
4535}
4536
b99bd4ef
NC
4537/* UNRESTRICT should be one if <shift> <register> is permitted for this
4538 instruction. */
4539
4540static int
4541decode_shift (str, unrestrict)
4542 char ** str;
4543 int unrestrict;
4544{
4545 const struct asm_shift_name * shift;
4546 char * p;
4547 char c;
4548
4549 skip_whitespace (* str);
4550
3882b010 4551 for (p = * str; ISALPHA (* p); p ++)
b99bd4ef
NC
4552 ;
4553
4554 if (p == * str)
4555 {
f03698e6 4556 inst.error = _("shift expression expected");
b99bd4ef
NC
4557 return FAIL;
4558 }
4559
4560 c = * p;
4561 * p = '\0';
4562 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
4563 * p = c;
4564
4565 if (shift == NULL)
4566 {
f03698e6 4567 inst.error = _("shift expression expected");
b99bd4ef
NC
4568 return FAIL;
4569 }
4570
4571 assert (shift->properties->index == shift_properties[shift->properties->index].index);
4572
4573 if (shift->properties->index == SHIFT_RRX)
4574 {
4575 * str = p;
4576 inst.instruction |= shift->properties->bit_field;
4577 return SUCCESS;
4578 }
4579
4580 skip_whitespace (p);
4581
4582 if (unrestrict && reg_required_here (& p, 8) != FAIL)
4583 {
4584 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
4585 * str = p;
4586 return SUCCESS;
4587 }
4588 else if (! is_immediate_prefix (* p))
4589 {
4590 inst.error = (unrestrict
4591 ? _("shift requires register or #expression")
4592 : _("shift requires #expression"));
4593 * str = p;
4594 return FAIL;
4595 }
4596
4597 inst.error = NULL;
4598 p ++;
4599
4600 if (my_get_expression (& inst.reloc.exp, & p))
4601 return FAIL;
4602
4603 /* Validate some simple #expressions. */
4604 if (inst.reloc.exp.X_op == O_constant)
4605 {
4606 unsigned num = inst.reloc.exp.X_add_number;
4607
4608 /* Reject operations greater than 32. */
4609 if (num > 32
4610 /* Reject a shift of 0 unless the mode allows it. */
4611 || (num == 0 && shift->properties->allows_0 == 0)
4612 /* Reject a shift of 32 unless the mode allows it. */
4613 || (num == 32 && shift->properties->allows_32 == 0)
4614 )
4615 {
4616 /* As a special case we allow a shift of zero for
4617 modes that do not support it to be recoded as an
4618 logical shift left of zero (ie nothing). We warn
4619 about this though. */
4620 if (num == 0)
4621 {
f03698e6 4622 as_warn (_("shift of 0 ignored."));
b99bd4ef
NC
4623 shift = & shift_names[0];
4624 assert (shift->properties->index == SHIFT_LSL);
4625 }
4626 else
4627 {
f03698e6 4628 inst.error = _("invalid immediate shift");
b99bd4ef
NC
4629 return FAIL;
4630 }
4631 }
4632
4633 /* Shifts of 32 are encoded as 0, for those shifts that
4634 support it. */
4635 if (num == 32)
4636 num = 0;
4637
4638 inst.instruction |= (num << 7) | shift->properties->bit_field;
4639 }
4640 else
4641 {
4642 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
4643 inst.reloc.pc_rel = 0;
4644 inst.instruction |= shift->properties->bit_field;
4645 }
4646
4647 * str = p;
4648 return SUCCESS;
4649}
4650
4651/* Do those data_ops which can take a negative immediate constant
4652 by altering the instuction. A bit of a hack really.
4653 MOV <-> MVN
4654 AND <-> BIC
4655 ADC <-> SBC
4656 by inverting the second operand, and
4657 ADD <-> SUB
4658 CMP <-> CMN
4659 by negating the second operand. */
4660
4661static int
4662negate_data_op (instruction, value)
4663 unsigned long * instruction;
4664 unsigned long value;
4665{
4666 int op, new_inst;
4667 unsigned long negated, inverted;
4668
4669 negated = validate_immediate (-value);
4670 inverted = validate_immediate (~value);
4671
4672 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
4673 switch (op)
4674 {
4675 /* First negates. */
4676 case OPCODE_SUB: /* ADD <-> SUB */
4677 new_inst = OPCODE_ADD;
4678 value = negated;
4679 break;
4680
4681 case OPCODE_ADD:
4682 new_inst = OPCODE_SUB;
4683 value = negated;
4684 break;
4685
4686 case OPCODE_CMP: /* CMP <-> CMN */
4687 new_inst = OPCODE_CMN;
4688 value = negated;
4689 break;
4690
4691 case OPCODE_CMN:
4692 new_inst = OPCODE_CMP;
4693 value = negated;
4694 break;
4695
4696 /* Now Inverted ops. */
4697 case OPCODE_MOV: /* MOV <-> MVN */
4698 new_inst = OPCODE_MVN;
4699 value = inverted;
4700 break;
4701
4702 case OPCODE_MVN:
4703 new_inst = OPCODE_MOV;
4704 value = inverted;
4705 break;
4706
4707 case OPCODE_AND: /* AND <-> BIC */
4708 new_inst = OPCODE_BIC;
4709 value = inverted;
4710 break;
4711
4712 case OPCODE_BIC:
4713 new_inst = OPCODE_AND;
4714 value = inverted;
4715 break;
4716
4717 case OPCODE_ADC: /* ADC <-> SBC */
4718 new_inst = OPCODE_SBC;
4719 value = inverted;
4720 break;
4721
4722 case OPCODE_SBC:
4723 new_inst = OPCODE_ADC;
4724 value = inverted;
4725 break;
4726
4727 /* We cannot do anything. */
4728 default:
4729 return FAIL;
4730 }
4731
4732 if (value == (unsigned) FAIL)
4733 return FAIL;
4734
4735 *instruction &= OPCODE_MASK;
4736 *instruction |= new_inst << DATA_OP_SHIFT;
4737 return value;
4738}
4739
4740static int
4741data_op2 (str)
4742 char ** str;
4743{
4744 int value;
4745 expressionS expr;
4746
4747 skip_whitespace (* str);
4748
4749 if (reg_required_here (str, 0) != FAIL)
4750 {
4751 if (skip_past_comma (str) == SUCCESS)
4752 /* Shift operation on register. */
4753 return decode_shift (str, NO_SHIFT_RESTRICT);
4754
4755 return SUCCESS;
4756 }
4757 else
4758 {
4759 /* Immediate expression. */
4760 if (is_immediate_prefix (**str))
4761 {
4762 (*str)++;
4763 inst.error = NULL;
4764
4765 if (my_get_expression (&inst.reloc.exp, str))
4766 return FAIL;
4767
4768 if (inst.reloc.exp.X_add_symbol)
4769 {
4770 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4771 inst.reloc.pc_rel = 0;
4772 }
4773 else
4774 {
4775 if (skip_past_comma (str) == SUCCESS)
4776 {
4777 /* #x, y -- ie explicit rotation by Y. */
4778 if (my_get_expression (&expr, str))
4779 return FAIL;
4780
4781 if (expr.X_op != O_constant)
4782 {
f03698e6 4783 inst.error = _("constant expression expected");
b99bd4ef
NC
4784 return FAIL;
4785 }
4786
4787 /* Rotate must be a multiple of 2. */
4788 if (((unsigned) expr.X_add_number) > 30
4789 || (expr.X_add_number & 1) != 0
4790 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
4791 {
f03698e6 4792 inst.error = _("invalid constant");
b99bd4ef
NC
4793 return FAIL;
4794 }
4795 inst.instruction |= INST_IMMEDIATE;
4796 inst.instruction |= inst.reloc.exp.X_add_number;
4797 inst.instruction |= expr.X_add_number << 7;
4798 return SUCCESS;
4799 }
4800
4801 /* Implicit rotation, select a suitable one. */
4802 value = validate_immediate (inst.reloc.exp.X_add_number);
4803
4804 if (value == FAIL)
4805 {
4806 /* Can't be done. Perhaps the code reads something like
4807 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4808 if ((value = negate_data_op (&inst.instruction,
4809 inst.reloc.exp.X_add_number))
4810 == FAIL)
4811 {
f03698e6 4812 inst.error = _("invalid constant");
b99bd4ef
NC
4813 return FAIL;
4814 }
4815 }
4816
4817 inst.instruction |= value;
4818 }
4819
4820 inst.instruction |= INST_IMMEDIATE;
4821 return SUCCESS;
4822 }
4823
4824 (*str)++;
f03698e6 4825 inst.error = _("register or shift expression expected");
b99bd4ef
NC
4826 return FAIL;
4827 }
4828}
4829
4830static int
4831fp_op2 (str)
4832 char ** str;
4833{
4834 skip_whitespace (* str);
4835
4836 if (fp_reg_required_here (str, 0) != FAIL)
4837 return SUCCESS;
4838 else
4839 {
4840 /* Immediate expression. */
4841 if (*((*str)++) == '#')
4842 {
4843 int i;
4844
4845 inst.error = NULL;
4846
4847 skip_whitespace (* str);
4848
4849 /* First try and match exact strings, this is to guarantee
4850 that some formats will work even for cross assembly. */
4851
4852 for (i = 0; fp_const[i]; i++)
4853 {
4854 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
4855 {
4856 char *start = *str;
4857
4858 *str += strlen (fp_const[i]);
4859 if (is_end_of_line[(unsigned char) **str])
4860 {
4861 inst.instruction |= i + 8;
4862 return SUCCESS;
4863 }
4864 *str = start;
4865 }
4866 }
4867
4868 /* Just because we didn't get a match doesn't mean that the
4869 constant isn't valid, just that it is in a format that we
4870 don't automatically recognize. Try parsing it with
4871 the standard expression routines. */
4872 if ((i = my_get_float_expression (str)) >= 0)
4873 {
4874 inst.instruction |= i + 8;
4875 return SUCCESS;
4876 }
4877
f03698e6 4878 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
4879 return FAIL;
4880 }
4881 inst.error =
f03698e6 4882 _("floating point register or immediate expression expected");
b99bd4ef
NC
4883 return FAIL;
4884 }
4885}
4886
4887static void
f2b7cb0a 4888do_arit (str)
b99bd4ef 4889 char * str;
b99bd4ef
NC
4890{
4891 skip_whitespace (str);
4892
4893 if (reg_required_here (&str, 12) == FAIL
4894 || skip_past_comma (&str) == FAIL
4895 || reg_required_here (&str, 16) == FAIL
4896 || skip_past_comma (&str) == FAIL
4897 || data_op2 (&str) == FAIL)
4898 {
4899 if (!inst.error)
4900 inst.error = BAD_ARGS;
4901 return;
4902 }
4903
b99bd4ef
NC
4904 end_of_line (str);
4905 return;
4906}
4907
4908static void
f2b7cb0a 4909do_adr (str)
b99bd4ef 4910 char * str;
b99bd4ef 4911{
90e4755a
RE
4912 /* This is a pseudo-op of the form "adr rd, label" to be converted
4913 into a relative address of the form "add rd, pc, #label-.-8". */
4914 skip_whitespace (str);
4915
4916 if (reg_required_here (&str, 12) == FAIL
4917 || skip_past_comma (&str) == FAIL
4918 || my_get_expression (&inst.reloc.exp, &str))
4919 {
4920 if (!inst.error)
4921 inst.error = BAD_ARGS;
4922 return;
4923 }
4924
4925 /* Frag hacking will turn this into a sub instruction if the offset turns
4926 out to be negative. */
4927 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4928 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
4929 inst.reloc.pc_rel = 1;
4930
4931 end_of_line (str);
4932}
4933
4934static void
f2b7cb0a 4935do_adrl (str)
90e4755a 4936 char * str;
90e4755a
RE
4937{
4938 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4939 into a relative address of the form:
4940 add rd, pc, #low(label-.-8)"
4941 add rd, rd, #high(label-.-8)" */
4942
4943 skip_whitespace (str);
4944
4945 if (reg_required_here (&str, 12) == FAIL
4946 || skip_past_comma (&str) == FAIL
4947 || my_get_expression (&inst.reloc.exp, &str))
4948 {
4949 if (!inst.error)
4950 inst.error = BAD_ARGS;
4951
4952 return;
4953 }
4954
4955 end_of_line (str);
4956 /* Frag hacking will turn this into a sub instruction if the offset turns
4957 out to be negative. */
4958 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
4959 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
4960 inst.reloc.pc_rel = 1;
4961 inst.size = INSN_SIZE * 2;
4962
4963 return;
4964}
4965
4966static void
f2b7cb0a 4967do_cmp (str)
90e4755a 4968 char * str;
90e4755a
RE
4969{
4970 skip_whitespace (str);
4971
4972 if (reg_required_here (&str, 16) == FAIL)
4973 {
4974 if (!inst.error)
4975 inst.error = BAD_ARGS;
4976 return;
4977 }
4978
4979 if (skip_past_comma (&str) == FAIL
4980 || data_op2 (&str) == FAIL)
4981 {
4982 if (!inst.error)
4983 inst.error = BAD_ARGS;
4984 return;
4985 }
4986
90e4755a
RE
4987 end_of_line (str);
4988 return;
4989}
4990
4991static void
f2b7cb0a 4992do_mov (str)
90e4755a 4993 char * str;
90e4755a
RE
4994{
4995 skip_whitespace (str);
4996
4997 if (reg_required_here (&str, 12) == FAIL)
4998 {
4999 if (!inst.error)
5000 inst.error = BAD_ARGS;
5001 return;
5002 }
5003
5004 if (skip_past_comma (&str) == FAIL
5005 || data_op2 (&str) == FAIL)
5006 {
5007 if (!inst.error)
5008 inst.error = BAD_ARGS;
5009 return;
5010 }
5011
90e4755a
RE
5012 end_of_line (str);
5013 return;
5014}
5015
5016static int
5017ldst_extend (str)
5018 char ** str;
5019{
5020 int add = INDEX_UP;
5021
5022 switch (**str)
5023 {
5024 case '#':
5025 case '$':
5026 (*str)++;
5027 if (my_get_expression (& inst.reloc.exp, str))
5028 return FAIL;
5029
5030 if (inst.reloc.exp.X_op == O_constant)
5031 {
5032 int value = inst.reloc.exp.X_add_number;
5033
5034 if (value < -4095 || value > 4095)
5035 {
5036 inst.error = _("address offset too large");
5037 return FAIL;
5038 }
5039
5040 if (value < 0)
5041 {
5042 value = -value;
5043 add = 0;
5044 }
5045
5046 inst.instruction |= add | value;
5047 }
5048 else
5049 {
5050 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5051 inst.reloc.pc_rel = 0;
5052 }
5053 return SUCCESS;
5054
5055 case '-':
5056 add = 0;
5057 /* Fall through. */
5058
5059 case '+':
5060 (*str)++;
5061 /* Fall through. */
5062
5063 default:
5064 if (reg_required_here (str, 0) == FAIL)
5065 return FAIL;
5066
5067 inst.instruction |= add | OFFSET_REG;
5068 if (skip_past_comma (str) == SUCCESS)
5069 return decode_shift (str, SHIFT_RESTRICT);
5070
5071 return SUCCESS;
5072 }
5073}
5074
5075static void
f2b7cb0a 5076do_ldst (str)
90e4755a 5077 char * str;
90e4755a
RE
5078{
5079 int pre_inc = 0;
5080 int conflict_reg;
5081 int value;
5082
b99bd4ef
NC
5083 skip_whitespace (str);
5084
90e4755a
RE
5085 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
5086 {
5087 if (!inst.error)
5088 inst.error = BAD_ARGS;
5089 return;
5090 }
5091
5092 if (skip_past_comma (&str) == FAIL)
5093 {
f03698e6 5094 inst.error = _("address expected");
90e4755a
RE
5095 return;
5096 }
5097
90e4755a
RE
5098 if (*str == '[')
5099 {
5100 int reg;
5101
5102 str++;
5103
5104 skip_whitespace (str);
5105
5106 if ((reg = reg_required_here (&str, 16)) == FAIL)
5107 return;
5108
5109 /* Conflicts can occur on stores as well as loads. */
5110 conflict_reg = (conflict_reg == reg);
5111
5112 skip_whitespace (str);
5113
5114 if (*str == ']')
5115 {
5116 str ++;
5117
5118 if (skip_past_comma (&str) == SUCCESS)
5119 {
5120 /* [Rn],... (post inc) */
5121 if (ldst_extend (&str) == FAIL)
5122 return;
5123 if (conflict_reg)
5124 as_warn (_("%s register same as write-back base"),
5125 ((inst.instruction & LOAD_BIT)
5126 ? _("destination") : _("source")));
5127 }
5128 else
5129 {
5130 /* [Rn] */
5131 skip_whitespace (str);
5132
5133 if (*str == '!')
5134 {
5135 if (conflict_reg)
5136 as_warn (_("%s register same as write-back base"),
5137 ((inst.instruction & LOAD_BIT)
5138 ? _("destination") : _("source")));
5139 str++;
5140 inst.instruction |= WRITE_BACK;
5141 }
5142
5143 inst.instruction |= INDEX_UP;
5144 pre_inc = 1;
5145 }
5146 }
5147 else
5148 {
5149 /* [Rn,...] */
5150 if (skip_past_comma (&str) == FAIL)
5151 {
5152 inst.error = _("pre-indexed expression expected");
5153 return;
5154 }
5155
5156 pre_inc = 1;
5157 if (ldst_extend (&str) == FAIL)
5158 return;
5159
5160 skip_whitespace (str);
5161
5162 if (*str++ != ']')
5163 {
5164 inst.error = _("missing ]");
5165 return;
5166 }
5167
5168 skip_whitespace (str);
5169
5170 if (*str == '!')
5171 {
5172 if (conflict_reg)
5173 as_warn (_("%s register same as write-back base"),
5174 ((inst.instruction & LOAD_BIT)
5175 ? _("destination") : _("source")));
5176 str++;
5177 inst.instruction |= WRITE_BACK;
5178 }
5179 }
5180 }
5181 else if (*str == '=')
5182 {
f03698e6
RE
5183 if ((inst.instruction & LOAD_BIT) == 0)
5184 {
5185 inst.error = _("invalid pseudo operation");
5186 return;
5187 }
5188
90e4755a
RE
5189 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5190 str++;
5191
5192 skip_whitespace (str);
5193
5194 if (my_get_expression (&inst.reloc.exp, &str))
5195 return;
5196
5197 if (inst.reloc.exp.X_op != O_constant
5198 && inst.reloc.exp.X_op != O_symbol)
5199 {
f03698e6 5200 inst.error = _("constant expression expected");
90e4755a
RE
5201 return;
5202 }
5203
e28cd48c 5204 if (inst.reloc.exp.X_op == O_constant)
90e4755a 5205 {
e28cd48c
RE
5206 value = validate_immediate (inst.reloc.exp.X_add_number);
5207
5208 if (value != FAIL)
90e4755a 5209 {
e28cd48c
RE
5210 /* This can be done with a mov instruction. */
5211 inst.instruction &= LITERAL_MASK;
5212 inst.instruction |= (INST_IMMEDIATE
5213 | (OPCODE_MOV << DATA_OP_SHIFT));
5214 inst.instruction |= value & 0xfff;
5215 end_of_line (str);
90e4755a
RE
5216 return;
5217 }
b99bd4ef 5218
e28cd48c
RE
5219 value = validate_immediate (~inst.reloc.exp.X_add_number);
5220
5221 if (value != FAIL)
5222 {
5223 /* This can be done with a mvn instruction. */
5224 inst.instruction &= LITERAL_MASK;
5225 inst.instruction |= (INST_IMMEDIATE
5226 | (OPCODE_MVN << DATA_OP_SHIFT));
5227 inst.instruction |= value & 0xfff;
5228 end_of_line (str);
5229 return;
5230 }
90e4755a 5231 }
e28cd48c
RE
5232
5233 /* Insert into literal pool. */
5234 if (add_to_lit_pool () == FAIL)
5235 {
5236 if (!inst.error)
5237 inst.error = _("literal pool insertion failed");
5238 return;
5239 }
5240
5241 /* Change the instruction exp to point to the pool. */
5242 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
5243 inst.reloc.pc_rel = 1;
5244 inst.instruction |= (REG_PC << 16);
5245 pre_inc = 1;
1cac9012
NC
5246 }
5247 else
5248 {
90e4755a
RE
5249 if (my_get_expression (&inst.reloc.exp, &str))
5250 return;
5251
5252 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5253#ifndef TE_WINCE
5254 /* PC rel adjust. */
5255 inst.reloc.exp.X_add_number -= 8;
5256#endif
1cac9012 5257 inst.reloc.pc_rel = 1;
90e4755a
RE
5258 inst.instruction |= (REG_PC << 16);
5259 pre_inc = 1;
b99bd4ef
NC
5260 }
5261
90e4755a 5262 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 5263 end_of_line (str);
90e4755a 5264 return;
b99bd4ef
NC
5265}
5266
5267static void
f2b7cb0a 5268do_ldstt (str)
90e4755a 5269 char * str;
b99bd4ef 5270{
90e4755a
RE
5271 int conflict_reg;
5272
b99bd4ef
NC
5273 skip_whitespace (str);
5274
90e4755a 5275 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
5276 {
5277 if (!inst.error)
5278 inst.error = BAD_ARGS;
5279 return;
5280 }
5281
90e4755a 5282 if (skip_past_comma (& str) == FAIL)
b99bd4ef 5283 {
f03698e6 5284 inst.error = _("address expected");
b99bd4ef
NC
5285 return;
5286 }
5287
90e4755a
RE
5288 if (*str == '[')
5289 {
5290 int reg;
b99bd4ef 5291
90e4755a 5292 str++;
b99bd4ef 5293
90e4755a 5294 skip_whitespace (str);
b99bd4ef 5295
90e4755a
RE
5296 if ((reg = reg_required_here (&str, 16)) == FAIL)
5297 return;
b99bd4ef 5298
90e4755a
RE
5299 /* ldrt/strt always use post-indexed addressing, so if the base is
5300 the same as Rd, we warn. */
5301 if (conflict_reg == reg)
5302 as_warn (_("%s register same as write-back base"),
5303 ((inst.instruction & LOAD_BIT)
5304 ? _("destination") : _("source")));
5305
5306 skip_whitespace (str);
5307
5308 if (*str == ']')
5309 {
5310 str ++;
5311
5312 if (skip_past_comma (&str) == SUCCESS)
5313 {
5314 /* [Rn],... (post inc) */
5315 if (ldst_extend (&str) == FAIL)
5316 return;
5317 }
5318 else
5319 {
5320 /* [Rn] */
5321 skip_whitespace (str);
5322
5323 /* Skip a write-back '!'. */
5324 if (*str == '!')
5325 str++;
5326
5327 inst.instruction |= INDEX_UP;
5328 }
5329 }
5330 else
5331 {
5332 inst.error = _("post-indexed expression expected");
5333 return;
5334 }
5335 }
5336 else
b99bd4ef 5337 {
90e4755a 5338 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
5339 return;
5340 }
5341
b99bd4ef
NC
5342 end_of_line (str);
5343 return;
5344}
5345
5346static int
90e4755a 5347ldst_extend_v4 (str)
b99bd4ef 5348 char ** str;
b99bd4ef
NC
5349{
5350 int add = INDEX_UP;
5351
5352 switch (**str)
5353 {
5354 case '#':
5355 case '$':
5356 (*str)++;
5357 if (my_get_expression (& inst.reloc.exp, str))
5358 return FAIL;
5359
5360 if (inst.reloc.exp.X_op == O_constant)
5361 {
5362 int value = inst.reloc.exp.X_add_number;
5363
90e4755a 5364 if (value < -255 || value > 255)
b99bd4ef
NC
5365 {
5366 inst.error = _("address offset too large");
5367 return FAIL;
5368 }
5369
5370 if (value < 0)
5371 {
5372 value = -value;
5373 add = 0;
5374 }
5375
5376 /* Halfword and signextension instructions have the
5377 immediate value split across bits 11..8 and bits 3..0. */
90e4755a
RE
5378 inst.instruction |= (add | HWOFFSET_IMM
5379 | ((value >> 4) << 8) | (value & 0xF));
b99bd4ef
NC
5380 }
5381 else
5382 {
90e4755a
RE
5383 inst.instruction |= HWOFFSET_IMM;
5384 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
5385 inst.reloc.pc_rel = 0;
5386 }
5387 return SUCCESS;
5388
5389 case '-':
5390 add = 0;
5391 /* Fall through. */
5392
5393 case '+':
5394 (*str)++;
5395 /* Fall through. */
5396
5397 default:
5398 if (reg_required_here (str, 0) == FAIL)
5399 return FAIL;
5400
90e4755a 5401 inst.instruction |= add;
b99bd4ef
NC
5402 return SUCCESS;
5403 }
5404}
5405
90e4755a 5406/* Halfword and signed-byte load/store operations. */
b99bd4ef 5407static void
f2b7cb0a 5408do_ldstv4 (str)
b99bd4ef 5409 char * str;
b99bd4ef 5410{
b99bd4ef
NC
5411 int pre_inc = 0;
5412 int conflict_reg;
5413 int value;
5414
b99bd4ef
NC
5415 skip_whitespace (str);
5416
5417 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
5418 {
5419 if (!inst.error)
5420 inst.error = BAD_ARGS;
5421 return;
5422 }
5423
5424 if (skip_past_comma (& str) == FAIL)
5425 {
f03698e6 5426 inst.error = _("address expected");
b99bd4ef
NC
5427 return;
5428 }
5429
5430 if (*str == '[')
5431 {
5432 int reg;
5433
5434 str++;
5435
5436 skip_whitespace (str);
5437
5438 if ((reg = reg_required_here (&str, 16)) == FAIL)
5439 return;
5440
5441 /* Conflicts can occur on stores as well as loads. */
5442 conflict_reg = (conflict_reg == reg);
5443
5444 skip_whitespace (str);
5445
5446 if (*str == ']')
5447 {
5448 str ++;
5449
5450 if (skip_past_comma (&str) == SUCCESS)
5451 {
5452 /* [Rn],... (post inc) */
90e4755a 5453 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
5454 return;
5455 if (conflict_reg)
90e4755a
RE
5456 as_warn (_("%s register same as write-back base"),
5457 ((inst.instruction & LOAD_BIT)
5458 ? _("destination") : _("source")));
b99bd4ef
NC
5459 }
5460 else
5461 {
5462 /* [Rn] */
90e4755a 5463 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
5464
5465 skip_whitespace (str);
5466
5467 if (*str == '!')
5468 {
5469 if (conflict_reg)
5470 as_warn (_("%s register same as write-back base"),
5471 ((inst.instruction & LOAD_BIT)
5472 ? _("destination") : _("source")));
5473 str++;
5474 inst.instruction |= WRITE_BACK;
5475 }
5476
90e4755a
RE
5477 inst.instruction |= INDEX_UP;
5478 pre_inc = 1;
b99bd4ef
NC
5479 }
5480 }
5481 else
5482 {
5483 /* [Rn,...] */
5484 if (skip_past_comma (&str) == FAIL)
5485 {
5486 inst.error = _("pre-indexed expression expected");
5487 return;
5488 }
5489
5490 pre_inc = 1;
90e4755a 5491 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
5492 return;
5493
5494 skip_whitespace (str);
5495
5496 if (*str++ != ']')
5497 {
5498 inst.error = _("missing ]");
5499 return;
5500 }
5501
5502 skip_whitespace (str);
5503
5504 if (*str == '!')
5505 {
5506 if (conflict_reg)
5507 as_warn (_("%s register same as write-back base"),
5508 ((inst.instruction & LOAD_BIT)
5509 ? _("destination") : _("source")));
5510 str++;
5511 inst.instruction |= WRITE_BACK;
5512 }
5513 }
5514 }
5515 else if (*str == '=')
5516 {
f03698e6
RE
5517 if ((inst.instruction & LOAD_BIT) == 0)
5518 {
5519 inst.error = _("invalid pseudo operation");
5520 return;
5521 }
5522
90e4755a 5523 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
5524 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5525 str++;
5526
5527 skip_whitespace (str);
5528
5529 if (my_get_expression (&inst.reloc.exp, &str))
5530 return;
5531
5532 if (inst.reloc.exp.X_op != O_constant
5533 && inst.reloc.exp.X_op != O_symbol)
5534 {
f03698e6 5535 inst.error = _("constant expression expected");
b99bd4ef
NC
5536 return;
5537 }
5538
d8273442 5539 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 5540 {
d8273442
NC
5541 value = validate_immediate (inst.reloc.exp.X_add_number);
5542
5543 if (value != FAIL)
b99bd4ef 5544 {
d8273442
NC
5545 /* This can be done with a mov instruction. */
5546 inst.instruction &= LITERAL_MASK;
5547 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 5548 inst.instruction |= value & 0xfff;
d8273442 5549 end_of_line (str);
b99bd4ef
NC
5550 return;
5551 }
cc8a6dd0 5552
d8273442 5553 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 5554
d8273442 5555 if (value != FAIL)
b99bd4ef 5556 {
d8273442
NC
5557 /* This can be done with a mvn instruction. */
5558 inst.instruction &= LITERAL_MASK;
5559 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 5560 inst.instruction |= value & 0xfff;
d8273442
NC
5561 end_of_line (str);
5562 return;
b99bd4ef 5563 }
b99bd4ef 5564 }
d8273442
NC
5565
5566 /* Insert into literal pool. */
5567 if (add_to_lit_pool () == FAIL)
5568 {
5569 if (!inst.error)
5570 inst.error = _("literal pool insertion failed");
5571 return;
5572 }
5573
5574 /* Change the instruction exp to point to the pool. */
90e4755a
RE
5575 inst.instruction |= HWOFFSET_IMM;
5576 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
5577 inst.reloc.pc_rel = 1;
5578 inst.instruction |= (REG_PC << 16);
5579 pre_inc = 1;
b99bd4ef
NC
5580 }
5581 else
5582 {
5583 if (my_get_expression (&inst.reloc.exp, &str))
5584 return;
5585
90e4755a
RE
5586 inst.instruction |= HWOFFSET_IMM;
5587 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
5588#ifndef TE_WINCE
5589 /* PC rel adjust. */
5590 inst.reloc.exp.X_add_number -= 8;
5591#endif
5592 inst.reloc.pc_rel = 1;
5593 inst.instruction |= (REG_PC << 16);
5594 pre_inc = 1;
5595 }
5596
90e4755a 5597 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef
NC
5598 end_of_line (str);
5599 return;
5600}
5601
5602static long
5603reg_list (strp)
5604 char ** strp;
5605{
5606 char * str = * strp;
5607 long range = 0;
5608 int another_range;
5609
5610 /* We come back here if we get ranges concatenated by '+' or '|'. */
5611 do
5612 {
5613 another_range = 0;
5614
5615 if (*str == '{')
5616 {
5617 int in_range = 0;
5618 int cur_reg = -1;
5619
5620 str++;
5621 do
5622 {
5623 int reg;
5624
5625 skip_whitespace (str);
5626
5627 if ((reg = reg_required_here (& str, -1)) == FAIL)
5628 return FAIL;
5629
5630 if (in_range)
5631 {
5632 int i;
5633
5634 if (reg <= cur_reg)
5635 {
f03698e6 5636 inst.error = _("bad range in register list");
b99bd4ef
NC
5637 return FAIL;
5638 }
5639
5640 for (i = cur_reg + 1; i < reg; i++)
5641 {
5642 if (range & (1 << i))
5643 as_tsktsk
f03698e6 5644 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
5645 i);
5646 else
5647 range |= 1 << i;
5648 }
5649 in_range = 0;
5650 }
5651
5652 if (range & (1 << reg))
f03698e6 5653 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
5654 reg);
5655 else if (reg <= cur_reg)
f03698e6 5656 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
5657
5658 range |= 1 << reg;
5659 cur_reg = reg;
5660 }
5661 while (skip_past_comma (&str) != FAIL
5662 || (in_range = 1, *str++ == '-'));
5663 str--;
5664 skip_whitespace (str);
5665
5666 if (*str++ != '}')
5667 {
f03698e6 5668 inst.error = _("missing `}'");
b99bd4ef
NC
5669 return FAIL;
5670 }
5671 }
5672 else
5673 {
5674 expressionS expr;
5675
5676 if (my_get_expression (&expr, &str))
5677 return FAIL;
5678
5679 if (expr.X_op == O_constant)
5680 {
5681 if (expr.X_add_number
5682 != (expr.X_add_number & 0x0000ffff))
5683 {
5684 inst.error = _("invalid register mask");
5685 return FAIL;
5686 }
5687
5688 if ((range & expr.X_add_number) != 0)
5689 {
5690 int regno = range & expr.X_add_number;
5691
5692 regno &= -regno;
5693 regno = (1 << regno) - 1;
5694 as_tsktsk
f03698e6 5695 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
5696 regno);
5697 }
5698
5699 range |= expr.X_add_number;
5700 }
5701 else
5702 {
5703 if (inst.reloc.type != 0)
5704 {
5705 inst.error = _("expression too complex");
5706 return FAIL;
5707 }
5708
5709 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
5710 inst.reloc.type = BFD_RELOC_ARM_MULTI;
5711 inst.reloc.pc_rel = 0;
5712 }
5713 }
5714
5715 skip_whitespace (str);
5716
5717 if (*str == '|' || *str == '+')
5718 {
5719 str++;
5720 another_range = 1;
5721 }
5722 }
5723 while (another_range);
5724
5725 *strp = str;
5726 return range;
5727}
5728
5729static void
f2b7cb0a 5730do_ldmstm (str)
b99bd4ef 5731 char * str;
b99bd4ef
NC
5732{
5733 int base_reg;
5734 long range;
5735
5736 skip_whitespace (str);
5737
5738 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
5739 return;
5740
5741 if (base_reg == REG_PC)
5742 {
5743 inst.error = _("r15 not allowed as base register");
5744 return;
5745 }
5746
5747 skip_whitespace (str);
5748
5749 if (*str == '!')
5750 {
90e4755a 5751 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
5752 str++;
5753 }
5754
5755 if (skip_past_comma (&str) == FAIL
5756 || (range = reg_list (&str)) == FAIL)
5757 {
5758 if (! inst.error)
5759 inst.error = BAD_ARGS;
5760 return;
5761 }
5762
5763 if (*str == '^')
5764 {
5765 str++;
90e4755a 5766 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
5767 }
5768
6189168b
NC
5769 if (inst.instruction & WRITE_BACK)
5770 {
5771 /* Check for unpredictable uses of writeback. */
5772 if (inst.instruction & LOAD_BIT)
5773 {
5774 /* Not allowed in LDM type 2. */
5775 if ((inst.instruction & LDM_TYPE_2_OR_3)
5776 && ((range & (1 << REG_PC)) == 0))
5777 as_warn (_("writeback of base register is UNPREDICTABLE"));
5778 /* Only allowed if base reg not in list for other types. */
5779 else if (range & (1 << base_reg))
5780 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
5781 }
5782 else /* STM. */
5783 {
5784 /* Not allowed for type 2. */
5785 if (inst.instruction & LDM_TYPE_2_OR_3)
5786 as_warn (_("writeback of base register is UNPREDICTABLE"));
5787 /* Only allowed if base reg not in list, or first in list. */
5788 else if ((range & (1 << base_reg))
5789 && (range & ((1 << base_reg) - 1)))
5790 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
5791 }
5792 }
5793
f2b7cb0a 5794 inst.instruction |= range;
b99bd4ef
NC
5795 end_of_line (str);
5796 return;
5797}
5798
5799static void
f2b7cb0a 5800do_swi (str)
b99bd4ef 5801 char * str;
b99bd4ef
NC
5802{
5803 skip_whitespace (str);
5804
5805 /* Allow optional leading '#'. */
5806 if (is_immediate_prefix (*str))
5807 str++;
5808
5809 if (my_get_expression (& inst.reloc.exp, & str))
5810 return;
5811
5812 inst.reloc.type = BFD_RELOC_ARM_SWI;
5813 inst.reloc.pc_rel = 0;
b99bd4ef
NC
5814 end_of_line (str);
5815
5816 return;
5817}
5818
5819static void
f2b7cb0a 5820do_swap (str)
b99bd4ef 5821 char * str;
b99bd4ef
NC
5822{
5823 int reg;
5824
5825 skip_whitespace (str);
5826
5827 if ((reg = reg_required_here (&str, 12)) == FAIL)
5828 return;
5829
5830 if (reg == REG_PC)
5831 {
5832 inst.error = _("r15 not allowed in swap");
5833 return;
5834 }
5835
5836 if (skip_past_comma (&str) == FAIL
5837 || (reg = reg_required_here (&str, 0)) == FAIL)
5838 {
5839 if (!inst.error)
5840 inst.error = BAD_ARGS;
5841 return;
5842 }
5843
5844 if (reg == REG_PC)
5845 {
5846 inst.error = _("r15 not allowed in swap");
5847 return;
5848 }
5849
5850 if (skip_past_comma (&str) == FAIL
5851 || *str++ != '[')
5852 {
5853 inst.error = BAD_ARGS;
5854 return;
5855 }
5856
5857 skip_whitespace (str);
5858
5859 if ((reg = reg_required_here (&str, 16)) == FAIL)
5860 return;
5861
5862 if (reg == REG_PC)
5863 {
5864 inst.error = BAD_PC;
5865 return;
5866 }
5867
5868 skip_whitespace (str);
5869
5870 if (*str++ != ']')
5871 {
5872 inst.error = _("missing ]");
5873 return;
5874 }
5875
b99bd4ef
NC
5876 end_of_line (str);
5877 return;
5878}
5879
5880static void
f2b7cb0a 5881do_branch (str)
b99bd4ef 5882 char * str;
b99bd4ef
NC
5883{
5884 if (my_get_expression (&inst.reloc.exp, &str))
5885 return;
5886
5887#ifdef OBJ_ELF
5888 {
5889 char * save_in;
5890
5891 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5892 required for the instruction. */
5893
5894 /* arm_parse_reloc () works on input_line_pointer.
5895 We actually want to parse the operands to the branch instruction
5896 passed in 'str'. Save the input pointer and restore it later. */
5897 save_in = input_line_pointer;
5898 input_line_pointer = str;
5899 if (inst.reloc.exp.X_op == O_symbol
5900 && *str == '('
5901 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5902 {
5903 inst.reloc.type = BFD_RELOC_ARM_PLT32;
5904 inst.reloc.pc_rel = 0;
5905 /* Modify str to point to after parsed operands, otherwise
5906 end_of_line() will complain about the (PLT) left in str. */
5907 str = input_line_pointer;
5908 }
5909 else
5910 {
5911 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5912 inst.reloc.pc_rel = 1;
5913 }
5914 input_line_pointer = save_in;
5915 }
5916#else
5917 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
5918 inst.reloc.pc_rel = 1;
5919#endif /* OBJ_ELF */
5920
5921 end_of_line (str);
5922 return;
5923}
5924
5925static void
f2b7cb0a 5926do_bx (str)
b99bd4ef 5927 char * str;
b99bd4ef
NC
5928{
5929 int reg;
5930
5931 skip_whitespace (str);
5932
5933 if ((reg = reg_required_here (&str, 0)) == FAIL)
5934 {
5935 inst.error = BAD_ARGS;
5936 return;
5937 }
5938
5939 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5940 if (reg == REG_PC)
f03698e6 5941 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
b99bd4ef
NC
5942
5943 end_of_line (str);
5944}
5945
5946static void
f2b7cb0a 5947do_cdp (str)
b99bd4ef 5948 char * str;
b99bd4ef
NC
5949{
5950 /* Co-processor data operation.
5951 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5952 skip_whitespace (str);
5953
5954 if (co_proc_number (&str) == FAIL)
5955 {
5956 if (!inst.error)
5957 inst.error = BAD_ARGS;
5958 return;
5959 }
5960
5961 if (skip_past_comma (&str) == FAIL
5962 || cp_opc_expr (&str, 20,4) == FAIL)
5963 {
5964 if (!inst.error)
5965 inst.error = BAD_ARGS;
5966 return;
5967 }
5968
5969 if (skip_past_comma (&str) == FAIL
5970 || cp_reg_required_here (&str, 12) == FAIL)
5971 {
5972 if (!inst.error)
5973 inst.error = BAD_ARGS;
5974 return;
5975 }
5976
5977 if (skip_past_comma (&str) == FAIL
5978 || cp_reg_required_here (&str, 16) == FAIL)
5979 {
5980 if (!inst.error)
5981 inst.error = BAD_ARGS;
5982 return;
5983 }
5984
5985 if (skip_past_comma (&str) == FAIL
5986 || cp_reg_required_here (&str, 0) == FAIL)
5987 {
5988 if (!inst.error)
5989 inst.error = BAD_ARGS;
5990 return;
5991 }
5992
5993 if (skip_past_comma (&str) == SUCCESS)
5994 {
5995 if (cp_opc_expr (&str, 5, 3) == FAIL)
5996 {
5997 if (!inst.error)
5998 inst.error = BAD_ARGS;
5999 return;
6000 }
6001 }
6002
6003 end_of_line (str);
6004 return;
6005}
6006
6007static void
f2b7cb0a 6008do_lstc (str)
b99bd4ef 6009 char * str;
b99bd4ef
NC
6010{
6011 /* Co-processor register load/store.
6012 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6013
6014 skip_whitespace (str);
6015
6016 if (co_proc_number (&str) == FAIL)
6017 {
6018 if (!inst.error)
6019 inst.error = BAD_ARGS;
6020 return;
6021 }
6022
6023 if (skip_past_comma (&str) == FAIL
6024 || cp_reg_required_here (&str, 12) == FAIL)
6025 {
6026 if (!inst.error)
6027 inst.error = BAD_ARGS;
6028 return;
6029 }
6030
6031 if (skip_past_comma (&str) == FAIL
bfae80f2 6032 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
6033 {
6034 if (! inst.error)
6035 inst.error = BAD_ARGS;
6036 return;
6037 }
6038
b99bd4ef
NC
6039 end_of_line (str);
6040 return;
6041}
6042
6043static void
f2b7cb0a 6044do_co_reg (str)
b99bd4ef 6045 char * str;
b99bd4ef
NC
6046{
6047 /* Co-processor register transfer.
6048 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6049
6050 skip_whitespace (str);
6051
6052 if (co_proc_number (&str) == FAIL)
6053 {
6054 if (!inst.error)
6055 inst.error = BAD_ARGS;
6056 return;
6057 }
6058
6059 if (skip_past_comma (&str) == FAIL
6060 || cp_opc_expr (&str, 21, 3) == FAIL)
6061 {
6062 if (!inst.error)
6063 inst.error = BAD_ARGS;
6064 return;
6065 }
6066
6067 if (skip_past_comma (&str) == FAIL
6068 || reg_required_here (&str, 12) == FAIL)
6069 {
6070 if (!inst.error)
6071 inst.error = BAD_ARGS;
6072 return;
6073 }
6074
6075 if (skip_past_comma (&str) == FAIL
6076 || cp_reg_required_here (&str, 16) == FAIL)
6077 {
6078 if (!inst.error)
6079 inst.error = BAD_ARGS;
6080 return;
6081 }
6082
6083 if (skip_past_comma (&str) == FAIL
6084 || cp_reg_required_here (&str, 0) == FAIL)
6085 {
6086 if (!inst.error)
6087 inst.error = BAD_ARGS;
6088 return;
6089 }
6090
6091 if (skip_past_comma (&str) == SUCCESS)
6092 {
6093 if (cp_opc_expr (&str, 5, 3) == FAIL)
6094 {
6095 if (!inst.error)
6096 inst.error = BAD_ARGS;
6097 return;
6098 }
6099 }
b99bd4ef
NC
6100
6101 end_of_line (str);
6102 return;
6103}
6104
6105static void
f2b7cb0a 6106do_fpa_ctrl (str)
b99bd4ef 6107 char * str;
b99bd4ef
NC
6108{
6109 /* FP control registers.
6110 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6111
6112 skip_whitespace (str);
6113
6114 if (reg_required_here (&str, 12) == FAIL)
6115 {
6116 if (!inst.error)
6117 inst.error = BAD_ARGS;
6118 return;
6119 }
6120
6121 end_of_line (str);
6122 return;
6123}
6124
6125static void
f2b7cb0a 6126do_fpa_ldst (str)
b99bd4ef 6127 char * str;
b99bd4ef
NC
6128{
6129 skip_whitespace (str);
6130
b99bd4ef
NC
6131 if (fp_reg_required_here (&str, 12) == FAIL)
6132 {
6133 if (!inst.error)
6134 inst.error = BAD_ARGS;
6135 return;
6136 }
6137
6138 if (skip_past_comma (&str) == FAIL
bfae80f2 6139 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
6140 {
6141 if (!inst.error)
6142 inst.error = BAD_ARGS;
6143 return;
6144 }
6145
6146 end_of_line (str);
6147}
6148
6149static void
f2b7cb0a 6150do_fpa_ldmstm (str)
b99bd4ef 6151 char * str;
b99bd4ef
NC
6152{
6153 int num_regs;
6154
6155 skip_whitespace (str);
6156
6157 if (fp_reg_required_here (&str, 12) == FAIL)
6158 {
6159 if (! inst.error)
6160 inst.error = BAD_ARGS;
6161 return;
6162 }
6163
6164 /* Get Number of registers to transfer. */
6165 if (skip_past_comma (&str) == FAIL
6166 || my_get_expression (&inst.reloc.exp, &str))
6167 {
6168 if (! inst.error)
6169 inst.error = _("constant expression expected");
6170 return;
6171 }
6172
6173 if (inst.reloc.exp.X_op != O_constant)
6174 {
f03698e6 6175 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
6176 return;
6177 }
6178
6179 num_regs = inst.reloc.exp.X_add_number;
6180
6181 if (num_regs < 1 || num_regs > 4)
6182 {
6183 inst.error = _("number of registers must be in the range [1:4]");
6184 return;
6185 }
6186
6187 switch (num_regs)
6188 {
6189 case 1:
6190 inst.instruction |= CP_T_X;
6191 break;
6192 case 2:
6193 inst.instruction |= CP_T_Y;
6194 break;
6195 case 3:
6196 inst.instruction |= CP_T_Y | CP_T_X;
6197 break;
6198 case 4:
6199 break;
6200 default:
6201 abort ();
6202 }
6203
e28cd48c 6204 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
6205 {
6206 int reg;
6207 int write_back;
6208 int offset;
6209
6210 /* The instruction specified "ea" or "fd", so we can only accept
6211 [Rn]{!}. The instruction does not really support stacking or
6212 unstacking, so we have to emulate these by setting appropriate
6213 bits and offsets. */
6214 if (skip_past_comma (&str) == FAIL
6215 || *str != '[')
6216 {
6217 if (! inst.error)
6218 inst.error = BAD_ARGS;
6219 return;
6220 }
6221
6222 str++;
6223 skip_whitespace (str);
6224
6225 if ((reg = reg_required_here (&str, 16)) == FAIL)
6226 return;
6227
6228 skip_whitespace (str);
6229
6230 if (*str != ']')
6231 {
6232 inst.error = BAD_ARGS;
6233 return;
6234 }
6235
6236 str++;
6237 if (*str == '!')
6238 {
6239 write_back = 1;
6240 str++;
6241 if (reg == REG_PC)
6242 {
6243 inst.error =
f03698e6 6244 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
6245 return;
6246 }
6247 }
6248 else
6249 write_back = 0;
6250
90e4755a 6251 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
6252 {
6253 /* Pre-decrement. */
6254 offset = 3 * num_regs;
6255 if (write_back)
90e4755a 6256 inst.instruction |= CP_T_WB;
b99bd4ef
NC
6257 }
6258 else
6259 {
6260 /* Post-increment. */
6261 if (write_back)
6262 {
90e4755a 6263 inst.instruction |= CP_T_WB;
b99bd4ef
NC
6264 offset = 3 * num_regs;
6265 }
6266 else
6267 {
6268 /* No write-back, so convert this into a standard pre-increment
6269 instruction -- aesthetically more pleasing. */
90e4755a 6270 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
6271 offset = 0;
6272 }
6273 }
6274
f2b7cb0a 6275 inst.instruction |= offset;
b99bd4ef
NC
6276 }
6277 else if (skip_past_comma (&str) == FAIL
bfae80f2 6278 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
6279 {
6280 if (! inst.error)
6281 inst.error = BAD_ARGS;
6282 return;
6283 }
6284
6285 end_of_line (str);
6286}
6287
6288static void
f2b7cb0a 6289do_fpa_dyadic (str)
b99bd4ef 6290 char * str;
b99bd4ef
NC
6291{
6292 skip_whitespace (str);
6293
b99bd4ef
NC
6294 if (fp_reg_required_here (&str, 12) == FAIL)
6295 {
6296 if (! inst.error)
6297 inst.error = BAD_ARGS;
6298 return;
6299 }
6300
6301 if (skip_past_comma (&str) == FAIL
6302 || fp_reg_required_here (&str, 16) == FAIL)
6303 {
6304 if (! inst.error)
6305 inst.error = BAD_ARGS;
6306 return;
6307 }
6308
6309 if (skip_past_comma (&str) == FAIL
6310 || fp_op2 (&str) == FAIL)
6311 {
6312 if (! inst.error)
6313 inst.error = BAD_ARGS;
6314 return;
6315 }
6316
b99bd4ef
NC
6317 end_of_line (str);
6318 return;
6319}
6320
6321static void
f2b7cb0a 6322do_fpa_monadic (str)
b99bd4ef 6323 char * str;
b99bd4ef
NC
6324{
6325 skip_whitespace (str);
6326
b99bd4ef
NC
6327 if (fp_reg_required_here (&str, 12) == FAIL)
6328 {
6329 if (! inst.error)
6330 inst.error = BAD_ARGS;
6331 return;
6332 }
6333
6334 if (skip_past_comma (&str) == FAIL
6335 || fp_op2 (&str) == FAIL)
6336 {
6337 if (! inst.error)
6338 inst.error = BAD_ARGS;
6339 return;
6340 }
6341
b99bd4ef
NC
6342 end_of_line (str);
6343 return;
6344}
6345
6346static void
f2b7cb0a 6347do_fpa_cmp (str)
b99bd4ef 6348 char * str;
b99bd4ef
NC
6349{
6350 skip_whitespace (str);
6351
6352 if (fp_reg_required_here (&str, 16) == FAIL)
6353 {
6354 if (! inst.error)
6355 inst.error = BAD_ARGS;
6356 return;
6357 }
6358
6359 if (skip_past_comma (&str) == FAIL
6360 || fp_op2 (&str) == FAIL)
6361 {
6362 if (! inst.error)
6363 inst.error = BAD_ARGS;
6364 return;
6365 }
6366
b99bd4ef
NC
6367 end_of_line (str);
6368 return;
6369}
6370
6371static void
f2b7cb0a 6372do_fpa_from_reg (str)
b99bd4ef 6373 char * str;
b99bd4ef
NC
6374{
6375 skip_whitespace (str);
6376
b99bd4ef
NC
6377 if (fp_reg_required_here (&str, 16) == FAIL)
6378 {
6379 if (! inst.error)
6380 inst.error = BAD_ARGS;
6381 return;
6382 }
6383
6384 if (skip_past_comma (&str) == FAIL
6385 || reg_required_here (&str, 12) == FAIL)
6386 {
6387 if (! inst.error)
6388 inst.error = BAD_ARGS;
6389 return;
6390 }
6391
b99bd4ef
NC
6392 end_of_line (str);
6393 return;
6394}
6395
6396static void
f2b7cb0a 6397do_fpa_to_reg (str)
b99bd4ef 6398 char * str;
b99bd4ef
NC
6399{
6400 skip_whitespace (str);
6401
6402 if (reg_required_here (&str, 12) == FAIL)
6403 return;
6404
6405 if (skip_past_comma (&str) == FAIL
6406 || fp_reg_required_here (&str, 0) == FAIL)
6407 {
6408 if (! inst.error)
6409 inst.error = BAD_ARGS;
6410 return;
6411 }
6412
b99bd4ef
NC
6413 end_of_line (str);
6414 return;
6415}
6416
b99bd4ef 6417static int
bfae80f2
RE
6418vfp_sp_reg_required_here (str, pos)
6419 char **str;
6420 enum vfp_sp_reg_pos pos;
b99bd4ef 6421{
bfae80f2
RE
6422 int reg;
6423 char *start = *str;
b99bd4ef 6424
bfae80f2 6425 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 6426 {
bfae80f2 6427 switch (pos)
b99bd4ef 6428 {
bfae80f2
RE
6429 case VFP_REG_Sd:
6430 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
6431 break;
6432
6433 case VFP_REG_Sn:
6434 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
6435 break;
6436
6437 case VFP_REG_Sm:
6438 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
6439 break;
6440
6441 default:
6442 abort ();
b99bd4ef 6443 }
bfae80f2
RE
6444 return reg;
6445 }
b99bd4ef 6446
bfae80f2
RE
6447 /* In the few cases where we might be able to accept something else
6448 this error can be overridden. */
6449 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
6450
6451 /* Restore the start point. */
6452 *str = start;
6453 return FAIL;
6454}
6455
6456static int
6457vfp_dp_reg_required_here (str, pos)
6458 char **str;
f201ccb3 6459 enum vfp_dp_reg_pos pos;
bfae80f2
RE
6460{
6461 int reg;
6462 char *start = *str;
6463
6464 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
6465 {
6466 switch (pos)
b99bd4ef 6467 {
bfae80f2
RE
6468 case VFP_REG_Dd:
6469 inst.instruction |= reg << 12;
6470 break;
b99bd4ef 6471
bfae80f2
RE
6472 case VFP_REG_Dn:
6473 inst.instruction |= reg << 16;
6474 break;
6475
6476 case VFP_REG_Dm:
6477 inst.instruction |= reg << 0;
6478 break;
6479
6480 default:
6481 abort ();
6482 }
6483 return reg;
b99bd4ef
NC
6484 }
6485
bfae80f2
RE
6486 /* In the few cases where we might be able to accept something else
6487 this error can be overridden. */
6488 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 6489
bfae80f2
RE
6490 /* Restore the start point. */
6491 *str = start;
6492 return FAIL;
6493}
b99bd4ef
NC
6494
6495static void
bfae80f2
RE
6496do_vfp_sp_monadic (str)
6497 char *str;
b99bd4ef 6498{
b99bd4ef
NC
6499 skip_whitespace (str);
6500
bfae80f2
RE
6501 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
6502 return;
6503
6504 if (skip_past_comma (&str) == FAIL
6505 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
6506 {
6507 if (! inst.error)
6508 inst.error = BAD_ARGS;
6509 return;
6510 }
6511
bfae80f2
RE
6512 end_of_line (str);
6513 return;
6514}
6515
6516static void
6517do_vfp_dp_monadic (str)
6518 char *str;
6519{
6520 skip_whitespace (str);
6521
6522 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
6523 return;
6524
6525 if (skip_past_comma (&str) == FAIL
6526 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 6527 {
bfae80f2
RE
6528 if (! inst.error)
6529 inst.error = BAD_ARGS;
6530 return;
b99bd4ef 6531 }
b99bd4ef 6532
bfae80f2
RE
6533 end_of_line (str);
6534 return;
6535}
b99bd4ef 6536
bfae80f2
RE
6537static void
6538do_vfp_sp_dyadic (str)
6539 char *str;
6540{
6541 skip_whitespace (str);
b99bd4ef 6542
bfae80f2
RE
6543 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
6544 return;
b99bd4ef 6545
bfae80f2
RE
6546 if (skip_past_comma (&str) == FAIL
6547 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
6548 || skip_past_comma (&str) == FAIL
6549 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 6550 {
bfae80f2
RE
6551 if (! inst.error)
6552 inst.error = BAD_ARGS;
6553 return;
6554 }
b99bd4ef 6555
bfae80f2
RE
6556 end_of_line (str);
6557 return;
6558}
b99bd4ef 6559
bfae80f2
RE
6560static void
6561do_vfp_dp_dyadic (str)
6562 char *str;
6563{
6564 skip_whitespace (str);
b99bd4ef 6565
bfae80f2
RE
6566 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
6567 return;
b99bd4ef 6568
bfae80f2
RE
6569 if (skip_past_comma (&str) == FAIL
6570 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
6571 || skip_past_comma (&str) == FAIL
6572 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6573 {
6574 if (! inst.error)
6575 inst.error = BAD_ARGS;
6576 return;
6577 }
b99bd4ef 6578
bfae80f2
RE
6579 end_of_line (str);
6580 return;
6581}
b99bd4ef 6582
bfae80f2
RE
6583static void
6584do_vfp_reg_from_sp (str)
6585 char *str;
6586{
6587 skip_whitespace (str);
6588
6589 if (reg_required_here (&str, 12) == FAIL)
6590 return;
6591
6592 if (skip_past_comma (&str) == FAIL
6593 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
6594 {
6595 if (! inst.error)
6596 inst.error = BAD_ARGS;
6597 return;
6598 }
6599
6600 end_of_line (str);
6601 return;
6602}
6603
6604static void
6605do_vfp_sp_reg2 (str)
6606 char *str;
6607{
6608 skip_whitespace (str);
6609
6610 if (reg_required_here (&str, 12) == FAIL)
6611 return;
6612
6613 if (skip_past_comma (&str) == FAIL
6614 || reg_required_here (&str, 16) == FAIL
6615 || skip_past_comma (&str) == FAIL)
6616 {
6617 if (! inst.error)
6618 inst.error = BAD_ARGS;
6619 return;
6620 }
6621
6622 /* We require exactly two consecutive SP registers. */
6623 if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
6624 {
6625 if (! inst.error)
6626 inst.error = _("only two consecutive VFP SP registers allowed here");
6627 }
6628
6629 end_of_line (str);
6630 return;
6631}
6632
6633static void
6634do_vfp_sp_from_reg (str)
6635 char *str;
6636{
6637 skip_whitespace (str);
6638
6639 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
6640 return;
6641
6642 if (skip_past_comma (&str) == FAIL
6643 || reg_required_here (&str, 12) == FAIL)
6644 {
6645 if (! inst.error)
6646 inst.error = BAD_ARGS;
6647 return;
6648 }
6649
6650 end_of_line (str);
6651 return;
6652}
6653
6654static void
6655do_vfp_reg_from_dp (str)
6656 char *str;
6657{
6658 skip_whitespace (str);
6659
6660 if (reg_required_here (&str, 12) == FAIL)
6661 return;
6662
6663 if (skip_past_comma (&str) == FAIL
6664 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
6665 {
6666 if (! inst.error)
6667 inst.error = BAD_ARGS;
6668 return;
6669 }
6670
6671 end_of_line (str);
6672 return;
6673}
6674
6675static void
6676do_vfp_reg2_from_dp (str)
6677 char *str;
6678{
6679 skip_whitespace (str);
6680
6681 if (reg_required_here (&str, 12) == FAIL)
6682 return;
6683
6684 if (skip_past_comma (&str) == FAIL
6685 || reg_required_here (&str, 16) == FAIL
6686 || skip_past_comma (&str) == FAIL
6687 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6688 {
6689 if (! inst.error)
6690 inst.error = BAD_ARGS;
6691 return;
6692 }
6693
6694 end_of_line (str);
6695 return;
6696}
6697
6698static void
6699do_vfp_dp_from_reg (str)
6700 char *str;
6701{
6702 skip_whitespace (str);
6703
6704 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
6705 return;
6706
6707 if (skip_past_comma (&str) == FAIL
6708 || reg_required_here (&str, 12) == FAIL)
6709 {
6710 if (! inst.error)
6711 inst.error = BAD_ARGS;
6712 return;
6713 }
6714
6715 end_of_line (str);
6716 return;
6717}
6718
6719static void
6720do_vfp_dp_from_reg2 (str)
6721 char *str;
6722{
6723 skip_whitespace (str);
6724
6725 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
6726 return;
6727
6728 if (skip_past_comma (&str) == FAIL
6729 || reg_required_here (&str, 12) == FAIL
6730 || skip_past_comma (&str) == FAIL
6731 || reg_required_here (&str, 16))
6732 {
6733 if (! inst.error)
6734 inst.error = BAD_ARGS;
6735 return;
6736 }
6737
6738 end_of_line (str);
6739 return;
6740}
6741
6742static const struct vfp_reg *
6743vfp_psr_parse (str)
6744 char **str;
6745{
6746 char *start = *str;
6747 char c;
6748 char *p;
6749 const struct vfp_reg *vreg;
6750
6751 p = start;
6752
6753 /* Find the end of the current token. */
6754 do
6755 {
6756 c = *p++;
6757 }
6758 while (ISALPHA (c));
6759
6760 /* Mark it. */
6761 *--p = 0;
6762
cc8a6dd0 6763 for (vreg = vfp_regs + 0;
bfae80f2
RE
6764 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
6765 vreg++)
6766 {
6767 if (strcmp (start, vreg->name) == 0)
6768 {
6769 *p = c;
6770 *str = p;
6771 return vreg;
6772 }
6773 }
6774
6775 *p = c;
6776 return NULL;
6777}
6778
6779static int
6780vfp_psr_required_here (str)
6781 char **str;
6782{
6783 char *start = *str;
6784 const struct vfp_reg *vreg;
6785
6786 vreg = vfp_psr_parse (str);
6787
6788 if (vreg)
6789 {
6790 inst.instruction |= vreg->regno;
6791 return SUCCESS;
6792 }
6793
6794 inst.error = _("VFP system register expected");
6795
6796 *str = start;
6797 return FAIL;
6798}
6799
6800static void
6801do_vfp_reg_from_ctrl (str)
6802 char *str;
6803{
6804 skip_whitespace (str);
6805
6806 if (reg_required_here (&str, 12) == FAIL)
6807 return;
6808
6809 if (skip_past_comma (&str) == FAIL
6810 || vfp_psr_required_here (&str) == FAIL)
6811 {
6812 if (! inst.error)
6813 inst.error = BAD_ARGS;
6814 return;
6815 }
6816
6817 end_of_line (str);
6818 return;
6819}
6820
6821static void
6822do_vfp_ctrl_from_reg (str)
6823 char *str;
6824{
6825 skip_whitespace (str);
6826
6827 if (vfp_psr_required_here (&str) == FAIL)
6828 return;
6829
6830 if (skip_past_comma (&str) == FAIL
6831 || reg_required_here (&str, 12) == FAIL)
6832 {
6833 if (! inst.error)
6834 inst.error = BAD_ARGS;
6835 return;
6836 }
6837
6838 end_of_line (str);
6839 return;
6840}
6841
6842static void
6843do_vfp_sp_ldst (str)
6844 char *str;
6845{
6846 skip_whitespace (str);
6847
6848 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
6849 {
6850 if (!inst.error)
6851 inst.error = BAD_ARGS;
6852 return;
6853 }
6854
6855 if (skip_past_comma (&str) == FAIL
6856 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
6857 {
6858 if (!inst.error)
6859 inst.error = BAD_ARGS;
6860 return;
6861 }
6862
6863 end_of_line (str);
6864 return;
6865}
6866
6867static void
6868do_vfp_dp_ldst (str)
6869 char *str;
6870{
6871 skip_whitespace (str);
6872
6873 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
6874 {
6875 if (!inst.error)
6876 inst.error = BAD_ARGS;
6877 return;
6878 }
6879
6880 if (skip_past_comma (&str) == FAIL
6881 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
6882 {
6883 if (!inst.error)
6884 inst.error = BAD_ARGS;
6885 return;
6886 }
6887
6888 end_of_line (str);
6889 return;
6890}
6891
6892/* Parse and encode a VFP SP register list, storing the initial
6893 register in position POS and returning the range as the result. If
6894 the string is invalid return FAIL (an invalid range). */
6895static long
6896vfp_sp_reg_list (str, pos)
6897 char **str;
6898 enum vfp_sp_reg_pos pos;
6899{
6900 long range = 0;
6901 int base_reg = 0;
6902 int new_base;
6903 long base_bits = 0;
6904 int count = 0;
6905 long tempinst;
6906 unsigned long mask = 0;
6907 int warned = 0;
6908
6909 if (**str != '{')
6910 return FAIL;
6911
6912 (*str)++;
6913 skip_whitespace (*str);
6914
6915 tempinst = inst.instruction;
6916
6917 do
6918 {
6919 inst.instruction = 0;
6920
6921 if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
6922 return FAIL;
6923
6924 if (count == 0 || base_reg > new_base)
6925 {
6926 base_reg = new_base;
6927 base_bits = inst.instruction;
6928 }
6929
6930 if (mask & (1 << new_base))
6931 {
6932 inst.error = _("invalid register list");
6933 return FAIL;
6934 }
6935
6936 if ((mask >> new_base) != 0 && ! warned)
6937 {
6938 as_tsktsk (_("register list not in ascending order"));
6939 warned = 1;
6940 }
6941
6942 mask |= 1 << new_base;
6943 count++;
6944
6945 skip_whitespace (*str);
6946
6947 if (**str == '-') /* We have the start of a range expression */
6948 {
6949 int high_range;
6950
6951 (*str)++;
6952
6953 if ((high_range
6954 = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
6955 == FAIL)
6956 {
6957 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
6958 return FAIL;
6959 }
6960
6961 if (high_range <= new_base)
6962 {
6963 inst.error = _("register range not in ascending order");
6964 return FAIL;
6965 }
6966
6967 for (new_base++; new_base <= high_range; new_base++)
6968 {
6969 if (mask & (1 << new_base))
6970 {
6971 inst.error = _("invalid register list");
6972 return FAIL;
6973 }
6974
6975 mask |= 1 << new_base;
6976 count++;
6977 }
6978 }
6979 }
6980 while (skip_past_comma (str) != FAIL);
6981
6982 if (**str != '}')
6983 {
6984 inst.error = _("invalid register list");
6985 return FAIL;
6986 }
6987
6988 (*str)++;
6989
6990 range = count;
6991
6992 /* Sanity check -- should have raised a parse error above. */
6993 if (count == 0 || count > 32)
c62e1cc3 6994 abort ();
bfae80f2
RE
6995
6996 /* Final test -- the registers must be consecutive. */
6997 while (count--)
6998 {
6999 if ((mask & (1 << base_reg++)) == 0)
7000 {
7001 inst.error = _("non-contiguous register range");
7002 return FAIL;
7003 }
7004 }
7005
7006 inst.instruction = tempinst | base_bits;
7007 return range;
7008}
7009
7010static long
7011vfp_dp_reg_list (str)
7012 char **str;
7013{
7014 long range = 0;
7015 int base_reg = 0;
7016 int new_base;
7017 int count = 0;
7018 long tempinst;
7019 unsigned long mask = 0;
7020 int warned = 0;
7021
7022 if (**str != '{')
7023 return FAIL;
7024
7025 (*str)++;
7026 skip_whitespace (*str);
7027
7028 tempinst = inst.instruction;
7029
7030 do
7031 {
7032 inst.instruction = 0;
7033
7034 if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7035 return FAIL;
7036
7037 if (count == 0 || base_reg > new_base)
7038 {
7039 base_reg = new_base;
7040 range = inst.instruction;
7041 }
7042
7043 if (mask & (1 << new_base))
7044 {
7045 inst.error = _("invalid register list");
7046 return FAIL;
7047 }
7048
7049 if ((mask >> new_base) != 0 && ! warned)
7050 {
7051 as_tsktsk (_("register list not in ascending order"));
7052 warned = 1;
7053 }
7054
7055 mask |= 1 << new_base;
7056 count++;
7057
7058 skip_whitespace (*str);
7059
7060 if (**str == '-') /* We have the start of a range expression */
7061 {
7062 int high_range;
7063
7064 (*str)++;
7065
7066 if ((high_range
7067 = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7068 == FAIL)
7069 {
7070 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7071 return FAIL;
7072 }
7073
7074 if (high_range <= new_base)
7075 {
7076 inst.error = _("register range not in ascending order");
7077 return FAIL;
7078 }
7079
7080 for (new_base++; new_base <= high_range; new_base++)
7081 {
7082 if (mask & (1 << new_base))
7083 {
7084 inst.error = _("invalid register list");
7085 return FAIL;
7086 }
7087
7088 mask |= 1 << new_base;
7089 count++;
7090 }
7091 }
7092 }
7093 while (skip_past_comma (str) != FAIL);
7094
7095 if (**str != '}')
7096 {
7097 inst.error = _("invalid register list");
7098 return FAIL;
7099 }
7100
7101 (*str)++;
7102
7103 range |= 2 * count;
7104
7105 /* Sanity check -- should have raised a parse error above. */
7106 if (count == 0 || count > 16)
c62e1cc3 7107 abort ();
bfae80f2
RE
7108
7109 /* Final test -- the registers must be consecutive. */
7110 while (count--)
7111 {
7112 if ((mask & (1 << base_reg++)) == 0)
7113 {
7114 inst.error = _("non-contiguous register range");
7115 return FAIL;
7116 }
7117 }
7118
7119 inst.instruction = tempinst;
7120 return range;
7121}
7122
7123static void
c62e1cc3 7124vfp_sp_ldstm (str, ldstm_type)
bfae80f2
RE
7125 char *str;
7126 enum vfp_ldstm_type ldstm_type;
7127{
7128 long range;
7129
7130 skip_whitespace (str);
7131
7132 if (reg_required_here (&str, 16) == FAIL)
7133 return;
7134
7135 skip_whitespace (str);
7136
7137 if (*str == '!')
7138 {
7139 inst.instruction |= WRITE_BACK;
7140 str++;
7141 }
7142 else if (ldstm_type != VFP_LDSTMIA)
7143 {
7144 inst.error = _("this addressing mode requires base-register writeback");
7145 return;
7146 }
7147
7148 if (skip_past_comma (&str) == FAIL
7149 || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
7150 {
7151 if (!inst.error)
7152 inst.error = BAD_ARGS;
7153 return;
7154 }
7155
7156 inst.instruction |= range;
7157 end_of_line (str);
7158}
7159
7160static void
c62e1cc3 7161vfp_dp_ldstm (str, ldstm_type)
bfae80f2
RE
7162 char *str;
7163 enum vfp_ldstm_type ldstm_type;
7164{
7165 long range;
7166
7167 skip_whitespace (str);
7168
7169 if (reg_required_here (&str, 16) == FAIL)
7170 return;
7171
7172 skip_whitespace (str);
7173
7174 if (*str == '!')
7175 {
7176 inst.instruction |= WRITE_BACK;
7177 str++;
7178 }
7179 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7180 {
7181 inst.error = _("this addressing mode requires base-register writeback");
7182 return;
7183 }
7184
7185 if (skip_past_comma (&str) == FAIL
7186 || (range = vfp_dp_reg_list (&str)) == FAIL)
7187 {
7188 if (!inst.error)
7189 inst.error = BAD_ARGS;
7190 return;
7191 }
7192
7193 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7194 range += 1;
7195
7196 inst.instruction |= range;
7197 end_of_line (str);
7198}
7199
7200static void
7201do_vfp_sp_ldstmia (str)
7202 char *str;
7203{
7204 vfp_sp_ldstm (str, VFP_LDSTMIA);
7205}
7206
7207static void
7208do_vfp_sp_ldstmdb (str)
7209 char *str;
7210{
7211 vfp_sp_ldstm (str, VFP_LDSTMDB);
7212}
7213
7214static void
7215do_vfp_dp_ldstmia (str)
7216 char *str;
7217{
7218 vfp_dp_ldstm (str, VFP_LDSTMIA);
7219}
7220
7221static void
7222do_vfp_dp_ldstmdb (str)
7223 char *str;
7224{
7225 vfp_dp_ldstm (str, VFP_LDSTMDB);
7226}
7227
7228static void
7229do_vfp_xp_ldstmia (str)
7230 char *str;
7231{
7232 vfp_dp_ldstm (str, VFP_LDSTMIAX);
7233}
7234
7235static void
7236do_vfp_xp_ldstmdb (str)
7237 char *str;
7238{
7239 vfp_dp_ldstm (str, VFP_LDSTMDBX);
7240}
7241
7242static void
7243do_vfp_sp_compare_z (str)
7244 char *str;
7245{
7246 skip_whitespace (str);
7247
7248 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7249 {
7250 if (!inst.error)
7251 inst.error = BAD_ARGS;
7252 return;
7253 }
7254
7255 end_of_line (str);
7256 return;
7257}
7258
7259static void
7260do_vfp_dp_compare_z (str)
7261 char *str;
7262{
7263 skip_whitespace (str);
7264
7265 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7266 {
7267 if (!inst.error)
7268 inst.error = BAD_ARGS;
7269 return;
7270 }
7271
7272 end_of_line (str);
7273 return;
7274}
7275
7276static void
7277do_vfp_dp_sp_cvt (str)
7278 char *str;
7279{
7280 skip_whitespace (str);
7281
7282 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7283 return;
7284
7285 if (skip_past_comma (&str) == FAIL
7286 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7287 {
7288 if (! inst.error)
7289 inst.error = BAD_ARGS;
7290 return;
7291 }
7292
7293 end_of_line (str);
7294 return;
7295}
7296
7297static void
7298do_vfp_sp_dp_cvt (str)
7299 char *str;
7300{
7301 skip_whitespace (str);
7302
7303 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7304 return;
7305
7306 if (skip_past_comma (&str) == FAIL
7307 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7308 {
7309 if (! inst.error)
7310 inst.error = BAD_ARGS;
7311 return;
7312 }
7313
7314 end_of_line (str);
7315 return;
7316}
7317
7318/* Thumb specific routines. */
7319
7320/* Parse and validate that a register is of the right form, this saves
7321 repeated checking of this information in many similar cases.
7322 Unlike the 32-bit case we do not insert the register into the opcode
7323 here, since the position is often unknown until the full instruction
7324 has been parsed. */
7325
7326static int
7327thumb_reg (strp, hi_lo)
7328 char ** strp;
7329 int hi_lo;
7330{
7331 int reg;
7332
7333 if ((reg = reg_required_here (strp, -1)) == FAIL)
7334 return FAIL;
7335
7336 switch (hi_lo)
7337 {
7338 case THUMB_REG_LO:
7339 if (reg > 7)
7340 {
7341 inst.error = _("lo register required");
7342 return FAIL;
7343 }
7344 break;
7345
7346 case THUMB_REG_HI:
7347 if (reg < 8)
7348 {
7349 inst.error = _("hi register required");
7350 return FAIL;
7351 }
7352 break;
7353
7354 default:
7355 break;
7356 }
7357
7358 return reg;
7359}
7360
7361/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
7362 was SUB. */
7363
7364static void
7365thumb_add_sub (str, subtract)
7366 char * str;
7367 int subtract;
7368{
7369 int Rd, Rs, Rn = FAIL;
7370
7371 skip_whitespace (str);
7372
7373 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
7374 || skip_past_comma (&str) == FAIL)
7375 {
7376 if (! inst.error)
7377 inst.error = BAD_ARGS;
7378 return;
7379 }
7380
7381 if (is_immediate_prefix (*str))
7382 {
7383 Rs = Rd;
7384 str++;
7385 if (my_get_expression (&inst.reloc.exp, &str))
7386 return;
7387 }
7388 else
7389 {
7390 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7391 return;
7392
7393 if (skip_past_comma (&str) == FAIL)
7394 {
7395 /* Two operand format, shuffle the registers
7396 and pretend there are 3. */
7397 Rn = Rs;
7398 Rs = Rd;
7399 }
7400 else if (is_immediate_prefix (*str))
7401 {
7402 str++;
7403 if (my_get_expression (&inst.reloc.exp, &str))
7404 return;
7405 }
7406 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7407 return;
7408 }
7409
7410 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7411 for the latter case, EXPR contains the immediate that was found. */
7412 if (Rn != FAIL)
7413 {
7414 /* All register format. */
7415 if (Rd > 7 || Rs > 7 || Rn > 7)
7416 {
7417 if (Rs != Rd)
7418 {
7419 inst.error = _("dest and source1 must be the same register");
7420 return;
7421 }
7422
7423 /* Can't do this for SUB. */
7424 if (subtract)
7425 {
7426 inst.error = _("subtract valid only on lo regs");
7427 return;
7428 }
7429
7430 inst.instruction = (T_OPCODE_ADD_HI
7431 | (Rd > 7 ? THUMB_H1 : 0)
7432 | (Rn > 7 ? THUMB_H2 : 0));
7433 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
7434 }
7435 else
7436 {
7437 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
7438 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
7439 }
7440 }
7441 else
7442 {
7443 /* Immediate expression, now things start to get nasty. */
7444
7445 /* First deal with HI regs, only very restricted cases allowed:
7446 Adjusting SP, and using PC or SP to get an address. */
7447 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
7448 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
7449 {
7450 inst.error = _("invalid Hi register with immediate");
7451 return;
7452 }
7453
7454 if (inst.reloc.exp.X_op != O_constant)
7455 {
7456 /* Value isn't known yet, all we can do is store all the fragments
7457 we know about in the instruction and let the reloc hacking
7458 work it all out. */
7459 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
7460 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
7461 }
7462 else
7463 {
7464 int offset = inst.reloc.exp.X_add_number;
7465
7466 if (subtract)
358b94bd 7467 offset = - offset;
bfae80f2
RE
7468
7469 if (offset < 0)
7470 {
358b94bd 7471 offset = - offset;
bfae80f2
RE
7472 subtract = 1;
7473
7474 /* Quick check, in case offset is MIN_INT. */
7475 if (offset < 0)
7476 {
7477 inst.error = _("immediate value out of range");
7478 return;
7479 }
7480 }
358b94bd
NC
7481 /* Note - you cannot convert a subtract of 0 into an
7482 add of 0 because the carry flag is set differently. */
7483 else if (offset > 0)
bfae80f2
RE
7484 subtract = 0;
7485
7486 if (Rd == REG_SP)
7487 {
7488 if (offset & ~0x1fc)
7489 {
7490 inst.error = _("invalid immediate value for stack adjust");
7491 return;
b99bd4ef
NC
7492 }
7493 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
7494 inst.instruction |= offset >> 2;
7495 }
7496 else if (Rs == REG_PC || Rs == REG_SP)
7497 {
7498 if (subtract
7499 || (offset & ~0x3fc))
7500 {
7501 inst.error = _("invalid immediate for address calculation");
7502 return;
7503 }
7504 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
7505 : T_OPCODE_ADD_SP);
7506 inst.instruction |= (Rd << 8) | (offset >> 2);
7507 }
7508 else if (Rs == Rd)
7509 {
7510 if (offset & ~0xff)
7511 {
7512 inst.error = _("immediate value out of range");
7513 return;
7514 }
7515 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
7516 inst.instruction |= (Rd << 8) | offset;
7517 }
7518 else
7519 {
7520 if (offset & ~0x7)
7521 {
7522 inst.error = _("immediate value out of range");
7523 return;
7524 }
7525 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
7526 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
7527 }
7528 }
7529 }
7530
7531 end_of_line (str);
7532}
7533
7534static void
7535thumb_shift (str, shift)
7536 char * str;
7537 int shift;
7538{
7539 int Rd, Rs, Rn = FAIL;
7540
7541 skip_whitespace (str);
7542
7543 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7544 || skip_past_comma (&str) == FAIL)
7545 {
7546 if (! inst.error)
7547 inst.error = BAD_ARGS;
7548 return;
7549 }
7550
7551 if (is_immediate_prefix (*str))
7552 {
7553 /* Two operand immediate format, set Rs to Rd. */
7554 Rs = Rd;
7555 str ++;
7556 if (my_get_expression (&inst.reloc.exp, &str))
7557 return;
7558 }
7559 else
7560 {
7561 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7562 return;
7563
7564 if (skip_past_comma (&str) == FAIL)
7565 {
7566 /* Two operand format, shuffle the registers
7567 and pretend there are 3. */
7568 Rn = Rs;
7569 Rs = Rd;
7570 }
7571 else if (is_immediate_prefix (*str))
7572 {
7573 str++;
7574 if (my_get_expression (&inst.reloc.exp, &str))
7575 return;
7576 }
7577 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7578 return;
7579 }
7580
7581 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7582 for the latter case, EXPR contains the immediate that was found. */
7583
7584 if (Rn != FAIL)
7585 {
7586 if (Rs != Rd)
7587 {
7588 inst.error = _("source1 and dest must be same register");
7589 return;
7590 }
7591
7592 switch (shift)
7593 {
7594 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
7595 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
7596 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
7597 }
7598
7599 inst.instruction |= Rd | (Rn << 3);
7600 }
7601 else
7602 {
7603 switch (shift)
7604 {
7605 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
7606 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
7607 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
7608 }
7609
7610 if (inst.reloc.exp.X_op != O_constant)
7611 {
7612 /* Value isn't known yet, create a dummy reloc and let reloc
7613 hacking fix it up. */
7614 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
7615 }
7616 else
7617 {
7618 unsigned shift_value = inst.reloc.exp.X_add_number;
7619
7620 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
7621 {
f03698e6 7622 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
7623 return;
7624 }
7625
7626 /* Shifts of zero are handled by converting to LSL. */
7627 if (shift_value == 0)
7628 inst.instruction = T_OPCODE_LSL_I;
7629
7630 /* Shifts of 32 are encoded as a shift of zero. */
7631 if (shift_value == 32)
7632 shift_value = 0;
7633
7634 inst.instruction |= shift_value << 6;
7635 }
7636
7637 inst.instruction |= Rd | (Rs << 3);
7638 }
7639
7640 end_of_line (str);
7641}
7642
7643static void
7644thumb_mov_compare (str, move)
7645 char * str;
7646 int move;
7647{
7648 int Rd, Rs = FAIL;
7649
7650 skip_whitespace (str);
7651
7652 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
7653 || skip_past_comma (&str) == FAIL)
7654 {
7655 if (! inst.error)
7656 inst.error = BAD_ARGS;
7657 return;
7658 }
7659
7660 if (is_immediate_prefix (*str))
7661 {
7662 str++;
7663 if (my_get_expression (&inst.reloc.exp, &str))
7664 return;
7665 }
7666 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7667 return;
7668
7669 if (Rs != FAIL)
7670 {
7671 if (Rs < 8 && Rd < 8)
7672 {
7673 if (move == THUMB_MOVE)
7674 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
7675 since a MOV instruction produces unpredictable results. */
7676 inst.instruction = T_OPCODE_ADD_I3;
7677 else
7678 inst.instruction = T_OPCODE_CMP_LR;
7679 inst.instruction |= Rd | (Rs << 3);
7680 }
7681 else
7682 {
7683 if (move == THUMB_MOVE)
7684 inst.instruction = T_OPCODE_MOV_HR;
7685 else
7686 inst.instruction = T_OPCODE_CMP_HR;
7687
7688 if (Rd > 7)
7689 inst.instruction |= THUMB_H1;
7690
7691 if (Rs > 7)
7692 inst.instruction |= THUMB_H2;
7693
7694 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
7695 }
7696 }
7697 else
7698 {
7699 if (Rd > 7)
7700 {
7701 inst.error = _("only lo regs allowed with immediate");
7702 return;
7703 }
7704
7705 if (move == THUMB_MOVE)
7706 inst.instruction = T_OPCODE_MOV_I8;
7707 else
7708 inst.instruction = T_OPCODE_CMP_I8;
7709
7710 inst.instruction |= Rd << 8;
7711
7712 if (inst.reloc.exp.X_op != O_constant)
7713 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
7714 else
7715 {
7716 unsigned value = inst.reloc.exp.X_add_number;
7717
7718 if (value > 255)
7719 {
7720 inst.error = _("invalid immediate");
7721 return;
7722 }
7723
7724 inst.instruction |= value;
7725 }
7726 }
7727
7728 end_of_line (str);
7729}
7730
7731static void
7732thumb_load_store (str, load_store, size)
7733 char * str;
7734 int load_store;
7735 int size;
7736{
7737 int Rd, Rb, Ro = FAIL;
7738
7739 skip_whitespace (str);
7740
7741 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
7742 || skip_past_comma (&str) == FAIL)
7743 {
7744 if (! inst.error)
7745 inst.error = BAD_ARGS;
7746 return;
7747 }
7748
7749 if (*str == '[')
7750 {
7751 str++;
7752 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
7753 return;
7754
7755 if (skip_past_comma (&str) != FAIL)
7756 {
7757 if (is_immediate_prefix (*str))
7758 {
7759 str++;
7760 if (my_get_expression (&inst.reloc.exp, &str))
7761 return;
7762 }
7763 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
7764 return;
7765 }
7766 else
7767 {
7768 inst.reloc.exp.X_op = O_constant;
7769 inst.reloc.exp.X_add_number = 0;
7770 }
7771
7772 if (*str != ']')
7773 {
7774 inst.error = _("expected ']'");
7775 return;
7776 }
7777 str++;
7778 }
7779 else if (*str == '=')
7780 {
f03698e6
RE
7781 if (load_store != THUMB_LOAD)
7782 {
7783 inst.error = _("invalid pseudo operation");
7784 return;
7785 }
7786
b99bd4ef
NC
7787 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7788 str++;
7789
7790 skip_whitespace (str);
7791
7792 if (my_get_expression (& inst.reloc.exp, & str))
7793 return;
7794
7795 end_of_line (str);
7796
7797 if ( inst.reloc.exp.X_op != O_constant
7798 && inst.reloc.exp.X_op != O_symbol)
7799 {
7800 inst.error = "Constant expression expected";
7801 return;
7802 }
7803
7804 if (inst.reloc.exp.X_op == O_constant
7805 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
7806 {
7807 /* This can be done with a mov instruction. */
7808
7809 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
7810 inst.instruction |= inst.reloc.exp.X_add_number;
7811 return;
7812 }
7813
7814 /* Insert into literal pool. */
7815 if (add_to_lit_pool () == FAIL)
7816 {
7817 if (!inst.error)
7818 inst.error = "literal pool insertion failed";
7819 return;
7820 }
7821
7822 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7823 inst.reloc.pc_rel = 1;
7824 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
7825 /* Adjust ARM pipeline offset to Thumb. */
7826 inst.reloc.exp.X_add_number += 4;
7827
7828 return;
7829 }
7830 else
7831 {
7832 if (my_get_expression (&inst.reloc.exp, &str))
7833 return;
7834
7835 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
7836 inst.reloc.pc_rel = 1;
7837 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
7838 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7839 end_of_line (str);
7840 return;
7841 }
7842
7843 if (Rb == REG_PC || Rb == REG_SP)
7844 {
7845 if (size != THUMB_WORD)
7846 {
7847 inst.error = _("byte or halfword not valid for base register");
7848 return;
7849 }
7850 else if (Rb == REG_PC && load_store != THUMB_LOAD)
7851 {
f03698e6 7852 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
7853 return;
7854 }
7855 else if (Ro != FAIL)
7856 {
f03698e6 7857 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
7858 return;
7859 }
7860
7861 if (Rb == REG_PC)
7862 inst.instruction = T_OPCODE_LDR_PC;
7863 else if (load_store == THUMB_LOAD)
7864 inst.instruction = T_OPCODE_LDR_SP;
7865 else
7866 inst.instruction = T_OPCODE_STR_SP;
7867
7868 inst.instruction |= Rd << 8;
7869 if (inst.reloc.exp.X_op == O_constant)
7870 {
7871 unsigned offset = inst.reloc.exp.X_add_number;
7872
7873 if (offset & ~0x3fc)
7874 {
7875 inst.error = _("invalid offset");
7876 return;
7877 }
7878
7879 inst.instruction |= offset >> 2;
7880 }
7881 else
7882 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7883 }
7884 else if (Rb > 7)
7885 {
7886 inst.error = _("invalid base register in load/store");
7887 return;
7888 }
7889 else if (Ro == FAIL)
7890 {
7891 /* Immediate offset. */
7892 if (size == THUMB_WORD)
7893 inst.instruction = (load_store == THUMB_LOAD
7894 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
7895 else if (size == THUMB_HALFWORD)
7896 inst.instruction = (load_store == THUMB_LOAD
7897 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
7898 else
7899 inst.instruction = (load_store == THUMB_LOAD
7900 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
7901
7902 inst.instruction |= Rd | (Rb << 3);
7903
7904 if (inst.reloc.exp.X_op == O_constant)
7905 {
7906 unsigned offset = inst.reloc.exp.X_add_number;
7907
7908 if (offset & ~(0x1f << size))
7909 {
f03698e6 7910 inst.error = _("invalid offset");
b99bd4ef
NC
7911 return;
7912 }
7913 inst.instruction |= (offset >> size) << 6;
7914 }
7915 else
7916 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
7917 }
7918 else
7919 {
7920 /* Register offset. */
7921 if (size == THUMB_WORD)
7922 inst.instruction = (load_store == THUMB_LOAD
7923 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
7924 else if (size == THUMB_HALFWORD)
7925 inst.instruction = (load_store == THUMB_LOAD
7926 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
7927 else
7928 inst.instruction = (load_store == THUMB_LOAD
7929 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
7930
7931 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
7932 }
7933
7934 end_of_line (str);
7935}
7936
404ff6b5
AH
7937/* A register must be given at this point.
7938
404ff6b5
AH
7939 Shift is the place to put it in inst.instruction.
7940
404ff6b5
AH
7941 Restores input start point on err.
7942 Returns the reg#, or FAIL. */
7943
7944static int
63e63b07 7945mav_reg_required_here (str, shift, regtype)
404ff6b5
AH
7946 char ** str;
7947 int shift;
6c43fab6 7948 enum arm_reg_type regtype;
404ff6b5 7949{
6c43fab6
RE
7950 int reg;
7951 char *start = *str;
404ff6b5 7952
6c43fab6 7953 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 7954 {
404ff6b5
AH
7955 if (shift >= 0)
7956 inst.instruction |= reg << shift;
7957
6c43fab6 7958 return reg;
404ff6b5
AH
7959 }
7960
6c43fab6 7961 /* Restore the start point. */
404ff6b5 7962 *str = start;
cc8a6dd0 7963
404ff6b5
AH
7964 /* In the few cases where we might be able to accept something else
7965 this error can be overridden. */
6c43fab6 7966 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 7967
404ff6b5
AH
7968 return FAIL;
7969}
7970
63e63b07 7971/* Cirrus Maverick Instructions. */
404ff6b5
AH
7972
7973/* Wrapper functions. */
7974
7975static void
63e63b07 7976do_mav_binops_1a (str)
6c43fab6
RE
7977 char * str;
7978{
63e63b07 7979 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
6c43fab6
RE
7980}
7981
7982static void
63e63b07 7983do_mav_binops_1b (str)
6c43fab6
RE
7984 char * str;
7985{
63e63b07 7986 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
6c43fab6
RE
7987}
7988
7989static void
63e63b07 7990do_mav_binops_1c (str)
404ff6b5 7991 char * str;
404ff6b5 7992{
63e63b07 7993 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
404ff6b5
AH
7994}
7995
7996static void
63e63b07 7997do_mav_binops_1d (str)
404ff6b5 7998 char * str;
404ff6b5 7999{
63e63b07 8000 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
8001}
8002
8003static void
63e63b07 8004do_mav_binops_1e (str)
404ff6b5 8005 char * str;
404ff6b5 8006{
63e63b07 8007 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
8008}
8009
8010static void
63e63b07 8011do_mav_binops_1f (str)
404ff6b5 8012 char * str;
404ff6b5 8013{
63e63b07 8014 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
404ff6b5
AH
8015}
8016
8017static void
63e63b07 8018do_mav_binops_1g (str)
404ff6b5 8019 char * str;
404ff6b5 8020{
63e63b07 8021 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
404ff6b5
AH
8022}
8023
8024static void
63e63b07 8025do_mav_binops_1h (str)
404ff6b5 8026 char * str;
404ff6b5 8027{
63e63b07 8028 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
404ff6b5
AH
8029}
8030
6c43fab6 8031static void
63e63b07 8032do_mav_binops_1i (str)
6c43fab6
RE
8033 char * str;
8034{
63e63b07 8035 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
6c43fab6
RE
8036}
8037
8038static void
63e63b07 8039do_mav_binops_1j (str)
6c43fab6
RE
8040 char * str;
8041{
63e63b07 8042 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
6c43fab6
RE
8043}
8044
8045static void
63e63b07 8046do_mav_binops_1k (str)
6c43fab6
RE
8047 char * str;
8048{
63e63b07 8049 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
6c43fab6
RE
8050}
8051
8052static void
63e63b07 8053do_mav_binops_1l (str)
6c43fab6
RE
8054 char * str;
8055{
63e63b07 8056 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
6c43fab6
RE
8057}
8058
8059static void
63e63b07 8060do_mav_binops_1m (str)
6c43fab6
RE
8061 char * str;
8062{
63e63b07 8063 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
6c43fab6
RE
8064}
8065
8066static void
63e63b07 8067do_mav_binops_1n (str)
6c43fab6
RE
8068 char * str;
8069{
63e63b07 8070 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8071}
8072
8073static void
63e63b07 8074do_mav_binops_1o (str)
6c43fab6
RE
8075 char * str;
8076{
63e63b07 8077 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8078}
8079
8080static void
63e63b07 8081do_mav_binops_2a (str)
6c43fab6
RE
8082 char * str;
8083{
63e63b07 8084 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
6c43fab6
RE
8085}
8086
8087static void
63e63b07 8088do_mav_binops_2b (str)
6c43fab6
RE
8089 char * str;
8090{
63e63b07 8091 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
6c43fab6
RE
8092}
8093
8094static void
63e63b07 8095do_mav_binops_2c (str)
6c43fab6
RE
8096 char * str;
8097{
63e63b07 8098 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
8099}
8100
8101static void
63e63b07 8102do_mav_binops_3a (str)
6c43fab6
RE
8103 char * str;
8104{
63e63b07 8105 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
8106}
8107
8108static void
63e63b07 8109do_mav_binops_3b (str)
6c43fab6
RE
8110 char * str;
8111{
63e63b07 8112 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
8113}
8114
8115static void
63e63b07 8116do_mav_binops_3c (str)
6c43fab6
RE
8117 char * str;
8118{
63e63b07 8119 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
6c43fab6
RE
8120}
8121
8122static void
63e63b07 8123do_mav_binops_3d (str)
6c43fab6
RE
8124 char * str;
8125{
63e63b07 8126 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
6c43fab6
RE
8127}
8128
8129static void
63e63b07 8130do_mav_triple_4a (str)
6c43fab6
RE
8131 char * str;
8132{
63e63b07 8133 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
6c43fab6
RE
8134}
8135
8136static void
63e63b07 8137do_mav_triple_4b (str)
6c43fab6
RE
8138 char * str;
8139{
63e63b07 8140 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
6c43fab6
RE
8141}
8142
8143static void
63e63b07 8144do_mav_triple_5a (str)
6c43fab6
RE
8145 char * str;
8146{
63e63b07 8147 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
8148}
8149
8150static void
63e63b07 8151do_mav_triple_5b (str)
6c43fab6
RE
8152 char * str;
8153{
63e63b07 8154 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
8155}
8156
8157static void
63e63b07 8158do_mav_triple_5c (str)
6c43fab6
RE
8159 char * str;
8160{
63e63b07 8161 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8162}
8163
8164static void
63e63b07 8165do_mav_triple_5d (str)
6c43fab6
RE
8166 char * str;
8167{
63e63b07 8168 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8169}
8170
8171static void
63e63b07 8172do_mav_triple_5e (str)
6c43fab6
RE
8173 char * str;
8174{
63e63b07 8175 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
8176}
8177
8178static void
63e63b07 8179do_mav_triple_5f (str)
6c43fab6
RE
8180 char * str;
8181{
63e63b07 8182 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
8183}
8184
8185static void
63e63b07 8186do_mav_triple_5g (str)
6c43fab6
RE
8187 char * str;
8188{
63e63b07 8189 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8190}
8191
8192static void
63e63b07 8193do_mav_triple_5h (str)
6c43fab6
RE
8194 char * str;
8195{
63e63b07 8196 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8197}
8198
8199static void
63e63b07 8200do_mav_quad_6a (str)
6c43fab6
RE
8201 char * str;
8202{
63e63b07 8203 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
6c43fab6
RE
8204 REG_TYPE_MVFX);
8205}
8206
8207static void
63e63b07 8208do_mav_quad_6b (str)
6c43fab6
RE
8209 char * str;
8210{
63e63b07 8211 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
6c43fab6
RE
8212 REG_TYPE_MVFX);
8213}
8214
cc8a6dd0 8215/* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
404ff6b5 8216static void
63e63b07 8217do_mav_dspsc_1 (str)
404ff6b5 8218 char * str;
404ff6b5 8219{
6c43fab6
RE
8220 skip_whitespace (str);
8221
8222 /* cfmvsc32. */
63e63b07 8223 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
6c43fab6 8224 || skip_past_comma (&str) == FAIL
63e63b07 8225 || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
6c43fab6
RE
8226 {
8227 if (!inst.error)
8228 inst.error = BAD_ARGS;
8229
8230 return;
8231 }
8232
8233 end_of_line (str);
404ff6b5
AH
8234}
8235
6c43fab6 8236/* cfmv32sc<cond> MVFX[15:0],DSPSC. */
404ff6b5 8237static void
63e63b07 8238do_mav_dspsc_2 (str)
404ff6b5 8239 char * str;
404ff6b5 8240{
6c43fab6
RE
8241 skip_whitespace (str);
8242
8243 /* cfmv32sc. */
63e63b07 8244 if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
6c43fab6 8245 || skip_past_comma (&str) == FAIL
63e63b07 8246 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
6c43fab6
RE
8247 {
8248 if (!inst.error)
8249 inst.error = BAD_ARGS;
8250
8251 return;
8252 }
8253
8254 end_of_line (str);
404ff6b5
AH
8255}
8256
8257static void
63e63b07 8258do_mav_shift_1 (str)
404ff6b5 8259 char * str;
404ff6b5 8260{
63e63b07 8261 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
404ff6b5
AH
8262}
8263
8264static void
63e63b07 8265do_mav_shift_2 (str)
404ff6b5 8266 char * str;
404ff6b5 8267{
63e63b07 8268 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
404ff6b5
AH
8269}
8270
8271static void
63e63b07 8272do_mav_ldst_1 (str)
404ff6b5 8273 char * str;
404ff6b5 8274{
63e63b07 8275 do_mav_ldst (str, REG_TYPE_MVF);
404ff6b5
AH
8276}
8277
8278static void
63e63b07 8279do_mav_ldst_2 (str)
404ff6b5 8280 char * str;
404ff6b5 8281{
63e63b07 8282 do_mav_ldst (str, REG_TYPE_MVD);
404ff6b5
AH
8283}
8284
8285static void
63e63b07 8286do_mav_ldst_3 (str)
404ff6b5 8287 char * str;
404ff6b5 8288{
63e63b07 8289 do_mav_ldst (str, REG_TYPE_MVFX);
404ff6b5
AH
8290}
8291
8292static void
63e63b07 8293do_mav_ldst_4 (str)
404ff6b5 8294 char * str;
404ff6b5 8295{
63e63b07 8296 do_mav_ldst (str, REG_TYPE_MVDX);
404ff6b5
AH
8297}
8298
8299/* Isnsn like "foo X,Y". */
8300
8301static void
63e63b07 8302do_mav_binops (str, mode, reg0, reg1)
404ff6b5 8303 char * str;
404ff6b5 8304 int mode;
6c43fab6
RE
8305 enum arm_reg_type reg0;
8306 enum arm_reg_type reg1;
404ff6b5 8307{
6c43fab6 8308 int shift0, shift1;
404ff6b5 8309
6c43fab6
RE
8310 shift0 = mode & 0xff;
8311 shift1 = (mode >> 8) & 0xff;
404ff6b5
AH
8312
8313 skip_whitespace (str);
8314
63e63b07 8315 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 8316 || skip_past_comma (&str) == FAIL
63e63b07 8317 || mav_reg_required_here (&str, shift1, reg1) == 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 X,Y,Z". */
8327
8328static void
63e63b07 8329do_mav_triple (str, mode, reg0, reg1, reg2)
404ff6b5 8330 char * str;
404ff6b5 8331 int mode;
6c43fab6
RE
8332 enum arm_reg_type reg0;
8333 enum arm_reg_type reg1;
8334 enum arm_reg_type reg2;
404ff6b5 8335{
6c43fab6 8336 int shift0, shift1, shift2;
404ff6b5 8337
6c43fab6
RE
8338 shift0 = mode & 0xff;
8339 shift1 = (mode >> 8) & 0xff;
8340 shift2 = (mode >> 16) & 0xff;
404ff6b5
AH
8341
8342 skip_whitespace (str);
8343
63e63b07 8344 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 8345 || skip_past_comma (&str) == FAIL
63e63b07 8346 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 8347 || skip_past_comma (&str) == FAIL
63e63b07 8348 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
404ff6b5
AH
8349 {
8350 if (!inst.error)
8351 inst.error = BAD_ARGS;
8352 }
8353 else
8354 end_of_line (str);
404ff6b5
AH
8355}
8356
8357/* Isnsn like "foo W,X,Y,Z".
8358 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8359
8360static void
63e63b07 8361do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
404ff6b5 8362 char * str;
404ff6b5 8363 int mode;
6c43fab6
RE
8364 enum arm_reg_type reg0;
8365 enum arm_reg_type reg1;
8366 enum arm_reg_type reg2;
8367 enum arm_reg_type reg3;
404ff6b5 8368{
6c43fab6 8369 int shift0, shift1, shift2, shift3;
404ff6b5 8370
6c43fab6
RE
8371 shift0= mode & 0xff;
8372 shift1 = (mode >> 8) & 0xff;
8373 shift2 = (mode >> 16) & 0xff;
8374 shift3 = (mode >> 24) & 0xff;
404ff6b5
AH
8375
8376 skip_whitespace (str);
8377
63e63b07 8378 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
404ff6b5 8379 || skip_past_comma (&str) == FAIL
63e63b07 8380 || mav_reg_required_here (&str, shift1, reg1) == FAIL
404ff6b5 8381 || skip_past_comma (&str) == FAIL
63e63b07 8382 || mav_reg_required_here (&str, shift2, reg2) == FAIL
404ff6b5 8383 || skip_past_comma (&str) == FAIL
63e63b07 8384 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
404ff6b5
AH
8385 {
8386 if (!inst.error)
8387 inst.error = BAD_ARGS;
8388 }
8389 else
8390 end_of_line (str);
404ff6b5
AH
8391}
8392
63e63b07 8393/* Maverick shift immediate instructions.
404ff6b5
AH
8394 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8395 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8396
8397static void
63e63b07 8398do_mav_shift (str, reg0, reg1)
404ff6b5 8399 char * str;
6c43fab6
RE
8400 enum arm_reg_type reg0;
8401 enum arm_reg_type reg1;
404ff6b5
AH
8402{
8403 int error;
8404 int imm, neg = 0;
8405
8406 skip_whitespace (str);
8407
8408 error = 0;
8409
63e63b07 8410 if (mav_reg_required_here (&str, 12, reg0) == FAIL
404ff6b5 8411 || skip_past_comma (&str) == FAIL
63e63b07 8412 || mav_reg_required_here (&str, 16, reg1) == FAIL
404ff6b5
AH
8413 || skip_past_comma (&str) == FAIL)
8414 {
8415 if (!inst.error)
8416 inst.error = BAD_ARGS;
8417 return;
8418 }
8419
8420 /* Calculate the immediate operand.
8421 The operand is a 7bit signed number. */
8422 skip_whitespace (str);
8423
8424 if (*str == '#')
8425 ++str;
8426
8420dfca 8427 if (!ISDIGIT (*str) && *str != '-')
404ff6b5
AH
8428 {
8429 inst.error = _("expecting immediate, 7bit operand");
8430 return;
8431 }
8432
8433 if (*str == '-')
8434 {
8435 neg = 1;
8436 ++str;
8437 }
8438
8420dfca 8439 for (imm = 0; *str && ISDIGIT (*str); ++str)
404ff6b5
AH
8440 imm = imm * 10 + *str - '0';
8441
8442 if (imm > 64)
8443 {
8444 inst.error = _("immediate out of range");
8445 return;
8446 }
8447
8448 /* Make negative imm's into 7bit signed numbers. */
8449 if (neg)
8450 {
8451 imm = -imm;
8452 imm &= 0x0000007f;
8453 }
8454
8455 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
8456 Bits 5-7 of the insn should have bits 4-6 of the immediate.
8457 Bit 4 should be 0. */
8458 imm = (imm & 0xf) | ((imm & 0x70) << 1);
8459
8460 inst.instruction |= imm;
404ff6b5 8461 end_of_line (str);
404ff6b5
AH
8462}
8463
8464static int
63e63b07 8465mav_parse_offset (str, negative)
404ff6b5
AH
8466 char ** str;
8467 int *negative;
8468{
8469 char * p = *str;
8470 int offset;
8471
8472 *negative = 0;
8473
8474 skip_whitespace (p);
8475
8476 if (*p == '#')
8477 ++p;
8478
8479 if (*p == '-')
8480 {
8481 *negative = 1;
8482 ++p;
8483 }
8484
8420dfca 8485 if (!ISDIGIT (*p))
404ff6b5
AH
8486 {
8487 inst.error = _("offset expected");
8488 return 0;
8489 }
8490
8420dfca 8491 for (offset = 0; *p && ISDIGIT (*p); ++p)
404ff6b5
AH
8492 offset = offset * 10 + *p - '0';
8493
8494 if (offset > 0xff)
8495 {
8496 inst.error = _("offset out of range");
8497 return 0;
8498 }
8499
8500 *str = p;
8501
8502 return *negative ? -offset : offset;
8503}
8504
63e63b07 8505/* Maverick load/store instructions.
404ff6b5
AH
8506 <insn><cond> CRd,[Rn,<offset>]{!}.
8507 <insn><cond> CRd,[Rn],<offset>. */
8508
8509static void
63e63b07 8510do_mav_ldst (str, reg0)
404ff6b5 8511 char * str;
6c43fab6 8512 enum arm_reg_type reg0;
404ff6b5
AH
8513{
8514 int offset, negative;
404ff6b5
AH
8515
8516 skip_whitespace (str);
8517
63e63b07 8518 if (mav_reg_required_here (&str, 12, reg0) == FAIL
6c43fab6 8519 || skip_past_comma (&str) == FAIL
404ff6b5 8520 || *str++ != '['
6c43fab6 8521 || reg_required_here (&str, 16) == FAIL)
404ff6b5
AH
8522 goto fail_ldst;
8523
6c43fab6 8524 if (skip_past_comma (&str) == SUCCESS)
404ff6b5
AH
8525 {
8526 /* You are here: "<offset>]{!}". */
8527 inst.instruction |= PRE_INDEX;
8528
63e63b07 8529 offset = mav_parse_offset (&str, &negative);
404ff6b5
AH
8530
8531 if (inst.error)
8532 return;
8533
8534 if (*str++ != ']')
8535 {
8536 inst.error = _("missing ]");
8537 return;
8538 }
8539
8540 if (*str == '!')
8541 {
8542 inst.instruction |= WRITE_BACK;
8543 ++str;
8544 }
8545 }
8546 else
8547 {
8548 /* You are here: "], <offset>". */
8549 if (*str++ != ']')
8550 {
8551 inst.error = _("missing ]");
8552 return;
8553 }
8554
8555 if (skip_past_comma (&str) == FAIL
63e63b07 8556 || (offset = mav_parse_offset (&str, &negative), inst.error))
404ff6b5
AH
8557 goto fail_ldst;
8558
8559 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
8560 }
8561
8562 if (negative)
8563 offset = -offset;
8564 else
8565 inst.instruction |= CP_T_UD; /* Postive, so set bit U. */
8566
8567 inst.instruction |= offset >> 2;
404ff6b5
AH
8568 end_of_line (str);
8569 return;
8570
8571fail_ldst:
8572 if (!inst.error)
8573 inst.error = BAD_ARGS;
8574 return;
8575}
8576
b99bd4ef
NC
8577static void
8578do_t_nop (str)
8579 char * str;
8580{
8581 /* Do nothing. */
8582 end_of_line (str);
8583 return;
8584}
8585
8586/* Handle the Format 4 instructions that do not have equivalents in other
8587 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
8588 BIC and MVN. */
8589
8590static void
8591do_t_arit (str)
8592 char * str;
8593{
8594 int Rd, Rs, Rn;
8595
8596 skip_whitespace (str);
8597
8598 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8599 || skip_past_comma (&str) == FAIL
8600 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8601 {
8602 inst.error = BAD_ARGS;
8603 return;
8604 }
8605
8606 if (skip_past_comma (&str) != FAIL)
8607 {
8608 /* Three operand format not allowed for TST, CMN, NEG and MVN.
8609 (It isn't allowed for CMP either, but that isn't handled by this
8610 function.) */
8611 if (inst.instruction == T_OPCODE_TST
8612 || inst.instruction == T_OPCODE_CMN
8613 || inst.instruction == T_OPCODE_NEG
8614 || inst.instruction == T_OPCODE_MVN)
8615 {
8616 inst.error = BAD_ARGS;
8617 return;
8618 }
8619
8620 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8621 return;
8622
8623 if (Rs != Rd)
8624 {
8625 inst.error = _("dest and source1 must be the same register");
8626 return;
8627 }
8628 Rs = Rn;
8629 }
8630
8631 if (inst.instruction == T_OPCODE_MUL
8632 && Rs == Rd)
8633 as_tsktsk (_("Rs and Rd must be different in MUL"));
8634
8635 inst.instruction |= Rd | (Rs << 3);
8636 end_of_line (str);
8637}
8638
8639static void
8640do_t_add (str)
8641 char * str;
8642{
8643 thumb_add_sub (str, 0);
8644}
8645
8646static void
8647do_t_asr (str)
8648 char * str;
8649{
8650 thumb_shift (str, THUMB_ASR);
8651}
8652
8653static void
8654do_t_branch9 (str)
8655 char * str;
8656{
8657 if (my_get_expression (&inst.reloc.exp, &str))
8658 return;
8659 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
8660 inst.reloc.pc_rel = 1;
8661 end_of_line (str);
8662}
8663
8664static void
8665do_t_branch12 (str)
8666 char * str;
8667{
8668 if (my_get_expression (&inst.reloc.exp, &str))
8669 return;
8670 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
8671 inst.reloc.pc_rel = 1;
8672 end_of_line (str);
8673}
8674
8675/* Find the real, Thumb encoded start of a Thumb function. */
8676
8677static symbolS *
8678find_real_start (symbolP)
8679 symbolS * symbolP;
8680{
8681 char * real_start;
8682 const char * name = S_GET_NAME (symbolP);
8683 symbolS * new_target;
8684
8685 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
8686#define STUB_NAME ".real_start_of"
8687
8688 if (name == NULL)
8689 abort ();
8690
8691 /* Names that start with '.' are local labels, not function entry points.
8692 The compiler may generate BL instructions to these labels because it
8693 needs to perform a branch to a far away location. */
8694 if (name[0] == '.')
8695 return symbolP;
8696
8697 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
8698 sprintf (real_start, "%s%s", STUB_NAME, name);
8699
8700 new_target = symbol_find (real_start);
8701
8702 if (new_target == NULL)
8703 {
8704 as_warn ("Failed to find real start of function: %s\n", name);
8705 new_target = symbolP;
8706 }
8707
8708 free (real_start);
8709
8710 return new_target;
8711}
8712
8713static void
8714do_t_branch23 (str)
8715 char * str;
8716{
8717 if (my_get_expression (& inst.reloc.exp, & str))
8718 return;
8719
8720 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
8721 inst.reloc.pc_rel = 1;
8722 end_of_line (str);
8723
8724 /* If the destination of the branch is a defined symbol which does not have
8725 the THUMB_FUNC attribute, then we must be calling a function which has
8726 the (interfacearm) attribute. We look for the Thumb entry point to that
8727 function and change the branch to refer to that function instead. */
8728 if ( inst.reloc.exp.X_op == O_symbol
8729 && inst.reloc.exp.X_add_symbol != NULL
8730 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
8731 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
8732 inst.reloc.exp.X_add_symbol =
8733 find_real_start (inst.reloc.exp.X_add_symbol);
8734}
8735
8736static void
8737do_t_bx (str)
8738 char * str;
8739{
8740 int reg;
8741
8742 skip_whitespace (str);
8743
8744 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8745 return;
8746
8747 /* This sets THUMB_H2 from the top bit of reg. */
8748 inst.instruction |= reg << 3;
8749
8750 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
8751 should cause the alignment to be checked once it is known. This is
8752 because BX PC only works if the instruction is word aligned. */
8753
8754 end_of_line (str);
8755}
8756
8757static void
8758do_t_compare (str)
8759 char * str;
8760{
8761 thumb_mov_compare (str, THUMB_COMPARE);
8762}
8763
8764static void
8765do_t_ldmstm (str)
8766 char * str;
8767{
8768 int Rb;
8769 long range;
8770
8771 skip_whitespace (str);
8772
8773 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8774 return;
8775
8776 if (*str != '!')
f03698e6 8777 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
b99bd4ef
NC
8778 else
8779 str++;
8780
8781 if (skip_past_comma (&str) == FAIL
8782 || (range = reg_list (&str)) == FAIL)
8783 {
8784 if (! inst.error)
8785 inst.error = BAD_ARGS;
8786 return;
8787 }
8788
8789 if (inst.reloc.type != BFD_RELOC_NONE)
8790 {
8791 /* This really doesn't seem worth it. */
8792 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 8793 inst.error = _("expression too complex");
b99bd4ef
NC
8794 return;
8795 }
8796
8797 if (range & ~0xff)
8798 {
8799 inst.error = _("only lo-regs valid in load/store multiple");
8800 return;
8801 }
8802
8803 inst.instruction |= (Rb << 8) | range;
8804 end_of_line (str);
8805}
8806
8807static void
8808do_t_ldr (str)
8809 char * str;
8810{
8811 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
8812}
8813
8814static void
8815do_t_ldrb (str)
8816 char * str;
8817{
8818 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
8819}
8820
8821static void
8822do_t_ldrh (str)
8823 char * str;
8824{
8825 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
8826}
8827
8828static void
8829do_t_lds (str)
8830 char * str;
8831{
8832 int Rd, Rb, Ro;
8833
8834 skip_whitespace (str);
8835
8836 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8837 || skip_past_comma (&str) == FAIL
8838 || *str++ != '['
8839 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8840 || skip_past_comma (&str) == FAIL
8841 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8842 || *str++ != ']')
8843 {
8844 if (! inst.error)
f03698e6 8845 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
b99bd4ef
NC
8846 return;
8847 }
8848
8849 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8850 end_of_line (str);
8851}
8852
8853static void
8854do_t_lsl (str)
8855 char * str;
8856{
8857 thumb_shift (str, THUMB_LSL);
8858}
8859
8860static void
8861do_t_lsr (str)
8862 char * str;
8863{
8864 thumb_shift (str, THUMB_LSR);
8865}
8866
8867static void
8868do_t_mov (str)
8869 char * str;
8870{
8871 thumb_mov_compare (str, THUMB_MOVE);
8872}
8873
8874static void
8875do_t_push_pop (str)
8876 char * str;
8877{
8878 long range;
8879
8880 skip_whitespace (str);
8881
8882 if ((range = reg_list (&str)) == FAIL)
8883 {
8884 if (! inst.error)
8885 inst.error = BAD_ARGS;
8886 return;
8887 }
8888
8889 if (inst.reloc.type != BFD_RELOC_NONE)
8890 {
8891 /* This really doesn't seem worth it. */
8892 inst.reloc.type = BFD_RELOC_NONE;
f03698e6 8893 inst.error = _("expression too complex");
b99bd4ef
NC
8894 return;
8895 }
8896
8897 if (range & ~0xff)
8898 {
8899 if ((inst.instruction == T_OPCODE_PUSH
8900 && (range & ~0xff) == 1 << REG_LR)
8901 || (inst.instruction == T_OPCODE_POP
8902 && (range & ~0xff) == 1 << REG_PC))
8903 {
8904 inst.instruction |= THUMB_PP_PC_LR;
8905 range &= 0xff;
8906 }
8907 else
8908 {
8909 inst.error = _("invalid register list to push/pop instruction");
8910 return;
8911 }
8912 }
8913
8914 inst.instruction |= range;
8915 end_of_line (str);
8916}
8917
8918static void
8919do_t_str (str)
8920 char * str;
8921{
8922 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
8923}
8924
8925static void
8926do_t_strb (str)
8927 char * str;
8928{
8929 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
8930}
8931
8932static void
8933do_t_strh (str)
8934 char * str;
8935{
8936 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
8937}
8938
8939static void
8940do_t_sub (str)
8941 char * str;
8942{
8943 thumb_add_sub (str, 1);
8944}
8945
8946static void
8947do_t_swi (str)
8948 char * str;
8949{
8950 skip_whitespace (str);
8951
8952 if (my_get_expression (&inst.reloc.exp, &str))
8953 return;
8954
8955 inst.reloc.type = BFD_RELOC_ARM_SWI;
8956 end_of_line (str);
8957 return;
8958}
8959
8960static void
8961do_t_adr (str)
8962 char * str;
8963{
8964 int reg;
8965
8966 /* This is a pseudo-op of the form "adr rd, label" to be converted
8967 into a relative address of the form "add rd, pc, #label-.-4". */
8968 skip_whitespace (str);
8969
8970 /* Store Rd in temporary location inside instruction. */
8971 if ((reg = reg_required_here (&str, 4)) == FAIL
8972 || (reg > 7) /* For Thumb reg must be r0..r7. */
8973 || skip_past_comma (&str) == FAIL
8974 || my_get_expression (&inst.reloc.exp, &str))
8975 {
8976 if (!inst.error)
8977 inst.error = BAD_ARGS;
8978 return;
8979 }
8980
8981 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8982 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
8983 inst.reloc.pc_rel = 1;
8984 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
8985
8986 end_of_line (str);
8987}
8988
8989static void
6c43fab6
RE
8990insert_reg (r, htab)
8991 const struct reg_entry *r;
8992 struct hash_control *htab;
b99bd4ef 8993{
6c43fab6 8994 int len = strlen (r->name) + 2;
b99bd4ef
NC
8995 char * buf = (char *) xmalloc (len);
8996 char * buf2 = (char *) xmalloc (len);
8997 int i = 0;
8998
8999#ifdef REGISTER_PREFIX
9000 buf[i++] = REGISTER_PREFIX;
9001#endif
9002
6c43fab6 9003 strcpy (buf + i, r->name);
b99bd4ef
NC
9004
9005 for (i = 0; buf[i]; i++)
3882b010 9006 buf2[i] = TOUPPER (buf[i]);
b99bd4ef
NC
9007
9008 buf2[i] = '\0';
9009
6c43fab6
RE
9010 hash_insert (htab, buf, (PTR) r);
9011 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9012}
9013
9014static void
6c43fab6
RE
9015build_reg_hsh (map)
9016 struct reg_map *map;
9017{
9018 const struct reg_entry *r;
9019
9020 if ((map->htab = hash_new ()) == NULL)
f03698e6 9021 as_fatal (_("virtual memory exhausted"));
6c43fab6
RE
9022
9023 for (r = map->names; r->name != NULL; r++)
9024 insert_reg (r, map->htab);
9025}
9026
9027static void
9028insert_reg_alias (str, regnum, htab)
b99bd4ef
NC
9029 char *str;
9030 int regnum;
6c43fab6 9031 struct hash_control *htab;
b99bd4ef
NC
9032{
9033 struct reg_entry *new =
9034 (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
9035 char *name = xmalloc (strlen (str) + 1);
9036 strcpy (name, str);
9037
9038 new->name = name;
9039 new->number = regnum;
9040
6c43fab6 9041 hash_insert (htab, name, (PTR) new);
b99bd4ef
NC
9042}
9043
6c43fab6
RE
9044/* Look for the .req directive. This is of the form:
9045
9046 newname .req existing_name
9047
9048 If we find one, or if it looks sufficiently like one that we want to
9049 handle any error here, return non-zero. Otherwise return zero. */
9050static int
9051create_register_alias (newname, p)
9052 char *newname;
9053 char *p;
9054{
9055 char *q;
9056 char c;
9057
9058 q = p;
9059 skip_whitespace (q);
9060
9061 c = *p;
9062 *p = '\0';
9063
9064 if (*q && !strncmp (q, ".req ", 5))
9065 {
9066 char *copy_of_str;
9067 char *r;
9068
9069#ifdef IGNORE_OPCODE_CASE
9070 newname = original_case_string;
9071#endif
9072 copy_of_str = newname;
9073
9074 q += 4;
9075 skip_whitespace (q);
9076
9077 for (r = q; *r != '\0'; r++)
9078 if (*r == ' ')
9079 break;
9080
9081 if (r != q)
9082 {
9083 enum arm_reg_type new_type, old_type;
9084 int old_regno;
9085 char d = *r;
9086
9087 *r = '\0';
9088 old_type = arm_reg_parse_any (q);
9089 *r = d;
9090
9091 new_type = arm_reg_parse_any (newname);
9092
9093 if (new_type == REG_TYPE_MAX)
9094 {
9095 if (old_type != REG_TYPE_MAX)
9096 {
9097 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9098 insert_reg_alias (newname, old_regno,
9099 all_reg_maps[old_type].htab);
9100 }
9101 else
9102 as_warn (_("register '%s' does not exist\n"), q);
9103 }
9104 else if (old_type == REG_TYPE_MAX)
9105 {
9106 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9107 copy_of_str, q);
9108 }
9109 else
9110 {
9111 /* Do not warn about redefinitions to the same alias. */
9112 if (new_type != old_type
9113 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9114 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9115 as_warn (_("ignoring redefinition of register alias '%s'"),
9116 copy_of_str);
9117
9118 }
9119 }
9120 else
9121 as_warn (_("ignoring incomplete .req pseuso op"));
9122
9123 *p = c;
9124 return 1;
9125 }
9126 *p = c;
9127 return 0;
9128}
cc8a6dd0 9129
b99bd4ef
NC
9130static void
9131set_constant_flonums ()
9132{
9133 int i;
9134
9135 for (i = 0; i < NUM_FLOAT_VALS; i++)
9136 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9137 abort ();
9138}
9139
90e4755a
RE
9140/* Iterate over the base tables to create the instruction patterns. */
9141static void
9142build_arm_ops_hsh ()
9143{
9144 unsigned int i;
9145 unsigned int j;
9146 static struct obstack insn_obstack;
9147
9148 obstack_begin (&insn_obstack, 4000);
9149
9150 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
9151 {
6c43fab6 9152 const struct asm_opcode *insn = insns + i;
90e4755a
RE
9153
9154 if (insn->cond_offset != 0)
9155 {
9156 /* Insn supports conditional execution. Build the varaints
9157 and insert them in the hash table. */
9158 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
9159 {
9160 unsigned len = strlen (insn->template);
9161 struct asm_opcode *new;
9162 char *template;
9163
9164 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
9165 /* All condition codes are two characters. */
9166 template = obstack_alloc (&insn_obstack, len + 3);
9167
9168 strncpy (template, insn->template, insn->cond_offset);
9169 strcpy (template + insn->cond_offset, conds[j].template);
9170 if (len > insn->cond_offset)
9171 strcpy (template + insn->cond_offset + 2,
9172 insn->template + insn->cond_offset);
9173 new->template = template;
9174 new->cond_offset = 0;
9175 new->variant = insn->variant;
9176 new->parms = insn->parms;
9177 new->value = (insn->value & ~COND_MASK) | conds[j].value;
9178
9179 hash_insert (arm_ops_hsh, new->template, (PTR) new);
9180 }
9181 }
9182 /* Finally, insert the unconditional insn in the table directly;
9183 no need to build a copy. */
9184 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
9185 }
9186}
9187
b99bd4ef
NC
9188void
9189md_begin ()
9190{
9191 unsigned mach;
9192 unsigned int i;
9193
9194 if ( (arm_ops_hsh = hash_new ()) == NULL
9195 || (arm_tops_hsh = hash_new ()) == NULL
9196 || (arm_cond_hsh = hash_new ()) == NULL
9197 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 9198 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 9199 as_fatal (_("virtual memory exhausted"));
b99bd4ef 9200
90e4755a 9201 build_arm_ops_hsh ();
b99bd4ef
NC
9202 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
9203 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
9204 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
9205 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
9206 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
9207 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
9208 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
9209 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
9210
6c43fab6
RE
9211 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
9212 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
9213
9214 set_constant_flonums ();
9215
03b1477f
RE
9216 /* Set the cpu variant based on the command-line options. We prefer
9217 -mcpu= over -march= if both are set (as for GCC); and we prefer
9218 -mfpu= over any other way of setting the floating point unit.
9219 Use of legacy options with new options are faulted. */
9220 if (legacy_cpu != -1)
9221 {
9222 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
9223 as_bad (_("use of old and new-style options to set CPU type"));
9224
9225 mcpu_cpu_opt = legacy_cpu;
9226 }
9227 else if (mcpu_cpu_opt == -1)
9228 mcpu_cpu_opt = march_cpu_opt;
9229
9230 if (legacy_fpu != -1)
9231 {
9232 if (mfpu_opt != -1)
9233 as_bad (_("use of old and new-style options to set FPU type"));
9234
9235 mfpu_opt = legacy_fpu;
9236 }
9237 else if (mfpu_opt == -1)
9238 {
9239 if (mcpu_fpu_opt != -1)
9240 mfpu_opt = mcpu_fpu_opt;
9241 else
9242 mfpu_opt = march_fpu_opt;
9243 }
9244
9245 if (mfpu_opt == -1)
9246 {
9247 if (mcpu_cpu_opt == -1)
9248 mfpu_opt = FPU_DEFAULT;
9249 else if (mcpu_cpu_opt & ARM_EXT_V5)
9250 mfpu_opt = FPU_ARCH_VFP_V2;
9251 else
9252 mfpu_opt = FPU_ARCH_FPA;
9253 }
9254
9255 if (mcpu_cpu_opt == -1)
9256 mcpu_cpu_opt = CPU_DEFAULT;
9257
9258 cpu_variant = mcpu_cpu_opt | mfpu_opt;
9259
b99bd4ef
NC
9260#if defined OBJ_COFF || defined OBJ_ELF
9261 {
9262 unsigned int flags = 0;
9263
9264 /* Set the flags in the private structure. */
9265 if (uses_apcs_26) flags |= F_APCS26;
9266 if (support_interwork) flags |= F_INTERWORK;
9267 if (uses_apcs_float) flags |= F_APCS_FLOAT;
9268 if (pic_code) flags |= F_PIC;
bfae80f2 9269 if ((cpu_variant & FPU_ANY) == FPU_NONE
03b1477f 9270 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
bfae80f2 9271 flags |= F_SOFT_FLOAT;
03b1477f
RE
9272 /* Using VFP conventions (even if soft-float). */
9273 if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
9274
b99bd4ef
NC
9275
9276 bfd_set_private_flags (stdoutput, flags);
9277
9278 /* We have run out flags in the COFF header to encode the
9279 status of ATPCS support, so instead we create a dummy,
9280 empty, debug section called .arm.atpcs. */
9281 if (atpcs)
9282 {
9283 asection * sec;
9284
9285 sec = bfd_make_section (stdoutput, ".arm.atpcs");
9286
9287 if (sec != NULL)
9288 {
9289 bfd_set_section_flags
9290 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
9291 bfd_set_section_size (stdoutput, sec, 0);
9292 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
9293 }
9294 }
9295 }
9296#endif
9297
9298 /* Record the CPU type as well. */
9299 switch (cpu_variant & ARM_CPU_MASK)
9300 {
9301 case ARM_2:
9302 mach = bfd_mach_arm_2;
9303 break;
9304
9305 case ARM_3: /* Also ARM_250. */
9306 mach = bfd_mach_arm_2a;
9307 break;
9308
b89dddec
RE
9309 case ARM_6: /* Also ARM_7. */
9310 mach = bfd_mach_arm_3;
9311 break;
9312
b99bd4ef 9313 default:
b99bd4ef
NC
9314 mach = bfd_mach_arm_4;
9315 break;
b99bd4ef
NC
9316 }
9317
9318 /* Catch special cases. */
03b1477f 9319 if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef
NC
9320 mach = bfd_mach_arm_XScale;
9321 else if (cpu_variant & ARM_EXT_V5E)
9322 mach = bfd_mach_arm_5TE;
9323 else if (cpu_variant & ARM_EXT_V5)
9324 {
b89dddec 9325 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
9326 mach = bfd_mach_arm_5T;
9327 else
9328 mach = bfd_mach_arm_5;
9329 }
b89dddec 9330 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 9331 {
b89dddec 9332 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
9333 mach = bfd_mach_arm_4T;
9334 else
9335 mach = bfd_mach_arm_4;
9336 }
b89dddec 9337 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
9338 mach = bfd_mach_arm_3M;
9339
9340 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
9341}
9342
9343/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
9344 for use in the a.out file, and stores them in the array pointed to by buf.
9345 This knows about the endian-ness of the target machine and does
9346 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
9347 2 (short) and 4 (long) Floating numbers are put out as a series of
9348 LITTLENUMS (shorts, here at least). */
9349
9350void
9351md_number_to_chars (buf, val, n)
9352 char * buf;
9353 valueT val;
9354 int n;
9355{
9356 if (target_big_endian)
9357 number_to_chars_bigendian (buf, val, n);
9358 else
9359 number_to_chars_littleendian (buf, val, n);
9360}
9361
9362static valueT
9363md_chars_to_number (buf, n)
9364 char * buf;
9365 int n;
9366{
9367 valueT result = 0;
9368 unsigned char * where = (unsigned char *) buf;
9369
9370 if (target_big_endian)
9371 {
9372 while (n--)
9373 {
9374 result <<= 8;
9375 result |= (*where++ & 255);
9376 }
9377 }
9378 else
9379 {
9380 while (n--)
9381 {
9382 result <<= 8;
9383 result |= (where[n] & 255);
9384 }
9385 }
9386
9387 return result;
9388}
9389
9390/* Turn a string in input_line_pointer into a floating point constant
9391 of type TYPE, and store the appropriate bytes in *LITP. The number
9392 of LITTLENUMS emitted is stored in *SIZEP. An error message is
9393 returned, or NULL on OK.
9394
9395 Note that fp constants aren't represent in the normal way on the ARM.
9396 In big endian mode, things are as expected. However, in little endian
9397 mode fp constants are big-endian word-wise, and little-endian byte-wise
9398 within the words. For example, (double) 1.1 in big endian mode is
9399 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
9400 the byte sequence 99 99 f1 3f 9a 99 99 99.
9401
9402 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
9403
9404char *
9405md_atof (type, litP, sizeP)
9406 char type;
9407 char * litP;
9408 int * sizeP;
9409{
9410 int prec;
9411 LITTLENUM_TYPE words[MAX_LITTLENUMS];
9412 char *t;
9413 int i;
9414
9415 switch (type)
9416 {
9417 case 'f':
9418 case 'F':
9419 case 's':
9420 case 'S':
9421 prec = 2;
9422 break;
9423
9424 case 'd':
9425 case 'D':
9426 case 'r':
9427 case 'R':
9428 prec = 4;
9429 break;
9430
9431 case 'x':
9432 case 'X':
9433 prec = 6;
9434 break;
9435
9436 case 'p':
9437 case 'P':
9438 prec = 6;
9439 break;
9440
9441 default:
9442 *sizeP = 0;
f03698e6 9443 return _("bad call to MD_ATOF()");
b99bd4ef
NC
9444 }
9445
9446 t = atof_ieee (input_line_pointer, type, words);
9447 if (t)
9448 input_line_pointer = t;
9449 *sizeP = prec * 2;
9450
9451 if (target_big_endian)
9452 {
9453 for (i = 0; i < prec; i++)
9454 {
9455 md_number_to_chars (litP, (valueT) words[i], 2);
9456 litP += 2;
9457 }
9458 }
9459 else
9460 {
bfae80f2
RE
9461 if (cpu_variant & FPU_ARCH_VFP)
9462 for (i = prec - 1; i >= 0; i--)
9463 {
9464 md_number_to_chars (litP, (valueT) words[i], 2);
9465 litP += 2;
9466 }
9467 else
9468 /* For a 4 byte float the order of elements in `words' is 1 0.
9469 For an 8 byte float the order is 1 0 3 2. */
9470 for (i = 0; i < prec; i += 2)
9471 {
9472 md_number_to_chars (litP, (valueT) words[i + 1], 2);
9473 md_number_to_chars (litP + 2, (valueT) words[i], 2);
9474 litP += 4;
9475 }
b99bd4ef
NC
9476 }
9477
9478 return 0;
9479}
9480
9481/* The knowledge of the PC's pipeline offset is built into the insns
9482 themselves. */
9483
9484long
9485md_pcrel_from (fixP)
9486 fixS * fixP;
9487{
9488 if (fixP->fx_addsy
9489 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
9490 && fixP->fx_subsy == NULL)
9491 return 0;
9492
9493 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
9494 {
9495 /* PC relative addressing on the Thumb is slightly odd
9496 as the bottom two bits of the PC are forced to zero
9497 for the calculation. */
9498 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
9499 }
9500
9501#ifdef TE_WINCE
9502 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
9503 so we un-adjust here to compensate for the accomodation. */
9504 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
9505#else
9506 return fixP->fx_where + fixP->fx_frag->fr_address;
9507#endif
9508}
9509
9510/* Round up a section size to the appropriate boundary. */
9511
9512valueT
9513md_section_align (segment, size)
9514 segT segment ATTRIBUTE_UNUSED;
9515 valueT size;
9516{
9517#ifdef OBJ_ELF
9518 return size;
9519#else
9520 /* Round all sects to multiple of 4. */
9521 return (size + 3) & ~3;
9522#endif
9523}
9524
9525/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
9526 Otherwise we have no need to default values of symbols. */
9527
9528symbolS *
9529md_undefined_symbol (name)
9530 char * name ATTRIBUTE_UNUSED;
9531{
9532#ifdef OBJ_ELF
9533 if (name[0] == '_' && name[1] == 'G'
9534 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
9535 {
9536 if (!GOT_symbol)
9537 {
9538 if (symbol_find (name))
9539 as_bad ("GOT already in the symbol table");
9540
9541 GOT_symbol = symbol_new (name, undefined_section,
9542 (valueT) 0, & zero_address_frag);
9543 }
9544
9545 return GOT_symbol;
9546 }
9547#endif
9548
9549 return 0;
9550}
9551
9552/* arm_reg_parse () := if it looks like a register, return its token and
9553 advance the pointer. */
9554
9555static int
6c43fab6 9556arm_reg_parse (ccp, htab)
b99bd4ef 9557 register char ** ccp;
6c43fab6 9558 struct hash_control *htab;
b99bd4ef
NC
9559{
9560 char * start = * ccp;
9561 char c;
9562 char * p;
9563 struct reg_entry * reg;
9564
9565#ifdef REGISTER_PREFIX
9566 if (*start != REGISTER_PREFIX)
9567 return FAIL;
9568 p = start + 1;
9569#else
9570 p = start;
9571#ifdef OPTIONAL_REGISTER_PREFIX
9572 if (*p == OPTIONAL_REGISTER_PREFIX)
9573 p++, start++;
9574#endif
9575#endif
3882b010 9576 if (!ISALPHA (*p) || !is_name_beginner (*p))
b99bd4ef
NC
9577 return FAIL;
9578
9579 c = *p++;
3882b010 9580 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
b99bd4ef
NC
9581 c = *p++;
9582
9583 *--p = 0;
6c43fab6 9584 reg = (struct reg_entry *) hash_find (htab, start);
b99bd4ef
NC
9585 *p = c;
9586
9587 if (reg)
9588 {
9589 *ccp = p;
9590 return reg->number;
9591 }
9592
9593 return FAIL;
9594}
9595
6c43fab6
RE
9596/* Search for the following register name in each of the possible reg name
9597 tables. Return the classification if found, or REG_TYPE_MAX if not
9598 present. */
9599static enum arm_reg_type
9600arm_reg_parse_any (cp)
9601 char *cp;
9602{
9603 int i;
9604
9605 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
9606 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
9607 return (enum arm_reg_type) i;
9608
9609 return REG_TYPE_MAX;
9610}
9611
94f592af
NC
9612void
9613md_apply_fix3 (fixP, valP, seg)
b99bd4ef 9614 fixS * fixP;
94f592af 9615 valueT * valP;
b99bd4ef
NC
9616 segT seg;
9617{
94f592af 9618 offsetT value = * valP;
b99bd4ef
NC
9619 offsetT newval;
9620 unsigned int newimm;
9621 unsigned long temp;
9622 int sign;
9623 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
9624 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
9625
9626 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
9627
9628 /* Note whether this will delete the relocation. */
9629#if 0
9630 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
9631 doesn't work fully.) */
9632 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
9633 && !fixP->fx_pcrel)
9634#else
9635 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
9636#endif
9637 fixP->fx_done = 1;
9638
9639 /* If this symbol is in a different section then we need to leave it for
9640 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
9641 so we have to undo it's effects here. */
9642 if (fixP->fx_pcrel)
9643 {
9644 if (fixP->fx_addsy != NULL
9645 && S_IS_DEFINED (fixP->fx_addsy)
9646 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
9647 {
9648 if (target_oabi
9649 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
9650 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
9651 ))
9652 value = 0;
9653 else
9654 value += md_pcrel_from (fixP);
9655 }
9656 }
9657
9658 /* Remember value for emit_reloc. */
9659 fixP->fx_addnumber = value;
9660
9661 switch (fixP->fx_r_type)
9662 {
9663 case BFD_RELOC_ARM_IMMEDIATE:
9664 newimm = validate_immediate (value);
9665 temp = md_chars_to_number (buf, INSN_SIZE);
9666
9667 /* If the instruction will fail, see if we can fix things up by
9668 changing the opcode. */
9669 if (newimm == (unsigned int) FAIL
9670 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
9671 {
9672 as_bad_where (fixP->fx_file, fixP->fx_line,
9673 _("invalid constant (%lx) after fixup"),
9674 (unsigned long) value);
9675 break;
9676 }
9677
9678 newimm |= (temp & 0xfffff000);
9679 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
6189168b 9680 fixP->fx_done = 1;
b99bd4ef
NC
9681 break;
9682
9683 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
9684 {
9685 unsigned int highpart = 0;
9686 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 9687
b99bd4ef
NC
9688 newimm = validate_immediate (value);
9689 temp = md_chars_to_number (buf, INSN_SIZE);
9690
9691 /* If the instruction will fail, see if we can fix things up by
9692 changing the opcode. */
9693 if (newimm == (unsigned int) FAIL
9694 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
9695 {
9696 /* No ? OK - try using two ADD instructions to generate
9697 the value. */
9698 newimm = validate_immediate_twopart (value, & highpart);
9699
9700 /* Yes - then make sure that the second instruction is
9701 also an add. */
9702 if (newimm != (unsigned int) FAIL)
9703 newinsn = temp;
9704 /* Still No ? Try using a negated value. */
9705 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
9706 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
9707 /* Otherwise - give up. */
9708 else
9709 {
9710 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9711 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 9712 (long) value);
b99bd4ef
NC
9713 break;
9714 }
9715
9716 /* Replace the first operand in the 2nd instruction (which
9717 is the PC) with the destination register. We have
9718 already added in the PC in the first instruction and we
9719 do not want to do it again. */
9720 newinsn &= ~ 0xf0000;
9721 newinsn |= ((newinsn & 0x0f000) << 4);
9722 }
9723
9724 newimm |= (temp & 0xfffff000);
9725 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
9726
9727 highpart |= (newinsn & 0xfffff000);
9728 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
9729 }
9730 break;
9731
9732 case BFD_RELOC_ARM_OFFSET_IMM:
9733 sign = value >= 0;
9734
9735 if (value < 0)
9736 value = - value;
9737
9738 if (validate_offset_imm (value, 0) == FAIL)
9739 {
9740 as_bad_where (fixP->fx_file, fixP->fx_line,
9741 _("bad immediate value for offset (%ld)"),
9742 (long) value);
9743 break;
9744 }
9745
9746 newval = md_chars_to_number (buf, INSN_SIZE);
9747 newval &= 0xff7ff000;
9748 newval |= value | (sign ? INDEX_UP : 0);
9749 md_number_to_chars (buf, newval, INSN_SIZE);
9750 break;
9751
9752 case BFD_RELOC_ARM_OFFSET_IMM8:
9753 case BFD_RELOC_ARM_HWLITERAL:
9754 sign = value >= 0;
9755
9756 if (value < 0)
9757 value = - value;
9758
9759 if (validate_offset_imm (value, 1) == FAIL)
9760 {
9761 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
9762 as_bad_where (fixP->fx_file, fixP->fx_line,
9763 _("invalid literal constant: pool needs to be closer"));
9764 else
9765 as_bad (_("bad immediate value for half-word offset (%ld)"),
9766 (long) value);
9767 break;
9768 }
9769
9770 newval = md_chars_to_number (buf, INSN_SIZE);
9771 newval &= 0xff7ff0f0;
9772 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
9773 md_number_to_chars (buf, newval, INSN_SIZE);
9774 break;
9775
9776 case BFD_RELOC_ARM_LITERAL:
9777 sign = value >= 0;
9778
9779 if (value < 0)
9780 value = - value;
9781
9782 if (validate_offset_imm (value, 0) == FAIL)
9783 {
9784 as_bad_where (fixP->fx_file, fixP->fx_line,
9785 _("invalid literal constant: pool needs to be closer"));
9786 break;
9787 }
9788
9789 newval = md_chars_to_number (buf, INSN_SIZE);
9790 newval &= 0xff7ff000;
9791 newval |= value | (sign ? INDEX_UP : 0);
9792 md_number_to_chars (buf, newval, INSN_SIZE);
9793 break;
9794
9795 case BFD_RELOC_ARM_SHIFT_IMM:
9796 newval = md_chars_to_number (buf, INSN_SIZE);
9797 if (((unsigned long) value) > 32
9798 || (value == 32
9799 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
9800 {
9801 as_bad_where (fixP->fx_file, fixP->fx_line,
9802 _("shift expression is too large"));
9803 break;
9804 }
9805
9806 if (value == 0)
9807 /* Shifts of zero must be done as lsl. */
9808 newval &= ~0x60;
9809 else if (value == 32)
9810 value = 0;
9811 newval &= 0xfffff07f;
9812 newval |= (value & 0x1f) << 7;
9813 md_number_to_chars (buf, newval, INSN_SIZE);
9814 break;
9815
9816 case BFD_RELOC_ARM_SWI:
9817 if (arm_data->thumb_mode)
9818 {
9819 if (((unsigned long) value) > 0xff)
9820 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9821 _("invalid swi expression"));
b99bd4ef
NC
9822 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
9823 newval |= value;
9824 md_number_to_chars (buf, newval, THUMB_SIZE);
9825 }
9826 else
9827 {
9828 if (((unsigned long) value) > 0x00ffffff)
9829 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9830 _("invalid swi expression"));
b99bd4ef
NC
9831 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
9832 newval |= value;
9833 md_number_to_chars (buf, newval, INSN_SIZE);
9834 }
9835 break;
9836
9837 case BFD_RELOC_ARM_MULTI:
9838 if (((unsigned long) value) > 0xffff)
9839 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9840 _("invalid expression in load/store multiple"));
b99bd4ef
NC
9841 newval = value | md_chars_to_number (buf, INSN_SIZE);
9842 md_number_to_chars (buf, newval, INSN_SIZE);
9843 break;
9844
9845 case BFD_RELOC_ARM_PCREL_BRANCH:
9846 newval = md_chars_to_number (buf, INSN_SIZE);
9847
9848 /* Sign-extend a 24-bit number. */
9849#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
9850
9851#ifdef OBJ_ELF
9852 if (! target_oabi)
9853 value = fixP->fx_offset;
9854#endif
9855
9856 /* We are going to store value (shifted right by two) in the
9857 instruction, in a 24 bit, signed field. Thus we need to check
9858 that none of the top 8 bits of the shifted value (top 7 bits of
9859 the unshifted, unsigned value) are set, or that they are all set. */
9860 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
9861 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
9862 {
9863#ifdef OBJ_ELF
9864 /* Normally we would be stuck at this point, since we cannot store
9865 the absolute address that is the destination of the branch in the
9866 24 bits of the branch instruction. If however, we happen to know
9867 that the destination of the branch is in the same section as the
9868 branch instruciton itself, then we can compute the relocation for
9869 ourselves and not have to bother the linker with it.
9870
9871 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
9872 because I have not worked out how to do this for OBJ_COFF or
9873 target_oabi. */
9874 if (! target_oabi
9875 && fixP->fx_addsy != NULL
9876 && S_IS_DEFINED (fixP->fx_addsy)
9877 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
9878 {
9879 /* Get pc relative value to go into the branch. */
94f592af 9880 value = * valP;
b99bd4ef
NC
9881
9882 /* Permit a backward branch provided that enough bits
9883 are set. Allow a forwards branch, provided that
9884 enough bits are clear. */
9885 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
9886 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
9887 fixP->fx_done = 1;
9888 }
9889
9890 if (! fixP->fx_done)
9891#endif
9892 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9893 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
9894 }
9895
9896 value >>= 2;
9897 value += SEXT24 (newval);
9898
9899 if ( (value & ~ ((offsetT) 0xffffff)) != 0
9900 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
9901 as_bad_where (fixP->fx_file, fixP->fx_line,
9902 _("out of range branch"));
9903
9904 newval = (value & 0x00ffffff) | (newval & 0xff000000);
9905 md_number_to_chars (buf, newval, INSN_SIZE);
9906 break;
9907
9908 case BFD_RELOC_ARM_PCREL_BLX:
9909 {
9910 offsetT hbit;
9911 newval = md_chars_to_number (buf, INSN_SIZE);
9912
9913#ifdef OBJ_ELF
9914 if (! target_oabi)
9915 value = fixP->fx_offset;
9916#endif
9917 hbit = (value >> 1) & 1;
9918 value = (value >> 2) & 0x00ffffff;
9919 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
9920 newval = value | (newval & 0xfe000000) | (hbit << 24);
9921 md_number_to_chars (buf, newval, INSN_SIZE);
9922 }
9923 break;
9924
9925 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
9926 newval = md_chars_to_number (buf, THUMB_SIZE);
9927 {
9928 addressT diff = (newval & 0xff) << 1;
9929 if (diff & 0x100)
9930 diff |= ~0xff;
9931
9932 value += diff;
9933 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
9934 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9935 _("branch out of range"));
b99bd4ef
NC
9936 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
9937 }
9938 md_number_to_chars (buf, newval, THUMB_SIZE);
9939 break;
9940
9941 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
9942 newval = md_chars_to_number (buf, THUMB_SIZE);
9943 {
9944 addressT diff = (newval & 0x7ff) << 1;
9945 if (diff & 0x800)
9946 diff |= ~0x7ff;
9947
9948 value += diff;
9949 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
9950 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9951 _("branch out of range"));
b99bd4ef
NC
9952 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
9953 }
9954 md_number_to_chars (buf, newval, THUMB_SIZE);
9955 break;
9956
9957 case BFD_RELOC_THUMB_PCREL_BLX:
9958 case BFD_RELOC_THUMB_PCREL_BRANCH23:
9959 {
9960 offsetT newval2;
9961 addressT diff;
9962
9963 newval = md_chars_to_number (buf, THUMB_SIZE);
9964 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
9965 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
9966 if (diff & 0x400000)
9967 diff |= ~0x3fffff;
9968#ifdef OBJ_ELF
9969 value = fixP->fx_offset;
9970#endif
9971 value += diff;
c62e1cc3 9972
b99bd4ef
NC
9973 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
9974 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 9975 _("branch with link out of range"));
b99bd4ef
NC
9976
9977 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
9978 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
9979 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
9980 /* For a BLX instruction, make sure that the relocation is rounded up
9981 to a word boundary. This follows the semantics of the instruction
9982 which specifies that bit 1 of the target address will come from bit
9983 1 of the base address. */
9984 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
9985 md_number_to_chars (buf, newval, THUMB_SIZE);
9986 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
9987 }
9988 break;
9989
9990 case BFD_RELOC_8:
9991 if (fixP->fx_done || fixP->fx_pcrel)
9992 md_number_to_chars (buf, value, 1);
9993#ifdef OBJ_ELF
9994 else if (!target_oabi)
9995 {
9996 value = fixP->fx_offset;
9997 md_number_to_chars (buf, value, 1);
9998 }
9999#endif
10000 break;
10001
10002 case BFD_RELOC_16:
10003 if (fixP->fx_done || fixP->fx_pcrel)
10004 md_number_to_chars (buf, value, 2);
10005#ifdef OBJ_ELF
10006 else if (!target_oabi)
10007 {
10008 value = fixP->fx_offset;
10009 md_number_to_chars (buf, value, 2);
10010 }
10011#endif
10012 break;
10013
10014#ifdef OBJ_ELF
10015 case BFD_RELOC_ARM_GOT32:
10016 case BFD_RELOC_ARM_GOTOFF:
10017 md_number_to_chars (buf, 0, 4);
10018 break;
10019#endif
10020
10021 case BFD_RELOC_RVA:
10022 case BFD_RELOC_32:
10023 if (fixP->fx_done || fixP->fx_pcrel)
10024 md_number_to_chars (buf, value, 4);
10025#ifdef OBJ_ELF
10026 else if (!target_oabi)
10027 {
10028 value = fixP->fx_offset;
10029 md_number_to_chars (buf, value, 4);
10030 }
10031#endif
10032 break;
10033
10034#ifdef OBJ_ELF
10035 case BFD_RELOC_ARM_PLT32:
10036 /* It appears the instruction is fully prepared at this point. */
10037 break;
10038#endif
10039
b99bd4ef
NC
10040 case BFD_RELOC_ARM_CP_OFF_IMM:
10041 sign = value >= 0;
10042 if (value < -1023 || value > 1023 || (value & 3))
10043 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10044 _("illegal value for co-processor offset"));
b99bd4ef
NC
10045 if (value < 0)
10046 value = -value;
10047 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
10048 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
10049 md_number_to_chars (buf, newval, INSN_SIZE);
10050 break;
10051
10052 case BFD_RELOC_ARM_THUMB_OFFSET:
10053 newval = md_chars_to_number (buf, THUMB_SIZE);
10054 /* Exactly what ranges, and where the offset is inserted depends
10055 on the type of instruction, we can establish this from the
10056 top 4 bits. */
10057 switch (newval >> 12)
10058 {
10059 case 4: /* PC load. */
10060 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
10061 forced to zero for these loads, so we will need to round
10062 up the offset if the instruction address is not word
10063 aligned (since the final address produced must be, and
10064 we can only describe word-aligned immediate offsets). */
10065
10066 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
10067 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10068 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
10069 (unsigned int) (fixP->fx_frag->fr_address
10070 + fixP->fx_where + value));
10071
10072 if ((value + 2) & ~0x3fe)
10073 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
10074 _("invalid offset, value too big (0x%08lX)"),
10075 (long) value);
b99bd4ef
NC
10076
10077 /* Round up, since pc will be rounded down. */
10078 newval |= (value + 2) >> 2;
10079 break;
10080
10081 case 9: /* SP load/store. */
10082 if (value & ~0x3fc)
10083 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
10084 _("invalid offset, value too big (0x%08lX)"),
10085 (long) value);
b99bd4ef
NC
10086 newval |= value >> 2;
10087 break;
10088
10089 case 6: /* Word load/store. */
10090 if (value & ~0x7c)
10091 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
10092 _("invalid offset, value too big (0x%08lX)"),
10093 (long) value);
b99bd4ef
NC
10094 newval |= value << 4; /* 6 - 2. */
10095 break;
10096
10097 case 7: /* Byte load/store. */
10098 if (value & ~0x1f)
10099 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
10100 _("invalid offset, value too big (0x%08lX)"),
10101 (long) value);
b99bd4ef
NC
10102 newval |= value << 6;
10103 break;
10104
10105 case 8: /* Halfword load/store. */
10106 if (value & ~0x3e)
10107 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
10108 _("invalid offset, value too big (0x%08lX)"),
10109 (long) value);
b99bd4ef
NC
10110 newval |= value << 5; /* 6 - 1. */
10111 break;
10112
10113 default:
10114 as_bad_where (fixP->fx_file, fixP->fx_line,
10115 "Unable to process relocation for thumb opcode: %lx",
10116 (unsigned long) newval);
10117 break;
10118 }
10119 md_number_to_chars (buf, newval, THUMB_SIZE);
10120 break;
10121
10122 case BFD_RELOC_ARM_THUMB_ADD:
10123 /* This is a complicated relocation, since we use it for all of
10124 the following immediate relocations:
10125
10126 3bit ADD/SUB
10127 8bit ADD/SUB
10128 9bit ADD/SUB SP word-aligned
10129 10bit ADD PC/SP word-aligned
10130
10131 The type of instruction being processed is encoded in the
10132 instruction field:
10133
10134 0x8000 SUB
10135 0x00F0 Rd
10136 0x000F Rs
10137 */
10138 newval = md_chars_to_number (buf, THUMB_SIZE);
10139 {
10140 int rd = (newval >> 4) & 0xf;
10141 int rs = newval & 0xf;
10142 int subtract = newval & 0x8000;
10143
10144 if (rd == REG_SP)
10145 {
10146 if (value & ~0x1fc)
10147 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10148 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
10149 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
10150 newval |= value >> 2;
10151 }
10152 else if (rs == REG_PC || rs == REG_SP)
10153 {
10154 if (subtract ||
10155 value & ~0x3fc)
10156 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10157 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
10158 (unsigned long) value);
10159 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
10160 newval |= rd << 8;
10161 newval |= value >> 2;
10162 }
10163 else if (rs == rd)
10164 {
10165 if (value & ~0xff)
10166 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10167 _("invalid 8bit immediate"));
b99bd4ef
NC
10168 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
10169 newval |= (rd << 8) | value;
10170 }
10171 else
10172 {
10173 if (value & ~0x7)
10174 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10175 _("invalid 3bit immediate"));
b99bd4ef
NC
10176 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
10177 newval |= rd | (rs << 3) | (value << 6);
10178 }
10179 }
10180 md_number_to_chars (buf, newval, THUMB_SIZE);
10181 break;
10182
10183 case BFD_RELOC_ARM_THUMB_IMM:
10184 newval = md_chars_to_number (buf, THUMB_SIZE);
10185 switch (newval >> 11)
10186 {
10187 case 0x04: /* 8bit immediate MOV. */
10188 case 0x05: /* 8bit immediate CMP. */
10189 if (value < 0 || value > 255)
10190 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10191 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
10192 (long) value);
10193 newval |= value;
10194 break;
10195
10196 default:
10197 abort ();
10198 }
10199 md_number_to_chars (buf, newval, THUMB_SIZE);
10200 break;
10201
10202 case BFD_RELOC_ARM_THUMB_SHIFT:
10203 /* 5bit shift value (0..31). */
10204 if (value < 0 || value > 31)
10205 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10206 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
10207 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
10208 newval |= value << 6;
10209 md_number_to_chars (buf, newval, THUMB_SIZE);
10210 break;
10211
10212 case BFD_RELOC_VTABLE_INHERIT:
10213 case BFD_RELOC_VTABLE_ENTRY:
10214 fixP->fx_done = 0;
94f592af 10215 return;
b99bd4ef
NC
10216
10217 case BFD_RELOC_NONE:
10218 default:
10219 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 10220 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 10221 }
b99bd4ef
NC
10222}
10223
10224/* Translate internal representation of relocation info to BFD target
10225 format. */
10226
10227arelent *
10228tc_gen_reloc (section, fixp)
10229 asection * section ATTRIBUTE_UNUSED;
10230 fixS * fixp;
10231{
10232 arelent * reloc;
10233 bfd_reloc_code_real_type code;
10234
10235 reloc = (arelent *) xmalloc (sizeof (arelent));
10236
10237 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
10238 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
10239 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
10240
10241 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
10242#ifndef OBJ_ELF
10243 if (fixp->fx_pcrel == 0)
10244 reloc->addend = fixp->fx_offset;
10245 else
10246 reloc->addend = fixp->fx_offset = reloc->address;
10247#else /* OBJ_ELF */
10248 reloc->addend = fixp->fx_offset;
10249#endif
10250
10251 switch (fixp->fx_r_type)
10252 {
10253 case BFD_RELOC_8:
10254 if (fixp->fx_pcrel)
10255 {
10256 code = BFD_RELOC_8_PCREL;
10257 break;
10258 }
10259
10260 case BFD_RELOC_16:
10261 if (fixp->fx_pcrel)
10262 {
10263 code = BFD_RELOC_16_PCREL;
10264 break;
10265 }
10266
10267 case BFD_RELOC_32:
10268 if (fixp->fx_pcrel)
10269 {
10270 code = BFD_RELOC_32_PCREL;
10271 break;
10272 }
10273
10274 case BFD_RELOC_ARM_PCREL_BRANCH:
10275 case BFD_RELOC_ARM_PCREL_BLX:
10276 case BFD_RELOC_RVA:
10277 case BFD_RELOC_THUMB_PCREL_BRANCH9:
10278 case BFD_RELOC_THUMB_PCREL_BRANCH12:
10279 case BFD_RELOC_THUMB_PCREL_BRANCH23:
10280 case BFD_RELOC_THUMB_PCREL_BLX:
10281 case BFD_RELOC_VTABLE_ENTRY:
10282 case BFD_RELOC_VTABLE_INHERIT:
10283 code = fixp->fx_r_type;
10284 break;
10285
10286 case BFD_RELOC_ARM_LITERAL:
10287 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
10288 /* If this is called then the a literal has
10289 been referenced across a section boundary. */
b99bd4ef 10290 as_bad_where (fixp->fx_file, fixp->fx_line,
ed71e111 10291 _("literal referenced across section boundary"));
b99bd4ef
NC
10292 return NULL;
10293
10294#ifdef OBJ_ELF
10295 case BFD_RELOC_ARM_GOT32:
10296 case BFD_RELOC_ARM_GOTOFF:
10297 case BFD_RELOC_ARM_PLT32:
10298 code = fixp->fx_r_type;
10299 break;
10300#endif
10301
10302 case BFD_RELOC_ARM_IMMEDIATE:
10303 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 10304 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
10305 return NULL;
10306
10307 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10308 as_bad_where (fixp->fx_file, fixp->fx_line,
10309 _("ADRL used for a symbol not defined in the same file"));
10310 return NULL;
10311
10312 case BFD_RELOC_ARM_OFFSET_IMM:
10313 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 10314 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
10315 return NULL;
10316
10317 default:
10318 {
10319 char * type;
10320
10321 switch (fixp->fx_r_type)
10322 {
b99bd4ef
NC
10323 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
10324 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
10325 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
10326 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
10327 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
10328 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
10329 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
10330 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
10331 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
10332 default: type = _("<unknown>"); break;
10333 }
10334 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 10335 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
10336 type);
10337 return NULL;
10338 }
10339 }
10340
10341#ifdef OBJ_ELF
8df7094c 10342 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
10343 && GOT_symbol
10344 && fixp->fx_addsy == GOT_symbol)
10345 {
10346 code = BFD_RELOC_ARM_GOTPC;
10347 reloc->addend = fixp->fx_offset = reloc->address;
10348 }
10349#endif
10350
10351 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
10352
10353 if (reloc->howto == NULL)
10354 {
10355 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 10356 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
10357 bfd_get_reloc_code_name (code));
10358 return NULL;
10359 }
10360
10361 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
10362 vtable entry to be used in the relocation's section offset. */
10363 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
10364 reloc->address = fixp->fx_offset;
10365
10366 return reloc;
10367}
10368
10369int
10370md_estimate_size_before_relax (fragP, segtype)
10371 fragS * fragP ATTRIBUTE_UNUSED;
10372 segT segtype ATTRIBUTE_UNUSED;
10373{
10374 as_fatal (_("md_estimate_size_before_relax\n"));
10375 return 1;
10376}
10377
10378static void
f03698e6
RE
10379output_inst (str)
10380 const char *str;
b99bd4ef
NC
10381{
10382 char * to = NULL;
10383
10384 if (inst.error)
10385 {
f03698e6 10386 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
10387 return;
10388 }
10389
10390 to = frag_more (inst.size);
10391
10392 if (thumb_mode && (inst.size > THUMB_SIZE))
10393 {
10394 assert (inst.size == (2 * THUMB_SIZE));
10395 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
10396 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
10397 }
10398 else if (inst.size > INSN_SIZE)
10399 {
10400 assert (inst.size == (2 * INSN_SIZE));
10401 md_number_to_chars (to, inst.instruction, INSN_SIZE);
10402 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
10403 }
10404 else
10405 md_number_to_chars (to, inst.instruction, inst.size);
10406
10407 if (inst.reloc.type != BFD_RELOC_NONE)
10408 fix_new_arm (frag_now, to - frag_now->fr_literal,
10409 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
10410 inst.reloc.type);
10411
10412#ifdef OBJ_ELF
10413 dwarf2_emit_insn (inst.size);
10414#endif
10415}
10416
10417void
10418md_assemble (str)
10419 char * str;
10420{
6c43fab6
RE
10421 char c;
10422 char *p;
10423 char *start;
b99bd4ef
NC
10424
10425 /* Align the instruction.
10426 This may not be the right thing to do but ... */
10427#if 0
10428 arm_align (2, 0);
10429#endif
b99bd4ef
NC
10430
10431 /* Align the previous label if needed. */
10432 if (last_label_seen != NULL)
10433 {
10434 symbol_set_frag (last_label_seen, frag_now);
10435 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
10436 S_SET_SEGMENT (last_label_seen, now_seg);
10437 }
10438
10439 memset (&inst, '\0', sizeof (inst));
10440 inst.reloc.type = BFD_RELOC_NONE;
10441
10442 skip_whitespace (str);
10443
10444 /* Scan up to the end of the op-code, which must end in white space or
10445 end of string. */
10446 for (start = p = str; *p != '\0'; p++)
10447 if (*p == ' ')
10448 break;
10449
10450 if (p == str)
10451 {
f03698e6 10452 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
10453 return;
10454 }
10455
10456 if (thumb_mode)
10457 {
05d2d07e 10458 const struct thumb_opcode * opcode;
b99bd4ef
NC
10459
10460 c = *p;
10461 *p = '\0';
05d2d07e 10462 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
10463 *p = c;
10464
10465 if (opcode)
10466 {
10467 /* Check that this instruction is supported for this CPU. */
90e4755a 10468 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 10469 {
f03698e6 10470 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
10471 return;
10472 }
10473
10474 inst.instruction = opcode->value;
10475 inst.size = opcode->size;
10476 (*opcode->parms) (p);
f03698e6 10477 output_inst (str);
b99bd4ef
NC
10478 return;
10479 }
10480 }
10481 else
10482 {
05d2d07e 10483 const struct asm_opcode * opcode;
b99bd4ef 10484
90e4755a
RE
10485 c = *p;
10486 *p = '\0';
6c43fab6 10487 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 10488 *p = c;
b99bd4ef 10489
90e4755a 10490 if (opcode)
b99bd4ef 10491 {
90e4755a
RE
10492 /* Check that this instruction is supported for this CPU. */
10493 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 10494 {
f03698e6 10495 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
10496 return;
10497 }
10498
90e4755a
RE
10499 inst.instruction = opcode->value;
10500 inst.size = INSN_SIZE;
f2b7cb0a 10501 (*opcode->parms) (p);
f03698e6 10502 output_inst (str);
90e4755a 10503 return;
b99bd4ef
NC
10504 }
10505 }
10506
10507 /* It wasn't an instruction, but it might be a register alias of the form
10508 alias .req reg. */
6c43fab6
RE
10509 if (create_register_alias (str, p))
10510 return;
b99bd4ef 10511
b99bd4ef
NC
10512 as_bad (_("bad instruction `%s'"), start);
10513}
10514
10515/* md_parse_option
10516 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 10517 See if it's a processor-specific option.
03b1477f
RE
10518
10519 This routine is somewhat complicated by the need for backwards
10520 compatibility (since older releases of gcc can't be changed).
10521 The new options try to make the interface as compatible as
10522 possible with GCC.
10523
10524 New options (supported) are:
10525
10526 -mcpu=<cpu name> Assemble for selected processor
10527 -march=<architecture name> Assemble for selected architecture
10528 -mfpu=<fpu architecture> Assemble for selected FPU.
10529 -EB/-mbig-endian Big-endian
10530 -EL/-mlittle-endian Little-endian
10531 -k Generate PIC code
10532 -mthumb Start in Thumb mode
10533 -mthumb-interwork Code supports ARM/Thumb interworking
10534
3d0c9500 10535 For now we will also provide support for:
03b1477f
RE
10536
10537 -mapcs-32 32-bit Program counter
10538 -mapcs-26 26-bit Program counter
10539 -macps-float Floats passed in FP registers
10540 -mapcs-reentrant Reentrant code
10541 -matpcs
10542 (sometime these will probably be replaced with -mapcs=<list of options>
10543 and -matpcs=<list of options>)
10544
10545 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
10546 Cpu variants, the arm part is optional:
10547 -m[arm]1 Currently not supported.
10548 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
10549 -m[arm]3 Arm 3 processor
10550 -m[arm]6[xx], Arm 6 processors
10551 -m[arm]7[xx][t][[d]m] Arm 7 processors
10552 -m[arm]8[10] Arm 8 processors
10553 -m[arm]9[20][tdmi] Arm 9 processors
10554 -mstrongarm[110[0]] StrongARM processors
10555 -mxscale XScale processors
10556 -m[arm]v[2345[t[e]]] Arm architectures
10557 -mall All (except the ARM1)
10558 FP variants:
10559 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
10560 -mfpe-old (No float load/store multiples)
bfae80f2
RE
10561 -mvfpxd VFP Single precision
10562 -mvfp All VFP
b99bd4ef 10563 -mno-fpu Disable all floating point instructions
b99bd4ef 10564
03b1477f
RE
10565 The following CPU names are recognized:
10566 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
10567 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
10568 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
10569 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
10570 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
10571 arm10t arm10e, arm1020t, arm1020e, arm10200e,
10572 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
10573
10574 */
10575
5a38dc70 10576const char * md_shortopts = "m:k";
03b1477f 10577
b99bd4ef
NC
10578#ifdef ARM_BI_ENDIAN
10579#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 10580#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 10581#else
21f0f23a
RE
10582#if TARGET_BYTES_BIG_ENDIAN
10583#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
10584#else
10585#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 10586#endif
ce058b6c 10587#endif
03b1477f
RE
10588
10589struct option md_longopts[] =
10590{
10591#ifdef OPTION_EB
10592 {"EB", no_argument, NULL, OPTION_EB},
10593#endif
10594#ifdef OPTION_EL
10595 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
10596#endif
10597 {NULL, no_argument, NULL, 0}
10598};
10599
10600size_t md_longopts_size = sizeof (md_longopts);
10601
03b1477f 10602struct arm_option_table
b99bd4ef 10603{
03b1477f
RE
10604 char *option; /* Option name to match. */
10605 char *help; /* Help information. */
10606 int *var; /* Variable to change. */
10607 int value; /* What to change it to. */
10608 char *deprecated; /* If non-null, print this message. */
10609};
b99bd4ef 10610
cc8a6dd0 10611struct arm_option_table arm_opts[] =
03b1477f
RE
10612{
10613 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
10614 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
10615 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
10616 &support_interwork, 1, NULL},
10617 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
10618 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
10619 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
10620 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
10621 1, NULL},
10622 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
10623 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
10624 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
10625 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
10626 NULL},
10627
10628 /* These are recognized by the assembler, but have no affect on code. */
10629 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
10630 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
10631
10632 /* DON'T add any new processors to this list -- we want the whole list
10633 to go away... Add them to the processors table instead. */
10634 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
10635 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
10636 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
10637 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
10638 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
10639 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
10640 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
10641 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
10642 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
10643 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
10644 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
10645 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
10646 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
10647 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
10648 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
10649 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
10650 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
10651 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
10652 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
10653 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
10654 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
10655 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
10656 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
10657 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
10658 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
10659 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
10660 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
10661 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
10662 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
10663 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
10664 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
10665 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
10666 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
10667 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
10668 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
10669 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
10670 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
10671 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
10672 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
10673 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
10674 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
10675 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
10676 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
10677 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
10678 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
10679 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
10680 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10681 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10682 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10683 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
10684 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
10685 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
10686 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
10687 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
10688 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
10689 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
10690 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
10691 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
10692 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
10693 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
10694 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
10695 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
10696 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
10697 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
10698 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
10699 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
10700 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
10701 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
10702 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
10703 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
10704 N_("use -mcpu=strongarm110")},
10705 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
10706 N_("use -mcpu=strongarm1100")},
10707 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
10708 N_("use -mcpu=strongarm1110")},
10709 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
10710 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
10711
10712 /* Architecture variants -- don't add any more to this list either. */
10713 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
10714 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
10715 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
10716 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
10717 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
10718 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
10719 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
10720 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
10721 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
10722 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
10723 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
10724 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
10725 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
10726 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
10727 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
10728 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
10729 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
10730 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
10731
10732 /* Floating point variants -- don't add any more to this list either. */
10733 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
10734 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
10735 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
10736 {"mno-fpu", NULL, &legacy_fpu, 0,
10737 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
10738
10739 {NULL, NULL, NULL, 0, NULL}
10740};
21f0f23a 10741
03b1477f
RE
10742struct arm_cpu_option_table
10743{
10744 char *name;
10745 int value;
10746 /* For some CPUs we assume an FPU unless the user explicitly sets
10747 -mfpu=... */
10748 int default_fpu;
10749};
10750
10751/* This list should, at a minimum, contain all the cpu names
10752 recognized by GCC. */
10753static struct arm_cpu_option_table arm_cpus[] =
10754{
10755 {"all", ARM_ANY, FPU_ARCH_FPA},
10756 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
10757 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
10758 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
10759 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
10760 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
10761 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
10762 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
10763 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
10764 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
10765 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
10766 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
10767 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
10768 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
10769 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
10770 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
10771 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
10772 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
10773 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
10774 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
10775 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10776 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
10777 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10778 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10779 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
10780 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
10781 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
10782 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
10783 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10784 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
10785 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
10786 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
10787 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
10788 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
10789 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
10790 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
10791 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
10792 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
10793 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
10794 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10795 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10796 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10797 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
10798 /* For V5 or later processors we default to using VFP; but the user
10799 should really set the FPU type explicitly. */
10800 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
10801 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 10802 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
10803 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
10804 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10805 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
10806 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10807 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
10808 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10809 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10810 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
10811 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
10812 /* ??? XSCALE is really an architecture. */
10813 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
10814 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
10815 /* Maverick */
10816 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
10817 {NULL, 0, 0}
10818};
cc8a6dd0 10819
03b1477f
RE
10820struct arm_arch_option_table
10821{
10822 char *name;
10823 int value;
10824 int default_fpu;
10825};
10826
10827/* This list should, at a minimum, contain all the architecture names
10828 recognized by GCC. */
10829static struct arm_arch_option_table arm_archs[] =
10830{
10831 {"all", ARM_ANY, FPU_ARCH_FPA},
10832 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
10833 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
10834 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
10835 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
10836 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
10837 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
10838 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
10839 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
10840 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
10841 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
10842 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
10843 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
10844 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
10845 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
10846 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 10847 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
03b1477f
RE
10848 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
10849 {NULL, 0, 0}
10850};
10851
10852/* ISA extensions in the co-processor space. */
10853struct arm_arch_extension_table
10854{
10855 char *name;
10856 int value;
10857};
10858
10859static struct arm_arch_extension_table arm_extensions[] =
10860{
10861 {"maverick", ARM_CEXT_MAVERICK},
10862 {"xscale", ARM_CEXT_XSCALE},
10863 {NULL, 0}
10864};
b99bd4ef 10865
03b1477f
RE
10866struct arm_fpu_option_table
10867{
10868 char *name;
10869 int value;
10870};
10871
10872/* This list should, at a minimum, contain all the fpu names
10873 recognized by GCC. */
10874static struct arm_fpu_option_table arm_fpus[] =
10875{
10876 {"softfpa", FPU_NONE},
10877 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
10878 {"fpe2", FPU_ARCH_FPE},
10879 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
10880 {"fpa", FPU_ARCH_FPA},
10881 {"fpa10", FPU_ARCH_FPA},
10882 {"fpa11", FPU_ARCH_FPA},
10883 {"arm7500fe", FPU_ARCH_FPA},
10884 {"softvfp", FPU_ARCH_VFP},
10885 {"softvfp+vfp", FPU_ARCH_VFP_V2},
10886 {"vfp", FPU_ARCH_VFP_V2},
10887 {"vfp9", FPU_ARCH_VFP_V2},
10888 {"vfp10", FPU_ARCH_VFP_V2},
10889 {"vfp10-r0", FPU_ARCH_VFP_V1},
10890 {"vfpxd", FPU_ARCH_VFP_V1xD},
10891 {"arm1020t", FPU_ARCH_VFP_V1},
10892 {"arm1020e", FPU_ARCH_VFP_V2},
10893 {NULL, 0}
10894};
10895
10896struct arm_long_option_table
10897{
10898 char *option; /* Substring to match. */
10899 char *help; /* Help information. */
10900 int (*func) PARAMS ((char *subopt)); /* Function to decode sub-option. */
10901 char *deprecated; /* If non-null, print this message. */
10902};
10903
10904static int
10905arm_parse_extension (str, opt_p)
10906 char *str;
10907 int *opt_p;
10908{
10909 while (str != NULL && *str != 0)
10910 {
10911 struct arm_arch_extension_table *opt;
10912 char *ext;
10913 int optlen;
10914
10915 if (*str != '+')
b99bd4ef 10916 {
03b1477f
RE
10917 as_bad (_("invalid architectural extension"));
10918 return 0;
10919 }
b99bd4ef 10920
03b1477f
RE
10921 str++;
10922 ext = strchr (str, '+');
b99bd4ef 10923
03b1477f
RE
10924 if (ext != NULL)
10925 optlen = ext - str;
10926 else
10927 optlen = strlen (str);
b99bd4ef 10928
03b1477f
RE
10929 if (optlen == 0)
10930 {
10931 as_bad (_("missing architectural extension"));
10932 return 0;
10933 }
b99bd4ef 10934
03b1477f
RE
10935 for (opt = arm_extensions; opt->name != NULL; opt++)
10936 if (strncmp (opt->name, str, optlen) == 0)
10937 {
10938 *opt_p |= opt->value;
10939 break;
10940 }
bfae80f2 10941
03b1477f
RE
10942 if (opt->name == NULL)
10943 {
10944 as_bad (_("unknown architectural extnsion `%s'"), str);
10945 return 0;
10946 }
b99bd4ef 10947
03b1477f
RE
10948 str = ext;
10949 };
b99bd4ef 10950
03b1477f
RE
10951 return 1;
10952}
b99bd4ef 10953
03b1477f
RE
10954static int
10955arm_parse_cpu (str)
10956 char *str;
10957{
10958 struct arm_cpu_option_table *opt;
10959 char *ext = strchr (str, '+');
10960 int optlen;
b99bd4ef 10961
03b1477f
RE
10962 if (ext != NULL)
10963 optlen = ext - str;
10964 else
10965 optlen = strlen (str);
b99bd4ef 10966
03b1477f
RE
10967 if (optlen == 0)
10968 {
10969 as_bad (_("missing cpu name `%s'"), str);
10970 return 0;
10971 }
b99bd4ef 10972
03b1477f
RE
10973 for (opt = arm_cpus; opt->name != NULL; opt++)
10974 if (strncmp (opt->name, str, optlen) == 0)
10975 {
10976 mcpu_cpu_opt = opt->value;
10977 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 10978
03b1477f
RE
10979 if (ext != NULL)
10980 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 10981
03b1477f
RE
10982 return 1;
10983 }
b99bd4ef 10984
03b1477f
RE
10985 as_bad (_("unknown cpu `%s'"), str);
10986 return 0;
10987}
b99bd4ef 10988
03b1477f
RE
10989static int
10990arm_parse_arch (str)
10991 char *str;
10992{
10993 struct arm_arch_option_table *opt;
10994 char *ext = strchr (str, '+');
10995 int optlen;
b99bd4ef 10996
03b1477f
RE
10997 if (ext != NULL)
10998 optlen = ext - str;
10999 else
11000 optlen = strlen (str);
b99bd4ef 11001
03b1477f
RE
11002 if (optlen == 0)
11003 {
11004 as_bad (_("missing architecture name `%s'"), str);
11005 return 0;
11006 }
b99bd4ef 11007
b99bd4ef 11008
03b1477f
RE
11009 for (opt = arm_archs; opt->name != NULL; opt++)
11010 if (strcmp (opt->name, str) == 0)
11011 {
11012 march_cpu_opt = opt->value;
11013 march_fpu_opt = opt->default_fpu;
b99bd4ef 11014
03b1477f
RE
11015 if (ext != NULL)
11016 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 11017
03b1477f
RE
11018 return 1;
11019 }
b99bd4ef 11020
03b1477f
RE
11021 as_bad (_("unknown architecture `%s'\n"), str);
11022 return 0;
11023}
11024
11025static int
11026arm_parse_fpu (str)
11027 char *str;
11028{
11029 struct arm_fpu_option_table *opt;
b99bd4ef 11030
03b1477f
RE
11031 for (opt = arm_fpus; opt->name != NULL; opt++)
11032 if (strcmp (opt->name, str) == 0)
11033 {
11034 mfpu_opt = opt->value;
11035 return 1;
11036 }
b99bd4ef 11037
03b1477f
RE
11038 as_bad (_("unknown floating point format `%s'\n"), str);
11039 return 0;
11040}
b99bd4ef 11041
03b1477f
RE
11042struct arm_long_option_table arm_long_opts[] =
11043{
11044 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
11045 arm_parse_cpu, NULL},
11046 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
11047 arm_parse_arch, NULL},
11048 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
11049 arm_parse_fpu, NULL},
11050 {NULL, NULL, 0, NULL}
11051};
b99bd4ef 11052
03b1477f
RE
11053int
11054md_parse_option (c, arg)
11055 int c;
11056 char * arg;
11057{
11058 struct arm_option_table *opt;
11059 struct arm_long_option_table *lopt;
b99bd4ef 11060
03b1477f
RE
11061 switch (c)
11062 {
11063#ifdef OPTION_EB
11064 case OPTION_EB:
11065 target_big_endian = 1;
b99bd4ef 11066 break;
03b1477f 11067#endif
b99bd4ef 11068
03b1477f
RE
11069#ifdef OPTION_EL
11070 case OPTION_EL:
11071 target_big_endian = 0;
b99bd4ef
NC
11072 break;
11073#endif
11074
03b1477f 11075 case 'a':
cc8a6dd0 11076 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
11077 ones. */
11078 return 0;
11079
b99bd4ef 11080 default:
03b1477f
RE
11081 for (opt = arm_opts; opt->option != NULL; opt++)
11082 {
11083 if (c == opt->option[0]
11084 && ((arg == NULL && opt->option[1] == 0)
11085 || strcmp (arg, opt->option + 1) == 0))
11086 {
11087#if WARN_DEPRECATED
11088 /* If the option is deprecated, tell the user. */
11089 if (opt->deprecated != NULL)
11090 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
11091 arg ? arg : "", _(opt->deprecated));
11092#endif
11093
11094 if (opt->var != NULL)
11095 *opt->var = opt->value;
11096
11097 return 1;
11098 }
11099 }
11100
11101 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
11102 {
cc8a6dd0 11103 /* These options are expected to have an argument. */
03b1477f
RE
11104 if (c == lopt->option[0]
11105 && arg != NULL
cc8a6dd0 11106 && strncmp (arg, lopt->option + 1,
03b1477f
RE
11107 strlen (lopt->option + 1)) == 0)
11108 {
11109#if WARN_DEPRECATED
11110 /* If the option is deprecated, tell the user. */
11111 if (lopt->deprecated != NULL)
11112 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
11113 _(lopt->deprecated));
11114#endif
11115
11116 /* Call the sup-option parser. */
11117 return (*lopt->func)(arg + strlen (lopt->option) - 1);
11118 }
11119 }
11120
11121 as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
b99bd4ef
NC
11122 return 0;
11123 }
11124
11125 return 1;
11126}
11127
11128void
11129md_show_usage (fp)
11130 FILE * fp;
11131{
03b1477f
RE
11132 struct arm_option_table *opt;
11133 struct arm_long_option_table *lopt;
11134
11135 fprintf (fp, _(" ARM-specific assembler options:\n"));
11136
11137 for (opt = arm_opts; opt->option != NULL; opt++)
11138 if (opt->help != NULL)
11139 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
11140
11141 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
11142 if (lopt->help != NULL)
11143 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
11144
11145#ifdef OPTION_EB
b99bd4ef 11146 fprintf (fp, _("\
03b1477f 11147 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 11148#endif
03b1477f
RE
11149
11150#ifdef OPTION_EL
b99bd4ef 11151 fprintf (fp, _("\
03b1477f 11152 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
11153#endif
11154}
11155
11156/* We need to be able to fix up arbitrary expressions in some statements.
11157 This is so that we can handle symbols that are an arbitrary distance from
11158 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
11159 which returns part of an address in a form which will be valid for
11160 a data instruction. We do this by pushing the expression into a symbol
11161 in the expr_section, and creating a fix for that. */
11162
11163static void
11164fix_new_arm (frag, where, size, exp, pc_rel, reloc)
11165 fragS * frag;
11166 int where;
11167 short int size;
11168 expressionS * exp;
11169 int pc_rel;
11170 int reloc;
11171{
11172 fixS * new_fix;
11173 arm_fix_data * arm_data;
11174
11175 switch (exp->X_op)
11176 {
11177 case O_constant:
11178 case O_symbol:
11179 case O_add:
11180 case O_subtract:
11181 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
11182 break;
11183
11184 default:
11185 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
11186 pc_rel, reloc);
11187 break;
11188 }
11189
11190 /* Mark whether the fix is to a THUMB instruction, or an ARM
11191 instruction. */
11192 arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
11193 new_fix->tc_fix_data = (PTR) arm_data;
11194 arm_data->thumb_mode = thumb_mode;
11195
11196 return;
11197}
11198
11199/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
11200
11201void
11202cons_fix_new_arm (frag, where, size, exp)
11203 fragS * frag;
11204 int where;
11205 int size;
11206 expressionS * exp;
11207{
11208 bfd_reloc_code_real_type type;
11209 int pcrel = 0;
11210
11211 /* Pick a reloc.
11212 FIXME: @@ Should look at CPU word size. */
11213 switch (size)
11214 {
11215 case 1:
11216 type = BFD_RELOC_8;
11217 break;
11218 case 2:
11219 type = BFD_RELOC_16;
11220 break;
11221 case 4:
11222 default:
11223 type = BFD_RELOC_32;
11224 break;
11225 case 8:
11226 type = BFD_RELOC_64;
11227 break;
11228 }
11229
11230 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
11231}
11232
11233/* A good place to do this, although this was probably not intended
11234 for this kind of use. We need to dump the literal pool before
11235 references are made to a null symbol pointer. */
11236
11237void
11238arm_cleanup ()
11239{
3d0c9500 11240 literal_pool * pool;
b99bd4ef 11241
3d0c9500
NC
11242 for (pool = list_of_pools; pool; pool = pool->next)
11243 {
11244 /* Put it at the end of the relevent section. */
11245 subseg_set (pool->section, pool->sub_section);
11246 s_ltorg (0);
11247 }
b99bd4ef
NC
11248}
11249
11250void
11251arm_start_line_hook ()
11252{
11253 last_label_seen = NULL;
11254}
11255
11256void
11257arm_frob_label (sym)
11258 symbolS * sym;
11259{
11260 last_label_seen = sym;
11261
11262 ARM_SET_THUMB (sym, thumb_mode);
11263
11264#if defined OBJ_COFF || defined OBJ_ELF
11265 ARM_SET_INTERWORK (sym, support_interwork);
11266#endif
11267
11268 /* Note - do not allow local symbols (.Lxxx) to be labeled
11269 as Thumb functions. This is because these labels, whilst
11270 they exist inside Thumb code, are not the entry points for
11271 possible ARM->Thumb calls. Also, these labels can be used
11272 as part of a computed goto or switch statement. eg gcc
11273 can generate code that looks like this:
11274
11275 ldr r2, [pc, .Laaa]
11276 lsl r3, r3, #2
11277 ldr r2, [r3, r2]
11278 mov pc, r2
cc8a6dd0 11279
b99bd4ef
NC
11280 .Lbbb: .word .Lxxx
11281 .Lccc: .word .Lyyy
11282 ..etc...
11283 .Laaa: .word Lbbb
11284
11285 The first instruction loads the address of the jump table.
11286 The second instruction converts a table index into a byte offset.
11287 The third instruction gets the jump address out of the table.
11288 The fourth instruction performs the jump.
cc8a6dd0 11289
b99bd4ef
NC
11290 If the address stored at .Laaa is that of a symbol which has the
11291 Thumb_Func bit set, then the linker will arrange for this address
11292 to have the bottom bit set, which in turn would mean that the
11293 address computation performed by the third instruction would end
11294 up with the bottom bit set. Since the ARM is capable of unaligned
11295 word loads, the instruction would then load the incorrect address
11296 out of the jump table, and chaos would ensue. */
11297 if (label_is_thumb_function_name
11298 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
11299 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
11300 {
11301 /* When the address of a Thumb function is taken the bottom
11302 bit of that address should be set. This will allow
11303 interworking between Arm and Thumb functions to work
11304 correctly. */
11305
11306 THUMB_SET_FUNC (sym, 1);
11307
11308 label_is_thumb_function_name = false;
11309 }
11310}
11311
11312/* Adjust the symbol table. This marks Thumb symbols as distinct from
11313 ARM ones. */
11314
11315void
11316arm_adjust_symtab ()
11317{
11318#ifdef OBJ_COFF
11319 symbolS * sym;
11320
11321 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
11322 {
11323 if (ARM_IS_THUMB (sym))
11324 {
11325 if (THUMB_IS_FUNC (sym))
11326 {
11327 /* Mark the symbol as a Thumb function. */
11328 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
11329 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
11330 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
11331
11332 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
11333 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
11334 else
11335 as_bad (_("%s: unexpected function type: %d"),
11336 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
11337 }
cc8a6dd0 11338 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
11339 {
11340 case C_EXT:
11341 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
11342 break;
11343 case C_STAT:
11344 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
11345 break;
11346 case C_LABEL:
11347 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
11348 break;
11349 default:
11350 /* Do nothing. */
11351 break;
11352 }
11353 }
11354
11355 if (ARM_IS_INTERWORK (sym))
11356 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
11357 }
11358#endif
11359#ifdef OBJ_ELF
11360 symbolS * sym;
11361 char bind;
11362
11363 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
11364 {
11365 if (ARM_IS_THUMB (sym))
11366 {
11367 elf_symbol_type * elf_sym;
11368
11369 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
11370 bind = ELF_ST_BIND (elf_sym);
11371
11372 /* If it's a .thumb_func, declare it as so,
11373 otherwise tag label as .code 16. */
11374 if (THUMB_IS_FUNC (sym))
11375 elf_sym->internal_elf_sym.st_info =
11376 ELF_ST_INFO (bind, STT_ARM_TFUNC);
11377 else
11378 elf_sym->internal_elf_sym.st_info =
11379 ELF_ST_INFO (bind, STT_ARM_16BIT);
11380 }
11381 }
11382#endif
11383}
11384
11385int
11386arm_data_in_code ()
11387{
11388 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
11389 {
11390 *input_line_pointer = '/';
11391 input_line_pointer += 5;
11392 *input_line_pointer = 0;
11393 return 1;
11394 }
11395
11396 return 0;
11397}
11398
11399char *
11400arm_canonicalize_symbol_name (name)
11401 char * name;
11402{
11403 int len;
11404
11405 if (thumb_mode && (len = strlen (name)) > 5
11406 && streq (name + len - 5, "/data"))
11407 *(name + len - 5) = 0;
11408
11409 return name;
11410}
11411
a161fe53 11412void
b99bd4ef
NC
11413arm_validate_fix (fixP)
11414 fixS * fixP;
11415{
11416 /* If the destination of the branch is a defined symbol which does not have
11417 the THUMB_FUNC attribute, then we must be calling a function which has
11418 the (interfacearm) attribute. We look for the Thumb entry point to that
11419 function and change the branch to refer to that function instead. */
11420 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
11421 && fixP->fx_addsy != NULL
11422 && S_IS_DEFINED (fixP->fx_addsy)
11423 && ! THUMB_IS_FUNC (fixP->fx_addsy))
11424 {
11425 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 11426 }
b99bd4ef
NC
11427}
11428
11429#ifdef OBJ_COFF
11430/* This is a little hack to help the gas/arm/adrl.s test. It prevents
11431 local labels from being added to the output symbol table when they
11432 are used with the ADRL pseudo op. The ADRL relocation should always
11433 be resolved before the binbary is emitted, so it is safe to say that
11434 it is adjustable. */
11435
11436boolean
11437arm_fix_adjustable (fixP)
11438 fixS * fixP;
11439{
11440 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
11441 return 1;
11442 return 0;
11443}
11444#endif
11445#ifdef OBJ_ELF
11446/* Relocations against Thumb function names must be left unadjusted,
11447 so that the linker can use this information to correctly set the
11448 bottom bit of their addresses. The MIPS version of this function
11449 also prevents relocations that are mips-16 specific, but I do not
11450 know why it does this.
11451
11452 FIXME:
11453 There is one other problem that ought to be addressed here, but
11454 which currently is not: Taking the address of a label (rather
11455 than a function) and then later jumping to that address. Such
11456 addresses also ought to have their bottom bit set (assuming that
11457 they reside in Thumb code), but at the moment they will not. */
11458
11459boolean
11460arm_fix_adjustable (fixP)
11461 fixS * fixP;
11462{
11463 if (fixP->fx_addsy == NULL)
11464 return 1;
11465
b99bd4ef
NC
11466 if (THUMB_IS_FUNC (fixP->fx_addsy)
11467 && fixP->fx_subsy == NULL)
11468 return 0;
11469
11470 /* We need the symbol name for the VTABLE entries. */
11471 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
11472 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11473 return 0;
11474
a161fe53
AM
11475 /* Don't allow symbols to be discarded on GOT related relocs. */
11476 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
11477 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
11478 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
11479 return 0;
11480
b99bd4ef
NC
11481 return 1;
11482}
11483
11484const char *
11485elf32_arm_target_format ()
11486{
11487 if (target_big_endian)
11488 {
11489 if (target_oabi)
11490 return "elf32-bigarm-oabi";
11491 else
11492 return "elf32-bigarm";
11493 }
11494 else
11495 {
11496 if (target_oabi)
11497 return "elf32-littlearm-oabi";
11498 else
11499 return "elf32-littlearm";
11500 }
11501}
11502
11503void
11504armelf_frob_symbol (symp, puntp)
11505 symbolS * symp;
11506 int * puntp;
11507{
11508 elf_frob_symbol (symp, puntp);
11509}
11510
11511int
11512arm_force_relocation (fixp)
11513 struct fix * fixp;
11514{
11515 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
11516 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
11517 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
11518 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
11519 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
11520 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
11521 return 1;
11522
a161fe53 11523 return S_FORCE_RELOC (fixp->fx_addsy);
b99bd4ef
NC
11524}
11525
11526static bfd_reloc_code_real_type
11527arm_parse_reloc ()
11528{
11529 char id [16];
11530 char * ip;
11531 unsigned int i;
11532 static struct
11533 {
11534 char * str;
11535 int len;
11536 bfd_reloc_code_real_type reloc;
11537 }
11538 reloc_map[] =
11539 {
11540#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
11541 MAP ("(got)", BFD_RELOC_ARM_GOT32),
11542 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
11543 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
11544 branch instructions generated by GCC for PLT relocs. */
11545 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
11546 { NULL, 0, BFD_RELOC_UNUSED }
11547#undef MAP
11548 };
11549
11550 for (i = 0, ip = input_line_pointer;
3882b010 11551 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
b99bd4ef 11552 i++, ip++)
3882b010 11553 id[i] = TOLOWER (*ip);
b99bd4ef
NC
11554
11555 for (i = 0; reloc_map[i].str; i++)
11556 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
11557 break;
11558
11559 input_line_pointer += reloc_map[i].len;
11560
11561 return reloc_map[i].reloc;
11562}
11563
11564static void
11565s_arm_elf_cons (nbytes)
11566 int nbytes;
11567{
11568 expressionS exp;
11569
11570#ifdef md_flush_pending_output
11571 md_flush_pending_output ();
11572#endif
11573
11574 if (is_it_end_of_statement ())
11575 {
11576 demand_empty_rest_of_line ();
11577 return;
11578 }
11579
11580#ifdef md_cons_align
11581 md_cons_align (nbytes);
11582#endif
11583
11584 do
11585 {
11586 bfd_reloc_code_real_type reloc;
11587
11588 expression (& exp);
11589
11590 if (exp.X_op == O_symbol
11591 && * input_line_pointer == '('
11592 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
11593 {
11594 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
11595 int size = bfd_get_reloc_size (howto);
11596
11597 if (size > nbytes)
11598 as_bad ("%s relocations do not fit in %d bytes",
11599 howto->name, nbytes);
11600 else
11601 {
11602 register char *p = frag_more ((int) nbytes);
11603 int offset = nbytes - size;
11604
11605 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
11606 &exp, 0, reloc);
11607 }
11608 }
11609 else
11610 emit_expr (&exp, (unsigned int) nbytes);
11611 }
11612 while (*input_line_pointer++ == ',');
11613
11614 /* Put terminator back into stream. */
11615 input_line_pointer --;
11616 demand_empty_rest_of_line ();
11617}
11618
11619#endif /* OBJ_ELF */
11620
11621/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
11622 of an rs_align_code fragment. */
11623
11624void
11625arm_handle_align (fragP)
11626 fragS *fragP;
11627{
11628 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
11629 static char const thumb_noop[2] = { 0xc0, 0x46 };
11630 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
11631 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
11632
11633 int bytes, fix, noop_size;
11634 char * p;
11635 const char * noop;
cc8a6dd0 11636
b99bd4ef
NC
11637 if (fragP->fr_type != rs_align_code)
11638 return;
11639
11640 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
11641 p = fragP->fr_literal + fragP->fr_fix;
11642 fix = 0;
cc8a6dd0 11643
b99bd4ef
NC
11644 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
11645 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 11646
b99bd4ef
NC
11647 if (fragP->tc_frag_data)
11648 {
11649 if (target_big_endian)
11650 noop = thumb_bigend_noop;
11651 else
11652 noop = thumb_noop;
11653 noop_size = sizeof (thumb_noop);
11654 }
11655 else
11656 {
11657 if (target_big_endian)
11658 noop = arm_bigend_noop;
11659 else
11660 noop = arm_noop;
11661 noop_size = sizeof (arm_noop);
11662 }
cc8a6dd0 11663
b99bd4ef
NC
11664 if (bytes & (noop_size - 1))
11665 {
11666 fix = bytes & (noop_size - 1);
11667 memset (p, 0, fix);
11668 p += fix;
11669 bytes -= fix;
11670 }
11671
11672 while (bytes >= noop_size)
11673 {
11674 memcpy (p, noop, noop_size);
11675 p += noop_size;
11676 bytes -= noop_size;
11677 fix += noop_size;
11678 }
cc8a6dd0 11679
b99bd4ef
NC
11680 fragP->fr_fix += fix;
11681 fragP->fr_var = noop_size;
11682}
11683
11684/* Called from md_do_align. Used to create an alignment
11685 frag in a code section. */
11686
11687void
11688arm_frag_align_code (n, max)
11689 int n;
11690 int max;
11691{
11692 char * p;
11693
11694 /* We assume that there will never be a requirment
11695 to support alignments greater than 32 bytes. */
11696 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
11697 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 11698
b99bd4ef
NC
11699 p = frag_var (rs_align_code,
11700 MAX_MEM_FOR_RS_ALIGN_CODE,
11701 1,
11702 (relax_substateT) max,
11703 (symbolS *) NULL,
11704 (offsetT) n,
11705 (char *) NULL);
11706 *p = 0;
11707
11708}
11709
11710/* Perform target specific initialisation of a frag. */
11711
11712void
11713arm_init_frag (fragP)
11714 fragS *fragP;
11715{
11716 /* Record whether this frag is in an ARM or a THUMB area. */
11717 fragP->tc_frag_data = thumb_mode;
11718}