Add ARM CFI support
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
69b97547 2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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)
34920d91
NC
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
b99bd4ef
NC
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
b99bd4ef
NC
27#include <string.h>
28#define NO_RELOC 0
29#include "as.h"
3882b010 30#include "safe-ctype.h"
b99bd4ef
NC
31
32/* Need TARGET_CPU. */
33#include "config.h"
34#include "subsegs.h"
35#include "obstack.h"
36#include "symbols.h"
37#include "listing.h"
38
f263249b
RE
39#include "opcode/arm.h"
40
b99bd4ef
NC
41#ifdef OBJ_ELF
42#include "elf/arm.h"
43#include "dwarf2dbg.h"
a394c00f 44#include "dw2gencfi.h"
b99bd4ef
NC
45#endif
46
7ed4c4c5 47/* XXX Set this to 1 after the next binutils release. */
03b1477f
RE
48#define WARN_DEPRECATED 0
49
7ed4c4c5
NC
50#ifdef OBJ_ELF
51/* Must be at least the size of the largest unwind opcode (currently two). */
52#define ARM_OPCODE_CHUNK_SIZE 8
53
54/* This structure holds the unwinding state. */
55
56static struct
57{
58 symbolS * proc_start;
59 symbolS * table_entry;
60 symbolS * personality_routine;
61 int personality_index;
62 /* The segment containing the function. */
63 segT saved_seg;
64 subsegT saved_subseg;
65 /* Opcodes generated from this function. */
66 unsigned char * opcodes;
67 int opcode_count;
68 int opcode_alloc;
69 /* The number of bytes pushed to the stack. */
70 offsetT frame_size;
71 /* We don't add stack adjustment opcodes immediately so that we can merge
72 multiple adjustments. We can also omit the final adjustment
73 when using a frame pointer. */
74 offsetT pending_offset;
75 /* These two fields are set by both unwind_movsp and unwind_setfp. They
76 hold the reg+offset to use when restoring sp from a frame pointer. */
77 offsetT fp_offset;
78 int fp_reg;
79 /* Nonzero if an unwind_setfp directive has been seen. */
80 unsigned fp_used:1;
81 /* Nonzero if the last opcode restores sp from fp_reg. */
82 unsigned sp_restored:1;
83} unwind;
84
85#endif /* OBJ_ELF */
86
33a392fb
PB
87enum arm_float_abi
88{
89 ARM_FLOAT_ABI_HARD,
90 ARM_FLOAT_ABI_SOFTFP,
91 ARM_FLOAT_ABI_SOFT
92};
93
b89dddec
RE
94/* Types of processor to assemble for. */
95#define ARM_1 ARM_ARCH_V1
96#define ARM_2 ARM_ARCH_V2
97#define ARM_3 ARM_ARCH_V2S
98#define ARM_250 ARM_ARCH_V2S
99#define ARM_6 ARM_ARCH_V3
100#define ARM_7 ARM_ARCH_V3
101#define ARM_8 ARM_ARCH_V4
102#define ARM_9 ARM_ARCH_V4T
103#define ARM_STRONG ARM_ARCH_V4
104#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
105
106#ifndef CPU_DEFAULT
107#if defined __XSCALE__
b89dddec 108#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
109#else
110#if defined __thumb__
b89dddec 111#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 112#else
03b1477f 113#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
114#endif
115#endif
116#endif
117
39c2da32
RE
118#ifdef TE_LINUX
119#define FPU_DEFAULT FPU_ARCH_FPA
120#endif
121
122#ifdef TE_NetBSD
123#ifdef OBJ_ELF
124#define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
125#else
126/* Legacy a.out format. */
127#define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
128#endif
129#endif
130
bfae80f2 131/* For backwards compatibility we default to the FPA. */
b99bd4ef 132#ifndef FPU_DEFAULT
b89dddec 133#define FPU_DEFAULT FPU_ARCH_FPA
b99bd4ef
NC
134#endif
135
136#define streq(a, b) (strcmp (a, b) == 0)
137#define skip_whitespace(str) while (*(str) == ' ') ++(str)
138
03b1477f 139static unsigned long cpu_variant;
b99bd4ef
NC
140static int target_oabi = 0;
141
b99bd4ef 142/* Flags stored in private area of BFD structure. */
b34976b6
AM
143static int uses_apcs_26 = FALSE;
144static int atpcs = FALSE;
145static int support_interwork = FALSE;
146static int uses_apcs_float = FALSE;
147static int pic_code = FALSE;
03b1477f
RE
148
149/* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
151 assembly flags. */
152static int legacy_cpu = -1;
153static int legacy_fpu = -1;
154
155static int mcpu_cpu_opt = -1;
156static int mcpu_fpu_opt = -1;
157static int march_cpu_opt = -1;
158static int march_fpu_opt = -1;
159static int mfpu_opt = -1;
33a392fb 160static int mfloat_abi_opt = -1;
7cc69913 161#ifdef OBJ_ELF
d507cf36 162static int meabi_flags = EF_ARM_EABI_UNKNOWN;
7cc69913 163#endif
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
09d92015 276/* Any kind of shift is accepted. */
b99bd4ef 277#define NO_SHIFT_RESTRICT 1
09d92015
MM
278/* The shift operand must be an immediate value, not a register. */
279#define SHIFT_IMMEDIATE 0
280/* The shift must be LSL or ASR and the operand must be an immediate. */
281#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
282/* The shift must be ASR and the operand must be an immediate. */
283#define SHIFT_ASR_IMMEDIATE 3
284/* The shift must be LSL and the operand must be an immediate. */
285#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
286
287#define NUM_FLOAT_VALS 8
288
05d2d07e 289const char * fp_const[] =
b99bd4ef
NC
290{
291 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
292};
293
294/* Number of littlenums required to hold an extended precision number. */
295#define MAX_LITTLENUMS 6
296
297LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
298
299#define FAIL (-1)
300#define SUCCESS (0)
301
bfae80f2
RE
302/* Whether a Co-processor load/store operation accepts write-back forms. */
303#define CP_WB_OK 1
304#define CP_NO_WB 0
305
b99bd4ef
NC
306#define SUFF_S 1
307#define SUFF_D 2
308#define SUFF_E 3
309#define SUFF_P 4
310
311#define CP_T_X 0x00008000
312#define CP_T_Y 0x00400000
313#define CP_T_Pre 0x01000000
314#define CP_T_UD 0x00800000
315#define CP_T_WB 0x00200000
316
317#define CONDS_BIT 0x00100000
318#define LOAD_BIT 0x00100000
b99bd4ef
NC
319
320#define DOUBLE_LOAD_FLAG 0x00000001
321
322struct asm_cond
323{
05d2d07e 324 const char * template;
b99bd4ef
NC
325 unsigned long value;
326};
327
b99bd4ef 328#define COND_ALWAYS 0xe0000000
90e4755a 329#define COND_MASK 0xf0000000
b99bd4ef 330
05d2d07e 331static const struct asm_cond conds[] =
b99bd4ef
NC
332{
333 {"eq", 0x00000000},
334 {"ne", 0x10000000},
335 {"cs", 0x20000000}, {"hs", 0x20000000},
336 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
337 {"mi", 0x40000000},
338 {"pl", 0x50000000},
339 {"vs", 0x60000000},
340 {"vc", 0x70000000},
341 {"hi", 0x80000000},
342 {"ls", 0x90000000},
343 {"ge", 0xa0000000},
344 {"lt", 0xb0000000},
345 {"gt", 0xc0000000},
346 {"le", 0xd0000000},
347 {"al", 0xe0000000},
348 {"nv", 0xf0000000}
349};
350
b99bd4ef
NC
351struct asm_psr
352{
b34976b6
AM
353 const char *template;
354 bfd_boolean cpsr;
b99bd4ef
NC
355 unsigned long field;
356};
357
2d2255b5 358/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
359#define SPSR_BIT (1 << 22)
360
361/* How many bits to shift the PSR_xxx bits up by. */
362#define PSR_SHIFT 16
363
364#define PSR_c (1 << 0)
365#define PSR_x (1 << 1)
366#define PSR_s (1 << 2)
367#define PSR_f (1 << 3)
368
05d2d07e 369static const struct asm_psr psrs[] =
b99bd4ef 370{
b34976b6
AM
371 {"CPSR", TRUE, PSR_c | PSR_f},
372 {"CPSR_all", TRUE, PSR_c | PSR_f},
373 {"SPSR", FALSE, PSR_c | PSR_f},
374 {"SPSR_all", FALSE, PSR_c | PSR_f},
375 {"CPSR_flg", TRUE, PSR_f},
376 {"CPSR_f", TRUE, PSR_f},
377 {"SPSR_flg", FALSE, PSR_f},
378 {"SPSR_f", FALSE, PSR_f},
379 {"CPSR_c", TRUE, PSR_c},
380 {"CPSR_ctl", TRUE, PSR_c},
381 {"SPSR_c", FALSE, PSR_c},
382 {"SPSR_ctl", FALSE, PSR_c},
383 {"CPSR_x", TRUE, PSR_x},
384 {"CPSR_s", TRUE, PSR_s},
385 {"SPSR_x", FALSE, PSR_x},
386 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 387 /* Combinations of flags. */
b34976b6
AM
388 {"CPSR_fs", TRUE, PSR_f | PSR_s},
389 {"CPSR_fx", TRUE, PSR_f | PSR_x},
390 {"CPSR_fc", TRUE, PSR_f | PSR_c},
391 {"CPSR_sf", TRUE, PSR_s | PSR_f},
392 {"CPSR_sx", TRUE, PSR_s | PSR_x},
393 {"CPSR_sc", TRUE, PSR_s | PSR_c},
394 {"CPSR_xf", TRUE, PSR_x | PSR_f},
395 {"CPSR_xs", TRUE, PSR_x | PSR_s},
396 {"CPSR_xc", TRUE, PSR_x | PSR_c},
397 {"CPSR_cf", TRUE, PSR_c | PSR_f},
398 {"CPSR_cs", TRUE, PSR_c | PSR_s},
399 {"CPSR_cx", TRUE, PSR_c | PSR_x},
400 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
401 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
402 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
403 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
404 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
405 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
406 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
407 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
408 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
409 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
410 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
411 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
412 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
413 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
414 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
415 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
416 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
417 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
418 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
419 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
420 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
421 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
422 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
423 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
424 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
425 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
426 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
427 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
428 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
429 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
430 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
431 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
432 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
433 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
434 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
435 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
436 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
437 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
438 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
439 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
440 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
441 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
442 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
443 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
444 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
445 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
446 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
447 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
448 {"SPSR_fs", FALSE, PSR_f | PSR_s},
449 {"SPSR_fx", FALSE, PSR_f | PSR_x},
450 {"SPSR_fc", FALSE, PSR_f | PSR_c},
451 {"SPSR_sf", FALSE, PSR_s | PSR_f},
452 {"SPSR_sx", FALSE, PSR_s | PSR_x},
453 {"SPSR_sc", FALSE, PSR_s | PSR_c},
454 {"SPSR_xf", FALSE, PSR_x | PSR_f},
455 {"SPSR_xs", FALSE, PSR_x | PSR_s},
456 {"SPSR_xc", FALSE, PSR_x | PSR_c},
457 {"SPSR_cf", FALSE, PSR_c | PSR_f},
458 {"SPSR_cs", FALSE, PSR_c | PSR_s},
459 {"SPSR_cx", FALSE, PSR_c | PSR_x},
460 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
461 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
462 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
463 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
464 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
465 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
466 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
467 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
468 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
469 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
470 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
471 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
472 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
473 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
474 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
475 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
476 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
477 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
478 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
479 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
480 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
481 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
482 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
483 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
484 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
485 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
486 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
487 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
488 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
489 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
490 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
491 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
492 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
493 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
494 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
495 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
496 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
497 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
498 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
499 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
500 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
501 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
502 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
503 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
504 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
505 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
506 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
507 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
508};
509
e16bb312
NC
510enum wreg_type
511 {
512 IWMMXT_REG_WR = 0,
513 IWMMXT_REG_WC = 1,
514 IWMMXT_REG_WR_OR_WC = 2,
515 IWMMXT_REG_WCG
516 };
517
518enum iwmmxt_insn_type
519{
520 check_rd,
521 check_wr,
522 check_wrwr,
523 check_wrwrwr,
524 check_wrwrwcg,
525 check_tbcst,
526 check_tmovmsk,
527 check_tmia,
528 check_tmcrr,
529 check_tmrrc,
530 check_tmcr,
531 check_tmrc,
532 check_tinsr,
533 check_textrc,
534 check_waligni,
535 check_textrm,
536 check_wshufh
537};
538
bfae80f2
RE
539enum vfp_dp_reg_pos
540{
541 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
542};
543
544enum vfp_sp_reg_pos
545{
546 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
547};
548
549enum vfp_ldstm_type
550{
551 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
552};
553
554/* VFP system registers. */
555struct vfp_reg
556{
557 const char *name;
558 unsigned long regno;
559};
560
cc8a6dd0 561static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
562{
563 {"fpsid", 0x00000000},
564 {"FPSID", 0x00000000},
565 {"fpscr", 0x00010000},
566 {"FPSCR", 0x00010000},
567 {"fpexc", 0x00080000},
568 {"FPEXC", 0x00080000}
569};
570
6c43fab6
RE
571/* Structure for a hash table entry for a register. */
572struct reg_entry
573{
574 const char * name;
575 int number;
0bbf2aa4 576 bfd_boolean builtin;
6c43fab6
RE
577};
578
e28cd48c 579/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
580#define REG_SP 13
581#define REG_LR 14
582#define REG_PC 15
583
e16bb312
NC
584#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
585#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
586#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
587
0bbf2aa4
NC
588/* These are the standard names. Users can add aliases with .req.
589 and delete them with .unreq. */
590
6c43fab6
RE
591/* Integer Register Numbers. */
592static const struct reg_entry rn_table[] =
593{
0bbf2aa4
NC
594 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
595 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
596 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
597 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 598 /* ATPCS Synonyms. */
0bbf2aa4
NC
599 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
600 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
601 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 602 /* Well-known aliases. */
0bbf2aa4
NC
603 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
604 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
605 {NULL, 0, TRUE}
6c43fab6
RE
606};
607
e16bb312
NC
608#define WR_PREFIX 0x200
609#define WC_PREFIX 0x400
610
611static const struct reg_entry iwmmxt_table[] =
612{
5a6c6817 613 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
614 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
615 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
616 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
617 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
618 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
619 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
620 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
621 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
622 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
623 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
624 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
625 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
626
627 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
628 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
629 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
630 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
631 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
632 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
633 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
634 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
635 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
636 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
637 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
638 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
639 {NULL, 0, TRUE}
e16bb312
NC
640};
641
6c43fab6
RE
642/* Co-processor Numbers. */
643static const struct reg_entry cp_table[] =
644{
0bbf2aa4
NC
645 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
646 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
647 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
648 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
649 {NULL, 0, TRUE}
6c43fab6
RE
650};
651
652/* Co-processor Register Numbers. */
653static const struct reg_entry cn_table[] =
654{
0bbf2aa4
NC
655 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
656 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
657 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
658 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 659 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
660 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
661 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
662 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
663 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
664 {NULL, 0, TRUE}
6c43fab6
RE
665};
666
667/* FPA Registers. */
668static const struct reg_entry fn_table[] =
669{
0bbf2aa4
NC
670 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
671 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
672 {NULL, 0, TRUE}
6c43fab6
RE
673};
674
bfae80f2
RE
675/* VFP SP Registers. */
676static const struct reg_entry sn_table[] =
677{
0bbf2aa4
NC
678 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
679 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
680 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
681 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
682 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
683 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
684 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
685 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
686 {NULL, 0, TRUE}
bfae80f2
RE
687};
688
689/* VFP DP Registers. */
690static const struct reg_entry dn_table[] =
691{
0bbf2aa4
NC
692 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
693 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
694 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
695 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
696 {NULL, 0, TRUE}
bfae80f2
RE
697};
698
63e63b07 699/* Maverick DSP coprocessor registers. */
6c43fab6
RE
700static const struct reg_entry mav_mvf_table[] =
701{
0bbf2aa4
NC
702 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
703 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
704 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
705 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
706 {NULL, 0, TRUE}
6c43fab6
RE
707};
708
709static const struct reg_entry mav_mvd_table[] =
710{
0bbf2aa4
NC
711 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
712 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
713 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
714 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
715 {NULL, 0, TRUE}
6c43fab6
RE
716};
717
718static const struct reg_entry mav_mvfx_table[] =
719{
0bbf2aa4
NC
720 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
721 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
722 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
723 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
724 {NULL, 0, TRUE}
6c43fab6
RE
725};
726
727static const struct reg_entry mav_mvdx_table[] =
728{
0bbf2aa4
NC
729 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
730 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
731 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
732 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
733 {NULL, 0, TRUE}
6c43fab6
RE
734};
735
736static const struct reg_entry mav_mvax_table[] =
737{
0bbf2aa4
NC
738 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
739 {NULL, 0, TRUE}
6c43fab6
RE
740};
741
742static const struct reg_entry mav_dspsc_table[] =
743{
0bbf2aa4
NC
744 {"dspsc", 0, TRUE},
745 {NULL, 0, TRUE}
6c43fab6
RE
746};
747
748struct reg_map
749{
a737bd4d
NC
750 const struct reg_entry * names;
751 int max_regno;
752 struct hash_control * htab;
753 const char * expected;
6c43fab6
RE
754};
755
756struct reg_map all_reg_maps[] =
757{
758 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
759 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
760 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 761 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
762 {sn_table, 31, NULL, N_("VFP single precision register expected")},
763 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
764 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
765 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
766 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 767 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
768 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
769 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 770 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
771};
772
773/* Enumeration matching entries in table above. */
774enum arm_reg_type
775{
776 REG_TYPE_RN = 0,
777#define REG_TYPE_FIRST REG_TYPE_RN
778 REG_TYPE_CP = 1,
779 REG_TYPE_CN = 2,
780 REG_TYPE_FN = 3,
bfae80f2
RE
781 REG_TYPE_SN = 4,
782 REG_TYPE_DN = 5,
783 REG_TYPE_MVF = 6,
784 REG_TYPE_MVD = 7,
785 REG_TYPE_MVFX = 8,
786 REG_TYPE_MVDX = 9,
787 REG_TYPE_MVAX = 10,
788 REG_TYPE_DSPSC = 11,
e16bb312 789 REG_TYPE_IWMMXT = 12,
bfae80f2 790
e16bb312 791 REG_TYPE_MAX = 13
6c43fab6 792};
404ff6b5 793
b99bd4ef
NC
794/* ARM instructions take 4bytes in the object file, Thumb instructions
795 take 2: */
796#define INSN_SIZE 4
797
404ff6b5 798/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 799#define MAV_MODE1 0x100c
404ff6b5
AH
800
801/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 802#define MAV_MODE2 0x0c10
404ff6b5 803
34920d91
NC
804/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
805#define MAV_MODE3 0x100c
404ff6b5
AH
806
807/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 808#define MAV_MODE4 0x0c0010
404ff6b5
AH
809
810/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 811#define MAV_MODE5 0x00100c
404ff6b5
AH
812
813/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 814#define MAV_MODE6 0x00100c05
b99bd4ef
NC
815
816struct asm_opcode
817{
818 /* Basic string to match. */
05d2d07e 819 const char * template;
b99bd4ef
NC
820
821 /* Basic instruction code. */
822 unsigned long value;
823
90e4755a
RE
824 /* Offset into the template where the condition code (if any) will be.
825 If zero, then the instruction is never conditional. */
826 unsigned cond_offset;
b99bd4ef 827
90e4755a
RE
828 /* Which architecture variant provides this instruction. */
829 unsigned long variant;
b99bd4ef
NC
830
831 /* Function to call to parse args. */
a737bd4d 832 void (* parms) (char *);
b99bd4ef
NC
833};
834
a737bd4d
NC
835/* Defines for various bits that we will want to toggle. */
836#define INST_IMMEDIATE 0x02000000
837#define OFFSET_REG 0x02000000
838#define HWOFFSET_IMM 0x00400000
839#define SHIFT_BY_REG 0x00000010
840#define PRE_INDEX 0x01000000
841#define INDEX_UP 0x00800000
842#define WRITE_BACK 0x00200000
843#define LDM_TYPE_2_OR_3 0x00400000
90e4755a 844
a737bd4d
NC
845#define LITERAL_MASK 0xf000f000
846#define OPCODE_MASK 0xfe1fffff
847#define V4_STR_BIT 0x00000020
90e4755a 848
a737bd4d 849#define DATA_OP_SHIFT 21
90e4755a 850
a737bd4d
NC
851/* Codes to distinguish the arithmetic instructions. */
852#define OPCODE_AND 0
853#define OPCODE_EOR 1
854#define OPCODE_SUB 2
855#define OPCODE_RSB 3
856#define OPCODE_ADD 4
857#define OPCODE_ADC 5
858#define OPCODE_SBC 6
859#define OPCODE_RSC 7
860#define OPCODE_TST 8
861#define OPCODE_TEQ 9
862#define OPCODE_CMP 10
863#define OPCODE_CMN 11
864#define OPCODE_ORR 12
865#define OPCODE_MOV 13
866#define OPCODE_BIC 14
867#define OPCODE_MVN 15
90e4755a 868
a737bd4d
NC
869#define T_OPCODE_MUL 0x4340
870#define T_OPCODE_TST 0x4200
871#define T_OPCODE_CMN 0x42c0
872#define T_OPCODE_NEG 0x4240
873#define T_OPCODE_MVN 0x43c0
90e4755a 874
a737bd4d
NC
875#define T_OPCODE_ADD_R3 0x1800
876#define T_OPCODE_SUB_R3 0x1a00
877#define T_OPCODE_ADD_HI 0x4400
878#define T_OPCODE_ADD_ST 0xb000
879#define T_OPCODE_SUB_ST 0xb080
880#define T_OPCODE_ADD_SP 0xa800
881#define T_OPCODE_ADD_PC 0xa000
882#define T_OPCODE_ADD_I8 0x3000
883#define T_OPCODE_SUB_I8 0x3800
884#define T_OPCODE_ADD_I3 0x1c00
885#define T_OPCODE_SUB_I3 0x1e00
b99bd4ef 886
a737bd4d
NC
887#define T_OPCODE_ASR_R 0x4100
888#define T_OPCODE_LSL_R 0x4080
889#define T_OPCODE_LSR_R 0x40c0
890#define T_OPCODE_ASR_I 0x1000
891#define T_OPCODE_LSL_I 0x0000
892#define T_OPCODE_LSR_I 0x0800
b99bd4ef 893
a737bd4d
NC
894#define T_OPCODE_MOV_I8 0x2000
895#define T_OPCODE_CMP_I8 0x2800
896#define T_OPCODE_CMP_LR 0x4280
897#define T_OPCODE_MOV_HR 0x4600
898#define T_OPCODE_CMP_HR 0x4500
b99bd4ef 899
a737bd4d
NC
900#define T_OPCODE_LDR_PC 0x4800
901#define T_OPCODE_LDR_SP 0x9800
902#define T_OPCODE_STR_SP 0x9000
903#define T_OPCODE_LDR_IW 0x6800
904#define T_OPCODE_STR_IW 0x6000
905#define T_OPCODE_LDR_IH 0x8800
906#define T_OPCODE_STR_IH 0x8000
907#define T_OPCODE_LDR_IB 0x7800
908#define T_OPCODE_STR_IB 0x7000
909#define T_OPCODE_LDR_RW 0x5800
910#define T_OPCODE_STR_RW 0x5000
911#define T_OPCODE_LDR_RH 0x5a00
912#define T_OPCODE_STR_RH 0x5200
913#define T_OPCODE_LDR_RB 0x5c00
914#define T_OPCODE_STR_RB 0x5400
c9b604bd 915
a737bd4d
NC
916#define T_OPCODE_PUSH 0xb400
917#define T_OPCODE_POP 0xbc00
b99bd4ef 918
a737bd4d 919#define T_OPCODE_BRANCH 0xe7fe
b99bd4ef 920
a737bd4d
NC
921#define THUMB_SIZE 2 /* Size of thumb instruction. */
922#define THUMB_REG_LO 0x1
923#define THUMB_REG_HI 0x2
924#define THUMB_REG_ANY 0x3
90e4755a 925
a737bd4d
NC
926#define THUMB_H1 0x0080
927#define THUMB_H2 0x0040
b99bd4ef 928
a737bd4d
NC
929#define THUMB_ASR 0
930#define THUMB_LSL 1
931#define THUMB_LSR 2
90e4755a 932
a737bd4d
NC
933#define THUMB_MOVE 0
934#define THUMB_COMPARE 1
935#define THUMB_CPY 2
90e4755a 936
a737bd4d
NC
937#define THUMB_LOAD 0
938#define THUMB_STORE 1
90e4755a 939
a737bd4d 940#define THUMB_PP_PC_LR 0x0100
90e4755a 941
a737bd4d
NC
942/* These three are used for immediate shifts, do not alter. */
943#define THUMB_WORD 2
944#define THUMB_HALFWORD 1
945#define THUMB_BYTE 0
90e4755a 946
a737bd4d
NC
947struct thumb_opcode
948{
949 /* Basic string to match. */
950 const char * template;
90e4755a 951
a737bd4d
NC
952 /* Basic instruction code. */
953 unsigned long value;
90e4755a 954
a737bd4d 955 int size;
b99bd4ef
NC
956
957 /* Which CPU variants this exists for. */
90e4755a 958 unsigned long variant;
b99bd4ef
NC
959
960 /* Function to call to parse args. */
a737bd4d 961 void (* parms) (char *);
b99bd4ef
NC
962};
963
f03698e6 964#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 965#define BAD_PC _("r15 not allowed here")
f03698e6 966#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
967#define ERR_NO_ACCUM _("acc0 expected")
968
969static struct hash_control * arm_ops_hsh = NULL;
970static struct hash_control * arm_tops_hsh = NULL;
971static struct hash_control * arm_cond_hsh = NULL;
972static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
973static struct hash_control * arm_psr_hsh = NULL;
974
b99bd4ef
NC
975/* Stuff needed to resolve the label ambiguity
976 As:
977 ...
978 label: <insn>
979 may differ from:
980 ...
981 label:
982 <insn>
983*/
984
985symbolS * last_label_seen;
b34976b6 986static int label_is_thumb_function_name = FALSE;
a737bd4d 987\f
3d0c9500 988/* Literal Pool stuff. */
b99bd4ef
NC
989
990#define MAX_LITERAL_POOL_SIZE 1024
991
3d0c9500
NC
992/* Literal pool structure. Held on a per-section
993 and per-sub-section basis. */
a737bd4d 994
3d0c9500 995typedef struct literal_pool
b99bd4ef 996{
3d0c9500
NC
997 expressionS literals [MAX_LITERAL_POOL_SIZE];
998 unsigned int next_free_entry;
999 unsigned int id;
1000 symbolS * symbol;
1001 segT section;
1002 subsegT sub_section;
61b5f74b 1003 struct literal_pool * next;
3d0c9500 1004} literal_pool;
b99bd4ef 1005
3d0c9500
NC
1006/* Pointer to a linked list of literal pools. */
1007literal_pool * list_of_pools = NULL;
b99bd4ef 1008
3d0c9500 1009static literal_pool *
a737bd4d 1010find_literal_pool (void)
3d0c9500
NC
1011{
1012 literal_pool * pool;
1013
1014 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1015 {
1016 if (pool->section == now_seg
1017 && pool->sub_section == now_subseg)
1018 break;
1019 }
1020
1021 return pool;
1022}
b99bd4ef 1023
3d0c9500 1024static literal_pool *
a737bd4d 1025find_or_make_literal_pool (void)
3d0c9500
NC
1026{
1027 /* Next literal pool ID number. */
1028 static unsigned int latest_pool_num = 1;
1029 literal_pool * pool;
1030
1031 pool = find_literal_pool ();
b99bd4ef 1032
3d0c9500
NC
1033 if (pool == NULL)
1034 {
1035 /* Create a new pool. */
a737bd4d 1036 pool = xmalloc (sizeof (* pool));
3d0c9500
NC
1037 if (! pool)
1038 return NULL;
1039
1040 pool->next_free_entry = 0;
1041 pool->section = now_seg;
1042 pool->sub_section = now_subseg;
1043 pool->next = list_of_pools;
1044 pool->symbol = NULL;
1045
1046 /* Add it to the list. */
1047 list_of_pools = pool;
1048 }
1049
1050 /* New pools, and emptied pools, will have a NULL symbol. */
1051 if (pool->symbol == NULL)
1052 {
1053 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1054 (valueT) 0, &zero_address_frag);
1055 pool->id = latest_pool_num ++;
1056 }
1057
1058 /* Done. */
1059 return pool;
1060}
1061
1062/* Add the literal in the global 'inst'
1063 structure to the relevent literal pool. */
a737bd4d 1064
b99bd4ef 1065static int
a737bd4d 1066add_to_lit_pool (void)
b99bd4ef 1067{
61b5f74b 1068 literal_pool * pool;
3d0c9500 1069 unsigned int entry;
b99bd4ef 1070
3d0c9500 1071 pool = find_or_make_literal_pool ();
b99bd4ef 1072
3d0c9500
NC
1073 /* Check if this literal value is already in the pool. */
1074 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1075 {
3d0c9500
NC
1076 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1077 && (inst.reloc.exp.X_op == O_constant)
1078 && (pool->literals[entry].X_add_number
b99bd4ef 1079 == inst.reloc.exp.X_add_number)
3d0c9500
NC
1080 && (pool->literals[entry].X_unsigned
1081 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
1082 break;
1083
3d0c9500
NC
1084 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1085 && (inst.reloc.exp.X_op == O_symbol)
1086 && (pool->literals[entry].X_add_number
b99bd4ef 1087 == inst.reloc.exp.X_add_number)
3d0c9500 1088 && (pool->literals[entry].X_add_symbol
b99bd4ef 1089 == inst.reloc.exp.X_add_symbol)
3d0c9500 1090 && (pool->literals[entry].X_op_symbol
b99bd4ef 1091 == inst.reloc.exp.X_op_symbol))
3d0c9500 1092 break;
b99bd4ef
NC
1093 }
1094
3d0c9500
NC
1095 /* Do we need to create a new entry? */
1096 if (entry == pool->next_free_entry)
b99bd4ef 1097 {
3d0c9500 1098 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 1099 {
ed71e111 1100 inst.error = _("literal pool overflow");
b99bd4ef
NC
1101 return FAIL;
1102 }
1103
3d0c9500
NC
1104 pool->literals[entry] = inst.reloc.exp;
1105 pool->next_free_entry += 1;
b99bd4ef
NC
1106 }
1107
3d0c9500 1108 inst.reloc.exp.X_op = O_symbol;
08df2379 1109 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 1110 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
1111
1112 return SUCCESS;
1113}
1114
1115/* Can't use symbol_new here, so have to create a symbol and then at
1116 a later date assign it a value. Thats what these functions do. */
1117
1118static void
a737bd4d
NC
1119symbol_locate (symbolS * symbolP,
1120 const char * name, /* It is copied, the caller can modify. */
1121 segT segment, /* Segment identifier (SEG_<something>). */
1122 valueT valu, /* Symbol value. */
1123 fragS * frag) /* Associated fragment. */
b99bd4ef
NC
1124{
1125 unsigned int name_length;
1126 char * preserved_copy_of_name;
1127
1128 name_length = strlen (name) + 1; /* +1 for \0. */
1129 obstack_grow (&notes, name, name_length);
1130 preserved_copy_of_name = obstack_finish (&notes);
1131#ifdef STRIP_UNDERSCORE
1132 if (preserved_copy_of_name[0] == '_')
1133 preserved_copy_of_name++;
1134#endif
1135
1136#ifdef tc_canonicalize_symbol_name
1137 preserved_copy_of_name =
1138 tc_canonicalize_symbol_name (preserved_copy_of_name);
1139#endif
1140
1141 S_SET_NAME (symbolP, preserved_copy_of_name);
1142
1143 S_SET_SEGMENT (symbolP, segment);
1144 S_SET_VALUE (symbolP, valu);
c62e1cc3 1145 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
1146
1147 symbol_set_frag (symbolP, frag);
1148
1149 /* Link to end of symbol chain. */
1150 {
1151 extern int symbol_table_frozen;
a737bd4d 1152
b99bd4ef
NC
1153 if (symbol_table_frozen)
1154 abort ();
1155 }
1156
1157 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1158
1159 obj_symbol_new_hook (symbolP);
1160
1161#ifdef tc_symbol_new_hook
1162 tc_symbol_new_hook (symbolP);
1163#endif
1164
1165#ifdef DEBUG_SYMS
1166 verify_symbol_chain (symbol_rootP, symbol_lastP);
1167#endif /* DEBUG_SYMS */
1168}
1169
1170/* Check that an immediate is valid.
1171 If so, convert it to the right format. */
1172
1173static unsigned int
a737bd4d 1174validate_immediate (unsigned int val)
b99bd4ef
NC
1175{
1176 unsigned int a;
1177 unsigned int i;
1178
1179#define rotate_left(v, n) (v << n | v >> (32 - n))
1180
1181 for (i = 0; i < 32; i += 2)
1182 if ((a = rotate_left (val, i)) <= 0xff)
1183 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1184
1185 return FAIL;
1186}
1187
2d2255b5 1188/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
1189 values, added together. We already know that this value cannot be
1190 computed by just one ARM instruction. */
1191
1192static unsigned int
a737bd4d
NC
1193validate_immediate_twopart (unsigned int val,
1194 unsigned int * highpart)
b99bd4ef
NC
1195{
1196 unsigned int a;
1197 unsigned int i;
1198
1199 for (i = 0; i < 32; i += 2)
1200 if (((a = rotate_left (val, i)) & 0xff) != 0)
1201 {
1202 if (a & 0xff00)
1203 {
1204 if (a & ~ 0xffff)
1205 continue;
1206 * highpart = (a >> 8) | ((i + 24) << 7);
1207 }
1208 else if (a & 0xff0000)
1209 {
1210 if (a & 0xff000000)
1211 continue;
1212 * highpart = (a >> 16) | ((i + 16) << 7);
1213 }
1214 else
1215 {
1216 assert (a & 0xff000000);
1217 * highpart = (a >> 24) | ((i + 8) << 7);
1218 }
1219
1220 return (a & 0xff) | (i << 7);
1221 }
1222
1223 return FAIL;
1224}
1225
1226static int
a737bd4d 1227validate_offset_imm (unsigned int val, int hwse)
b99bd4ef
NC
1228{
1229 if ((hwse && val > 255) || val > 4095)
1230 return FAIL;
1231 return val;
1232}
1233
6057a28f
NC
1234\f
1235#ifdef OBJ_ELF
6057a28f
NC
1236/* This code is to handle mapping symbols as defined in the ARM ELF spec.
1237 (This text is taken from version B-02 of the spec):
1238
1239 4.4.7 Mapping and tagging symbols
1240
1241 A section of an ARM ELF file can contain a mixture of ARM code,
1242 Thumb code, and data. There are inline transitions between code
1243 and data at literal pool boundaries. There can also be inline
1244 transitions between ARM code and Thumb code, for example in
1245 ARM-Thumb inter-working veneers. Linkers, machine-level
1246 debuggers, profiling tools, and disassembly tools need to map
1247 images accurately. For example, setting an ARM breakpoint on a
1248 Thumb location, or in a literal pool, can crash the program
1249 being debugged, ruining the debugging session.
1250
1251 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1252 tagged (see section 4.4.7.2 below) using local symbols (with
1253 binding STB_LOCAL). To assist consumers, mapping and tagging
1254 symbols should be collated first in the symbol table, before
1255 other symbols with binding STB_LOCAL.
1256
1257 To allow properly collated mapping and tagging symbols to be
1258 skipped by consumers that have no interest in them, the first
1259 such symbol should have the name $m and its st_value field equal
1260 to the total number of mapping and tagging symbols (including
1261 the $m) in the symbol table.
1262
1263 4.4.7.1 Mapping symbols
1264
1265 $a Labels the first byte of a sequence of ARM instructions.
1266 Its type is STT_FUNC.
1267
1268 $d Labels the first byte of a sequence of data items.
1269 Its type is STT_OBJECT.
1270
1271 $t Labels the first byte of a sequence of Thumb instructions.
1272 Its type is STT_FUNC.
1273
1274 This list of mapping symbols may be extended in the future.
1275
1276 Section-relative mapping symbols
1277
1278 Mapping symbols defined in a section define a sequence of
1279 half-open address intervals that cover the address range of the
1280 section. Each interval starts at the address defined by a
1281 mapping symbol, and continues up to, but not including, the
1282 address defined by the next (in address order) mapping symbol or
1283 the end of the section. A corollary is that there must be a
1284 mapping symbol defined at the beginning of each section.
1285 Consumers can ignore the size of a section-relative mapping
1286 symbol. Producers can set it to 0.
1287
1288 Absolute mapping symbols
1289
1290 Because of the need to crystallize a Thumb address with the
1291 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1292 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1293 or $t.
1294
1295 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1296 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1297 where [x, y) denotes the half-open address range from x,
1298 inclusive, to y, exclusive.
1299
1300 In the absence of a mapping symbol, a consumer can interpret a
1301 function symbol with an odd value as the Thumb code address
1302 obtained by clearing the least significant bit of the
1303 value. This interpretation is deprecated, and it may not work in
1304 the future.
1305
1306 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1307 the EABI (which is still under development), so they are not
1308 implemented here. */
1309
69b97547
NC
1310static enum mstate mapstate = MAP_UNDEFINED;
1311
6057a28f
NC
1312static void
1313mapping_state (enum mstate state)
1314{
6057a28f
NC
1315 symbolS * symbolP;
1316 const char * symname;
1317 int type;
1318
1319 if (mapstate == state)
1320 /* The mapping symbol has already been emitted.
1321 There is nothing else to do. */
1322 return;
1323
1324 mapstate = state;
1325
1326 switch (state)
1327 {
1328 case MAP_DATA:
1329 symname = "$d";
1330 type = BSF_OBJECT;
1331 break;
1332 case MAP_ARM:
1333 symname = "$a";
1334 type = BSF_FUNCTION;
1335 break;
1336 case MAP_THUMB:
1337 symname = "$t";
1338 type = BSF_FUNCTION;
1339 break;
69b97547 1340 case MAP_UNDEFINED:
a737bd4d 1341 return;
6057a28f
NC
1342 default:
1343 abort ();
1344 }
1345
69b97547
NC
1346 seg_info (now_seg)->tc_segment_info_data = state;
1347
6057a28f
NC
1348 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1349 symbol_table_insert (symbolP);
1350 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
a737bd4d 1351
6057a28f
NC
1352 switch (state)
1353 {
1354 case MAP_ARM:
1355 THUMB_SET_FUNC (symbolP, 0);
1356 ARM_SET_THUMB (symbolP, 0);
1357 ARM_SET_INTERWORK (symbolP, support_interwork);
1358 break;
a737bd4d 1359
6057a28f
NC
1360 case MAP_THUMB:
1361 THUMB_SET_FUNC (symbolP, 1);
1362 ARM_SET_THUMB (symbolP, 1);
1363 ARM_SET_INTERWORK (symbolP, support_interwork);
1364 break;
a737bd4d 1365
6057a28f
NC
1366 case MAP_DATA:
1367 default:
1368 return;
1369 }
1370}
1371
a737bd4d
NC
1372/* When we change sections we need to issue a new mapping symbol. */
1373
1374void
1375arm_elf_change_section (void)
1376{
1377 flagword flags;
1378
40a18ebd
NC
1379 /* Link an unlinked unwind index table section to the .text section. */
1380 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1381 && elf_linked_to_section (now_seg) == NULL)
1382 elf_linked_to_section (now_seg) = text_section;
1383
a737bd4d
NC
1384 if (!SEG_NORMAL (now_seg))
1385 return;
1386
1387 flags = bfd_get_section_flags (stdoutput, now_seg);
1388
1389 /* We can ignore sections that only contain debug info. */
1390 if ((flags & SEC_ALLOC) == 0)
1391 return;
1392
1393 mapstate = seg_info (now_seg)->tc_segment_info_data;
1394}
40a18ebd
NC
1395
1396int
1397arm_elf_section_type (const char * str, size_t len)
1398{
1399 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1400 return SHT_ARM_EXIDX;
1401
1402 return -1;
1403}
a737bd4d
NC
1404#else
1405#define mapping_state(a)
1406#endif /* OBJ_ELF */
1407\f
1408/* arm_reg_parse () := if it looks like a register, return its token and
1409 advance the pointer. */
1410
1411static int
1412arm_reg_parse (char ** ccp, struct hash_control * htab)
1413{
1414 char * start = * ccp;
1415 char c;
1416 char * p;
1417 struct reg_entry * reg;
1418
1419#ifdef REGISTER_PREFIX
1420 if (*start != REGISTER_PREFIX)
1421 return FAIL;
1422 p = start + 1;
1423#else
1424 p = start;
1425#ifdef OPTIONAL_REGISTER_PREFIX
1426 if (*p == OPTIONAL_REGISTER_PREFIX)
1427 p++, start++;
1428#endif
1429#endif
1430 if (!ISALPHA (*p) || !is_name_beginner (*p))
1431 return FAIL;
1432
1433 c = *p++;
1434 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1435 c = *p++;
1436
1437 *--p = 0;
1438 reg = (struct reg_entry *) hash_find (htab, start);
1439 *p = c;
1440
1441 if (reg)
1442 {
1443 *ccp = p;
1444 return reg->number;
1445 }
1446
1447 return FAIL;
1448}
1449
1450/* Search for the following register name in each of the possible reg name
1451 tables. Return the classification if found, or REG_TYPE_MAX if not
1452 present. */
6057a28f 1453
a737bd4d
NC
1454static enum arm_reg_type
1455arm_reg_parse_any (char *cp)
6057a28f 1456{
a737bd4d 1457 int i;
6057a28f 1458
a737bd4d
NC
1459 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1460 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1461 return (enum arm_reg_type) i;
6057a28f 1462
a737bd4d
NC
1463 return REG_TYPE_MAX;
1464}
6057a28f 1465
a737bd4d
NC
1466static void
1467opcode_select (int width)
1468{
1469 switch (width)
1470 {
1471 case 16:
1472 if (! thumb_mode)
1473 {
1474 if (! (cpu_variant & ARM_EXT_V4T))
1475 as_bad (_("selected processor does not support THUMB opcodes"));
6057a28f 1476
a737bd4d
NC
1477 thumb_mode = 1;
1478 /* No need to force the alignment, since we will have been
1479 coming from ARM mode, which is word-aligned. */
1480 record_alignment (now_seg, 1);
1481 }
1482 mapping_state (MAP_THUMB);
1483 break;
1484
1485 case 32:
1486 if (thumb_mode)
1487 {
1488 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1489 as_bad (_("selected processor does not support ARM opcodes"));
1490
1491 thumb_mode = 0;
1492
1493 if (!need_pass_2)
1494 frag_align (2, 0, 0);
1495
1496 record_alignment (now_seg, 1);
1497 }
1498 mapping_state (MAP_ARM);
1499 break;
1500
1501 default:
1502 as_bad (_("invalid instruction size selected (%d)"), width);
1503 }
6057a28f 1504}
6057a28f 1505
b99bd4ef 1506static void
a737bd4d 1507s_req (int a ATTRIBUTE_UNUSED)
b99bd4ef 1508{
f03698e6 1509 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
1510}
1511
0bbf2aa4
NC
1512/* The .unreq directive deletes an alias which was previously defined
1513 by .req. For example:
1514
1515 my_alias .req r11
1516 .unreq my_alias */
1517
1518static void
1519s_unreq (int a ATTRIBUTE_UNUSED)
1520{
a737bd4d 1521 char * name;
0bbf2aa4
NC
1522 char saved_char;
1523
1524 skip_whitespace (input_line_pointer);
1525 name = input_line_pointer;
1526
1527 while (*input_line_pointer != 0
1528 && *input_line_pointer != ' '
1529 && *input_line_pointer != '\n')
1530 ++input_line_pointer;
1531
1532 saved_char = *input_line_pointer;
1533 *input_line_pointer = 0;
1534
1535 if (*name)
1536 {
1537 enum arm_reg_type req_type = arm_reg_parse_any (name);
1538
1539 if (req_type != REG_TYPE_MAX)
1540 {
1541 char *temp_name = name;
1542 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1543
1544 if (req_no != FAIL)
1545 {
1546 struct reg_entry *req_entry;
1547
1548 /* Check to see if this alias is a builtin one. */
1549 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1550
1551 if (!req_entry)
1552 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1553 else if (req_entry->builtin)
67c1ffbe 1554 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
1555 points to a const data structure, so we only need to
1556 free up the memory used by the key in the hash table.
1557 Unfortunately we have not recorded this value, so this
1558 is a memory leak. */
1559 /* FIXME: Should we issue a warning message ? */
1560 ;
1561 else
1562 {
67c1ffbe 1563 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
1564 key and the value, but fortunately the key is the same
1565 as the value->name field. */
1566 free ((char *) req_entry->name);
1567 free (req_entry);
1568 }
1569 }
1570 else
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1572 }
1573 else
1574 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1575 }
1576 else
1577 as_bad (_("invalid syntax for .unreq directive"));
1578
1579 *input_line_pointer = saved_char;
1580 demand_empty_rest_of_line ();
1581}
1582
b99bd4ef 1583static void
a737bd4d 1584s_bss (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1585{
1586 /* We don't support putting frags in the BSS segment, we fake it by
1587 marking in_bss, then looking at s_skip for clues. */
1588 subseg_set (bss_section, 0);
1589 demand_empty_rest_of_line ();
6057a28f 1590 mapping_state (MAP_DATA);
b99bd4ef
NC
1591}
1592
1593static void
a737bd4d 1594s_even (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1595{
1596 /* Never make frag if expect extra pass. */
1597 if (!need_pass_2)
1598 frag_align (1, 0, 0);
1599
1600 record_alignment (now_seg, 1);
1601
1602 demand_empty_rest_of_line ();
1603}
1604
1605static void
a737bd4d 1606s_ltorg (int ignored ATTRIBUTE_UNUSED)
b99bd4ef 1607{
3d0c9500
NC
1608 unsigned int entry;
1609 literal_pool * pool;
b99bd4ef
NC
1610 char sym_name[20];
1611
3d0c9500
NC
1612 pool = find_literal_pool ();
1613 if (pool == NULL
1614 || pool->symbol == NULL
1615 || pool->next_free_entry == 0)
b99bd4ef
NC
1616 return;
1617
69b97547
NC
1618 mapping_state (MAP_DATA);
1619
b99bd4ef
NC
1620 /* Align pool as you have word accesses.
1621 Only make a frag if we have to. */
1622 if (!need_pass_2)
1623 frag_align (2, 0, 0);
1624
1625 record_alignment (now_seg, 2);
1626
3d0c9500 1627 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 1628
3d0c9500 1629 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 1630 (valueT) frag_now_fix (), frag_now);
3d0c9500 1631 symbol_table_insert (pool->symbol);
b99bd4ef 1632
3d0c9500 1633 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
1634
1635#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 1636 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
1637#endif
1638
3d0c9500 1639 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1640 /* First output the expression in the instruction to the pool. */
3d0c9500 1641 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 1642
3d0c9500
NC
1643 /* Mark the pool as empty. */
1644 pool->next_free_entry = 0;
1645 pool->symbol = NULL;
b99bd4ef
NC
1646}
1647
1648/* Same as s_align_ptwo but align 0 => align 2. */
1649
1650static void
a737bd4d 1651s_align (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1652{
a737bd4d
NC
1653 int temp;
1654 long temp_fill;
b99bd4ef
NC
1655 long max_alignment = 15;
1656
1657 temp = get_absolute_expression ();
1658 if (temp > max_alignment)
f03698e6 1659 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
1660 else if (temp < 0)
1661 {
f03698e6 1662 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
1663 temp = 0;
1664 }
1665
1666 if (*input_line_pointer == ',')
1667 {
1668 input_line_pointer++;
1669 temp_fill = get_absolute_expression ();
1670 }
1671 else
1672 temp_fill = 0;
1673
1674 if (!temp)
1675 temp = 2;
1676
1677 /* Only make a frag if we HAVE to. */
1678 if (temp && !need_pass_2)
1679 frag_align (temp, (int) temp_fill, 0);
1680 demand_empty_rest_of_line ();
1681
1682 record_alignment (now_seg, temp);
1683}
1684
1685static void
a737bd4d 1686s_force_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1687{
1688 /* If we are not already in thumb mode go into it, EVEN if
1689 the target processor does not support thumb instructions.
1690 This is used by gcc/config/arm/lib1funcs.asm for example
1691 to compile interworking support functions even if the
1692 target processor should not support interworking. */
1693 if (! thumb_mode)
1694 {
1695 thumb_mode = 2;
1696
1697 record_alignment (now_seg, 1);
1698 }
1699
1700 demand_empty_rest_of_line ();
1701}
1702
1703static void
a737bd4d 1704s_thumb_func (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1705{
1706 if (! thumb_mode)
1707 opcode_select (16);
1708
1709 /* The following label is the name/address of the start of a Thumb function.
1710 We need to know this for the interworking support. */
b34976b6 1711 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
1712
1713 demand_empty_rest_of_line ();
1714}
1715
1716/* Perform a .set directive, but also mark the alias as
1717 being a thumb function. */
1718
1719static void
a737bd4d 1720s_thumb_set (int equiv)
b99bd4ef
NC
1721{
1722 /* XXX the following is a duplicate of the code for s_set() in read.c
1723 We cannot just call that code as we need to get at the symbol that
1724 is created. */
a737bd4d
NC
1725 char * name;
1726 char delim;
1727 char * end_name;
1728 symbolS * symbolP;
b99bd4ef
NC
1729
1730 /* Especial apologies for the random logic:
1731 This just grew, and could be parsed much more simply!
1732 Dean - in haste. */
1733 name = input_line_pointer;
1734 delim = get_symbol_end ();
1735 end_name = input_line_pointer;
1736 *end_name = delim;
1737
1738 SKIP_WHITESPACE ();
1739
1740 if (*input_line_pointer != ',')
1741 {
1742 *end_name = 0;
f03698e6 1743 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
1744 *end_name = delim;
1745 ignore_rest_of_line ();
1746 return;
1747 }
1748
1749 input_line_pointer++;
1750 *end_name = 0;
1751
1752 if (name[0] == '.' && name[1] == '\0')
1753 {
1754 /* XXX - this should not happen to .thumb_set. */
1755 abort ();
1756 }
1757
1758 if ((symbolP = symbol_find (name)) == NULL
1759 && (symbolP = md_undefined_symbol (name)) == NULL)
1760 {
1761#ifndef NO_LISTING
1762 /* When doing symbol listings, play games with dummy fragments living
1763 outside the normal fragment chain to record the file and line info
1764 for this symbol. */
1765 if (listing & LISTING_SYMBOLS)
1766 {
1767 extern struct list_info_struct * listing_tail;
a737bd4d 1768 fragS * dummy_frag = xmalloc (sizeof (fragS));
b99bd4ef
NC
1769
1770 memset (dummy_frag, 0, sizeof (fragS));
1771 dummy_frag->fr_type = rs_fill;
1772 dummy_frag->line = listing_tail;
1773 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1774 dummy_frag->fr_symbol = symbolP;
1775 }
1776 else
1777#endif
1778 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1779
1780#ifdef OBJ_COFF
1781 /* "set" symbols are local unless otherwise specified. */
1782 SF_SET_LOCAL (symbolP);
1783#endif /* OBJ_COFF */
1784 } /* Make a new symbol. */
1785
1786 symbol_table_insert (symbolP);
1787
1788 * end_name = delim;
1789
1790 if (equiv
1791 && S_IS_DEFINED (symbolP)
1792 && S_GET_SEGMENT (symbolP) != reg_section)
1793 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1794
1795 pseudo_set (symbolP);
1796
1797 demand_empty_rest_of_line ();
1798
1799 /* XXX Now we come to the Thumb specific bit of code. */
1800
1801 THUMB_SET_FUNC (symbolP, 1);
1802 ARM_SET_THUMB (symbolP, 1);
1803#if defined OBJ_ELF || defined OBJ_COFF
1804 ARM_SET_INTERWORK (symbolP, support_interwork);
1805#endif
1806}
1807
b99bd4ef 1808static void
a737bd4d 1809s_arm (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1810{
1811 opcode_select (32);
1812 demand_empty_rest_of_line ();
1813}
1814
1815static void
a737bd4d 1816s_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1817{
1818 opcode_select (16);
1819 demand_empty_rest_of_line ();
1820}
1821
1822static void
a737bd4d 1823s_code (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1824{
a737bd4d 1825 int temp;
b99bd4ef
NC
1826
1827 temp = get_absolute_expression ();
1828 switch (temp)
1829 {
1830 case 16:
1831 case 32:
1832 opcode_select (temp);
1833 break;
1834
1835 default:
1836 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1837 }
1838}
1839
1840static void
a737bd4d 1841end_of_line (char * str)
b99bd4ef
NC
1842{
1843 skip_whitespace (str);
1844
f03698e6
RE
1845 if (*str != '\0' && !inst.error)
1846 inst.error = _("garbage following instruction");
b99bd4ef
NC
1847}
1848
1849static int
a737bd4d 1850skip_past_comma (char ** str)
b99bd4ef
NC
1851{
1852 char * p = * str, c;
1853 int comma = 0;
1854
1855 while ((c = *p) == ' ' || c == ',')
1856 {
1857 p++;
1858 if (c == ',' && comma++)
1859 return FAIL;
1860 }
1861
1862 if (c == '\0')
1863 return FAIL;
1864
1865 *str = p;
1866 return comma ? SUCCESS : FAIL;
1867}
1868
a737bd4d
NC
1869/* Return TRUE if anything in the expression is a bignum. */
1870
1871static int
1872walk_no_bignums (symbolS * sp)
1873{
1874 if (symbol_get_value_expression (sp)->X_op == O_big)
1875 return 1;
1876
1877 if (symbol_get_value_expression (sp)->X_add_symbol)
1878 {
1879 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1880 || (symbol_get_value_expression (sp)->X_op_symbol
1881 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1882 }
1883
1884 return 0;
1885}
1886
1887static int in_my_get_expression = 0;
1888
1889static int
1890my_get_expression (expressionS * ep, char ** str)
1891{
1892 char * save_in;
1893 segT seg;
1894
1895 save_in = input_line_pointer;
1896 input_line_pointer = *str;
1897 in_my_get_expression = 1;
1898 seg = expression (ep);
1899 in_my_get_expression = 0;
1900
1901 if (ep->X_op == O_illegal)
1902 {
1903 /* We found a bad expression in md_operand(). */
1904 *str = input_line_pointer;
1905 input_line_pointer = save_in;
1906 return 1;
1907 }
1908
1909#ifdef OBJ_AOUT
1910 if (seg != absolute_section
1911 && seg != text_section
1912 && seg != data_section
1913 && seg != bss_section
1914 && seg != undefined_section)
1915 {
1916 inst.error = _("bad_segment");
1917 *str = input_line_pointer;
1918 input_line_pointer = save_in;
1919 return 1;
1920 }
1921#endif
1922
1923 /* Get rid of any bignums now, so that we don't generate an error for which
1924 we can't establish a line number later on. Big numbers are never valid
1925 in instructions, which is where this routine is always called. */
1926 if (ep->X_op == O_big
1927 || (ep->X_add_symbol
1928 && (walk_no_bignums (ep->X_add_symbol)
1929 || (ep->X_op_symbol
1930 && walk_no_bignums (ep->X_op_symbol)))))
1931 {
1932 inst.error = _("invalid constant");
1933 *str = input_line_pointer;
1934 input_line_pointer = save_in;
1935 return 1;
1936 }
1937
1938 *str = input_line_pointer;
1939 input_line_pointer = save_in;
1940 return 0;
1941}
1942
b99bd4ef
NC
1943/* A standard register must be given at this point.
1944 SHIFT is the place to put it in inst.instruction.
1945 Restores input start point on error.
1946 Returns the reg#, or FAIL. */
1947
1948static int
a737bd4d 1949reg_required_here (char ** str, int shift)
b99bd4ef
NC
1950{
1951 static char buff [128]; /* XXX */
1952 int reg;
1953 char * start = * str;
1954
6c43fab6 1955 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
1956 {
1957 if (shift >= 0)
1958 inst.instruction |= reg << shift;
1959 return reg;
1960 }
1961
1962 /* Restore the start point, we may have got a reg of the wrong class. */
1963 *str = start;
1964
1965 /* In the few cases where we might be able to accept something else
1966 this error can be overridden. */
f03698e6 1967 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
1968 inst.error = buff;
1969
1970 return FAIL;
1971}
1972
5a6c6817 1973/* A Intel Wireless MMX technology register
e16bb312
NC
1974 must be given at this point.
1975 Shift is the place to put it in inst.instruction.
1976 Restores input start point on err.
1977 Returns the reg#, or FAIL. */
1978
1979static int
a737bd4d
NC
1980wreg_required_here (char ** str,
1981 int shift,
1982 enum wreg_type reg_type)
e16bb312
NC
1983{
1984 static char buff [128];
1985 int reg;
1986 char * start = *str;
1987
1988 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1989 {
1990 if (wr_register (reg)
1991 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1992 {
1993 if (shift >= 0)
1994 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1995 return reg;
1996 }
1997 else if (wc_register (reg)
1998 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1999 {
2000 if (shift >= 0)
2001 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2002 return reg;
2003 }
2004 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2005 {
2006 if (shift >= 0)
2007 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2008 return reg;
2009 }
2010 }
2011
2012 /* Restore the start point, we may have got a reg of the wrong class. */
2013 *str = start;
2014
2015 /* In the few cases where we might be able to accept
2016 something else this error can be overridden. */
5a6c6817 2017 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
2018 inst.error = buff;
2019
2020 return FAIL;
2021}
2022
05d2d07e 2023static const struct asm_psr *
a737bd4d 2024arm_psr_parse (char ** ccp)
b99bd4ef
NC
2025{
2026 char * start = * ccp;
2027 char c;
2028 char * p;
05d2d07e 2029 const struct asm_psr * psr;
b99bd4ef
NC
2030
2031 p = start;
2032
2033 /* Skip to the end of the next word in the input stream. */
2034 do
2035 {
2036 c = *p++;
2037 }
3882b010 2038 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2039
2040 /* Terminate the word. */
2041 *--p = 0;
2042
2043 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2044 feature for ease of use and backwards compatibility. */
2045 if (!strncmp (start, "cpsr", 4))
2046 strncpy (start, "CPSR", 4);
2047 else if (!strncmp (start, "spsr", 4))
2048 strncpy (start, "SPSR", 4);
2049
2050 /* Now locate the word in the psr hash table. */
05d2d07e 2051 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
2052
2053 /* Restore the input stream. */
2054 *p = c;
2055
2056 /* If we found a valid match, advance the
2057 stream pointer past the end of the word. */
2058 *ccp = p;
2059
2060 return psr;
2061}
2062
2063/* Parse the input looking for a PSR flag. */
2064
2065static int
a737bd4d 2066psr_required_here (char ** str)
b99bd4ef
NC
2067{
2068 char * start = * str;
05d2d07e 2069 const struct asm_psr * psr;
b99bd4ef
NC
2070
2071 psr = arm_psr_parse (str);
2072
2073 if (psr)
2074 {
2075 /* If this is the SPSR that is being modified, set the R bit. */
2076 if (! psr->cpsr)
2077 inst.instruction |= SPSR_BIT;
2078
2079 /* Set the psr flags in the MSR instruction. */
2080 inst.instruction |= psr->field << PSR_SHIFT;
2081
2082 return SUCCESS;
2083 }
2084
2085 /* In the few cases where we might be able to accept
2086 something else this error can be overridden. */
2087 inst.error = _("flag for {c}psr instruction expected");
2088
2089 /* Restore the start point. */
2090 *str = start;
2091 return FAIL;
2092}
2093
2094static int
a737bd4d 2095co_proc_number (char ** str)
b99bd4ef
NC
2096{
2097 int processor, pchar;
6c43fab6 2098 char *start;
b99bd4ef 2099
6c43fab6
RE
2100 skip_whitespace (*str);
2101 start = *str;
b99bd4ef
NC
2102
2103 /* The data sheet seems to imply that just a number on its own is valid
2104 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2105 accept either. */
6c43fab6
RE
2106 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2107 == FAIL)
b99bd4ef 2108 {
6c43fab6
RE
2109 *str = start;
2110
2111 pchar = *(*str)++;
2112 if (pchar >= '0' && pchar <= '9')
b99bd4ef 2113 {
6c43fab6
RE
2114 processor = pchar - '0';
2115 if (**str >= '0' && **str <= '9')
b99bd4ef 2116 {
6c43fab6
RE
2117 processor = processor * 10 + *(*str)++ - '0';
2118 if (processor > 15)
2119 {
f03698e6 2120 inst.error = _("illegal co-processor number");
6c43fab6
RE
2121 return FAIL;
2122 }
b99bd4ef
NC
2123 }
2124 }
6c43fab6
RE
2125 else
2126 {
376eb240 2127 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
2128 return FAIL;
2129 }
b99bd4ef
NC
2130 }
2131
2132 inst.instruction |= processor << 8;
2133 return SUCCESS;
2134}
2135
2136static int
a737bd4d 2137cp_opc_expr (char ** str, int where, int length)
b99bd4ef
NC
2138{
2139 expressionS expr;
2140
2141 skip_whitespace (* str);
2142
2143 memset (&expr, '\0', sizeof (expr));
2144
2145 if (my_get_expression (&expr, str))
2146 return FAIL;
2147 if (expr.X_op != O_constant)
2148 {
2149 inst.error = _("bad or missing expression");
2150 return FAIL;
2151 }
2152
2153 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2154 {
2155 inst.error = _("immediate co-processor expression too large");
2156 return FAIL;
2157 }
2158
2159 inst.instruction |= expr.X_add_number << where;
2160 return SUCCESS;
2161}
2162
2163static int
a737bd4d 2164cp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2165{
2166 int reg;
2167 char * start = *str;
2168
6c43fab6 2169 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 2170 {
b99bd4ef
NC
2171 inst.instruction |= reg << where;
2172 return reg;
2173 }
2174
2175 /* In the few cases where we might be able to accept something else
2176 this error can be overridden. */
376eb240 2177 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
2178
2179 /* Restore the start point. */
2180 *str = start;
2181 return FAIL;
2182}
2183
2184static int
a737bd4d 2185fp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2186{
2187 int reg;
2188 char * start = * str;
2189
6c43fab6 2190 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 2191 {
b99bd4ef
NC
2192 inst.instruction |= reg << where;
2193 return reg;
2194 }
2195
2196 /* In the few cases where we might be able to accept something else
2197 this error can be overridden. */
376eb240 2198 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
2199
2200 /* Restore the start point. */
2201 *str = start;
2202 return FAIL;
2203}
2204
2205static int
a737bd4d 2206cp_address_offset (char ** str)
b99bd4ef
NC
2207{
2208 int offset;
2209
2210 skip_whitespace (* str);
2211
2212 if (! is_immediate_prefix (**str))
2213 {
2214 inst.error = _("immediate expression expected");
2215 return FAIL;
2216 }
2217
2218 (*str)++;
2219
2220 if (my_get_expression (& inst.reloc.exp, str))
2221 return FAIL;
2222
2223 if (inst.reloc.exp.X_op == O_constant)
2224 {
2225 offset = inst.reloc.exp.X_add_number;
2226
2227 if (offset & 3)
2228 {
2229 inst.error = _("co-processor address must be word aligned");
2230 return FAIL;
2231 }
2232
2233 if (offset > 1023 || offset < -1023)
2234 {
2235 inst.error = _("offset too large");
2236 return FAIL;
2237 }
2238
2239 if (offset >= 0)
2240 inst.instruction |= INDEX_UP;
2241 else
2242 offset = -offset;
2243
2244 inst.instruction |= offset >> 2;
2245 }
2246 else
2247 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2248
2249 return SUCCESS;
2250}
2251
2252static int
a737bd4d 2253cp_address_required_here (char ** str, int wb_ok)
b99bd4ef
NC
2254{
2255 char * p = * str;
2256 int pre_inc = 0;
2257 int write_back = 0;
2258
2259 if (*p == '[')
2260 {
2261 int reg;
2262
2263 p++;
2264 skip_whitespace (p);
2265
2266 if ((reg = reg_required_here (& p, 16)) == FAIL)
2267 return FAIL;
2268
2269 skip_whitespace (p);
2270
2271 if (*p == ']')
2272 {
2273 p++;
2274
f02232aa
NC
2275 skip_whitespace (p);
2276
2277 if (*p == '\0')
b99bd4ef 2278 {
f02232aa 2279 /* As an extension to the official ARM syntax we allow:
f02232aa 2280 [Rn]
f02232aa 2281 as a short hand for:
f02232aa
NC
2282 [Rn,#0] */
2283 inst.instruction |= PRE_INDEX | INDEX_UP;
2284 *str = p;
2285 return SUCCESS;
2286 }
a737bd4d 2287
f02232aa
NC
2288 if (skip_past_comma (& p) == FAIL)
2289 {
2290 inst.error = _("comma expected after closing square bracket");
2291 return FAIL;
2292 }
b99bd4ef 2293
f02232aa
NC
2294 skip_whitespace (p);
2295
2296 if (*p == '#')
2297 {
2298 if (wb_ok)
b99bd4ef 2299 {
f02232aa
NC
2300 /* [Rn], #expr */
2301 write_back = WRITE_BACK;
2302
2303 if (reg == REG_PC)
2304 {
2305 inst.error = _("pc may not be used in post-increment");
2306 return FAIL;
2307 }
2308
2309 if (cp_address_offset (& p) == FAIL)
2310 return FAIL;
b99bd4ef 2311 }
f02232aa
NC
2312 else
2313 pre_inc = PRE_INDEX | INDEX_UP;
2314 }
2315 else if (*p == '{')
2316 {
2317 int option;
b99bd4ef 2318
f02232aa
NC
2319 /* [Rn], {<expr>} */
2320 p++;
2321
2322 skip_whitespace (p);
2323
2324 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 2325 return FAIL;
f02232aa
NC
2326
2327 if (inst.reloc.exp.X_op == O_constant)
2328 {
2329 option = inst.reloc.exp.X_add_number;
2330
2331 if (option > 255 || option < 0)
2332 {
2333 inst.error = _("'option' field too large");
2334 return FAIL;
2335 }
2336
2337 skip_whitespace (p);
2338
2339 if (*p != '}')
2340 {
2341 inst.error = _("'}' expected at end of 'option' field");
2342 return FAIL;
2343 }
2344 else
2345 {
2346 p++;
2347 inst.instruction |= option;
2348 inst.instruction |= INDEX_UP;
2349 }
2350 }
2351 else
2352 {
2353 inst.error = _("non-constant expressions for 'option' field not supported");
2354 return FAIL;
2355 }
b99bd4ef
NC
2356 }
2357 else
f02232aa
NC
2358 {
2359 inst.error = _("# or { expected after comma");
a737bd4d 2360 return FAIL;
f02232aa 2361 }
b99bd4ef
NC
2362 }
2363 else
2364 {
2365 /* '['Rn, #expr']'[!] */
2366
2367 if (skip_past_comma (& p) == FAIL)
2368 {
2369 inst.error = _("pre-indexed expression expected");
2370 return FAIL;
2371 }
2372
2373 pre_inc = PRE_INDEX;
2374
2375 if (cp_address_offset (& p) == FAIL)
2376 return FAIL;
2377
2378 skip_whitespace (p);
2379
2380 if (*p++ != ']')
2381 {
2382 inst.error = _("missing ]");
2383 return FAIL;
2384 }
2385
2386 skip_whitespace (p);
2387
bfae80f2 2388 if (wb_ok && *p == '!')
b99bd4ef
NC
2389 {
2390 if (reg == REG_PC)
2391 {
2392 inst.error = _("pc may not be used with write-back");
2393 return FAIL;
2394 }
2395
2396 p++;
2397 write_back = WRITE_BACK;
2398 }
2399 }
2400 }
2401 else
2402 {
2403 if (my_get_expression (&inst.reloc.exp, &p))
2404 return FAIL;
2405
2406 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2407 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2408 inst.reloc.pc_rel = 1;
2409 inst.instruction |= (REG_PC << 16);
2410 pre_inc = PRE_INDEX;
2411 }
2412
2413 inst.instruction |= write_back | pre_inc;
2414 *str = p;
2415 return SUCCESS;
2416}
2417
e16bb312 2418static int
a737bd4d 2419cp_byte_address_offset (char ** str)
e16bb312
NC
2420{
2421 int offset;
2422
2423 skip_whitespace (* str);
2424
2425 if (! is_immediate_prefix (**str))
2426 {
2427 inst.error = _("immediate expression expected");
2428 return FAIL;
2429 }
2430
2431 (*str)++;
a737bd4d 2432
e16bb312
NC
2433 if (my_get_expression (& inst.reloc.exp, str))
2434 return FAIL;
a737bd4d 2435
e16bb312
NC
2436 if (inst.reloc.exp.X_op == O_constant)
2437 {
2438 offset = inst.reloc.exp.X_add_number;
a737bd4d 2439
e16bb312
NC
2440 if (offset > 255 || offset < -255)
2441 {
2442 inst.error = _("offset too large");
2443 return FAIL;
2444 }
2445
2446 if (offset >= 0)
2447 inst.instruction |= INDEX_UP;
2448 else
2449 offset = -offset;
2450
2451 inst.instruction |= offset;
2452 }
2453 else
2454 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2455
2456 return SUCCESS;
2457}
2458
2459static int
a737bd4d 2460cp_byte_address_required_here (char ** str)
e16bb312
NC
2461{
2462 char * p = * str;
2463 int pre_inc = 0;
2464 int write_back = 0;
2465
2466 if (*p == '[')
2467 {
2468 int reg;
2469
2470 p++;
2471 skip_whitespace (p);
2472
2473 if ((reg = reg_required_here (& p, 16)) == FAIL)
2474 return FAIL;
2475
2476 skip_whitespace (p);
2477
2478 if (*p == ']')
2479 {
2480 p++;
a737bd4d 2481
e16bb312
NC
2482 if (skip_past_comma (& p) == SUCCESS)
2483 {
2484 /* [Rn], #expr */
2485 write_back = WRITE_BACK;
a737bd4d 2486
e16bb312
NC
2487 if (reg == REG_PC)
2488 {
2489 inst.error = _("pc may not be used in post-increment");
2490 return FAIL;
2491 }
2492
2493 if (cp_byte_address_offset (& p) == FAIL)
2494 return FAIL;
2495 }
2496 else
2497 pre_inc = PRE_INDEX | INDEX_UP;
2498 }
2499 else
2500 {
2501 /* '['Rn, #expr']'[!] */
2502
2503 if (skip_past_comma (& p) == FAIL)
2504 {
2505 inst.error = _("pre-indexed expression expected");
2506 return FAIL;
2507 }
2508
2509 pre_inc = PRE_INDEX;
a737bd4d 2510
e16bb312
NC
2511 if (cp_byte_address_offset (& p) == FAIL)
2512 return FAIL;
2513
2514 skip_whitespace (p);
2515
2516 if (*p++ != ']')
2517 {
2518 inst.error = _("missing ]");
2519 return FAIL;
2520 }
2521
2522 skip_whitespace (p);
2523
2524 if (*p == '!')
2525 {
2526 if (reg == REG_PC)
2527 {
2528 inst.error = _("pc may not be used with write-back");
2529 return FAIL;
2530 }
2531
2532 p++;
2533 write_back = WRITE_BACK;
2534 }
2535 }
2536 }
2537 else
2538 {
2539 if (my_get_expression (&inst.reloc.exp, &p))
2540 return FAIL;
2541
2542 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2543 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2544 inst.reloc.pc_rel = 1;
2545 inst.instruction |= (REG_PC << 16);
2546 pre_inc = PRE_INDEX;
2547 }
2548
2549 inst.instruction |= write_back | pre_inc;
2550 *str = p;
2551 return SUCCESS;
2552}
2553
0dd132b6
NC
2554static void
2555do_nop (char * str)
2556{
2557 skip_whitespace (str);
2558 if (*str == '{')
2559 {
2560 str++;
2561
2562 if (my_get_expression (&inst.reloc.exp, &str))
2563 inst.reloc.exp.X_op = O_illegal;
2564 else
2565 {
2566 skip_whitespace (str);
2567 if (*str == '}')
2568 str++;
2569 else
2570 inst.reloc.exp.X_op = O_illegal;
2571 }
2572
2573 if (inst.reloc.exp.X_op != O_constant
2574 || inst.reloc.exp.X_add_number > 255
2575 || inst.reloc.exp.X_add_number < 0)
2576 {
2577 inst.error = _("Invalid NOP hint");
2578 return;
2579 }
2580
2581 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2582 inst.instruction &= 0xf0000000;
2583 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2584 }
2585
2586 end_of_line (str);
2587}
2588
b99bd4ef 2589static void
a737bd4d 2590do_empty (char * str)
b99bd4ef
NC
2591{
2592 /* Do nothing really. */
b99bd4ef 2593 end_of_line (str);
b99bd4ef
NC
2594}
2595
2596static void
a737bd4d 2597do_mrs (char * str)
b99bd4ef
NC
2598{
2599 int skip = 0;
2600
2601 /* Only one syntax. */
2602 skip_whitespace (str);
2603
2604 if (reg_required_here (&str, 12) == FAIL)
2605 {
2606 inst.error = BAD_ARGS;
2607 return;
2608 }
2609
2610 if (skip_past_comma (&str) == FAIL)
2611 {
2612 inst.error = _("comma expected after register name");
2613 return;
2614 }
2615
2616 skip_whitespace (str);
2617
a737bd4d
NC
2618 if ( streq (str, "CPSR")
2619 || streq (str, "SPSR")
2d2255b5 2620 /* Lower case versions for backwards compatibility. */
a737bd4d
NC
2621 || streq (str, "cpsr")
2622 || streq (str, "spsr"))
b99bd4ef
NC
2623 skip = 4;
2624
2d2255b5 2625 /* This is for backwards compatibility with older toolchains. */
a737bd4d
NC
2626 else if ( streq (str, "cpsr_all")
2627 || streq (str, "spsr_all"))
b99bd4ef
NC
2628 skip = 8;
2629 else
2630 {
f03698e6 2631 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
2632 return;
2633 }
2634
2635 if (* str == 's' || * str == 'S')
2636 inst.instruction |= SPSR_BIT;
2637 str += skip;
2638
b99bd4ef
NC
2639 end_of_line (str);
2640}
2641
2642/* Two possible forms:
2643 "{C|S}PSR_<field>, Rm",
2644 "{C|S}PSR_f, #expression". */
2645
2646static void
a737bd4d 2647do_msr (char * str)
b99bd4ef
NC
2648{
2649 skip_whitespace (str);
2650
2651 if (psr_required_here (& str) == FAIL)
2652 return;
2653
2654 if (skip_past_comma (& str) == FAIL)
2655 {
2656 inst.error = _("comma missing after psr flags");
2657 return;
2658 }
2659
2660 skip_whitespace (str);
2661
2662 if (reg_required_here (& str, 0) != FAIL)
2663 {
2664 inst.error = NULL;
b99bd4ef
NC
2665 end_of_line (str);
2666 return;
2667 }
2668
2669 if (! is_immediate_prefix (* str))
2670 {
2671 inst.error =
2672 _("only a register or immediate value can follow a psr flag");
2673 return;
2674 }
2675
2676 str ++;
2677 inst.error = NULL;
2678
2679 if (my_get_expression (& inst.reloc.exp, & str))
2680 {
2681 inst.error =
2682 _("only a register or immediate value can follow a psr flag");
2683 return;
2684 }
2685
2686#if 0 /* The first edition of the ARM architecture manual stated that
2687 writing anything other than the flags with an immediate operation
2688 had UNPREDICTABLE effects. This constraint was removed in the
2689 second edition of the specification. */
2690 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2691 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2692 {
2693 inst.error = _("immediate value cannot be used to set this field");
2694 return;
2695 }
2696#endif
2697
f2b7cb0a 2698 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
2699
2700 if (inst.reloc.exp.X_add_symbol)
2701 {
2702 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2703 inst.reloc.pc_rel = 0;
2704 }
2705 else
2706 {
2707 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2708
2709 if (value == (unsigned) FAIL)
2710 {
f03698e6 2711 inst.error = _("invalid constant");
b99bd4ef
NC
2712 return;
2713 }
2714
2715 inst.instruction |= value;
2716 }
2717
2718 inst.error = NULL;
b99bd4ef
NC
2719 end_of_line (str);
2720}
2721
2722/* Long Multiply Parser
2723 UMULL RdLo, RdHi, Rm, Rs
2724 SMULL RdLo, RdHi, Rm, Rs
2725 UMLAL RdLo, RdHi, Rm, Rs
2726 SMLAL RdLo, RdHi, Rm, Rs. */
2727
2728static void
a737bd4d 2729do_mull (char * str)
b99bd4ef
NC
2730{
2731 int rdlo, rdhi, rm, rs;
2732
2733 /* Only one format "rdlo, rdhi, rm, rs". */
2734 skip_whitespace (str);
2735
2736 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2737 {
2738 inst.error = BAD_ARGS;
2739 return;
2740 }
2741
2742 if (skip_past_comma (&str) == FAIL
2743 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2744 {
2745 inst.error = BAD_ARGS;
2746 return;
2747 }
2748
2749 if (skip_past_comma (&str) == FAIL
2750 || (rm = reg_required_here (&str, 0)) == FAIL)
2751 {
2752 inst.error = BAD_ARGS;
2753 return;
2754 }
2755
2756 /* rdhi, rdlo and rm must all be different. */
2757 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2758 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2759
2760 if (skip_past_comma (&str) == FAIL
2761 || (rs = reg_required_here (&str, 8)) == FAIL)
2762 {
2763 inst.error = BAD_ARGS;
2764 return;
2765 }
2766
2767 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2768 {
2769 inst.error = BAD_PC;
2770 return;
2771 }
2772
b99bd4ef 2773 end_of_line (str);
b99bd4ef
NC
2774}
2775
2776static void
a737bd4d 2777do_mul (char * str)
b99bd4ef
NC
2778{
2779 int rd, rm;
2780
2781 /* Only one format "rd, rm, rs". */
2782 skip_whitespace (str);
2783
2784 if ((rd = reg_required_here (&str, 16)) == FAIL)
2785 {
2786 inst.error = BAD_ARGS;
2787 return;
2788 }
2789
2790 if (rd == REG_PC)
2791 {
2792 inst.error = BAD_PC;
2793 return;
2794 }
2795
2796 if (skip_past_comma (&str) == FAIL
2797 || (rm = reg_required_here (&str, 0)) == FAIL)
2798 {
2799 inst.error = BAD_ARGS;
2800 return;
2801 }
2802
2803 if (rm == REG_PC)
2804 {
2805 inst.error = BAD_PC;
2806 return;
2807 }
2808
2809 if (rm == rd)
2810 as_tsktsk (_("rd and rm should be different in mul"));
2811
2812 if (skip_past_comma (&str) == FAIL
2813 || (rm = reg_required_here (&str, 8)) == FAIL)
2814 {
2815 inst.error = BAD_ARGS;
2816 return;
2817 }
2818
2819 if (rm == REG_PC)
2820 {
2821 inst.error = BAD_PC;
2822 return;
2823 }
2824
b99bd4ef 2825 end_of_line (str);
b99bd4ef
NC
2826}
2827
2828static void
a737bd4d 2829do_mla (char * str)
b99bd4ef
NC
2830{
2831 int rd, rm;
2832
2833 /* Only one format "rd, rm, rs, rn". */
2834 skip_whitespace (str);
2835
2836 if ((rd = reg_required_here (&str, 16)) == FAIL)
2837 {
2838 inst.error = BAD_ARGS;
2839 return;
2840 }
2841
2842 if (rd == REG_PC)
2843 {
2844 inst.error = BAD_PC;
2845 return;
2846 }
2847
2848 if (skip_past_comma (&str) == FAIL
2849 || (rm = reg_required_here (&str, 0)) == FAIL)
2850 {
2851 inst.error = BAD_ARGS;
2852 return;
2853 }
2854
2855 if (rm == REG_PC)
2856 {
2857 inst.error = BAD_PC;
2858 return;
2859 }
2860
2861 if (rm == rd)
2862 as_tsktsk (_("rd and rm should be different in mla"));
2863
2864 if (skip_past_comma (&str) == FAIL
2865 || (rd = reg_required_here (&str, 8)) == FAIL
2866 || skip_past_comma (&str) == FAIL
2867 || (rm = reg_required_here (&str, 12)) == FAIL)
2868 {
2869 inst.error = BAD_ARGS;
2870 return;
2871 }
2872
2873 if (rd == REG_PC || rm == REG_PC)
2874 {
2875 inst.error = BAD_PC;
2876 return;
2877 }
2878
b99bd4ef 2879 end_of_line (str);
b99bd4ef
NC
2880}
2881
2882/* Expects *str -> the characters "acc0", possibly with leading blanks.
2883 Advances *str to the next non-alphanumeric.
2884 Returns 0, or else FAIL (in which case sets inst.error).
2885
2886 (In a future XScale, there may be accumulators other than zero.
2887 At that time this routine and its callers can be upgraded to suit.) */
2888
2889static int
a737bd4d 2890accum0_required_here (char ** str)
b99bd4ef
NC
2891{
2892 static char buff [128]; /* Note the address is taken. Hence, static. */
2893 char * p = * str;
2894 char c;
2895 int result = 0; /* The accum number. */
2896
2897 skip_whitespace (p);
2898
a737bd4d
NC
2899 *str = p; /* Advance caller's string pointer too. */
2900 c = *p++;
2901 while (ISALNUM (c))
2902 c = *p++;
2903
2904 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2905
2906 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2907 {
2908 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2909 inst.error = buff;
2910 result = FAIL;
2911 }
2912
2913 *p = c; /* Unzap. */
2914 *str = p; /* Caller's string pointer to after match. */
2915 return result;
2916}
2917
2918static int
2919ldst_extend_v4 (char ** str)
2920{
2921 int add = INDEX_UP;
2922
2923 switch (**str)
2924 {
2925 case '#':
2926 case '$':
2927 (*str)++;
2928 if (my_get_expression (& inst.reloc.exp, str))
2929 return FAIL;
2930
2931 if (inst.reloc.exp.X_op == O_constant)
2932 {
2933 int value = inst.reloc.exp.X_add_number;
2934
2935 if (value < -255 || value > 255)
2936 {
2937 inst.error = _("address offset too large");
2938 return FAIL;
2939 }
2940
2941 if (value < 0)
2942 {
2943 value = -value;
2944 add = 0;
2945 }
2946
2947 /* Halfword and signextension instructions have the
2948 immediate value split across bits 11..8 and bits 3..0. */
2949 inst.instruction |= (add | HWOFFSET_IMM
2950 | ((value >> 4) << 8) | (value & 0xF));
2951 }
2952 else
2953 {
2954 inst.instruction |= HWOFFSET_IMM;
2955 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2956 inst.reloc.pc_rel = 0;
2957 }
2958 return SUCCESS;
2959
2960 case '-':
2961 add = 0;
2962 /* Fall through. */
2963
2964 case '+':
2965 (*str)++;
2966 /* Fall through. */
b99bd4ef 2967
a737bd4d
NC
2968 default:
2969 if (reg_required_here (str, 0) == FAIL)
2970 return FAIL;
b99bd4ef 2971
a737bd4d
NC
2972 inst.instruction |= add;
2973 return SUCCESS;
b99bd4ef 2974 }
b99bd4ef
NC
2975}
2976
2977/* Expects **str -> after a comma. May be leading blanks.
2978 Advances *str, recognizing a load mode, and setting inst.instruction.
2979 Returns rn, or else FAIL (in which case may set inst.error
2980 and not advance str)
2981
2982 Note: doesn't know Rd, so no err checks that require such knowledge. */
2983
2984static int
a737bd4d 2985ld_mode_required_here (char ** string)
b99bd4ef
NC
2986{
2987 char * str = * string;
2988 int rn;
2989 int pre_inc = 0;
2990
2991 skip_whitespace (str);
2992
2993 if (* str == '[')
2994 {
2995 str++;
2996
2997 skip_whitespace (str);
2998
2999 if ((rn = reg_required_here (& str, 16)) == FAIL)
3000 return FAIL;
3001
3002 skip_whitespace (str);
3003
3004 if (* str == ']')
3005 {
3006 str ++;
3007
3008 if (skip_past_comma (& str) == SUCCESS)
3009 {
3010 /* [Rn],... (post inc) */
90e4755a 3011 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3012 return FAIL;
3013 }
3014 else /* [Rn] */
3015 {
cc8a6dd0 3016 skip_whitespace (str);
b99bd4ef 3017
cc8a6dd0
KH
3018 if (* str == '!')
3019 {
3020 str ++;
3021 inst.instruction |= WRITE_BACK;
3022 }
b99bd4ef
NC
3023
3024 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3025 pre_inc = 1;
3026 }
3027 }
3028 else /* [Rn,...] */
3029 {
3030 if (skip_past_comma (& str) == FAIL)
3031 {
3032 inst.error = _("pre-indexed expression expected");
3033 return FAIL;
3034 }
3035
3036 pre_inc = 1;
3037
90e4755a 3038 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3039 return FAIL;
3040
3041 skip_whitespace (str);
3042
3043 if (* str ++ != ']')
3044 {
3045 inst.error = _("missing ]");
3046 return FAIL;
3047 }
3048
3049 skip_whitespace (str);
3050
3051 if (* str == '!')
3052 {
3053 str ++;
3054 inst.instruction |= WRITE_BACK;
3055 }
3056 }
3057 }
3058 else if (* str == '=') /* ldr's "r,=label" syntax */
3059 /* We should never reach here, because <text> = <expression> is
3060 caught gas/read.c read_a_source_file() as a .set operation. */
3061 return FAIL;
3062 else /* PC +- 8 bit immediate offset. */
3063 {
3064 if (my_get_expression (& inst.reloc.exp, & str))
3065 return FAIL;
3066
3067 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3068 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3069 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3070 inst.reloc.pc_rel = 1;
3071 inst.instruction |= (REG_PC << 16);
3072
3073 rn = REG_PC;
3074 pre_inc = 1;
3075 }
3076
3077 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3078 * string = str;
3079
3080 return rn;
3081}
3082
3083/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3084 SMLAxy{cond} Rd,Rm,Rs,Rn
3085 SMLAWy{cond} Rd,Rm,Rs,Rn
3086 Error if any register is R15. */
3087
3088static void
a737bd4d 3089do_smla (char * str)
b99bd4ef
NC
3090{
3091 int rd, rm, rs, rn;
3092
3093 skip_whitespace (str);
3094
3095 if ((rd = reg_required_here (& str, 16)) == FAIL
3096 || skip_past_comma (& str) == FAIL
3097 || (rm = reg_required_here (& str, 0)) == FAIL
3098 || skip_past_comma (& str) == FAIL
3099 || (rs = reg_required_here (& str, 8)) == FAIL
3100 || skip_past_comma (& str) == FAIL
3101 || (rn = reg_required_here (& str, 12)) == FAIL)
3102 inst.error = BAD_ARGS;
3103
3104 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3105 inst.error = BAD_PC;
3106
b99bd4ef
NC
3107 else
3108 end_of_line (str);
3109}
3110
3111/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3112 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3113 Error if any register is R15.
3114 Warning if Rdlo == Rdhi. */
3115
3116static void
a737bd4d 3117do_smlal (char * str)
b99bd4ef
NC
3118{
3119 int rdlo, rdhi, rm, rs;
3120
3121 skip_whitespace (str);
3122
3123 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3124 || skip_past_comma (& str) == FAIL
3125 || (rdhi = reg_required_here (& str, 16)) == FAIL
3126 || skip_past_comma (& str) == FAIL
3127 || (rm = reg_required_here (& str, 0)) == FAIL
3128 || skip_past_comma (& str) == FAIL
3129 || (rs = reg_required_here (& str, 8)) == FAIL)
3130 {
3131 inst.error = BAD_ARGS;
3132 return;
3133 }
3134
3135 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3136 {
3137 inst.error = BAD_PC;
3138 return;
3139 }
3140
3141 if (rdlo == rdhi)
3142 as_tsktsk (_("rdhi and rdlo must be different"));
3143
f2b7cb0a 3144 end_of_line (str);
b99bd4ef
NC
3145}
3146
3147/* ARM V5E (El Segundo) signed-multiply (argument parse)
3148 SMULxy{cond} Rd,Rm,Rs
3149 Error if any register is R15. */
3150
3151static void
a737bd4d 3152do_smul (char * str)
b99bd4ef
NC
3153{
3154 int rd, rm, rs;
3155
3156 skip_whitespace (str);
3157
3158 if ((rd = reg_required_here (& str, 16)) == FAIL
3159 || skip_past_comma (& str) == FAIL
3160 || (rm = reg_required_here (& str, 0)) == FAIL
3161 || skip_past_comma (& str) == FAIL
3162 || (rs = reg_required_here (& str, 8)) == FAIL)
3163 inst.error = BAD_ARGS;
3164
3165 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3166 inst.error = BAD_PC;
3167
b99bd4ef
NC
3168 else
3169 end_of_line (str);
3170}
3171
3172/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3173 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3174 Error if any register is R15. */
3175
3176static void
a737bd4d 3177do_qadd (char * str)
b99bd4ef
NC
3178{
3179 int rd, rm, rn;
3180
3181 skip_whitespace (str);
3182
3183 if ((rd = reg_required_here (& str, 12)) == FAIL
3184 || skip_past_comma (& str) == FAIL
3185 || (rm = reg_required_here (& str, 0)) == FAIL
3186 || skip_past_comma (& str) == FAIL
3187 || (rn = reg_required_here (& str, 16)) == FAIL)
3188 inst.error = BAD_ARGS;
3189
3190 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3191 inst.error = BAD_PC;
3192
b99bd4ef
NC
3193 else
3194 end_of_line (str);
3195}
3196
3197/* ARM V5E (el Segundo)
3198 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3199 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3200
3201 These are equivalent to the XScale instructions MAR and MRA,
3202 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3203
3204 Result unpredicatable if Rd or Rn is R15. */
3205
3206static void
a737bd4d 3207do_co_reg2c (char * str)
b99bd4ef
NC
3208{
3209 int rd, rn;
3210
3211 skip_whitespace (str);
3212
3213 if (co_proc_number (& str) == FAIL)
3214 {
3215 if (!inst.error)
3216 inst.error = BAD_ARGS;
3217 return;
3218 }
3219
3220 if (skip_past_comma (& str) == FAIL
3221 || cp_opc_expr (& str, 4, 4) == FAIL)
3222 {
3223 if (!inst.error)
3224 inst.error = BAD_ARGS;
3225 return;
3226 }
3227
3228 if (skip_past_comma (& str) == FAIL
3229 || (rd = reg_required_here (& str, 12)) == FAIL)
3230 {
3231 if (!inst.error)
3232 inst.error = BAD_ARGS;
3233 return;
3234 }
3235
3236 if (skip_past_comma (& str) == FAIL
3237 || (rn = reg_required_here (& str, 16)) == FAIL)
3238 {
3239 if (!inst.error)
3240 inst.error = BAD_ARGS;
3241 return;
3242 }
3243
09d92015
MM
3244 /* Unpredictable result if rd or rn is R15. */
3245 if (rd == REG_PC || rn == REG_PC)
3246 as_tsktsk
3247 (_("Warning: instruction unpredictable when using r15"));
3248
3249 if (skip_past_comma (& str) == FAIL
3250 || cp_reg_required_here (& str, 0) == FAIL)
3251 {
3252 if (!inst.error)
3253 inst.error = BAD_ARGS;
3254 return;
3255 }
3256
3257 end_of_line (str);
3258}
3259
3260/* ARM V5 count-leading-zeroes instruction (argument parse)
3261 CLZ{<cond>} <Rd>, <Rm>
3262 Condition defaults to COND_ALWAYS.
3263 Error if Rd or Rm are R15. */
3264
3265static void
a737bd4d 3266do_clz (char * str)
09d92015
MM
3267{
3268 int rd, rm;
3269
3270 skip_whitespace (str);
3271
3272 if (((rd = reg_required_here (& str, 12)) == FAIL)
3273 || (skip_past_comma (& str) == FAIL)
3274 || ((rm = reg_required_here (& str, 0)) == FAIL))
3275 inst.error = BAD_ARGS;
3276
3277 else if (rd == REG_PC || rm == REG_PC )
3278 inst.error = BAD_PC;
3279
3280 else
3281 end_of_line (str);
3282}
3283
3284/* ARM V5 (argument parse)
3285 LDC2{L} <coproc>, <CRd>, <addressing mode>
3286 STC2{L} <coproc>, <CRd>, <addressing mode>
3287 Instruction is not conditional, and has 0xf in the condition field.
3288 Otherwise, it's the same as LDC/STC. */
3289
3290static void
a737bd4d 3291do_lstc2 (char * str)
09d92015
MM
3292{
3293 skip_whitespace (str);
3294
3295 if (co_proc_number (& str) == FAIL)
3296 {
3297 if (!inst.error)
3298 inst.error = BAD_ARGS;
3299 }
3300 else if (skip_past_comma (& str) == FAIL
3301 || cp_reg_required_here (& str, 12) == FAIL)
3302 {
3303 if (!inst.error)
3304 inst.error = BAD_ARGS;
3305 }
3306 else if (skip_past_comma (& str) == FAIL
3307 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3308 {
3309 if (! inst.error)
3310 inst.error = BAD_ARGS;
3311 }
3312 else
3313 end_of_line (str);
3314}
3315
3316/* ARM V5 (argument parse)
3317 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3318 Instruction is not conditional, and has 0xf in the condition field.
3319 Otherwise, it's the same as CDP. */
3320
3321static void
a737bd4d 3322do_cdp2 (char * str)
09d92015
MM
3323{
3324 skip_whitespace (str);
3325
3326 if (co_proc_number (& str) == FAIL)
3327 {
3328 if (!inst.error)
3329 inst.error = BAD_ARGS;
3330 return;
3331 }
3332
3333 if (skip_past_comma (& str) == FAIL
3334 || cp_opc_expr (& str, 20,4) == FAIL)
3335 {
3336 if (!inst.error)
3337 inst.error = BAD_ARGS;
3338 return;
3339 }
3340
3341 if (skip_past_comma (& str) == FAIL
3342 || cp_reg_required_here (& str, 12) == FAIL)
3343 {
3344 if (!inst.error)
3345 inst.error = BAD_ARGS;
3346 return;
3347 }
3348
3349 if (skip_past_comma (& str) == FAIL
3350 || cp_reg_required_here (& str, 16) == FAIL)
3351 {
3352 if (!inst.error)
3353 inst.error = BAD_ARGS;
3354 return;
3355 }
3356
3357 if (skip_past_comma (& str) == FAIL
3358 || cp_reg_required_here (& str, 0) == FAIL)
3359 {
3360 if (!inst.error)
3361 inst.error = BAD_ARGS;
3362 return;
3363 }
3364
3365 if (skip_past_comma (& str) == SUCCESS)
3366 {
3367 if (cp_opc_expr (& str, 5, 3) == FAIL)
3368 {
3369 if (!inst.error)
3370 inst.error = BAD_ARGS;
3371 return;
3372 }
3373 }
3374
3375 end_of_line (str);
3376}
3377
3378/* ARM V5 (argument parse)
3379 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3380 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3381 Instruction is not conditional, and has 0xf in the condition field.
3382 Otherwise, it's the same as MCR/MRC. */
3383
3384static void
a737bd4d 3385do_co_reg2 (char * str)
09d92015
MM
3386{
3387 skip_whitespace (str);
3388
3389 if (co_proc_number (& str) == FAIL)
3390 {
3391 if (!inst.error)
3392 inst.error = BAD_ARGS;
3393 return;
3394 }
3395
3396 if (skip_past_comma (& str) == FAIL
3397 || cp_opc_expr (& str, 21, 3) == FAIL)
3398 {
3399 if (!inst.error)
3400 inst.error = BAD_ARGS;
3401 return;
3402 }
3403
3404 if (skip_past_comma (& str) == FAIL
3405 || reg_required_here (& str, 12) == FAIL)
3406 {
3407 if (!inst.error)
3408 inst.error = BAD_ARGS;
3409 return;
3410 }
3411
3412 if (skip_past_comma (& str) == FAIL
3413 || cp_reg_required_here (& str, 16) == FAIL)
3414 {
3415 if (!inst.error)
3416 inst.error = BAD_ARGS;
3417 return;
3418 }
3419
3420 if (skip_past_comma (& str) == FAIL
3421 || cp_reg_required_here (& str, 0) == FAIL)
3422 {
3423 if (!inst.error)
3424 inst.error = BAD_ARGS;
3425 return;
3426 }
3427
3428 if (skip_past_comma (& str) == SUCCESS)
3429 {
3430 if (cp_opc_expr (& str, 5, 3) == FAIL)
3431 {
3432 if (!inst.error)
3433 inst.error = BAD_ARGS;
3434 return;
3435 }
3436 }
3437
3438 end_of_line (str);
3439}
3440
a737bd4d
NC
3441static void
3442do_bx (char * str)
3443{
3444 int reg;
3445
3446 skip_whitespace (str);
3447
3448 if ((reg = reg_required_here (&str, 0)) == FAIL)
3449 {
3450 inst.error = BAD_ARGS;
3451 return;
3452 }
3453
3454 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3455 if (reg == REG_PC)
3456 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3457
3458 end_of_line (str);
3459}
3460
09d92015 3461/* ARM v5TEJ. Jump to Jazelle code. */
a737bd4d 3462
09d92015 3463static void
a737bd4d 3464do_bxj (char * str)
09d92015
MM
3465{
3466 int reg;
3467
3468 skip_whitespace (str);
3469
3470 if ((reg = reg_required_here (&str, 0)) == FAIL)
3471 {
3472 inst.error = BAD_ARGS;
3473 return;
3474 }
3475
a737bd4d
NC
3476 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3477 if (reg == REG_PC)
3478 as_tsktsk (_("use of r15 in bxj is not really useful"));
3479
3480 end_of_line (str);
3481}
3482
3483/* ARM V6 umaal (argument parse). */
3484
3485static void
3486do_umaal (char * str)
3487{
3488 int rdlo, rdhi, rm, rs;
3489
3490 skip_whitespace (str);
3491 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3492 || skip_past_comma (& str) == FAIL
3493 || (rdhi = reg_required_here (& str, 16)) == FAIL
3494 || skip_past_comma (& str) == FAIL
3495 || (rm = reg_required_here (& str, 0)) == FAIL
3496 || skip_past_comma (& str) == FAIL
3497 || (rs = reg_required_here (& str, 8)) == FAIL)
3498 {
3499 inst.error = BAD_ARGS;
3500 return;
3501 }
3502
3503 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3504 {
3505 inst.error = BAD_PC;
3506 return;
3507 }
3508
3509 end_of_line (str);
3510}
3511
3512/* ARM V6 strex (argument parse). */
3513
3514static void
3515do_strex (char * str)
3516{
3517 int rd, rm, rn;
3518
3519 /* Parse Rd, Rm,. */
3520 skip_whitespace (str);
3521 if ((rd = reg_required_here (& str, 12)) == FAIL
3522 || skip_past_comma (& str) == FAIL
3523 || (rm = reg_required_here (& str, 0)) == FAIL
3524 || skip_past_comma (& str) == FAIL)
3525 {
3526 inst.error = BAD_ARGS;
3527 return;
3528 }
3529 if (rd == REG_PC || rm == REG_PC)
3530 {
3531 inst.error = BAD_PC;
3532 return;
3533 }
3534 if (rd == rm)
3535 {
3536 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3537 return;
3538 }
3539
3540 /* Skip past '['. */
3541 if ((strlen (str) >= 1)
3542 && strncmp (str, "[", 1) == 0)
3543 str += 1;
3544
3545 skip_whitespace (str);
3546
3547 /* Parse Rn. */
3548 if ((rn = reg_required_here (& str, 16)) == FAIL)
3549 {
3550 inst.error = BAD_ARGS;
3551 return;
3552 }
3553 else if (rn == REG_PC)
3554 {
3555 inst.error = BAD_PC;
3556 return;
3557 }
3558 if (rd == rn)
3559 {
3560 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3561 return;
3562 }
3563 skip_whitespace (str);
3564
3565 /* Skip past ']'. */
3566 if ((strlen (str) >= 1)
3567 && strncmp (str, "]", 1) == 0)
3568 str += 1;
3569
3570 end_of_line (str);
3571}
3572
3573/* KIND indicates what kind of shifts are accepted. */
3574
3575static int
3576decode_shift (char ** str, int kind)
3577{
3578 const struct asm_shift_name * shift;
3579 char * p;
3580 char c;
3581
3582 skip_whitespace (* str);
3583
3584 for (p = * str; ISALPHA (* p); p ++)
3585 ;
3586
3587 if (p == * str)
3588 {
3589 inst.error = _("shift expression expected");
3590 return FAIL;
3591 }
3592
3593 c = * p;
3594 * p = '\0';
3595 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3596 * p = c;
3597
3598 if (shift == NULL)
3599 {
3600 inst.error = _("shift expression expected");
3601 return FAIL;
3602 }
3603
3604 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3605
3606 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3607 && shift->properties->index != SHIFT_LSL
3608 && shift->properties->index != SHIFT_ASR)
3609 {
3610 inst.error = _("'LSL' or 'ASR' required");
3611 return FAIL;
3612 }
3613 else if (kind == SHIFT_LSL_IMMEDIATE
3614 && shift->properties->index != SHIFT_LSL)
3615 {
3616 inst.error = _("'LSL' required");
3617 return FAIL;
3618 }
3619 else if (kind == SHIFT_ASR_IMMEDIATE
3620 && shift->properties->index != SHIFT_ASR)
3621 {
3622 inst.error = _("'ASR' required");
3623 return FAIL;
3624 }
3625
3626 if (shift->properties->index == SHIFT_RRX)
3627 {
3628 * str = p;
3629 inst.instruction |= shift->properties->bit_field;
3630 return SUCCESS;
3631 }
3632
3633 skip_whitespace (p);
3634
3635 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3636 {
3637 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3638 * str = p;
3639 return SUCCESS;
3640 }
3641 else if (! is_immediate_prefix (* p))
3642 {
3643 inst.error = (NO_SHIFT_RESTRICT
3644 ? _("shift requires register or #expression")
3645 : _("shift requires #expression"));
3646 * str = p;
3647 return FAIL;
3648 }
3649
3650 inst.error = NULL;
3651 p ++;
3652
3653 if (my_get_expression (& inst.reloc.exp, & p))
3654 return FAIL;
3655
3656 /* Validate some simple #expressions. */
3657 if (inst.reloc.exp.X_op == O_constant)
3658 {
3659 unsigned num = inst.reloc.exp.X_add_number;
3660
3661 /* Reject operations greater than 32. */
3662 if (num > 32
3663 /* Reject a shift of 0 unless the mode allows it. */
3664 || (num == 0 && shift->properties->allows_0 == 0)
3665 /* Reject a shift of 32 unless the mode allows it. */
3666 || (num == 32 && shift->properties->allows_32 == 0)
3667 )
3668 {
3669 /* As a special case we allow a shift of zero for
3670 modes that do not support it to be recoded as an
3671 logical shift left of zero (ie nothing). We warn
3672 about this though. */
3673 if (num == 0)
3674 {
3675 as_warn (_("shift of 0 ignored."));
3676 shift = & shift_names[0];
3677 assert (shift->properties->index == SHIFT_LSL);
3678 }
3679 else
3680 {
3681 inst.error = _("invalid immediate shift");
3682 return FAIL;
3683 }
3684 }
3685
3686 /* Shifts of 32 are encoded as 0, for those shifts that
3687 support it. */
3688 if (num == 32)
3689 num = 0;
3690
3691 inst.instruction |= (num << 7) | shift->properties->bit_field;
3692 }
3693 else
3694 {
3695 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3696 inst.reloc.pc_rel = 0;
3697 inst.instruction |= shift->properties->bit_field;
3698 }
3699
3700 * str = p;
3701 return SUCCESS;
09d92015
MM
3702}
3703
09d92015 3704static void
a737bd4d 3705do_sat (char ** str, int bias)
09d92015 3706{
a737bd4d
NC
3707 int rd, rm;
3708 expressionS expr;
09d92015 3709
a737bd4d 3710 skip_whitespace (*str);
09d92015 3711
a737bd4d
NC
3712 /* Parse <Rd>, field. */
3713 if ((rd = reg_required_here (str, 12)) == FAIL
3714 || skip_past_comma (str) == FAIL)
09d92015
MM
3715 {
3716 inst.error = BAD_ARGS;
a737bd4d 3717 return;
09d92015 3718 }
a737bd4d 3719 if (rd == REG_PC)
09d92015
MM
3720 {
3721 inst.error = BAD_PC;
3722 return;
3723 }
3724
a737bd4d
NC
3725 /* Parse #<immed>, field. */
3726 if (is_immediate_prefix (**str))
3727 (*str)++;
3728 else
09d92015 3729 {
a737bd4d 3730 inst.error = _("immediate expression expected");
09d92015
MM
3731 return;
3732 }
a737bd4d 3733 if (my_get_expression (&expr, str))
09d92015 3734 {
a737bd4d 3735 inst.error = _("bad expression");
09d92015
MM
3736 return;
3737 }
a737bd4d 3738 if (expr.X_op != O_constant)
09d92015 3739 {
a737bd4d 3740 inst.error = _("constant expression expected");
09d92015
MM
3741 return;
3742 }
a737bd4d
NC
3743 if (expr.X_add_number + bias < 0
3744 || expr.X_add_number + bias > 31)
3745 {
3746 inst.error = _("immediate value out of range");
3747 return;
3748 }
3749 inst.instruction |= (expr.X_add_number + bias) << 16;
3750 if (skip_past_comma (str) == FAIL)
09d92015
MM
3751 {
3752 inst.error = BAD_ARGS;
3753 return;
3754 }
a737bd4d
NC
3755
3756 /* Parse <Rm> field. */
3757 if ((rm = reg_required_here (str, 0)) == FAIL)
09d92015 3758 {
a737bd4d 3759 inst.error = BAD_ARGS;
09d92015
MM
3760 return;
3761 }
a737bd4d 3762 if (rm == REG_PC)
09d92015 3763 {
a737bd4d 3764 inst.error = BAD_PC;
09d92015
MM
3765 return;
3766 }
09d92015 3767
a737bd4d
NC
3768 if (skip_past_comma (str) == SUCCESS)
3769 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
09d92015
MM
3770}
3771
a737bd4d 3772/* ARM V6 ssat (argument parse). */
09d92015
MM
3773
3774static void
a737bd4d 3775do_ssat (char * str)
09d92015
MM
3776{
3777 do_sat (&str, /*bias=*/-1);
3778 end_of_line (str);
3779}
3780
a737bd4d 3781/* ARM V6 usat (argument parse). */
09d92015
MM
3782
3783static void
a737bd4d 3784do_usat (char * str)
09d92015
MM
3785{
3786 do_sat (&str, /*bias=*/0);
3787 end_of_line (str);
3788}
3789
3790static void
a737bd4d 3791do_sat16 (char ** str, int bias)
09d92015
MM
3792{
3793 int rd, rm;
3794 expressionS expr;
3795
3796 skip_whitespace (*str);
a737bd4d
NC
3797
3798 /* Parse the <Rd> field. */
09d92015
MM
3799 if ((rd = reg_required_here (str, 12)) == FAIL
3800 || skip_past_comma (str) == FAIL)
3801 {
3802 inst.error = BAD_ARGS;
3803 return;
3804 }
3805 if (rd == REG_PC)
3806 {
3807 inst.error = BAD_PC;
3808 return;
3809 }
3810
a737bd4d 3811 /* Parse #<immed>, field. */
09d92015
MM
3812 if (is_immediate_prefix (**str))
3813 (*str)++;
3814 else
3815 {
3816 inst.error = _("immediate expression expected");
3817 return;
3818 }
3819 if (my_get_expression (&expr, str))
3820 {
3821 inst.error = _("bad expression");
3822 return;
3823 }
3824 if (expr.X_op != O_constant)
3825 {
3826 inst.error = _("constant expression expected");
3827 return;
3828 }
3829 if (expr.X_add_number + bias < 0
a737bd4d 3830 || expr.X_add_number + bias > 15)
09d92015
MM
3831 {
3832 inst.error = _("immediate value out of range");
3833 return;
3834 }
3835 inst.instruction |= (expr.X_add_number + bias) << 16;
3836 if (skip_past_comma (str) == FAIL)
3837 {
3838 inst.error = BAD_ARGS;
3839 return;
3840 }
3841
a737bd4d 3842 /* Parse <Rm> field. */
09d92015
MM
3843 if ((rm = reg_required_here (str, 0)) == FAIL)
3844 {
3845 inst.error = BAD_ARGS;
3846 return;
3847 }
3848 if (rm == REG_PC)
3849 {
3850 inst.error = BAD_PC;
3851 return;
3852 }
09d92015
MM
3853}
3854
a737bd4d 3855/* ARM V6 ssat16 (argument parse). */
09d92015
MM
3856
3857static void
a737bd4d 3858do_ssat16 (char * str)
09d92015
MM
3859{
3860 do_sat16 (&str, /*bias=*/-1);
3861 end_of_line (str);
3862}
3863
3864static void
a737bd4d 3865do_usat16 (char * str)
09d92015
MM
3866{
3867 do_sat16 (&str, /*bias=*/0);
3868 end_of_line (str);
3869}
3870
3871static void
a737bd4d 3872do_cps_mode (char ** str)
09d92015 3873{
09d92015
MM
3874 expressionS expr;
3875
3876 skip_whitespace (*str);
3877
a737bd4d 3878 if (! is_immediate_prefix (**str))
09d92015
MM
3879 {
3880 inst.error = _("immediate expression expected");
3881 return;
3882 }
a737bd4d
NC
3883
3884 (*str)++; /* Strip off the immediate signifier. */
09d92015
MM
3885 if (my_get_expression (&expr, str))
3886 {
3887 inst.error = _("bad expression");
3888 return;
3889 }
a737bd4d 3890
09d92015
MM
3891 if (expr.X_op != O_constant)
3892 {
3893 inst.error = _("constant expression expected");
3894 return;
3895 }
09d92015 3896
a737bd4d
NC
3897 /* The mode is a 5 bit field. Valid values are 0-31. */
3898 if (((unsigned) expr.X_add_number) > 31
3899 || (inst.reloc.exp.X_add_number) < 0)
09d92015 3900 {
a737bd4d 3901 inst.error = _("invalid constant");
09d92015
MM
3902 return;
3903 }
a737bd4d
NC
3904
3905 inst.instruction |= expr.X_add_number;
09d92015
MM
3906}
3907
a737bd4d 3908/* ARM V6 srs (argument parse). */
09d92015
MM
3909
3910static void
a737bd4d 3911do_srs (char * str)
09d92015
MM
3912{
3913 char *exclam;
3914 skip_whitespace (str);
3915 exclam = strchr (str, '!');
3916 if (exclam)
3917 *exclam = '\0';
3918 do_cps_mode (&str);
3919 if (exclam)
3920 *exclam = '!';
a737bd4d 3921 if (*str == '!')
09d92015
MM
3922 {
3923 inst.instruction |= WRITE_BACK;
3924 str++;
3925 }
3926 end_of_line (str);
3927}
3928
a737bd4d 3929/* ARM V6 SMMUL (argument parse). */
09d92015
MM
3930
3931static void
a737bd4d 3932do_smmul (char * str)
09d92015
MM
3933{
3934 int rd, rm, rs;
a737bd4d 3935
09d92015
MM
3936 skip_whitespace (str);
3937 if ((rd = reg_required_here (&str, 16)) == FAIL
3938 || skip_past_comma (&str) == FAIL
3939 || (rm = reg_required_here (&str, 0)) == FAIL
3940 || skip_past_comma (&str) == FAIL
3941 || (rs = reg_required_here (&str, 8)) == FAIL)
3942 {
3943 inst.error = BAD_ARGS;
3944 return;
3945 }
3946
a737bd4d 3947 if ( rd == REG_PC
09d92015
MM
3948 || rm == REG_PC
3949 || rs == REG_PC)
3950 {
3951 inst.error = BAD_PC;
3952 return;
3953 }
3954
3955 end_of_line (str);
09d92015
MM
3956}
3957
a737bd4d 3958/* ARM V6 SMLALD (argument parse). */
09d92015
MM
3959
3960static void
a737bd4d 3961do_smlald (char * str)
09d92015
MM
3962{
3963 int rdlo, rdhi, rm, rs;
a737bd4d 3964
09d92015
MM
3965 skip_whitespace (str);
3966 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3967 || skip_past_comma (&str) == FAIL
3968 || (rdhi = reg_required_here (&str, 16)) == FAIL
3969 || skip_past_comma (&str) == FAIL
3970 || (rm = reg_required_here (&str, 0)) == FAIL
3971 || skip_past_comma (&str) == FAIL
3972 || (rs = reg_required_here (&str, 8)) == FAIL)
3973 {
3974 inst.error = BAD_ARGS;
3975 return;
3976 }
3977
a737bd4d
NC
3978 if ( rdlo == REG_PC
3979 || rdhi == REG_PC
09d92015
MM
3980 || rm == REG_PC
3981 || rs == REG_PC)
3982 {
3983 inst.error = BAD_PC;
3984 return;
3985 }
3986
3987 end_of_line (str);
3988}
3989
a737bd4d 3990/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
09d92015
MM
3991 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3992
a737bd4d
NC
3993static void
3994do_smlad (char * str)
09d92015
MM
3995{
3996 int rd, rm, rs, rn;
a737bd4d 3997
09d92015
MM
3998 skip_whitespace (str);
3999 if ((rd = reg_required_here (&str, 16)) == FAIL
4000 || skip_past_comma (&str) == FAIL
4001 || (rm = reg_required_here (&str, 0)) == FAIL
4002 || skip_past_comma (&str) == FAIL
4003 || (rs = reg_required_here (&str, 8)) == FAIL
4004 || skip_past_comma (&str) == FAIL
4005 || (rn = reg_required_here (&str, 12)) == FAIL)
4006 {
4007 inst.error = BAD_ARGS;
4008 return;
4009 }
a737bd4d
NC
4010
4011 if ( rd == REG_PC
4012 || rn == REG_PC
09d92015
MM
4013 || rs == REG_PC
4014 || rm == REG_PC)
4015 {
4016 inst.error = BAD_PC;
4017 return;
4018 }
4019
4020 end_of_line (str);
09d92015
MM
4021}
4022
4023/* Returns true if the endian-specifier indicates big-endianness. */
4024
4025static int
a737bd4d 4026do_endian_specifier (char * str)
09d92015
MM
4027{
4028 int big_endian = 0;
4029
4030 skip_whitespace (str);
4031 if (strlen (str) < 2)
4032 inst.error = _("missing endian specifier");
4033 else if (strncasecmp (str, "BE", 2) == 0)
4034 {
4035 str += 2;
4036 big_endian = 1;
4037 }
4038 else if (strncasecmp (str, "LE", 2) == 0)
4039 str += 2;
4040 else
4041 inst.error = _("valid endian specifiers are be or le");
4042
4043 end_of_line (str);
4044
4045 return big_endian;
4046}
4047
a737bd4d
NC
4048/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4049 preserving the other bits.
4050
4051 setend <endian_specifier>, where <endian_specifier> is either
4052 BE or LE. */
4053
4054static void
4055do_setend (char * str)
4056{
4057 if (do_endian_specifier (str))
4058 inst.instruction |= 0x200;
4059}
4060
09d92015
MM
4061/* ARM V6 SXTH.
4062
4063 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4064 Condition defaults to COND_ALWAYS.
a737bd4d 4065 Error if any register uses R15. */
09d92015 4066
a737bd4d
NC
4067static void
4068do_sxth (char * str)
09d92015
MM
4069{
4070 int rd, rm;
4071 expressionS expr;
4072 int rotation_clear_mask = 0xfffff3ff;
4073 int rotation_eight_mask = 0x00000400;
4074 int rotation_sixteen_mask = 0x00000800;
4075 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4076
09d92015
MM
4077 skip_whitespace (str);
4078 if ((rd = reg_required_here (&str, 12)) == FAIL
4079 || skip_past_comma (&str) == FAIL
4080 || (rm = reg_required_here (&str, 0)) == FAIL)
4081 {
4082 inst.error = BAD_ARGS;
4083 return;
4084 }
4085
4086 else if (rd == REG_PC || rm == REG_PC)
4087 {
4088 inst.error = BAD_PC;
4089 return;
4090 }
a737bd4d
NC
4091
4092 /* Zero out the rotation field. */
09d92015 4093 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4094
4095 /* Check for lack of optional rotation field. */
09d92015
MM
4096 if (skip_past_comma (&str) == FAIL)
4097 {
4098 end_of_line (str);
4099 return;
4100 }
a737bd4d
NC
4101
4102 /* Move past 'ROR'. */
09d92015
MM
4103 skip_whitespace (str);
4104 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4105 str += 3;
09d92015
MM
4106 else
4107 {
4108 inst.error = _("missing rotation field after comma");
4109 return;
4110 }
a737bd4d
NC
4111
4112 /* Get the immediate constant. */
09d92015
MM
4113 skip_whitespace (str);
4114 if (is_immediate_prefix (* str))
4115 str++;
4116 else
4117 {
4118 inst.error = _("immediate expression expected");
4119 return;
4120 }
a737bd4d 4121
09d92015
MM
4122 if (my_get_expression (&expr, &str))
4123 {
4124 inst.error = _("bad expression");
4125 return;
4126 }
4127
4128 if (expr.X_op != O_constant)
4129 {
4130 inst.error = _("constant expression expected");
4131 return;
4132 }
a737bd4d
NC
4133
4134 switch (expr.X_add_number)
09d92015
MM
4135 {
4136 case 0:
a737bd4d 4137 /* Rotation field has already been zeroed. */
09d92015
MM
4138 break;
4139 case 8:
4140 inst.instruction |= rotation_eight_mask;
4141 break;
4142
4143 case 16:
4144 inst.instruction |= rotation_sixteen_mask;
4145 break;
a737bd4d 4146
09d92015
MM
4147 case 24:
4148 inst.instruction |= rotation_twenty_four_mask;
4149 break;
4150
4151 default:
4152 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4153 break;
4154 }
4155
4156 end_of_line (str);
09d92015
MM
4157}
4158
4159/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4160 extends it to 32-bits, and adds the result to a value in another
4161 register. You can specify a rotation by 0, 8, 16, or 24 bits
4162 before extracting the 16-bit value.
4163 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4164 Condition defaults to COND_ALWAYS.
a737bd4d 4165 Error if any register uses R15. */
09d92015 4166
a737bd4d
NC
4167static void
4168do_sxtah (char * str)
09d92015
MM
4169{
4170 int rd, rn, rm;
4171 expressionS expr;
4172 int rotation_clear_mask = 0xfffff3ff;
4173 int rotation_eight_mask = 0x00000400;
4174 int rotation_sixteen_mask = 0x00000800;
4175 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4176
09d92015
MM
4177 skip_whitespace (str);
4178 if ((rd = reg_required_here (&str, 12)) == FAIL
4179 || skip_past_comma (&str) == FAIL
4180 || (rn = reg_required_here (&str, 16)) == FAIL
4181 || skip_past_comma (&str) == FAIL
4182 || (rm = reg_required_here (&str, 0)) == FAIL)
4183 {
4184 inst.error = BAD_ARGS;
4185 return;
4186 }
4187
4188 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4189 {
4190 inst.error = BAD_PC;
4191 return;
4192 }
a737bd4d
NC
4193
4194 /* Zero out the rotation field. */
09d92015 4195 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4196
4197 /* Check for lack of optional rotation field. */
09d92015
MM
4198 if (skip_past_comma (&str) == FAIL)
4199 {
4200 end_of_line (str);
4201 return;
4202 }
a737bd4d
NC
4203
4204 /* Move past 'ROR'. */
09d92015
MM
4205 skip_whitespace (str);
4206 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4207 str += 3;
09d92015
MM
4208 else
4209 {
4210 inst.error = _("missing rotation field after comma");
4211 return;
4212 }
a737bd4d
NC
4213
4214 /* Get the immediate constant. */
09d92015
MM
4215 skip_whitespace (str);
4216 if (is_immediate_prefix (* str))
4217 str++;
4218 else
4219 {
4220 inst.error = _("immediate expression expected");
4221 return;
4222 }
a737bd4d 4223
09d92015
MM
4224 if (my_get_expression (&expr, &str))
4225 {
4226 inst.error = _("bad expression");
4227 return;
4228 }
4229
4230 if (expr.X_op != O_constant)
4231 {
4232 inst.error = _("constant expression expected");
4233 return;
4234 }
a737bd4d
NC
4235
4236 switch (expr.X_add_number)
09d92015
MM
4237 {
4238 case 0:
a737bd4d 4239 /* Rotation field has already been zeroed. */
09d92015
MM
4240 break;
4241
4242 case 8:
4243 inst.instruction |= rotation_eight_mask;
4244 break;
4245
4246 case 16:
4247 inst.instruction |= rotation_sixteen_mask;
4248 break;
a737bd4d 4249
09d92015
MM
4250 case 24:
4251 inst.instruction |= rotation_twenty_four_mask;
4252 break;
4253
4254 default:
4255 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4256 break;
4257 }
4258
4259 end_of_line (str);
09d92015 4260}
a737bd4d 4261
09d92015
MM
4262
4263/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4264 word at the specified address and the following word
a737bd4d 4265 respectively.
09d92015 4266 Unconditionally executed.
a737bd4d 4267 Error if Rn is R15. */
09d92015
MM
4268
4269static void
a737bd4d 4270do_rfe (char * str)
09d92015
MM
4271{
4272 int rn;
4273
4274 skip_whitespace (str);
a737bd4d 4275
09d92015
MM
4276 if ((rn = reg_required_here (&str, 16)) == FAIL)
4277 return;
b99bd4ef 4278
09d92015 4279 if (rn == REG_PC)
b99bd4ef 4280 {
09d92015 4281 inst.error = BAD_PC;
b99bd4ef
NC
4282 return;
4283 }
4284
09d92015 4285 skip_whitespace (str);
a737bd4d 4286
09d92015
MM
4287 if (*str == '!')
4288 {
4289 inst.instruction |= WRITE_BACK;
4290 str++;
4291 }
b99bd4ef
NC
4292 end_of_line (str);
4293}
4294
09d92015
MM
4295/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4296 register (argument parse).
4297 REV{<cond>} Rd, Rm.
4298 Condition defaults to COND_ALWAYS.
a737bd4d 4299 Error if Rd or Rm are R15. */
b99bd4ef
NC
4300
4301static void
a737bd4d 4302do_rev (char * str)
b99bd4ef
NC
4303{
4304 int rd, rm;
4305
b99bd4ef
NC
4306 skip_whitespace (str);
4307
09d92015
MM
4308 if ((rd = reg_required_here (&str, 12)) == FAIL
4309 || skip_past_comma (&str) == FAIL
4310 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
4311 inst.error = BAD_ARGS;
4312
09d92015 4313 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
4314 inst.error = BAD_PC;
4315
4316 else
4317 end_of_line (str);
4318}
4319
09d92015 4320/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
a737bd4d 4321 QADD16{<cond>} <Rd>, <Rn>, <Rm>
09d92015
MM
4322 Condition defaults to COND_ALWAYS.
4323 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
4324
4325static void
a737bd4d 4326do_qadd16 (char * str)
b99bd4ef 4327{
09d92015
MM
4328 int rd, rm, rn;
4329
b99bd4ef
NC
4330 skip_whitespace (str);
4331
09d92015
MM
4332 if ((rd = reg_required_here (&str, 12)) == FAIL
4333 || skip_past_comma (&str) == FAIL
4334 || (rn = reg_required_here (&str, 16)) == FAIL
4335 || skip_past_comma (&str) == FAIL
4336 || (rm = reg_required_here (&str, 0)) == FAIL)
4337 inst.error = BAD_ARGS;
4338
4339 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4340 inst.error = BAD_PC;
4341
b99bd4ef
NC
4342 else
4343 end_of_line (str);
4344}
4345
b99bd4ef 4346static void
a737bd4d 4347do_pkh_core (char * str, int shift)
b99bd4ef 4348{
09d92015 4349 int rd, rn, rm;
b99bd4ef 4350
09d92015
MM
4351 skip_whitespace (str);
4352 if (((rd = reg_required_here (&str, 12)) == FAIL)
4353 || (skip_past_comma (&str) == FAIL)
4354 || ((rn = reg_required_here (&str, 16)) == FAIL)
4355 || (skip_past_comma (&str) == FAIL)
4356 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 4357 {
09d92015 4358 inst.error = BAD_ARGS;
b99bd4ef
NC
4359 return;
4360 }
4361
09d92015 4362 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 4363 {
09d92015 4364 inst.error = BAD_PC;
b99bd4ef
NC
4365 return;
4366 }
4367
a737bd4d
NC
4368 /* Check for optional shift immediate constant. */
4369 if (skip_past_comma (&str) == FAIL)
b99bd4ef 4370 {
09d92015
MM
4371 if (shift == SHIFT_ASR_IMMEDIATE)
4372 {
4373 /* If the shift specifier is ommited, turn the instruction
4374 into pkhbt rd, rm, rn. First, switch the instruction
4375 code, and clear the rn and rm fields. */
4376 inst.instruction &= 0xfff0f010;
4377 /* Now, re-encode the registers. */
4378 inst.instruction |= (rm << 16) | rn;
4379 }
b99bd4ef
NC
4380 return;
4381 }
4382
09d92015
MM
4383 decode_shift (&str, shift);
4384}
4385
a737bd4d
NC
4386/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4387 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4388 Condition defaults to COND_ALWAYS.
4389 Error if Rd, Rn or Rm are R15. */
4390
4391static void
4392do_pkhbt (char * str)
4393{
4394 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4395}
4396
4397/* ARM V6 PKHTB (Argument Parse). */
4398
4399static void
4400do_pkhtb (char * str)
4401{
4402 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4403}
4404
09d92015 4405/* ARM V6 Load Register Exclusive instruction (argument parse).
0dd132b6 4406 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
09d92015 4407 Condition defaults to COND_ALWAYS.
a737bd4d
NC
4408 Error if Rd or Rn are R15.
4409 See ARMARMv6 A4.1.27: LDREX. */
09d92015
MM
4410
4411static void
a737bd4d 4412do_ldrex (char * str)
09d92015
MM
4413{
4414 int rd, rn;
4415
4416 skip_whitespace (str);
4417
a737bd4d 4418 /* Parse Rd. */
09d92015
MM
4419 if (((rd = reg_required_here (&str, 12)) == FAIL)
4420 || (skip_past_comma (&str) == FAIL))
b99bd4ef 4421 {
09d92015 4422 inst.error = BAD_ARGS;
b99bd4ef
NC
4423 return;
4424 }
09d92015 4425 else if (rd == REG_PC)
b99bd4ef 4426 {
09d92015 4427 inst.error = BAD_PC;
b99bd4ef
NC
4428 return;
4429 }
a737bd4d 4430 skip_whitespace (str);
b99bd4ef 4431
a737bd4d
NC
4432 /* Skip past '['. */
4433 if ((strlen (str) >= 1)
09d92015 4434 &&strncmp (str, "[", 1) == 0)
a737bd4d
NC
4435 str += 1;
4436 skip_whitespace (str);
09d92015 4437
a737bd4d 4438 /* Parse Rn. */
09d92015 4439 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 4440 {
09d92015
MM
4441 inst.error = BAD_ARGS;
4442 return;
b99bd4ef 4443 }
09d92015
MM
4444 else if (rn == REG_PC)
4445 {
4446 inst.error = BAD_PC;
4447 return;
4448 }
a737bd4d 4449 skip_whitespace (str);
b99bd4ef 4450
a737bd4d
NC
4451 /* Skip past ']'. */
4452 if ((strlen (str) >= 1)
09d92015 4453 && strncmp (str, "]", 1) == 0)
a737bd4d
NC
4454 str += 1;
4455
b99bd4ef
NC
4456 end_of_line (str);
4457}
4458
09d92015 4459/* ARM V6 change processor state instruction (argument parse)
a737bd4d 4460 CPS, CPSIE, CSPID . */
b99bd4ef
NC
4461
4462static void
a737bd4d 4463do_cps (char * str)
b99bd4ef 4464{
09d92015
MM
4465 do_cps_mode (&str);
4466 end_of_line (str);
4467}
b99bd4ef 4468
09d92015 4469static void
a737bd4d 4470do_cps_flags (char ** str, int thumb_p)
ea6ef066 4471{
a737bd4d
NC
4472 struct cps_flag
4473 {
09d92015
MM
4474 char character;
4475 unsigned long arm_value;
4476 unsigned long thumb_value;
4477 };
a737bd4d
NC
4478 static struct cps_flag flag_table[] =
4479 {
09d92015
MM
4480 {'a', 0x100, 0x4 },
4481 {'i', 0x080, 0x2 },
4482 {'f', 0x040, 0x1 }
4483 };
ea6ef066 4484
09d92015 4485 int saw_a_flag = 0;
ea6ef066 4486
09d92015
MM
4487 skip_whitespace (*str);
4488
a737bd4d 4489 /* Get the a, f and i flags. */
09d92015 4490 while (**str && **str != ',')
ea6ef066 4491 {
09d92015
MM
4492 struct cps_flag *p;
4493 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
a737bd4d 4494
09d92015
MM
4495 for (p = flag_table; p < q; ++p)
4496 if (strncasecmp (*str, &p->character, 1) == 0)
4497 {
4498 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4499 saw_a_flag = 1;
4500 break;
4501 }
4502 if (p == q)
4503 {
4504 inst.error = _("unrecognized flag");
4505 return;
4506 }
4507 (*str)++;
ea6ef066 4508 }
a737bd4d
NC
4509
4510 if (!saw_a_flag)
4511 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4512}
4513
4514static void
4515do_cpsi (char * str)
4516{
4517 do_cps_flags (&str, /*thumb_p=*/0);
4518
4519 if (skip_past_comma (&str) == SUCCESS)
4520 {
4521 skip_whitespace (str);
4522 do_cps_mode (&str);
4523 }
4524 end_of_line (str);
ea6ef066
RE
4525}
4526
b99bd4ef
NC
4527/* THUMB V5 breakpoint instruction (argument parse)
4528 BKPT <immed_8>. */
4529
4530static void
a737bd4d 4531do_t_bkpt (char * str)
b99bd4ef
NC
4532{
4533 expressionS expr;
4534 unsigned long number;
4535
4536 skip_whitespace (str);
4537
4538 /* Allow optional leading '#'. */
4539 if (is_immediate_prefix (*str))
4540 str ++;
4541
4542 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
4543 if (my_get_expression (& expr, & str)
4544 || (expr.X_op != O_constant
4545 /* As a convenience we allow 'bkpt' without an operand. */
4546 && expr.X_op != O_absent))
b99bd4ef 4547 {
143c8e19 4548 inst.error = _("bad expression");
b99bd4ef
NC
4549 return;
4550 }
4551
4552 number = expr.X_add_number;
4553
4554 /* Check it fits an 8 bit unsigned. */
4555 if (number != (number & 0xff))
4556 {
4557 inst.error = _("immediate value out of range");
4558 return;
4559 }
4560
4561 inst.instruction |= number;
4562
4563 end_of_line (str);
4564}
4565
a737bd4d
NC
4566static bfd_reloc_code_real_type
4567arm_parse_reloc (void)
4568{
4569 char id [16];
4570 char * ip;
4571 unsigned int i;
4572 static struct
4573 {
4574 char * str;
4575 int len;
4576 bfd_reloc_code_real_type reloc;
4577 }
4578 reloc_map[] =
4579 {
4580#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4581 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4582 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4583 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4584 branch instructions generated by GCC for PLT relocs. */
4585 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4586 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4587 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4588 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4589 { NULL, 0, BFD_RELOC_UNUSED }
4590#undef MAP
4591 };
4592
4593 for (i = 0, ip = input_line_pointer;
4594 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4595 i++, ip++)
4596 id[i] = TOLOWER (*ip);
4597
4598 for (i = 0; reloc_map[i].str; i++)
4599 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4600 break;
4601
4602 input_line_pointer += reloc_map[i].len;
4603
4604 return reloc_map[i].reloc;
4605}
4606
b99bd4ef
NC
4607/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4608 Expects inst.instruction is set for BLX(1).
4609 Note: this is cloned from do_branch, and the reloc changed to be a
4610 new one that can cope with setting one extra bit (the H bit). */
4611
4612static void
a737bd4d 4613do_branch25 (char * str)
b99bd4ef
NC
4614{
4615 if (my_get_expression (& inst.reloc.exp, & str))
4616 return;
4617
4618#ifdef OBJ_ELF
4619 {
4620 char * save_in;
4621
4622 /* ScottB: February 5, 1998 */
4623 /* Check to see of PLT32 reloc required for the instruction. */
4624
4625 /* arm_parse_reloc() works on input_line_pointer.
4626 We actually want to parse the operands to the branch instruction
4627 passed in 'str'. Save the input pointer and restore it later. */
4628 save_in = input_line_pointer;
4629 input_line_pointer = str;
4630
4631 if (inst.reloc.exp.X_op == O_symbol
4632 && *str == '('
4633 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4634 {
4635 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4636 inst.reloc.pc_rel = 0;
4637 /* Modify str to point to after parsed operands, otherwise
4638 end_of_line() will complain about the (PLT) left in str. */
4639 str = input_line_pointer;
4640 }
4641 else
4642 {
4643 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4644 inst.reloc.pc_rel = 1;
4645 }
4646
4647 input_line_pointer = save_in;
4648 }
4649#else
4650 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4651 inst.reloc.pc_rel = 1;
4652#endif /* OBJ_ELF */
4653
4654 end_of_line (str);
4655}
4656
4657/* ARM V5 branch-link-exchange instruction (argument parse)
4658 BLX <target_addr> ie BLX(1)
4659 BLX{<condition>} <Rm> ie BLX(2)
4660 Unfortunately, there are two different opcodes for this mnemonic.
4661 So, the insns[].value is not used, and the code here zaps values
4662 into inst.instruction.
4663 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4664
4665static void
a737bd4d 4666do_blx (char * str)
b99bd4ef
NC
4667{
4668 char * mystr = str;
4669 int rm;
4670
b99bd4ef
NC
4671 skip_whitespace (mystr);
4672 rm = reg_required_here (& mystr, 0);
4673
4674 /* The above may set inst.error. Ignore his opinion. */
4675 inst.error = 0;
4676
4677 if (rm != FAIL)
4678 {
4679 /* Arg is a register.
4680 Use the condition code our caller put in inst.instruction.
4681 Pass ourselves off as a BX with a funny opcode. */
4682 inst.instruction |= 0x012fff30;
f2b7cb0a 4683 do_bx (str);
b99bd4ef
NC
4684 }
4685 else
4686 {
4687 /* This must be is BLX <target address>, no condition allowed. */
4688 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4689 {
4690 inst.error = BAD_COND;
b99bd4ef 4691 return;
cc8a6dd0 4692 }
b99bd4ef
NC
4693
4694 inst.instruction = 0xfafffffe;
4695
4696 /* Process like a B/BL, but with a different reloc.
4697 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4698 do_branch25 (str);
b99bd4ef
NC
4699 }
4700}
4701
4702/* ARM V5 Thumb BLX (argument parse)
4703 BLX <target_addr> which is BLX(1)
4704 BLX <Rm> which is BLX(2)
4705 Unfortunately, there are two different opcodes for this mnemonic.
4706 So, the tinsns[].value is not used, and the code here zaps values
4707 into inst.instruction. */
4708
4709static void
a737bd4d 4710do_t_blx (char * str)
b99bd4ef
NC
4711{
4712 char * mystr = str;
4713 int rm;
4714
4715 skip_whitespace (mystr);
4716 inst.instruction = 0x4780;
4717
4718 /* Note that this call is to the ARM register recognizer. BLX(2)
4719 uses the ARM register space, not the Thumb one, so a call to
4720 thumb_reg() would be wrong. */
4721 rm = reg_required_here (& mystr, 3);
4722 inst.error = 0;
4723
4724 if (rm != FAIL)
4725 {
4726 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4727 inst.size = 2;
4728 }
4729 else
4730 {
4731 /* No ARM register. This must be BLX(1). Change the .instruction. */
4732 inst.instruction = 0xf7ffeffe;
4733 inst.size = 4;
4734
4735 if (my_get_expression (& inst.reloc.exp, & mystr))
4736 return;
4737
4738 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4739 inst.reloc.pc_rel = 1;
4740 }
4741
4742 end_of_line (mystr);
4743}
4744
4745/* ARM V5 breakpoint instruction (argument parse)
4746 BKPT <16 bit unsigned immediate>
4747 Instruction is not conditional.
4748 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 4749 and it is an error if the caller tried to override that. */
b99bd4ef
NC
4750
4751static void
a737bd4d 4752do_bkpt (char * str)
b99bd4ef
NC
4753{
4754 expressionS expr;
4755 unsigned long number;
4756
4757 skip_whitespace (str);
4758
4759 /* Allow optional leading '#'. */
4760 if (is_immediate_prefix (* str))
4761 str++;
4762
4763 memset (& expr, '\0', sizeof (expr));
4764
143c8e19
NC
4765 if (my_get_expression (& expr, & str)
4766 || (expr.X_op != O_constant
4767 /* As a convenience we allow 'bkpt' without an operand. */
4768 && expr.X_op != O_absent))
b99bd4ef 4769 {
143c8e19 4770 inst.error = _("bad expression");
b99bd4ef
NC
4771 return;
4772 }
4773
4774 number = expr.X_add_number;
4775
4776 /* Check it fits a 16 bit unsigned. */
4777 if (number != (number & 0xffff))
4778 {
4779 inst.error = _("immediate value out of range");
4780 return;
4781 }
4782
4783 /* Top 12 of 16 bits to bits 19:8. */
4784 inst.instruction |= (number & 0xfff0) << 4;
4785
4786 /* Bottom 4 of 16 bits to bits 3:0. */
4787 inst.instruction |= number & 0xf;
4788
4789 end_of_line (str);
b99bd4ef
NC
4790}
4791
09d92015
MM
4792/* THUMB CPS instruction (argument parse). */
4793
4794static void
a737bd4d 4795do_t_cps (char * str)
09d92015
MM
4796{
4797 do_cps_flags (&str, /*thumb_p=*/1);
4798 end_of_line (str);
4799}
4800
a737bd4d
NC
4801/* Parse and validate that a register is of the right form, this saves
4802 repeated checking of this information in many similar cases.
4803 Unlike the 32-bit case we do not insert the register into the opcode
4804 here, since the position is often unknown until the full instruction
4805 has been parsed. */
4806
4807static int
4808thumb_reg (char ** strp, int hi_lo)
4809{
4810 int reg;
4811
4812 if ((reg = reg_required_here (strp, -1)) == FAIL)
4813 return FAIL;
4814
4815 switch (hi_lo)
4816 {
4817 case THUMB_REG_LO:
4818 if (reg > 7)
4819 {
4820 inst.error = _("lo register required");
4821 return FAIL;
4822 }
4823 break;
4824
4825 case THUMB_REG_HI:
4826 if (reg < 8)
4827 {
4828 inst.error = _("hi register required");
4829 return FAIL;
4830 }
4831 break;
4832
4833 default:
4834 break;
4835 }
4836
4837 return reg;
4838}
4839
4840static void
4841thumb_mov_compare (char * str, int move)
4842{
4843 int Rd, Rs = FAIL;
4844
4845 skip_whitespace (str);
4846
4847 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4848 || skip_past_comma (&str) == FAIL)
4849 {
4850 if (! inst.error)
4851 inst.error = BAD_ARGS;
4852 return;
4853 }
4854
4855 if (move != THUMB_CPY && is_immediate_prefix (*str))
4856 {
4857 str++;
4858 if (my_get_expression (&inst.reloc.exp, &str))
4859 return;
4860 }
4861 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4862 return;
4863
4864 if (Rs != FAIL)
4865 {
4866 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4867 {
4868 if (move == THUMB_MOVE)
4869 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4870 since a MOV instruction produces unpredictable results. */
4871 inst.instruction = T_OPCODE_ADD_I3;
4872 else
4873 inst.instruction = T_OPCODE_CMP_LR;
4874 inst.instruction |= Rd | (Rs << 3);
4875 }
4876 else
4877 {
4878 if (move == THUMB_MOVE)
4879 inst.instruction = T_OPCODE_MOV_HR;
4880 else if (move != THUMB_CPY)
4881 inst.instruction = T_OPCODE_CMP_HR;
4882
4883 if (Rd > 7)
4884 inst.instruction |= THUMB_H1;
4885
4886 if (Rs > 7)
4887 inst.instruction |= THUMB_H2;
4888
4889 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4890 }
4891 }
4892 else
4893 {
4894 if (Rd > 7)
4895 {
4896 inst.error = _("only lo regs allowed with immediate");
4897 return;
4898 }
4899
4900 if (move == THUMB_MOVE)
4901 inst.instruction = T_OPCODE_MOV_I8;
4902 else
4903 inst.instruction = T_OPCODE_CMP_I8;
4904
4905 inst.instruction |= Rd << 8;
4906
4907 if (inst.reloc.exp.X_op != O_constant)
4908 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4909 else
4910 {
4911 unsigned value = inst.reloc.exp.X_add_number;
4912
4913 if (value > 255)
4914 {
4915 inst.error = _("invalid immediate");
4916 return;
4917 }
4918
4919 inst.instruction |= value;
4920 }
4921 }
4922
4923 end_of_line (str);
4924}
4925
09d92015
MM
4926/* THUMB CPY instruction (argument parse). */
4927
4928static void
a737bd4d 4929do_t_cpy (char * str)
09d92015
MM
4930{
4931 thumb_mov_compare (str, THUMB_CPY);
4932}
4933
4934/* THUMB SETEND instruction (argument parse). */
4935
4936static void
a737bd4d 4937do_t_setend (char * str)
09d92015
MM
4938{
4939 if (do_endian_specifier (str))
4940 inst.instruction |= 0x8;
4941}
4942
e16bb312
NC
4943/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4944
4945static unsigned long
a737bd4d
NC
4946check_iwmmxt_insn (char * str,
4947 enum iwmmxt_insn_type insn_type,
4948 int immediate_size)
e16bb312
NC
4949{
4950 int reg = 0;
4951 const char * inst_error;
4952 expressionS expr;
4953 unsigned long number;
4954
4955 inst_error = inst.error;
4956 if (!inst.error)
4957 inst.error = BAD_ARGS;
4958 skip_whitespace (str);
4959
4960 switch (insn_type)
4961 {
4962 case check_rd:
4963 if ((reg = reg_required_here (&str, 12)) == FAIL)
4964 return FAIL;
4965 break;
a737bd4d 4966
e16bb312
NC
4967 case check_wr:
4968 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4969 return FAIL;
4970 break;
a737bd4d 4971
e16bb312
NC
4972 case check_wrwr:
4973 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4974 || skip_past_comma (&str) == FAIL
4975 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4976 return FAIL;
4977 break;
a737bd4d 4978
e16bb312
NC
4979 case check_wrwrwr:
4980 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4981 || skip_past_comma (&str) == FAIL
4982 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4983 || skip_past_comma (&str) == FAIL
4984 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4985 return FAIL;
4986 break;
a737bd4d 4987
e16bb312
NC
4988 case check_wrwrwcg:
4989 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4990 || skip_past_comma (&str) == FAIL
4991 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4992 || skip_past_comma (&str) == FAIL
4993 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4994 return FAIL;
4995 break;
a737bd4d 4996
e16bb312
NC
4997 case check_tbcst:
4998 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4999 || skip_past_comma (&str) == FAIL
5000 || reg_required_here (&str, 12) == FAIL))
5001 return FAIL;
5002 break;
a737bd4d 5003
e16bb312
NC
5004 case check_tmovmsk:
5005 if ((reg_required_here (&str, 12) == FAIL
5006 || skip_past_comma (&str) == FAIL
5007 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5008 return FAIL;
5009 break;
a737bd4d 5010
e16bb312
NC
5011 case check_tmia:
5012 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5013 || skip_past_comma (&str) == FAIL
5014 || reg_required_here (&str, 0) == FAIL
5015 || skip_past_comma (&str) == FAIL
5016 || reg_required_here (&str, 12) == FAIL))
5017 return FAIL;
5018 break;
a737bd4d 5019
e16bb312
NC
5020 case check_tmcrr:
5021 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5022 || skip_past_comma (&str) == FAIL
5023 || reg_required_here (&str, 12) == FAIL
5024 || skip_past_comma (&str) == FAIL
5025 || reg_required_here (&str, 16) == FAIL))
5026 return FAIL;
5027 break;
a737bd4d 5028
e16bb312
NC
5029 case check_tmrrc:
5030 if ((reg_required_here (&str, 12) == FAIL
5031 || skip_past_comma (&str) == FAIL
5032 || reg_required_here (&str, 16) == FAIL
5033 || skip_past_comma (&str) == FAIL
5034 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5035 return FAIL;
5036 break;
a737bd4d 5037
e16bb312
NC
5038 case check_tmcr:
5039 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5040 || skip_past_comma (&str) == FAIL
5041 || reg_required_here (&str, 12) == FAIL))
5042 return FAIL;
5043 break;
a737bd4d 5044
e16bb312
NC
5045 case check_tmrc:
5046 if ((reg_required_here (&str, 12) == FAIL
5047 || skip_past_comma (&str) == FAIL
5048 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5049 return FAIL;
5050 break;
a737bd4d 5051
e16bb312
NC
5052 case check_tinsr:
5053 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5054 || skip_past_comma (&str) == FAIL
5055 || reg_required_here (&str, 12) == FAIL
5056 || skip_past_comma (&str) == FAIL))
5057 return FAIL;
5058 break;
a737bd4d 5059
e16bb312
NC
5060 case check_textrc:
5061 if ((reg_required_here (&str, 12) == FAIL
5062 || skip_past_comma (&str) == FAIL))
5063 return FAIL;
5064 break;
a737bd4d 5065
e16bb312
NC
5066 case check_waligni:
5067 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5068 || skip_past_comma (&str) == FAIL
5069 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5070 || skip_past_comma (&str) == FAIL
5071 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5072 || skip_past_comma (&str) == FAIL))
5073 return FAIL;
5074 break;
a737bd4d 5075
e16bb312
NC
5076 case check_textrm:
5077 if ((reg_required_here (&str, 12) == FAIL
5078 || skip_past_comma (&str) == FAIL
5079 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5080 || skip_past_comma (&str) == FAIL))
5081 return FAIL;
5082 break;
a737bd4d 5083
e16bb312
NC
5084 case check_wshufh:
5085 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5086 || skip_past_comma (&str) == FAIL
5087 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5088 || skip_past_comma (&str) == FAIL))
5089 return FAIL;
5090 break;
5091 }
a737bd4d 5092
e16bb312
NC
5093 if (immediate_size == 0)
5094 {
5095 end_of_line (str);
5096 inst.error = inst_error;
5097 return reg;
5098 }
5099 else
5100 {
a737bd4d
NC
5101 skip_whitespace (str);
5102
5103 /* Allow optional leading '#'. */
e16bb312
NC
5104 if (is_immediate_prefix (* str))
5105 str++;
5106
5107 memset (& expr, '\0', sizeof (expr));
a737bd4d 5108
e16bb312
NC
5109 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5110 {
5111 inst.error = _("bad or missing expression");
5112 return FAIL;
5113 }
a737bd4d 5114
e16bb312 5115 number = expr.X_add_number;
a737bd4d 5116
e16bb312
NC
5117 if (number != (number & immediate_size))
5118 {
5119 inst.error = _("immediate value out of range");
5120 return FAIL;
5121 }
5122 end_of_line (str);
5123 inst.error = inst_error;
5124 return number;
5125 }
5126}
5127
5128static void
a737bd4d 5129do_iwmmxt_byte_addr (char * str)
e16bb312
NC
5130{
5131 int op = (inst.instruction & 0x300) >> 8;
5132 int reg;
5133
5134 inst.instruction &= ~0x300;
a737bd4d 5135 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5136
5137 skip_whitespace (str);
5138
5139 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5140 || skip_past_comma (& str) == FAIL
5141 || cp_byte_address_required_here (&str) == FAIL)
5142 {
5143 if (! inst.error)
5144 inst.error = BAD_ARGS;
5145 }
5146 else
5147 end_of_line (str);
5148
5149 if (wc_register (reg))
5150 {
ece01a63 5151 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5152 inst.instruction |= 0xf0000100;
5153 inst.instruction &= ~0x00400000;
5154 }
5155}
5156
5157static void
a737bd4d 5158do_iwmmxt_tandc (char * str)
e16bb312
NC
5159{
5160 int reg;
5161
5162 reg = check_iwmmxt_insn (str, check_rd, 0);
5163
5164 if (reg != REG_PC && !inst.error)
5165 inst.error = _("only r15 allowed here");
e16bb312
NC
5166}
5167
5168static void
a737bd4d 5169do_iwmmxt_tbcst (char * str)
e16bb312
NC
5170{
5171 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
5172}
5173
5174static void
a737bd4d 5175do_iwmmxt_textrc (char * str)
e16bb312
NC
5176{
5177 unsigned long number;
5178
5179 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5180 return;
5181
5182 inst.instruction |= number & 0x7;
e16bb312
NC
5183}
5184
5185static void
a737bd4d 5186do_iwmmxt_textrm (char * str)
e16bb312
NC
5187{
5188 unsigned long number;
5189
5190 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5191 return;
5192
5193 inst.instruction |= number & 0x7;
5194}
5195
5196static void
a737bd4d 5197do_iwmmxt_tinsr (char * str)
e16bb312
NC
5198{
5199 unsigned long number;
5200
5201 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5202 return;
5203
5204 inst.instruction |= number & 0x7;
e16bb312
NC
5205}
5206
5207static void
a737bd4d 5208do_iwmmxt_tmcr (char * str)
e16bb312
NC
5209{
5210 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
5211}
5212
5213static void
a737bd4d 5214do_iwmmxt_tmcrr (char * str)
e16bb312
NC
5215{
5216 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
5217}
5218
5219static void
a737bd4d 5220do_iwmmxt_tmia (char * str)
e16bb312
NC
5221{
5222 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
5223}
5224
5225static void
a737bd4d 5226do_iwmmxt_tmovmsk (char * str)
e16bb312
NC
5227{
5228 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
5229}
5230
5231static void
a737bd4d 5232do_iwmmxt_tmrc (char * str)
e16bb312
NC
5233{
5234 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
5235}
5236
5237static void
a737bd4d 5238do_iwmmxt_tmrrc (char * str)
e16bb312
NC
5239{
5240 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
5241}
5242
5243static void
a737bd4d 5244do_iwmmxt_torc (char * str)
e16bb312
NC
5245{
5246 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
5247}
5248
5249static void
a737bd4d 5250do_iwmmxt_waligni (char * str)
e16bb312
NC
5251{
5252 unsigned long number;
5253
5254 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5255 return;
5256
5257 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
5258}
5259
5260static void
a737bd4d 5261do_iwmmxt_wmov (char * str)
e16bb312
NC
5262{
5263 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5264 return;
a737bd4d 5265
e16bb312 5266 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
5267}
5268
5269static void
a737bd4d 5270do_iwmmxt_word_addr (char * str)
e16bb312
NC
5271{
5272 int op = (inst.instruction & 0x300) >> 8;
5273 int reg;
5274
5275 inst.instruction &= ~0x300;
a737bd4d 5276 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5277
5278 skip_whitespace (str);
5279
5280 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5281 || skip_past_comma (& str) == FAIL
5282 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5283 {
5284 if (! inst.error)
5285 inst.error = BAD_ARGS;
5286 }
5287 else
5288 end_of_line (str);
5289
5290 if (wc_register (reg))
5291 {
ece01a63
ILT
5292 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5293 as_bad (_("conditional execution not supported with control register"));
5294 if (op != 2)
5295 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5296 inst.instruction |= 0xf0000100;
5297 inst.instruction &= ~0x00400000;
5298 }
5299}
5300
5301static void
a737bd4d 5302do_iwmmxt_wrwr (char * str)
e16bb312
NC
5303{
5304 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
5305}
5306
5307static void
a737bd4d 5308do_iwmmxt_wrwrwcg (char * str)
e16bb312
NC
5309{
5310 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
5311}
5312
5313static void
a737bd4d 5314do_iwmmxt_wrwrwr (char * str)
e16bb312
NC
5315{
5316 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
5317}
5318
5319static void
a737bd4d 5320do_iwmmxt_wshufh (char * str)
e16bb312
NC
5321{
5322 unsigned long number;
5323
5324 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5325 return;
5326
5327 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
5328}
5329
5330static void
a737bd4d 5331do_iwmmxt_wzero (char * str)
e16bb312
NC
5332{
5333 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5334 return;
5335
5336 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
5337}
5338
b99bd4ef
NC
5339/* Xscale multiply-accumulate (argument parse)
5340 MIAcc acc0,Rm,Rs
5341 MIAPHcc acc0,Rm,Rs
5342 MIAxycc acc0,Rm,Rs. */
5343
5344static void
a737bd4d 5345do_xsc_mia (char * str)
b99bd4ef
NC
5346{
5347 int rs;
5348 int rm;
5349
f2b7cb0a 5350 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5351 inst.error = ERR_NO_ACCUM;
5352
5353 else if (skip_past_comma (& str) == FAIL
5354 || (rm = reg_required_here (& str, 0)) == FAIL)
5355 inst.error = BAD_ARGS;
5356
5357 else if (skip_past_comma (& str) == FAIL
5358 || (rs = reg_required_here (& str, 12)) == FAIL)
5359 inst.error = BAD_ARGS;
5360
5361 /* inst.instruction has now been zapped with both rm and rs. */
5362 else if (rm == REG_PC || rs == REG_PC)
5363 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5364
5365 else
5366 end_of_line (str);
5367}
5368
5369/* Xscale move-accumulator-register (argument parse)
5370
5371 MARcc acc0,RdLo,RdHi. */
5372
5373static void
a737bd4d 5374do_xsc_mar (char * str)
b99bd4ef
NC
5375{
5376 int rdlo, rdhi;
5377
f2b7cb0a 5378 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5379 inst.error = ERR_NO_ACCUM;
5380
5381 else if (skip_past_comma (& str) == FAIL
5382 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5383 inst.error = BAD_ARGS;
5384
5385 else if (skip_past_comma (& str) == FAIL
5386 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5387 inst.error = BAD_ARGS;
5388
5389 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5390 else if (rdlo == REG_PC || rdhi == REG_PC)
5391 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5392
5393 else
5394 end_of_line (str);
5395}
5396
5397/* Xscale move-register-accumulator (argument parse)
5398
5399 MRAcc RdLo,RdHi,acc0. */
5400
5401static void
a737bd4d 5402do_xsc_mra (char * str)
b99bd4ef
NC
5403{
5404 int rdlo;
5405 int rdhi;
5406
b99bd4ef
NC
5407 skip_whitespace (str);
5408
5409 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5410 inst.error = BAD_ARGS;
5411
5412 else if (skip_past_comma (& str) == FAIL
5413 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5414 inst.error = BAD_ARGS;
5415
5416 else if (skip_past_comma (& str) == FAIL
5417 || accum0_required_here (& str) == FAIL)
5418 inst.error = ERR_NO_ACCUM;
5419
a737bd4d
NC
5420 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5421 else if (rdlo == rdhi)
5422 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5423
5424 else if (rdlo == REG_PC || rdhi == REG_PC)
5425 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5426 else
5427 end_of_line (str);
5428}
5429
5430static int
5431ldst_extend (char ** str)
5432{
5433 int add = INDEX_UP;
5434
5435 switch (**str)
5436 {
5437 case '#':
5438 case '$':
5439 (*str)++;
5440 if (my_get_expression (& inst.reloc.exp, str))
5441 return FAIL;
5442
5443 if (inst.reloc.exp.X_op == O_constant)
5444 {
5445 int value = inst.reloc.exp.X_add_number;
5446
5447 if (value < -4095 || value > 4095)
5448 {
5449 inst.error = _("address offset too large");
5450 return FAIL;
5451 }
5452
5453 if (value < 0)
5454 {
5455 value = -value;
5456 add = 0;
5457 }
5458
5459 inst.instruction |= add | value;
5460 }
5461 else
5462 {
5463 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5464 inst.reloc.pc_rel = 0;
5465 }
5466 return SUCCESS;
5467
5468 case '-':
5469 add = 0;
5470 /* Fall through. */
5471
5472 case '+':
5473 (*str)++;
5474 /* Fall through. */
5475
5476 default:
5477 if (reg_required_here (str, 0) == FAIL)
5478 return FAIL;
5479
5480 inst.instruction |= add | OFFSET_REG;
5481 if (skip_past_comma (str) == SUCCESS)
5482 return decode_shift (str, SHIFT_IMMEDIATE);
b99bd4ef 5483
a737bd4d
NC
5484 return SUCCESS;
5485 }
b99bd4ef
NC
5486}
5487
c9b604bd 5488/* ARMv5TE: Preload-Cache
b99bd4ef
NC
5489
5490 PLD <addr_mode>
5491
5492 Syntactically, like LDR with B=1, W=0, L=1. */
5493
5494static void
a737bd4d 5495do_pld (char * str)
b99bd4ef
NC
5496{
5497 int rd;
5498
b99bd4ef
NC
5499 skip_whitespace (str);
5500
5501 if (* str != '[')
5502 {
5503 inst.error = _("'[' expected after PLD mnemonic");
5504 return;
5505 }
5506
90e4755a 5507 ++str;
b99bd4ef
NC
5508 skip_whitespace (str);
5509
5510 if ((rd = reg_required_here (& str, 16)) == FAIL)
5511 return;
5512
5513 skip_whitespace (str);
5514
90e4755a 5515 if (*str == ']')
b99bd4ef
NC
5516 {
5517 /* [Rn], ... ? */
90e4755a 5518 ++str;
b99bd4ef
NC
5519 skip_whitespace (str);
5520
90e4755a
RE
5521 /* Post-indexed addressing is not allowed with PLD. */
5522 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5523 {
90e4755a
RE
5524 inst.error
5525 = _("post-indexed expression used in preload instruction");
5526 return;
b99bd4ef 5527 }
90e4755a 5528 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
5529 {
5530 inst.error = _("writeback used in preload instruction");
90e4755a 5531 ++str;
b99bd4ef
NC
5532 }
5533 else /* [Rn] */
5534 inst.instruction |= INDEX_UP | PRE_INDEX;
5535 }
5536 else /* [Rn, ...] */
5537 {
5538 if (skip_past_comma (& str) == FAIL)
5539 {
5540 inst.error = _("pre-indexed expression expected");
5541 return;
5542 }
5543
90e4755a 5544 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
5545 return;
5546
5547 skip_whitespace (str);
5548
5549 if (* str != ']')
5550 {
5551 inst.error = _("missing ]");
5552 return;
5553 }
5554
5555 ++ str;
5556 skip_whitespace (str);
5557
5558 if (* str == '!') /* [Rn]! */
5559 {
5560 inst.error = _("writeback used in preload instruction");
5561 ++ str;
5562 }
5563
5564 inst.instruction |= PRE_INDEX;
5565 }
5566
5567 end_of_line (str);
5568}
5569
c9b604bd 5570/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
5571 Mode is like LDRH.
5572
5573 LDRccD R, mode
5574 STRccD R, mode. */
5575
5576static void
a737bd4d 5577do_ldrd (char * str)
b99bd4ef
NC
5578{
5579 int rd;
5580 int rn;
5581
b99bd4ef
NC
5582 skip_whitespace (str);
5583
5584 if ((rd = reg_required_here (& str, 12)) == FAIL)
5585 {
5586 inst.error = BAD_ARGS;
5587 return;
5588 }
5589
5590 if (skip_past_comma (& str) == FAIL
5591 || (rn = ld_mode_required_here (& str)) == FAIL)
5592 {
5593 if (!inst.error)
cc8a6dd0 5594 inst.error = BAD_ARGS;
a737bd4d 5595 return;
b99bd4ef
NC
5596 }
5597
a737bd4d
NC
5598 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5599 if (rd & 1) /* Unpredictable result if Rd is odd. */
5600 {
5601 inst.error = _("destination register must be even");
5602 return;
5603 }
b99bd4ef 5604
a737bd4d 5605 if (rd == REG_LR)
b99bd4ef 5606 {
a737bd4d
NC
5607 inst.error = _("r14 not allowed here");
5608 return;
b99bd4ef 5609 }
a737bd4d
NC
5610
5611 if (((rd == rn) || (rd + 1 == rn))
5612 && ((inst.instruction & WRITE_BACK)
5613 || (!(inst.instruction & PRE_INDEX))))
5614 as_warn (_("pre/post-indexing used when modified address register is destination"));
5615
5616 /* For an index-register load, the index register must not overlap the
5617 destination (even if not write-back). */
5618 if ((inst.instruction & V4_STR_BIT) == 0
5619 && (inst.instruction & HWOFFSET_IMM) == 0)
b99bd4ef 5620 {
a737bd4d
NC
5621 int rm = inst.instruction & 0x0000000f;
5622
5623 if (rm == rd || (rm == rd + 1))
5624 as_warn (_("ldrd destination registers must not overlap index register"));
b99bd4ef
NC
5625 }
5626
a737bd4d
NC
5627 end_of_line (str);
5628}
b99bd4ef 5629
a737bd4d
NC
5630/* Returns the index into fp_values of a floating point number,
5631 or -1 if not in the table. */
b99bd4ef 5632
a737bd4d
NC
5633static int
5634my_get_float_expression (char ** str)
5635{
5636 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5637 char * save_in;
5638 expressionS exp;
5639 int i;
5640 int j;
b99bd4ef 5641
a737bd4d
NC
5642 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5643
5644 /* Look for a raw floating point number. */
5645 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5646 && is_end_of_line[(unsigned char) *save_in])
5647 {
5648 for (i = 0; i < NUM_FLOAT_VALS; i++)
b99bd4ef 5649 {
a737bd4d 5650 for (j = 0; j < MAX_LITTLENUMS; j++)
b99bd4ef 5651 {
a737bd4d
NC
5652 if (words[j] != fp_values[i][j])
5653 break;
b99bd4ef 5654 }
a737bd4d
NC
5655
5656 if (j == MAX_LITTLENUMS)
b99bd4ef 5657 {
a737bd4d
NC
5658 *str = save_in;
5659 return i;
b99bd4ef
NC
5660 }
5661 }
a737bd4d 5662 }
b99bd4ef 5663
a737bd4d
NC
5664 /* Try and parse a more complex expression, this will probably fail
5665 unless the code uses a floating point prefix (eg "0f"). */
5666 save_in = input_line_pointer;
5667 input_line_pointer = *str;
5668 if (expression (&exp) == absolute_section
5669 && exp.X_op == O_big
5670 && exp.X_add_number < 0)
5671 {
5672 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5673 Ditto for 15. */
5674 if (gen_to_words (words, 5, (long) 15) == 0)
5675 {
5676 for (i = 0; i < NUM_FLOAT_VALS; i++)
5677 {
5678 for (j = 0; j < MAX_LITTLENUMS; j++)
5679 {
5680 if (words[j] != fp_values[i][j])
5681 break;
5682 }
b99bd4ef 5683
a737bd4d
NC
5684 if (j == MAX_LITTLENUMS)
5685 {
5686 *str = input_line_pointer;
5687 input_line_pointer = save_in;
5688 return i;
5689 }
5690 }
5691 }
b99bd4ef 5692 }
a737bd4d
NC
5693
5694 *str = input_line_pointer;
5695 input_line_pointer = save_in;
5696 return -1;
5697}
5698
5699/* We handle all bad expressions here, so that we can report the faulty
5700 instruction in the error message. */
5701void
5702md_operand (expressionS * expr)
5703{
5704 if (in_my_get_expression)
b99bd4ef 5705 {
a737bd4d
NC
5706 expr->X_op = O_illegal;
5707 if (inst.error == NULL)
5708 inst.error = _("bad expression");
b99bd4ef 5709 }
b99bd4ef
NC
5710}
5711
5712/* Do those data_ops which can take a negative immediate constant
2d2255b5 5713 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
5714 MOV <-> MVN
5715 AND <-> BIC
5716 ADC <-> SBC
5717 by inverting the second operand, and
5718 ADD <-> SUB
5719 CMP <-> CMN
5720 by negating the second operand. */
5721
5722static int
a737bd4d
NC
5723negate_data_op (unsigned long * instruction,
5724 unsigned long value)
b99bd4ef
NC
5725{
5726 int op, new_inst;
5727 unsigned long negated, inverted;
5728
5729 negated = validate_immediate (-value);
5730 inverted = validate_immediate (~value);
5731
5732 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5733 switch (op)
5734 {
5735 /* First negates. */
5736 case OPCODE_SUB: /* ADD <-> SUB */
5737 new_inst = OPCODE_ADD;
5738 value = negated;
5739 break;
5740
5741 case OPCODE_ADD:
5742 new_inst = OPCODE_SUB;
5743 value = negated;
5744 break;
5745
5746 case OPCODE_CMP: /* CMP <-> CMN */
5747 new_inst = OPCODE_CMN;
5748 value = negated;
5749 break;
5750
5751 case OPCODE_CMN:
5752 new_inst = OPCODE_CMP;
5753 value = negated;
5754 break;
5755
5756 /* Now Inverted ops. */
5757 case OPCODE_MOV: /* MOV <-> MVN */
5758 new_inst = OPCODE_MVN;
5759 value = inverted;
5760 break;
5761
5762 case OPCODE_MVN:
5763 new_inst = OPCODE_MOV;
5764 value = inverted;
5765 break;
5766
5767 case OPCODE_AND: /* AND <-> BIC */
5768 new_inst = OPCODE_BIC;
5769 value = inverted;
5770 break;
5771
5772 case OPCODE_BIC:
5773 new_inst = OPCODE_AND;
5774 value = inverted;
5775 break;
5776
5777 case OPCODE_ADC: /* ADC <-> SBC */
5778 new_inst = OPCODE_SBC;
5779 value = inverted;
5780 break;
5781
5782 case OPCODE_SBC:
5783 new_inst = OPCODE_ADC;
5784 value = inverted;
5785 break;
5786
5787 /* We cannot do anything. */
5788 default:
5789 return FAIL;
5790 }
5791
5792 if (value == (unsigned) FAIL)
5793 return FAIL;
5794
5795 *instruction &= OPCODE_MASK;
5796 *instruction |= new_inst << DATA_OP_SHIFT;
5797 return value;
5798}
5799
5800static int
a737bd4d 5801data_op2 (char ** str)
b99bd4ef
NC
5802{
5803 int value;
5804 expressionS expr;
5805
5806 skip_whitespace (* str);
5807
5808 if (reg_required_here (str, 0) != FAIL)
5809 {
5810 if (skip_past_comma (str) == SUCCESS)
5811 /* Shift operation on register. */
5812 return decode_shift (str, NO_SHIFT_RESTRICT);
5813
5814 return SUCCESS;
5815 }
5816 else
5817 {
5818 /* Immediate expression. */
5819 if (is_immediate_prefix (**str))
5820 {
5821 (*str)++;
5822 inst.error = NULL;
5823
5824 if (my_get_expression (&inst.reloc.exp, str))
5825 return FAIL;
5826
5827 if (inst.reloc.exp.X_add_symbol)
5828 {
5829 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5830 inst.reloc.pc_rel = 0;
5831 }
5832 else
5833 {
5834 if (skip_past_comma (str) == SUCCESS)
5835 {
5836 /* #x, y -- ie explicit rotation by Y. */
5837 if (my_get_expression (&expr, str))
5838 return FAIL;
5839
5840 if (expr.X_op != O_constant)
5841 {
f03698e6 5842 inst.error = _("constant expression expected");
b99bd4ef
NC
5843 return FAIL;
5844 }
5845
5846 /* Rotate must be a multiple of 2. */
5847 if (((unsigned) expr.X_add_number) > 30
5848 || (expr.X_add_number & 1) != 0
5849 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5850 {
f03698e6 5851 inst.error = _("invalid constant");
b99bd4ef
NC
5852 return FAIL;
5853 }
5854 inst.instruction |= INST_IMMEDIATE;
5855 inst.instruction |= inst.reloc.exp.X_add_number;
5856 inst.instruction |= expr.X_add_number << 7;
5857 return SUCCESS;
5858 }
5859
5860 /* Implicit rotation, select a suitable one. */
5861 value = validate_immediate (inst.reloc.exp.X_add_number);
5862
5863 if (value == FAIL)
5864 {
5865 /* Can't be done. Perhaps the code reads something like
5866 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5867 if ((value = negate_data_op (&inst.instruction,
5868 inst.reloc.exp.X_add_number))
5869 == FAIL)
5870 {
f03698e6 5871 inst.error = _("invalid constant");
b99bd4ef
NC
5872 return FAIL;
5873 }
5874 }
5875
5876 inst.instruction |= value;
5877 }
5878
5879 inst.instruction |= INST_IMMEDIATE;
5880 return SUCCESS;
5881 }
5882
5883 (*str)++;
f03698e6 5884 inst.error = _("register or shift expression expected");
b99bd4ef
NC
5885 return FAIL;
5886 }
5887}
5888
5889static int
a737bd4d 5890fp_op2 (char ** str)
b99bd4ef
NC
5891{
5892 skip_whitespace (* str);
5893
5894 if (fp_reg_required_here (str, 0) != FAIL)
5895 return SUCCESS;
5896 else
5897 {
5898 /* Immediate expression. */
5899 if (*((*str)++) == '#')
5900 {
5901 int i;
5902
5903 inst.error = NULL;
5904
5905 skip_whitespace (* str);
5906
5907 /* First try and match exact strings, this is to guarantee
5908 that some formats will work even for cross assembly. */
5909
5910 for (i = 0; fp_const[i]; i++)
5911 {
5912 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5913 {
5914 char *start = *str;
5915
5916 *str += strlen (fp_const[i]);
5917 if (is_end_of_line[(unsigned char) **str])
5918 {
5919 inst.instruction |= i + 8;
5920 return SUCCESS;
5921 }
5922 *str = start;
5923 }
5924 }
5925
5926 /* Just because we didn't get a match doesn't mean that the
5927 constant isn't valid, just that it is in a format that we
5928 don't automatically recognize. Try parsing it with
5929 the standard expression routines. */
5930 if ((i = my_get_float_expression (str)) >= 0)
5931 {
5932 inst.instruction |= i + 8;
5933 return SUCCESS;
5934 }
5935
f03698e6 5936 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
5937 return FAIL;
5938 }
5939 inst.error =
f03698e6 5940 _("floating point register or immediate expression expected");
b99bd4ef
NC
5941 return FAIL;
5942 }
5943}
5944
5945static void
a737bd4d 5946do_arit (char * str)
b99bd4ef
NC
5947{
5948 skip_whitespace (str);
5949
5950 if (reg_required_here (&str, 12) == FAIL
5951 || skip_past_comma (&str) == FAIL
5952 || reg_required_here (&str, 16) == FAIL
5953 || skip_past_comma (&str) == FAIL
5954 || data_op2 (&str) == FAIL)
5955 {
5956 if (!inst.error)
5957 inst.error = BAD_ARGS;
5958 return;
5959 }
5960
b99bd4ef 5961 end_of_line (str);
b99bd4ef
NC
5962}
5963
5964static void
a737bd4d 5965do_adr (char * str)
b99bd4ef 5966{
90e4755a
RE
5967 /* This is a pseudo-op of the form "adr rd, label" to be converted
5968 into a relative address of the form "add rd, pc, #label-.-8". */
5969 skip_whitespace (str);
5970
5971 if (reg_required_here (&str, 12) == FAIL
5972 || skip_past_comma (&str) == FAIL
5973 || my_get_expression (&inst.reloc.exp, &str))
5974 {
5975 if (!inst.error)
5976 inst.error = BAD_ARGS;
5977 return;
5978 }
5979
5980 /* Frag hacking will turn this into a sub instruction if the offset turns
5981 out to be negative. */
5982 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 5983#ifndef TE_WINCE
90e4755a 5984 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 5985#endif
90e4755a
RE
5986 inst.reloc.pc_rel = 1;
5987
5988 end_of_line (str);
5989}
5990
5991static void
a737bd4d 5992do_adrl (char * str)
90e4755a
RE
5993{
5994 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5995 into a relative address of the form:
5996 add rd, pc, #low(label-.-8)"
5997 add rd, rd, #high(label-.-8)" */
5998
5999 skip_whitespace (str);
6000
6001 if (reg_required_here (&str, 12) == FAIL
6002 || skip_past_comma (&str) == FAIL
6003 || my_get_expression (&inst.reloc.exp, &str))
6004 {
6005 if (!inst.error)
6006 inst.error = BAD_ARGS;
6007
6008 return;
6009 }
6010
6011 end_of_line (str);
6012 /* Frag hacking will turn this into a sub instruction if the offset turns
6013 out to be negative. */
6014 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
a737bd4d 6015#ifndef TE_WINCE
90e4755a 6016 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 6017#endif
90e4755a
RE
6018 inst.reloc.pc_rel = 1;
6019 inst.size = INSN_SIZE * 2;
90e4755a
RE
6020}
6021
6022static void
a737bd4d 6023do_cmp (char * str)
90e4755a
RE
6024{
6025 skip_whitespace (str);
6026
6027 if (reg_required_here (&str, 16) == FAIL)
6028 {
6029 if (!inst.error)
6030 inst.error = BAD_ARGS;
6031 return;
6032 }
6033
6034 if (skip_past_comma (&str) == FAIL
6035 || data_op2 (&str) == FAIL)
6036 {
6037 if (!inst.error)
6038 inst.error = BAD_ARGS;
6039 return;
6040 }
6041
90e4755a 6042 end_of_line (str);
90e4755a
RE
6043}
6044
6045static void
a737bd4d 6046do_mov (char * str)
90e4755a
RE
6047{
6048 skip_whitespace (str);
6049
6050 if (reg_required_here (&str, 12) == FAIL)
6051 {
6052 if (!inst.error)
6053 inst.error = BAD_ARGS;
6054 return;
6055 }
6056
6057 if (skip_past_comma (&str) == FAIL
6058 || data_op2 (&str) == FAIL)
6059 {
6060 if (!inst.error)
6061 inst.error = BAD_ARGS;
6062 return;
6063 }
6064
90e4755a 6065 end_of_line (str);
90e4755a
RE
6066}
6067
90e4755a 6068static void
a737bd4d 6069do_ldst (char * str)
90e4755a
RE
6070{
6071 int pre_inc = 0;
6072 int conflict_reg;
6073 int value;
6074
b99bd4ef
NC
6075 skip_whitespace (str);
6076
90e4755a
RE
6077 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6078 {
6079 if (!inst.error)
6080 inst.error = BAD_ARGS;
6081 return;
6082 }
6083
6084 if (skip_past_comma (&str) == FAIL)
6085 {
f03698e6 6086 inst.error = _("address expected");
90e4755a
RE
6087 return;
6088 }
6089
90e4755a
RE
6090 if (*str == '[')
6091 {
6092 int reg;
6093
6094 str++;
6095
6096 skip_whitespace (str);
6097
6098 if ((reg = reg_required_here (&str, 16)) == FAIL)
6099 return;
6100
6101 /* Conflicts can occur on stores as well as loads. */
6102 conflict_reg = (conflict_reg == reg);
6103
6104 skip_whitespace (str);
6105
6106 if (*str == ']')
6107 {
6108 str ++;
6109
6110 if (skip_past_comma (&str) == SUCCESS)
6111 {
6112 /* [Rn],... (post inc) */
6113 if (ldst_extend (&str) == FAIL)
6114 return;
6115 if (conflict_reg)
6116 as_warn (_("%s register same as write-back base"),
6117 ((inst.instruction & LOAD_BIT)
6118 ? _("destination") : _("source")));
6119 }
6120 else
6121 {
6122 /* [Rn] */
6123 skip_whitespace (str);
6124
6125 if (*str == '!')
6126 {
6127 if (conflict_reg)
6128 as_warn (_("%s register same as write-back base"),
6129 ((inst.instruction & LOAD_BIT)
6130 ? _("destination") : _("source")));
6131 str++;
6132 inst.instruction |= WRITE_BACK;
6133 }
6134
6135 inst.instruction |= INDEX_UP;
6136 pre_inc = 1;
6137 }
6138 }
6139 else
6140 {
6141 /* [Rn,...] */
6142 if (skip_past_comma (&str) == FAIL)
6143 {
6144 inst.error = _("pre-indexed expression expected");
6145 return;
6146 }
6147
6148 pre_inc = 1;
6149 if (ldst_extend (&str) == FAIL)
6150 return;
6151
6152 skip_whitespace (str);
6153
6154 if (*str++ != ']')
6155 {
6156 inst.error = _("missing ]");
6157 return;
6158 }
6159
6160 skip_whitespace (str);
6161
6162 if (*str == '!')
6163 {
6164 if (conflict_reg)
6165 as_warn (_("%s register same as write-back base"),
6166 ((inst.instruction & LOAD_BIT)
6167 ? _("destination") : _("source")));
6168 str++;
6169 inst.instruction |= WRITE_BACK;
6170 }
6171 }
6172 }
6173 else if (*str == '=')
6174 {
f03698e6
RE
6175 if ((inst.instruction & LOAD_BIT) == 0)
6176 {
6177 inst.error = _("invalid pseudo operation");
6178 return;
6179 }
6180
90e4755a
RE
6181 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6182 str++;
6183
6184 skip_whitespace (str);
6185
6186 if (my_get_expression (&inst.reloc.exp, &str))
6187 return;
6188
6189 if (inst.reloc.exp.X_op != O_constant
6190 && inst.reloc.exp.X_op != O_symbol)
6191 {
f03698e6 6192 inst.error = _("constant expression expected");
90e4755a
RE
6193 return;
6194 }
6195
e28cd48c 6196 if (inst.reloc.exp.X_op == O_constant)
90e4755a 6197 {
e28cd48c
RE
6198 value = validate_immediate (inst.reloc.exp.X_add_number);
6199
6200 if (value != FAIL)
90e4755a 6201 {
e28cd48c
RE
6202 /* This can be done with a mov instruction. */
6203 inst.instruction &= LITERAL_MASK;
6204 inst.instruction |= (INST_IMMEDIATE
6205 | (OPCODE_MOV << DATA_OP_SHIFT));
6206 inst.instruction |= value & 0xfff;
6207 end_of_line (str);
90e4755a
RE
6208 return;
6209 }
b99bd4ef 6210
e28cd48c
RE
6211 value = validate_immediate (~inst.reloc.exp.X_add_number);
6212
6213 if (value != FAIL)
6214 {
6215 /* This can be done with a mvn instruction. */
6216 inst.instruction &= LITERAL_MASK;
6217 inst.instruction |= (INST_IMMEDIATE
6218 | (OPCODE_MVN << DATA_OP_SHIFT));
6219 inst.instruction |= value & 0xfff;
6220 end_of_line (str);
6221 return;
6222 }
90e4755a 6223 }
e28cd48c
RE
6224
6225 /* Insert into literal pool. */
6226 if (add_to_lit_pool () == FAIL)
6227 {
6228 if (!inst.error)
6229 inst.error = _("literal pool insertion failed");
6230 return;
6231 }
6232
6233 /* Change the instruction exp to point to the pool. */
6234 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6235 inst.reloc.pc_rel = 1;
6236 inst.instruction |= (REG_PC << 16);
6237 pre_inc = 1;
1cac9012
NC
6238 }
6239 else
6240 {
90e4755a
RE
6241 if (my_get_expression (&inst.reloc.exp, &str))
6242 return;
6243
6244 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6245#ifndef TE_WINCE
6246 /* PC rel adjust. */
6247 inst.reloc.exp.X_add_number -= 8;
6248#endif
1cac9012 6249 inst.reloc.pc_rel = 1;
90e4755a
RE
6250 inst.instruction |= (REG_PC << 16);
6251 pre_inc = 1;
b99bd4ef
NC
6252 }
6253
90e4755a 6254 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6255 end_of_line (str);
b99bd4ef
NC
6256}
6257
6258static void
a737bd4d 6259do_ldstt (char * str)
b99bd4ef 6260{
90e4755a
RE
6261 int conflict_reg;
6262
b99bd4ef
NC
6263 skip_whitespace (str);
6264
90e4755a 6265 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
6266 {
6267 if (!inst.error)
6268 inst.error = BAD_ARGS;
6269 return;
6270 }
6271
90e4755a 6272 if (skip_past_comma (& str) == FAIL)
b99bd4ef 6273 {
f03698e6 6274 inst.error = _("address expected");
b99bd4ef
NC
6275 return;
6276 }
6277
90e4755a
RE
6278 if (*str == '[')
6279 {
6280 int reg;
b99bd4ef 6281
90e4755a 6282 str++;
b99bd4ef 6283
90e4755a 6284 skip_whitespace (str);
b99bd4ef 6285
90e4755a
RE
6286 if ((reg = reg_required_here (&str, 16)) == FAIL)
6287 return;
b99bd4ef 6288
90e4755a
RE
6289 /* ldrt/strt always use post-indexed addressing, so if the base is
6290 the same as Rd, we warn. */
6291 if (conflict_reg == reg)
6292 as_warn (_("%s register same as write-back base"),
6293 ((inst.instruction & LOAD_BIT)
6294 ? _("destination") : _("source")));
6295
6296 skip_whitespace (str);
6297
6298 if (*str == ']')
6299 {
6300 str ++;
6301
6302 if (skip_past_comma (&str) == SUCCESS)
6303 {
6304 /* [Rn],... (post inc) */
6305 if (ldst_extend (&str) == FAIL)
6306 return;
6307 }
6308 else
6309 {
6310 /* [Rn] */
6311 skip_whitespace (str);
6312
6313 /* Skip a write-back '!'. */
6314 if (*str == '!')
6315 str++;
6316
6317 inst.instruction |= INDEX_UP;
6318 }
6319 }
6320 else
6321 {
6322 inst.error = _("post-indexed expression expected");
6323 return;
6324 }
6325 }
6326 else
b99bd4ef 6327 {
90e4755a 6328 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
6329 return;
6330 }
6331
b99bd4ef 6332 end_of_line (str);
b99bd4ef
NC
6333}
6334
90e4755a 6335/* Halfword and signed-byte load/store operations. */
a737bd4d 6336
b99bd4ef 6337static void
a737bd4d 6338do_ldstv4 (char * str)
b99bd4ef 6339{
b99bd4ef
NC
6340 int pre_inc = 0;
6341 int conflict_reg;
6342 int value;
6343
b99bd4ef
NC
6344 skip_whitespace (str);
6345
6346 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6347 {
6348 if (!inst.error)
6349 inst.error = BAD_ARGS;
6350 return;
6351 }
6352
6353 if (skip_past_comma (& str) == FAIL)
6354 {
f03698e6 6355 inst.error = _("address expected");
b99bd4ef
NC
6356 return;
6357 }
6358
6359 if (*str == '[')
6360 {
6361 int reg;
6362
6363 str++;
6364
6365 skip_whitespace (str);
6366
6367 if ((reg = reg_required_here (&str, 16)) == FAIL)
6368 return;
6369
6370 /* Conflicts can occur on stores as well as loads. */
6371 conflict_reg = (conflict_reg == reg);
6372
6373 skip_whitespace (str);
6374
6375 if (*str == ']')
6376 {
6377 str ++;
6378
6379 if (skip_past_comma (&str) == SUCCESS)
6380 {
6381 /* [Rn],... (post inc) */
90e4755a 6382 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6383 return;
6384 if (conflict_reg)
90e4755a
RE
6385 as_warn (_("%s register same as write-back base"),
6386 ((inst.instruction & LOAD_BIT)
6387 ? _("destination") : _("source")));
b99bd4ef
NC
6388 }
6389 else
6390 {
6391 /* [Rn] */
90e4755a 6392 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
6393
6394 skip_whitespace (str);
6395
6396 if (*str == '!')
6397 {
6398 if (conflict_reg)
6399 as_warn (_("%s register same as write-back base"),
6400 ((inst.instruction & LOAD_BIT)
6401 ? _("destination") : _("source")));
6402 str++;
6403 inst.instruction |= WRITE_BACK;
6404 }
6405
90e4755a
RE
6406 inst.instruction |= INDEX_UP;
6407 pre_inc = 1;
b99bd4ef
NC
6408 }
6409 }
6410 else
6411 {
6412 /* [Rn,...] */
6413 if (skip_past_comma (&str) == FAIL)
6414 {
6415 inst.error = _("pre-indexed expression expected");
6416 return;
6417 }
6418
6419 pre_inc = 1;
90e4755a 6420 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6421 return;
6422
6423 skip_whitespace (str);
6424
6425 if (*str++ != ']')
6426 {
6427 inst.error = _("missing ]");
6428 return;
6429 }
6430
6431 skip_whitespace (str);
6432
6433 if (*str == '!')
6434 {
6435 if (conflict_reg)
6436 as_warn (_("%s register same as write-back base"),
6437 ((inst.instruction & LOAD_BIT)
6438 ? _("destination") : _("source")));
6439 str++;
6440 inst.instruction |= WRITE_BACK;
6441 }
6442 }
6443 }
6444 else if (*str == '=')
6445 {
f03698e6
RE
6446 if ((inst.instruction & LOAD_BIT) == 0)
6447 {
6448 inst.error = _("invalid pseudo operation");
6449 return;
6450 }
6451
90e4755a 6452 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
6453 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6454 str++;
6455
6456 skip_whitespace (str);
6457
6458 if (my_get_expression (&inst.reloc.exp, &str))
6459 return;
6460
6461 if (inst.reloc.exp.X_op != O_constant
6462 && inst.reloc.exp.X_op != O_symbol)
6463 {
f03698e6 6464 inst.error = _("constant expression expected");
b99bd4ef
NC
6465 return;
6466 }
6467
d8273442 6468 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 6469 {
d8273442
NC
6470 value = validate_immediate (inst.reloc.exp.X_add_number);
6471
6472 if (value != FAIL)
b99bd4ef 6473 {
d8273442
NC
6474 /* This can be done with a mov instruction. */
6475 inst.instruction &= LITERAL_MASK;
6476 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 6477 inst.instruction |= value & 0xfff;
d8273442 6478 end_of_line (str);
b99bd4ef
NC
6479 return;
6480 }
cc8a6dd0 6481
d8273442 6482 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 6483
d8273442 6484 if (value != FAIL)
b99bd4ef 6485 {
d8273442
NC
6486 /* This can be done with a mvn instruction. */
6487 inst.instruction &= LITERAL_MASK;
6488 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 6489 inst.instruction |= value & 0xfff;
d8273442
NC
6490 end_of_line (str);
6491 return;
b99bd4ef 6492 }
b99bd4ef 6493 }
d8273442
NC
6494
6495 /* Insert into literal pool. */
6496 if (add_to_lit_pool () == FAIL)
6497 {
6498 if (!inst.error)
6499 inst.error = _("literal pool insertion failed");
6500 return;
6501 }
6502
6503 /* Change the instruction exp to point to the pool. */
90e4755a
RE
6504 inst.instruction |= HWOFFSET_IMM;
6505 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
6506 inst.reloc.pc_rel = 1;
6507 inst.instruction |= (REG_PC << 16);
6508 pre_inc = 1;
b99bd4ef
NC
6509 }
6510 else
6511 {
6512 if (my_get_expression (&inst.reloc.exp, &str))
6513 return;
6514
90e4755a
RE
6515 inst.instruction |= HWOFFSET_IMM;
6516 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
6517#ifndef TE_WINCE
6518 /* PC rel adjust. */
6519 inst.reloc.exp.X_add_number -= 8;
6520#endif
6521 inst.reloc.pc_rel = 1;
6522 inst.instruction |= (REG_PC << 16);
6523 pre_inc = 1;
6524 }
6525
90e4755a 6526 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6527 end_of_line (str);
b99bd4ef
NC
6528}
6529
6530static long
a737bd4d 6531reg_list (char ** strp)
b99bd4ef
NC
6532{
6533 char * str = * strp;
6534 long range = 0;
6535 int another_range;
6536
6537 /* We come back here if we get ranges concatenated by '+' or '|'. */
6538 do
6539 {
6540 another_range = 0;
6541
6542 if (*str == '{')
6543 {
6544 int in_range = 0;
6545 int cur_reg = -1;
6546
6547 str++;
6548 do
6549 {
6550 int reg;
6551
6552 skip_whitespace (str);
6553
6554 if ((reg = reg_required_here (& str, -1)) == FAIL)
6555 return FAIL;
6556
6557 if (in_range)
6558 {
6559 int i;
6560
6561 if (reg <= cur_reg)
6562 {
f03698e6 6563 inst.error = _("bad range in register list");
b99bd4ef
NC
6564 return FAIL;
6565 }
6566
6567 for (i = cur_reg + 1; i < reg; i++)
6568 {
6569 if (range & (1 << i))
6570 as_tsktsk
f03698e6 6571 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6572 i);
6573 else
6574 range |= 1 << i;
6575 }
6576 in_range = 0;
6577 }
6578
6579 if (range & (1 << reg))
f03698e6 6580 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6581 reg);
6582 else if (reg <= cur_reg)
f03698e6 6583 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
6584
6585 range |= 1 << reg;
6586 cur_reg = reg;
6587 }
6588 while (skip_past_comma (&str) != FAIL
6589 || (in_range = 1, *str++ == '-'));
6590 str--;
6591 skip_whitespace (str);
6592
6593 if (*str++ != '}')
6594 {
f03698e6 6595 inst.error = _("missing `}'");
b99bd4ef
NC
6596 return FAIL;
6597 }
6598 }
6599 else
6600 {
6601 expressionS expr;
6602
6603 if (my_get_expression (&expr, &str))
6604 return FAIL;
6605
6606 if (expr.X_op == O_constant)
6607 {
6608 if (expr.X_add_number
6609 != (expr.X_add_number & 0x0000ffff))
6610 {
6611 inst.error = _("invalid register mask");
6612 return FAIL;
6613 }
6614
6615 if ((range & expr.X_add_number) != 0)
6616 {
6617 int regno = range & expr.X_add_number;
6618
6619 regno &= -regno;
6620 regno = (1 << regno) - 1;
6621 as_tsktsk
f03698e6 6622 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6623 regno);
6624 }
6625
6626 range |= expr.X_add_number;
6627 }
6628 else
6629 {
6630 if (inst.reloc.type != 0)
6631 {
6632 inst.error = _("expression too complex");
6633 return FAIL;
6634 }
6635
6636 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6637 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6638 inst.reloc.pc_rel = 0;
6639 }
6640 }
6641
6642 skip_whitespace (str);
6643
6644 if (*str == '|' || *str == '+')
6645 {
6646 str++;
6647 another_range = 1;
6648 }
6649 }
6650 while (another_range);
6651
6652 *strp = str;
6653 return range;
6654}
6655
6656static void
a737bd4d 6657do_ldmstm (char * str)
b99bd4ef
NC
6658{
6659 int base_reg;
6660 long range;
6661
6662 skip_whitespace (str);
6663
6664 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6665 return;
6666
6667 if (base_reg == REG_PC)
6668 {
6669 inst.error = _("r15 not allowed as base register");
6670 return;
6671 }
6672
6673 skip_whitespace (str);
6674
6675 if (*str == '!')
6676 {
90e4755a 6677 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
6678 str++;
6679 }
6680
6681 if (skip_past_comma (&str) == FAIL
6682 || (range = reg_list (&str)) == FAIL)
6683 {
6684 if (! inst.error)
6685 inst.error = BAD_ARGS;
6686 return;
6687 }
6688
6689 if (*str == '^')
6690 {
6691 str++;
90e4755a 6692 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
6693 }
6694
6189168b
NC
6695 if (inst.instruction & WRITE_BACK)
6696 {
6697 /* Check for unpredictable uses of writeback. */
6698 if (inst.instruction & LOAD_BIT)
6699 {
6700 /* Not allowed in LDM type 2. */
6701 if ((inst.instruction & LDM_TYPE_2_OR_3)
6702 && ((range & (1 << REG_PC)) == 0))
6703 as_warn (_("writeback of base register is UNPREDICTABLE"));
6704 /* Only allowed if base reg not in list for other types. */
6705 else if (range & (1 << base_reg))
6706 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6707 }
6708 else /* STM. */
6709 {
6710 /* Not allowed for type 2. */
6711 if (inst.instruction & LDM_TYPE_2_OR_3)
6712 as_warn (_("writeback of base register is UNPREDICTABLE"));
6713 /* Only allowed if base reg not in list, or first in list. */
6714 else if ((range & (1 << base_reg))
6715 && (range & ((1 << base_reg) - 1)))
6716 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6717 }
6718 }
61b5f74b 6719
f2b7cb0a 6720 inst.instruction |= range;
b99bd4ef 6721 end_of_line (str);
b99bd4ef
NC
6722}
6723
0dd132b6
NC
6724static void
6725do_smi (char * str)
6726{
6727 skip_whitespace (str);
6728
6729 /* Allow optional leading '#'. */
6730 if (is_immediate_prefix (*str))
6731 str++;
6732
6733 if (my_get_expression (& inst.reloc.exp, & str))
6734 return;
6735
6736 inst.reloc.type = BFD_RELOC_ARM_SMI;
6737 inst.reloc.pc_rel = 0;
6738 end_of_line (str);
6739}
6740
b99bd4ef 6741static void
a737bd4d 6742do_swi (char * str)
b99bd4ef
NC
6743{
6744 skip_whitespace (str);
6745
6746 /* Allow optional leading '#'. */
6747 if (is_immediate_prefix (*str))
6748 str++;
6749
6750 if (my_get_expression (& inst.reloc.exp, & str))
6751 return;
6752
6753 inst.reloc.type = BFD_RELOC_ARM_SWI;
6754 inst.reloc.pc_rel = 0;
b99bd4ef 6755 end_of_line (str);
b99bd4ef
NC
6756}
6757
6758static void
a737bd4d 6759do_swap (char * str)
b99bd4ef
NC
6760{
6761 int reg;
6762
6763 skip_whitespace (str);
6764
6765 if ((reg = reg_required_here (&str, 12)) == FAIL)
6766 return;
6767
6768 if (reg == REG_PC)
6769 {
6770 inst.error = _("r15 not allowed in swap");
6771 return;
6772 }
6773
6774 if (skip_past_comma (&str) == FAIL
6775 || (reg = reg_required_here (&str, 0)) == FAIL)
6776 {
6777 if (!inst.error)
6778 inst.error = BAD_ARGS;
6779 return;
6780 }
6781
6782 if (reg == REG_PC)
6783 {
6784 inst.error = _("r15 not allowed in swap");
6785 return;
6786 }
6787
6788 if (skip_past_comma (&str) == FAIL
6789 || *str++ != '[')
6790 {
6791 inst.error = BAD_ARGS;
6792 return;
6793 }
6794
6795 skip_whitespace (str);
6796
6797 if ((reg = reg_required_here (&str, 16)) == FAIL)
6798 return;
6799
6800 if (reg == REG_PC)
6801 {
6802 inst.error = BAD_PC;
6803 return;
6804 }
6805
6806 skip_whitespace (str);
6807
6808 if (*str++ != ']')
6809 {
6810 inst.error = _("missing ]");
6811 return;
6812 }
6813
b99bd4ef 6814 end_of_line (str);
b99bd4ef
NC
6815}
6816
6817static void
a737bd4d 6818do_branch (char * str)
b99bd4ef
NC
6819{
6820 if (my_get_expression (&inst.reloc.exp, &str))
6821 return;
6822
6823#ifdef OBJ_ELF
6824 {
6825 char * save_in;
6826
6827 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6828 required for the instruction. */
6829
6830 /* arm_parse_reloc () works on input_line_pointer.
6831 We actually want to parse the operands to the branch instruction
6832 passed in 'str'. Save the input pointer and restore it later. */
6833 save_in = input_line_pointer;
6834 input_line_pointer = str;
6835 if (inst.reloc.exp.X_op == O_symbol
6836 && *str == '('
6837 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6838 {
6839 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6840 inst.reloc.pc_rel = 0;
6841 /* Modify str to point to after parsed operands, otherwise
6842 end_of_line() will complain about the (PLT) left in str. */
6843 str = input_line_pointer;
6844 }
6845 else
6846 {
6847 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6848 inst.reloc.pc_rel = 1;
6849 }
6850 input_line_pointer = save_in;
6851 }
6852#else
6853 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6854 inst.reloc.pc_rel = 1;
6855#endif /* OBJ_ELF */
6856
6857 end_of_line (str);
b99bd4ef
NC
6858}
6859
6860static void
a737bd4d 6861do_cdp (char * str)
b99bd4ef
NC
6862{
6863 /* Co-processor data operation.
6864 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6865 skip_whitespace (str);
6866
6867 if (co_proc_number (&str) == FAIL)
6868 {
6869 if (!inst.error)
6870 inst.error = BAD_ARGS;
6871 return;
6872 }
6873
6874 if (skip_past_comma (&str) == FAIL
6875 || cp_opc_expr (&str, 20,4) == FAIL)
6876 {
6877 if (!inst.error)
6878 inst.error = BAD_ARGS;
6879 return;
6880 }
6881
6882 if (skip_past_comma (&str) == FAIL
6883 || cp_reg_required_here (&str, 12) == FAIL)
6884 {
6885 if (!inst.error)
6886 inst.error = BAD_ARGS;
6887 return;
6888 }
6889
6890 if (skip_past_comma (&str) == FAIL
6891 || cp_reg_required_here (&str, 16) == FAIL)
6892 {
6893 if (!inst.error)
6894 inst.error = BAD_ARGS;
6895 return;
6896 }
6897
6898 if (skip_past_comma (&str) == FAIL
6899 || cp_reg_required_here (&str, 0) == FAIL)
6900 {
6901 if (!inst.error)
6902 inst.error = BAD_ARGS;
6903 return;
6904 }
6905
6906 if (skip_past_comma (&str) == SUCCESS)
6907 {
6908 if (cp_opc_expr (&str, 5, 3) == FAIL)
6909 {
6910 if (!inst.error)
6911 inst.error = BAD_ARGS;
6912 return;
6913 }
6914 }
6915
6916 end_of_line (str);
b99bd4ef
NC
6917}
6918
6919static void
a737bd4d 6920do_lstc (char * str)
b99bd4ef
NC
6921{
6922 /* Co-processor register load/store.
6923 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6924
6925 skip_whitespace (str);
6926
6927 if (co_proc_number (&str) == FAIL)
6928 {
6929 if (!inst.error)
6930 inst.error = BAD_ARGS;
6931 return;
6932 }
6933
6934 if (skip_past_comma (&str) == FAIL
6935 || cp_reg_required_here (&str, 12) == FAIL)
6936 {
6937 if (!inst.error)
6938 inst.error = BAD_ARGS;
6939 return;
6940 }
6941
6942 if (skip_past_comma (&str) == FAIL
bfae80f2 6943 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
6944 {
6945 if (! inst.error)
6946 inst.error = BAD_ARGS;
6947 return;
6948 }
6949
b99bd4ef 6950 end_of_line (str);
b99bd4ef
NC
6951}
6952
6953static void
a737bd4d 6954do_co_reg (char * str)
b99bd4ef
NC
6955{
6956 /* Co-processor register transfer.
6957 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6958
6959 skip_whitespace (str);
6960
6961 if (co_proc_number (&str) == FAIL)
6962 {
6963 if (!inst.error)
6964 inst.error = BAD_ARGS;
6965 return;
6966 }
6967
6968 if (skip_past_comma (&str) == FAIL
6969 || cp_opc_expr (&str, 21, 3) == FAIL)
6970 {
6971 if (!inst.error)
6972 inst.error = BAD_ARGS;
6973 return;
6974 }
6975
6976 if (skip_past_comma (&str) == FAIL
6977 || reg_required_here (&str, 12) == FAIL)
6978 {
6979 if (!inst.error)
6980 inst.error = BAD_ARGS;
6981 return;
6982 }
6983
6984 if (skip_past_comma (&str) == FAIL
6985 || cp_reg_required_here (&str, 16) == FAIL)
6986 {
6987 if (!inst.error)
6988 inst.error = BAD_ARGS;
6989 return;
6990 }
6991
6992 if (skip_past_comma (&str) == FAIL
6993 || cp_reg_required_here (&str, 0) == FAIL)
6994 {
6995 if (!inst.error)
6996 inst.error = BAD_ARGS;
6997 return;
6998 }
6999
7000 if (skip_past_comma (&str) == SUCCESS)
7001 {
7002 if (cp_opc_expr (&str, 5, 3) == FAIL)
7003 {
7004 if (!inst.error)
7005 inst.error = BAD_ARGS;
7006 return;
7007 }
7008 }
b99bd4ef
NC
7009
7010 end_of_line (str);
b99bd4ef
NC
7011}
7012
7013static void
a737bd4d 7014do_fpa_ctrl (char * str)
b99bd4ef
NC
7015{
7016 /* FP control registers.
7017 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7018
7019 skip_whitespace (str);
7020
7021 if (reg_required_here (&str, 12) == FAIL)
7022 {
7023 if (!inst.error)
7024 inst.error = BAD_ARGS;
7025 return;
7026 }
7027
7028 end_of_line (str);
b99bd4ef
NC
7029}
7030
7031static void
a737bd4d 7032do_fpa_ldst (char * str)
b99bd4ef
NC
7033{
7034 skip_whitespace (str);
7035
b99bd4ef
NC
7036 if (fp_reg_required_here (&str, 12) == FAIL)
7037 {
7038 if (!inst.error)
7039 inst.error = BAD_ARGS;
7040 return;
7041 }
7042
7043 if (skip_past_comma (&str) == FAIL
bfae80f2 7044 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7045 {
7046 if (!inst.error)
7047 inst.error = BAD_ARGS;
7048 return;
7049 }
7050
7051 end_of_line (str);
7052}
7053
7054static void
a737bd4d 7055do_fpa_ldmstm (char * str)
b99bd4ef
NC
7056{
7057 int num_regs;
7058
7059 skip_whitespace (str);
7060
7061 if (fp_reg_required_here (&str, 12) == FAIL)
7062 {
7063 if (! inst.error)
7064 inst.error = BAD_ARGS;
7065 return;
7066 }
7067
7068 /* Get Number of registers to transfer. */
7069 if (skip_past_comma (&str) == FAIL
7070 || my_get_expression (&inst.reloc.exp, &str))
7071 {
7072 if (! inst.error)
7073 inst.error = _("constant expression expected");
7074 return;
7075 }
7076
7077 if (inst.reloc.exp.X_op != O_constant)
7078 {
f03698e6 7079 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
7080 return;
7081 }
7082
7083 num_regs = inst.reloc.exp.X_add_number;
7084
7085 if (num_regs < 1 || num_regs > 4)
7086 {
7087 inst.error = _("number of registers must be in the range [1:4]");
7088 return;
7089 }
7090
7091 switch (num_regs)
7092 {
7093 case 1:
7094 inst.instruction |= CP_T_X;
7095 break;
7096 case 2:
7097 inst.instruction |= CP_T_Y;
7098 break;
7099 case 3:
7100 inst.instruction |= CP_T_Y | CP_T_X;
7101 break;
7102 case 4:
7103 break;
7104 default:
7105 abort ();
7106 }
7107
e28cd48c 7108 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
7109 {
7110 int reg;
7111 int write_back;
7112 int offset;
7113
7114 /* The instruction specified "ea" or "fd", so we can only accept
7115 [Rn]{!}. The instruction does not really support stacking or
7116 unstacking, so we have to emulate these by setting appropriate
7117 bits and offsets. */
7118 if (skip_past_comma (&str) == FAIL
7119 || *str != '[')
7120 {
7121 if (! inst.error)
7122 inst.error = BAD_ARGS;
7123 return;
7124 }
7125
7126 str++;
7127 skip_whitespace (str);
7128
7129 if ((reg = reg_required_here (&str, 16)) == FAIL)
7130 return;
7131
7132 skip_whitespace (str);
7133
7134 if (*str != ']')
7135 {
7136 inst.error = BAD_ARGS;
7137 return;
7138 }
7139
7140 str++;
7141 if (*str == '!')
7142 {
7143 write_back = 1;
7144 str++;
7145 if (reg == REG_PC)
7146 {
7147 inst.error =
f03698e6 7148 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
7149 return;
7150 }
7151 }
7152 else
7153 write_back = 0;
7154
90e4755a 7155 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
7156 {
7157 /* Pre-decrement. */
7158 offset = 3 * num_regs;
7159 if (write_back)
90e4755a 7160 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7161 }
7162 else
7163 {
7164 /* Post-increment. */
7165 if (write_back)
7166 {
90e4755a 7167 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7168 offset = 3 * num_regs;
7169 }
7170 else
7171 {
7172 /* No write-back, so convert this into a standard pre-increment
7173 instruction -- aesthetically more pleasing. */
90e4755a 7174 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
7175 offset = 0;
7176 }
7177 }
7178
f2b7cb0a 7179 inst.instruction |= offset;
b99bd4ef
NC
7180 }
7181 else if (skip_past_comma (&str) == FAIL
bfae80f2 7182 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7183 {
7184 if (! inst.error)
7185 inst.error = BAD_ARGS;
7186 return;
7187 }
7188
7189 end_of_line (str);
7190}
7191
7192static void
a737bd4d 7193do_fpa_dyadic (char * str)
b99bd4ef
NC
7194{
7195 skip_whitespace (str);
7196
b99bd4ef
NC
7197 if (fp_reg_required_here (&str, 12) == FAIL)
7198 {
7199 if (! inst.error)
7200 inst.error = BAD_ARGS;
7201 return;
7202 }
7203
7204 if (skip_past_comma (&str) == FAIL
7205 || fp_reg_required_here (&str, 16) == FAIL)
7206 {
7207 if (! inst.error)
7208 inst.error = BAD_ARGS;
7209 return;
7210 }
7211
7212 if (skip_past_comma (&str) == FAIL
7213 || fp_op2 (&str) == FAIL)
7214 {
7215 if (! inst.error)
7216 inst.error = BAD_ARGS;
7217 return;
7218 }
7219
b99bd4ef 7220 end_of_line (str);
b99bd4ef
NC
7221}
7222
7223static void
a737bd4d 7224do_fpa_monadic (char * str)
b99bd4ef
NC
7225{
7226 skip_whitespace (str);
7227
b99bd4ef
NC
7228 if (fp_reg_required_here (&str, 12) == FAIL)
7229 {
7230 if (! inst.error)
7231 inst.error = BAD_ARGS;
7232 return;
7233 }
7234
7235 if (skip_past_comma (&str) == FAIL
7236 || fp_op2 (&str) == FAIL)
7237 {
7238 if (! inst.error)
7239 inst.error = BAD_ARGS;
7240 return;
7241 }
7242
b99bd4ef 7243 end_of_line (str);
b99bd4ef
NC
7244}
7245
7246static void
a737bd4d 7247do_fpa_cmp (char * str)
b99bd4ef
NC
7248{
7249 skip_whitespace (str);
7250
7251 if (fp_reg_required_here (&str, 16) == FAIL)
7252 {
7253 if (! inst.error)
7254 inst.error = BAD_ARGS;
7255 return;
7256 }
7257
7258 if (skip_past_comma (&str) == FAIL
7259 || fp_op2 (&str) == FAIL)
7260 {
7261 if (! inst.error)
7262 inst.error = BAD_ARGS;
7263 return;
7264 }
7265
b99bd4ef 7266 end_of_line (str);
b99bd4ef
NC
7267}
7268
7269static void
a737bd4d 7270do_fpa_from_reg (char * str)
b99bd4ef
NC
7271{
7272 skip_whitespace (str);
7273
b99bd4ef
NC
7274 if (fp_reg_required_here (&str, 16) == FAIL)
7275 {
7276 if (! inst.error)
7277 inst.error = BAD_ARGS;
7278 return;
7279 }
7280
7281 if (skip_past_comma (&str) == FAIL
7282 || reg_required_here (&str, 12) == FAIL)
7283 {
7284 if (! inst.error)
7285 inst.error = BAD_ARGS;
7286 return;
7287 }
7288
b99bd4ef 7289 end_of_line (str);
b99bd4ef
NC
7290}
7291
7292static void
a737bd4d 7293do_fpa_to_reg (char * str)
b99bd4ef
NC
7294{
7295 skip_whitespace (str);
7296
7297 if (reg_required_here (&str, 12) == FAIL)
7298 return;
7299
7300 if (skip_past_comma (&str) == FAIL
7301 || fp_reg_required_here (&str, 0) == FAIL)
7302 {
7303 if (! inst.error)
7304 inst.error = BAD_ARGS;
7305 return;
7306 }
7307
b99bd4ef 7308 end_of_line (str);
b99bd4ef
NC
7309}
7310
7ed4c4c5
NC
7311/* Encode a VFP SP register number. */
7312
7313static void
7314vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7315{
7316 switch (pos)
7317 {
7318 case VFP_REG_Sd:
7319 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7320 break;
7321
7322 case VFP_REG_Sn:
7323 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7324 break;
7325
7326 case VFP_REG_Sm:
7327 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7328 break;
7329
7330 default:
7331 abort ();
7332 }
7333}
7334
b99bd4ef 7335static int
a737bd4d
NC
7336vfp_sp_reg_required_here (char ** str,
7337 enum vfp_sp_reg_pos pos)
b99bd4ef 7338{
bfae80f2 7339 int reg;
7ed4c4c5 7340 char * start = *str;
b99bd4ef 7341
bfae80f2 7342 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 7343 {
7ed4c4c5 7344 vfp_sp_encode_reg (reg, pos);
bfae80f2
RE
7345 return reg;
7346 }
b99bd4ef 7347
bfae80f2
RE
7348 /* In the few cases where we might be able to accept something else
7349 this error can be overridden. */
7350 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7351
7352 /* Restore the start point. */
7353 *str = start;
7354 return FAIL;
7355}
7356
7357static int
a737bd4d
NC
7358vfp_dp_reg_required_here (char ** str,
7359 enum vfp_dp_reg_pos pos)
bfae80f2 7360{
a737bd4d
NC
7361 int reg;
7362 char * start = *str;
bfae80f2
RE
7363
7364 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7365 {
7366 switch (pos)
b99bd4ef 7367 {
bfae80f2
RE
7368 case VFP_REG_Dd:
7369 inst.instruction |= reg << 12;
7370 break;
b99bd4ef 7371
bfae80f2
RE
7372 case VFP_REG_Dn:
7373 inst.instruction |= reg << 16;
7374 break;
7375
7376 case VFP_REG_Dm:
7377 inst.instruction |= reg << 0;
7378 break;
7379
7380 default:
7381 abort ();
7382 }
7383 return reg;
b99bd4ef
NC
7384 }
7385
bfae80f2
RE
7386 /* In the few cases where we might be able to accept something else
7387 this error can be overridden. */
7388 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 7389
bfae80f2
RE
7390 /* Restore the start point. */
7391 *str = start;
7392 return FAIL;
7393}
b99bd4ef
NC
7394
7395static void
a737bd4d 7396do_vfp_sp_monadic (char * str)
b99bd4ef 7397{
b99bd4ef
NC
7398 skip_whitespace (str);
7399
bfae80f2
RE
7400 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7401 return;
7402
7403 if (skip_past_comma (&str) == FAIL
7404 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
7405 {
7406 if (! inst.error)
7407 inst.error = BAD_ARGS;
7408 return;
7409 }
7410
bfae80f2 7411 end_of_line (str);
bfae80f2
RE
7412}
7413
7414static void
a737bd4d 7415do_vfp_dp_monadic (char * str)
bfae80f2
RE
7416{
7417 skip_whitespace (str);
7418
7419 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7420 return;
7421
7422 if (skip_past_comma (&str) == FAIL
7423 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 7424 {
bfae80f2
RE
7425 if (! inst.error)
7426 inst.error = BAD_ARGS;
7427 return;
b99bd4ef 7428 }
b99bd4ef 7429
bfae80f2 7430 end_of_line (str);
bfae80f2 7431}
b99bd4ef 7432
bfae80f2 7433static void
a737bd4d 7434do_vfp_sp_dyadic (char * str)
bfae80f2
RE
7435{
7436 skip_whitespace (str);
b99bd4ef 7437
bfae80f2
RE
7438 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7439 return;
b99bd4ef 7440
bfae80f2
RE
7441 if (skip_past_comma (&str) == FAIL
7442 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7443 || skip_past_comma (&str) == FAIL
7444 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 7445 {
bfae80f2
RE
7446 if (! inst.error)
7447 inst.error = BAD_ARGS;
7448 return;
7449 }
b99bd4ef 7450
bfae80f2 7451 end_of_line (str);
bfae80f2 7452}
b99bd4ef 7453
bfae80f2 7454static void
a737bd4d 7455do_vfp_dp_dyadic (char * str)
bfae80f2
RE
7456{
7457 skip_whitespace (str);
b99bd4ef 7458
bfae80f2
RE
7459 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7460 return;
b99bd4ef 7461
bfae80f2
RE
7462 if (skip_past_comma (&str) == FAIL
7463 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7464 || skip_past_comma (&str) == FAIL
7465 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7466 {
7467 if (! inst.error)
7468 inst.error = BAD_ARGS;
7469 return;
7470 }
b99bd4ef 7471
bfae80f2 7472 end_of_line (str);
bfae80f2 7473}
b99bd4ef 7474
bfae80f2 7475static void
a737bd4d 7476do_vfp_reg_from_sp (char * str)
bfae80f2
RE
7477{
7478 skip_whitespace (str);
7479
7480 if (reg_required_here (&str, 12) == FAIL)
7481 return;
7482
7483 if (skip_past_comma (&str) == FAIL
7484 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7485 {
7486 if (! inst.error)
7487 inst.error = BAD_ARGS;
7488 return;
7489 }
7490
7491 end_of_line (str);
bfae80f2
RE
7492}
7493
7ed4c4c5
NC
7494/* Parse a VFP register list. If the string is invalid return FAIL.
7495 Otherwise return the number of registers, and set PBASE to the first
7496 register. Double precision registers are matched if DP is nonzero. */
a737bd4d 7497
7ed4c4c5
NC
7498static int
7499vfp_parse_reg_list (char **str, int *pbase, int dp)
a737bd4d 7500{
7ed4c4c5 7501 int base_reg;
a737bd4d 7502 int new_base;
7ed4c4c5
NC
7503 int regtype;
7504 int max_regs;
a737bd4d 7505 int count = 0;
a737bd4d 7506 int warned = 0;
7ed4c4c5
NC
7507 unsigned long mask = 0;
7508 int i;
a737bd4d
NC
7509
7510 if (**str != '{')
7511 return FAIL;
7512
7513 (*str)++;
7514 skip_whitespace (*str);
7515
7ed4c4c5 7516 if (dp)
a737bd4d 7517 {
7ed4c4c5
NC
7518 regtype = REG_TYPE_DN;
7519 max_regs = 16;
7520 }
7521 else
7522 {
7523 regtype = REG_TYPE_SN;
7524 max_regs = 32;
7525 }
a737bd4d 7526
7ed4c4c5 7527 base_reg = max_regs;
a737bd4d 7528
7ed4c4c5
NC
7529 do
7530 {
7531 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7532 if (new_base == FAIL)
a737bd4d 7533 {
7ed4c4c5
NC
7534 inst.error = _(all_reg_maps[regtype].expected);
7535 return FAIL;
a737bd4d
NC
7536 }
7537
7ed4c4c5
NC
7538 if (new_base < base_reg)
7539 base_reg = new_base;
7540
a737bd4d
NC
7541 if (mask & (1 << new_base))
7542 {
7543 inst.error = _("invalid register list");
7544 return FAIL;
7545 }
7546
7547 if ((mask >> new_base) != 0 && ! warned)
7548 {
7549 as_tsktsk (_("register list not in ascending order"));
7550 warned = 1;
7551 }
7552
7553 mask |= 1 << new_base;
7554 count++;
7555
7556 skip_whitespace (*str);
7557
7558 if (**str == '-') /* We have the start of a range expression */
7559 {
7560 int high_range;
7561
7562 (*str)++;
7563
7564 if ((high_range
7ed4c4c5 7565 = arm_reg_parse (str, all_reg_maps[regtype].htab))
a737bd4d
NC
7566 == FAIL)
7567 {
7ed4c4c5 7568 inst.error = _(all_reg_maps[regtype].expected);
a737bd4d
NC
7569 return FAIL;
7570 }
7571
7572 if (high_range <= new_base)
7573 {
7574 inst.error = _("register range not in ascending order");
7575 return FAIL;
7576 }
7577
7578 for (new_base++; new_base <= high_range; new_base++)
7579 {
7580 if (mask & (1 << new_base))
7581 {
7582 inst.error = _("invalid register list");
7583 return FAIL;
7584 }
7585
7586 mask |= 1 << new_base;
7587 count++;
7588 }
7589 }
7590 }
7591 while (skip_past_comma (str) != FAIL);
7592
a737bd4d
NC
7593 (*str)++;
7594
a737bd4d 7595 /* Sanity check -- should have raised a parse error above. */
7ed4c4c5 7596 if (count == 0 || count > max_regs)
a737bd4d
NC
7597 abort ();
7598
7ed4c4c5
NC
7599 *pbase = base_reg;
7600
a737bd4d 7601 /* Final test -- the registers must be consecutive. */
7ed4c4c5
NC
7602 mask >>= base_reg;
7603 for (i = 0; i < count; i++)
a737bd4d 7604 {
7ed4c4c5 7605 if ((mask & (1u << i)) == 0)
a737bd4d
NC
7606 {
7607 inst.error = _("non-contiguous register range");
7608 return FAIL;
7609 }
7610 }
7611
7ed4c4c5 7612 return count;
a737bd4d
NC
7613}
7614
bfae80f2 7615static void
a737bd4d 7616do_vfp_reg2_from_sp2 (char * str)
bfae80f2 7617{
7ed4c4c5
NC
7618 int reg;
7619
bfae80f2
RE
7620 skip_whitespace (str);
7621
e45d0630
PB
7622 if (reg_required_here (&str, 12) == FAIL
7623 || skip_past_comma (&str) == FAIL
bfae80f2
RE
7624 || reg_required_here (&str, 16) == FAIL
7625 || skip_past_comma (&str) == FAIL)
7626 {
7627 if (! inst.error)
7628 inst.error = BAD_ARGS;
7629 return;
7630 }
7631
7632 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7633 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
bfae80f2
RE
7634 {
7635 if (! inst.error)
7636 inst.error = _("only two consecutive VFP SP registers allowed here");
7637 }
7ed4c4c5 7638 vfp_sp_encode_reg (reg, VFP_REG_Sm);
bfae80f2
RE
7639
7640 end_of_line (str);
bfae80f2
RE
7641}
7642
7643static void
a737bd4d 7644do_vfp_sp_from_reg (char * str)
bfae80f2
RE
7645{
7646 skip_whitespace (str);
7647
7648 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7649 return;
7650
7651 if (skip_past_comma (&str) == FAIL
7652 || reg_required_here (&str, 12) == FAIL)
7653 {
7654 if (! inst.error)
7655 inst.error = BAD_ARGS;
7656 return;
7657 }
7658
7659 end_of_line (str);
bfae80f2
RE
7660}
7661
e45d0630 7662static void
a737bd4d 7663do_vfp_sp2_from_reg2 (char * str)
e45d0630 7664{
7ed4c4c5
NC
7665 int reg;
7666
e45d0630
PB
7667 skip_whitespace (str);
7668
7669 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7670 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
e45d0630
PB
7671 {
7672 if (! inst.error)
7673 inst.error = _("only two consecutive VFP SP registers allowed here");
7674 }
7ed4c4c5 7675 vfp_sp_encode_reg (reg, VFP_REG_Sm);
e45d0630
PB
7676
7677 if (skip_past_comma (&str) == FAIL
7678 || reg_required_here (&str, 12) == FAIL
7679 || skip_past_comma (&str) == FAIL
7680 || reg_required_here (&str, 16) == FAIL)
7681 {
7682 if (! inst.error)
7683 inst.error = BAD_ARGS;
7684 return;
7685 }
7686
7687 end_of_line (str);
7688}
7689
bfae80f2 7690static void
a737bd4d 7691do_vfp_reg_from_dp (char * str)
bfae80f2
RE
7692{
7693 skip_whitespace (str);
7694
7695 if (reg_required_here (&str, 12) == FAIL)
7696 return;
7697
7698 if (skip_past_comma (&str) == FAIL
7699 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7700 {
7701 if (! inst.error)
7702 inst.error = BAD_ARGS;
7703 return;
7704 }
7705
7706 end_of_line (str);
bfae80f2
RE
7707}
7708
7709static void
a737bd4d 7710do_vfp_reg2_from_dp (char * str)
bfae80f2
RE
7711{
7712 skip_whitespace (str);
7713
7714 if (reg_required_here (&str, 12) == FAIL)
7715 return;
7716
7717 if (skip_past_comma (&str) == FAIL
7718 || reg_required_here (&str, 16) == FAIL
7719 || skip_past_comma (&str) == FAIL
7720 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7721 {
7722 if (! inst.error)
7723 inst.error = BAD_ARGS;
7724 return;
7725 }
7726
7727 end_of_line (str);
bfae80f2
RE
7728}
7729
7730static void
a737bd4d 7731do_vfp_dp_from_reg (char * str)
bfae80f2
RE
7732{
7733 skip_whitespace (str);
7734
7735 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7736 return;
7737
7738 if (skip_past_comma (&str) == FAIL
7739 || reg_required_here (&str, 12) == FAIL)
7740 {
7741 if (! inst.error)
7742 inst.error = BAD_ARGS;
7743 return;
7744 }
7745
7746 end_of_line (str);
bfae80f2
RE
7747}
7748
7749static void
a737bd4d 7750do_vfp_dp_from_reg2 (char * str)
bfae80f2
RE
7751{
7752 skip_whitespace (str);
7753
7754 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7755 return;
7756
7757 if (skip_past_comma (&str) == FAIL
7758 || reg_required_here (&str, 12) == FAIL
7759 || skip_past_comma (&str) == FAIL
e45d0630 7760 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
7761 {
7762 if (! inst.error)
7763 inst.error = BAD_ARGS;
7764 return;
7765 }
7766
7767 end_of_line (str);
bfae80f2
RE
7768}
7769
7770static const struct vfp_reg *
a737bd4d 7771vfp_psr_parse (char ** str)
bfae80f2
RE
7772{
7773 char *start = *str;
7774 char c;
7775 char *p;
7776 const struct vfp_reg *vreg;
7777
7778 p = start;
7779
7780 /* Find the end of the current token. */
7781 do
7782 {
7783 c = *p++;
7784 }
7785 while (ISALPHA (c));
7786
7787 /* Mark it. */
7788 *--p = 0;
7789
cc8a6dd0 7790 for (vreg = vfp_regs + 0;
bfae80f2
RE
7791 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7792 vreg++)
7793 {
a737bd4d 7794 if (streq (start, vreg->name))
bfae80f2
RE
7795 {
7796 *p = c;
7797 *str = p;
7798 return vreg;
7799 }
7800 }
7801
7802 *p = c;
7803 return NULL;
7804}
7805
7806static int
a737bd4d 7807vfp_psr_required_here (char ** str)
bfae80f2
RE
7808{
7809 char *start = *str;
7810 const struct vfp_reg *vreg;
7811
7812 vreg = vfp_psr_parse (str);
7813
7814 if (vreg)
7815 {
7816 inst.instruction |= vreg->regno;
7817 return SUCCESS;
7818 }
7819
7820 inst.error = _("VFP system register expected");
7821
7822 *str = start;
7823 return FAIL;
7824}
7825
7826static void
a737bd4d 7827do_vfp_reg_from_ctrl (char * str)
bfae80f2
RE
7828{
7829 skip_whitespace (str);
7830
7831 if (reg_required_here (&str, 12) == FAIL)
7832 return;
7833
7834 if (skip_past_comma (&str) == FAIL
7835 || vfp_psr_required_here (&str) == FAIL)
7836 {
7837 if (! inst.error)
7838 inst.error = BAD_ARGS;
7839 return;
7840 }
7841
7842 end_of_line (str);
bfae80f2
RE
7843}
7844
7845static void
a737bd4d 7846do_vfp_ctrl_from_reg (char * str)
bfae80f2
RE
7847{
7848 skip_whitespace (str);
7849
7850 if (vfp_psr_required_here (&str) == FAIL)
7851 return;
7852
7853 if (skip_past_comma (&str) == FAIL
7854 || reg_required_here (&str, 12) == FAIL)
7855 {
7856 if (! inst.error)
7857 inst.error = BAD_ARGS;
7858 return;
7859 }
7860
7861 end_of_line (str);
bfae80f2
RE
7862}
7863
7864static void
a737bd4d 7865do_vfp_sp_ldst (char * str)
bfae80f2
RE
7866{
7867 skip_whitespace (str);
7868
7869 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7870 {
7871 if (!inst.error)
7872 inst.error = BAD_ARGS;
7873 return;
7874 }
7875
7876 if (skip_past_comma (&str) == FAIL
7877 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7878 {
7879 if (!inst.error)
7880 inst.error = BAD_ARGS;
7881 return;
7882 }
7883
7884 end_of_line (str);
bfae80f2
RE
7885}
7886
7887static void
a737bd4d 7888do_vfp_dp_ldst (char * str)
bfae80f2
RE
7889{
7890 skip_whitespace (str);
7891
7892 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7893 {
7894 if (!inst.error)
7895 inst.error = BAD_ARGS;
7896 return;
7897 }
7898
7899 if (skip_past_comma (&str) == FAIL
7900 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7901 {
7902 if (!inst.error)
a737bd4d
NC
7903 inst.error = BAD_ARGS;
7904 return;
bfae80f2
RE
7905 }
7906
a737bd4d 7907 end_of_line (str);
bfae80f2
RE
7908}
7909
bfae80f2
RE
7910
7911static void
a737bd4d 7912vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 7913{
7ed4c4c5
NC
7914 int count;
7915 int reg;
bfae80f2
RE
7916
7917 skip_whitespace (str);
7918
7919 if (reg_required_here (&str, 16) == FAIL)
7920 return;
7921
7922 skip_whitespace (str);
7923
7924 if (*str == '!')
7925 {
7926 inst.instruction |= WRITE_BACK;
7927 str++;
7928 }
7929 else if (ldstm_type != VFP_LDSTMIA)
7930 {
7931 inst.error = _("this addressing mode requires base-register writeback");
7932 return;
7933 }
7934
7935 if (skip_past_comma (&str) == FAIL
7ed4c4c5 7936 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
bfae80f2
RE
7937 {
7938 if (!inst.error)
7939 inst.error = BAD_ARGS;
7940 return;
7941 }
7ed4c4c5 7942 vfp_sp_encode_reg (reg, VFP_REG_Sd);
bfae80f2 7943
7ed4c4c5 7944 inst.instruction |= count;
bfae80f2
RE
7945 end_of_line (str);
7946}
7947
7948static void
a737bd4d 7949vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 7950{
7ed4c4c5
NC
7951 int count;
7952 int reg;
bfae80f2
RE
7953
7954 skip_whitespace (str);
7955
7956 if (reg_required_here (&str, 16) == FAIL)
7957 return;
7958
7959 skip_whitespace (str);
7960
7961 if (*str == '!')
7962 {
7963 inst.instruction |= WRITE_BACK;
7964 str++;
7965 }
7966 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7967 {
7968 inst.error = _("this addressing mode requires base-register writeback");
7969 return;
7970 }
7971
7972 if (skip_past_comma (&str) == FAIL
7ed4c4c5 7973 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
bfae80f2
RE
7974 {
7975 if (!inst.error)
7976 inst.error = BAD_ARGS;
7977 return;
7978 }
7979
7ed4c4c5 7980 count <<= 1;
bfae80f2 7981 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7ed4c4c5 7982 count += 1;
bfae80f2 7983
7ed4c4c5 7984 inst.instruction |= (reg << 12) | count;
bfae80f2
RE
7985 end_of_line (str);
7986}
7987
7988static void
a737bd4d 7989do_vfp_sp_ldstmia (char * str)
bfae80f2
RE
7990{
7991 vfp_sp_ldstm (str, VFP_LDSTMIA);
7992}
7993
7994static void
a737bd4d 7995do_vfp_sp_ldstmdb (char * str)
bfae80f2
RE
7996{
7997 vfp_sp_ldstm (str, VFP_LDSTMDB);
7998}
7999
8000static void
a737bd4d 8001do_vfp_dp_ldstmia (char * str)
bfae80f2
RE
8002{
8003 vfp_dp_ldstm (str, VFP_LDSTMIA);
8004}
8005
8006static void
a737bd4d 8007do_vfp_dp_ldstmdb (char * str)
bfae80f2
RE
8008{
8009 vfp_dp_ldstm (str, VFP_LDSTMDB);
8010}
8011
8012static void
a737bd4d 8013do_vfp_xp_ldstmia (char *str)
bfae80f2
RE
8014{
8015 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8016}
8017
8018static void
a737bd4d 8019do_vfp_xp_ldstmdb (char * str)
bfae80f2
RE
8020{
8021 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8022}
8023
8024static void
a737bd4d 8025do_vfp_sp_compare_z (char * str)
bfae80f2
RE
8026{
8027 skip_whitespace (str);
8028
8029 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8030 {
8031 if (!inst.error)
8032 inst.error = BAD_ARGS;
8033 return;
8034 }
8035
8036 end_of_line (str);
bfae80f2
RE
8037}
8038
8039static void
a737bd4d 8040do_vfp_dp_compare_z (char * str)
bfae80f2
RE
8041{
8042 skip_whitespace (str);
8043
8044 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8045 {
8046 if (!inst.error)
8047 inst.error = BAD_ARGS;
8048 return;
8049 }
8050
8051 end_of_line (str);
bfae80f2
RE
8052}
8053
8054static void
a737bd4d 8055do_vfp_dp_sp_cvt (char * str)
bfae80f2
RE
8056{
8057 skip_whitespace (str);
8058
8059 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8060 return;
8061
8062 if (skip_past_comma (&str) == FAIL
8063 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8064 {
8065 if (! inst.error)
8066 inst.error = BAD_ARGS;
8067 return;
8068 }
8069
8070 end_of_line (str);
bfae80f2
RE
8071}
8072
8073static void
a737bd4d 8074do_vfp_sp_dp_cvt (char * str)
bfae80f2
RE
8075{
8076 skip_whitespace (str);
8077
8078 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8079 return;
8080
8081 if (skip_past_comma (&str) == FAIL
8082 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8083 {
8084 if (! inst.error)
8085 inst.error = BAD_ARGS;
8086 return;
8087 }
8088
8089 end_of_line (str);
bfae80f2
RE
8090}
8091
8092/* Thumb specific routines. */
8093
bfae80f2
RE
8094/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8095 was SUB. */
8096
8097static void
a737bd4d 8098thumb_add_sub (char * str, int subtract)
bfae80f2
RE
8099{
8100 int Rd, Rs, Rn = FAIL;
8101
8102 skip_whitespace (str);
8103
8104 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8105 || skip_past_comma (&str) == FAIL)
8106 {
8107 if (! inst.error)
8108 inst.error = BAD_ARGS;
8109 return;
8110 }
8111
8112 if (is_immediate_prefix (*str))
8113 {
8114 Rs = Rd;
8115 str++;
8116 if (my_get_expression (&inst.reloc.exp, &str))
8117 return;
8118 }
8119 else
8120 {
8121 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8122 return;
8123
8124 if (skip_past_comma (&str) == FAIL)
8125 {
8126 /* Two operand format, shuffle the registers
8127 and pretend there are 3. */
8128 Rn = Rs;
8129 Rs = Rd;
8130 }
8131 else if (is_immediate_prefix (*str))
8132 {
8133 str++;
8134 if (my_get_expression (&inst.reloc.exp, &str))
8135 return;
8136 }
8137 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8138 return;
8139 }
8140
8141 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8142 for the latter case, EXPR contains the immediate that was found. */
8143 if (Rn != FAIL)
8144 {
8145 /* All register format. */
8146 if (Rd > 7 || Rs > 7 || Rn > 7)
8147 {
8148 if (Rs != Rd)
8149 {
8150 inst.error = _("dest and source1 must be the same register");
8151 return;
8152 }
8153
8154 /* Can't do this for SUB. */
8155 if (subtract)
8156 {
8157 inst.error = _("subtract valid only on lo regs");
8158 return;
8159 }
8160
8161 inst.instruction = (T_OPCODE_ADD_HI
8162 | (Rd > 7 ? THUMB_H1 : 0)
8163 | (Rn > 7 ? THUMB_H2 : 0));
8164 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8165 }
8166 else
8167 {
8168 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8169 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8170 }
8171 }
8172 else
8173 {
8174 /* Immediate expression, now things start to get nasty. */
8175
8176 /* First deal with HI regs, only very restricted cases allowed:
8177 Adjusting SP, and using PC or SP to get an address. */
8178 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8179 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8180 {
8181 inst.error = _("invalid Hi register with immediate");
8182 return;
8183 }
8184
8185 if (inst.reloc.exp.X_op != O_constant)
8186 {
8187 /* Value isn't known yet, all we can do is store all the fragments
8188 we know about in the instruction and let the reloc hacking
8189 work it all out. */
8190 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8191 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8192 }
8193 else
8194 {
8195 int offset = inst.reloc.exp.X_add_number;
8196
8197 if (subtract)
358b94bd 8198 offset = - offset;
bfae80f2
RE
8199
8200 if (offset < 0)
8201 {
358b94bd 8202 offset = - offset;
bfae80f2
RE
8203 subtract = 1;
8204
8205 /* Quick check, in case offset is MIN_INT. */
8206 if (offset < 0)
8207 {
8208 inst.error = _("immediate value out of range");
8209 return;
8210 }
8211 }
358b94bd
NC
8212 /* Note - you cannot convert a subtract of 0 into an
8213 add of 0 because the carry flag is set differently. */
8214 else if (offset > 0)
bfae80f2
RE
8215 subtract = 0;
8216
8217 if (Rd == REG_SP)
8218 {
8219 if (offset & ~0x1fc)
8220 {
8221 inst.error = _("invalid immediate value for stack adjust");
8222 return;
b99bd4ef
NC
8223 }
8224 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8225 inst.instruction |= offset >> 2;
8226 }
8227 else if (Rs == REG_PC || Rs == REG_SP)
8228 {
8229 if (subtract
8230 || (offset & ~0x3fc))
8231 {
8232 inst.error = _("invalid immediate for address calculation");
8233 return;
8234 }
8235 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8236 : T_OPCODE_ADD_SP);
8237 inst.instruction |= (Rd << 8) | (offset >> 2);
8238 }
8239 else if (Rs == Rd)
8240 {
8241 if (offset & ~0xff)
8242 {
8243 inst.error = _("immediate value out of range");
8244 return;
8245 }
8246 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8247 inst.instruction |= (Rd << 8) | offset;
8248 }
8249 else
8250 {
8251 if (offset & ~0x7)
8252 {
8253 inst.error = _("immediate value out of range");
8254 return;
8255 }
8256 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8257 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8258 }
8259 }
8260 }
8261
8262 end_of_line (str);
8263}
8264
8265static void
a737bd4d 8266thumb_shift (char * str, int shift)
b99bd4ef
NC
8267{
8268 int Rd, Rs, Rn = FAIL;
8269
8270 skip_whitespace (str);
8271
8272 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8273 || skip_past_comma (&str) == FAIL)
8274 {
8275 if (! inst.error)
8276 inst.error = BAD_ARGS;
8277 return;
8278 }
8279
8280 if (is_immediate_prefix (*str))
8281 {
8282 /* Two operand immediate format, set Rs to Rd. */
8283 Rs = Rd;
8284 str ++;
8285 if (my_get_expression (&inst.reloc.exp, &str))
8286 return;
8287 }
8288 else
8289 {
8290 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8291 return;
8292
8293 if (skip_past_comma (&str) == FAIL)
8294 {
8295 /* Two operand format, shuffle the registers
8296 and pretend there are 3. */
8297 Rn = Rs;
8298 Rs = Rd;
8299 }
8300 else if (is_immediate_prefix (*str))
8301 {
8302 str++;
8303 if (my_get_expression (&inst.reloc.exp, &str))
8304 return;
8305 }
8306 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8307 return;
8308 }
8309
8310 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8311 for the latter case, EXPR contains the immediate that was found. */
8312
8313 if (Rn != FAIL)
8314 {
8315 if (Rs != Rd)
8316 {
8317 inst.error = _("source1 and dest must be same register");
8318 return;
8319 }
8320
8321 switch (shift)
8322 {
8323 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8324 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8325 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8326 }
8327
8328 inst.instruction |= Rd | (Rn << 3);
8329 }
8330 else
8331 {
8332 switch (shift)
8333 {
8334 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8335 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8336 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8337 }
8338
8339 if (inst.reloc.exp.X_op != O_constant)
8340 {
8341 /* Value isn't known yet, create a dummy reloc and let reloc
8342 hacking fix it up. */
8343 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8344 }
8345 else
8346 {
8347 unsigned shift_value = inst.reloc.exp.X_add_number;
8348
8349 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8350 {
f03698e6 8351 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
8352 return;
8353 }
8354
8355 /* Shifts of zero are handled by converting to LSL. */
8356 if (shift_value == 0)
8357 inst.instruction = T_OPCODE_LSL_I;
8358
8359 /* Shifts of 32 are encoded as a shift of zero. */
8360 if (shift_value == 32)
8361 shift_value = 0;
8362
8363 inst.instruction |= shift_value << 6;
8364 }
8365
8366 inst.instruction |= Rd | (Rs << 3);
8367 }
8368
8369 end_of_line (str);
8370}
8371
8372static void
a737bd4d 8373thumb_load_store (char * str, int load_store, int size)
b99bd4ef
NC
8374{
8375 int Rd, Rb, Ro = FAIL;
8376
8377 skip_whitespace (str);
8378
8379 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8380 || skip_past_comma (&str) == FAIL)
8381 {
8382 if (! inst.error)
8383 inst.error = BAD_ARGS;
8384 return;
8385 }
8386
8387 if (*str == '[')
8388 {
8389 str++;
8390 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8391 return;
8392
8393 if (skip_past_comma (&str) != FAIL)
8394 {
8395 if (is_immediate_prefix (*str))
8396 {
8397 str++;
8398 if (my_get_expression (&inst.reloc.exp, &str))
8399 return;
8400 }
8401 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8402 return;
8403 }
8404 else
8405 {
8406 inst.reloc.exp.X_op = O_constant;
8407 inst.reloc.exp.X_add_number = 0;
8408 }
8409
8410 if (*str != ']')
8411 {
8412 inst.error = _("expected ']'");
8413 return;
8414 }
8415 str++;
8416 }
8417 else if (*str == '=')
8418 {
f03698e6
RE
8419 if (load_store != THUMB_LOAD)
8420 {
8421 inst.error = _("invalid pseudo operation");
8422 return;
8423 }
8424
b99bd4ef
NC
8425 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8426 str++;
8427
8428 skip_whitespace (str);
8429
8430 if (my_get_expression (& inst.reloc.exp, & str))
8431 return;
8432
8433 end_of_line (str);
8434
8435 if ( inst.reloc.exp.X_op != O_constant
8436 && inst.reloc.exp.X_op != O_symbol)
8437 {
8438 inst.error = "Constant expression expected";
8439 return;
8440 }
8441
8442 if (inst.reloc.exp.X_op == O_constant
8443 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8444 {
8445 /* This can be done with a mov instruction. */
8446
8447 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8448 inst.instruction |= inst.reloc.exp.X_add_number;
8449 return;
8450 }
8451
8452 /* Insert into literal pool. */
8453 if (add_to_lit_pool () == FAIL)
8454 {
8455 if (!inst.error)
8456 inst.error = "literal pool insertion failed";
8457 return;
8458 }
8459
8460 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8461 inst.reloc.pc_rel = 1;
8462 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8463 /* Adjust ARM pipeline offset to Thumb. */
8464 inst.reloc.exp.X_add_number += 4;
8465
8466 return;
8467 }
8468 else
8469 {
8470 if (my_get_expression (&inst.reloc.exp, &str))
8471 return;
8472
8473 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8474 inst.reloc.pc_rel = 1;
8475 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8476 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8477 end_of_line (str);
8478 return;
8479 }
8480
8481 if (Rb == REG_PC || Rb == REG_SP)
8482 {
8483 if (size != THUMB_WORD)
8484 {
8485 inst.error = _("byte or halfword not valid for base register");
8486 return;
8487 }
8488 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8489 {
f03698e6 8490 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
8491 return;
8492 }
8493 else if (Ro != FAIL)
8494 {
f03698e6 8495 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
8496 return;
8497 }
8498
8499 if (Rb == REG_PC)
8500 inst.instruction = T_OPCODE_LDR_PC;
8501 else if (load_store == THUMB_LOAD)
8502 inst.instruction = T_OPCODE_LDR_SP;
8503 else
8504 inst.instruction = T_OPCODE_STR_SP;
8505
8506 inst.instruction |= Rd << 8;
8507 if (inst.reloc.exp.X_op == O_constant)
8508 {
8509 unsigned offset = inst.reloc.exp.X_add_number;
8510
8511 if (offset & ~0x3fc)
8512 {
8513 inst.error = _("invalid offset");
8514 return;
8515 }
8516
8517 inst.instruction |= offset >> 2;
8518 }
8519 else
8520 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8521 }
8522 else if (Rb > 7)
8523 {
8524 inst.error = _("invalid base register in load/store");
8525 return;
8526 }
8527 else if (Ro == FAIL)
8528 {
8529 /* Immediate offset. */
8530 if (size == THUMB_WORD)
8531 inst.instruction = (load_store == THUMB_LOAD
8532 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8533 else if (size == THUMB_HALFWORD)
8534 inst.instruction = (load_store == THUMB_LOAD
8535 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8536 else
8537 inst.instruction = (load_store == THUMB_LOAD
8538 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8539
8540 inst.instruction |= Rd | (Rb << 3);
8541
8542 if (inst.reloc.exp.X_op == O_constant)
8543 {
8544 unsigned offset = inst.reloc.exp.X_add_number;
8545
8546 if (offset & ~(0x1f << size))
8547 {
f03698e6 8548 inst.error = _("invalid offset");
b99bd4ef
NC
8549 return;
8550 }
8551 inst.instruction |= (offset >> size) << 6;
8552 }
8553 else
8554 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8555 }
8556 else
8557 {
8558 /* Register offset. */
8559 if (size == THUMB_WORD)
8560 inst.instruction = (load_store == THUMB_LOAD
8561 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8562 else if (size == THUMB_HALFWORD)
8563 inst.instruction = (load_store == THUMB_LOAD
8564 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8565 else
8566 inst.instruction = (load_store == THUMB_LOAD
8567 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8568
8569 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8570 }
8571
8572 end_of_line (str);
8573}
8574
404ff6b5
AH
8575/* A register must be given at this point.
8576
404ff6b5
AH
8577 Shift is the place to put it in inst.instruction.
8578
404ff6b5
AH
8579 Restores input start point on err.
8580 Returns the reg#, or FAIL. */
8581
8582static int
a737bd4d 8583mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
404ff6b5 8584{
6c43fab6
RE
8585 int reg;
8586 char *start = *str;
404ff6b5 8587
6c43fab6 8588 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 8589 {
404ff6b5
AH
8590 if (shift >= 0)
8591 inst.instruction |= reg << shift;
8592
6c43fab6 8593 return reg;
404ff6b5
AH
8594 }
8595
6c43fab6 8596 /* Restore the start point. */
404ff6b5 8597 *str = start;
cc8a6dd0 8598
3631a3c8
NC
8599 /* Try generic coprocessor name if applicable. */
8600 if (regtype == REG_TYPE_MVF ||
8601 regtype == REG_TYPE_MVD ||
8602 regtype == REG_TYPE_MVFX ||
8603 regtype == REG_TYPE_MVDX)
8604 {
8605 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8606 {
8607 if (shift >= 0)
8608 inst.instruction |= reg << shift;
8609
8610 return reg;
8611 }
8612
8613 /* Restore the start point. */
8614 *str = start;
8615 }
8616
404ff6b5
AH
8617 /* In the few cases where we might be able to accept something else
8618 this error can be overridden. */
6c43fab6 8619 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 8620
404ff6b5
AH
8621 return FAIL;
8622}
8623
a737bd4d
NC
8624/* Cirrus Maverick Instructions. */
8625
8626/* Isnsn like "foo X,Y". */
8627
8628static void
8629do_mav_binops (char * str,
8630 int mode,
8631 enum arm_reg_type reg0,
8632 enum arm_reg_type reg1)
8633{
8634 int shift0, shift1;
8635
8636 shift0 = mode & 0xff;
8637 shift1 = (mode >> 8) & 0xff;
8638
8639 skip_whitespace (str);
8640
8641 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8642 || skip_past_comma (&str) == FAIL
8643 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8644 {
8645 if (!inst.error)
8646 inst.error = BAD_ARGS;
8647 }
8648 else
8649 end_of_line (str);
8650}
8651
8652/* Isnsn like "foo X,Y,Z". */
8653
8654static void
8655do_mav_triple (char * str,
8656 int mode,
8657 enum arm_reg_type reg0,
8658 enum arm_reg_type reg1,
8659 enum arm_reg_type reg2)
8660{
8661 int shift0, shift1, shift2;
8662
8663 shift0 = mode & 0xff;
8664 shift1 = (mode >> 8) & 0xff;
8665 shift2 = (mode >> 16) & 0xff;
8666
8667 skip_whitespace (str);
8668
8669 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8670 || skip_past_comma (&str) == FAIL
8671 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8672 || skip_past_comma (&str) == FAIL
8673 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8674 {
8675 if (!inst.error)
8676 inst.error = BAD_ARGS;
8677 }
8678 else
8679 end_of_line (str);
8680}
8681
8682/* Wrapper functions. */
8683
8684static void
8685do_mav_binops_1a (char * str)
8686{
8687 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8688}
8689
8690static void
8691do_mav_binops_1b (char * str)
8692{
8693 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8694}
8695
8696static void
8697do_mav_binops_1c (char * str)
8698{
8699 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8700}
8701
8702static void
8703do_mav_binops_1d (char * str)
8704{
8705 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8706}
8707
8708static void
8709do_mav_binops_1e (char * str)
8710{
8711 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8712}
8713
8714static void
8715do_mav_binops_1f (char * str)
8716{
8717 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8718}
8719
8720static void
8721do_mav_binops_1g (char * str)
8722{
8723 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8724}
8725
8726static void
8727do_mav_binops_1h (char * str)
8728{
8729 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8730}
8731
8732static void
8733do_mav_binops_1i (char * str)
8734{
8735 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8736}
8737
8738static void
8739do_mav_binops_1j (char * str)
8740{
8741 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8742}
8743
8744static void
8745do_mav_binops_1k (char * str)
8746{
8747 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8748}
8749
8750static void
8751do_mav_binops_1l (char * str)
8752{
8753 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8754}
8755
8756static void
8757do_mav_binops_1m (char * str)
8758{
8759 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8760}
8761
8762static void
8763do_mav_binops_1n (char * str)
8764{
8765 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8766}
8767
8768static void
8769do_mav_binops_1o (char * str)
8770{
8771 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8772}
8773
8774static void
8775do_mav_binops_2a (char * str)
8776{
8777 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8778}
8779
8780static void
8781do_mav_binops_2b (char * str)
8782{
8783 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8784}
404ff6b5 8785
a737bd4d
NC
8786static void
8787do_mav_binops_2c (char * str)
8788{
8789 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8790}
404ff6b5
AH
8791
8792static void
a737bd4d 8793do_mav_binops_3a (char * str)
6c43fab6 8794{
a737bd4d 8795 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
8796}
8797
8798static void
a737bd4d 8799do_mav_binops_3b (char * str)
6c43fab6 8800{
a737bd4d 8801 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
8802}
8803
8804static void
a737bd4d 8805do_mav_binops_3c (char * str)
404ff6b5 8806{
a737bd4d 8807 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
404ff6b5
AH
8808}
8809
8810static void
a737bd4d 8811do_mav_binops_3d (char * str)
404ff6b5 8812{
a737bd4d 8813 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
404ff6b5
AH
8814}
8815
8816static void
a737bd4d 8817do_mav_triple_4a (char * str)
404ff6b5 8818{
a737bd4d 8819 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
404ff6b5
AH
8820}
8821
8822static void
a737bd4d 8823do_mav_triple_4b (char * str)
404ff6b5 8824{
a737bd4d 8825 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
404ff6b5
AH
8826}
8827
8828static void
a737bd4d 8829do_mav_triple_5a (char * str)
404ff6b5 8830{
a737bd4d 8831 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
8832}
8833
8834static void
a737bd4d 8835do_mav_triple_5b (char * str)
404ff6b5 8836{
a737bd4d 8837 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
8838}
8839
6c43fab6 8840static void
a737bd4d 8841do_mav_triple_5c (char * str)
6c43fab6 8842{
a737bd4d 8843 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8844}
8845
8846static void
a737bd4d 8847do_mav_triple_5d (char * str)
6c43fab6 8848{
a737bd4d 8849 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8850}
8851
8852static void
a737bd4d 8853do_mav_triple_5e (char * str)
6c43fab6 8854{
a737bd4d 8855 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
8856}
8857
8858static void
a737bd4d 8859do_mav_triple_5f (char * str)
6c43fab6 8860{
a737bd4d 8861 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
8862}
8863
8864static void
a737bd4d 8865do_mav_triple_5g (char * str)
6c43fab6 8866{
a737bd4d 8867 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8868}
8869
8870static void
a737bd4d 8871do_mav_triple_5h (char * str)
6c43fab6 8872{
a737bd4d 8873 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8874}
8875
a737bd4d
NC
8876/* Isnsn like "foo W,X,Y,Z".
8877 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8878
6c43fab6 8879static void
a737bd4d
NC
8880do_mav_quad (char * str,
8881 int mode,
8882 enum arm_reg_type reg0,
8883 enum arm_reg_type reg1,
8884 enum arm_reg_type reg2,
8885 enum arm_reg_type reg3)
6c43fab6 8886{
a737bd4d
NC
8887 int shift0, shift1, shift2, shift3;
8888
8889 shift0= mode & 0xff;
8890 shift1 = (mode >> 8) & 0xff;
8891 shift2 = (mode >> 16) & 0xff;
8892 shift3 = (mode >> 24) & 0xff;
8893
8894 skip_whitespace (str);
8895
8896 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8897 || skip_past_comma (&str) == FAIL
8898 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8899 || skip_past_comma (&str) == FAIL
8900 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8901 || skip_past_comma (&str) == FAIL
8902 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8903 {
8904 if (!inst.error)
8905 inst.error = BAD_ARGS;
8906 }
8907 else
8908 end_of_line (str);
6c43fab6
RE
8909}
8910
8911static void
a737bd4d 8912do_mav_quad_6a (char * str)
6c43fab6 8913{
a737bd4d
NC
8914 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8915 REG_TYPE_MVFX);
6c43fab6
RE
8916}
8917
8918static void
a737bd4d 8919do_mav_quad_6b (char * str)
6c43fab6 8920{
a737bd4d
NC
8921 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8922 REG_TYPE_MVFX);
6c43fab6
RE
8923}
8924
a737bd4d 8925/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
6c43fab6 8926static void
a737bd4d 8927do_mav_dspsc_1 (char * str)
6c43fab6 8928{
a737bd4d
NC
8929 skip_whitespace (str);
8930
8931 /* cfmvsc32. */
8932 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8933 || skip_past_comma (&str) == FAIL
8934 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8935 {
8936 if (!inst.error)
8937 inst.error = BAD_ARGS;
8938
8939 return;
8940 }
8941
8942 end_of_line (str);
6c43fab6
RE
8943}
8944
a737bd4d 8945/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
6c43fab6 8946static void
a737bd4d 8947do_mav_dspsc_2 (char * str)
6c43fab6 8948{
a737bd4d
NC
8949 skip_whitespace (str);
8950
8951 /* cfmv32sc. */
8952 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8953 || skip_past_comma (&str) == FAIL
8954 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8955 {
8956 if (!inst.error)
8957 inst.error = BAD_ARGS;
8958
8959 return;
8960 }
8961
8962 end_of_line (str);
6c43fab6
RE
8963}
8964
a737bd4d
NC
8965/* Maverick shift immediate instructions.
8966 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8967 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8968
6c43fab6 8969static void
a737bd4d
NC
8970do_mav_shift (char * str,
8971 enum arm_reg_type reg0,
8972 enum arm_reg_type reg1)
6c43fab6 8973{
a737bd4d
NC
8974 int error;
8975 int imm, neg = 0;
8976
8977 skip_whitespace (str);
8978
8979 error = 0;
8980
8981 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8982 || skip_past_comma (&str) == FAIL
8983 || mav_reg_required_here (&str, 16, reg1) == FAIL
8984 || skip_past_comma (&str) == FAIL)
8985 {
8986 if (!inst.error)
8987 inst.error = BAD_ARGS;
8988 return;
8989 }
8990
8991 /* Calculate the immediate operand.
8992 The operand is a 7bit signed number. */
8993 skip_whitespace (str);
8994
8995 if (*str == '#')
8996 ++str;
8997
8998 if (!ISDIGIT (*str) && *str != '-')
8999 {
9000 inst.error = _("expecting immediate, 7bit operand");
9001 return;
9002 }
9003
9004 if (*str == '-')
9005 {
9006 neg = 1;
9007 ++str;
9008 }
9009
9010 for (imm = 0; *str && ISDIGIT (*str); ++str)
9011 imm = imm * 10 + *str - '0';
9012
9013 if (imm > 64)
9014 {
9015 inst.error = _("immediate out of range");
9016 return;
9017 }
9018
9019 /* Make negative imm's into 7bit signed numbers. */
9020 if (neg)
9021 {
9022 imm = -imm;
9023 imm &= 0x0000007f;
9024 }
9025
9026 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9027 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9028 Bit 4 should be 0. */
9029 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9030
9031 inst.instruction |= imm;
9032 end_of_line (str);
6c43fab6
RE
9033}
9034
9035static void
a737bd4d 9036do_mav_shift_1 (char * str)
6c43fab6 9037{
a737bd4d 9038 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9039}
9040
9041static void
a737bd4d 9042do_mav_shift_2 (char * str)
6c43fab6 9043{
a737bd4d
NC
9044 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9045}
9046
9047static int
9048mav_parse_offset (char ** str, int * negative)
9049{
9050 char * p = *str;
9051 int offset;
9052
9053 *negative = 0;
9054
9055 skip_whitespace (p);
9056
9057 if (*p == '#')
9058 ++p;
9059
9060 if (*p == '-')
9061 {
9062 *negative = 1;
9063 ++p;
9064 }
9065
9066 if (!ISDIGIT (*p))
9067 {
9068 inst.error = _("offset expected");
9069 return 0;
9070 }
9071
9072 for (offset = 0; *p && ISDIGIT (*p); ++p)
9073 offset = offset * 10 + *p - '0';
9074
9075 if (offset > 0x3fc)
9076 {
9077 inst.error = _("offset out of range");
9078 return 0;
9079 }
9080 if (offset & 0x3)
9081 {
9082 inst.error = _("offset not a multiple of 4");
9083 return 0;
9084 }
9085
9086 *str = p;
9087
9088 return *negative ? -offset : offset;
6c43fab6
RE
9089}
9090
a737bd4d
NC
9091/* Maverick load/store instructions.
9092 <insn><cond> CRd,[Rn,<offset>]{!}.
9093 <insn><cond> CRd,[Rn],<offset>. */
9094
9095static void
9096do_mav_ldst (char * str, enum arm_reg_type reg0)
9097{
9098 int offset, negative;
9099
9100 skip_whitespace (str);
9101
9102 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9103 || skip_past_comma (&str) == FAIL
9104 || *str++ != '['
9105 || reg_required_here (&str, 16) == FAIL)
9106 goto fail_ldst;
9107
9108 if (skip_past_comma (&str) == SUCCESS)
9109 {
9110 /* You are here: "<offset>]{!}". */
9111 inst.instruction |= PRE_INDEX;
9112
9113 offset = mav_parse_offset (&str, &negative);
9114
9115 if (inst.error)
9116 return;
9117
9118 if (*str++ != ']')
9119 {
9120 inst.error = _("missing ]");
9121 return;
9122 }
9123
9124 if (*str == '!')
9125 {
9126 inst.instruction |= WRITE_BACK;
9127 ++str;
9128 }
9129 }
9130 else
9131 {
9132 /* You are here: "], <offset>". */
9133 if (*str++ != ']')
9134 {
9135 inst.error = _("missing ]");
9136 return;
9137 }
9138
9139 if (skip_past_comma (&str) == FAIL
9140 || (offset = mav_parse_offset (&str, &negative), inst.error))
9141 goto fail_ldst;
6c43fab6 9142
a737bd4d
NC
9143 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9144 }
6c43fab6 9145
a737bd4d
NC
9146 if (negative)
9147 offset = -offset;
9148 else
9149 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
6c43fab6 9150
a737bd4d
NC
9151 inst.instruction |= offset >> 2;
9152 end_of_line (str);
9153 return;
6c43fab6 9154
a737bd4d
NC
9155fail_ldst:
9156 if (!inst.error)
9157 inst.error = BAD_ARGS;
6c43fab6
RE
9158}
9159
9160static void
a737bd4d 9161do_mav_ldst_1 (char * str)
6c43fab6 9162{
a737bd4d 9163 do_mav_ldst (str, REG_TYPE_MVF);
6c43fab6
RE
9164}
9165
9166static void
a737bd4d 9167do_mav_ldst_2 (char * str)
6c43fab6 9168{
a737bd4d 9169 do_mav_ldst (str, REG_TYPE_MVD);
6c43fab6
RE
9170}
9171
9172static void
a737bd4d 9173do_mav_ldst_3 (char * str)
6c43fab6 9174{
a737bd4d 9175 do_mav_ldst (str, REG_TYPE_MVFX);
6c43fab6
RE
9176}
9177
9178static void
a737bd4d 9179do_mav_ldst_4 (char * str)
6c43fab6 9180{
a737bd4d 9181 do_mav_ldst (str, REG_TYPE_MVDX);
6c43fab6
RE
9182}
9183
9184static void
a737bd4d 9185do_t_nop (char * str)
6c43fab6 9186{
a737bd4d
NC
9187 /* Do nothing. */
9188 end_of_line (str);
6c43fab6
RE
9189}
9190
a737bd4d
NC
9191/* Handle the Format 4 instructions that do not have equivalents in other
9192 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9193 BIC and MVN. */
6c43fab6
RE
9194
9195static void
a737bd4d 9196do_t_arit (char * str)
6c43fab6 9197{
a737bd4d 9198 int Rd, Rs, Rn;
6c43fab6 9199
6c43fab6
RE
9200 skip_whitespace (str);
9201
a737bd4d 9202 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6c43fab6 9203 || skip_past_comma (&str) == FAIL
a737bd4d 9204 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6c43fab6 9205 {
a737bd4d 9206 inst.error = BAD_ARGS;
6c43fab6
RE
9207 return;
9208 }
9209
a737bd4d 9210 if (skip_past_comma (&str) != FAIL)
6c43fab6 9211 {
a737bd4d
NC
9212 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9213 (It isn't allowed for CMP either, but that isn't handled by this
9214 function.) */
9215 if (inst.instruction == T_OPCODE_TST
9216 || inst.instruction == T_OPCODE_CMN
9217 || inst.instruction == T_OPCODE_NEG
9218 || inst.instruction == T_OPCODE_MVN)
9219 {
9220 inst.error = BAD_ARGS;
9221 return;
9222 }
6c43fab6 9223
a737bd4d
NC
9224 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9225 return;
9226
9227 if (Rs != Rd)
9228 {
9229 inst.error = _("dest and source1 must be the same register");
9230 return;
9231 }
9232 Rs = Rn;
6c43fab6
RE
9233 }
9234
a737bd4d
NC
9235 if (inst.instruction == T_OPCODE_MUL
9236 && Rs == Rd)
9237 as_tsktsk (_("Rs and Rd must be different in MUL"));
9238
9239 inst.instruction |= Rd | (Rs << 3);
6c43fab6 9240 end_of_line (str);
404ff6b5
AH
9241}
9242
9243static void
a737bd4d 9244do_t_add (char * str)
404ff6b5 9245{
a737bd4d 9246 thumb_add_sub (str, 0);
404ff6b5
AH
9247}
9248
9249static void
a737bd4d 9250do_t_asr (char * str)
404ff6b5 9251{
a737bd4d 9252 thumb_shift (str, THUMB_ASR);
404ff6b5
AH
9253}
9254
9255static void
a737bd4d 9256do_t_branch9 (char * str)
404ff6b5 9257{
a737bd4d
NC
9258 if (my_get_expression (&inst.reloc.exp, &str))
9259 return;
9260 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9261 inst.reloc.pc_rel = 1;
9262 end_of_line (str);
404ff6b5
AH
9263}
9264
9265static void
a737bd4d 9266do_t_branch12 (char * str)
404ff6b5 9267{
a737bd4d
NC
9268 if (my_get_expression (&inst.reloc.exp, &str))
9269 return;
9270 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9271 inst.reloc.pc_rel = 1;
9272 end_of_line (str);
404ff6b5
AH
9273}
9274
a737bd4d 9275/* Find the real, Thumb encoded start of a Thumb function. */
404ff6b5 9276
a737bd4d
NC
9277static symbolS *
9278find_real_start (symbolS * symbolP)
404ff6b5 9279{
a737bd4d
NC
9280 char * real_start;
9281 const char * name = S_GET_NAME (symbolP);
9282 symbolS * new_target;
404ff6b5 9283
a737bd4d
NC
9284 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9285#define STUB_NAME ".real_start_of"
404ff6b5 9286
a737bd4d
NC
9287 if (name == NULL)
9288 abort ();
404ff6b5 9289
a737bd4d
NC
9290 /* Names that start with '.' are local labels, not function entry points.
9291 The compiler may generate BL instructions to these labels because it
9292 needs to perform a branch to a far away location. */
9293 if (name[0] == '.')
9294 return symbolP;
404ff6b5 9295
a737bd4d
NC
9296 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9297 sprintf (real_start, "%s%s", STUB_NAME, name);
404ff6b5 9298
a737bd4d
NC
9299 new_target = symbol_find (real_start);
9300
9301 if (new_target == NULL)
404ff6b5 9302 {
a737bd4d
NC
9303 as_warn ("Failed to find real start of function: %s\n", name);
9304 new_target = symbolP;
404ff6b5 9305 }
404ff6b5 9306
a737bd4d
NC
9307 free (real_start);
9308
9309 return new_target;
9310}
404ff6b5
AH
9311
9312static void
a737bd4d 9313do_t_branch23 (char * str)
404ff6b5 9314{
a737bd4d
NC
9315 if (my_get_expression (& inst.reloc.exp, & str))
9316 return;
404ff6b5 9317
a737bd4d
NC
9318 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9319 inst.reloc.pc_rel = 1;
9320 end_of_line (str);
404ff6b5 9321
a737bd4d
NC
9322 /* If the destination of the branch is a defined symbol which does not have
9323 the THUMB_FUNC attribute, then we must be calling a function which has
9324 the (interfacearm) attribute. We look for the Thumb entry point to that
9325 function and change the branch to refer to that function instead. */
9326 if ( inst.reloc.exp.X_op == O_symbol
9327 && inst.reloc.exp.X_add_symbol != NULL
9328 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9329 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9330 inst.reloc.exp.X_add_symbol =
9331 find_real_start (inst.reloc.exp.X_add_symbol);
404ff6b5
AH
9332}
9333
404ff6b5 9334static void
a737bd4d 9335do_t_bx (char * str)
404ff6b5 9336{
a737bd4d 9337 int reg;
404ff6b5
AH
9338
9339 skip_whitespace (str);
9340
a737bd4d
NC
9341 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9342 return;
9343
9344 /* This sets THUMB_H2 from the top bit of reg. */
9345 inst.instruction |= reg << 3;
9346
9347 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9348 should cause the alignment to be checked once it is known. This is
9349 because BX PC only works if the instruction is word aligned. */
9350
9351 end_of_line (str);
404ff6b5
AH
9352}
9353
a737bd4d
NC
9354static void
9355do_t_compare (char * str)
9356{
9357 thumb_mov_compare (str, THUMB_COMPARE);
9358}
404ff6b5
AH
9359
9360static void
a737bd4d 9361do_t_ldmstm (char * str)
404ff6b5 9362{
a737bd4d
NC
9363 int Rb;
9364 long range;
404ff6b5
AH
9365
9366 skip_whitespace (str);
9367
a737bd4d
NC
9368 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9369 return;
404ff6b5 9370
a737bd4d
NC
9371 if (*str != '!')
9372 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9373 else
9374 str++;
9375
9376 if (skip_past_comma (&str) == FAIL
9377 || (range = reg_list (&str)) == FAIL)
404ff6b5 9378 {
a737bd4d 9379 if (! inst.error)
404ff6b5
AH
9380 inst.error = BAD_ARGS;
9381 return;
9382 }
9383
a737bd4d 9384 if (inst.reloc.type != BFD_RELOC_NONE)
404ff6b5 9385 {
a737bd4d
NC
9386 /* This really doesn't seem worth it. */
9387 inst.reloc.type = BFD_RELOC_NONE;
9388 inst.error = _("expression too complex");
404ff6b5
AH
9389 return;
9390 }
9391
a737bd4d 9392 if (range & ~0xff)
404ff6b5 9393 {
a737bd4d 9394 inst.error = _("only lo-regs valid in load/store multiple");
404ff6b5
AH
9395 return;
9396 }
9397
a737bd4d 9398 inst.instruction |= (Rb << 8) | range;
404ff6b5 9399 end_of_line (str);
404ff6b5
AH
9400}
9401
a737bd4d
NC
9402static void
9403do_t_ldr (char * str)
404ff6b5 9404{
a737bd4d
NC
9405 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9406}
404ff6b5 9407
a737bd4d
NC
9408static void
9409do_t_ldrb (char * str)
9410{
9411 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9412}
404ff6b5 9413
a737bd4d
NC
9414static void
9415do_t_ldrh (char * str)
9416{
9417 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9418}
404ff6b5 9419
a737bd4d
NC
9420static void
9421do_t_lds (char * str)
9422{
9423 int Rd, Rb, Ro;
404ff6b5 9424
a737bd4d 9425 skip_whitespace (str);
404ff6b5 9426
a737bd4d
NC
9427 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9428 || skip_past_comma (&str) == FAIL
9429 || *str++ != '['
9430 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9431 || skip_past_comma (&str) == FAIL
9432 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9433 || *str++ != ']')
404ff6b5 9434 {
a737bd4d
NC
9435 if (! inst.error)
9436 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9437 return;
404ff6b5
AH
9438 }
9439
a737bd4d
NC
9440 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9441 end_of_line (str);
9442}
404ff6b5 9443
a737bd4d
NC
9444static void
9445do_t_lsl (char * str)
9446{
9447 thumb_shift (str, THUMB_LSL);
9448}
404ff6b5 9449
a737bd4d
NC
9450static void
9451do_t_lsr (char * str)
9452{
9453 thumb_shift (str, THUMB_LSR);
404ff6b5
AH
9454}
9455
a737bd4d
NC
9456static void
9457do_t_mov (char * str)
9458{
9459 thumb_mov_compare (str, THUMB_MOVE);
9460}
404ff6b5
AH
9461
9462static void
a737bd4d 9463do_t_push_pop (char * str)
404ff6b5 9464{
a737bd4d 9465 long range;
404ff6b5
AH
9466
9467 skip_whitespace (str);
9468
a737bd4d 9469 if ((range = reg_list (&str)) == FAIL)
404ff6b5 9470 {
a737bd4d
NC
9471 if (! inst.error)
9472 inst.error = BAD_ARGS;
9473 return;
9474 }
404ff6b5 9475
a737bd4d
NC
9476 if (inst.reloc.type != BFD_RELOC_NONE)
9477 {
9478 /* This really doesn't seem worth it. */
9479 inst.reloc.type = BFD_RELOC_NONE;
9480 inst.error = _("expression too complex");
9481 return;
9482 }
404ff6b5 9483
a737bd4d
NC
9484 if (range & ~0xff)
9485 {
9486 if ((inst.instruction == T_OPCODE_PUSH
9487 && (range & ~0xff) == 1 << REG_LR)
9488 || (inst.instruction == T_OPCODE_POP
9489 && (range & ~0xff) == 1 << REG_PC))
404ff6b5 9490 {
a737bd4d
NC
9491 inst.instruction |= THUMB_PP_PC_LR;
9492 range &= 0xff;
404ff6b5 9493 }
a737bd4d 9494 else
404ff6b5 9495 {
a737bd4d 9496 inst.error = _("invalid register list to push/pop instruction");
404ff6b5
AH
9497 return;
9498 }
404ff6b5
AH
9499 }
9500
a737bd4d 9501 inst.instruction |= range;
404ff6b5 9502 end_of_line (str);
a737bd4d 9503}
404ff6b5 9504
a737bd4d
NC
9505static void
9506do_t_str (char * str)
9507{
9508 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
404ff6b5
AH
9509}
9510
b99bd4ef 9511static void
a737bd4d 9512do_t_strb (char * str)
b99bd4ef 9513{
a737bd4d 9514 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
b99bd4ef
NC
9515}
9516
a737bd4d
NC
9517static void
9518do_t_strh (char * str)
9519{
9520 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9521}
b99bd4ef
NC
9522
9523static void
a737bd4d 9524do_t_sub (char * str)
b99bd4ef 9525{
a737bd4d
NC
9526 thumb_add_sub (str, 1);
9527}
b99bd4ef 9528
a737bd4d
NC
9529static void
9530do_t_swi (char * str)
9531{
b99bd4ef
NC
9532 skip_whitespace (str);
9533
a737bd4d
NC
9534 if (my_get_expression (&inst.reloc.exp, &str))
9535 return;
b99bd4ef 9536
a737bd4d
NC
9537 inst.reloc.type = BFD_RELOC_ARM_SWI;
9538 end_of_line (str);
9539}
b99bd4ef 9540
a737bd4d
NC
9541static void
9542do_t_adr (char * str)
9543{
9544 int reg;
b99bd4ef 9545
a737bd4d
NC
9546 /* This is a pseudo-op of the form "adr rd, label" to be converted
9547 into a relative address of the form "add rd, pc, #label-.-4". */
9548 skip_whitespace (str);
9549
9550 /* Store Rd in temporary location inside instruction. */
9551 if ((reg = reg_required_here (&str, 4)) == FAIL
9552 || (reg > 7) /* For Thumb reg must be r0..r7. */
9553 || skip_past_comma (&str) == FAIL
9554 || my_get_expression (&inst.reloc.exp, &str))
9555 {
9556 if (!inst.error)
9557 inst.error = BAD_ARGS;
9558 return;
b99bd4ef
NC
9559 }
9560
a737bd4d
NC
9561 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9562 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9563 inst.reloc.pc_rel = 1;
9564 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
b99bd4ef 9565
b99bd4ef
NC
9566 end_of_line (str);
9567}
9568
9569static void
a737bd4d
NC
9570insert_reg (const struct reg_entry * r,
9571 struct hash_control * htab)
b99bd4ef 9572{
a737bd4d
NC
9573 int len = strlen (r->name) + 2;
9574 char * buf = xmalloc (len);
9575 char * buf2 = xmalloc (len);
9576 int i = 0;
b99bd4ef 9577
a737bd4d
NC
9578#ifdef REGISTER_PREFIX
9579 buf[i++] = REGISTER_PREFIX;
9580#endif
9581
9582 strcpy (buf + i, r->name);
9583
9584 for (i = 0; buf[i]; i++)
9585 buf2[i] = TOUPPER (buf[i]);
9586
9587 buf2[i] = '\0';
9588
9589 hash_insert (htab, buf, (PTR) r);
9590 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9591}
9592
9593static void
a737bd4d 9594build_reg_hsh (struct reg_map * map)
b99bd4ef 9595{
a737bd4d
NC
9596 const struct reg_entry *r;
9597
9598 if ((map->htab = hash_new ()) == NULL)
9599 as_fatal (_("virtual memory exhausted"));
9600
9601 for (r = map->names; r->name != NULL; r++)
9602 insert_reg (r, map->htab);
b99bd4ef
NC
9603}
9604
9605static void
a737bd4d
NC
9606insert_reg_alias (char * str,
9607 int regnum,
9608 struct hash_control *htab)
b99bd4ef 9609{
a737bd4d
NC
9610 const char * error;
9611 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9612 const char * name = xmalloc (strlen (str) + 1);
9613
9614 strcpy ((char *) name, str);
9615
9616 new->name = name;
9617 new->number = regnum;
9618 new->builtin = FALSE;
9619
9620 error = hash_insert (htab, name, (PTR) new);
9621 if (error)
9622 {
9623 as_bad (_("failed to create an alias for %s, reason: %s"),
9624 str, error);
9625 free ((char *) name);
9626 free (new);
9627 }
b99bd4ef
NC
9628}
9629
a737bd4d 9630/* Look for the .req directive. This is of the form:
b99bd4ef 9631
a737bd4d
NC
9632 new_register_name .req existing_register_name
9633
9634 If we find one, or if it looks sufficiently like one that we want to
9635 handle any error here, return non-zero. Otherwise return zero. */
9636
9637static int
9638create_register_alias (char * newname, char * p)
b99bd4ef 9639{
a737bd4d
NC
9640 char * q;
9641 char c;
b99bd4ef 9642
a737bd4d
NC
9643 q = p;
9644 skip_whitespace (q);
b99bd4ef 9645
a737bd4d
NC
9646 c = *p;
9647 *p = '\0';
b99bd4ef 9648
a737bd4d
NC
9649 if (*q && !strncmp (q, ".req ", 5))
9650 {
9651 char *copy_of_str;
9652 char *r;
b99bd4ef 9653
a737bd4d
NC
9654#ifndef IGNORE_OPCODE_CASE
9655 newname = original_case_string;
9656#endif
9657 copy_of_str = newname;
b99bd4ef 9658
a737bd4d
NC
9659 q += 4;
9660 skip_whitespace (q);
b99bd4ef 9661
a737bd4d
NC
9662 for (r = q; *r != '\0'; r++)
9663 if (*r == ' ')
9664 break;
b99bd4ef 9665
a737bd4d
NC
9666 if (r != q)
9667 {
9668 enum arm_reg_type new_type, old_type;
9669 int old_regno;
9670 char d = *r;
b99bd4ef 9671
a737bd4d
NC
9672 *r = '\0';
9673 old_type = arm_reg_parse_any (q);
9674 *r = d;
9675
9676 new_type = arm_reg_parse_any (newname);
9677
9678 if (new_type == REG_TYPE_MAX)
9679 {
9680 if (old_type != REG_TYPE_MAX)
9681 {
9682 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9683 insert_reg_alias (newname, old_regno,
9684 all_reg_maps[old_type].htab);
9685 }
9686 else
9687 as_warn (_("register '%s' does not exist\n"), q);
9688 }
9689 else if (old_type == REG_TYPE_MAX)
9690 {
9691 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9692 copy_of_str, q);
9693 }
9694 else
9695 {
9696 /* Do not warn about redefinitions to the same alias. */
9697 if (new_type != old_type
9698 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9699 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9700 as_warn (_("ignoring redefinition of register alias '%s'"),
9701 copy_of_str);
9702
9703 }
9704 }
9705 else
9706 as_warn (_("ignoring incomplete .req pseuso op"));
9707
9708 *p = c;
9709 return 1;
9710 }
9711
9712 *p = c;
9713 return 0;
b99bd4ef
NC
9714}
9715
9716static void
a737bd4d 9717set_constant_flonums (void)
b99bd4ef 9718{
a737bd4d 9719 int i;
b99bd4ef 9720
a737bd4d
NC
9721 for (i = 0; i < NUM_FLOAT_VALS; i++)
9722 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9723 abort ();
b99bd4ef
NC
9724}
9725
a737bd4d
NC
9726\f
9727static const struct asm_opcode insns[] =
b99bd4ef 9728{
a737bd4d
NC
9729 /* Core ARM Instructions. */
9730 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9731 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9732 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9733 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9734 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9735 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9736 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9737 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9738 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9739 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9740 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9741 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9742 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9743 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9744 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9745 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9746 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9747 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9748 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9749 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9750
9751 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9752 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9753 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9754 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9755 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9756 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9757 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9758 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9759 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9760 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9761 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9762 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9763
9764 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9765 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9766 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9767 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9768
9769 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9770 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9771 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9772 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9773 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9774 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9775 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9776 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9777
9778 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9779 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9780 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9781 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9782 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9783 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9784 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9785 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9786
9787 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9788 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9789 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9790 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9791 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9792 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9793 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9794 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
b99bd4ef 9795
a737bd4d
NC
9796 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9797#ifdef TE_WINCE
9798 /* XXX This is the wrong place to do this. Think multi-arch. */
9799 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9800 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9801#else
9802 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9803 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9804#endif
b99bd4ef 9805
a737bd4d
NC
9806 /* Pseudo ops. */
9807 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9808 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
0dd132b6 9809 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
b99bd4ef 9810
a737bd4d
NC
9811 /* ARM 2 multiplies. */
9812 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9813 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9814 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9815 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 9816
a737bd4d
NC
9817 /* Generic coprocessor instructions. */
9818 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9819 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9820 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9821 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9822 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9823 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9824 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
b99bd4ef 9825
a737bd4d
NC
9826 /* ARM 3 - swp instructions. */
9827 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9828 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 9829
a737bd4d
NC
9830 /* ARM 6 Status register instructions. */
9831 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9832 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9833 /* ScottB: our code uses 0xe128f000 for msr.
9834 NickC: but this is wrong because the bits 16 through 19 are
9835 handled by the PSR_xxx defines above. */
b99bd4ef 9836
a737bd4d
NC
9837 /* ARM 7M long multiplies. */
9838 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9839 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9840 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9841 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9842 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9843 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9844 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9845 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
b99bd4ef 9846
a737bd4d
NC
9847 /* ARM Architecture 4. */
9848 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9849 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9850 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9851 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 9852
a737bd4d
NC
9853 /* ARM Architecture 4T. */
9854 /* Note: bx (and blx) are required on V5, even if the processor does
9855 not support Thumb. */
9856 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
b99bd4ef 9857
a737bd4d
NC
9858 /* ARM Architecture 5T. */
9859 /* Note: blx has 2 variants, so the .value is set dynamically.
9860 Only one of the variants has conditional execution. */
9861 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9862 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9863 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9864 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9865 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9866 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9867 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9868 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9869 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9870 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
b99bd4ef 9871
a737bd4d
NC
9872 /* ARM Architecture 5TExP. */
9873 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9874 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9875 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9876 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 9877
a737bd4d
NC
9878 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9879 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 9880
a737bd4d
NC
9881 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9882 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9883 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9884 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
b99bd4ef 9885
a737bd4d
NC
9886 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9887 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9888 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9889 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 9890
a737bd4d
NC
9891 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9892 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 9893
a737bd4d
NC
9894 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9895 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9896 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9897 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
b99bd4ef 9898
a737bd4d
NC
9899 /* ARM Architecture 5TE. */
9900 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9901 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9902 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
b99bd4ef 9903
a737bd4d
NC
9904 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9905 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
b99bd4ef 9906
a737bd4d
NC
9907 /* ARM Architecture 5TEJ. */
9908 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
b99bd4ef 9909
a737bd4d
NC
9910 /* ARM V6. */
9911 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9912 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9913 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9914 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9915 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9916 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9917 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9918 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9919 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9920 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9921 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9922 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9923 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9924 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9925 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9926 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9927 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9928 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9929 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9930 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9931 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9932 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9933 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9934 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9935 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9936 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9937 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9938 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9939 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9940 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9941 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9942 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9943 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9944 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9945 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9946 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9947 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9948 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9949 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9950 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9951 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9952 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9953 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9954 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9955 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9956 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9957 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9958 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9959 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9960 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9961 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9962 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9963 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9964 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9965 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9966 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
9967 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
9968 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
9969 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
9970 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
9971 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
9972 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
9973 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
9974 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
9975 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
9976 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
9977 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
9978 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
9979 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
9980 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
9981 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
9982 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
9983 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
9984 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
9985 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
9986 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
9987 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
9988 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
9989 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
9990 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
9991 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
9992 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
9993 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
9994 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
9995 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
9996 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
9997 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
9998 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
9999 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10000 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10001 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10002 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10003 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10004 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10005 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10006 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10007 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10008 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10009 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
b99bd4ef 10010
0dd132b6
NC
10011 /* ARM V6K. */
10012 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10013 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10014 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10015 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10016 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10017 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10018 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10019 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10020 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10021 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10022 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
7ed4c4c5 10023
0dd132b6
NC
10024 /* ARM V6Z. */
10025 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10026
a737bd4d
NC
10027 /* Core FPA instruction set (V1). */
10028 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10029 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10030 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10031 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
b99bd4ef 10032
a737bd4d
NC
10033 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10034 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10035 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10036 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10037
a737bd4d
NC
10038 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10039 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10040 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10041 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10042
a737bd4d
NC
10043 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10044 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10045 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10046 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10047 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10048 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10049 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10050 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10051 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10052 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10053 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10054 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10055
a737bd4d
NC
10056 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10057 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10058 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10059 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10060 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10061 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10062 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10063 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10064 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10065 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10066 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10067 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10068
a737bd4d
NC
10069 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10070 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10071 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10072 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10073 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10074 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10075 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10076 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10077 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10078 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10079 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10080 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10081
a737bd4d
NC
10082 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10083 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10085 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10091 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10093 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10094
a737bd4d
NC
10095 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10096 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10098 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10104 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10106 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10107
a737bd4d
NC
10108 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10109 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10111 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10117 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10119 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10120
a737bd4d
NC
10121 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10122 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10124 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10130 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10132 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10133
a737bd4d
NC
10134 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10135 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10137 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10143 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10145 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10146
a737bd4d
NC
10147 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10148 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10150 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10156 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10158 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10159
a737bd4d
NC
10160 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10161 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10163 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10169 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10171 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10172
a737bd4d
NC
10173 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10174 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10176 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10182 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10184 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10185
a737bd4d
NC
10186 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10187 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10189 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10195 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10197 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10198
a737bd4d
NC
10199 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10200 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10202 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10208 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10210 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10211
a737bd4d
NC
10212 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10213 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10215 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10221 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10223 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10224
a737bd4d
NC
10225 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10226 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10228 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10234 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10236 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10237
a737bd4d
NC
10238 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10239 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10240 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10241 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10242 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10243 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10244 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10245 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10246 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10247 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10248 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10249 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10250
a737bd4d
NC
10251 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10252 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10253 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10254 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10255 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10256 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10257 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10258 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10259 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10260 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10261 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10262 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10263
a737bd4d
NC
10264 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10265 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10266 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10267 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10268 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10269 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10270 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10271 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10272 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10273 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10274 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10275 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10276
a737bd4d
NC
10277 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10278 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10279 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10280 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10281 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10282 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10283 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10284 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10285 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10286 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10287 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10288 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10289
a737bd4d
NC
10290 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10291 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10293 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10299 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10301 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10302
a737bd4d
NC
10303 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10304 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10306 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10312 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10314 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10315
a737bd4d
NC
10316 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10317 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10319 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10325 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10327 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10328
a737bd4d
NC
10329 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10330 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10332 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10338 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10340 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10341
a737bd4d
NC
10342 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10343 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10345 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10351 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10353 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10354
a737bd4d
NC
10355 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10356 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10358 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10364 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10366 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10367
a737bd4d
NC
10368 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10369 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10371 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10377 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10379 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10380
a737bd4d
NC
10381 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10382 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10384 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10390 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10392 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10393
a737bd4d
NC
10394 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10395 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10397 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10403 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10405 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10406
a737bd4d
NC
10407 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10408 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10409 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10410 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10411 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10412 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10413 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10414 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10415 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10416 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10417 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10418 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10419
a737bd4d
NC
10420 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10421 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10422 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10423 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10424 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10425 not be an optional suffix, but part of the instruction. To be
10426 compatible, we accept either. */
10427 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10428 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
b99bd4ef 10429
a737bd4d
NC
10430 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10431 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10432 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10433 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10434 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10435 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10436 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10437 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10438 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10439 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10440 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10441 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
6c43fab6 10442
a737bd4d
NC
10443 /* The implementation of the FIX instruction is broken on some
10444 assemblers, in that it accepts a precision specifier as well as a
10445 rounding specifier, despite the fact that this is meaningless.
10446 To be more compatible, we accept it as well, though of course it
10447 does not set any bits. */
10448 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10449 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10450 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10451 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10452 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10453 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10454 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10455 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10456 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10457 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10458 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10459 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10460 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
6c43fab6 10461
a737bd4d
NC
10462 /* Instructions that were new with the real FPA, call them V2. */
10463 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10464 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10465 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10466 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10467 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10468 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
6c43fab6 10469
a737bd4d
NC
10470 /* VFP V1xD (single precision). */
10471 /* Moves and type conversions. */
10472 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10473 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10474 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10475 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10476 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10477 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10478 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10479 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10480 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10481 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10482 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10483 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
6c43fab6 10484
a737bd4d
NC
10485 /* Memory operations. */
10486 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10487 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10488 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10489 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10490 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10491 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10492 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10493 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10494 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10495 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10496 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10497 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10498 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10499 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10500 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10501 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10502 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10503 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
6c43fab6 10504
a737bd4d
NC
10505 /* Monadic operations. */
10506 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10507 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10508 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
6c43fab6 10509
a737bd4d
NC
10510 /* Dyadic operations. */
10511 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10512 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10513 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10514 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10515 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10516 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10517 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10518 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10519 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
6c43fab6 10520
a737bd4d
NC
10521 /* Comparisons. */
10522 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10523 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10524 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10525 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
6c43fab6 10526
a737bd4d
NC
10527 /* VFP V1 (Double precision). */
10528 /* Moves and type conversions. */
10529 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10530 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10531 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10532 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10533 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10534 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10535 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10536 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10537 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10538 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10539 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10540 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10541 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
6c43fab6 10542
a737bd4d
NC
10543 /* Memory operations. */
10544 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10545 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10546 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10547 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10548 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10549 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10550 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10551 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10552 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10553 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
6c43fab6 10554
a737bd4d
NC
10555 /* Monadic operations. */
10556 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10557 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10558 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
6c43fab6 10559
a737bd4d
NC
10560 /* Dyadic operations. */
10561 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10562 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10563 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10564 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10565 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10566 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10567 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10568 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10569 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
6c43fab6 10570
a737bd4d
NC
10571 /* Comparisons. */
10572 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10573 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10574 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10575 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
6c43fab6 10576
a737bd4d
NC
10577 /* VFP V2. */
10578 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10579 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10580 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10581 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
6c43fab6 10582
a737bd4d
NC
10583 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10584 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10585 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10586 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10587 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10588 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10589 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10590 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10591 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
cc8a6dd0 10592
a737bd4d
NC
10593 /* Intel Wireless MMX technology instructions. */
10594 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10595 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10596 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10597 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10598 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10599 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10600 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10601 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10602 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10603 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10604 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10605 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10606 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10607 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10608 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10609 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10610 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10611 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10612 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10613 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10614 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10615 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10616 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10617 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10618 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10619 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10620 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10621 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10622 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10623 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10624 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10625 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10626 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10627 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10628 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10629 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10630 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10631 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10632 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10633 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10634 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10635 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10636 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10637 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10638 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10639 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10640 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10641 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10642 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10643 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10644 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10645 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10646 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10647 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10648 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10649 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10650 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10651 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10652 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10653 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10654 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10655 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10656 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10657 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10658 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10659 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10660 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10661 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10662 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10663 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10664 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10665 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10666 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10667 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10668 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10671 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10673 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10678 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10680 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10682 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10683 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10684 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10686 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10688 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10690 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10693 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10695 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10696 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10697 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10698 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10699 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10700 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10701 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10702 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10703 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10704 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10705 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10706 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10707 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10708 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10709 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10710 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10711 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10712 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10713 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10714 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10715 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10716 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10717 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10718 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10719 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10720 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10721 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10722 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10723 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10724 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10725 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10726 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10727 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10728 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10729 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10730 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10731 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10732 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10733 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10734 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10735 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10736 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10737 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10738 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10739 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10740 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10741 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10742 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10743 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10744 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10745 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10746 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10747 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10748 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10749 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10750 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10751 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10752 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10753 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10754 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10755 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
b99bd4ef 10756
a737bd4d
NC
10757 /* Cirrus Maverick instructions. */
10758 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10759 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10760 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10761 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10762 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10763 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10764 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10765 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10766 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10767 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10768 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10769 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10770 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10771 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10772 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10773 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10774 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10775 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10776 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10777 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10778 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10779 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10780 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10781 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10782 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10783 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10784 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10785 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10786 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10787 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10788 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10789 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10790 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10791 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10792 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10793 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10794 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10795 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10796 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10797 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10798 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10799 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10800 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10801 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10802 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10803 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10804 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10805 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10806 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10807 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10808 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10809 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10810 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10811 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10812 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10813 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10814 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10815 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10816 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10817 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10818 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10819 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10820 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10821 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10822 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10823 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10824 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10825 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10826 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10827 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10828 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10829 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10830 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10831 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10832 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10833 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10834};
b99bd4ef 10835
90e4755a 10836/* Iterate over the base tables to create the instruction patterns. */
a737bd4d 10837
90e4755a 10838static void
a737bd4d 10839build_arm_ops_hsh (void)
90e4755a
RE
10840{
10841 unsigned int i;
10842 unsigned int j;
10843 static struct obstack insn_obstack;
10844
10845 obstack_begin (&insn_obstack, 4000);
10846
10847 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10848 {
6c43fab6 10849 const struct asm_opcode *insn = insns + i;
90e4755a
RE
10850
10851 if (insn->cond_offset != 0)
10852 {
10853 /* Insn supports conditional execution. Build the varaints
10854 and insert them in the hash table. */
10855 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10856 {
10857 unsigned len = strlen (insn->template);
10858 struct asm_opcode *new;
10859 char *template;
10860
10861 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10862 /* All condition codes are two characters. */
10863 template = obstack_alloc (&insn_obstack, len + 3);
10864
10865 strncpy (template, insn->template, insn->cond_offset);
10866 strcpy (template + insn->cond_offset, conds[j].template);
10867 if (len > insn->cond_offset)
10868 strcpy (template + insn->cond_offset + 2,
10869 insn->template + insn->cond_offset);
10870 new->template = template;
10871 new->cond_offset = 0;
10872 new->variant = insn->variant;
10873 new->parms = insn->parms;
10874 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10875
10876 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10877 }
10878 }
10879 /* Finally, insert the unconditional insn in the table directly;
10880 no need to build a copy. */
10881 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10882 }
10883}
10884
0bbf2aa4 10885#if 0 /* Suppressed - for now. */
5a6c6817
NC
10886#if defined OBJ_ELF || defined OBJ_COFF
10887
10888#ifdef OBJ_ELF
10889#define arm_Note Elf_External_Note
10890#else
10891typedef struct
10892{
10893 unsigned char namesz[4]; /* Size of entry's owner string. */
10894 unsigned char descsz[4]; /* Size of the note descriptor. */
10895 unsigned char type[4]; /* Interpretation of the descriptor. */
10896 char name[1]; /* Start of the name+desc data. */
10897} arm_Note;
10898#endif
10899
10900/* The description is kept to a fix sized in order to make updating
10901 it and merging it easier. */
10902#define ARM_NOTE_DESCRIPTION_LENGTH 8
10903
10904static void
a737bd4d
NC
10905arm_add_note (const char * name,
10906 const char * description,
10907 unsigned int type)
5a6c6817
NC
10908{
10909 arm_Note note ATTRIBUTE_UNUSED;
10910 char * p;
10911 unsigned int name_len;
10912
10913 name_len = (strlen (name) + 1 + 3) & ~3;
a737bd4d 10914
5a6c6817
NC
10915 p = frag_more (sizeof (note.namesz));
10916 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10917
10918 p = frag_more (sizeof (note.descsz));
10919 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10920
10921 p = frag_more (sizeof (note.type));
10922 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10923
10924 p = frag_more (name_len);
10925 strcpy (p, name);
10926
a737bd4d
NC
10927 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10928 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10929 frag_align (2, 0, 0);
10930}
10931#endif
10932#endif
10933
10934\f
10935static const struct thumb_opcode tinsns[] =
10936{
10937 /* Thumb v1 (ARMv4T). */
10938 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10939 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10940 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10941 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10942 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10943 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10944 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10945 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10946 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10947 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10948 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10949 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10950 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10951 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10952 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10953 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10954 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10955 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10956 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10957 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10958 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10959 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10960 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10961 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10962 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
10963 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
10964 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
10965 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
10966 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
10967 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
10968 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
10969 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
10970 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
10971 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10972 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10973 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10974 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10975 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
10976 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
10977 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
10978 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
10979 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
10980 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
10981 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
10982 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
10983 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
10984 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
10985 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
10986 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
10987 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
10988 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
10989 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
10990 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
10991 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
10992 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
10993 /* Pseudo ops: */
10994 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
10995 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
10996 /* Thumb v2 (ARMv5T). */
10997 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
10998 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
10999
11000 /* ARM V6. */
11001 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11002 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11003 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11004 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11005 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11006 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11007 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11008 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11009 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11010 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11011 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11012};
5a6c6817 11013
b99bd4ef 11014void
a737bd4d 11015md_begin (void)
b99bd4ef
NC
11016{
11017 unsigned mach;
11018 unsigned int i;
11019
11020 if ( (arm_ops_hsh = hash_new ()) == NULL
11021 || (arm_tops_hsh = hash_new ()) == NULL
11022 || (arm_cond_hsh = hash_new ()) == NULL
11023 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11024 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11025 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11026
90e4755a 11027 build_arm_ops_hsh ();
b99bd4ef
NC
11028 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11029 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11030 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11031 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11032 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11033 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11034 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11035 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11036
6c43fab6
RE
11037 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11038 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11039
11040 set_constant_flonums ();
11041
03b1477f
RE
11042 /* Set the cpu variant based on the command-line options. We prefer
11043 -mcpu= over -march= if both are set (as for GCC); and we prefer
11044 -mfpu= over any other way of setting the floating point unit.
11045 Use of legacy options with new options are faulted. */
11046 if (legacy_cpu != -1)
11047 {
11048 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11049 as_bad (_("use of old and new-style options to set CPU type"));
11050
11051 mcpu_cpu_opt = legacy_cpu;
11052 }
11053 else if (mcpu_cpu_opt == -1)
11054 mcpu_cpu_opt = march_cpu_opt;
11055
11056 if (legacy_fpu != -1)
11057 {
11058 if (mfpu_opt != -1)
11059 as_bad (_("use of old and new-style options to set FPU type"));
11060
11061 mfpu_opt = legacy_fpu;
11062 }
11063 else if (mfpu_opt == -1)
11064 {
39c2da32
RE
11065#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11066 /* Some environments specify a default FPU. If they don't, infer it
11067 from the processor. */
03b1477f
RE
11068 if (mcpu_fpu_opt != -1)
11069 mfpu_opt = mcpu_fpu_opt;
11070 else
11071 mfpu_opt = march_fpu_opt;
39c2da32
RE
11072#else
11073 mfpu_opt = FPU_DEFAULT;
11074#endif
03b1477f
RE
11075 }
11076
11077 if (mfpu_opt == -1)
11078 {
11079 if (mcpu_cpu_opt == -1)
11080 mfpu_opt = FPU_DEFAULT;
11081 else if (mcpu_cpu_opt & ARM_EXT_V5)
11082 mfpu_opt = FPU_ARCH_VFP_V2;
11083 else
11084 mfpu_opt = FPU_ARCH_FPA;
11085 }
11086
11087 if (mcpu_cpu_opt == -1)
11088 mcpu_cpu_opt = CPU_DEFAULT;
11089
11090 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11091
b99bd4ef 11092 {
7cc69913
NC
11093 unsigned int flags = 0;
11094
11095#if defined OBJ_ELF
11096 flags = meabi_flags;
d507cf36
PB
11097
11098 switch (meabi_flags)
33a392fb 11099 {
d507cf36 11100 case EF_ARM_EABI_UNKNOWN:
7cc69913
NC
11101#endif
11102#if defined OBJ_COFF || defined OBJ_ELF
d507cf36
PB
11103 /* Set the flags in the private structure. */
11104 if (uses_apcs_26) flags |= F_APCS26;
11105 if (support_interwork) flags |= F_INTERWORK;
11106 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11107 if (pic_code) flags |= F_PIC;
11108 if ((cpu_variant & FPU_ANY) == FPU_NONE
11109 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11110 flags |= F_SOFT_FLOAT;
11111
d507cf36
PB
11112 switch (mfloat_abi_opt)
11113 {
11114 case ARM_FLOAT_ABI_SOFT:
11115 case ARM_FLOAT_ABI_SOFTFP:
11116 flags |= F_SOFT_FLOAT;
11117 break;
33a392fb 11118
d507cf36
PB
11119 case ARM_FLOAT_ABI_HARD:
11120 if (flags & F_SOFT_FLOAT)
11121 as_bad (_("hard-float conflicts with specified fpu"));
11122 break;
11123 }
03b1477f 11124
7cc69913
NC
11125 /* Using VFP conventions (even if soft-float). */
11126 if (cpu_variant & FPU_VFP_EXT_NONE)
11127 flags |= F_VFP_FLOAT;
11128#endif
fde78edd 11129#if defined OBJ_ELF
d507cf36
PB
11130 if (cpu_variant & FPU_ARCH_MAVERICK)
11131 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11132 break;
11133
8cb51566 11134 case EF_ARM_EABI_VER4:
d507cf36
PB
11135 /* No additional flags to set. */
11136 break;
11137
11138 default:
11139 abort ();
11140 }
7cc69913
NC
11141#endif
11142#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef
NC
11143 bfd_set_private_flags (stdoutput, flags);
11144
11145 /* We have run out flags in the COFF header to encode the
11146 status of ATPCS support, so instead we create a dummy,
11147 empty, debug section called .arm.atpcs. */
11148 if (atpcs)
11149 {
11150 asection * sec;
11151
11152 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11153
11154 if (sec != NULL)
11155 {
11156 bfd_set_section_flags
11157 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11158 bfd_set_section_size (stdoutput, sec, 0);
11159 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11160 }
11161 }
b99bd4ef 11162#endif
7cc69913 11163 }
b99bd4ef
NC
11164
11165 /* Record the CPU type as well. */
11166 switch (cpu_variant & ARM_CPU_MASK)
11167 {
11168 case ARM_2:
11169 mach = bfd_mach_arm_2;
11170 break;
11171
11172 case ARM_3: /* Also ARM_250. */
11173 mach = bfd_mach_arm_2a;
11174 break;
11175
b89dddec
RE
11176 case ARM_6: /* Also ARM_7. */
11177 mach = bfd_mach_arm_3;
11178 break;
11179
b99bd4ef 11180 default:
5a6c6817 11181 mach = bfd_mach_arm_unknown;
b99bd4ef 11182 break;
b99bd4ef
NC
11183 }
11184
11185 /* Catch special cases. */
e16bb312
NC
11186 if (cpu_variant & ARM_CEXT_IWMMXT)
11187 mach = bfd_mach_arm_iWMMXt;
11188 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11189 mach = bfd_mach_arm_XScale;
fde78edd
NC
11190 else if (cpu_variant & ARM_CEXT_MAVERICK)
11191 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11192 else if (cpu_variant & ARM_EXT_V5E)
11193 mach = bfd_mach_arm_5TE;
11194 else if (cpu_variant & ARM_EXT_V5)
11195 {
b89dddec 11196 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11197 mach = bfd_mach_arm_5T;
11198 else
11199 mach = bfd_mach_arm_5;
11200 }
b89dddec 11201 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11202 {
b89dddec 11203 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11204 mach = bfd_mach_arm_4T;
11205 else
11206 mach = bfd_mach_arm_4;
11207 }
b89dddec 11208 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11209 mach = bfd_mach_arm_3M;
11210
5a6c6817 11211#if 0 /* Suppressed - for now. */
e16bb312 11212#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11213
11214 /* Create a .note section to fully identify this arm binary. */
11215
11216#define NOTE_ARCH_STRING "arch: "
11217
11218#if defined OBJ_COFF && ! defined NT_VERSION
11219#define NT_VERSION 1
11220#define NT_ARCH 2
11221#endif
a737bd4d 11222
e16bb312 11223 {
e16bb312
NC
11224 segT current_seg = now_seg;
11225 subsegT current_subseg = now_subseg;
11226 asection * arm_arch;
5a6c6817
NC
11227 const char * arch_string;
11228
e16bb312
NC
11229 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11230
11231#ifdef OBJ_COFF
11232 bfd_set_section_flags (stdoutput, arm_arch,
11233 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11234 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11235#else
11236 bfd_set_section_flags (stdoutput, arm_arch,
11237 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11238#endif
11239 arm_arch->output_section = arm_arch;
11240 subseg_set (arm_arch, 0);
e16bb312 11241
5a6c6817
NC
11242 switch (mach)
11243 {
11244 default:
11245 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11246 case bfd_mach_arm_2: arch_string = "armv2"; break;
11247 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11248 case bfd_mach_arm_3: arch_string = "armv3"; break;
11249 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11250 case bfd_mach_arm_4: arch_string = "armv4"; break;
11251 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11252 case bfd_mach_arm_5: arch_string = "armv5"; break;
11253 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11254 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11255 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11256 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
a737bd4d 11257 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
5a6c6817
NC
11258 }
11259
11260 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11261
11262 subseg_set (current_seg, current_subseg);
11263 }
11264#endif
5a6c6817 11265#endif /* Suppressed code. */
a737bd4d 11266
b99bd4ef
NC
11267 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11268}
11269
11270/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11271 for use in the a.out file, and stores them in the array pointed to by buf.
11272 This knows about the endian-ness of the target machine and does
11273 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11274 2 (short) and 4 (long) Floating numbers are put out as a series of
11275 LITTLENUMS (shorts, here at least). */
11276
11277void
a737bd4d 11278md_number_to_chars (char * buf, valueT val, int n)
b99bd4ef
NC
11279{
11280 if (target_big_endian)
11281 number_to_chars_bigendian (buf, val, n);
11282 else
11283 number_to_chars_littleendian (buf, val, n);
11284}
11285
11286static valueT
a737bd4d 11287md_chars_to_number (char * buf, int n)
b99bd4ef
NC
11288{
11289 valueT result = 0;
11290 unsigned char * where = (unsigned char *) buf;
11291
11292 if (target_big_endian)
11293 {
11294 while (n--)
11295 {
11296 result <<= 8;
11297 result |= (*where++ & 255);
11298 }
11299 }
11300 else
11301 {
11302 while (n--)
11303 {
11304 result <<= 8;
11305 result |= (where[n] & 255);
11306 }
11307 }
11308
11309 return result;
11310}
11311
11312/* Turn a string in input_line_pointer into a floating point constant
11313 of type TYPE, and store the appropriate bytes in *LITP. The number
11314 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11315 returned, or NULL on OK.
11316
11317 Note that fp constants aren't represent in the normal way on the ARM.
11318 In big endian mode, things are as expected. However, in little endian
11319 mode fp constants are big-endian word-wise, and little-endian byte-wise
11320 within the words. For example, (double) 1.1 in big endian mode is
11321 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11322 the byte sequence 99 99 f1 3f 9a 99 99 99.
11323
11324 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11325
11326char *
a737bd4d 11327md_atof (int type, char * litP, int * sizeP)
b99bd4ef
NC
11328{
11329 int prec;
11330 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11331 char *t;
11332 int i;
11333
11334 switch (type)
11335 {
11336 case 'f':
11337 case 'F':
11338 case 's':
11339 case 'S':
11340 prec = 2;
11341 break;
11342
11343 case 'd':
11344 case 'D':
11345 case 'r':
11346 case 'R':
11347 prec = 4;
11348 break;
11349
11350 case 'x':
11351 case 'X':
11352 prec = 6;
11353 break;
11354
11355 case 'p':
11356 case 'P':
11357 prec = 6;
11358 break;
11359
11360 default:
11361 *sizeP = 0;
f03698e6 11362 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11363 }
11364
11365 t = atof_ieee (input_line_pointer, type, words);
11366 if (t)
11367 input_line_pointer = t;
11368 *sizeP = prec * 2;
11369
11370 if (target_big_endian)
11371 {
11372 for (i = 0; i < prec; i++)
11373 {
11374 md_number_to_chars (litP, (valueT) words[i], 2);
11375 litP += 2;
11376 }
11377 }
11378 else
11379 {
bfae80f2
RE
11380 if (cpu_variant & FPU_ARCH_VFP)
11381 for (i = prec - 1; i >= 0; i--)
11382 {
11383 md_number_to_chars (litP, (valueT) words[i], 2);
11384 litP += 2;
11385 }
11386 else
11387 /* For a 4 byte float the order of elements in `words' is 1 0.
11388 For an 8 byte float the order is 1 0 3 2. */
11389 for (i = 0; i < prec; i += 2)
11390 {
11391 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11392 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11393 litP += 4;
11394 }
b99bd4ef
NC
11395 }
11396
11397 return 0;
11398}
11399
11400/* The knowledge of the PC's pipeline offset is built into the insns
11401 themselves. */
11402
11403long
a737bd4d 11404md_pcrel_from (fixS * fixP)
b99bd4ef
NC
11405{
11406 if (fixP->fx_addsy
11407 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11408 && fixP->fx_subsy == NULL)
11409 return 0;
11410
11411 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11412 {
11413 /* PC relative addressing on the Thumb is slightly odd
11414 as the bottom two bits of the PC are forced to zero
11415 for the calculation. */
11416 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11417 }
11418
11419#ifdef TE_WINCE
2d2255b5
KH
11420 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11421 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11422 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11423#else
11424 return fixP->fx_where + fixP->fx_frag->fr_address;
11425#endif
11426}
11427
11428/* Round up a section size to the appropriate boundary. */
11429
11430valueT
a737bd4d
NC
11431md_section_align (segT segment ATTRIBUTE_UNUSED,
11432 valueT size)
b99bd4ef
NC
11433{
11434#ifdef OBJ_ELF
11435 return size;
11436#else
11437 /* Round all sects to multiple of 4. */
11438 return (size + 3) & ~3;
11439#endif
11440}
11441
11442/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11443 Otherwise we have no need to default values of symbols. */
11444
11445symbolS *
a737bd4d 11446md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
b99bd4ef
NC
11447{
11448#ifdef OBJ_ELF
11449 if (name[0] == '_' && name[1] == 'G'
11450 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11451 {
11452 if (!GOT_symbol)
11453 {
11454 if (symbol_find (name))
11455 as_bad ("GOT already in the symbol table");
11456
11457 GOT_symbol = symbol_new (name, undefined_section,
11458 (valueT) 0, & zero_address_frag);
11459 }
11460
11461 return GOT_symbol;
11462 }
11463#endif
11464
11465 return 0;
11466}
11467
94f592af 11468void
a737bd4d
NC
11469md_apply_fix3 (fixS * fixP,
11470 valueT * valP,
11471 segT seg)
b99bd4ef 11472{
94f592af 11473 offsetT value = * valP;
b99bd4ef
NC
11474 offsetT newval;
11475 unsigned int newimm;
11476 unsigned long temp;
11477 int sign;
11478 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11479 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11480
11481 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
11482
11483 /* Note whether this will delete the relocation. */
11484#if 0
11485 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11486 doesn't work fully.) */
11487 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
11488 && !fixP->fx_pcrel)
11489#else
11490 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11491#endif
11492 fixP->fx_done = 1;
11493
11494 /* If this symbol is in a different section then we need to leave it for
11495 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11496 so we have to undo it's effects here. */
11497 if (fixP->fx_pcrel)
11498 {
11499 if (fixP->fx_addsy != NULL
11500 && S_IS_DEFINED (fixP->fx_addsy)
11501 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
11502 {
11503 if (target_oabi
11504 && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
11505 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
11506 ))
11507 value = 0;
11508 else
11509 value += md_pcrel_from (fixP);
11510 }
11511 }
11512
11513 /* Remember value for emit_reloc. */
11514 fixP->fx_addnumber = value;
11515
11516 switch (fixP->fx_r_type)
11517 {
11518 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
11519 /* We claim that this fixup has been processed here,
11520 even if in fact we generate an error because we do
11521 not have a reloc for it, so tc_gen_reloc will reject it. */
11522 fixP->fx_done = 1;
11523
11524 if (fixP->fx_addsy
11525 && ! S_IS_DEFINED (fixP->fx_addsy))
11526 {
11527 as_bad_where (fixP->fx_file, fixP->fx_line,
11528 _("undefined symbol %s used as an immediate value"),
11529 S_GET_NAME (fixP->fx_addsy));
11530 break;
11531 }
11532
b99bd4ef
NC
11533 newimm = validate_immediate (value);
11534 temp = md_chars_to_number (buf, INSN_SIZE);
11535
11536 /* If the instruction will fail, see if we can fix things up by
11537 changing the opcode. */
11538 if (newimm == (unsigned int) FAIL
11539 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11540 {
11541 as_bad_where (fixP->fx_file, fixP->fx_line,
11542 _("invalid constant (%lx) after fixup"),
11543 (unsigned long) value);
11544 break;
11545 }
11546
11547 newimm |= (temp & 0xfffff000);
11548 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11549 break;
11550
11551 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11552 {
11553 unsigned int highpart = 0;
11554 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 11555
b99bd4ef
NC
11556 newimm = validate_immediate (value);
11557 temp = md_chars_to_number (buf, INSN_SIZE);
11558
11559 /* If the instruction will fail, see if we can fix things up by
11560 changing the opcode. */
11561 if (newimm == (unsigned int) FAIL
11562 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11563 {
11564 /* No ? OK - try using two ADD instructions to generate
11565 the value. */
11566 newimm = validate_immediate_twopart (value, & highpart);
11567
11568 /* Yes - then make sure that the second instruction is
11569 also an add. */
11570 if (newimm != (unsigned int) FAIL)
11571 newinsn = temp;
11572 /* Still No ? Try using a negated value. */
11573 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11574 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11575 /* Otherwise - give up. */
11576 else
11577 {
11578 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11579 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 11580 (long) value);
b99bd4ef
NC
11581 break;
11582 }
11583
11584 /* Replace the first operand in the 2nd instruction (which
11585 is the PC) with the destination register. We have
11586 already added in the PC in the first instruction and we
11587 do not want to do it again. */
11588 newinsn &= ~ 0xf0000;
11589 newinsn |= ((newinsn & 0x0f000) << 4);
11590 }
11591
11592 newimm |= (temp & 0xfffff000);
11593 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11594
11595 highpart |= (newinsn & 0xfffff000);
11596 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11597 }
11598 break;
11599
11600 case BFD_RELOC_ARM_OFFSET_IMM:
11601 sign = value >= 0;
11602
11603 if (value < 0)
11604 value = - value;
11605
11606 if (validate_offset_imm (value, 0) == FAIL)
11607 {
11608 as_bad_where (fixP->fx_file, fixP->fx_line,
11609 _("bad immediate value for offset (%ld)"),
11610 (long) value);
11611 break;
11612 }
11613
11614 newval = md_chars_to_number (buf, INSN_SIZE);
11615 newval &= 0xff7ff000;
11616 newval |= value | (sign ? INDEX_UP : 0);
11617 md_number_to_chars (buf, newval, INSN_SIZE);
11618 break;
11619
11620 case BFD_RELOC_ARM_OFFSET_IMM8:
11621 case BFD_RELOC_ARM_HWLITERAL:
11622 sign = value >= 0;
11623
11624 if (value < 0)
11625 value = - value;
11626
11627 if (validate_offset_imm (value, 1) == FAIL)
11628 {
11629 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11630 as_bad_where (fixP->fx_file, fixP->fx_line,
11631 _("invalid literal constant: pool needs to be closer"));
11632 else
11633 as_bad (_("bad immediate value for half-word offset (%ld)"),
11634 (long) value);
11635 break;
11636 }
11637
11638 newval = md_chars_to_number (buf, INSN_SIZE);
11639 newval &= 0xff7ff0f0;
11640 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11641 md_number_to_chars (buf, newval, INSN_SIZE);
11642 break;
11643
11644 case BFD_RELOC_ARM_LITERAL:
11645 sign = value >= 0;
11646
11647 if (value < 0)
11648 value = - value;
11649
11650 if (validate_offset_imm (value, 0) == FAIL)
11651 {
11652 as_bad_where (fixP->fx_file, fixP->fx_line,
11653 _("invalid literal constant: pool needs to be closer"));
11654 break;
11655 }
11656
11657 newval = md_chars_to_number (buf, INSN_SIZE);
11658 newval &= 0xff7ff000;
11659 newval |= value | (sign ? INDEX_UP : 0);
11660 md_number_to_chars (buf, newval, INSN_SIZE);
11661 break;
11662
11663 case BFD_RELOC_ARM_SHIFT_IMM:
11664 newval = md_chars_to_number (buf, INSN_SIZE);
11665 if (((unsigned long) value) > 32
11666 || (value == 32
11667 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11668 {
11669 as_bad_where (fixP->fx_file, fixP->fx_line,
11670 _("shift expression is too large"));
11671 break;
11672 }
11673
11674 if (value == 0)
11675 /* Shifts of zero must be done as lsl. */
11676 newval &= ~0x60;
11677 else if (value == 32)
11678 value = 0;
11679 newval &= 0xfffff07f;
11680 newval |= (value & 0x1f) << 7;
11681 md_number_to_chars (buf, newval, INSN_SIZE);
11682 break;
11683
0dd132b6
NC
11684 case BFD_RELOC_ARM_SMI:
11685 if (((unsigned long) value) > 0xffff)
11686 as_bad_where (fixP->fx_file, fixP->fx_line,
11687 _("invalid smi expression"));
11688 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11689 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11690 md_number_to_chars (buf, newval, INSN_SIZE);
11691 break;
11692
b99bd4ef
NC
11693 case BFD_RELOC_ARM_SWI:
11694 if (arm_data->thumb_mode)
11695 {
11696 if (((unsigned long) value) > 0xff)
11697 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11698 _("invalid swi expression"));
b99bd4ef
NC
11699 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11700 newval |= value;
11701 md_number_to_chars (buf, newval, THUMB_SIZE);
11702 }
11703 else
11704 {
11705 if (((unsigned long) value) > 0x00ffffff)
11706 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11707 _("invalid swi expression"));
b99bd4ef
NC
11708 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11709 newval |= value;
11710 md_number_to_chars (buf, newval, INSN_SIZE);
11711 }
11712 break;
11713
11714 case BFD_RELOC_ARM_MULTI:
11715 if (((unsigned long) value) > 0xffff)
11716 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11717 _("invalid expression in load/store multiple"));
b99bd4ef
NC
11718 newval = value | md_chars_to_number (buf, INSN_SIZE);
11719 md_number_to_chars (buf, newval, INSN_SIZE);
11720 break;
11721
11722 case BFD_RELOC_ARM_PCREL_BRANCH:
11723 newval = md_chars_to_number (buf, INSN_SIZE);
11724
11725 /* Sign-extend a 24-bit number. */
11726#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11727
11728#ifdef OBJ_ELF
11729 if (! target_oabi)
11730 value = fixP->fx_offset;
11731#endif
11732
11733 /* We are going to store value (shifted right by two) in the
11734 instruction, in a 24 bit, signed field. Thus we need to check
11735 that none of the top 8 bits of the shifted value (top 7 bits of
11736 the unshifted, unsigned value) are set, or that they are all set. */
11737 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11738 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11739 {
11740#ifdef OBJ_ELF
11741 /* Normally we would be stuck at this point, since we cannot store
11742 the absolute address that is the destination of the branch in the
11743 24 bits of the branch instruction. If however, we happen to know
11744 that the destination of the branch is in the same section as the
2d2255b5 11745 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
11746 ourselves and not have to bother the linker with it.
11747
11748 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
11749 because I have not worked out how to do this for OBJ_COFF or
11750 target_oabi. */
11751 if (! target_oabi
11752 && fixP->fx_addsy != NULL
11753 && S_IS_DEFINED (fixP->fx_addsy)
11754 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11755 {
11756 /* Get pc relative value to go into the branch. */
94f592af 11757 value = * valP;
b99bd4ef
NC
11758
11759 /* Permit a backward branch provided that enough bits
11760 are set. Allow a forwards branch, provided that
11761 enough bits are clear. */
11762 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11763 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11764 fixP->fx_done = 1;
11765 }
11766
11767 if (! fixP->fx_done)
11768#endif
11769 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11770 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
11771 }
11772
11773 value >>= 2;
11774 value += SEXT24 (newval);
11775
11776 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11777 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11778 as_bad_where (fixP->fx_file, fixP->fx_line,
11779 _("out of range branch"));
11780
11781 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11782 md_number_to_chars (buf, newval, INSN_SIZE);
11783 break;
11784
11785 case BFD_RELOC_ARM_PCREL_BLX:
11786 {
11787 offsetT hbit;
11788 newval = md_chars_to_number (buf, INSN_SIZE);
11789
11790#ifdef OBJ_ELF
11791 if (! target_oabi)
11792 value = fixP->fx_offset;
11793#endif
11794 hbit = (value >> 1) & 1;
11795 value = (value >> 2) & 0x00ffffff;
11796 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11797 newval = value | (newval & 0xfe000000) | (hbit << 24);
11798 md_number_to_chars (buf, newval, INSN_SIZE);
11799 }
11800 break;
11801
11802 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11803 newval = md_chars_to_number (buf, THUMB_SIZE);
11804 {
11805 addressT diff = (newval & 0xff) << 1;
11806 if (diff & 0x100)
11807 diff |= ~0xff;
11808
11809 value += diff;
11810 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11811 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11812 _("branch out of range"));
b99bd4ef
NC
11813 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11814 }
11815 md_number_to_chars (buf, newval, THUMB_SIZE);
11816 break;
11817
11818 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11819 newval = md_chars_to_number (buf, THUMB_SIZE);
11820 {
11821 addressT diff = (newval & 0x7ff) << 1;
11822 if (diff & 0x800)
11823 diff |= ~0x7ff;
11824
11825 value += diff;
11826 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11827 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11828 _("branch out of range"));
b99bd4ef
NC
11829 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11830 }
11831 md_number_to_chars (buf, newval, THUMB_SIZE);
11832 break;
11833
11834 case BFD_RELOC_THUMB_PCREL_BLX:
11835 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11836 {
11837 offsetT newval2;
11838 addressT diff;
11839
11840 newval = md_chars_to_number (buf, THUMB_SIZE);
11841 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11842 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11843 if (diff & 0x400000)
11844 diff |= ~0x3fffff;
11845#ifdef OBJ_ELF
11846 value = fixP->fx_offset;
11847#endif
11848 value += diff;
c62e1cc3 11849
b99bd4ef
NC
11850 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11851 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11852 _("branch with link out of range"));
b99bd4ef
NC
11853
11854 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11855 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11856 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
11857 /* For a BLX instruction, make sure that the relocation is rounded up
11858 to a word boundary. This follows the semantics of the instruction
11859 which specifies that bit 1 of the target address will come from bit
11860 1 of the base address. */
11861 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
11862 md_number_to_chars (buf, newval, THUMB_SIZE);
11863 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11864 }
11865 break;
11866
11867 case BFD_RELOC_8:
11868 if (fixP->fx_done || fixP->fx_pcrel)
11869 md_number_to_chars (buf, value, 1);
11870#ifdef OBJ_ELF
11871 else if (!target_oabi)
11872 {
11873 value = fixP->fx_offset;
11874 md_number_to_chars (buf, value, 1);
11875 }
11876#endif
11877 break;
11878
11879 case BFD_RELOC_16:
11880 if (fixP->fx_done || fixP->fx_pcrel)
11881 md_number_to_chars (buf, value, 2);
11882#ifdef OBJ_ELF
11883 else if (!target_oabi)
11884 {
11885 value = fixP->fx_offset;
11886 md_number_to_chars (buf, value, 2);
11887 }
11888#endif
11889 break;
11890
11891#ifdef OBJ_ELF
11892 case BFD_RELOC_ARM_GOT32:
11893 case BFD_RELOC_ARM_GOTOFF:
eb043451 11894 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
11895 md_number_to_chars (buf, 0, 4);
11896 break;
11897#endif
11898
11899 case BFD_RELOC_RVA:
11900 case BFD_RELOC_32:
9c504268 11901 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
11902 case BFD_RELOC_ARM_ROSEGREL32:
11903 case BFD_RELOC_ARM_SBREL32:
eb043451 11904 case BFD_RELOC_32_PCREL:
b99bd4ef
NC
11905 if (fixP->fx_done || fixP->fx_pcrel)
11906 md_number_to_chars (buf, value, 4);
11907#ifdef OBJ_ELF
11908 else if (!target_oabi)
11909 {
11910 value = fixP->fx_offset;
11911 md_number_to_chars (buf, value, 4);
11912 }
11913#endif
11914 break;
11915
11916#ifdef OBJ_ELF
eb043451
PB
11917 case BFD_RELOC_ARM_PREL31:
11918 if (fixP->fx_done || fixP->fx_pcrel)
11919 {
11920 newval = md_chars_to_number (buf, 4) & 0x80000000;
11921 if ((value ^ (value >> 1)) & 0x40000000)
11922 {
11923 as_bad_where (fixP->fx_file, fixP->fx_line,
11924 _("rel31 relocation overflow"));
11925 }
11926 newval |= value & 0x7fffffff;
11927 md_number_to_chars (buf, newval, 4);
11928 }
11929 break;
11930
b99bd4ef
NC
11931 case BFD_RELOC_ARM_PLT32:
11932 /* It appears the instruction is fully prepared at this point. */
11933 break;
11934#endif
11935
b99bd4ef
NC
11936 case BFD_RELOC_ARM_CP_OFF_IMM:
11937 sign = value >= 0;
11938 if (value < -1023 || value > 1023 || (value & 3))
11939 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11940 _("illegal value for co-processor offset"));
b99bd4ef
NC
11941 if (value < 0)
11942 value = -value;
11943 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11944 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11945 md_number_to_chars (buf, newval, INSN_SIZE);
11946 break;
11947
e16bb312
NC
11948 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11949 sign = value >= 0;
11950 if (value < -255 || value > 255)
11951 as_bad_where (fixP->fx_file, fixP->fx_line,
11952 _("Illegal value for co-processor offset"));
11953 if (value < 0)
11954 value = -value;
11955 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11956 newval |= value | (sign ? INDEX_UP : 0);
11957 md_number_to_chars (buf, newval , INSN_SIZE);
11958 break;
11959
b99bd4ef
NC
11960 case BFD_RELOC_ARM_THUMB_OFFSET:
11961 newval = md_chars_to_number (buf, THUMB_SIZE);
11962 /* Exactly what ranges, and where the offset is inserted depends
11963 on the type of instruction, we can establish this from the
11964 top 4 bits. */
11965 switch (newval >> 12)
11966 {
11967 case 4: /* PC load. */
11968 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11969 forced to zero for these loads, so we will need to round
11970 up the offset if the instruction address is not word
11971 aligned (since the final address produced must be, and
11972 we can only describe word-aligned immediate offsets). */
11973
11974 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11975 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11976 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
11977 (unsigned int) (fixP->fx_frag->fr_address
11978 + fixP->fx_where + value));
11979
11980 if ((value + 2) & ~0x3fe)
11981 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11982 _("invalid offset, value too big (0x%08lX)"),
11983 (long) value);
b99bd4ef
NC
11984
11985 /* Round up, since pc will be rounded down. */
11986 newval |= (value + 2) >> 2;
11987 break;
11988
11989 case 9: /* SP load/store. */
11990 if (value & ~0x3fc)
11991 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11992 _("invalid offset, value too big (0x%08lX)"),
11993 (long) value);
b99bd4ef
NC
11994 newval |= value >> 2;
11995 break;
11996
11997 case 6: /* Word load/store. */
11998 if (value & ~0x7c)
11999 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12000 _("invalid offset, value too big (0x%08lX)"),
12001 (long) value);
b99bd4ef
NC
12002 newval |= value << 4; /* 6 - 2. */
12003 break;
12004
12005 case 7: /* Byte load/store. */
12006 if (value & ~0x1f)
12007 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12008 _("invalid offset, value too big (0x%08lX)"),
12009 (long) value);
b99bd4ef
NC
12010 newval |= value << 6;
12011 break;
12012
12013 case 8: /* Halfword load/store. */
12014 if (value & ~0x3e)
12015 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12016 _("invalid offset, value too big (0x%08lX)"),
12017 (long) value);
b99bd4ef
NC
12018 newval |= value << 5; /* 6 - 1. */
12019 break;
12020
12021 default:
12022 as_bad_where (fixP->fx_file, fixP->fx_line,
12023 "Unable to process relocation for thumb opcode: %lx",
12024 (unsigned long) newval);
12025 break;
12026 }
12027 md_number_to_chars (buf, newval, THUMB_SIZE);
12028 break;
12029
12030 case BFD_RELOC_ARM_THUMB_ADD:
12031 /* This is a complicated relocation, since we use it for all of
12032 the following immediate relocations:
12033
12034 3bit ADD/SUB
12035 8bit ADD/SUB
12036 9bit ADD/SUB SP word-aligned
12037 10bit ADD PC/SP word-aligned
12038
12039 The type of instruction being processed is encoded in the
12040 instruction field:
12041
12042 0x8000 SUB
12043 0x00F0 Rd
12044 0x000F Rs
12045 */
12046 newval = md_chars_to_number (buf, THUMB_SIZE);
12047 {
12048 int rd = (newval >> 4) & 0xf;
12049 int rs = newval & 0xf;
12050 int subtract = newval & 0x8000;
12051
12052 if (rd == REG_SP)
12053 {
12054 if (value & ~0x1fc)
12055 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12056 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12057 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12058 newval |= value >> 2;
12059 }
12060 else if (rs == REG_PC || rs == REG_SP)
12061 {
12062 if (subtract ||
12063 value & ~0x3fc)
12064 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12065 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12066 (unsigned long) value);
12067 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12068 newval |= rd << 8;
12069 newval |= value >> 2;
12070 }
12071 else if (rs == rd)
12072 {
12073 if (value & ~0xff)
12074 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12075 _("invalid 8bit immediate"));
b99bd4ef
NC
12076 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12077 newval |= (rd << 8) | value;
12078 }
12079 else
12080 {
12081 if (value & ~0x7)
12082 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12083 _("invalid 3bit immediate"));
b99bd4ef
NC
12084 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12085 newval |= rd | (rs << 3) | (value << 6);
12086 }
12087 }
12088 md_number_to_chars (buf, newval, THUMB_SIZE);
12089 break;
12090
12091 case BFD_RELOC_ARM_THUMB_IMM:
12092 newval = md_chars_to_number (buf, THUMB_SIZE);
12093 switch (newval >> 11)
12094 {
12095 case 0x04: /* 8bit immediate MOV. */
12096 case 0x05: /* 8bit immediate CMP. */
12097 if (value < 0 || value > 255)
12098 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12099 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12100 (long) value);
12101 newval |= value;
12102 break;
12103
12104 default:
12105 abort ();
12106 }
12107 md_number_to_chars (buf, newval, THUMB_SIZE);
12108 break;
12109
12110 case BFD_RELOC_ARM_THUMB_SHIFT:
12111 /* 5bit shift value (0..31). */
12112 if (value < 0 || value > 31)
12113 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12114 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12115 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12116 newval |= value << 6;
12117 md_number_to_chars (buf, newval, THUMB_SIZE);
12118 break;
12119
12120 case BFD_RELOC_VTABLE_INHERIT:
12121 case BFD_RELOC_VTABLE_ENTRY:
12122 fixP->fx_done = 0;
94f592af 12123 return;
b99bd4ef
NC
12124
12125 case BFD_RELOC_NONE:
12126 default:
12127 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12128 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12129 }
b99bd4ef
NC
12130}
12131
12132/* Translate internal representation of relocation info to BFD target
12133 format. */
12134
12135arelent *
a737bd4d
NC
12136tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12137 fixS * fixp)
b99bd4ef
NC
12138{
12139 arelent * reloc;
12140 bfd_reloc_code_real_type code;
12141
a737bd4d 12142 reloc = xmalloc (sizeof (arelent));
b99bd4ef 12143
a737bd4d 12144 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
b99bd4ef
NC
12145 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12146 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12147
12148 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12149#ifndef OBJ_ELF
12150 if (fixp->fx_pcrel == 0)
12151 reloc->addend = fixp->fx_offset;
12152 else
12153 reloc->addend = fixp->fx_offset = reloc->address;
12154#else /* OBJ_ELF */
12155 reloc->addend = fixp->fx_offset;
12156#endif
12157
12158 switch (fixp->fx_r_type)
12159 {
12160 case BFD_RELOC_8:
12161 if (fixp->fx_pcrel)
12162 {
12163 code = BFD_RELOC_8_PCREL;
12164 break;
12165 }
12166
12167 case BFD_RELOC_16:
12168 if (fixp->fx_pcrel)
12169 {
12170 code = BFD_RELOC_16_PCREL;
12171 break;
12172 }
12173
12174 case BFD_RELOC_32:
12175 if (fixp->fx_pcrel)
12176 {
12177 code = BFD_RELOC_32_PCREL;
12178 break;
12179 }
12180
12181 case BFD_RELOC_ARM_PCREL_BRANCH:
12182 case BFD_RELOC_ARM_PCREL_BLX:
12183 case BFD_RELOC_RVA:
12184 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12185 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12186 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12187 case BFD_RELOC_THUMB_PCREL_BLX:
12188 case BFD_RELOC_VTABLE_ENTRY:
12189 case BFD_RELOC_VTABLE_INHERIT:
12190 code = fixp->fx_r_type;
12191 break;
12192
12193 case BFD_RELOC_ARM_LITERAL:
12194 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12195 /* If this is called then the a literal has
12196 been referenced across a section boundary. */
b99bd4ef 12197 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12198 _("literal referenced across section boundary"));
b99bd4ef
NC
12199 return NULL;
12200
12201#ifdef OBJ_ELF
12202 case BFD_RELOC_ARM_GOT32:
12203 case BFD_RELOC_ARM_GOTOFF:
12204 case BFD_RELOC_ARM_PLT32:
9c504268 12205 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12206 case BFD_RELOC_ARM_ROSEGREL32:
12207 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12208 case BFD_RELOC_ARM_PREL31:
12209 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12210 code = fixp->fx_r_type;
12211 break;
12212#endif
12213
12214 case BFD_RELOC_ARM_IMMEDIATE:
12215 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12216 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12217 return NULL;
12218
12219 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12220 as_bad_where (fixp->fx_file, fixp->fx_line,
12221 _("ADRL used for a symbol not defined in the same file"));
12222 return NULL;
12223
12224 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12225 if (fixp->fx_addsy != NULL
12226 && !S_IS_DEFINED (fixp->fx_addsy)
12227 && S_IS_LOCAL (fixp->fx_addsy))
12228 {
12229 as_bad_where (fixp->fx_file, fixp->fx_line,
12230 _("undefined local label `%s'"),
12231 S_GET_NAME (fixp->fx_addsy));
12232 return NULL;
12233 }
12234
b99bd4ef 12235 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12236 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12237 return NULL;
12238
12239 default:
12240 {
12241 char * type;
12242
12243 switch (fixp->fx_r_type)
12244 {
b99bd4ef
NC
12245 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12246 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
0dd132b6 12247 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
b99bd4ef
NC
12248 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12249 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12250 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12251 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12252 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12253 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12254 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12255 default: type = _("<unknown>"); break;
12256 }
12257 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12258 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12259 type);
12260 return NULL;
12261 }
12262 }
12263
12264#ifdef OBJ_ELF
8df7094c 12265 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12266 && GOT_symbol
12267 && fixp->fx_addsy == GOT_symbol)
12268 {
12269 code = BFD_RELOC_ARM_GOTPC;
12270 reloc->addend = fixp->fx_offset = reloc->address;
12271 }
12272#endif
12273
12274 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12275
12276 if (reloc->howto == NULL)
12277 {
12278 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12279 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12280 bfd_get_reloc_code_name (code));
12281 return NULL;
12282 }
12283
12284 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12285 vtable entry to be used in the relocation's section offset. */
12286 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12287 reloc->address = fixp->fx_offset;
12288
12289 return reloc;
12290}
12291
12292int
a737bd4d
NC
12293md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12294 segT segtype ATTRIBUTE_UNUSED)
b99bd4ef
NC
12295{
12296 as_fatal (_("md_estimate_size_before_relax\n"));
12297 return 1;
12298}
12299
a737bd4d
NC
12300/* We need to be able to fix up arbitrary expressions in some statements.
12301 This is so that we can handle symbols that are an arbitrary distance from
12302 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12303 which returns part of an address in a form which will be valid for
12304 a data instruction. We do this by pushing the expression into a symbol
12305 in the expr_section, and creating a fix for that. */
12306
12307static void
12308fix_new_arm (fragS * frag,
12309 int where,
12310 short int size,
12311 expressionS * exp,
12312 int pc_rel,
12313 int reloc)
12314{
12315 fixS * new_fix;
12316 arm_fix_data * arm_data;
12317
12318 switch (exp->X_op)
12319 {
12320 case O_constant:
12321 case O_symbol:
12322 case O_add:
12323 case O_subtract:
12324 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12325 break;
12326
12327 default:
12328 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12329 pc_rel, reloc);
12330 break;
12331 }
12332
12333 /* Mark whether the fix is to a THUMB instruction, or an ARM
12334 instruction. */
12335 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12336 new_fix->tc_fix_data = (PTR) arm_data;
12337 arm_data->thumb_mode = thumb_mode;
12338}
12339
b99bd4ef 12340static void
a737bd4d 12341output_inst (const char * str)
b99bd4ef
NC
12342{
12343 char * to = NULL;
12344
12345 if (inst.error)
12346 {
f03698e6 12347 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12348 return;
12349 }
12350
12351 to = frag_more (inst.size);
12352
12353 if (thumb_mode && (inst.size > THUMB_SIZE))
12354 {
12355 assert (inst.size == (2 * THUMB_SIZE));
12356 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12357 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12358 }
12359 else if (inst.size > INSN_SIZE)
12360 {
12361 assert (inst.size == (2 * INSN_SIZE));
12362 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12363 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12364 }
12365 else
12366 md_number_to_chars (to, inst.instruction, inst.size);
12367
12368 if (inst.reloc.type != BFD_RELOC_NONE)
12369 fix_new_arm (frag_now, to - frag_now->fr_literal,
12370 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12371 inst.reloc.type);
12372
12373#ifdef OBJ_ELF
12374 dwarf2_emit_insn (inst.size);
12375#endif
12376}
12377
12378void
a737bd4d 12379md_assemble (char * str)
b99bd4ef 12380{
6c43fab6
RE
12381 char c;
12382 char *p;
12383 char *start;
b99bd4ef
NC
12384
12385 /* Align the instruction.
12386 This may not be the right thing to do but ... */
12387#if 0
12388 arm_align (2, 0);
12389#endif
b99bd4ef
NC
12390
12391 /* Align the previous label if needed. */
12392 if (last_label_seen != NULL)
12393 {
12394 symbol_set_frag (last_label_seen, frag_now);
12395 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12396 S_SET_SEGMENT (last_label_seen, now_seg);
12397 }
12398
12399 memset (&inst, '\0', sizeof (inst));
12400 inst.reloc.type = BFD_RELOC_NONE;
12401
12402 skip_whitespace (str);
12403
12404 /* Scan up to the end of the op-code, which must end in white space or
12405 end of string. */
12406 for (start = p = str; *p != '\0'; p++)
12407 if (*p == ' ')
12408 break;
12409
12410 if (p == str)
12411 {
f03698e6 12412 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12413 return;
12414 }
12415
12416 if (thumb_mode)
12417 {
05d2d07e 12418 const struct thumb_opcode * opcode;
b99bd4ef
NC
12419
12420 c = *p;
12421 *p = '\0';
05d2d07e 12422 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12423 *p = c;
12424
12425 if (opcode)
12426 {
12427 /* Check that this instruction is supported for this CPU. */
90e4755a 12428 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12429 {
f03698e6 12430 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12431 return;
12432 }
12433
6057a28f 12434 mapping_state (MAP_THUMB);
b99bd4ef
NC
12435 inst.instruction = opcode->value;
12436 inst.size = opcode->size;
a737bd4d 12437 opcode->parms (p);
f03698e6 12438 output_inst (str);
b99bd4ef
NC
12439 return;
12440 }
12441 }
12442 else
12443 {
05d2d07e 12444 const struct asm_opcode * opcode;
b99bd4ef 12445
90e4755a
RE
12446 c = *p;
12447 *p = '\0';
6c43fab6 12448 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12449 *p = c;
b99bd4ef 12450
90e4755a 12451 if (opcode)
b99bd4ef 12452 {
90e4755a
RE
12453 /* Check that this instruction is supported for this CPU. */
12454 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12455 {
f03698e6 12456 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12457 return;
12458 }
12459
6057a28f 12460 mapping_state (MAP_ARM);
90e4755a
RE
12461 inst.instruction = opcode->value;
12462 inst.size = INSN_SIZE;
a737bd4d 12463 opcode->parms (p);
f03698e6 12464 output_inst (str);
90e4755a 12465 return;
b99bd4ef
NC
12466 }
12467 }
12468
12469 /* It wasn't an instruction, but it might be a register alias of the form
12470 alias .req reg. */
6c43fab6
RE
12471 if (create_register_alias (str, p))
12472 return;
b99bd4ef 12473
b99bd4ef
NC
12474 as_bad (_("bad instruction `%s'"), start);
12475}
12476
12477/* md_parse_option
12478 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12479 See if it's a processor-specific option.
03b1477f
RE
12480
12481 This routine is somewhat complicated by the need for backwards
12482 compatibility (since older releases of gcc can't be changed).
12483 The new options try to make the interface as compatible as
12484 possible with GCC.
12485
12486 New options (supported) are:
12487
12488 -mcpu=<cpu name> Assemble for selected processor
12489 -march=<architecture name> Assemble for selected architecture
12490 -mfpu=<fpu architecture> Assemble for selected FPU.
12491 -EB/-mbig-endian Big-endian
12492 -EL/-mlittle-endian Little-endian
12493 -k Generate PIC code
12494 -mthumb Start in Thumb mode
12495 -mthumb-interwork Code supports ARM/Thumb interworking
12496
3d0c9500 12497 For now we will also provide support for:
03b1477f
RE
12498
12499 -mapcs-32 32-bit Program counter
12500 -mapcs-26 26-bit Program counter
12501 -macps-float Floats passed in FP registers
12502 -mapcs-reentrant Reentrant code
12503 -matpcs
12504 (sometime these will probably be replaced with -mapcs=<list of options>
12505 and -matpcs=<list of options>)
12506
12507 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
12508 Cpu variants, the arm part is optional:
12509 -m[arm]1 Currently not supported.
12510 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12511 -m[arm]3 Arm 3 processor
12512 -m[arm]6[xx], Arm 6 processors
12513 -m[arm]7[xx][t][[d]m] Arm 7 processors
12514 -m[arm]8[10] Arm 8 processors
12515 -m[arm]9[20][tdmi] Arm 9 processors
12516 -mstrongarm[110[0]] StrongARM processors
12517 -mxscale XScale processors
12518 -m[arm]v[2345[t[e]]] Arm architectures
12519 -mall All (except the ARM1)
12520 FP variants:
12521 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12522 -mfpe-old (No float load/store multiples)
bfae80f2
RE
12523 -mvfpxd VFP Single precision
12524 -mvfp All VFP
b99bd4ef 12525 -mno-fpu Disable all floating point instructions
b99bd4ef 12526
03b1477f
RE
12527 The following CPU names are recognized:
12528 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12529 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12530 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12531 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12532 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12533 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12534 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12535
12536 */
12537
5a38dc70 12538const char * md_shortopts = "m:k";
03b1477f 12539
b99bd4ef
NC
12540#ifdef ARM_BI_ENDIAN
12541#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 12542#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12543#else
21f0f23a
RE
12544#if TARGET_BYTES_BIG_ENDIAN
12545#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
12546#else
12547#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12548#endif
ce058b6c 12549#endif
03b1477f
RE
12550
12551struct option md_longopts[] =
12552{
12553#ifdef OPTION_EB
12554 {"EB", no_argument, NULL, OPTION_EB},
12555#endif
12556#ifdef OPTION_EL
12557 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
12558#endif
12559 {NULL, no_argument, NULL, 0}
12560};
12561
12562size_t md_longopts_size = sizeof (md_longopts);
12563
03b1477f 12564struct arm_option_table
b99bd4ef 12565{
03b1477f
RE
12566 char *option; /* Option name to match. */
12567 char *help; /* Help information. */
12568 int *var; /* Variable to change. */
12569 int value; /* What to change it to. */
12570 char *deprecated; /* If non-null, print this message. */
12571};
b99bd4ef 12572
cc8a6dd0 12573struct arm_option_table arm_opts[] =
03b1477f
RE
12574{
12575 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12576 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12577 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12578 &support_interwork, 1, NULL},
12579 {"moabi", N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
12580 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12581 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12582 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12583 1, NULL},
12584 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12585 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12586 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12587 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12588 NULL},
12589
12590 /* These are recognized by the assembler, but have no affect on code. */
12591 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12592 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12593
12594 /* DON'T add any new processors to this list -- we want the whole list
12595 to go away... Add them to the processors table instead. */
12596 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12597 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12598 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12599 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12600 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12601 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12602 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12603 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12604 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12605 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12606 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12607 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12608 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12609 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12610 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12611 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12612 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12613 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12614 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12615 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12616 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12617 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12618 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12619 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12620 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12621 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12622 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12623 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12624 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12625 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12626 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12627 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12628 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12629 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12630 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12631 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12632 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12633 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12634 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12635 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12636 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12637 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12638 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12639 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12640 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12641 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12642 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12643 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12644 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12645 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12646 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12647 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12648 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12649 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12650 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12651 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12652 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12653 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12654 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12655 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12656 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12657 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12658 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12659 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12660 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12661 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12662 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12663 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12664 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12665 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12666 N_("use -mcpu=strongarm110")},
12667 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12668 N_("use -mcpu=strongarm1100")},
12669 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12670 N_("use -mcpu=strongarm1110")},
12671 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 12672 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
12673 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12674
12675 /* Architecture variants -- don't add any more to this list either. */
12676 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12677 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12678 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12679 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12680 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12681 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12682 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12683 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12684 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12685 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12686 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12687 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12688 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12689 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12690 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12691 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12692 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12693 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12694
12695 /* Floating point variants -- don't add any more to this list either. */
12696 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12697 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12698 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12699 {"mno-fpu", NULL, &legacy_fpu, 0,
12700 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12701
12702 {NULL, NULL, NULL, 0, NULL}
12703};
21f0f23a 12704
03b1477f
RE
12705struct arm_cpu_option_table
12706{
12707 char *name;
12708 int value;
12709 /* For some CPUs we assume an FPU unless the user explicitly sets
12710 -mfpu=... */
12711 int default_fpu;
12712};
12713
12714/* This list should, at a minimum, contain all the cpu names
12715 recognized by GCC. */
12716static struct arm_cpu_option_table arm_cpus[] =
12717{
12718 {"all", ARM_ANY, FPU_ARCH_FPA},
12719 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12720 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12721 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12722 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12723 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12724 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12725 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12726 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12727 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12728 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12729 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12730 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12731 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12732 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12733 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12734 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12735 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12736 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12737 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12738 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12739 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12740 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12741 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12742 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12743 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12744 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12745 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12746 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12747 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 12748 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
12749 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12750 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12751 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12752 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12753 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12754 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12755 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12756 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12757 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12758 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12759 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12760 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12761 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12762 /* For V5 or later processors we default to using VFP; but the user
12763 should really set the FPU type explicitly. */
12764 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12765 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 12766 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 12767 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 12768 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
12769 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12770 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12771 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12772 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12773 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12774 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12775 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12776 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12777 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 12778 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
8783612f 12779 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015 12780 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 12781 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 12782 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 12783 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
0dd132b6
NC
12784 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12785 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12786 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12787 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
03b1477f
RE
12788 /* ??? XSCALE is really an architecture. */
12789 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 12790 /* ??? iwmmxt is not a processor. */
e16bb312 12791 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
12792 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12793 /* Maverick */
33a392fb 12794 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
12795 {NULL, 0, 0}
12796};
cc8a6dd0 12797
03b1477f
RE
12798struct arm_arch_option_table
12799{
12800 char *name;
12801 int value;
12802 int default_fpu;
12803};
12804
12805/* This list should, at a minimum, contain all the architecture names
12806 recognized by GCC. */
12807static struct arm_arch_option_table arm_archs[] =
12808{
12809 {"all", ARM_ANY, FPU_ARCH_FPA},
12810 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12811 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12812 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12813 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12814 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12815 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12816 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12817 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12818 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12819 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12820 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12821 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12822 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12823 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12824 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 12825 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 12826 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 12827 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
0dd132b6
NC
12828 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12829 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12830 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
03b1477f 12831 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 12832 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
12833 {NULL, 0, 0}
12834};
12835
12836/* ISA extensions in the co-processor space. */
12837struct arm_arch_extension_table
12838{
12839 char *name;
12840 int value;
12841};
12842
12843static struct arm_arch_extension_table arm_extensions[] =
12844{
12845 {"maverick", ARM_CEXT_MAVERICK},
12846 {"xscale", ARM_CEXT_XSCALE},
e16bb312 12847 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
12848 {NULL, 0}
12849};
b99bd4ef 12850
03b1477f
RE
12851struct arm_fpu_option_table
12852{
12853 char *name;
12854 int value;
12855};
12856
12857/* This list should, at a minimum, contain all the fpu names
12858 recognized by GCC. */
12859static struct arm_fpu_option_table arm_fpus[] =
12860{
12861 {"softfpa", FPU_NONE},
12862 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
12863 {"fpe2", FPU_ARCH_FPE},
12864 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
12865 {"fpa", FPU_ARCH_FPA},
12866 {"fpa10", FPU_ARCH_FPA},
12867 {"fpa11", FPU_ARCH_FPA},
12868 {"arm7500fe", FPU_ARCH_FPA},
12869 {"softvfp", FPU_ARCH_VFP},
12870 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12871 {"vfp", FPU_ARCH_VFP_V2},
12872 {"vfp9", FPU_ARCH_VFP_V2},
12873 {"vfp10", FPU_ARCH_VFP_V2},
12874 {"vfp10-r0", FPU_ARCH_VFP_V1},
12875 {"vfpxd", FPU_ARCH_VFP_V1xD},
12876 {"arm1020t", FPU_ARCH_VFP_V1},
12877 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 12878 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 12879 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
12880 {"maverick", FPU_ARCH_MAVERICK},
12881 {NULL, 0}
12882};
12883
12884struct arm_float_abi_option_table
12885{
12886 char *name;
12887 int value;
12888};
12889
12890static struct arm_float_abi_option_table arm_float_abis[] =
12891{
12892 {"hard", ARM_FLOAT_ABI_HARD},
12893 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12894 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
12895 {NULL, 0}
12896};
12897
d507cf36
PB
12898struct arm_eabi_option_table
12899{
12900 char *name;
12901 unsigned int value;
12902};
12903
7cc69913 12904#ifdef OBJ_ELF
8cb51566 12905/* We only know how to output GNU and ver 4 (AAELF) formats. */
d507cf36
PB
12906static struct arm_eabi_option_table arm_eabis[] =
12907{
12908 {"gnu", EF_ARM_EABI_UNKNOWN},
8cb51566 12909 {"4", EF_ARM_EABI_VER4},
d507cf36
PB
12910 {NULL, 0}
12911};
7cc69913 12912#endif
d507cf36 12913
03b1477f
RE
12914struct arm_long_option_table
12915{
a737bd4d
NC
12916 char * option; /* Substring to match. */
12917 char * help; /* Help information. */
12918 int (* func) (char * subopt); /* Function to decode sub-option. */
12919 char * deprecated; /* If non-null, print this message. */
03b1477f
RE
12920};
12921
12922static int
a737bd4d 12923arm_parse_extension (char * str, int * opt_p)
03b1477f
RE
12924{
12925 while (str != NULL && *str != 0)
12926 {
a737bd4d
NC
12927 struct arm_arch_extension_table * opt;
12928 char * ext;
03b1477f
RE
12929 int optlen;
12930
12931 if (*str != '+')
b99bd4ef 12932 {
03b1477f
RE
12933 as_bad (_("invalid architectural extension"));
12934 return 0;
12935 }
b99bd4ef 12936
03b1477f
RE
12937 str++;
12938 ext = strchr (str, '+');
b99bd4ef 12939
03b1477f
RE
12940 if (ext != NULL)
12941 optlen = ext - str;
12942 else
12943 optlen = strlen (str);
b99bd4ef 12944
03b1477f
RE
12945 if (optlen == 0)
12946 {
12947 as_bad (_("missing architectural extension"));
12948 return 0;
12949 }
b99bd4ef 12950
03b1477f
RE
12951 for (opt = arm_extensions; opt->name != NULL; opt++)
12952 if (strncmp (opt->name, str, optlen) == 0)
12953 {
12954 *opt_p |= opt->value;
12955 break;
12956 }
bfae80f2 12957
03b1477f
RE
12958 if (opt->name == NULL)
12959 {
12960 as_bad (_("unknown architectural extnsion `%s'"), str);
12961 return 0;
12962 }
b99bd4ef 12963
03b1477f
RE
12964 str = ext;
12965 };
b99bd4ef 12966
03b1477f
RE
12967 return 1;
12968}
b99bd4ef 12969
03b1477f 12970static int
a737bd4d 12971arm_parse_cpu (char * str)
03b1477f 12972{
a737bd4d
NC
12973 struct arm_cpu_option_table * opt;
12974 char * ext = strchr (str, '+');
03b1477f 12975 int optlen;
b99bd4ef 12976
03b1477f
RE
12977 if (ext != NULL)
12978 optlen = ext - str;
12979 else
12980 optlen = strlen (str);
b99bd4ef 12981
03b1477f
RE
12982 if (optlen == 0)
12983 {
12984 as_bad (_("missing cpu name `%s'"), str);
12985 return 0;
12986 }
b99bd4ef 12987
03b1477f
RE
12988 for (opt = arm_cpus; opt->name != NULL; opt++)
12989 if (strncmp (opt->name, str, optlen) == 0)
12990 {
12991 mcpu_cpu_opt = opt->value;
12992 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 12993
03b1477f
RE
12994 if (ext != NULL)
12995 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 12996
03b1477f
RE
12997 return 1;
12998 }
b99bd4ef 12999
03b1477f
RE
13000 as_bad (_("unknown cpu `%s'"), str);
13001 return 0;
13002}
b99bd4ef 13003
03b1477f 13004static int
a737bd4d 13005arm_parse_arch (char * str)
03b1477f
RE
13006{
13007 struct arm_arch_option_table *opt;
13008 char *ext = strchr (str, '+');
13009 int optlen;
b99bd4ef 13010
03b1477f
RE
13011 if (ext != NULL)
13012 optlen = ext - str;
13013 else
13014 optlen = strlen (str);
b99bd4ef 13015
03b1477f
RE
13016 if (optlen == 0)
13017 {
13018 as_bad (_("missing architecture name `%s'"), str);
13019 return 0;
13020 }
b99bd4ef 13021
b99bd4ef 13022
03b1477f 13023 for (opt = arm_archs; opt->name != NULL; opt++)
a737bd4d 13024 if (streq (opt->name, str))
03b1477f
RE
13025 {
13026 march_cpu_opt = opt->value;
13027 march_fpu_opt = opt->default_fpu;
b99bd4ef 13028
03b1477f
RE
13029 if (ext != NULL)
13030 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13031
03b1477f
RE
13032 return 1;
13033 }
b99bd4ef 13034
03b1477f
RE
13035 as_bad (_("unknown architecture `%s'\n"), str);
13036 return 0;
13037}
13038
13039static int
a737bd4d 13040arm_parse_fpu (char * str)
03b1477f 13041{
a737bd4d 13042 struct arm_fpu_option_table * opt;
b99bd4ef 13043
03b1477f 13044 for (opt = arm_fpus; opt->name != NULL; opt++)
a737bd4d 13045 if (streq (opt->name, str))
03b1477f
RE
13046 {
13047 mfpu_opt = opt->value;
13048 return 1;
13049 }
b99bd4ef 13050
03b1477f
RE
13051 as_bad (_("unknown floating point format `%s'\n"), str);
13052 return 0;
13053}
b99bd4ef 13054
33a392fb 13055static int
a737bd4d 13056arm_parse_float_abi (char * str)
33a392fb 13057{
a737bd4d 13058 struct arm_float_abi_option_table * opt;
33a392fb
PB
13059
13060 for (opt = arm_float_abis; opt->name != NULL; opt++)
a737bd4d 13061 if (streq (opt->name, str))
33a392fb
PB
13062 {
13063 mfloat_abi_opt = opt->value;
13064 return 1;
13065 }
13066
13067 as_bad (_("unknown floating point abi `%s'\n"), str);
13068 return 0;
13069}
13070
7cc69913 13071#ifdef OBJ_ELF
d507cf36 13072static int
a737bd4d 13073arm_parse_eabi (char * str)
d507cf36
PB
13074{
13075 struct arm_eabi_option_table *opt;
13076
13077 for (opt = arm_eabis; opt->name != NULL; opt++)
a737bd4d 13078 if (streq (opt->name, str))
d507cf36
PB
13079 {
13080 meabi_flags = opt->value;
13081 return 1;
13082 }
13083 as_bad (_("unknown EABI `%s'\n"), str);
13084 return 0;
13085}
7cc69913 13086#endif
d507cf36 13087
03b1477f
RE
13088struct arm_long_option_table arm_long_opts[] =
13089{
13090 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13091 arm_parse_cpu, NULL},
13092 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13093 arm_parse_arch, NULL},
13094 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13095 arm_parse_fpu, NULL},
33a392fb
PB
13096 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13097 arm_parse_float_abi, NULL},
7cc69913 13098#ifdef OBJ_ELF
d507cf36
PB
13099 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13100 arm_parse_eabi, NULL},
7cc69913 13101#endif
03b1477f
RE
13102 {NULL, NULL, 0, NULL}
13103};
b99bd4ef 13104
03b1477f 13105int
a737bd4d 13106md_parse_option (int c, char * arg)
03b1477f
RE
13107{
13108 struct arm_option_table *opt;
13109 struct arm_long_option_table *lopt;
b99bd4ef 13110
03b1477f
RE
13111 switch (c)
13112 {
13113#ifdef OPTION_EB
13114 case OPTION_EB:
13115 target_big_endian = 1;
b99bd4ef 13116 break;
03b1477f 13117#endif
b99bd4ef 13118
03b1477f
RE
13119#ifdef OPTION_EL
13120 case OPTION_EL:
13121 target_big_endian = 0;
b99bd4ef
NC
13122 break;
13123#endif
13124
03b1477f 13125 case 'a':
cc8a6dd0 13126 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13127 ones. */
13128 return 0;
13129
b99bd4ef 13130 default:
03b1477f
RE
13131 for (opt = arm_opts; opt->option != NULL; opt++)
13132 {
13133 if (c == opt->option[0]
13134 && ((arg == NULL && opt->option[1] == 0)
a737bd4d 13135 || streq (arg, opt->option + 1)))
03b1477f
RE
13136 {
13137#if WARN_DEPRECATED
13138 /* If the option is deprecated, tell the user. */
13139 if (opt->deprecated != NULL)
13140 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13141 arg ? arg : "", _(opt->deprecated));
13142#endif
13143
13144 if (opt->var != NULL)
13145 *opt->var = opt->value;
13146
13147 return 1;
13148 }
13149 }
13150
13151 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13152 {
cc8a6dd0 13153 /* These options are expected to have an argument. */
03b1477f
RE
13154 if (c == lopt->option[0]
13155 && arg != NULL
cc8a6dd0 13156 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13157 strlen (lopt->option + 1)) == 0)
13158 {
13159#if WARN_DEPRECATED
13160 /* If the option is deprecated, tell the user. */
13161 if (lopt->deprecated != NULL)
13162 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13163 _(lopt->deprecated));
13164#endif
13165
13166 /* Call the sup-option parser. */
a737bd4d 13167 return lopt->func (arg + strlen (lopt->option) - 1);
03b1477f
RE
13168 }
13169 }
13170
b99bd4ef
NC
13171 return 0;
13172 }
13173
13174 return 1;
13175}
13176
13177void
a737bd4d 13178md_show_usage (FILE * fp)
b99bd4ef 13179{
03b1477f
RE
13180 struct arm_option_table *opt;
13181 struct arm_long_option_table *lopt;
13182
13183 fprintf (fp, _(" ARM-specific assembler options:\n"));
13184
13185 for (opt = arm_opts; opt->option != NULL; opt++)
13186 if (opt->help != NULL)
13187 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13188
13189 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13190 if (lopt->help != NULL)
13191 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13192
13193#ifdef OPTION_EB
b99bd4ef 13194 fprintf (fp, _("\
03b1477f 13195 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13196#endif
03b1477f
RE
13197
13198#ifdef OPTION_EL
b99bd4ef 13199 fprintf (fp, _("\
03b1477f 13200 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13201#endif
13202}
13203
b99bd4ef
NC
13204/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13205
13206void
a737bd4d
NC
13207cons_fix_new_arm (fragS * frag,
13208 int where,
13209 int size,
13210 expressionS * exp)
b99bd4ef
NC
13211{
13212 bfd_reloc_code_real_type type;
13213 int pcrel = 0;
13214
13215 /* Pick a reloc.
13216 FIXME: @@ Should look at CPU word size. */
13217 switch (size)
13218 {
13219 case 1:
13220 type = BFD_RELOC_8;
13221 break;
13222 case 2:
13223 type = BFD_RELOC_16;
13224 break;
13225 case 4:
13226 default:
13227 type = BFD_RELOC_32;
13228 break;
13229 case 8:
13230 type = BFD_RELOC_64;
13231 break;
13232 }
13233
13234 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13235}
13236
13237/* A good place to do this, although this was probably not intended
13238 for this kind of use. We need to dump the literal pool before
13239 references are made to a null symbol pointer. */
13240
13241void
a737bd4d 13242arm_cleanup (void)
b99bd4ef 13243{
3d0c9500 13244 literal_pool * pool;
b99bd4ef 13245
3d0c9500
NC
13246 for (pool = list_of_pools; pool; pool = pool->next)
13247 {
13248 /* Put it at the end of the relevent section. */
13249 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13250#ifdef OBJ_ELF
13251 arm_elf_change_section ();
13252#endif
3d0c9500
NC
13253 s_ltorg (0);
13254 }
b99bd4ef
NC
13255}
13256
13257void
a737bd4d 13258arm_start_line_hook (void)
b99bd4ef
NC
13259{
13260 last_label_seen = NULL;
13261}
13262
13263void
a737bd4d 13264arm_frob_label (symbolS * sym)
b99bd4ef
NC
13265{
13266 last_label_seen = sym;
13267
13268 ARM_SET_THUMB (sym, thumb_mode);
13269
13270#if defined OBJ_COFF || defined OBJ_ELF
13271 ARM_SET_INTERWORK (sym, support_interwork);
13272#endif
13273
13274 /* Note - do not allow local symbols (.Lxxx) to be labeled
13275 as Thumb functions. This is because these labels, whilst
13276 they exist inside Thumb code, are not the entry points for
13277 possible ARM->Thumb calls. Also, these labels can be used
13278 as part of a computed goto or switch statement. eg gcc
13279 can generate code that looks like this:
13280
13281 ldr r2, [pc, .Laaa]
13282 lsl r3, r3, #2
13283 ldr r2, [r3, r2]
13284 mov pc, r2
cc8a6dd0 13285
b99bd4ef
NC
13286 .Lbbb: .word .Lxxx
13287 .Lccc: .word .Lyyy
13288 ..etc...
13289 .Laaa: .word Lbbb
13290
13291 The first instruction loads the address of the jump table.
13292 The second instruction converts a table index into a byte offset.
13293 The third instruction gets the jump address out of the table.
13294 The fourth instruction performs the jump.
cc8a6dd0 13295
b99bd4ef
NC
13296 If the address stored at .Laaa is that of a symbol which has the
13297 Thumb_Func bit set, then the linker will arrange for this address
13298 to have the bottom bit set, which in turn would mean that the
13299 address computation performed by the third instruction would end
13300 up with the bottom bit set. Since the ARM is capable of unaligned
13301 word loads, the instruction would then load the incorrect address
13302 out of the jump table, and chaos would ensue. */
13303 if (label_is_thumb_function_name
13304 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13305 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13306 {
13307 /* When the address of a Thumb function is taken the bottom
13308 bit of that address should be set. This will allow
13309 interworking between Arm and Thumb functions to work
13310 correctly. */
13311
13312 THUMB_SET_FUNC (sym, 1);
13313
b34976b6 13314 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13315 }
13316}
13317
13318/* Adjust the symbol table. This marks Thumb symbols as distinct from
13319 ARM ones. */
13320
13321void
a737bd4d 13322arm_adjust_symtab (void)
b99bd4ef
NC
13323{
13324#ifdef OBJ_COFF
13325 symbolS * sym;
13326
13327 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13328 {
13329 if (ARM_IS_THUMB (sym))
13330 {
13331 if (THUMB_IS_FUNC (sym))
13332 {
13333 /* Mark the symbol as a Thumb function. */
13334 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13335 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13336 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13337
13338 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13339 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13340 else
13341 as_bad (_("%s: unexpected function type: %d"),
13342 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13343 }
cc8a6dd0 13344 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13345 {
13346 case C_EXT:
13347 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13348 break;
13349 case C_STAT:
13350 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13351 break;
13352 case C_LABEL:
13353 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13354 break;
13355 default:
13356 /* Do nothing. */
13357 break;
13358 }
13359 }
13360
13361 if (ARM_IS_INTERWORK (sym))
13362 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13363 }
13364#endif
13365#ifdef OBJ_ELF
13366 symbolS * sym;
13367 char bind;
13368
13369 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13370 {
13371 if (ARM_IS_THUMB (sym))
13372 {
13373 elf_symbol_type * elf_sym;
13374
13375 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13376 bind = ELF_ST_BIND (elf_sym);
13377
13378 /* If it's a .thumb_func, declare it as so,
13379 otherwise tag label as .code 16. */
13380 if (THUMB_IS_FUNC (sym))
13381 elf_sym->internal_elf_sym.st_info =
13382 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13383 else
13384 elf_sym->internal_elf_sym.st_info =
13385 ELF_ST_INFO (bind, STT_ARM_16BIT);
13386 }
13387 }
13388#endif
13389}
13390
13391int
a737bd4d 13392arm_data_in_code (void)
b99bd4ef
NC
13393{
13394 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13395 {
13396 *input_line_pointer = '/';
13397 input_line_pointer += 5;
13398 *input_line_pointer = 0;
13399 return 1;
13400 }
13401
13402 return 0;
13403}
13404
13405char *
a737bd4d 13406arm_canonicalize_symbol_name (char * name)
b99bd4ef
NC
13407{
13408 int len;
13409
13410 if (thumb_mode && (len = strlen (name)) > 5
13411 && streq (name + len - 5, "/data"))
13412 *(name + len - 5) = 0;
13413
13414 return name;
13415}
13416
bfc866a6 13417#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13418void
a737bd4d 13419arm_validate_fix (fixS * fixP)
b99bd4ef
NC
13420{
13421 /* If the destination of the branch is a defined symbol which does not have
13422 the THUMB_FUNC attribute, then we must be calling a function which has
13423 the (interfacearm) attribute. We look for the Thumb entry point to that
13424 function and change the branch to refer to that function instead. */
13425 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13426 && fixP->fx_addsy != NULL
13427 && S_IS_DEFINED (fixP->fx_addsy)
13428 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13429 {
13430 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13431 }
b99bd4ef 13432}
bfc866a6 13433#endif
b99bd4ef 13434
114424c6 13435int
a737bd4d 13436arm_force_relocation (struct fix * fixp)
114424c6
AM
13437{
13438#if defined (OBJ_COFF) && defined (TE_PE)
13439 if (fixp->fx_r_type == BFD_RELOC_RVA)
13440 return 1;
13441#endif
13442#ifdef OBJ_ELF
ae6063d4 13443 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13444 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13445 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13446 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13447 return 1;
13448#endif
13449
13450 /* Resolve these relocations even if the symbol is extern or weak. */
13451 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13452 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13453 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13454 return 0;
13455
ae6063d4 13456 return generic_force_reloc (fixp);
114424c6
AM
13457}
13458
b99bd4ef
NC
13459#ifdef OBJ_COFF
13460/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13461 local labels from being added to the output symbol table when they
13462 are used with the ADRL pseudo op. The ADRL relocation should always
13463 be resolved before the binbary is emitted, so it is safe to say that
13464 it is adjustable. */
13465
b34976b6 13466bfd_boolean
a737bd4d 13467arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13468{
13469 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13470 return 1;
13471 return 0;
13472}
13473#endif
114424c6 13474
b99bd4ef
NC
13475#ifdef OBJ_ELF
13476/* Relocations against Thumb function names must be left unadjusted,
13477 so that the linker can use this information to correctly set the
13478 bottom bit of their addresses. The MIPS version of this function
13479 also prevents relocations that are mips-16 specific, but I do not
13480 know why it does this.
13481
13482 FIXME:
13483 There is one other problem that ought to be addressed here, but
13484 which currently is not: Taking the address of a label (rather
13485 than a function) and then later jumping to that address. Such
13486 addresses also ought to have their bottom bit set (assuming that
13487 they reside in Thumb code), but at the moment they will not. */
13488
b34976b6 13489bfd_boolean
a737bd4d 13490arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13491{
13492 if (fixP->fx_addsy == NULL)
13493 return 1;
13494
b99bd4ef
NC
13495 if (THUMB_IS_FUNC (fixP->fx_addsy)
13496 && fixP->fx_subsy == NULL)
13497 return 0;
13498
13499 /* We need the symbol name for the VTABLE entries. */
13500 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13501 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13502 return 0;
13503
a161fe53
AM
13504 /* Don't allow symbols to be discarded on GOT related relocs. */
13505 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13506 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
13507 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13508 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
13509 return 0;
13510
b99bd4ef
NC
13511 return 1;
13512}
13513
13514const char *
a737bd4d 13515elf32_arm_target_format (void)
b99bd4ef 13516{
e5a52504
MM
13517#ifdef TE_SYMBIAN
13518 return (target_big_endian
13519 ? "elf32-bigarm-symbian"
13520 : "elf32-littlearm-symbian");
a737bd4d 13521#else
b99bd4ef
NC
13522 if (target_big_endian)
13523 {
13524 if (target_oabi)
13525 return "elf32-bigarm-oabi";
13526 else
13527 return "elf32-bigarm";
13528 }
13529 else
13530 {
13531 if (target_oabi)
13532 return "elf32-littlearm-oabi";
13533 else
13534 return "elf32-littlearm";
13535 }
e5a52504 13536#endif
b99bd4ef
NC
13537}
13538
13539void
a737bd4d
NC
13540armelf_frob_symbol (symbolS * symp,
13541 int * puntp)
b99bd4ef
NC
13542{
13543 elf_frob_symbol (symp, puntp);
13544}
13545
b99bd4ef 13546static void
a737bd4d 13547s_arm_elf_cons (int nbytes)
b99bd4ef
NC
13548{
13549 expressionS exp;
13550
13551#ifdef md_flush_pending_output
13552 md_flush_pending_output ();
13553#endif
13554
13555 if (is_it_end_of_statement ())
13556 {
13557 demand_empty_rest_of_line ();
13558 return;
13559 }
13560
13561#ifdef md_cons_align
13562 md_cons_align (nbytes);
13563#endif
13564
6057a28f 13565 mapping_state (MAP_DATA);
b99bd4ef
NC
13566 do
13567 {
13568 bfd_reloc_code_real_type reloc;
13569
13570 expression (& exp);
13571
13572 if (exp.X_op == O_symbol
13573 && * input_line_pointer == '('
13574 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13575 {
13576 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13577 int size = bfd_get_reloc_size (howto);
13578
13579 if (size > nbytes)
13580 as_bad ("%s relocations do not fit in %d bytes",
13581 howto->name, nbytes);
13582 else
13583 {
a737bd4d 13584 char *p = frag_more ((int) nbytes);
b99bd4ef
NC
13585 int offset = nbytes - size;
13586
13587 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13588 &exp, 0, reloc);
13589 }
13590 }
13591 else
13592 emit_expr (&exp, (unsigned int) nbytes);
13593 }
13594 while (*input_line_pointer++ == ',');
13595
13596 /* Put terminator back into stream. */
13597 input_line_pointer --;
13598 demand_empty_rest_of_line ();
13599}
13600
eb043451
PB
13601
13602/* Parse a .rel31 directive. */
13603
13604static void
13605s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13606{
13607 expressionS exp;
13608 char *p;
13609 valueT highbit;
a737bd4d 13610
eb043451
PB
13611 SKIP_WHITESPACE ();
13612
13613 highbit = 0;
13614 if (*input_line_pointer == '1')
13615 highbit = 0x80000000;
13616 else if (*input_line_pointer != '0')
13617 as_bad (_("expected 0 or 1"));
13618
13619 input_line_pointer++;
13620 SKIP_WHITESPACE ();
13621 if (*input_line_pointer != ',')
13622 as_bad (_("missing comma"));
13623 input_line_pointer++;
13624
13625#ifdef md_flush_pending_output
13626 md_flush_pending_output ();
13627#endif
13628
13629#ifdef md_cons_align
13630 md_cons_align (4);
13631#endif
13632
13633 mapping_state (MAP_DATA);
13634
13635 expression (&exp);
13636
13637 p = frag_more (4);
13638 md_number_to_chars (p, highbit, 4);
13639 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13640 BFD_RELOC_ARM_PREL31);
13641
13642 demand_empty_rest_of_line ();
13643}
7ed4c4c5
NC
13644\f
13645/* Code to deal with unwinding tables. */
13646
13647static void add_unwind_adjustsp (offsetT);
13648
13649/* Switch to section NAME and create section if necessary. It's
13650 rather ugly that we have to manipulate input_line_pointer but I
13651 don't see any other way to accomplish the same thing without
13652 changing obj-elf.c (which may be the Right Thing, in the end).
13653 Copied from tc-ia64.c. */
13654
13655static void
13656set_section (char *name)
13657{
13658 char *saved_input_line_pointer;
13659
13660 saved_input_line_pointer = input_line_pointer;
13661 input_line_pointer = name;
13662 obj_elf_section (0);
13663 input_line_pointer = saved_input_line_pointer;
13664}
13665
13666/* Cenerate and deferred unwind frame offset. */
13667
13668static void
13669flush_pending_unwind (void)
13670{
13671 offsetT offset;
13672
13673 offset = unwind.pending_offset;
13674 unwind.pending_offset = 0;
13675 if (offset != 0)
13676 add_unwind_adjustsp (offset);
13677}
13678
13679/* Add an opcode to this list for this function. Two-byte opcodes should
13680 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13681 order. */
13682
13683static void
13684add_unwind_opcode (valueT op, int length)
13685{
13686 /* Add any deferred stack adjustment. */
13687 if (unwind.pending_offset)
13688 flush_pending_unwind ();
13689
13690 unwind.sp_restored = 0;
13691
13692 if (unwind.opcode_count + length > unwind.opcode_alloc)
13693 {
13694 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13695 if (unwind.opcodes)
13696 unwind.opcodes = xrealloc (unwind.opcodes,
13697 unwind.opcode_alloc);
13698 else
13699 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13700 }
13701 while (length > 0)
13702 {
13703 length--;
13704 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13705 op >>= 8;
13706 unwind.opcode_count++;
13707 }
13708}
13709
13710/* Add unwind opcodes to adjust the stack pointer. */
13711
13712static void
13713add_unwind_adjustsp (offsetT offset)
13714{
13715 valueT op;
13716
13717 if (offset > 0x200)
13718 {
13719 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13720 char bytes[5];
13721 int n;
13722 valueT o;
13723
13724 /* Long form: 0xb2, uleb128. */
13725 /* This might not fit in a word so add the individual bytes,
13726 remembering the list is built in reverse order. */
13727 o = (valueT) ((offset - 0x204) >> 2);
13728 if (o == 0)
13729 add_unwind_opcode (0, 1);
13730
13731 /* Calculate the uleb128 encoding of the offset. */
13732 n = 0;
13733 while (o)
13734 {
13735 bytes[n] = o & 0x7f;
13736 o >>= 7;
13737 if (o)
13738 bytes[n] |= 0x80;
13739 n++;
13740 }
13741 /* Add the insn. */
13742 for (; n; n--)
13743 add_unwind_opcode (bytes[n - 1], 1);
13744 add_unwind_opcode (0xb2, 1);
13745 }
13746 else if (offset > 0x100)
13747 {
13748 /* Two short opcodes. */
13749 add_unwind_opcode (0x3f, 1);
13750 op = (offset - 0x104) >> 2;
13751 add_unwind_opcode (op, 1);
13752 }
13753 else if (offset > 0)
13754 {
13755 /* Short opcode. */
13756 op = (offset - 4) >> 2;
13757 add_unwind_opcode (op, 1);
13758 }
13759 else if (offset < 0)
13760 {
13761 offset = -offset;
13762 while (offset > 0x100)
13763 {
13764 add_unwind_opcode (0x7f, 1);
13765 offset -= 0x100;
13766 }
13767 op = ((offset - 4) >> 2) | 0x40;
13768 add_unwind_opcode (op, 1);
13769 }
13770}
13771
13772/* Finish the list of unwind opcodes for this function. */
13773static void
13774finish_unwind_opcodes (void)
13775{
13776 valueT op;
13777
13778 if (unwind.fp_used)
13779 {
13780 /* Adjust sp as neccessary. */
13781 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13782 flush_pending_unwind ();
13783
13784 /* After restoring sp from the frame pointer. */
13785 op = 0x90 | unwind.fp_reg;
13786 add_unwind_opcode (op, 1);
13787 }
13788 else
13789 flush_pending_unwind ();
13790}
13791
13792
13793/* Start an exception table entry. If idx is nonzero this is an index table
13794 entry. */
13795
13796static void
13797start_unwind_section (const segT text_seg, int idx)
13798{
13799 const char * text_name;
13800 const char * prefix;
13801 const char * prefix_once;
13802 size_t prefix_len;
13803 size_t text_len;
13804 char * sec_name;
13805 size_t sec_name_len;
13806
13807 if (idx)
13808 {
13809 prefix = ELF_STRING_ARM_unwind;
13810 prefix_once = ELF_STRING_ARM_unwind_once;
13811 }
13812 else
13813 {
13814 prefix = ELF_STRING_ARM_unwind_info;
13815 prefix_once = ELF_STRING_ARM_unwind_info_once;
13816 }
13817
13818 text_name = segment_name (text_seg);
13819 if (streq (text_name, ".text"))
13820 text_name = "";
13821
13822 if (strncmp (text_name, ".gnu.linkonce.t.",
13823 strlen (".gnu.linkonce.t.")) == 0)
13824 {
13825 prefix = prefix_once;
13826 text_name += strlen (".gnu.linkonce.t.");
13827 }
13828
13829 prefix_len = strlen (prefix);
13830 text_len = strlen (text_name);
13831 sec_name_len = prefix_len + text_len;
13832 sec_name = alloca (sec_name_len + 1);
13833 memcpy (sec_name, prefix, prefix_len);
13834 memcpy (sec_name + prefix_len, text_name, text_len);
13835 sec_name[prefix_len + text_len] = '\0';
13836
13837 /* Handle COMDAT group. */
13838 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13839 {
13840 char *section;
13841 size_t len, group_name_len;
13842 const char *group_name = elf_group_name (text_seg);
13843
13844 if (group_name == NULL)
13845 {
13846 as_bad ("Group section `%s' has no group signature",
13847 segment_name (text_seg));
13848 ignore_rest_of_line ();
13849 return;
13850 }
13851 /* We have to construct a fake section directive. */
13852 group_name_len = strlen (group_name);
13853 if (idx)
13854 prefix_len = 13;
13855 else
13856 prefix_len = 16;
13857
13858 len = (sec_name_len
13859 + prefix_len /* ,"aG",%sectiontype, */
13860 + group_name_len /* ,group_name */
13861 + 7); /* ,comdat */
13862
13863 section = alloca (len + 1);
13864 memcpy (section, sec_name, sec_name_len);
13865 if (idx)
13866 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13867 else
13868 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13869 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13870 memcpy (section + len - 7, ",comdat", 7);
13871 section [len] = '\0';
13872 set_section (section);
13873 }
13874 else
13875 {
13876 set_section (sec_name);
13877 bfd_set_section_flags (stdoutput, now_seg,
13878 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13879 }
13880
13881 /* Set the setion link for index tables. */
13882 if (idx)
13883 elf_linked_to_section (now_seg) = text_seg;
13884}
13885
13886
13887/* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13888 personality routine data. Returns zero, or the index table value for
13889 and inline entry. */
13890
13891static valueT
13892create_unwind_entry (int have_data)
13893{
13894 int size;
13895 addressT where;
13896 unsigned char *ptr;
13897 /* The current word of data. */
13898 valueT data;
13899 /* The number of bytes left in this word. */
13900 int n;
13901
13902 finish_unwind_opcodes ();
13903
13904 /* Remember the current text section. */
13905 unwind.saved_seg = now_seg;
13906 unwind.saved_subseg = now_subseg;
13907
13908 start_unwind_section (now_seg, 0);
13909
13910 if (unwind.personality_routine == NULL)
13911 {
13912 if (unwind.personality_index == -2)
13913 {
13914 if (have_data)
13915 as_bad (_("handerdata in cantunwind frame"));
13916 return 1; /* EXIDX_CANTUNWIND. */
13917 }
13918
13919 /* Use a default personality routine if none is specified. */
13920 if (unwind.personality_index == -1)
13921 {
13922 if (unwind.opcode_count > 3)
13923 unwind.personality_index = 1;
13924 else
13925 unwind.personality_index = 0;
13926 }
13927
13928 /* Space for the personality routine entry. */
13929 if (unwind.personality_index == 0)
13930 {
13931 if (unwind.opcode_count > 3)
13932 as_bad (_("too many unwind opcodes for personality routine 0"));
13933
13934 if (!have_data)
13935 {
13936 /* All the data is inline in the index table. */
13937 data = 0x80;
13938 n = 3;
13939 while (unwind.opcode_count > 0)
13940 {
13941 unwind.opcode_count--;
13942 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13943 n--;
13944 }
13945
13946 /* Pad with "finish" opcodes. */
13947 while (n--)
13948 data = (data << 8) | 0xb0;
13949
13950 return data;
13951 }
13952 size = 0;
13953 }
13954 else
13955 /* We get two opcodes "free" in the first word. */
13956 size = unwind.opcode_count - 2;
13957 }
13958 else
13959 /* An extra byte is required for the opcode count. */
13960 size = unwind.opcode_count + 1;
13961
13962 size = (size + 3) >> 2;
13963 if (size > 0xff)
13964 as_bad (_("too many unwind opcodes"));
13965
13966 frag_align (2, 0, 0);
13967 record_alignment (now_seg, 2);
13968 unwind.table_entry = expr_build_dot ();
13969
13970 /* Allocate the table entry. */
13971 ptr = frag_more ((size << 2) + 4);
13972 where = frag_now_fix () - ((size << 2) + 4);
13973
13974 switch (unwind.personality_index)
13975 {
13976 case -1:
13977 /* ??? Should this be a PLT generating relocation? */
13978 /* Custom personality routine. */
13979 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13980 BFD_RELOC_ARM_PREL31);
13981 where += 4;
13982 ptr += 4;
13983
13984 /* Set the first byte to the number of additional words. */
13985 data = size - 1;
13986 n = 3;
13987 break;
13988
13989 /* ABI defined personality routines. */
13990 /* TODO: Emit R_ARM_NONE to the personality routine. */
13991 case 0:
13992 /* Three opcodes bytes are packed into the first word. */
13993 data = 0x80;
13994 n = 3;
13995 break;
13996
13997 case 1:
13998 case 2:
13999 /* The size and first two opcode bytes go in the first word. */
14000 data = ((0x80 + unwind.personality_index) << 8) | size;
14001 n = 2;
14002 break;
14003
14004 default:
14005 /* Should never happen. */
14006 abort ();
14007 }
14008
14009 /* Pack the opcodes into words (MSB first), reversing the list at the same
14010 time. */
14011 while (unwind.opcode_count > 0)
14012 {
14013 if (n == 0)
14014 {
14015 md_number_to_chars (ptr, data, 4);
14016 ptr += 4;
14017 n = 4;
14018 data = 0;
14019 }
14020 unwind.opcode_count--;
14021 n--;
14022 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14023 }
14024
14025 /* Finish off the last word. */
14026 if (n < 4)
14027 {
14028 /* Pad with "finish" opcodes. */
14029 while (n--)
14030 data = (data << 8) | 0xb0;
14031
14032 md_number_to_chars (ptr, data, 4);
14033 }
14034
14035 if (!have_data)
14036 {
14037 /* Add an empty descriptor if there is no user-specified data. */
14038 ptr = frag_more (4);
14039 md_number_to_chars (ptr, 0, 4);
14040 }
14041
14042 return 0;
14043}
14044
14045
14046/* Parse an unwind_fnstart directive. Simply records the current location. */
14047
14048static void
14049s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14050{
14051 demand_empty_rest_of_line ();
14052 /* Mark the start of the function. */
14053 unwind.proc_start = expr_build_dot ();
14054
14055 /* Reset the rest of the unwind info. */
14056 unwind.opcode_count = 0;
14057 unwind.table_entry = NULL;
14058 unwind.personality_routine = NULL;
14059 unwind.personality_index = -1;
14060 unwind.frame_size = 0;
14061 unwind.fp_offset = 0;
14062 unwind.fp_reg = 13;
14063 unwind.fp_used = 0;
14064 unwind.sp_restored = 0;
14065}
14066
14067
14068/* Parse a handlerdata directive. Creates the exception handling table entry
14069 for the function. */
14070
14071static void
14072s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14073{
14074 demand_empty_rest_of_line ();
14075 if (unwind.table_entry)
14076 as_bad (_("dupicate .handlerdata directive"));
14077
14078 create_unwind_entry (1);
14079}
14080
14081/* Parse an unwind_fnend directive. Generates the index table entry. */
14082
14083static void
14084s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14085{
14086 long where;
14087 unsigned char *ptr;
14088 valueT val;
14089
14090 demand_empty_rest_of_line ();
14091
14092 /* Add eh table entry. */
14093 if (unwind.table_entry == NULL)
14094 val = create_unwind_entry (0);
14095 else
14096 val = 0;
14097
14098 /* Add index table entry. This is two words. */
14099 start_unwind_section (unwind.saved_seg, 1);
14100 frag_align (2, 0, 0);
14101 record_alignment (now_seg, 2);
14102
14103 ptr = frag_more (8);
14104 where = frag_now_fix () - 8;
14105
14106 /* Self relative offset of the function start. */
14107 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14108 BFD_RELOC_32);
14109
14110 if (val)
14111 /* Inline exception table entry. */
14112 md_number_to_chars (ptr + 4, val, 4);
14113 else
14114 /* Self relative offset of the table entry. */
14115 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14116 BFD_RELOC_ARM_PREL31);
14117
14118 /* Restore the original section. */
14119 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14120}
14121
14122
14123/* Parse an unwind_cantunwind directive. */
14124
14125static void
14126s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14127{
14128 demand_empty_rest_of_line ();
14129 if (unwind.personality_routine || unwind.personality_index != -1)
14130 as_bad (_("personality routine specified for cantunwind frame"));
14131
14132 unwind.personality_index = -2;
14133}
14134
14135
14136/* Parse a personalityindex directive. */
14137
14138static void
14139s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14140{
14141 expressionS exp;
14142
14143 if (unwind.personality_routine || unwind.personality_index != -1)
14144 as_bad (_("duplicate .personalityindex directive"));
14145
14146 SKIP_WHITESPACE ();
14147
14148 expression (&exp);
14149
14150 if (exp.X_op != O_constant
14151 || exp.X_add_number < 0 || exp.X_add_number > 15)
14152 {
14153 as_bad (_("bad personality routine number"));
14154 ignore_rest_of_line ();
14155 return;
14156 }
14157
14158 unwind.personality_index = exp.X_add_number;
14159
14160 demand_empty_rest_of_line ();
14161}
14162
14163
14164/* Parse a personality directive. */
14165
14166static void
14167s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14168{
14169 char *name, *p, c;
14170
14171 if (unwind.personality_routine || unwind.personality_index != -1)
14172 as_bad (_("duplicate .personality directive"));
14173
14174 SKIP_WHITESPACE ();
14175 name = input_line_pointer;
14176 c = get_symbol_end ();
14177 p = input_line_pointer;
14178 unwind.personality_routine = symbol_find_or_make (name);
14179 *p = c;
14180 SKIP_WHITESPACE ();
14181 demand_empty_rest_of_line ();
14182}
14183
14184
14185/* Parse a directive saving core registers. */
14186
14187static void
14188s_arm_unwind_save_core (void)
14189{
14190 valueT op;
14191 long range;
14192 int n;
14193
14194 SKIP_WHITESPACE ();
14195 range = reg_list (&input_line_pointer);
14196 if (range == FAIL)
14197 {
14198 as_bad (_("expected register list"));
14199 ignore_rest_of_line ();
14200 return;
14201 }
14202
14203 demand_empty_rest_of_line ();
14204
14205 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14206 into .unwind_save {..., sp...}. We aren't bothered about the value of
14207 ip because it is clobbered by calls. */
14208 if (unwind.sp_restored && unwind.fp_reg == 12
14209 && (range & 0x3000) == 0x1000)
14210 {
14211 unwind.opcode_count--;
14212 unwind.sp_restored = 0;
14213 range = (range | 0x2000) & ~0x1000;
14214 unwind.pending_offset = 0;
14215 }
14216
14217 /* See if we can use the short opcodes. These pop a block of upto 8
14218 registers starting with r4, plus maybe r14. */
14219 for (n = 0; n < 8; n++)
14220 {
14221 /* Break at the first non-saved register. */
14222 if ((range & (1 << (n + 4))) == 0)
14223 break;
14224 }
14225 /* See if there are any other bits set. */
14226 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14227 {
14228 /* Use the long form. */
14229 op = 0x8000 | ((range >> 4) & 0xfff);
14230 add_unwind_opcode (op, 2);
14231 }
14232 else
14233 {
14234 /* Use the short form. */
14235 if (range & 0x4000)
14236 op = 0xa8; /* Pop r14. */
14237 else
14238 op = 0xa0; /* Do not pop r14. */
14239 op |= (n - 1);
14240 add_unwind_opcode (op, 1);
14241 }
14242
14243 /* Pop r0-r3. */
14244 if (range & 0xf)
14245 {
14246 op = 0xb100 | (range & 0xf);
14247 add_unwind_opcode (op, 2);
14248 }
14249
14250 /* Record the number of bytes pushed. */
14251 for (n = 0; n < 16; n++)
14252 {
14253 if (range & (1 << n))
14254 unwind.frame_size += 4;
14255 }
14256}
14257
14258
14259/* Parse a directive saving FPA registers. */
14260
14261static void
14262s_arm_unwind_save_fpa (int reg)
14263{
14264 expressionS exp;
14265 int num_regs;
14266 valueT op;
14267
14268 /* Get Number of registers to transfer. */
14269 if (skip_past_comma (&input_line_pointer) != FAIL)
14270 expression (&exp);
14271 else
14272 exp.X_op = O_illegal;
14273
14274 if (exp.X_op != O_constant)
14275 {
14276 as_bad (_("expected , <constant>"));
14277 ignore_rest_of_line ();
14278 return;
14279 }
14280
14281 num_regs = exp.X_add_number;
14282
14283 if (num_regs < 1 || num_regs > 4)
14284 {
14285 as_bad (_("number of registers must be in the range [1:4]"));
14286 ignore_rest_of_line ();
14287 return;
14288 }
14289
14290 demand_empty_rest_of_line ();
14291
14292 if (reg == 4)
14293 {
14294 /* Short form. */
14295 op = 0xb4 | (num_regs - 1);
14296 add_unwind_opcode (op, 1);
14297 }
14298 else
14299 {
14300 /* Long form. */
14301 op = 0xc800 | (reg << 4) | (num_regs - 1);
14302 add_unwind_opcode (op, 2);
14303 }
14304 unwind.frame_size += num_regs * 12;
14305}
14306
14307
14308/* Parse a directive saving VFP registers. */
14309
14310static void
14311s_arm_unwind_save_vfp (void)
14312{
14313 int count;
14314 int reg;
14315 valueT op;
14316
14317 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14318 if (count == FAIL)
14319 {
14320 as_bad (_("expected register list"));
14321 ignore_rest_of_line ();
14322 return;
14323 }
14324
14325 demand_empty_rest_of_line ();
14326
14327 if (reg == 8)
14328 {
14329 /* Short form. */
14330 op = 0xb8 | (count - 1);
14331 add_unwind_opcode (op, 1);
14332 }
14333 else
14334 {
14335 /* Long form. */
14336 op = 0xb300 | (reg << 4) | (count - 1);
14337 add_unwind_opcode (op, 2);
14338 }
14339 unwind.frame_size += count * 8 + 4;
14340}
14341
14342
14343/* Parse a directive saving iWMMXt registers. */
14344
14345static void
14346s_arm_unwind_save_wmmx (void)
14347{
14348 int reg;
14349 int hi_reg;
14350 int i;
14351 unsigned wcg_mask;
14352 unsigned wr_mask;
14353 valueT op;
14354
14355 if (*input_line_pointer == '{')
14356 input_line_pointer++;
14357
14358 wcg_mask = 0;
14359 wr_mask = 0;
14360 do
14361 {
14362 reg = arm_reg_parse (&input_line_pointer,
14363 all_reg_maps[REG_TYPE_IWMMXT].htab);
14364
14365 if (wr_register (reg))
14366 {
14367 i = reg & ~WR_PREFIX;
14368 if (wr_mask >> i)
14369 as_tsktsk (_("register list not in ascending order"));
14370 wr_mask |= 1 << i;
14371 }
14372 else if (wcg_register (reg))
14373 {
14374 i = (reg & ~WC_PREFIX) - 8;
14375 if (wcg_mask >> i)
14376 as_tsktsk (_("register list not in ascending order"));
14377 wcg_mask |= 1 << i;
14378 }
14379 else
14380 {
14381 as_bad (_("expected wr or wcgr"));
14382 goto error;
14383 }
14384
14385 SKIP_WHITESPACE ();
14386 if (*input_line_pointer == '-')
14387 {
14388 hi_reg = arm_reg_parse (&input_line_pointer,
14389 all_reg_maps[REG_TYPE_IWMMXT].htab);
14390 if (wr_register (reg) && wr_register (hi_reg))
14391 {
14392 for (; reg < hi_reg; reg++)
14393 wr_mask |= 1 << (reg & ~WR_PREFIX);
14394 }
14395 else if (wcg_register (reg) && wcg_register (hi_reg))
14396 {
14397 for (; reg < hi_reg; reg++)
14398 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14399 }
14400 else
14401 {
14402 as_bad (_("bad register range"));
14403 goto error;
14404 }
14405 }
14406 }
14407 while (skip_past_comma (&input_line_pointer) != FAIL);
14408
14409 SKIP_WHITESPACE ();
14410 if (*input_line_pointer == '}')
14411 input_line_pointer++;
14412
14413 demand_empty_rest_of_line ();
14414
14415 if (wr_mask && wcg_mask)
14416 {
14417 as_bad (_("inconsistent register types"));
14418 goto error;
14419 }
14420
14421 /* Generate any deferred opcodes becuuse we're going to be looking at
14422 the list. */
14423 flush_pending_unwind ();
14424
14425 if (wcg_mask)
14426 {
14427 for (i = 0; i < 16; i++)
14428 {
14429 if (wcg_mask & (1 << i))
14430 unwind.frame_size += 4;
14431 }
14432 op = 0xc700 | wcg_mask;
14433 add_unwind_opcode (op, 2);
14434 }
14435 else
14436 {
14437 for (i = 0; i < 16; i++)
14438 {
14439 if (wr_mask & (1 << i))
14440 unwind.frame_size += 8;
14441 }
14442 /* Attempt to combine with a previous opcode. We do this because gcc
14443 likes to output separate unwind directives for a single block of
14444 registers. */
14445 if (unwind.opcode_count > 0)
14446 {
14447 i = unwind.opcodes[unwind.opcode_count - 1];
14448 if ((i & 0xf8) == 0xc0)
14449 {
14450 i &= 7;
14451 /* Only merge if the blocks are contiguous. */
14452 if (i < 6)
14453 {
14454 if ((wr_mask & 0xfe00) == (1 << 9))
14455 {
14456 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14457 unwind.opcode_count--;
14458 }
14459 }
14460 else if (i == 6 && unwind.opcode_count >= 2)
14461 {
14462 i = unwind.opcodes[unwind.opcode_count - 2];
14463 reg = i >> 4;
14464 i &= 0xf;
14465
14466 op = 0xffff << (reg - 1);
14467 if (reg > 0
14468 || ((wr_mask & op) == (1u << (reg - 1))))
14469 {
14470 op = (1 << (reg + i + 1)) - 1;
14471 op &= ~((1 << reg) - 1);
14472 wr_mask |= op;
14473 unwind.opcode_count -= 2;
14474 }
14475 }
14476 }
14477 }
14478
14479 hi_reg = 15;
14480 /* We want to generate opcodes in the order the registers have been
14481 saved, ie. descending order. */
14482 for (reg = 15; reg >= -1; reg--)
14483 {
14484 /* Save registers in blocks. */
14485 if (reg < 0
14486 || !(wr_mask & (1 << reg)))
14487 {
14488 /* We found an unsaved reg. Generate opcodes to save the
14489 preceeding block. */
14490 if (reg != hi_reg)
14491 {
14492 if (reg == 9)
14493 {
14494 /* Short form. */
14495 op = 0xc0 | (hi_reg - 10);
14496 add_unwind_opcode (op, 1);
14497 }
14498 else
14499 {
14500 /* Long form. */
14501 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14502 add_unwind_opcode (op, 2);
14503 }
14504 }
14505 hi_reg = reg - 1;
14506 }
14507 }
14508 }
14509 return;
14510error:
14511 ignore_rest_of_line ();
14512}
14513
14514
14515/* Parse an unwind_save directive. */
14516
14517static void
14518s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14519{
14520 char *saved_ptr;
14521 int reg;
14522
14523 /* Figure out what sort of save we have. */
14524 SKIP_WHITESPACE ();
14525 saved_ptr = input_line_pointer;
14526
14527 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14528 if (reg != FAIL)
14529 {
14530 s_arm_unwind_save_fpa (reg);
14531 return;
14532 }
14533
14534 if (*input_line_pointer == '{')
14535 input_line_pointer++;
14536
14537 SKIP_WHITESPACE ();
14538
14539 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14540 if (reg != FAIL)
14541 {
14542 input_line_pointer = saved_ptr;
14543 s_arm_unwind_save_core ();
14544 return;
14545 }
14546
14547 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14548 if (reg != FAIL)
14549 {
14550 input_line_pointer = saved_ptr;
14551 s_arm_unwind_save_vfp ();
14552 return;
14553 }
14554
14555 reg = arm_reg_parse (&input_line_pointer,
14556 all_reg_maps[REG_TYPE_IWMMXT].htab);
14557 if (reg != FAIL)
14558 {
14559 input_line_pointer = saved_ptr;
14560 s_arm_unwind_save_wmmx ();
14561 return;
14562 }
14563
14564 /* TODO: Maverick registers. */
14565 as_bad (_("unrecognised register"));
14566}
14567
14568
14569/* Parse an unwind_movsp directive. */
14570
14571static void
14572s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14573{
14574 int reg;
14575 valueT op;
14576
14577 SKIP_WHITESPACE ();
14578 reg = reg_required_here (&input_line_pointer, -1);
14579 if (reg == FAIL)
14580 {
14581 as_bad (_("ARM register expected"));
14582 ignore_rest_of_line ();
14583 return;
14584 }
14585
14586 if (reg == 13 || reg == 15)
14587 {
14588 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14589 ignore_rest_of_line ();
14590 return;
14591 }
14592
14593 if (unwind.fp_reg != 13)
14594 as_bad (_("unexpected .unwind_movsp directive"));
14595
14596 /* Generate opcode to restore the value. */
14597 op = 0x90 | reg;
14598 add_unwind_opcode (op, 1);
14599
14600 /* Record the information for later. */
14601 unwind.fp_reg = reg;
14602 unwind.fp_offset = unwind.frame_size;
14603 unwind.sp_restored = 1;
14604 demand_empty_rest_of_line ();
14605}
14606
14607
14608/* Parse #<number>. */
14609
14610static int
14611require_hashconst (int * val)
14612{
14613 expressionS exp;
14614
14615 SKIP_WHITESPACE ();
14616 if (*input_line_pointer == '#')
14617 {
14618 input_line_pointer++;
14619 expression (&exp);
14620 }
14621 else
14622 exp.X_op = O_illegal;
14623
14624 if (exp.X_op != O_constant)
14625 {
14626 as_bad (_("expected #constant"));
14627 ignore_rest_of_line ();
14628 return FAIL;
14629 }
14630 *val = exp.X_add_number;
14631 return SUCCESS;
14632}
14633
14634/* Parse an unwind_pad directive. */
14635
14636static void
14637s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14638{
14639 int offset;
14640
14641 if (require_hashconst (&offset) == FAIL)
14642 return;
14643
14644 if (offset & 3)
14645 {
14646 as_bad (_("stack increment must be multiple of 4"));
14647 ignore_rest_of_line ();
14648 return;
14649 }
14650
14651 /* Don't generate any opcodes, just record the details for later. */
14652 unwind.frame_size += offset;
14653 unwind.pending_offset += offset;
14654
14655 demand_empty_rest_of_line ();
14656}
14657
14658/* Parse an unwind_setfp directive. */
14659
14660static void
14661s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14662{
14663 int sp_reg;
14664 int fp_reg;
14665 int offset;
14666
14667 fp_reg = reg_required_here (&input_line_pointer, -1);
14668 if (skip_past_comma (&input_line_pointer) == FAIL)
14669 sp_reg = FAIL;
14670 else
14671 sp_reg = reg_required_here (&input_line_pointer, -1);
14672
14673 if (fp_reg == FAIL || sp_reg == FAIL)
14674 {
14675 as_bad (_("expected <reg>, <reg>"));
14676 ignore_rest_of_line ();
14677 return;
14678 }
14679
14680 /* Optonal constant. */
14681 if (skip_past_comma (&input_line_pointer) != FAIL)
14682 {
14683 if (require_hashconst (&offset) == FAIL)
14684 return;
14685 }
14686 else
14687 offset = 0;
14688
14689 demand_empty_rest_of_line ();
14690
14691 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14692 {
14693 as_bad (_("register must be either sp or set by a previous"
14694 "unwind_movsp directive"));
14695 return;
14696 }
14697
14698 /* Don't generate any opcodes, just record the information for later. */
14699 unwind.fp_reg = fp_reg;
14700 unwind.fp_used = 1;
14701 if (sp_reg == 13)
14702 unwind.fp_offset = unwind.frame_size - offset;
14703 else
14704 unwind.fp_offset -= offset;
14705}
14706
14707/* Parse an unwind_raw directive. */
14708
14709static void
14710s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14711{
14712 expressionS exp;
14713 /* This is an arbitary limit. */
14714 unsigned char op[16];
14715 int count;
14716
14717 SKIP_WHITESPACE ();
14718 expression (&exp);
14719 if (exp.X_op == O_constant
14720 && skip_past_comma (&input_line_pointer) != FAIL)
14721 {
14722 unwind.frame_size += exp.X_add_number;
14723 expression (&exp);
14724 }
14725 else
14726 exp.X_op = O_illegal;
14727
14728 if (exp.X_op != O_constant)
14729 {
14730 as_bad (_("expected <offset>, <opcode>"));
14731 ignore_rest_of_line ();
14732 return;
14733 }
14734
14735 count = 0;
14736
14737 /* Parse the opcode. */
14738 for (;;)
14739 {
14740 if (count >= 16)
14741 {
14742 as_bad (_("unwind opcode too long"));
14743 ignore_rest_of_line ();
14744 }
14745 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14746 {
14747 as_bad (_("invalid unwind opcode"));
14748 ignore_rest_of_line ();
14749 return;
14750 }
14751 op[count++] = exp.X_add_number;
14752
14753 /* Parse the next byte. */
14754 if (skip_past_comma (&input_line_pointer) == FAIL)
14755 break;
14756
14757 expression (&exp);
14758 }
14759
14760 /* Add the opcode bytes in reverse order. */
14761 while (count--)
14762 add_unwind_opcode (op[count], 1);
14763
14764 demand_empty_rest_of_line ();
14765}
eb043451 14766
b99bd4ef
NC
14767#endif /* OBJ_ELF */
14768
14769/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14770 of an rs_align_code fragment. */
14771
14772void
a737bd4d 14773arm_handle_align (fragS * fragP)
b99bd4ef
NC
14774{
14775 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14776 static char const thumb_noop[2] = { 0xc0, 0x46 };
14777 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14778 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14779
14780 int bytes, fix, noop_size;
14781 char * p;
14782 const char * noop;
cc8a6dd0 14783
b99bd4ef
NC
14784 if (fragP->fr_type != rs_align_code)
14785 return;
14786
14787 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14788 p = fragP->fr_literal + fragP->fr_fix;
14789 fix = 0;
cc8a6dd0 14790
b99bd4ef
NC
14791 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14792 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14793
b99bd4ef
NC
14794 if (fragP->tc_frag_data)
14795 {
14796 if (target_big_endian)
14797 noop = thumb_bigend_noop;
14798 else
14799 noop = thumb_noop;
14800 noop_size = sizeof (thumb_noop);
14801 }
14802 else
14803 {
14804 if (target_big_endian)
14805 noop = arm_bigend_noop;
14806 else
14807 noop = arm_noop;
14808 noop_size = sizeof (arm_noop);
14809 }
cc8a6dd0 14810
b99bd4ef
NC
14811 if (bytes & (noop_size - 1))
14812 {
14813 fix = bytes & (noop_size - 1);
14814 memset (p, 0, fix);
14815 p += fix;
14816 bytes -= fix;
14817 }
14818
14819 while (bytes >= noop_size)
14820 {
14821 memcpy (p, noop, noop_size);
14822 p += noop_size;
14823 bytes -= noop_size;
14824 fix += noop_size;
14825 }
cc8a6dd0 14826
b99bd4ef
NC
14827 fragP->fr_fix += fix;
14828 fragP->fr_var = noop_size;
14829}
14830
14831/* Called from md_do_align. Used to create an alignment
14832 frag in a code section. */
14833
14834void
a737bd4d 14835arm_frag_align_code (int n, int max)
b99bd4ef
NC
14836{
14837 char * p;
14838
2d2255b5 14839 /* We assume that there will never be a requirement
b99bd4ef
NC
14840 to support alignments greater than 32 bytes. */
14841 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14842 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14843
b99bd4ef
NC
14844 p = frag_var (rs_align_code,
14845 MAX_MEM_FOR_RS_ALIGN_CODE,
14846 1,
14847 (relax_substateT) max,
14848 (symbolS *) NULL,
14849 (offsetT) n,
14850 (char *) NULL);
14851 *p = 0;
b99bd4ef
NC
14852}
14853
14854/* Perform target specific initialisation of a frag. */
14855
14856void
a737bd4d 14857arm_init_frag (fragS * fragP)
b99bd4ef
NC
14858{
14859 /* Record whether this frag is in an ARM or a THUMB area. */
14860 fragP->tc_frag_data = thumb_mode;
14861}
a737bd4d 14862
a394c00f
NC
14863#ifdef OBJ_ELF
14864
14865/* Convert REGNAME to a DWARF-2 register number. */
14866
14867int
14868tc_arm_regname_to_dw2regnum (const char *regname)
14869{
14870 unsigned int i;
14871
14872 for (i = 0; rn_table[i].name; i++)
14873 if (streq (regname, rn_table[i].name))
14874 return rn_table[i].number;
14875
14876 return -1;
14877}
14878
14879/* Initialize the DWARF-2 unwind information for this procedure. */
14880
14881void
14882tc_arm_frame_initial_instructions (void)
14883{
14884 cfi_add_CFA_def_cfa (REG_SP, 0);
14885}
14886#endif
14887
a737bd4d
NC
14888/* This table describes all the machine specific pseudo-ops the assembler
14889 has to support. The fields are:
14890 pseudo-op name without dot
14891 function to call to execute this pseudo-op
14892 Integer arg to pass to the function. */
14893
14894const pseudo_typeS md_pseudo_table[] =
14895{
14896 /* Never called because '.req' does not start a line. */
14897 { "req", s_req, 0 },
14898 { "unreq", s_unreq, 0 },
14899 { "bss", s_bss, 0 },
14900 { "align", s_align, 0 },
14901 { "arm", s_arm, 0 },
14902 { "thumb", s_thumb, 0 },
14903 { "code", s_code, 0 },
14904 { "force_thumb", s_force_thumb, 0 },
14905 { "thumb_func", s_thumb_func, 0 },
14906 { "thumb_set", s_thumb_set, 0 },
14907 { "even", s_even, 0 },
14908 { "ltorg", s_ltorg, 0 },
14909 { "pool", s_ltorg, 0 },
14910#ifdef OBJ_ELF
14911 { "word", s_arm_elf_cons, 4 },
14912 { "long", s_arm_elf_cons, 4 },
14913 { "rel31", s_arm_rel31, 0 },
7ed4c4c5
NC
14914 { "fnstart", s_arm_unwind_fnstart, 0 },
14915 { "fnend", s_arm_unwind_fnend, 0 },
14916 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14917 { "personality", s_arm_unwind_personality, 0 },
14918 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14919 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14920 { "save", s_arm_unwind_save, 0 },
14921 { "movsp", s_arm_unwind_movsp, 0 },
14922 { "pad", s_arm_unwind_pad, 0 },
14923 { "setfp", s_arm_unwind_setfp, 0 },
14924 { "unwind_raw", s_arm_unwind_raw, 0 },
a737bd4d
NC
14925#else
14926 { "word", cons, 4},
14927#endif
14928 { "extend", float_cons, 'x' },
14929 { "ldouble", float_cons, 'x' },
14930 { "packed", float_cons, 'p' },
14931 { 0, 0, 0 }
14932};
This page took 0.956057 seconds and 4 git commands to generate.