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