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