]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
* config/tc-xtensa.c (xtensa_switch_section_emit_state): Use subseg_set.
[thirdparty/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 140
b99bd4ef 141/* Flags stored in private area of BFD structure. */
b34976b6
AM
142static int uses_apcs_26 = FALSE;
143static int atpcs = FALSE;
144static int support_interwork = FALSE;
145static int uses_apcs_float = FALSE;
146static int pic_code = FALSE;
03b1477f
RE
147
148/* Variables that we set while parsing command-line options. Once all
149 options have been read we re-process these values to set the real
150 assembly flags. */
151static int legacy_cpu = -1;
152static int legacy_fpu = -1;
153
154static int mcpu_cpu_opt = -1;
155static int mcpu_fpu_opt = -1;
156static int march_cpu_opt = -1;
157static int march_fpu_opt = -1;
158static int mfpu_opt = -1;
33a392fb 159static int mfloat_abi_opt = -1;
7cc69913 160#ifdef OBJ_ELF
d507cf36 161static int meabi_flags = EF_ARM_EABI_UNKNOWN;
7cc69913 162#endif
b99bd4ef
NC
163
164/* This array holds the chars that always start a comment. If the
165 pre-processor is disabled, these aren't very useful. */
f57c81f6 166const char comment_chars[] = "@";
b99bd4ef
NC
167
168/* This array holds the chars that only start a comment at the beginning of
169 a line. If the line seems to have the form '# 123 filename'
170 .line and .file directives will appear in the pre-processed output. */
171/* Note that input_file.c hand checks for '#' at the beginning of the
172 first line of the input file. This is because the compiler outputs
173 #NO_APP at the beginning of its output. */
174/* Also note that comments like this one will always work. */
05d2d07e 175const char line_comment_chars[] = "#";
b99bd4ef 176
da89cce1 177const char line_separator_chars[] = ";";
b99bd4ef
NC
178
179/* Chars that can be used to separate mant
180 from exp in floating point numbers. */
05d2d07e 181const char EXP_CHARS[] = "eE";
b99bd4ef
NC
182
183/* Chars that mean this number is a floating point constant. */
184/* As in 0f12.456 */
185/* or 0d1.2345e12 */
186
05d2d07e 187const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
188
189/* Prefix characters that indicate the start of an immediate
190 value. */
191#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
192
193#ifdef OBJ_ELF
194/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
195symbolS * GOT_symbol;
196#endif
197
198/* Size of relocation record. */
05d2d07e 199const int md_reloc_size = 8;
b99bd4ef
NC
200
201/* 0: assemble for ARM,
202 1: assemble for Thumb,
203 2: assemble for Thumb even though target CPU does not support thumb
204 instructions. */
205static int thumb_mode = 0;
206
207typedef struct arm_fix
208{
209 int thumb_mode;
210} arm_fix_data;
211
212struct arm_it
213{
05d2d07e 214 const char * error;
b99bd4ef 215 unsigned long instruction;
b99bd4ef
NC
216 int size;
217 struct
218 {
219 bfd_reloc_code_real_type type;
220 expressionS exp;
221 int pc_rel;
222 } reloc;
223};
224
225struct arm_it inst;
226
227enum asm_shift_index
228{
229 SHIFT_LSL = 0,
230 SHIFT_LSR,
231 SHIFT_ASR,
232 SHIFT_ROR,
233 SHIFT_RRX
234};
235
236struct asm_shift_properties
237{
238 enum asm_shift_index index;
239 unsigned long bit_field;
240 unsigned int allows_0 : 1;
241 unsigned int allows_32 : 1;
242};
243
244static const struct asm_shift_properties shift_properties [] =
245{
246 { SHIFT_LSL, 0, 1, 0},
247 { SHIFT_LSR, 0x20, 0, 1},
248 { SHIFT_ASR, 0x40, 0, 1},
249 { SHIFT_ROR, 0x60, 0, 0},
250 { SHIFT_RRX, 0x60, 0, 0}
251};
252
253struct asm_shift_name
254{
255 const char * name;
256 const struct asm_shift_properties * properties;
257};
258
259static const struct asm_shift_name shift_names [] =
260{
261 { "asl", shift_properties + SHIFT_LSL },
262 { "lsl", shift_properties + SHIFT_LSL },
263 { "lsr", shift_properties + SHIFT_LSR },
264 { "asr", shift_properties + SHIFT_ASR },
265 { "ror", shift_properties + SHIFT_ROR },
266 { "rrx", shift_properties + SHIFT_RRX },
267 { "ASL", shift_properties + SHIFT_LSL },
268 { "LSL", shift_properties + SHIFT_LSL },
269 { "LSR", shift_properties + SHIFT_LSR },
270 { "ASR", shift_properties + SHIFT_ASR },
271 { "ROR", shift_properties + SHIFT_ROR },
272 { "RRX", shift_properties + SHIFT_RRX }
273};
274
09d92015 275/* Any kind of shift is accepted. */
b99bd4ef 276#define NO_SHIFT_RESTRICT 1
09d92015
MM
277/* The shift operand must be an immediate value, not a register. */
278#define SHIFT_IMMEDIATE 0
279/* The shift must be LSL or ASR and the operand must be an immediate. */
280#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
281/* The shift must be ASR and the operand must be an immediate. */
282#define SHIFT_ASR_IMMEDIATE 3
283/* The shift must be LSL and the operand must be an immediate. */
284#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
285
286#define NUM_FLOAT_VALS 8
287
05d2d07e 288const char * fp_const[] =
b99bd4ef
NC
289{
290 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
291};
292
293/* Number of littlenums required to hold an extended precision number. */
294#define MAX_LITTLENUMS 6
295
296LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
297
298#define FAIL (-1)
299#define SUCCESS (0)
300
bfae80f2
RE
301/* Whether a Co-processor load/store operation accepts write-back forms. */
302#define CP_WB_OK 1
303#define CP_NO_WB 0
304
b99bd4ef
NC
305#define SUFF_S 1
306#define SUFF_D 2
307#define SUFF_E 3
308#define SUFF_P 4
309
310#define CP_T_X 0x00008000
311#define CP_T_Y 0x00400000
312#define CP_T_Pre 0x01000000
313#define CP_T_UD 0x00800000
314#define CP_T_WB 0x00200000
315
316#define CONDS_BIT 0x00100000
317#define LOAD_BIT 0x00100000
b99bd4ef
NC
318
319#define DOUBLE_LOAD_FLAG 0x00000001
320
321struct asm_cond
322{
05d2d07e 323 const char * template;
b99bd4ef
NC
324 unsigned long value;
325};
326
b99bd4ef 327#define COND_ALWAYS 0xe0000000
90e4755a 328#define COND_MASK 0xf0000000
b99bd4ef 329
05d2d07e 330static const struct asm_cond conds[] =
b99bd4ef
NC
331{
332 {"eq", 0x00000000},
333 {"ne", 0x10000000},
334 {"cs", 0x20000000}, {"hs", 0x20000000},
335 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
336 {"mi", 0x40000000},
337 {"pl", 0x50000000},
338 {"vs", 0x60000000},
339 {"vc", 0x70000000},
340 {"hi", 0x80000000},
341 {"ls", 0x90000000},
342 {"ge", 0xa0000000},
343 {"lt", 0xb0000000},
344 {"gt", 0xc0000000},
345 {"le", 0xd0000000},
346 {"al", 0xe0000000},
347 {"nv", 0xf0000000}
348};
349
b99bd4ef
NC
350struct asm_psr
351{
b34976b6
AM
352 const char *template;
353 bfd_boolean cpsr;
b99bd4ef
NC
354 unsigned long field;
355};
356
2d2255b5 357/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
358#define SPSR_BIT (1 << 22)
359
360/* How many bits to shift the PSR_xxx bits up by. */
361#define PSR_SHIFT 16
362
363#define PSR_c (1 << 0)
364#define PSR_x (1 << 1)
365#define PSR_s (1 << 2)
366#define PSR_f (1 << 3)
367
05d2d07e 368static const struct asm_psr psrs[] =
b99bd4ef 369{
b34976b6
AM
370 {"CPSR", TRUE, PSR_c | PSR_f},
371 {"CPSR_all", TRUE, PSR_c | PSR_f},
372 {"SPSR", FALSE, PSR_c | PSR_f},
373 {"SPSR_all", FALSE, PSR_c | PSR_f},
374 {"CPSR_flg", TRUE, PSR_f},
375 {"CPSR_f", TRUE, PSR_f},
376 {"SPSR_flg", FALSE, PSR_f},
377 {"SPSR_f", FALSE, PSR_f},
378 {"CPSR_c", TRUE, PSR_c},
379 {"CPSR_ctl", TRUE, PSR_c},
380 {"SPSR_c", FALSE, PSR_c},
381 {"SPSR_ctl", FALSE, PSR_c},
382 {"CPSR_x", TRUE, PSR_x},
383 {"CPSR_s", TRUE, PSR_s},
384 {"SPSR_x", FALSE, PSR_x},
385 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 386 /* Combinations of flags. */
b34976b6
AM
387 {"CPSR_fs", TRUE, PSR_f | PSR_s},
388 {"CPSR_fx", TRUE, PSR_f | PSR_x},
389 {"CPSR_fc", TRUE, PSR_f | PSR_c},
390 {"CPSR_sf", TRUE, PSR_s | PSR_f},
391 {"CPSR_sx", TRUE, PSR_s | PSR_x},
392 {"CPSR_sc", TRUE, PSR_s | PSR_c},
393 {"CPSR_xf", TRUE, PSR_x | PSR_f},
394 {"CPSR_xs", TRUE, PSR_x | PSR_s},
395 {"CPSR_xc", TRUE, PSR_x | PSR_c},
396 {"CPSR_cf", TRUE, PSR_c | PSR_f},
397 {"CPSR_cs", TRUE, PSR_c | PSR_s},
398 {"CPSR_cx", TRUE, PSR_c | PSR_x},
399 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
400 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
401 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
402 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
403 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
404 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
405 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
406 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
407 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
408 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
409 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
410 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
411 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
412 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
413 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
414 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
415 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
416 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
417 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
418 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
419 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
420 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
421 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
422 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
423 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
424 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
425 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
426 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
427 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
428 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
429 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
430 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
431 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
432 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
433 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
434 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
435 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
436 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
437 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
438 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
439 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
440 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
441 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
442 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
443 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
444 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
445 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
446 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
447 {"SPSR_fs", FALSE, PSR_f | PSR_s},
448 {"SPSR_fx", FALSE, PSR_f | PSR_x},
449 {"SPSR_fc", FALSE, PSR_f | PSR_c},
450 {"SPSR_sf", FALSE, PSR_s | PSR_f},
451 {"SPSR_sx", FALSE, PSR_s | PSR_x},
452 {"SPSR_sc", FALSE, PSR_s | PSR_c},
453 {"SPSR_xf", FALSE, PSR_x | PSR_f},
454 {"SPSR_xs", FALSE, PSR_x | PSR_s},
455 {"SPSR_xc", FALSE, PSR_x | PSR_c},
456 {"SPSR_cf", FALSE, PSR_c | PSR_f},
457 {"SPSR_cs", FALSE, PSR_c | PSR_s},
458 {"SPSR_cx", FALSE, PSR_c | PSR_x},
459 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
460 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
461 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
462 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
463 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
464 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
465 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
466 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
467 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
468 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
469 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
470 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
471 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
472 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
473 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
474 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
475 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
476 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
477 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
478 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
479 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
480 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
481 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
482 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
483 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
484 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
485 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
486 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
487 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
488 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
489 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
490 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
491 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
492 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
493 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
494 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
495 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
496 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
497 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
498 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
499 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
500 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
501 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
502 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
503 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
504 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
505 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
506 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
507};
508
e16bb312
NC
509enum wreg_type
510 {
511 IWMMXT_REG_WR = 0,
512 IWMMXT_REG_WC = 1,
513 IWMMXT_REG_WR_OR_WC = 2,
514 IWMMXT_REG_WCG
515 };
516
517enum iwmmxt_insn_type
518{
519 check_rd,
520 check_wr,
521 check_wrwr,
522 check_wrwrwr,
523 check_wrwrwcg,
524 check_tbcst,
525 check_tmovmsk,
526 check_tmia,
527 check_tmcrr,
528 check_tmrrc,
529 check_tmcr,
530 check_tmrc,
531 check_tinsr,
532 check_textrc,
533 check_waligni,
534 check_textrm,
535 check_wshufh
536};
537
bfae80f2
RE
538enum vfp_dp_reg_pos
539{
540 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
541};
542
543enum vfp_sp_reg_pos
544{
545 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
546};
547
548enum vfp_ldstm_type
549{
550 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
551};
552
553/* VFP system registers. */
554struct vfp_reg
555{
556 const char *name;
557 unsigned long regno;
558};
559
cc8a6dd0 560static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
561{
562 {"fpsid", 0x00000000},
563 {"FPSID", 0x00000000},
564 {"fpscr", 0x00010000},
565 {"FPSCR", 0x00010000},
566 {"fpexc", 0x00080000},
567 {"FPEXC", 0x00080000}
568};
569
6c43fab6
RE
570/* Structure for a hash table entry for a register. */
571struct reg_entry
572{
573 const char * name;
574 int number;
0bbf2aa4 575 bfd_boolean builtin;
6c43fab6
RE
576};
577
e28cd48c 578/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
579#define REG_SP 13
580#define REG_LR 14
581#define REG_PC 15
582
e16bb312
NC
583#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
584#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
585#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
586
0bbf2aa4
NC
587/* These are the standard names. Users can add aliases with .req.
588 and delete them with .unreq. */
589
6c43fab6
RE
590/* Integer Register Numbers. */
591static const struct reg_entry rn_table[] =
592{
0bbf2aa4
NC
593 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
594 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
595 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
596 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 597 /* ATPCS Synonyms. */
0bbf2aa4
NC
598 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
599 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
600 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 601 /* Well-known aliases. */
0bbf2aa4
NC
602 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
603 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
604 {NULL, 0, TRUE}
6c43fab6
RE
605};
606
e16bb312
NC
607#define WR_PREFIX 0x200
608#define WC_PREFIX 0x400
609
610static const struct reg_entry iwmmxt_table[] =
611{
5a6c6817 612 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
613 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
614 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
615 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
616 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
617 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
618 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
619 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
620 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
621 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
622 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
623 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
624 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
625
626 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
627 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
628 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
629 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
630 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
631 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
632 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
633 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
634 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
635 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
636 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
637 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
638 {NULL, 0, TRUE}
e16bb312
NC
639};
640
6c43fab6
RE
641/* Co-processor Numbers. */
642static const struct reg_entry cp_table[] =
643{
0bbf2aa4
NC
644 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
645 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
646 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
647 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
648 {NULL, 0, TRUE}
6c43fab6
RE
649};
650
651/* Co-processor Register Numbers. */
652static const struct reg_entry cn_table[] =
653{
0bbf2aa4
NC
654 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
655 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
656 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
657 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 658 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
659 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
660 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
661 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
662 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
663 {NULL, 0, TRUE}
6c43fab6
RE
664};
665
666/* FPA Registers. */
667static const struct reg_entry fn_table[] =
668{
0bbf2aa4
NC
669 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
670 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
671 {NULL, 0, TRUE}
6c43fab6
RE
672};
673
bfae80f2
RE
674/* VFP SP Registers. */
675static const struct reg_entry sn_table[] =
676{
0bbf2aa4
NC
677 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
678 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
679 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
680 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
681 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
682 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
683 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
684 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
685 {NULL, 0, TRUE}
bfae80f2
RE
686};
687
688/* VFP DP Registers. */
689static const struct reg_entry dn_table[] =
690{
0bbf2aa4
NC
691 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
692 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
693 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
694 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
695 {NULL, 0, TRUE}
bfae80f2
RE
696};
697
63e63b07 698/* Maverick DSP coprocessor registers. */
6c43fab6
RE
699static const struct reg_entry mav_mvf_table[] =
700{
0bbf2aa4
NC
701 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
702 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
703 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
704 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
705 {NULL, 0, TRUE}
6c43fab6
RE
706};
707
708static const struct reg_entry mav_mvd_table[] =
709{
0bbf2aa4
NC
710 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
711 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
712 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
713 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
714 {NULL, 0, TRUE}
6c43fab6
RE
715};
716
717static const struct reg_entry mav_mvfx_table[] =
718{
0bbf2aa4
NC
719 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
720 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
721 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
722 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
723 {NULL, 0, TRUE}
6c43fab6
RE
724};
725
726static const struct reg_entry mav_mvdx_table[] =
727{
0bbf2aa4
NC
728 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
729 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
730 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
731 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
732 {NULL, 0, TRUE}
6c43fab6
RE
733};
734
735static const struct reg_entry mav_mvax_table[] =
736{
0bbf2aa4
NC
737 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
738 {NULL, 0, TRUE}
6c43fab6
RE
739};
740
741static const struct reg_entry mav_dspsc_table[] =
742{
0bbf2aa4
NC
743 {"dspsc", 0, TRUE},
744 {NULL, 0, TRUE}
6c43fab6
RE
745};
746
747struct reg_map
748{
a737bd4d
NC
749 const struct reg_entry * names;
750 int max_regno;
751 struct hash_control * htab;
752 const char * expected;
6c43fab6
RE
753};
754
755struct reg_map all_reg_maps[] =
756{
757 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
758 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
759 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 760 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
761 {sn_table, 31, NULL, N_("VFP single precision register expected")},
762 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
763 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
764 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
765 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 766 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
767 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
768 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 769 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
770};
771
772/* Enumeration matching entries in table above. */
773enum arm_reg_type
774{
775 REG_TYPE_RN = 0,
776#define REG_TYPE_FIRST REG_TYPE_RN
777 REG_TYPE_CP = 1,
778 REG_TYPE_CN = 2,
779 REG_TYPE_FN = 3,
bfae80f2
RE
780 REG_TYPE_SN = 4,
781 REG_TYPE_DN = 5,
782 REG_TYPE_MVF = 6,
783 REG_TYPE_MVD = 7,
784 REG_TYPE_MVFX = 8,
785 REG_TYPE_MVDX = 9,
786 REG_TYPE_MVAX = 10,
787 REG_TYPE_DSPSC = 11,
e16bb312 788 REG_TYPE_IWMMXT = 12,
bfae80f2 789
e16bb312 790 REG_TYPE_MAX = 13
6c43fab6 791};
404ff6b5 792
b99bd4ef
NC
793/* ARM instructions take 4bytes in the object file, Thumb instructions
794 take 2: */
795#define INSN_SIZE 4
796
404ff6b5 797/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 798#define MAV_MODE1 0x100c
404ff6b5
AH
799
800/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 801#define MAV_MODE2 0x0c10
404ff6b5 802
34920d91
NC
803/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
804#define MAV_MODE3 0x100c
404ff6b5
AH
805
806/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 807#define MAV_MODE4 0x0c0010
404ff6b5
AH
808
809/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 810#define MAV_MODE5 0x00100c
404ff6b5
AH
811
812/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 813#define MAV_MODE6 0x00100c05
b99bd4ef
NC
814
815struct asm_opcode
816{
817 /* Basic string to match. */
05d2d07e 818 const char * template;
b99bd4ef
NC
819
820 /* Basic instruction code. */
821 unsigned long value;
822
90e4755a
RE
823 /* Offset into the template where the condition code (if any) will be.
824 If zero, then the instruction is never conditional. */
825 unsigned cond_offset;
b99bd4ef 826
90e4755a
RE
827 /* Which architecture variant provides this instruction. */
828 unsigned long variant;
b99bd4ef
NC
829
830 /* Function to call to parse args. */
a737bd4d 831 void (* parms) (char *);
b99bd4ef
NC
832};
833
a737bd4d
NC
834/* Defines for various bits that we will want to toggle. */
835#define INST_IMMEDIATE 0x02000000
836#define OFFSET_REG 0x02000000
837#define HWOFFSET_IMM 0x00400000
838#define SHIFT_BY_REG 0x00000010
839#define PRE_INDEX 0x01000000
840#define INDEX_UP 0x00800000
841#define WRITE_BACK 0x00200000
842#define LDM_TYPE_2_OR_3 0x00400000
90e4755a 843
a737bd4d
NC
844#define LITERAL_MASK 0xf000f000
845#define OPCODE_MASK 0xfe1fffff
846#define V4_STR_BIT 0x00000020
90e4755a 847
a737bd4d 848#define DATA_OP_SHIFT 21
90e4755a 849
a737bd4d
NC
850/* Codes to distinguish the arithmetic instructions. */
851#define OPCODE_AND 0
852#define OPCODE_EOR 1
853#define OPCODE_SUB 2
854#define OPCODE_RSB 3
855#define OPCODE_ADD 4
856#define OPCODE_ADC 5
857#define OPCODE_SBC 6
858#define OPCODE_RSC 7
859#define OPCODE_TST 8
860#define OPCODE_TEQ 9
861#define OPCODE_CMP 10
862#define OPCODE_CMN 11
863#define OPCODE_ORR 12
864#define OPCODE_MOV 13
865#define OPCODE_BIC 14
866#define OPCODE_MVN 15
90e4755a 867
a737bd4d
NC
868#define T_OPCODE_MUL 0x4340
869#define T_OPCODE_TST 0x4200
870#define T_OPCODE_CMN 0x42c0
871#define T_OPCODE_NEG 0x4240
872#define T_OPCODE_MVN 0x43c0
90e4755a 873
a737bd4d
NC
874#define T_OPCODE_ADD_R3 0x1800
875#define T_OPCODE_SUB_R3 0x1a00
876#define T_OPCODE_ADD_HI 0x4400
877#define T_OPCODE_ADD_ST 0xb000
878#define T_OPCODE_SUB_ST 0xb080
879#define T_OPCODE_ADD_SP 0xa800
880#define T_OPCODE_ADD_PC 0xa000
881#define T_OPCODE_ADD_I8 0x3000
882#define T_OPCODE_SUB_I8 0x3800
883#define T_OPCODE_ADD_I3 0x1c00
884#define T_OPCODE_SUB_I3 0x1e00
b99bd4ef 885
a737bd4d
NC
886#define T_OPCODE_ASR_R 0x4100
887#define T_OPCODE_LSL_R 0x4080
888#define T_OPCODE_LSR_R 0x40c0
889#define T_OPCODE_ASR_I 0x1000
890#define T_OPCODE_LSL_I 0x0000
891#define T_OPCODE_LSR_I 0x0800
b99bd4ef 892
a737bd4d
NC
893#define T_OPCODE_MOV_I8 0x2000
894#define T_OPCODE_CMP_I8 0x2800
895#define T_OPCODE_CMP_LR 0x4280
896#define T_OPCODE_MOV_HR 0x4600
897#define T_OPCODE_CMP_HR 0x4500
b99bd4ef 898
a737bd4d
NC
899#define T_OPCODE_LDR_PC 0x4800
900#define T_OPCODE_LDR_SP 0x9800
901#define T_OPCODE_STR_SP 0x9000
902#define T_OPCODE_LDR_IW 0x6800
903#define T_OPCODE_STR_IW 0x6000
904#define T_OPCODE_LDR_IH 0x8800
905#define T_OPCODE_STR_IH 0x8000
906#define T_OPCODE_LDR_IB 0x7800
907#define T_OPCODE_STR_IB 0x7000
908#define T_OPCODE_LDR_RW 0x5800
909#define T_OPCODE_STR_RW 0x5000
910#define T_OPCODE_LDR_RH 0x5a00
911#define T_OPCODE_STR_RH 0x5200
912#define T_OPCODE_LDR_RB 0x5c00
913#define T_OPCODE_STR_RB 0x5400
c9b604bd 914
a737bd4d
NC
915#define T_OPCODE_PUSH 0xb400
916#define T_OPCODE_POP 0xbc00
b99bd4ef 917
a737bd4d 918#define T_OPCODE_BRANCH 0xe7fe
b99bd4ef 919
a737bd4d
NC
920#define THUMB_SIZE 2 /* Size of thumb instruction. */
921#define THUMB_REG_LO 0x1
922#define THUMB_REG_HI 0x2
923#define THUMB_REG_ANY 0x3
90e4755a 924
a737bd4d
NC
925#define THUMB_H1 0x0080
926#define THUMB_H2 0x0040
b99bd4ef 927
a737bd4d
NC
928#define THUMB_ASR 0
929#define THUMB_LSL 1
930#define THUMB_LSR 2
90e4755a 931
a737bd4d
NC
932#define THUMB_MOVE 0
933#define THUMB_COMPARE 1
934#define THUMB_CPY 2
90e4755a 935
a737bd4d
NC
936#define THUMB_LOAD 0
937#define THUMB_STORE 1
90e4755a 938
a737bd4d 939#define THUMB_PP_PC_LR 0x0100
90e4755a 940
a737bd4d
NC
941/* These three are used for immediate shifts, do not alter. */
942#define THUMB_WORD 2
943#define THUMB_HALFWORD 1
944#define THUMB_BYTE 0
90e4755a 945
a737bd4d
NC
946struct thumb_opcode
947{
948 /* Basic string to match. */
949 const char * template;
90e4755a 950
a737bd4d
NC
951 /* Basic instruction code. */
952 unsigned long value;
90e4755a 953
a737bd4d 954 int size;
b99bd4ef
NC
955
956 /* Which CPU variants this exists for. */
90e4755a 957 unsigned long variant;
b99bd4ef
NC
958
959 /* Function to call to parse args. */
a737bd4d 960 void (* parms) (char *);
b99bd4ef
NC
961};
962
f03698e6 963#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 964#define BAD_PC _("r15 not allowed here")
f03698e6 965#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
966#define ERR_NO_ACCUM _("acc0 expected")
967
968static struct hash_control * arm_ops_hsh = NULL;
969static struct hash_control * arm_tops_hsh = NULL;
970static struct hash_control * arm_cond_hsh = NULL;
971static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
972static struct hash_control * arm_psr_hsh = NULL;
973
b99bd4ef
NC
974/* Stuff needed to resolve the label ambiguity
975 As:
976 ...
977 label: <insn>
978 may differ from:
979 ...
980 label:
981 <insn>
982*/
983
984symbolS * last_label_seen;
b34976b6 985static int label_is_thumb_function_name = FALSE;
a737bd4d 986\f
3d0c9500 987/* Literal Pool stuff. */
b99bd4ef
NC
988
989#define MAX_LITERAL_POOL_SIZE 1024
990
3d0c9500
NC
991/* Literal pool structure. Held on a per-section
992 and per-sub-section basis. */
a737bd4d 993
3d0c9500 994typedef struct literal_pool
b99bd4ef 995{
3d0c9500
NC
996 expressionS literals [MAX_LITERAL_POOL_SIZE];
997 unsigned int next_free_entry;
998 unsigned int id;
999 symbolS * symbol;
1000 segT section;
1001 subsegT sub_section;
61b5f74b 1002 struct literal_pool * next;
3d0c9500 1003} literal_pool;
b99bd4ef 1004
3d0c9500
NC
1005/* Pointer to a linked list of literal pools. */
1006literal_pool * list_of_pools = NULL;
b99bd4ef 1007
3d0c9500 1008static literal_pool *
a737bd4d 1009find_literal_pool (void)
3d0c9500
NC
1010{
1011 literal_pool * pool;
1012
1013 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1014 {
1015 if (pool->section == now_seg
1016 && pool->sub_section == now_subseg)
1017 break;
1018 }
1019
1020 return pool;
1021}
b99bd4ef 1022
3d0c9500 1023static literal_pool *
a737bd4d 1024find_or_make_literal_pool (void)
3d0c9500
NC
1025{
1026 /* Next literal pool ID number. */
1027 static unsigned int latest_pool_num = 1;
1028 literal_pool * pool;
1029
1030 pool = find_literal_pool ();
b99bd4ef 1031
3d0c9500
NC
1032 if (pool == NULL)
1033 {
1034 /* Create a new pool. */
a737bd4d 1035 pool = xmalloc (sizeof (* pool));
3d0c9500
NC
1036 if (! pool)
1037 return NULL;
1038
1039 pool->next_free_entry = 0;
1040 pool->section = now_seg;
1041 pool->sub_section = now_subseg;
1042 pool->next = list_of_pools;
1043 pool->symbol = NULL;
1044
1045 /* Add it to the list. */
1046 list_of_pools = pool;
1047 }
1048
1049 /* New pools, and emptied pools, will have a NULL symbol. */
1050 if (pool->symbol == NULL)
1051 {
1052 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1053 (valueT) 0, &zero_address_frag);
1054 pool->id = latest_pool_num ++;
1055 }
1056
1057 /* Done. */
1058 return pool;
1059}
1060
1061/* Add the literal in the global 'inst'
1062 structure to the relevent literal pool. */
a737bd4d 1063
b99bd4ef 1064static int
a737bd4d 1065add_to_lit_pool (void)
b99bd4ef 1066{
61b5f74b 1067 literal_pool * pool;
3d0c9500 1068 unsigned int entry;
b99bd4ef 1069
3d0c9500 1070 pool = find_or_make_literal_pool ();
b99bd4ef 1071
3d0c9500
NC
1072 /* Check if this literal value is already in the pool. */
1073 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1074 {
3d0c9500
NC
1075 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1076 && (inst.reloc.exp.X_op == O_constant)
1077 && (pool->literals[entry].X_add_number
b99bd4ef 1078 == inst.reloc.exp.X_add_number)
3d0c9500
NC
1079 && (pool->literals[entry].X_unsigned
1080 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
1081 break;
1082
3d0c9500
NC
1083 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1084 && (inst.reloc.exp.X_op == O_symbol)
1085 && (pool->literals[entry].X_add_number
b99bd4ef 1086 == inst.reloc.exp.X_add_number)
3d0c9500 1087 && (pool->literals[entry].X_add_symbol
b99bd4ef 1088 == inst.reloc.exp.X_add_symbol)
3d0c9500 1089 && (pool->literals[entry].X_op_symbol
b99bd4ef 1090 == inst.reloc.exp.X_op_symbol))
3d0c9500 1091 break;
b99bd4ef
NC
1092 }
1093
3d0c9500
NC
1094 /* Do we need to create a new entry? */
1095 if (entry == pool->next_free_entry)
b99bd4ef 1096 {
3d0c9500 1097 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 1098 {
ed71e111 1099 inst.error = _("literal pool overflow");
b99bd4ef
NC
1100 return FAIL;
1101 }
1102
3d0c9500
NC
1103 pool->literals[entry] = inst.reloc.exp;
1104 pool->next_free_entry += 1;
b99bd4ef
NC
1105 }
1106
3d0c9500 1107 inst.reloc.exp.X_op = O_symbol;
08df2379 1108 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 1109 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
1110
1111 return SUCCESS;
1112}
1113
1114/* Can't use symbol_new here, so have to create a symbol and then at
1115 a later date assign it a value. Thats what these functions do. */
1116
1117static void
a737bd4d
NC
1118symbol_locate (symbolS * symbolP,
1119 const char * name, /* It is copied, the caller can modify. */
1120 segT segment, /* Segment identifier (SEG_<something>). */
1121 valueT valu, /* Symbol value. */
1122 fragS * frag) /* Associated fragment. */
b99bd4ef
NC
1123{
1124 unsigned int name_length;
1125 char * preserved_copy_of_name;
1126
1127 name_length = strlen (name) + 1; /* +1 for \0. */
1128 obstack_grow (&notes, name, name_length);
1129 preserved_copy_of_name = obstack_finish (&notes);
1130#ifdef STRIP_UNDERSCORE
1131 if (preserved_copy_of_name[0] == '_')
1132 preserved_copy_of_name++;
1133#endif
1134
1135#ifdef tc_canonicalize_symbol_name
1136 preserved_copy_of_name =
1137 tc_canonicalize_symbol_name (preserved_copy_of_name);
1138#endif
1139
1140 S_SET_NAME (symbolP, preserved_copy_of_name);
1141
1142 S_SET_SEGMENT (symbolP, segment);
1143 S_SET_VALUE (symbolP, valu);
c62e1cc3 1144 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
1145
1146 symbol_set_frag (symbolP, frag);
1147
1148 /* Link to end of symbol chain. */
1149 {
1150 extern int symbol_table_frozen;
a737bd4d 1151
b99bd4ef
NC
1152 if (symbol_table_frozen)
1153 abort ();
1154 }
1155
1156 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1157
1158 obj_symbol_new_hook (symbolP);
1159
1160#ifdef tc_symbol_new_hook
1161 tc_symbol_new_hook (symbolP);
1162#endif
1163
1164#ifdef DEBUG_SYMS
1165 verify_symbol_chain (symbol_rootP, symbol_lastP);
1166#endif /* DEBUG_SYMS */
1167}
1168
1169/* Check that an immediate is valid.
1170 If so, convert it to the right format. */
1171
1172static unsigned int
a737bd4d 1173validate_immediate (unsigned int val)
b99bd4ef
NC
1174{
1175 unsigned int a;
1176 unsigned int i;
1177
1178#define rotate_left(v, n) (v << n | v >> (32 - n))
1179
1180 for (i = 0; i < 32; i += 2)
1181 if ((a = rotate_left (val, i)) <= 0xff)
1182 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1183
1184 return FAIL;
1185}
1186
2d2255b5 1187/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
1188 values, added together. We already know that this value cannot be
1189 computed by just one ARM instruction. */
1190
1191static unsigned int
a737bd4d
NC
1192validate_immediate_twopart (unsigned int val,
1193 unsigned int * highpart)
b99bd4ef
NC
1194{
1195 unsigned int a;
1196 unsigned int i;
1197
1198 for (i = 0; i < 32; i += 2)
1199 if (((a = rotate_left (val, i)) & 0xff) != 0)
1200 {
1201 if (a & 0xff00)
1202 {
1203 if (a & ~ 0xffff)
1204 continue;
1205 * highpart = (a >> 8) | ((i + 24) << 7);
1206 }
1207 else if (a & 0xff0000)
1208 {
1209 if (a & 0xff000000)
1210 continue;
1211 * highpart = (a >> 16) | ((i + 16) << 7);
1212 }
1213 else
1214 {
1215 assert (a & 0xff000000);
1216 * highpart = (a >> 24) | ((i + 8) << 7);
1217 }
1218
1219 return (a & 0xff) | (i << 7);
1220 }
1221
1222 return FAIL;
1223}
1224
1225static int
a737bd4d 1226validate_offset_imm (unsigned int val, int hwse)
b99bd4ef
NC
1227{
1228 if ((hwse && val > 255) || val > 4095)
1229 return FAIL;
1230 return val;
1231}
1232
6057a28f
NC
1233\f
1234#ifdef OBJ_ELF
6057a28f
NC
1235/* This code is to handle mapping symbols as defined in the ARM ELF spec.
1236 (This text is taken from version B-02 of the spec):
1237
1238 4.4.7 Mapping and tagging symbols
1239
1240 A section of an ARM ELF file can contain a mixture of ARM code,
1241 Thumb code, and data. There are inline transitions between code
1242 and data at literal pool boundaries. There can also be inline
1243 transitions between ARM code and Thumb code, for example in
1244 ARM-Thumb inter-working veneers. Linkers, machine-level
1245 debuggers, profiling tools, and disassembly tools need to map
1246 images accurately. For example, setting an ARM breakpoint on a
1247 Thumb location, or in a literal pool, can crash the program
1248 being debugged, ruining the debugging session.
1249
1250 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1251 tagged (see section 4.4.7.2 below) using local symbols (with
1252 binding STB_LOCAL). To assist consumers, mapping and tagging
1253 symbols should be collated first in the symbol table, before
1254 other symbols with binding STB_LOCAL.
1255
1256 To allow properly collated mapping and tagging symbols to be
1257 skipped by consumers that have no interest in them, the first
1258 such symbol should have the name $m and its st_value field equal
1259 to the total number of mapping and tagging symbols (including
1260 the $m) in the symbol table.
1261
1262 4.4.7.1 Mapping symbols
1263
1264 $a Labels the first byte of a sequence of ARM instructions.
1265 Its type is STT_FUNC.
1266
1267 $d Labels the first byte of a sequence of data items.
1268 Its type is STT_OBJECT.
1269
1270 $t Labels the first byte of a sequence of Thumb instructions.
1271 Its type is STT_FUNC.
1272
1273 This list of mapping symbols may be extended in the future.
1274
1275 Section-relative mapping symbols
1276
1277 Mapping symbols defined in a section define a sequence of
1278 half-open address intervals that cover the address range of the
1279 section. Each interval starts at the address defined by a
1280 mapping symbol, and continues up to, but not including, the
1281 address defined by the next (in address order) mapping symbol or
1282 the end of the section. A corollary is that there must be a
1283 mapping symbol defined at the beginning of each section.
1284 Consumers can ignore the size of a section-relative mapping
1285 symbol. Producers can set it to 0.
1286
1287 Absolute mapping symbols
1288
1289 Because of the need to crystallize a Thumb address with the
1290 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1291 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1292 or $t.
1293
1294 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1295 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1296 where [x, y) denotes the half-open address range from x,
1297 inclusive, to y, exclusive.
1298
1299 In the absence of a mapping symbol, a consumer can interpret a
1300 function symbol with an odd value as the Thumb code address
1301 obtained by clearing the least significant bit of the
1302 value. This interpretation is deprecated, and it may not work in
1303 the future.
1304
1305 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1306 the EABI (which is still under development), so they are not
1307 implemented here. */
1308
69b97547
NC
1309static enum mstate mapstate = MAP_UNDEFINED;
1310
6057a28f
NC
1311static void
1312mapping_state (enum mstate state)
1313{
6057a28f
NC
1314 symbolS * symbolP;
1315 const char * symname;
1316 int type;
1317
1318 if (mapstate == state)
1319 /* The mapping symbol has already been emitted.
1320 There is nothing else to do. */
1321 return;
1322
1323 mapstate = state;
1324
1325 switch (state)
1326 {
1327 case MAP_DATA:
1328 symname = "$d";
1329 type = BSF_OBJECT;
1330 break;
1331 case MAP_ARM:
1332 symname = "$a";
1333 type = BSF_FUNCTION;
1334 break;
1335 case MAP_THUMB:
1336 symname = "$t";
1337 type = BSF_FUNCTION;
1338 break;
69b97547 1339 case MAP_UNDEFINED:
a737bd4d 1340 return;
6057a28f
NC
1341 default:
1342 abort ();
1343 }
1344
69b97547
NC
1345 seg_info (now_seg)->tc_segment_info_data = state;
1346
6057a28f
NC
1347 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1348 symbol_table_insert (symbolP);
1349 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
a737bd4d 1350
6057a28f
NC
1351 switch (state)
1352 {
1353 case MAP_ARM:
1354 THUMB_SET_FUNC (symbolP, 0);
1355 ARM_SET_THUMB (symbolP, 0);
1356 ARM_SET_INTERWORK (symbolP, support_interwork);
1357 break;
a737bd4d 1358
6057a28f
NC
1359 case MAP_THUMB:
1360 THUMB_SET_FUNC (symbolP, 1);
1361 ARM_SET_THUMB (symbolP, 1);
1362 ARM_SET_INTERWORK (symbolP, support_interwork);
1363 break;
a737bd4d 1364
6057a28f
NC
1365 case MAP_DATA:
1366 default:
1367 return;
1368 }
1369}
1370
a737bd4d
NC
1371/* When we change sections we need to issue a new mapping symbol. */
1372
1373void
1374arm_elf_change_section (void)
1375{
1376 flagword flags;
1377
40a18ebd
NC
1378 /* Link an unlinked unwind index table section to the .text section. */
1379 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1380 && elf_linked_to_section (now_seg) == NULL)
1381 elf_linked_to_section (now_seg) = text_section;
1382
a737bd4d
NC
1383 if (!SEG_NORMAL (now_seg))
1384 return;
1385
1386 flags = bfd_get_section_flags (stdoutput, now_seg);
1387
1388 /* We can ignore sections that only contain debug info. */
1389 if ((flags & SEC_ALLOC) == 0)
1390 return;
1391
1392 mapstate = seg_info (now_seg)->tc_segment_info_data;
1393}
40a18ebd
NC
1394
1395int
1396arm_elf_section_type (const char * str, size_t len)
1397{
1398 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1399 return SHT_ARM_EXIDX;
1400
1401 return -1;
1402}
a737bd4d
NC
1403#else
1404#define mapping_state(a)
1405#endif /* OBJ_ELF */
1406\f
1407/* arm_reg_parse () := if it looks like a register, return its token and
1408 advance the pointer. */
1409
1410static int
1411arm_reg_parse (char ** ccp, struct hash_control * htab)
1412{
1413 char * start = * ccp;
1414 char c;
1415 char * p;
1416 struct reg_entry * reg;
1417
1418#ifdef REGISTER_PREFIX
1419 if (*start != REGISTER_PREFIX)
1420 return FAIL;
1421 p = start + 1;
1422#else
1423 p = start;
1424#ifdef OPTIONAL_REGISTER_PREFIX
1425 if (*p == OPTIONAL_REGISTER_PREFIX)
1426 p++, start++;
1427#endif
1428#endif
1429 if (!ISALPHA (*p) || !is_name_beginner (*p))
1430 return FAIL;
1431
1432 c = *p++;
1433 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1434 c = *p++;
1435
1436 *--p = 0;
1437 reg = (struct reg_entry *) hash_find (htab, start);
1438 *p = c;
1439
1440 if (reg)
1441 {
1442 *ccp = p;
1443 return reg->number;
1444 }
1445
1446 return FAIL;
1447}
1448
1449/* Search for the following register name in each of the possible reg name
1450 tables. Return the classification if found, or REG_TYPE_MAX if not
1451 present. */
6057a28f 1452
a737bd4d
NC
1453static enum arm_reg_type
1454arm_reg_parse_any (char *cp)
6057a28f 1455{
a737bd4d 1456 int i;
6057a28f 1457
a737bd4d
NC
1458 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1459 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1460 return (enum arm_reg_type) i;
6057a28f 1461
a737bd4d
NC
1462 return REG_TYPE_MAX;
1463}
6057a28f 1464
a737bd4d
NC
1465static void
1466opcode_select (int width)
1467{
1468 switch (width)
1469 {
1470 case 16:
1471 if (! thumb_mode)
1472 {
1473 if (! (cpu_variant & ARM_EXT_V4T))
1474 as_bad (_("selected processor does not support THUMB opcodes"));
6057a28f 1475
a737bd4d
NC
1476 thumb_mode = 1;
1477 /* No need to force the alignment, since we will have been
1478 coming from ARM mode, which is word-aligned. */
1479 record_alignment (now_seg, 1);
1480 }
1481 mapping_state (MAP_THUMB);
1482 break;
1483
1484 case 32:
1485 if (thumb_mode)
1486 {
1487 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1488 as_bad (_("selected processor does not support ARM opcodes"));
1489
1490 thumb_mode = 0;
1491
1492 if (!need_pass_2)
1493 frag_align (2, 0, 0);
1494
1495 record_alignment (now_seg, 1);
1496 }
1497 mapping_state (MAP_ARM);
1498 break;
1499
1500 default:
1501 as_bad (_("invalid instruction size selected (%d)"), width);
1502 }
6057a28f 1503}
6057a28f 1504
b99bd4ef 1505static void
a737bd4d 1506s_req (int a ATTRIBUTE_UNUSED)
b99bd4ef 1507{
f03698e6 1508 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
1509}
1510
0bbf2aa4
NC
1511/* The .unreq directive deletes an alias which was previously defined
1512 by .req. For example:
1513
1514 my_alias .req r11
1515 .unreq my_alias */
1516
1517static void
1518s_unreq (int a ATTRIBUTE_UNUSED)
1519{
a737bd4d 1520 char * name;
0bbf2aa4
NC
1521 char saved_char;
1522
1523 skip_whitespace (input_line_pointer);
1524 name = input_line_pointer;
1525
1526 while (*input_line_pointer != 0
1527 && *input_line_pointer != ' '
1528 && *input_line_pointer != '\n')
1529 ++input_line_pointer;
1530
1531 saved_char = *input_line_pointer;
1532 *input_line_pointer = 0;
1533
1534 if (*name)
1535 {
1536 enum arm_reg_type req_type = arm_reg_parse_any (name);
1537
1538 if (req_type != REG_TYPE_MAX)
1539 {
1540 char *temp_name = name;
1541 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1542
1543 if (req_no != FAIL)
1544 {
1545 struct reg_entry *req_entry;
1546
1547 /* Check to see if this alias is a builtin one. */
1548 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1549
1550 if (!req_entry)
1551 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1552 else if (req_entry->builtin)
67c1ffbe 1553 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
1554 points to a const data structure, so we only need to
1555 free up the memory used by the key in the hash table.
1556 Unfortunately we have not recorded this value, so this
1557 is a memory leak. */
1558 /* FIXME: Should we issue a warning message ? */
1559 ;
1560 else
1561 {
67c1ffbe 1562 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
1563 key and the value, but fortunately the key is the same
1564 as the value->name field. */
1565 free ((char *) req_entry->name);
1566 free (req_entry);
1567 }
1568 }
1569 else
1570 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1571 }
1572 else
1573 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1574 }
1575 else
1576 as_bad (_("invalid syntax for .unreq directive"));
1577
1578 *input_line_pointer = saved_char;
1579 demand_empty_rest_of_line ();
1580}
1581
b99bd4ef 1582static void
a737bd4d 1583s_bss (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1584{
1585 /* We don't support putting frags in the BSS segment, we fake it by
1586 marking in_bss, then looking at s_skip for clues. */
1587 subseg_set (bss_section, 0);
1588 demand_empty_rest_of_line ();
6057a28f 1589 mapping_state (MAP_DATA);
b99bd4ef
NC
1590}
1591
1592static void
a737bd4d 1593s_even (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1594{
1595 /* Never make frag if expect extra pass. */
1596 if (!need_pass_2)
1597 frag_align (1, 0, 0);
1598
1599 record_alignment (now_seg, 1);
1600
1601 demand_empty_rest_of_line ();
1602}
1603
1604static void
a737bd4d 1605s_ltorg (int ignored ATTRIBUTE_UNUSED)
b99bd4ef 1606{
3d0c9500
NC
1607 unsigned int entry;
1608 literal_pool * pool;
b99bd4ef
NC
1609 char sym_name[20];
1610
3d0c9500
NC
1611 pool = find_literal_pool ();
1612 if (pool == NULL
1613 || pool->symbol == NULL
1614 || pool->next_free_entry == 0)
b99bd4ef
NC
1615 return;
1616
69b97547
NC
1617 mapping_state (MAP_DATA);
1618
b99bd4ef
NC
1619 /* Align pool as you have word accesses.
1620 Only make a frag if we have to. */
1621 if (!need_pass_2)
1622 frag_align (2, 0, 0);
1623
1624 record_alignment (now_seg, 2);
1625
3d0c9500 1626 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 1627
3d0c9500 1628 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 1629 (valueT) frag_now_fix (), frag_now);
3d0c9500 1630 symbol_table_insert (pool->symbol);
b99bd4ef 1631
3d0c9500 1632 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
1633
1634#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 1635 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
1636#endif
1637
3d0c9500 1638 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1639 /* First output the expression in the instruction to the pool. */
3d0c9500 1640 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 1641
3d0c9500
NC
1642 /* Mark the pool as empty. */
1643 pool->next_free_entry = 0;
1644 pool->symbol = NULL;
b99bd4ef
NC
1645}
1646
1647/* Same as s_align_ptwo but align 0 => align 2. */
1648
1649static void
a737bd4d 1650s_align (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1651{
a737bd4d
NC
1652 int temp;
1653 long temp_fill;
b99bd4ef
NC
1654 long max_alignment = 15;
1655
1656 temp = get_absolute_expression ();
1657 if (temp > max_alignment)
f03698e6 1658 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
1659 else if (temp < 0)
1660 {
f03698e6 1661 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
1662 temp = 0;
1663 }
1664
1665 if (*input_line_pointer == ',')
1666 {
1667 input_line_pointer++;
1668 temp_fill = get_absolute_expression ();
1669 }
1670 else
1671 temp_fill = 0;
1672
1673 if (!temp)
1674 temp = 2;
1675
1676 /* Only make a frag if we HAVE to. */
1677 if (temp && !need_pass_2)
1678 frag_align (temp, (int) temp_fill, 0);
1679 demand_empty_rest_of_line ();
1680
1681 record_alignment (now_seg, temp);
1682}
1683
1684static void
a737bd4d 1685s_force_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1686{
1687 /* If we are not already in thumb mode go into it, EVEN if
1688 the target processor does not support thumb instructions.
1689 This is used by gcc/config/arm/lib1funcs.asm for example
1690 to compile interworking support functions even if the
1691 target processor should not support interworking. */
1692 if (! thumb_mode)
1693 {
1694 thumb_mode = 2;
1695
1696 record_alignment (now_seg, 1);
1697 }
1698
1699 demand_empty_rest_of_line ();
1700}
1701
1702static void
a737bd4d 1703s_thumb_func (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1704{
1705 if (! thumb_mode)
1706 opcode_select (16);
1707
1708 /* The following label is the name/address of the start of a Thumb function.
1709 We need to know this for the interworking support. */
b34976b6 1710 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
1711
1712 demand_empty_rest_of_line ();
1713}
1714
1715/* Perform a .set directive, but also mark the alias as
1716 being a thumb function. */
1717
1718static void
a737bd4d 1719s_thumb_set (int equiv)
b99bd4ef
NC
1720{
1721 /* XXX the following is a duplicate of the code for s_set() in read.c
1722 We cannot just call that code as we need to get at the symbol that
1723 is created. */
a737bd4d
NC
1724 char * name;
1725 char delim;
1726 char * end_name;
1727 symbolS * symbolP;
b99bd4ef
NC
1728
1729 /* Especial apologies for the random logic:
1730 This just grew, and could be parsed much more simply!
1731 Dean - in haste. */
1732 name = input_line_pointer;
1733 delim = get_symbol_end ();
1734 end_name = input_line_pointer;
1735 *end_name = delim;
1736
1737 SKIP_WHITESPACE ();
1738
1739 if (*input_line_pointer != ',')
1740 {
1741 *end_name = 0;
f03698e6 1742 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
1743 *end_name = delim;
1744 ignore_rest_of_line ();
1745 return;
1746 }
1747
1748 input_line_pointer++;
1749 *end_name = 0;
1750
1751 if (name[0] == '.' && name[1] == '\0')
1752 {
1753 /* XXX - this should not happen to .thumb_set. */
1754 abort ();
1755 }
1756
1757 if ((symbolP = symbol_find (name)) == NULL
1758 && (symbolP = md_undefined_symbol (name)) == NULL)
1759 {
1760#ifndef NO_LISTING
1761 /* When doing symbol listings, play games with dummy fragments living
1762 outside the normal fragment chain to record the file and line info
1763 for this symbol. */
1764 if (listing & LISTING_SYMBOLS)
1765 {
1766 extern struct list_info_struct * listing_tail;
a737bd4d 1767 fragS * dummy_frag = xmalloc (sizeof (fragS));
b99bd4ef
NC
1768
1769 memset (dummy_frag, 0, sizeof (fragS));
1770 dummy_frag->fr_type = rs_fill;
1771 dummy_frag->line = listing_tail;
1772 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1773 dummy_frag->fr_symbol = symbolP;
1774 }
1775 else
1776#endif
1777 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1778
1779#ifdef OBJ_COFF
1780 /* "set" symbols are local unless otherwise specified. */
1781 SF_SET_LOCAL (symbolP);
1782#endif /* OBJ_COFF */
1783 } /* Make a new symbol. */
1784
1785 symbol_table_insert (symbolP);
1786
1787 * end_name = delim;
1788
1789 if (equiv
1790 && S_IS_DEFINED (symbolP)
1791 && S_GET_SEGMENT (symbolP) != reg_section)
1792 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1793
1794 pseudo_set (symbolP);
1795
1796 demand_empty_rest_of_line ();
1797
1798 /* XXX Now we come to the Thumb specific bit of code. */
1799
1800 THUMB_SET_FUNC (symbolP, 1);
1801 ARM_SET_THUMB (symbolP, 1);
1802#if defined OBJ_ELF || defined OBJ_COFF
1803 ARM_SET_INTERWORK (symbolP, support_interwork);
1804#endif
1805}
1806
b99bd4ef 1807static void
a737bd4d 1808s_arm (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1809{
1810 opcode_select (32);
1811 demand_empty_rest_of_line ();
1812}
1813
1814static void
a737bd4d 1815s_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1816{
1817 opcode_select (16);
1818 demand_empty_rest_of_line ();
1819}
1820
1821static void
a737bd4d 1822s_code (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1823{
a737bd4d 1824 int temp;
b99bd4ef
NC
1825
1826 temp = get_absolute_expression ();
1827 switch (temp)
1828 {
1829 case 16:
1830 case 32:
1831 opcode_select (temp);
1832 break;
1833
1834 default:
1835 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1836 }
1837}
1838
1839static void
a737bd4d 1840end_of_line (char * str)
b99bd4ef
NC
1841{
1842 skip_whitespace (str);
1843
f03698e6
RE
1844 if (*str != '\0' && !inst.error)
1845 inst.error = _("garbage following instruction");
b99bd4ef
NC
1846}
1847
1848static int
a737bd4d 1849skip_past_comma (char ** str)
b99bd4ef
NC
1850{
1851 char * p = * str, c;
1852 int comma = 0;
1853
1854 while ((c = *p) == ' ' || c == ',')
1855 {
1856 p++;
1857 if (c == ',' && comma++)
1858 return FAIL;
1859 }
1860
1861 if (c == '\0')
1862 return FAIL;
1863
1864 *str = p;
1865 return comma ? SUCCESS : FAIL;
1866}
1867
a737bd4d
NC
1868/* Return TRUE if anything in the expression is a bignum. */
1869
1870static int
1871walk_no_bignums (symbolS * sp)
1872{
1873 if (symbol_get_value_expression (sp)->X_op == O_big)
1874 return 1;
1875
1876 if (symbol_get_value_expression (sp)->X_add_symbol)
1877 {
1878 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1879 || (symbol_get_value_expression (sp)->X_op_symbol
1880 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1881 }
1882
1883 return 0;
1884}
1885
1886static int in_my_get_expression = 0;
1887
1888static int
1889my_get_expression (expressionS * ep, char ** str)
1890{
1891 char * save_in;
1892 segT seg;
1893
1894 save_in = input_line_pointer;
1895 input_line_pointer = *str;
1896 in_my_get_expression = 1;
1897 seg = expression (ep);
1898 in_my_get_expression = 0;
1899
1900 if (ep->X_op == O_illegal)
1901 {
1902 /* We found a bad expression in md_operand(). */
1903 *str = input_line_pointer;
1904 input_line_pointer = save_in;
1905 return 1;
1906 }
1907
1908#ifdef OBJ_AOUT
1909 if (seg != absolute_section
1910 && seg != text_section
1911 && seg != data_section
1912 && seg != bss_section
1913 && seg != undefined_section)
1914 {
1915 inst.error = _("bad_segment");
1916 *str = input_line_pointer;
1917 input_line_pointer = save_in;
1918 return 1;
1919 }
1920#endif
1921
1922 /* Get rid of any bignums now, so that we don't generate an error for which
1923 we can't establish a line number later on. Big numbers are never valid
1924 in instructions, which is where this routine is always called. */
1925 if (ep->X_op == O_big
1926 || (ep->X_add_symbol
1927 && (walk_no_bignums (ep->X_add_symbol)
1928 || (ep->X_op_symbol
1929 && walk_no_bignums (ep->X_op_symbol)))))
1930 {
1931 inst.error = _("invalid constant");
1932 *str = input_line_pointer;
1933 input_line_pointer = save_in;
1934 return 1;
1935 }
1936
1937 *str = input_line_pointer;
1938 input_line_pointer = save_in;
1939 return 0;
1940}
1941
b99bd4ef
NC
1942/* A standard register must be given at this point.
1943 SHIFT is the place to put it in inst.instruction.
1944 Restores input start point on error.
1945 Returns the reg#, or FAIL. */
1946
1947static int
a737bd4d 1948reg_required_here (char ** str, int shift)
b99bd4ef
NC
1949{
1950 static char buff [128]; /* XXX */
1951 int reg;
1952 char * start = * str;
1953
6c43fab6 1954 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
1955 {
1956 if (shift >= 0)
1957 inst.instruction |= reg << shift;
1958 return reg;
1959 }
1960
1961 /* Restore the start point, we may have got a reg of the wrong class. */
1962 *str = start;
1963
1964 /* In the few cases where we might be able to accept something else
1965 this error can be overridden. */
f03698e6 1966 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
1967 inst.error = buff;
1968
1969 return FAIL;
1970}
1971
5a6c6817 1972/* A Intel Wireless MMX technology register
e16bb312
NC
1973 must be given at this point.
1974 Shift is the place to put it in inst.instruction.
1975 Restores input start point on err.
1976 Returns the reg#, or FAIL. */
1977
1978static int
a737bd4d
NC
1979wreg_required_here (char ** str,
1980 int shift,
1981 enum wreg_type reg_type)
e16bb312
NC
1982{
1983 static char buff [128];
1984 int reg;
1985 char * start = *str;
1986
1987 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1988 {
1989 if (wr_register (reg)
1990 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1991 {
1992 if (shift >= 0)
1993 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1994 return reg;
1995 }
1996 else if (wc_register (reg)
1997 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1998 {
1999 if (shift >= 0)
2000 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2001 return reg;
2002 }
2003 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2004 {
2005 if (shift >= 0)
2006 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2007 return reg;
2008 }
2009 }
2010
2011 /* Restore the start point, we may have got a reg of the wrong class. */
2012 *str = start;
2013
2014 /* In the few cases where we might be able to accept
2015 something else this error can be overridden. */
5a6c6817 2016 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
2017 inst.error = buff;
2018
2019 return FAIL;
2020}
2021
05d2d07e 2022static const struct asm_psr *
a737bd4d 2023arm_psr_parse (char ** ccp)
b99bd4ef
NC
2024{
2025 char * start = * ccp;
2026 char c;
2027 char * p;
05d2d07e 2028 const struct asm_psr * psr;
b99bd4ef
NC
2029
2030 p = start;
2031
2032 /* Skip to the end of the next word in the input stream. */
2033 do
2034 {
2035 c = *p++;
2036 }
3882b010 2037 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2038
2039 /* Terminate the word. */
2040 *--p = 0;
2041
2042 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2043 feature for ease of use and backwards compatibility. */
2044 if (!strncmp (start, "cpsr", 4))
2045 strncpy (start, "CPSR", 4);
2046 else if (!strncmp (start, "spsr", 4))
2047 strncpy (start, "SPSR", 4);
2048
2049 /* Now locate the word in the psr hash table. */
05d2d07e 2050 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
2051
2052 /* Restore the input stream. */
2053 *p = c;
2054
2055 /* If we found a valid match, advance the
2056 stream pointer past the end of the word. */
2057 *ccp = p;
2058
2059 return psr;
2060}
2061
2062/* Parse the input looking for a PSR flag. */
2063
2064static int
a737bd4d 2065psr_required_here (char ** str)
b99bd4ef
NC
2066{
2067 char * start = * str;
05d2d07e 2068 const struct asm_psr * psr;
b99bd4ef
NC
2069
2070 psr = arm_psr_parse (str);
2071
2072 if (psr)
2073 {
2074 /* If this is the SPSR that is being modified, set the R bit. */
2075 if (! psr->cpsr)
2076 inst.instruction |= SPSR_BIT;
2077
2078 /* Set the psr flags in the MSR instruction. */
2079 inst.instruction |= psr->field << PSR_SHIFT;
2080
2081 return SUCCESS;
2082 }
2083
2084 /* In the few cases where we might be able to accept
2085 something else this error can be overridden. */
2086 inst.error = _("flag for {c}psr instruction expected");
2087
2088 /* Restore the start point. */
2089 *str = start;
2090 return FAIL;
2091}
2092
2093static int
a737bd4d 2094co_proc_number (char ** str)
b99bd4ef
NC
2095{
2096 int processor, pchar;
6c43fab6 2097 char *start;
b99bd4ef 2098
6c43fab6
RE
2099 skip_whitespace (*str);
2100 start = *str;
b99bd4ef
NC
2101
2102 /* The data sheet seems to imply that just a number on its own is valid
2103 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2104 accept either. */
6c43fab6
RE
2105 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2106 == FAIL)
b99bd4ef 2107 {
6c43fab6
RE
2108 *str = start;
2109
2110 pchar = *(*str)++;
2111 if (pchar >= '0' && pchar <= '9')
b99bd4ef 2112 {
6c43fab6
RE
2113 processor = pchar - '0';
2114 if (**str >= '0' && **str <= '9')
b99bd4ef 2115 {
6c43fab6
RE
2116 processor = processor * 10 + *(*str)++ - '0';
2117 if (processor > 15)
2118 {
f03698e6 2119 inst.error = _("illegal co-processor number");
6c43fab6
RE
2120 return FAIL;
2121 }
b99bd4ef
NC
2122 }
2123 }
6c43fab6
RE
2124 else
2125 {
376eb240 2126 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
2127 return FAIL;
2128 }
b99bd4ef
NC
2129 }
2130
2131 inst.instruction |= processor << 8;
2132 return SUCCESS;
2133}
2134
2135static int
a737bd4d 2136cp_opc_expr (char ** str, int where, int length)
b99bd4ef
NC
2137{
2138 expressionS expr;
2139
2140 skip_whitespace (* str);
2141
2142 memset (&expr, '\0', sizeof (expr));
2143
2144 if (my_get_expression (&expr, str))
2145 return FAIL;
2146 if (expr.X_op != O_constant)
2147 {
2148 inst.error = _("bad or missing expression");
2149 return FAIL;
2150 }
2151
2152 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2153 {
2154 inst.error = _("immediate co-processor expression too large");
2155 return FAIL;
2156 }
2157
2158 inst.instruction |= expr.X_add_number << where;
2159 return SUCCESS;
2160}
2161
2162static int
a737bd4d 2163cp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2164{
2165 int reg;
2166 char * start = *str;
2167
6c43fab6 2168 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 2169 {
b99bd4ef
NC
2170 inst.instruction |= reg << where;
2171 return reg;
2172 }
2173
2174 /* In the few cases where we might be able to accept something else
2175 this error can be overridden. */
376eb240 2176 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
2177
2178 /* Restore the start point. */
2179 *str = start;
2180 return FAIL;
2181}
2182
2183static int
a737bd4d 2184fp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2185{
2186 int reg;
2187 char * start = * str;
2188
6c43fab6 2189 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 2190 {
b99bd4ef
NC
2191 inst.instruction |= reg << where;
2192 return reg;
2193 }
2194
2195 /* In the few cases where we might be able to accept something else
2196 this error can be overridden. */
376eb240 2197 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
2198
2199 /* Restore the start point. */
2200 *str = start;
2201 return FAIL;
2202}
2203
2204static int
a737bd4d 2205cp_address_offset (char ** str)
b99bd4ef
NC
2206{
2207 int offset;
2208
2209 skip_whitespace (* str);
2210
2211 if (! is_immediate_prefix (**str))
2212 {
2213 inst.error = _("immediate expression expected");
2214 return FAIL;
2215 }
2216
2217 (*str)++;
2218
2219 if (my_get_expression (& inst.reloc.exp, str))
2220 return FAIL;
2221
2222 if (inst.reloc.exp.X_op == O_constant)
2223 {
2224 offset = inst.reloc.exp.X_add_number;
2225
2226 if (offset & 3)
2227 {
2228 inst.error = _("co-processor address must be word aligned");
2229 return FAIL;
2230 }
2231
2232 if (offset > 1023 || offset < -1023)
2233 {
2234 inst.error = _("offset too large");
2235 return FAIL;
2236 }
2237
2238 if (offset >= 0)
2239 inst.instruction |= INDEX_UP;
2240 else
2241 offset = -offset;
2242
2243 inst.instruction |= offset >> 2;
2244 }
2245 else
2246 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2247
2248 return SUCCESS;
2249}
2250
2251static int
a737bd4d 2252cp_address_required_here (char ** str, int wb_ok)
b99bd4ef
NC
2253{
2254 char * p = * str;
2255 int pre_inc = 0;
2256 int write_back = 0;
2257
2258 if (*p == '[')
2259 {
2260 int reg;
2261
2262 p++;
2263 skip_whitespace (p);
2264
2265 if ((reg = reg_required_here (& p, 16)) == FAIL)
2266 return FAIL;
2267
2268 skip_whitespace (p);
2269
2270 if (*p == ']')
2271 {
2272 p++;
2273
f02232aa
NC
2274 skip_whitespace (p);
2275
2276 if (*p == '\0')
b99bd4ef 2277 {
f02232aa 2278 /* As an extension to the official ARM syntax we allow:
f02232aa 2279 [Rn]
f02232aa 2280 as a short hand for:
f02232aa
NC
2281 [Rn,#0] */
2282 inst.instruction |= PRE_INDEX | INDEX_UP;
2283 *str = p;
2284 return SUCCESS;
2285 }
a737bd4d 2286
f02232aa
NC
2287 if (skip_past_comma (& p) == FAIL)
2288 {
2289 inst.error = _("comma expected after closing square bracket");
2290 return FAIL;
2291 }
b99bd4ef 2292
f02232aa
NC
2293 skip_whitespace (p);
2294
2295 if (*p == '#')
2296 {
2297 if (wb_ok)
b99bd4ef 2298 {
f02232aa
NC
2299 /* [Rn], #expr */
2300 write_back = WRITE_BACK;
2301
2302 if (reg == REG_PC)
2303 {
2304 inst.error = _("pc may not be used in post-increment");
2305 return FAIL;
2306 }
2307
2308 if (cp_address_offset (& p) == FAIL)
2309 return FAIL;
b99bd4ef 2310 }
f02232aa
NC
2311 else
2312 pre_inc = PRE_INDEX | INDEX_UP;
2313 }
2314 else if (*p == '{')
2315 {
2316 int option;
b99bd4ef 2317
f02232aa
NC
2318 /* [Rn], {<expr>} */
2319 p++;
2320
2321 skip_whitespace (p);
2322
2323 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 2324 return FAIL;
f02232aa
NC
2325
2326 if (inst.reloc.exp.X_op == O_constant)
2327 {
2328 option = inst.reloc.exp.X_add_number;
2329
2330 if (option > 255 || option < 0)
2331 {
2332 inst.error = _("'option' field too large");
2333 return FAIL;
2334 }
2335
2336 skip_whitespace (p);
2337
2338 if (*p != '}')
2339 {
2340 inst.error = _("'}' expected at end of 'option' field");
2341 return FAIL;
2342 }
2343 else
2344 {
2345 p++;
2346 inst.instruction |= option;
2347 inst.instruction |= INDEX_UP;
2348 }
2349 }
2350 else
2351 {
2352 inst.error = _("non-constant expressions for 'option' field not supported");
2353 return FAIL;
2354 }
b99bd4ef
NC
2355 }
2356 else
f02232aa
NC
2357 {
2358 inst.error = _("# or { expected after comma");
a737bd4d 2359 return FAIL;
f02232aa 2360 }
b99bd4ef
NC
2361 }
2362 else
2363 {
2364 /* '['Rn, #expr']'[!] */
2365
2366 if (skip_past_comma (& p) == FAIL)
2367 {
2368 inst.error = _("pre-indexed expression expected");
2369 return FAIL;
2370 }
2371
2372 pre_inc = PRE_INDEX;
2373
2374 if (cp_address_offset (& p) == FAIL)
2375 return FAIL;
2376
2377 skip_whitespace (p);
2378
2379 if (*p++ != ']')
2380 {
2381 inst.error = _("missing ]");
2382 return FAIL;
2383 }
2384
2385 skip_whitespace (p);
2386
bfae80f2 2387 if (wb_ok && *p == '!')
b99bd4ef
NC
2388 {
2389 if (reg == REG_PC)
2390 {
2391 inst.error = _("pc may not be used with write-back");
2392 return FAIL;
2393 }
2394
2395 p++;
2396 write_back = WRITE_BACK;
2397 }
2398 }
2399 }
2400 else
2401 {
2402 if (my_get_expression (&inst.reloc.exp, &p))
2403 return FAIL;
2404
2405 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2406 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2407 inst.reloc.pc_rel = 1;
2408 inst.instruction |= (REG_PC << 16);
2409 pre_inc = PRE_INDEX;
2410 }
2411
2412 inst.instruction |= write_back | pre_inc;
2413 *str = p;
2414 return SUCCESS;
2415}
2416
e16bb312 2417static int
a737bd4d 2418cp_byte_address_offset (char ** str)
e16bb312
NC
2419{
2420 int offset;
2421
2422 skip_whitespace (* str);
2423
2424 if (! is_immediate_prefix (**str))
2425 {
2426 inst.error = _("immediate expression expected");
2427 return FAIL;
2428 }
2429
2430 (*str)++;
a737bd4d 2431
e16bb312
NC
2432 if (my_get_expression (& inst.reloc.exp, str))
2433 return FAIL;
a737bd4d 2434
e16bb312
NC
2435 if (inst.reloc.exp.X_op == O_constant)
2436 {
2437 offset = inst.reloc.exp.X_add_number;
a737bd4d 2438
e16bb312
NC
2439 if (offset > 255 || offset < -255)
2440 {
2441 inst.error = _("offset too large");
2442 return FAIL;
2443 }
2444
2445 if (offset >= 0)
2446 inst.instruction |= INDEX_UP;
2447 else
2448 offset = -offset;
2449
2450 inst.instruction |= offset;
2451 }
2452 else
2453 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2454
2455 return SUCCESS;
2456}
2457
2458static int
a737bd4d 2459cp_byte_address_required_here (char ** str)
e16bb312
NC
2460{
2461 char * p = * str;
2462 int pre_inc = 0;
2463 int write_back = 0;
2464
2465 if (*p == '[')
2466 {
2467 int reg;
2468
2469 p++;
2470 skip_whitespace (p);
2471
2472 if ((reg = reg_required_here (& p, 16)) == FAIL)
2473 return FAIL;
2474
2475 skip_whitespace (p);
2476
2477 if (*p == ']')
2478 {
2479 p++;
a737bd4d 2480
e16bb312
NC
2481 if (skip_past_comma (& p) == SUCCESS)
2482 {
2483 /* [Rn], #expr */
2484 write_back = WRITE_BACK;
a737bd4d 2485
e16bb312
NC
2486 if (reg == REG_PC)
2487 {
2488 inst.error = _("pc may not be used in post-increment");
2489 return FAIL;
2490 }
2491
2492 if (cp_byte_address_offset (& p) == FAIL)
2493 return FAIL;
2494 }
2495 else
2496 pre_inc = PRE_INDEX | INDEX_UP;
2497 }
2498 else
2499 {
2500 /* '['Rn, #expr']'[!] */
2501
2502 if (skip_past_comma (& p) == FAIL)
2503 {
2504 inst.error = _("pre-indexed expression expected");
2505 return FAIL;
2506 }
2507
2508 pre_inc = PRE_INDEX;
a737bd4d 2509
e16bb312
NC
2510 if (cp_byte_address_offset (& p) == FAIL)
2511 return FAIL;
2512
2513 skip_whitespace (p);
2514
2515 if (*p++ != ']')
2516 {
2517 inst.error = _("missing ]");
2518 return FAIL;
2519 }
2520
2521 skip_whitespace (p);
2522
2523 if (*p == '!')
2524 {
2525 if (reg == REG_PC)
2526 {
2527 inst.error = _("pc may not be used with write-back");
2528 return FAIL;
2529 }
2530
2531 p++;
2532 write_back = WRITE_BACK;
2533 }
2534 }
2535 }
2536 else
2537 {
2538 if (my_get_expression (&inst.reloc.exp, &p))
2539 return FAIL;
2540
2541 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2542 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2543 inst.reloc.pc_rel = 1;
2544 inst.instruction |= (REG_PC << 16);
2545 pre_inc = PRE_INDEX;
2546 }
2547
2548 inst.instruction |= write_back | pre_inc;
2549 *str = p;
2550 return SUCCESS;
2551}
2552
0dd132b6
NC
2553static void
2554do_nop (char * str)
2555{
2556 skip_whitespace (str);
2557 if (*str == '{')
2558 {
2559 str++;
2560
2561 if (my_get_expression (&inst.reloc.exp, &str))
2562 inst.reloc.exp.X_op = O_illegal;
2563 else
2564 {
2565 skip_whitespace (str);
2566 if (*str == '}')
2567 str++;
2568 else
2569 inst.reloc.exp.X_op = O_illegal;
2570 }
2571
2572 if (inst.reloc.exp.X_op != O_constant
2573 || inst.reloc.exp.X_add_number > 255
2574 || inst.reloc.exp.X_add_number < 0)
2575 {
2576 inst.error = _("Invalid NOP hint");
2577 return;
2578 }
2579
2580 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2581 inst.instruction &= 0xf0000000;
2582 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2583 }
2584
2585 end_of_line (str);
2586}
2587
b99bd4ef 2588static void
a737bd4d 2589do_empty (char * str)
b99bd4ef
NC
2590{
2591 /* Do nothing really. */
b99bd4ef 2592 end_of_line (str);
b99bd4ef
NC
2593}
2594
2595static void
a737bd4d 2596do_mrs (char * str)
b99bd4ef
NC
2597{
2598 int skip = 0;
2599
2600 /* Only one syntax. */
2601 skip_whitespace (str);
2602
2603 if (reg_required_here (&str, 12) == FAIL)
2604 {
2605 inst.error = BAD_ARGS;
2606 return;
2607 }
2608
2609 if (skip_past_comma (&str) == FAIL)
2610 {
2611 inst.error = _("comma expected after register name");
2612 return;
2613 }
2614
2615 skip_whitespace (str);
2616
a737bd4d
NC
2617 if ( streq (str, "CPSR")
2618 || streq (str, "SPSR")
2d2255b5 2619 /* Lower case versions for backwards compatibility. */
a737bd4d
NC
2620 || streq (str, "cpsr")
2621 || streq (str, "spsr"))
b99bd4ef
NC
2622 skip = 4;
2623
2d2255b5 2624 /* This is for backwards compatibility with older toolchains. */
a737bd4d
NC
2625 else if ( streq (str, "cpsr_all")
2626 || streq (str, "spsr_all"))
b99bd4ef
NC
2627 skip = 8;
2628 else
2629 {
f03698e6 2630 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
2631 return;
2632 }
2633
2634 if (* str == 's' || * str == 'S')
2635 inst.instruction |= SPSR_BIT;
2636 str += skip;
2637
b99bd4ef
NC
2638 end_of_line (str);
2639}
2640
2641/* Two possible forms:
2642 "{C|S}PSR_<field>, Rm",
2643 "{C|S}PSR_f, #expression". */
2644
2645static void
a737bd4d 2646do_msr (char * str)
b99bd4ef
NC
2647{
2648 skip_whitespace (str);
2649
2650 if (psr_required_here (& str) == FAIL)
2651 return;
2652
2653 if (skip_past_comma (& str) == FAIL)
2654 {
2655 inst.error = _("comma missing after psr flags");
2656 return;
2657 }
2658
2659 skip_whitespace (str);
2660
2661 if (reg_required_here (& str, 0) != FAIL)
2662 {
2663 inst.error = NULL;
b99bd4ef
NC
2664 end_of_line (str);
2665 return;
2666 }
2667
2668 if (! is_immediate_prefix (* str))
2669 {
2670 inst.error =
2671 _("only a register or immediate value can follow a psr flag");
2672 return;
2673 }
2674
2675 str ++;
2676 inst.error = NULL;
2677
2678 if (my_get_expression (& inst.reloc.exp, & str))
2679 {
2680 inst.error =
2681 _("only a register or immediate value can follow a psr flag");
2682 return;
2683 }
2684
2685#if 0 /* The first edition of the ARM architecture manual stated that
2686 writing anything other than the flags with an immediate operation
2687 had UNPREDICTABLE effects. This constraint was removed in the
2688 second edition of the specification. */
2689 if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
2690 && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
2691 {
2692 inst.error = _("immediate value cannot be used to set this field");
2693 return;
2694 }
2695#endif
2696
f2b7cb0a 2697 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
2698
2699 if (inst.reloc.exp.X_add_symbol)
2700 {
2701 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2702 inst.reloc.pc_rel = 0;
2703 }
2704 else
2705 {
2706 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2707
2708 if (value == (unsigned) FAIL)
2709 {
f03698e6 2710 inst.error = _("invalid constant");
b99bd4ef
NC
2711 return;
2712 }
2713
2714 inst.instruction |= value;
2715 }
2716
2717 inst.error = NULL;
b99bd4ef
NC
2718 end_of_line (str);
2719}
2720
2721/* Long Multiply Parser
2722 UMULL RdLo, RdHi, Rm, Rs
2723 SMULL RdLo, RdHi, Rm, Rs
2724 UMLAL RdLo, RdHi, Rm, Rs
2725 SMLAL RdLo, RdHi, Rm, Rs. */
2726
2727static void
a737bd4d 2728do_mull (char * str)
b99bd4ef
NC
2729{
2730 int rdlo, rdhi, rm, rs;
2731
2732 /* Only one format "rdlo, rdhi, rm, rs". */
2733 skip_whitespace (str);
2734
2735 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2736 {
2737 inst.error = BAD_ARGS;
2738 return;
2739 }
2740
2741 if (skip_past_comma (&str) == FAIL
2742 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2743 {
2744 inst.error = BAD_ARGS;
2745 return;
2746 }
2747
2748 if (skip_past_comma (&str) == FAIL
2749 || (rm = reg_required_here (&str, 0)) == FAIL)
2750 {
2751 inst.error = BAD_ARGS;
2752 return;
2753 }
2754
2755 /* rdhi, rdlo and rm must all be different. */
2756 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2757 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2758
2759 if (skip_past_comma (&str) == FAIL
2760 || (rs = reg_required_here (&str, 8)) == FAIL)
2761 {
2762 inst.error = BAD_ARGS;
2763 return;
2764 }
2765
2766 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2767 {
2768 inst.error = BAD_PC;
2769 return;
2770 }
2771
b99bd4ef 2772 end_of_line (str);
b99bd4ef
NC
2773}
2774
2775static void
a737bd4d 2776do_mul (char * str)
b99bd4ef
NC
2777{
2778 int rd, rm;
2779
2780 /* Only one format "rd, rm, rs". */
2781 skip_whitespace (str);
2782
2783 if ((rd = reg_required_here (&str, 16)) == FAIL)
2784 {
2785 inst.error = BAD_ARGS;
2786 return;
2787 }
2788
2789 if (rd == REG_PC)
2790 {
2791 inst.error = BAD_PC;
2792 return;
2793 }
2794
2795 if (skip_past_comma (&str) == FAIL
2796 || (rm = reg_required_here (&str, 0)) == FAIL)
2797 {
2798 inst.error = BAD_ARGS;
2799 return;
2800 }
2801
2802 if (rm == REG_PC)
2803 {
2804 inst.error = BAD_PC;
2805 return;
2806 }
2807
2808 if (rm == rd)
2809 as_tsktsk (_("rd and rm should be different in mul"));
2810
2811 if (skip_past_comma (&str) == FAIL
2812 || (rm = reg_required_here (&str, 8)) == FAIL)
2813 {
2814 inst.error = BAD_ARGS;
2815 return;
2816 }
2817
2818 if (rm == REG_PC)
2819 {
2820 inst.error = BAD_PC;
2821 return;
2822 }
2823
b99bd4ef 2824 end_of_line (str);
b99bd4ef
NC
2825}
2826
2827static void
a737bd4d 2828do_mla (char * str)
b99bd4ef
NC
2829{
2830 int rd, rm;
2831
2832 /* Only one format "rd, rm, rs, rn". */
2833 skip_whitespace (str);
2834
2835 if ((rd = reg_required_here (&str, 16)) == FAIL)
2836 {
2837 inst.error = BAD_ARGS;
2838 return;
2839 }
2840
2841 if (rd == REG_PC)
2842 {
2843 inst.error = BAD_PC;
2844 return;
2845 }
2846
2847 if (skip_past_comma (&str) == FAIL
2848 || (rm = reg_required_here (&str, 0)) == FAIL)
2849 {
2850 inst.error = BAD_ARGS;
2851 return;
2852 }
2853
2854 if (rm == REG_PC)
2855 {
2856 inst.error = BAD_PC;
2857 return;
2858 }
2859
2860 if (rm == rd)
2861 as_tsktsk (_("rd and rm should be different in mla"));
2862
2863 if (skip_past_comma (&str) == FAIL
2864 || (rd = reg_required_here (&str, 8)) == FAIL
2865 || skip_past_comma (&str) == FAIL
2866 || (rm = reg_required_here (&str, 12)) == FAIL)
2867 {
2868 inst.error = BAD_ARGS;
2869 return;
2870 }
2871
2872 if (rd == REG_PC || rm == REG_PC)
2873 {
2874 inst.error = BAD_PC;
2875 return;
2876 }
2877
b99bd4ef 2878 end_of_line (str);
b99bd4ef
NC
2879}
2880
2881/* Expects *str -> the characters "acc0", possibly with leading blanks.
2882 Advances *str to the next non-alphanumeric.
2883 Returns 0, or else FAIL (in which case sets inst.error).
2884
2885 (In a future XScale, there may be accumulators other than zero.
2886 At that time this routine and its callers can be upgraded to suit.) */
2887
2888static int
a737bd4d 2889accum0_required_here (char ** str)
b99bd4ef
NC
2890{
2891 static char buff [128]; /* Note the address is taken. Hence, static. */
2892 char * p = * str;
2893 char c;
2894 int result = 0; /* The accum number. */
2895
2896 skip_whitespace (p);
2897
a737bd4d
NC
2898 *str = p; /* Advance caller's string pointer too. */
2899 c = *p++;
2900 while (ISALNUM (c))
2901 c = *p++;
2902
2903 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2904
2905 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2906 {
2907 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2908 inst.error = buff;
2909 result = FAIL;
2910 }
2911
2912 *p = c; /* Unzap. */
2913 *str = p; /* Caller's string pointer to after match. */
2914 return result;
2915}
2916
2917static int
2918ldst_extend_v4 (char ** str)
2919{
2920 int add = INDEX_UP;
2921
2922 switch (**str)
2923 {
2924 case '#':
2925 case '$':
2926 (*str)++;
2927 if (my_get_expression (& inst.reloc.exp, str))
2928 return FAIL;
2929
2930 if (inst.reloc.exp.X_op == O_constant)
2931 {
2932 int value = inst.reloc.exp.X_add_number;
2933
2934 if (value < -255 || value > 255)
2935 {
2936 inst.error = _("address offset too large");
2937 return FAIL;
2938 }
2939
2940 if (value < 0)
2941 {
2942 value = -value;
2943 add = 0;
2944 }
2945
2946 /* Halfword and signextension instructions have the
2947 immediate value split across bits 11..8 and bits 3..0. */
2948 inst.instruction |= (add | HWOFFSET_IMM
2949 | ((value >> 4) << 8) | (value & 0xF));
2950 }
2951 else
2952 {
2953 inst.instruction |= HWOFFSET_IMM;
2954 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2955 inst.reloc.pc_rel = 0;
2956 }
2957 return SUCCESS;
2958
2959 case '-':
2960 add = 0;
2961 /* Fall through. */
2962
2963 case '+':
2964 (*str)++;
2965 /* Fall through. */
b99bd4ef 2966
a737bd4d
NC
2967 default:
2968 if (reg_required_here (str, 0) == FAIL)
2969 return FAIL;
b99bd4ef 2970
a737bd4d
NC
2971 inst.instruction |= add;
2972 return SUCCESS;
b99bd4ef 2973 }
b99bd4ef
NC
2974}
2975
2976/* Expects **str -> after a comma. May be leading blanks.
2977 Advances *str, recognizing a load mode, and setting inst.instruction.
2978 Returns rn, or else FAIL (in which case may set inst.error
2979 and not advance str)
2980
2981 Note: doesn't know Rd, so no err checks that require such knowledge. */
2982
2983static int
a737bd4d 2984ld_mode_required_here (char ** string)
b99bd4ef
NC
2985{
2986 char * str = * string;
2987 int rn;
2988 int pre_inc = 0;
2989
2990 skip_whitespace (str);
2991
2992 if (* str == '[')
2993 {
2994 str++;
2995
2996 skip_whitespace (str);
2997
2998 if ((rn = reg_required_here (& str, 16)) == FAIL)
2999 return FAIL;
3000
3001 skip_whitespace (str);
3002
3003 if (* str == ']')
3004 {
3005 str ++;
3006
3007 if (skip_past_comma (& str) == SUCCESS)
3008 {
3009 /* [Rn],... (post inc) */
90e4755a 3010 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3011 return FAIL;
3012 }
3013 else /* [Rn] */
3014 {
cc8a6dd0 3015 skip_whitespace (str);
b99bd4ef 3016
cc8a6dd0
KH
3017 if (* str == '!')
3018 {
3019 str ++;
3020 inst.instruction |= WRITE_BACK;
3021 }
b99bd4ef
NC
3022
3023 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3024 pre_inc = 1;
3025 }
3026 }
3027 else /* [Rn,...] */
3028 {
3029 if (skip_past_comma (& str) == FAIL)
3030 {
3031 inst.error = _("pre-indexed expression expected");
3032 return FAIL;
3033 }
3034
3035 pre_inc = 1;
3036
90e4755a 3037 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3038 return FAIL;
3039
3040 skip_whitespace (str);
3041
3042 if (* str ++ != ']')
3043 {
3044 inst.error = _("missing ]");
3045 return FAIL;
3046 }
3047
3048 skip_whitespace (str);
3049
3050 if (* str == '!')
3051 {
3052 str ++;
3053 inst.instruction |= WRITE_BACK;
3054 }
3055 }
3056 }
3057 else if (* str == '=') /* ldr's "r,=label" syntax */
3058 /* We should never reach here, because <text> = <expression> is
3059 caught gas/read.c read_a_source_file() as a .set operation. */
3060 return FAIL;
3061 else /* PC +- 8 bit immediate offset. */
3062 {
3063 if (my_get_expression (& inst.reloc.exp, & str))
3064 return FAIL;
3065
3066 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3067 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3068 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3069 inst.reloc.pc_rel = 1;
3070 inst.instruction |= (REG_PC << 16);
3071
3072 rn = REG_PC;
3073 pre_inc = 1;
3074 }
3075
3076 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3077 * string = str;
3078
3079 return rn;
3080}
3081
3082/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3083 SMLAxy{cond} Rd,Rm,Rs,Rn
3084 SMLAWy{cond} Rd,Rm,Rs,Rn
3085 Error if any register is R15. */
3086
3087static void
a737bd4d 3088do_smla (char * str)
b99bd4ef
NC
3089{
3090 int rd, rm, rs, rn;
3091
3092 skip_whitespace (str);
3093
3094 if ((rd = reg_required_here (& str, 16)) == FAIL
3095 || skip_past_comma (& str) == FAIL
3096 || (rm = reg_required_here (& str, 0)) == FAIL
3097 || skip_past_comma (& str) == FAIL
3098 || (rs = reg_required_here (& str, 8)) == FAIL
3099 || skip_past_comma (& str) == FAIL
3100 || (rn = reg_required_here (& str, 12)) == FAIL)
3101 inst.error = BAD_ARGS;
3102
3103 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3104 inst.error = BAD_PC;
3105
b99bd4ef
NC
3106 else
3107 end_of_line (str);
3108}
3109
3110/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3111 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3112 Error if any register is R15.
3113 Warning if Rdlo == Rdhi. */
3114
3115static void
a737bd4d 3116do_smlal (char * str)
b99bd4ef
NC
3117{
3118 int rdlo, rdhi, rm, rs;
3119
3120 skip_whitespace (str);
3121
3122 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3123 || skip_past_comma (& str) == FAIL
3124 || (rdhi = reg_required_here (& str, 16)) == FAIL
3125 || skip_past_comma (& str) == FAIL
3126 || (rm = reg_required_here (& str, 0)) == FAIL
3127 || skip_past_comma (& str) == FAIL
3128 || (rs = reg_required_here (& str, 8)) == FAIL)
3129 {
3130 inst.error = BAD_ARGS;
3131 return;
3132 }
3133
3134 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3135 {
3136 inst.error = BAD_PC;
3137 return;
3138 }
3139
3140 if (rdlo == rdhi)
3141 as_tsktsk (_("rdhi and rdlo must be different"));
3142
f2b7cb0a 3143 end_of_line (str);
b99bd4ef
NC
3144}
3145
3146/* ARM V5E (El Segundo) signed-multiply (argument parse)
3147 SMULxy{cond} Rd,Rm,Rs
3148 Error if any register is R15. */
3149
3150static void
a737bd4d 3151do_smul (char * str)
b99bd4ef
NC
3152{
3153 int rd, rm, rs;
3154
3155 skip_whitespace (str);
3156
3157 if ((rd = reg_required_here (& str, 16)) == FAIL
3158 || skip_past_comma (& str) == FAIL
3159 || (rm = reg_required_here (& str, 0)) == FAIL
3160 || skip_past_comma (& str) == FAIL
3161 || (rs = reg_required_here (& str, 8)) == FAIL)
3162 inst.error = BAD_ARGS;
3163
3164 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3165 inst.error = BAD_PC;
3166
b99bd4ef
NC
3167 else
3168 end_of_line (str);
3169}
3170
3171/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3172 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3173 Error if any register is R15. */
3174
3175static void
a737bd4d 3176do_qadd (char * str)
b99bd4ef
NC
3177{
3178 int rd, rm, rn;
3179
3180 skip_whitespace (str);
3181
3182 if ((rd = reg_required_here (& str, 12)) == FAIL
3183 || skip_past_comma (& str) == FAIL
3184 || (rm = reg_required_here (& str, 0)) == FAIL
3185 || skip_past_comma (& str) == FAIL
3186 || (rn = reg_required_here (& str, 16)) == FAIL)
3187 inst.error = BAD_ARGS;
3188
3189 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3190 inst.error = BAD_PC;
3191
b99bd4ef
NC
3192 else
3193 end_of_line (str);
3194}
3195
3196/* ARM V5E (el Segundo)
3197 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3198 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3199
3200 These are equivalent to the XScale instructions MAR and MRA,
3201 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3202
3203 Result unpredicatable if Rd or Rn is R15. */
3204
3205static void
a737bd4d 3206do_co_reg2c (char * str)
b99bd4ef
NC
3207{
3208 int rd, rn;
3209
3210 skip_whitespace (str);
3211
3212 if (co_proc_number (& str) == FAIL)
3213 {
3214 if (!inst.error)
3215 inst.error = BAD_ARGS;
3216 return;
3217 }
3218
3219 if (skip_past_comma (& str) == FAIL
3220 || cp_opc_expr (& str, 4, 4) == FAIL)
3221 {
3222 if (!inst.error)
3223 inst.error = BAD_ARGS;
3224 return;
3225 }
3226
3227 if (skip_past_comma (& str) == FAIL
3228 || (rd = reg_required_here (& str, 12)) == FAIL)
3229 {
3230 if (!inst.error)
3231 inst.error = BAD_ARGS;
3232 return;
3233 }
3234
3235 if (skip_past_comma (& str) == FAIL
3236 || (rn = reg_required_here (& str, 16)) == FAIL)
3237 {
3238 if (!inst.error)
3239 inst.error = BAD_ARGS;
3240 return;
3241 }
3242
09d92015
MM
3243 /* Unpredictable result if rd or rn is R15. */
3244 if (rd == REG_PC || rn == REG_PC)
3245 as_tsktsk
3246 (_("Warning: instruction unpredictable when using r15"));
3247
3248 if (skip_past_comma (& str) == FAIL
3249 || cp_reg_required_here (& str, 0) == FAIL)
3250 {
3251 if (!inst.error)
3252 inst.error = BAD_ARGS;
3253 return;
3254 }
3255
3256 end_of_line (str);
3257}
3258
3259/* ARM V5 count-leading-zeroes instruction (argument parse)
3260 CLZ{<cond>} <Rd>, <Rm>
3261 Condition defaults to COND_ALWAYS.
3262 Error if Rd or Rm are R15. */
3263
3264static void
a737bd4d 3265do_clz (char * str)
09d92015
MM
3266{
3267 int rd, rm;
3268
3269 skip_whitespace (str);
3270
3271 if (((rd = reg_required_here (& str, 12)) == FAIL)
3272 || (skip_past_comma (& str) == FAIL)
3273 || ((rm = reg_required_here (& str, 0)) == FAIL))
3274 inst.error = BAD_ARGS;
3275
3276 else if (rd == REG_PC || rm == REG_PC )
3277 inst.error = BAD_PC;
3278
3279 else
3280 end_of_line (str);
3281}
3282
3283/* ARM V5 (argument parse)
3284 LDC2{L} <coproc>, <CRd>, <addressing mode>
3285 STC2{L} <coproc>, <CRd>, <addressing mode>
3286 Instruction is not conditional, and has 0xf in the condition field.
3287 Otherwise, it's the same as LDC/STC. */
3288
3289static void
a737bd4d 3290do_lstc2 (char * str)
09d92015
MM
3291{
3292 skip_whitespace (str);
3293
3294 if (co_proc_number (& str) == FAIL)
3295 {
3296 if (!inst.error)
3297 inst.error = BAD_ARGS;
3298 }
3299 else if (skip_past_comma (& str) == FAIL
3300 || cp_reg_required_here (& str, 12) == FAIL)
3301 {
3302 if (!inst.error)
3303 inst.error = BAD_ARGS;
3304 }
3305 else if (skip_past_comma (& str) == FAIL
3306 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3307 {
3308 if (! inst.error)
3309 inst.error = BAD_ARGS;
3310 }
3311 else
3312 end_of_line (str);
3313}
3314
3315/* ARM V5 (argument parse)
3316 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3317 Instruction is not conditional, and has 0xf in the condition field.
3318 Otherwise, it's the same as CDP. */
3319
3320static void
a737bd4d 3321do_cdp2 (char * str)
09d92015
MM
3322{
3323 skip_whitespace (str);
3324
3325 if (co_proc_number (& str) == FAIL)
3326 {
3327 if (!inst.error)
3328 inst.error = BAD_ARGS;
3329 return;
3330 }
3331
3332 if (skip_past_comma (& str) == FAIL
3333 || cp_opc_expr (& str, 20,4) == FAIL)
3334 {
3335 if (!inst.error)
3336 inst.error = BAD_ARGS;
3337 return;
3338 }
3339
3340 if (skip_past_comma (& str) == FAIL
3341 || cp_reg_required_here (& str, 12) == FAIL)
3342 {
3343 if (!inst.error)
3344 inst.error = BAD_ARGS;
3345 return;
3346 }
3347
3348 if (skip_past_comma (& str) == FAIL
3349 || cp_reg_required_here (& str, 16) == FAIL)
3350 {
3351 if (!inst.error)
3352 inst.error = BAD_ARGS;
3353 return;
3354 }
3355
3356 if (skip_past_comma (& str) == FAIL
3357 || cp_reg_required_here (& str, 0) == FAIL)
3358 {
3359 if (!inst.error)
3360 inst.error = BAD_ARGS;
3361 return;
3362 }
3363
3364 if (skip_past_comma (& str) == SUCCESS)
3365 {
3366 if (cp_opc_expr (& str, 5, 3) == FAIL)
3367 {
3368 if (!inst.error)
3369 inst.error = BAD_ARGS;
3370 return;
3371 }
3372 }
3373
3374 end_of_line (str);
3375}
3376
3377/* ARM V5 (argument parse)
3378 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3379 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3380 Instruction is not conditional, and has 0xf in the condition field.
3381 Otherwise, it's the same as MCR/MRC. */
3382
3383static void
a737bd4d 3384do_co_reg2 (char * str)
09d92015
MM
3385{
3386 skip_whitespace (str);
3387
3388 if (co_proc_number (& str) == FAIL)
3389 {
3390 if (!inst.error)
3391 inst.error = BAD_ARGS;
3392 return;
3393 }
3394
3395 if (skip_past_comma (& str) == FAIL
3396 || cp_opc_expr (& str, 21, 3) == FAIL)
3397 {
3398 if (!inst.error)
3399 inst.error = BAD_ARGS;
3400 return;
3401 }
3402
3403 if (skip_past_comma (& str) == FAIL
3404 || reg_required_here (& str, 12) == FAIL)
3405 {
3406 if (!inst.error)
3407 inst.error = BAD_ARGS;
3408 return;
3409 }
3410
3411 if (skip_past_comma (& str) == FAIL
3412 || cp_reg_required_here (& str, 16) == FAIL)
3413 {
3414 if (!inst.error)
3415 inst.error = BAD_ARGS;
3416 return;
3417 }
3418
3419 if (skip_past_comma (& str) == FAIL
3420 || cp_reg_required_here (& str, 0) == FAIL)
3421 {
3422 if (!inst.error)
3423 inst.error = BAD_ARGS;
3424 return;
3425 }
3426
3427 if (skip_past_comma (& str) == SUCCESS)
3428 {
3429 if (cp_opc_expr (& str, 5, 3) == FAIL)
3430 {
3431 if (!inst.error)
3432 inst.error = BAD_ARGS;
3433 return;
3434 }
3435 }
3436
3437 end_of_line (str);
3438}
3439
a737bd4d
NC
3440static void
3441do_bx (char * str)
3442{
3443 int reg;
3444
3445 skip_whitespace (str);
3446
3447 if ((reg = reg_required_here (&str, 0)) == FAIL)
3448 {
3449 inst.error = BAD_ARGS;
3450 return;
3451 }
3452
3453 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3454 if (reg == REG_PC)
3455 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3456
3457 end_of_line (str);
3458}
3459
09d92015 3460/* ARM v5TEJ. Jump to Jazelle code. */
a737bd4d 3461
09d92015 3462static void
a737bd4d 3463do_bxj (char * str)
09d92015
MM
3464{
3465 int reg;
3466
3467 skip_whitespace (str);
3468
3469 if ((reg = reg_required_here (&str, 0)) == FAIL)
3470 {
3471 inst.error = BAD_ARGS;
3472 return;
3473 }
3474
a737bd4d
NC
3475 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3476 if (reg == REG_PC)
3477 as_tsktsk (_("use of r15 in bxj is not really useful"));
3478
3479 end_of_line (str);
3480}
3481
3482/* ARM V6 umaal (argument parse). */
3483
3484static void
3485do_umaal (char * str)
3486{
3487 int rdlo, rdhi, rm, rs;
3488
3489 skip_whitespace (str);
3490 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3491 || skip_past_comma (& str) == FAIL
3492 || (rdhi = reg_required_here (& str, 16)) == FAIL
3493 || skip_past_comma (& str) == FAIL
3494 || (rm = reg_required_here (& str, 0)) == FAIL
3495 || skip_past_comma (& str) == FAIL
3496 || (rs = reg_required_here (& str, 8)) == FAIL)
3497 {
3498 inst.error = BAD_ARGS;
3499 return;
3500 }
3501
3502 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3503 {
3504 inst.error = BAD_PC;
3505 return;
3506 }
3507
3508 end_of_line (str);
3509}
3510
3511/* ARM V6 strex (argument parse). */
3512
3513static void
3514do_strex (char * str)
3515{
3516 int rd, rm, rn;
3517
3518 /* Parse Rd, Rm,. */
3519 skip_whitespace (str);
3520 if ((rd = reg_required_here (& str, 12)) == FAIL
3521 || skip_past_comma (& str) == FAIL
3522 || (rm = reg_required_here (& str, 0)) == FAIL
3523 || skip_past_comma (& str) == FAIL)
3524 {
3525 inst.error = BAD_ARGS;
3526 return;
3527 }
3528 if (rd == REG_PC || rm == REG_PC)
3529 {
3530 inst.error = BAD_PC;
3531 return;
3532 }
3533 if (rd == rm)
3534 {
3535 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3536 return;
3537 }
3538
3539 /* Skip past '['. */
3540 if ((strlen (str) >= 1)
3541 && strncmp (str, "[", 1) == 0)
3542 str += 1;
3543
3544 skip_whitespace (str);
3545
3546 /* Parse Rn. */
3547 if ((rn = reg_required_here (& str, 16)) == FAIL)
3548 {
3549 inst.error = BAD_ARGS;
3550 return;
3551 }
3552 else if (rn == REG_PC)
3553 {
3554 inst.error = BAD_PC;
3555 return;
3556 }
3557 if (rd == rn)
3558 {
3559 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3560 return;
3561 }
3562 skip_whitespace (str);
3563
3564 /* Skip past ']'. */
3565 if ((strlen (str) >= 1)
3566 && strncmp (str, "]", 1) == 0)
3567 str += 1;
3568
3569 end_of_line (str);
3570}
3571
3572/* KIND indicates what kind of shifts are accepted. */
3573
3574static int
3575decode_shift (char ** str, int kind)
3576{
3577 const struct asm_shift_name * shift;
3578 char * p;
3579 char c;
3580
3581 skip_whitespace (* str);
3582
3583 for (p = * str; ISALPHA (* p); p ++)
3584 ;
3585
3586 if (p == * str)
3587 {
3588 inst.error = _("shift expression expected");
3589 return FAIL;
3590 }
3591
3592 c = * p;
3593 * p = '\0';
3594 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3595 * p = c;
3596
3597 if (shift == NULL)
3598 {
3599 inst.error = _("shift expression expected");
3600 return FAIL;
3601 }
3602
3603 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3604
3605 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3606 && shift->properties->index != SHIFT_LSL
3607 && shift->properties->index != SHIFT_ASR)
3608 {
3609 inst.error = _("'LSL' or 'ASR' required");
3610 return FAIL;
3611 }
3612 else if (kind == SHIFT_LSL_IMMEDIATE
3613 && shift->properties->index != SHIFT_LSL)
3614 {
3615 inst.error = _("'LSL' required");
3616 return FAIL;
3617 }
3618 else if (kind == SHIFT_ASR_IMMEDIATE
3619 && shift->properties->index != SHIFT_ASR)
3620 {
3621 inst.error = _("'ASR' required");
3622 return FAIL;
3623 }
3624
3625 if (shift->properties->index == SHIFT_RRX)
3626 {
3627 * str = p;
3628 inst.instruction |= shift->properties->bit_field;
3629 return SUCCESS;
3630 }
3631
3632 skip_whitespace (p);
3633
3634 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3635 {
3636 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3637 * str = p;
3638 return SUCCESS;
3639 }
3640 else if (! is_immediate_prefix (* p))
3641 {
3642 inst.error = (NO_SHIFT_RESTRICT
3643 ? _("shift requires register or #expression")
3644 : _("shift requires #expression"));
3645 * str = p;
3646 return FAIL;
3647 }
3648
3649 inst.error = NULL;
3650 p ++;
3651
3652 if (my_get_expression (& inst.reloc.exp, & p))
3653 return FAIL;
3654
3655 /* Validate some simple #expressions. */
3656 if (inst.reloc.exp.X_op == O_constant)
3657 {
3658 unsigned num = inst.reloc.exp.X_add_number;
3659
3660 /* Reject operations greater than 32. */
3661 if (num > 32
3662 /* Reject a shift of 0 unless the mode allows it. */
3663 || (num == 0 && shift->properties->allows_0 == 0)
3664 /* Reject a shift of 32 unless the mode allows it. */
3665 || (num == 32 && shift->properties->allows_32 == 0)
3666 )
3667 {
3668 /* As a special case we allow a shift of zero for
3669 modes that do not support it to be recoded as an
3670 logical shift left of zero (ie nothing). We warn
3671 about this though. */
3672 if (num == 0)
3673 {
3674 as_warn (_("shift of 0 ignored."));
3675 shift = & shift_names[0];
3676 assert (shift->properties->index == SHIFT_LSL);
3677 }
3678 else
3679 {
3680 inst.error = _("invalid immediate shift");
3681 return FAIL;
3682 }
3683 }
3684
3685 /* Shifts of 32 are encoded as 0, for those shifts that
3686 support it. */
3687 if (num == 32)
3688 num = 0;
3689
3690 inst.instruction |= (num << 7) | shift->properties->bit_field;
3691 }
3692 else
3693 {
3694 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3695 inst.reloc.pc_rel = 0;
3696 inst.instruction |= shift->properties->bit_field;
3697 }
3698
3699 * str = p;
3700 return SUCCESS;
09d92015
MM
3701}
3702
09d92015 3703static void
a737bd4d 3704do_sat (char ** str, int bias)
09d92015 3705{
a737bd4d
NC
3706 int rd, rm;
3707 expressionS expr;
09d92015 3708
a737bd4d 3709 skip_whitespace (*str);
09d92015 3710
a737bd4d
NC
3711 /* Parse <Rd>, field. */
3712 if ((rd = reg_required_here (str, 12)) == FAIL
3713 || skip_past_comma (str) == FAIL)
09d92015
MM
3714 {
3715 inst.error = BAD_ARGS;
a737bd4d 3716 return;
09d92015 3717 }
a737bd4d 3718 if (rd == REG_PC)
09d92015
MM
3719 {
3720 inst.error = BAD_PC;
3721 return;
3722 }
3723
a737bd4d
NC
3724 /* Parse #<immed>, field. */
3725 if (is_immediate_prefix (**str))
3726 (*str)++;
3727 else
09d92015 3728 {
a737bd4d 3729 inst.error = _("immediate expression expected");
09d92015
MM
3730 return;
3731 }
a737bd4d 3732 if (my_get_expression (&expr, str))
09d92015 3733 {
a737bd4d 3734 inst.error = _("bad expression");
09d92015
MM
3735 return;
3736 }
a737bd4d 3737 if (expr.X_op != O_constant)
09d92015 3738 {
a737bd4d 3739 inst.error = _("constant expression expected");
09d92015
MM
3740 return;
3741 }
a737bd4d
NC
3742 if (expr.X_add_number + bias < 0
3743 || expr.X_add_number + bias > 31)
3744 {
3745 inst.error = _("immediate value out of range");
3746 return;
3747 }
3748 inst.instruction |= (expr.X_add_number + bias) << 16;
3749 if (skip_past_comma (str) == FAIL)
09d92015
MM
3750 {
3751 inst.error = BAD_ARGS;
3752 return;
3753 }
a737bd4d
NC
3754
3755 /* Parse <Rm> field. */
3756 if ((rm = reg_required_here (str, 0)) == FAIL)
09d92015 3757 {
a737bd4d 3758 inst.error = BAD_ARGS;
09d92015
MM
3759 return;
3760 }
a737bd4d 3761 if (rm == REG_PC)
09d92015 3762 {
a737bd4d 3763 inst.error = BAD_PC;
09d92015
MM
3764 return;
3765 }
09d92015 3766
a737bd4d
NC
3767 if (skip_past_comma (str) == SUCCESS)
3768 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
09d92015
MM
3769}
3770
a737bd4d 3771/* ARM V6 ssat (argument parse). */
09d92015
MM
3772
3773static void
a737bd4d 3774do_ssat (char * str)
09d92015
MM
3775{
3776 do_sat (&str, /*bias=*/-1);
3777 end_of_line (str);
3778}
3779
a737bd4d 3780/* ARM V6 usat (argument parse). */
09d92015
MM
3781
3782static void
a737bd4d 3783do_usat (char * str)
09d92015
MM
3784{
3785 do_sat (&str, /*bias=*/0);
3786 end_of_line (str);
3787}
3788
3789static void
a737bd4d 3790do_sat16 (char ** str, int bias)
09d92015
MM
3791{
3792 int rd, rm;
3793 expressionS expr;
3794
3795 skip_whitespace (*str);
a737bd4d
NC
3796
3797 /* Parse the <Rd> field. */
09d92015
MM
3798 if ((rd = reg_required_here (str, 12)) == FAIL
3799 || skip_past_comma (str) == FAIL)
3800 {
3801 inst.error = BAD_ARGS;
3802 return;
3803 }
3804 if (rd == REG_PC)
3805 {
3806 inst.error = BAD_PC;
3807 return;
3808 }
3809
a737bd4d 3810 /* Parse #<immed>, field. */
09d92015
MM
3811 if (is_immediate_prefix (**str))
3812 (*str)++;
3813 else
3814 {
3815 inst.error = _("immediate expression expected");
3816 return;
3817 }
3818 if (my_get_expression (&expr, str))
3819 {
3820 inst.error = _("bad expression");
3821 return;
3822 }
3823 if (expr.X_op != O_constant)
3824 {
3825 inst.error = _("constant expression expected");
3826 return;
3827 }
3828 if (expr.X_add_number + bias < 0
a737bd4d 3829 || expr.X_add_number + bias > 15)
09d92015
MM
3830 {
3831 inst.error = _("immediate value out of range");
3832 return;
3833 }
3834 inst.instruction |= (expr.X_add_number + bias) << 16;
3835 if (skip_past_comma (str) == FAIL)
3836 {
3837 inst.error = BAD_ARGS;
3838 return;
3839 }
3840
a737bd4d 3841 /* Parse <Rm> field. */
09d92015
MM
3842 if ((rm = reg_required_here (str, 0)) == FAIL)
3843 {
3844 inst.error = BAD_ARGS;
3845 return;
3846 }
3847 if (rm == REG_PC)
3848 {
3849 inst.error = BAD_PC;
3850 return;
3851 }
09d92015
MM
3852}
3853
a737bd4d 3854/* ARM V6 ssat16 (argument parse). */
09d92015
MM
3855
3856static void
a737bd4d 3857do_ssat16 (char * str)
09d92015
MM
3858{
3859 do_sat16 (&str, /*bias=*/-1);
3860 end_of_line (str);
3861}
3862
3863static void
a737bd4d 3864do_usat16 (char * str)
09d92015
MM
3865{
3866 do_sat16 (&str, /*bias=*/0);
3867 end_of_line (str);
3868}
3869
3870static void
a737bd4d 3871do_cps_mode (char ** str)
09d92015 3872{
09d92015
MM
3873 expressionS expr;
3874
3875 skip_whitespace (*str);
3876
a737bd4d 3877 if (! is_immediate_prefix (**str))
09d92015
MM
3878 {
3879 inst.error = _("immediate expression expected");
3880 return;
3881 }
a737bd4d
NC
3882
3883 (*str)++; /* Strip off the immediate signifier. */
09d92015
MM
3884 if (my_get_expression (&expr, str))
3885 {
3886 inst.error = _("bad expression");
3887 return;
3888 }
a737bd4d 3889
09d92015
MM
3890 if (expr.X_op != O_constant)
3891 {
3892 inst.error = _("constant expression expected");
3893 return;
3894 }
09d92015 3895
a737bd4d
NC
3896 /* The mode is a 5 bit field. Valid values are 0-31. */
3897 if (((unsigned) expr.X_add_number) > 31
3898 || (inst.reloc.exp.X_add_number) < 0)
09d92015 3899 {
a737bd4d 3900 inst.error = _("invalid constant");
09d92015
MM
3901 return;
3902 }
a737bd4d
NC
3903
3904 inst.instruction |= expr.X_add_number;
09d92015
MM
3905}
3906
a737bd4d 3907/* ARM V6 srs (argument parse). */
09d92015
MM
3908
3909static void
a737bd4d 3910do_srs (char * str)
09d92015
MM
3911{
3912 char *exclam;
3913 skip_whitespace (str);
3914 exclam = strchr (str, '!');
3915 if (exclam)
3916 *exclam = '\0';
3917 do_cps_mode (&str);
3918 if (exclam)
3919 *exclam = '!';
a737bd4d 3920 if (*str == '!')
09d92015
MM
3921 {
3922 inst.instruction |= WRITE_BACK;
3923 str++;
3924 }
3925 end_of_line (str);
3926}
3927
a737bd4d 3928/* ARM V6 SMMUL (argument parse). */
09d92015
MM
3929
3930static void
a737bd4d 3931do_smmul (char * str)
09d92015
MM
3932{
3933 int rd, rm, rs;
a737bd4d 3934
09d92015
MM
3935 skip_whitespace (str);
3936 if ((rd = reg_required_here (&str, 16)) == FAIL
3937 || skip_past_comma (&str) == FAIL
3938 || (rm = reg_required_here (&str, 0)) == FAIL
3939 || skip_past_comma (&str) == FAIL
3940 || (rs = reg_required_here (&str, 8)) == FAIL)
3941 {
3942 inst.error = BAD_ARGS;
3943 return;
3944 }
3945
a737bd4d 3946 if ( rd == REG_PC
09d92015
MM
3947 || rm == REG_PC
3948 || rs == REG_PC)
3949 {
3950 inst.error = BAD_PC;
3951 return;
3952 }
3953
3954 end_of_line (str);
09d92015
MM
3955}
3956
a737bd4d 3957/* ARM V6 SMLALD (argument parse). */
09d92015
MM
3958
3959static void
a737bd4d 3960do_smlald (char * str)
09d92015
MM
3961{
3962 int rdlo, rdhi, rm, rs;
a737bd4d 3963
09d92015
MM
3964 skip_whitespace (str);
3965 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3966 || skip_past_comma (&str) == FAIL
3967 || (rdhi = reg_required_here (&str, 16)) == FAIL
3968 || skip_past_comma (&str) == FAIL
3969 || (rm = reg_required_here (&str, 0)) == FAIL
3970 || skip_past_comma (&str) == FAIL
3971 || (rs = reg_required_here (&str, 8)) == FAIL)
3972 {
3973 inst.error = BAD_ARGS;
3974 return;
3975 }
3976
a737bd4d
NC
3977 if ( rdlo == REG_PC
3978 || rdhi == REG_PC
09d92015
MM
3979 || rm == REG_PC
3980 || rs == REG_PC)
3981 {
3982 inst.error = BAD_PC;
3983 return;
3984 }
3985
3986 end_of_line (str);
3987}
3988
a737bd4d 3989/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
09d92015
MM
3990 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3991
a737bd4d
NC
3992static void
3993do_smlad (char * str)
09d92015
MM
3994{
3995 int rd, rm, rs, rn;
a737bd4d 3996
09d92015
MM
3997 skip_whitespace (str);
3998 if ((rd = reg_required_here (&str, 16)) == FAIL
3999 || skip_past_comma (&str) == FAIL
4000 || (rm = reg_required_here (&str, 0)) == FAIL
4001 || skip_past_comma (&str) == FAIL
4002 || (rs = reg_required_here (&str, 8)) == FAIL
4003 || skip_past_comma (&str) == FAIL
4004 || (rn = reg_required_here (&str, 12)) == FAIL)
4005 {
4006 inst.error = BAD_ARGS;
4007 return;
4008 }
a737bd4d
NC
4009
4010 if ( rd == REG_PC
4011 || rn == REG_PC
09d92015
MM
4012 || rs == REG_PC
4013 || rm == REG_PC)
4014 {
4015 inst.error = BAD_PC;
4016 return;
4017 }
4018
4019 end_of_line (str);
09d92015
MM
4020}
4021
4022/* Returns true if the endian-specifier indicates big-endianness. */
4023
4024static int
a737bd4d 4025do_endian_specifier (char * str)
09d92015
MM
4026{
4027 int big_endian = 0;
4028
4029 skip_whitespace (str);
4030 if (strlen (str) < 2)
4031 inst.error = _("missing endian specifier");
4032 else if (strncasecmp (str, "BE", 2) == 0)
4033 {
4034 str += 2;
4035 big_endian = 1;
4036 }
4037 else if (strncasecmp (str, "LE", 2) == 0)
4038 str += 2;
4039 else
4040 inst.error = _("valid endian specifiers are be or le");
4041
4042 end_of_line (str);
4043
4044 return big_endian;
4045}
4046
a737bd4d
NC
4047/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4048 preserving the other bits.
4049
4050 setend <endian_specifier>, where <endian_specifier> is either
4051 BE or LE. */
4052
4053static void
4054do_setend (char * str)
4055{
4056 if (do_endian_specifier (str))
4057 inst.instruction |= 0x200;
4058}
4059
09d92015
MM
4060/* ARM V6 SXTH.
4061
4062 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4063 Condition defaults to COND_ALWAYS.
a737bd4d 4064 Error if any register uses R15. */
09d92015 4065
a737bd4d
NC
4066static void
4067do_sxth (char * str)
09d92015
MM
4068{
4069 int rd, rm;
4070 expressionS expr;
4071 int rotation_clear_mask = 0xfffff3ff;
4072 int rotation_eight_mask = 0x00000400;
4073 int rotation_sixteen_mask = 0x00000800;
4074 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4075
09d92015
MM
4076 skip_whitespace (str);
4077 if ((rd = reg_required_here (&str, 12)) == FAIL
4078 || skip_past_comma (&str) == FAIL
4079 || (rm = reg_required_here (&str, 0)) == FAIL)
4080 {
4081 inst.error = BAD_ARGS;
4082 return;
4083 }
4084
4085 else if (rd == REG_PC || rm == REG_PC)
4086 {
4087 inst.error = BAD_PC;
4088 return;
4089 }
a737bd4d
NC
4090
4091 /* Zero out the rotation field. */
09d92015 4092 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4093
4094 /* Check for lack of optional rotation field. */
09d92015
MM
4095 if (skip_past_comma (&str) == FAIL)
4096 {
4097 end_of_line (str);
4098 return;
4099 }
a737bd4d
NC
4100
4101 /* Move past 'ROR'. */
09d92015
MM
4102 skip_whitespace (str);
4103 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4104 str += 3;
09d92015
MM
4105 else
4106 {
4107 inst.error = _("missing rotation field after comma");
4108 return;
4109 }
a737bd4d
NC
4110
4111 /* Get the immediate constant. */
09d92015
MM
4112 skip_whitespace (str);
4113 if (is_immediate_prefix (* str))
4114 str++;
4115 else
4116 {
4117 inst.error = _("immediate expression expected");
4118 return;
4119 }
a737bd4d 4120
09d92015
MM
4121 if (my_get_expression (&expr, &str))
4122 {
4123 inst.error = _("bad expression");
4124 return;
4125 }
4126
4127 if (expr.X_op != O_constant)
4128 {
4129 inst.error = _("constant expression expected");
4130 return;
4131 }
a737bd4d
NC
4132
4133 switch (expr.X_add_number)
09d92015
MM
4134 {
4135 case 0:
a737bd4d 4136 /* Rotation field has already been zeroed. */
09d92015
MM
4137 break;
4138 case 8:
4139 inst.instruction |= rotation_eight_mask;
4140 break;
4141
4142 case 16:
4143 inst.instruction |= rotation_sixteen_mask;
4144 break;
a737bd4d 4145
09d92015
MM
4146 case 24:
4147 inst.instruction |= rotation_twenty_four_mask;
4148 break;
4149
4150 default:
4151 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4152 break;
4153 }
4154
4155 end_of_line (str);
09d92015
MM
4156}
4157
4158/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4159 extends it to 32-bits, and adds the result to a value in another
4160 register. You can specify a rotation by 0, 8, 16, or 24 bits
4161 before extracting the 16-bit value.
4162 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4163 Condition defaults to COND_ALWAYS.
a737bd4d 4164 Error if any register uses R15. */
09d92015 4165
a737bd4d
NC
4166static void
4167do_sxtah (char * str)
09d92015
MM
4168{
4169 int rd, rn, rm;
4170 expressionS expr;
4171 int rotation_clear_mask = 0xfffff3ff;
4172 int rotation_eight_mask = 0x00000400;
4173 int rotation_sixteen_mask = 0x00000800;
4174 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4175
09d92015
MM
4176 skip_whitespace (str);
4177 if ((rd = reg_required_here (&str, 12)) == FAIL
4178 || skip_past_comma (&str) == FAIL
4179 || (rn = reg_required_here (&str, 16)) == FAIL
4180 || skip_past_comma (&str) == FAIL
4181 || (rm = reg_required_here (&str, 0)) == FAIL)
4182 {
4183 inst.error = BAD_ARGS;
4184 return;
4185 }
4186
4187 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4188 {
4189 inst.error = BAD_PC;
4190 return;
4191 }
a737bd4d
NC
4192
4193 /* Zero out the rotation field. */
09d92015 4194 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4195
4196 /* Check for lack of optional rotation field. */
09d92015
MM
4197 if (skip_past_comma (&str) == FAIL)
4198 {
4199 end_of_line (str);
4200 return;
4201 }
a737bd4d
NC
4202
4203 /* Move past 'ROR'. */
09d92015
MM
4204 skip_whitespace (str);
4205 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4206 str += 3;
09d92015
MM
4207 else
4208 {
4209 inst.error = _("missing rotation field after comma");
4210 return;
4211 }
a737bd4d
NC
4212
4213 /* Get the immediate constant. */
09d92015
MM
4214 skip_whitespace (str);
4215 if (is_immediate_prefix (* str))
4216 str++;
4217 else
4218 {
4219 inst.error = _("immediate expression expected");
4220 return;
4221 }
a737bd4d 4222
09d92015
MM
4223 if (my_get_expression (&expr, &str))
4224 {
4225 inst.error = _("bad expression");
4226 return;
4227 }
4228
4229 if (expr.X_op != O_constant)
4230 {
4231 inst.error = _("constant expression expected");
4232 return;
4233 }
a737bd4d
NC
4234
4235 switch (expr.X_add_number)
09d92015
MM
4236 {
4237 case 0:
a737bd4d 4238 /* Rotation field has already been zeroed. */
09d92015
MM
4239 break;
4240
4241 case 8:
4242 inst.instruction |= rotation_eight_mask;
4243 break;
4244
4245 case 16:
4246 inst.instruction |= rotation_sixteen_mask;
4247 break;
a737bd4d 4248
09d92015
MM
4249 case 24:
4250 inst.instruction |= rotation_twenty_four_mask;
4251 break;
4252
4253 default:
4254 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4255 break;
4256 }
4257
4258 end_of_line (str);
09d92015 4259}
a737bd4d 4260
09d92015
MM
4261
4262/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4263 word at the specified address and the following word
a737bd4d 4264 respectively.
09d92015 4265 Unconditionally executed.
a737bd4d 4266 Error if Rn is R15. */
09d92015
MM
4267
4268static void
a737bd4d 4269do_rfe (char * str)
09d92015
MM
4270{
4271 int rn;
4272
4273 skip_whitespace (str);
a737bd4d 4274
09d92015
MM
4275 if ((rn = reg_required_here (&str, 16)) == FAIL)
4276 return;
b99bd4ef 4277
09d92015 4278 if (rn == REG_PC)
b99bd4ef 4279 {
09d92015 4280 inst.error = BAD_PC;
b99bd4ef
NC
4281 return;
4282 }
4283
09d92015 4284 skip_whitespace (str);
a737bd4d 4285
09d92015
MM
4286 if (*str == '!')
4287 {
4288 inst.instruction |= WRITE_BACK;
4289 str++;
4290 }
b99bd4ef
NC
4291 end_of_line (str);
4292}
4293
09d92015
MM
4294/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4295 register (argument parse).
4296 REV{<cond>} Rd, Rm.
4297 Condition defaults to COND_ALWAYS.
a737bd4d 4298 Error if Rd or Rm are R15. */
b99bd4ef
NC
4299
4300static void
a737bd4d 4301do_rev (char * str)
b99bd4ef
NC
4302{
4303 int rd, rm;
4304
b99bd4ef
NC
4305 skip_whitespace (str);
4306
09d92015
MM
4307 if ((rd = reg_required_here (&str, 12)) == FAIL
4308 || skip_past_comma (&str) == FAIL
4309 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
4310 inst.error = BAD_ARGS;
4311
09d92015 4312 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
4313 inst.error = BAD_PC;
4314
4315 else
4316 end_of_line (str);
4317}
4318
09d92015 4319/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
a737bd4d 4320 QADD16{<cond>} <Rd>, <Rn>, <Rm>
09d92015
MM
4321 Condition defaults to COND_ALWAYS.
4322 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
4323
4324static void
a737bd4d 4325do_qadd16 (char * str)
b99bd4ef 4326{
09d92015
MM
4327 int rd, rm, rn;
4328
b99bd4ef
NC
4329 skip_whitespace (str);
4330
09d92015
MM
4331 if ((rd = reg_required_here (&str, 12)) == FAIL
4332 || skip_past_comma (&str) == FAIL
4333 || (rn = reg_required_here (&str, 16)) == FAIL
4334 || skip_past_comma (&str) == FAIL
4335 || (rm = reg_required_here (&str, 0)) == FAIL)
4336 inst.error = BAD_ARGS;
4337
4338 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4339 inst.error = BAD_PC;
4340
b99bd4ef
NC
4341 else
4342 end_of_line (str);
4343}
4344
b99bd4ef 4345static void
a737bd4d 4346do_pkh_core (char * str, int shift)
b99bd4ef 4347{
09d92015 4348 int rd, rn, rm;
b99bd4ef 4349
09d92015
MM
4350 skip_whitespace (str);
4351 if (((rd = reg_required_here (&str, 12)) == FAIL)
4352 || (skip_past_comma (&str) == FAIL)
4353 || ((rn = reg_required_here (&str, 16)) == FAIL)
4354 || (skip_past_comma (&str) == FAIL)
4355 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 4356 {
09d92015 4357 inst.error = BAD_ARGS;
b99bd4ef
NC
4358 return;
4359 }
4360
09d92015 4361 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 4362 {
09d92015 4363 inst.error = BAD_PC;
b99bd4ef
NC
4364 return;
4365 }
4366
a737bd4d
NC
4367 /* Check for optional shift immediate constant. */
4368 if (skip_past_comma (&str) == FAIL)
b99bd4ef 4369 {
09d92015
MM
4370 if (shift == SHIFT_ASR_IMMEDIATE)
4371 {
4372 /* If the shift specifier is ommited, turn the instruction
4373 into pkhbt rd, rm, rn. First, switch the instruction
4374 code, and clear the rn and rm fields. */
4375 inst.instruction &= 0xfff0f010;
4376 /* Now, re-encode the registers. */
4377 inst.instruction |= (rm << 16) | rn;
4378 }
b99bd4ef
NC
4379 return;
4380 }
4381
09d92015
MM
4382 decode_shift (&str, shift);
4383}
4384
a737bd4d
NC
4385/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4386 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4387 Condition defaults to COND_ALWAYS.
4388 Error if Rd, Rn or Rm are R15. */
4389
4390static void
4391do_pkhbt (char * str)
4392{
4393 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4394}
4395
4396/* ARM V6 PKHTB (Argument Parse). */
4397
4398static void
4399do_pkhtb (char * str)
4400{
4401 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4402}
4403
09d92015 4404/* ARM V6 Load Register Exclusive instruction (argument parse).
0dd132b6 4405 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
09d92015 4406 Condition defaults to COND_ALWAYS.
a737bd4d
NC
4407 Error if Rd or Rn are R15.
4408 See ARMARMv6 A4.1.27: LDREX. */
09d92015
MM
4409
4410static void
a737bd4d 4411do_ldrex (char * str)
09d92015
MM
4412{
4413 int rd, rn;
4414
4415 skip_whitespace (str);
4416
a737bd4d 4417 /* Parse Rd. */
09d92015
MM
4418 if (((rd = reg_required_here (&str, 12)) == FAIL)
4419 || (skip_past_comma (&str) == FAIL))
b99bd4ef 4420 {
09d92015 4421 inst.error = BAD_ARGS;
b99bd4ef
NC
4422 return;
4423 }
09d92015 4424 else if (rd == REG_PC)
b99bd4ef 4425 {
09d92015 4426 inst.error = BAD_PC;
b99bd4ef
NC
4427 return;
4428 }
a737bd4d 4429 skip_whitespace (str);
b99bd4ef 4430
a737bd4d
NC
4431 /* Skip past '['. */
4432 if ((strlen (str) >= 1)
09d92015 4433 &&strncmp (str, "[", 1) == 0)
a737bd4d
NC
4434 str += 1;
4435 skip_whitespace (str);
09d92015 4436
a737bd4d 4437 /* Parse Rn. */
09d92015 4438 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 4439 {
09d92015
MM
4440 inst.error = BAD_ARGS;
4441 return;
b99bd4ef 4442 }
09d92015
MM
4443 else if (rn == REG_PC)
4444 {
4445 inst.error = BAD_PC;
4446 return;
4447 }
a737bd4d 4448 skip_whitespace (str);
b99bd4ef 4449
a737bd4d
NC
4450 /* Skip past ']'. */
4451 if ((strlen (str) >= 1)
09d92015 4452 && strncmp (str, "]", 1) == 0)
a737bd4d
NC
4453 str += 1;
4454
b99bd4ef
NC
4455 end_of_line (str);
4456}
4457
09d92015 4458/* ARM V6 change processor state instruction (argument parse)
a737bd4d 4459 CPS, CPSIE, CSPID . */
b99bd4ef
NC
4460
4461static void
a737bd4d 4462do_cps (char * str)
b99bd4ef 4463{
09d92015
MM
4464 do_cps_mode (&str);
4465 end_of_line (str);
4466}
b99bd4ef 4467
09d92015 4468static void
a737bd4d 4469do_cps_flags (char ** str, int thumb_p)
ea6ef066 4470{
a737bd4d
NC
4471 struct cps_flag
4472 {
09d92015
MM
4473 char character;
4474 unsigned long arm_value;
4475 unsigned long thumb_value;
4476 };
a737bd4d
NC
4477 static struct cps_flag flag_table[] =
4478 {
09d92015
MM
4479 {'a', 0x100, 0x4 },
4480 {'i', 0x080, 0x2 },
4481 {'f', 0x040, 0x1 }
4482 };
ea6ef066 4483
09d92015 4484 int saw_a_flag = 0;
ea6ef066 4485
09d92015
MM
4486 skip_whitespace (*str);
4487
a737bd4d 4488 /* Get the a, f and i flags. */
09d92015 4489 while (**str && **str != ',')
ea6ef066 4490 {
09d92015
MM
4491 struct cps_flag *p;
4492 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
a737bd4d 4493
09d92015
MM
4494 for (p = flag_table; p < q; ++p)
4495 if (strncasecmp (*str, &p->character, 1) == 0)
4496 {
4497 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4498 saw_a_flag = 1;
4499 break;
4500 }
4501 if (p == q)
4502 {
4503 inst.error = _("unrecognized flag");
4504 return;
4505 }
4506 (*str)++;
ea6ef066 4507 }
a737bd4d
NC
4508
4509 if (!saw_a_flag)
4510 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4511}
4512
4513static void
4514do_cpsi (char * str)
4515{
4516 do_cps_flags (&str, /*thumb_p=*/0);
4517
4518 if (skip_past_comma (&str) == SUCCESS)
4519 {
4520 skip_whitespace (str);
4521 do_cps_mode (&str);
4522 }
4523 end_of_line (str);
ea6ef066
RE
4524}
4525
b99bd4ef
NC
4526/* THUMB V5 breakpoint instruction (argument parse)
4527 BKPT <immed_8>. */
4528
4529static void
a737bd4d 4530do_t_bkpt (char * str)
b99bd4ef
NC
4531{
4532 expressionS expr;
4533 unsigned long number;
4534
4535 skip_whitespace (str);
4536
4537 /* Allow optional leading '#'. */
4538 if (is_immediate_prefix (*str))
4539 str ++;
4540
4541 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
4542 if (my_get_expression (& expr, & str)
4543 || (expr.X_op != O_constant
4544 /* As a convenience we allow 'bkpt' without an operand. */
4545 && expr.X_op != O_absent))
b99bd4ef 4546 {
143c8e19 4547 inst.error = _("bad expression");
b99bd4ef
NC
4548 return;
4549 }
4550
4551 number = expr.X_add_number;
4552
4553 /* Check it fits an 8 bit unsigned. */
4554 if (number != (number & 0xff))
4555 {
4556 inst.error = _("immediate value out of range");
4557 return;
4558 }
4559
4560 inst.instruction |= number;
4561
4562 end_of_line (str);
4563}
4564
a737bd4d
NC
4565static bfd_reloc_code_real_type
4566arm_parse_reloc (void)
4567{
4568 char id [16];
4569 char * ip;
4570 unsigned int i;
4571 static struct
4572 {
4573 char * str;
4574 int len;
4575 bfd_reloc_code_real_type reloc;
4576 }
4577 reloc_map[] =
4578 {
4579#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4580 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4581 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4582 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4583 branch instructions generated by GCC for PLT relocs. */
4584 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4585 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4586 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4587 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4588 { NULL, 0, BFD_RELOC_UNUSED }
4589#undef MAP
4590 };
4591
4592 for (i = 0, ip = input_line_pointer;
4593 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4594 i++, ip++)
4595 id[i] = TOLOWER (*ip);
4596
4597 for (i = 0; reloc_map[i].str; i++)
4598 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4599 break;
4600
4601 input_line_pointer += reloc_map[i].len;
4602
4603 return reloc_map[i].reloc;
4604}
4605
b99bd4ef
NC
4606/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4607 Expects inst.instruction is set for BLX(1).
4608 Note: this is cloned from do_branch, and the reloc changed to be a
4609 new one that can cope with setting one extra bit (the H bit). */
4610
4611static void
a737bd4d 4612do_branch25 (char * str)
b99bd4ef
NC
4613{
4614 if (my_get_expression (& inst.reloc.exp, & str))
4615 return;
4616
4617#ifdef OBJ_ELF
4618 {
4619 char * save_in;
4620
4621 /* ScottB: February 5, 1998 */
4622 /* Check to see of PLT32 reloc required for the instruction. */
4623
4624 /* arm_parse_reloc() works on input_line_pointer.
4625 We actually want to parse the operands to the branch instruction
4626 passed in 'str'. Save the input pointer and restore it later. */
4627 save_in = input_line_pointer;
4628 input_line_pointer = str;
4629
4630 if (inst.reloc.exp.X_op == O_symbol
4631 && *str == '('
4632 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4633 {
4634 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4635 inst.reloc.pc_rel = 0;
4636 /* Modify str to point to after parsed operands, otherwise
4637 end_of_line() will complain about the (PLT) left in str. */
4638 str = input_line_pointer;
4639 }
4640 else
4641 {
4642 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4643 inst.reloc.pc_rel = 1;
4644 }
4645
4646 input_line_pointer = save_in;
4647 }
4648#else
4649 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4650 inst.reloc.pc_rel = 1;
4651#endif /* OBJ_ELF */
4652
4653 end_of_line (str);
4654}
4655
4656/* ARM V5 branch-link-exchange instruction (argument parse)
4657 BLX <target_addr> ie BLX(1)
4658 BLX{<condition>} <Rm> ie BLX(2)
4659 Unfortunately, there are two different opcodes for this mnemonic.
4660 So, the insns[].value is not used, and the code here zaps values
4661 into inst.instruction.
4662 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4663
4664static void
a737bd4d 4665do_blx (char * str)
b99bd4ef
NC
4666{
4667 char * mystr = str;
4668 int rm;
4669
b99bd4ef
NC
4670 skip_whitespace (mystr);
4671 rm = reg_required_here (& mystr, 0);
4672
4673 /* The above may set inst.error. Ignore his opinion. */
4674 inst.error = 0;
4675
4676 if (rm != FAIL)
4677 {
4678 /* Arg is a register.
4679 Use the condition code our caller put in inst.instruction.
4680 Pass ourselves off as a BX with a funny opcode. */
4681 inst.instruction |= 0x012fff30;
f2b7cb0a 4682 do_bx (str);
b99bd4ef
NC
4683 }
4684 else
4685 {
4686 /* This must be is BLX <target address>, no condition allowed. */
4687 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4688 {
4689 inst.error = BAD_COND;
b99bd4ef 4690 return;
cc8a6dd0 4691 }
b99bd4ef
NC
4692
4693 inst.instruction = 0xfafffffe;
4694
4695 /* Process like a B/BL, but with a different reloc.
4696 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4697 do_branch25 (str);
b99bd4ef
NC
4698 }
4699}
4700
4701/* ARM V5 Thumb BLX (argument parse)
4702 BLX <target_addr> which is BLX(1)
4703 BLX <Rm> which is BLX(2)
4704 Unfortunately, there are two different opcodes for this mnemonic.
4705 So, the tinsns[].value is not used, and the code here zaps values
4706 into inst.instruction. */
4707
4708static void
a737bd4d 4709do_t_blx (char * str)
b99bd4ef
NC
4710{
4711 char * mystr = str;
4712 int rm;
4713
4714 skip_whitespace (mystr);
4715 inst.instruction = 0x4780;
4716
4717 /* Note that this call is to the ARM register recognizer. BLX(2)
4718 uses the ARM register space, not the Thumb one, so a call to
4719 thumb_reg() would be wrong. */
4720 rm = reg_required_here (& mystr, 3);
4721 inst.error = 0;
4722
4723 if (rm != FAIL)
4724 {
4725 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4726 inst.size = 2;
4727 }
4728 else
4729 {
4730 /* No ARM register. This must be BLX(1). Change the .instruction. */
4731 inst.instruction = 0xf7ffeffe;
4732 inst.size = 4;
4733
4734 if (my_get_expression (& inst.reloc.exp, & mystr))
4735 return;
4736
4737 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4738 inst.reloc.pc_rel = 1;
4739 }
4740
4741 end_of_line (mystr);
4742}
4743
4744/* ARM V5 breakpoint instruction (argument parse)
4745 BKPT <16 bit unsigned immediate>
4746 Instruction is not conditional.
4747 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 4748 and it is an error if the caller tried to override that. */
b99bd4ef
NC
4749
4750static void
a737bd4d 4751do_bkpt (char * str)
b99bd4ef
NC
4752{
4753 expressionS expr;
4754 unsigned long number;
4755
4756 skip_whitespace (str);
4757
4758 /* Allow optional leading '#'. */
4759 if (is_immediate_prefix (* str))
4760 str++;
4761
4762 memset (& expr, '\0', sizeof (expr));
4763
143c8e19
NC
4764 if (my_get_expression (& expr, & str)
4765 || (expr.X_op != O_constant
4766 /* As a convenience we allow 'bkpt' without an operand. */
4767 && expr.X_op != O_absent))
b99bd4ef 4768 {
143c8e19 4769 inst.error = _("bad expression");
b99bd4ef
NC
4770 return;
4771 }
4772
4773 number = expr.X_add_number;
4774
4775 /* Check it fits a 16 bit unsigned. */
4776 if (number != (number & 0xffff))
4777 {
4778 inst.error = _("immediate value out of range");
4779 return;
4780 }
4781
4782 /* Top 12 of 16 bits to bits 19:8. */
4783 inst.instruction |= (number & 0xfff0) << 4;
4784
4785 /* Bottom 4 of 16 bits to bits 3:0. */
4786 inst.instruction |= number & 0xf;
4787
4788 end_of_line (str);
b99bd4ef
NC
4789}
4790
09d92015
MM
4791/* THUMB CPS instruction (argument parse). */
4792
4793static void
a737bd4d 4794do_t_cps (char * str)
09d92015
MM
4795{
4796 do_cps_flags (&str, /*thumb_p=*/1);
4797 end_of_line (str);
4798}
4799
a737bd4d
NC
4800/* Parse and validate that a register is of the right form, this saves
4801 repeated checking of this information in many similar cases.
4802 Unlike the 32-bit case we do not insert the register into the opcode
4803 here, since the position is often unknown until the full instruction
4804 has been parsed. */
4805
4806static int
4807thumb_reg (char ** strp, int hi_lo)
4808{
4809 int reg;
4810
4811 if ((reg = reg_required_here (strp, -1)) == FAIL)
4812 return FAIL;
4813
4814 switch (hi_lo)
4815 {
4816 case THUMB_REG_LO:
4817 if (reg > 7)
4818 {
4819 inst.error = _("lo register required");
4820 return FAIL;
4821 }
4822 break;
4823
4824 case THUMB_REG_HI:
4825 if (reg < 8)
4826 {
4827 inst.error = _("hi register required");
4828 return FAIL;
4829 }
4830 break;
4831
4832 default:
4833 break;
4834 }
4835
4836 return reg;
4837}
4838
4839static void
4840thumb_mov_compare (char * str, int move)
4841{
4842 int Rd, Rs = FAIL;
4843
4844 skip_whitespace (str);
4845
4846 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4847 || skip_past_comma (&str) == FAIL)
4848 {
4849 if (! inst.error)
4850 inst.error = BAD_ARGS;
4851 return;
4852 }
4853
4854 if (move != THUMB_CPY && is_immediate_prefix (*str))
4855 {
4856 str++;
4857 if (my_get_expression (&inst.reloc.exp, &str))
4858 return;
4859 }
4860 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4861 return;
4862
4863 if (Rs != FAIL)
4864 {
4865 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4866 {
4867 if (move == THUMB_MOVE)
4868 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4869 since a MOV instruction produces unpredictable results. */
4870 inst.instruction = T_OPCODE_ADD_I3;
4871 else
4872 inst.instruction = T_OPCODE_CMP_LR;
4873 inst.instruction |= Rd | (Rs << 3);
4874 }
4875 else
4876 {
4877 if (move == THUMB_MOVE)
4878 inst.instruction = T_OPCODE_MOV_HR;
4879 else if (move != THUMB_CPY)
4880 inst.instruction = T_OPCODE_CMP_HR;
4881
4882 if (Rd > 7)
4883 inst.instruction |= THUMB_H1;
4884
4885 if (Rs > 7)
4886 inst.instruction |= THUMB_H2;
4887
4888 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4889 }
4890 }
4891 else
4892 {
4893 if (Rd > 7)
4894 {
4895 inst.error = _("only lo regs allowed with immediate");
4896 return;
4897 }
4898
4899 if (move == THUMB_MOVE)
4900 inst.instruction = T_OPCODE_MOV_I8;
4901 else
4902 inst.instruction = T_OPCODE_CMP_I8;
4903
4904 inst.instruction |= Rd << 8;
4905
4906 if (inst.reloc.exp.X_op != O_constant)
4907 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4908 else
4909 {
4910 unsigned value = inst.reloc.exp.X_add_number;
4911
4912 if (value > 255)
4913 {
4914 inst.error = _("invalid immediate");
4915 return;
4916 }
4917
4918 inst.instruction |= value;
4919 }
4920 }
4921
4922 end_of_line (str);
4923}
4924
09d92015
MM
4925/* THUMB CPY instruction (argument parse). */
4926
4927static void
a737bd4d 4928do_t_cpy (char * str)
09d92015
MM
4929{
4930 thumb_mov_compare (str, THUMB_CPY);
4931}
4932
4933/* THUMB SETEND instruction (argument parse). */
4934
4935static void
a737bd4d 4936do_t_setend (char * str)
09d92015
MM
4937{
4938 if (do_endian_specifier (str))
4939 inst.instruction |= 0x8;
4940}
4941
e16bb312
NC
4942/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4943
4944static unsigned long
a737bd4d
NC
4945check_iwmmxt_insn (char * str,
4946 enum iwmmxt_insn_type insn_type,
4947 int immediate_size)
e16bb312
NC
4948{
4949 int reg = 0;
4950 const char * inst_error;
4951 expressionS expr;
4952 unsigned long number;
4953
4954 inst_error = inst.error;
4955 if (!inst.error)
4956 inst.error = BAD_ARGS;
4957 skip_whitespace (str);
4958
4959 switch (insn_type)
4960 {
4961 case check_rd:
4962 if ((reg = reg_required_here (&str, 12)) == FAIL)
4963 return FAIL;
4964 break;
a737bd4d 4965
e16bb312
NC
4966 case check_wr:
4967 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4968 return FAIL;
4969 break;
a737bd4d 4970
e16bb312
NC
4971 case check_wrwr:
4972 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4973 || skip_past_comma (&str) == FAIL
4974 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4975 return FAIL;
4976 break;
a737bd4d 4977
e16bb312
NC
4978 case check_wrwrwr:
4979 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4980 || skip_past_comma (&str) == FAIL
4981 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4982 || skip_past_comma (&str) == FAIL
4983 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4984 return FAIL;
4985 break;
a737bd4d 4986
e16bb312
NC
4987 case check_wrwrwcg:
4988 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4989 || skip_past_comma (&str) == FAIL
4990 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4991 || skip_past_comma (&str) == FAIL
4992 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4993 return FAIL;
4994 break;
a737bd4d 4995
e16bb312
NC
4996 case check_tbcst:
4997 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4998 || skip_past_comma (&str) == FAIL
4999 || reg_required_here (&str, 12) == FAIL))
5000 return FAIL;
5001 break;
a737bd4d 5002
e16bb312
NC
5003 case check_tmovmsk:
5004 if ((reg_required_here (&str, 12) == FAIL
5005 || skip_past_comma (&str) == FAIL
5006 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5007 return FAIL;
5008 break;
a737bd4d 5009
e16bb312
NC
5010 case check_tmia:
5011 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5012 || skip_past_comma (&str) == FAIL
5013 || reg_required_here (&str, 0) == FAIL
5014 || skip_past_comma (&str) == FAIL
5015 || reg_required_here (&str, 12) == FAIL))
5016 return FAIL;
5017 break;
a737bd4d 5018
e16bb312
NC
5019 case check_tmcrr:
5020 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5021 || skip_past_comma (&str) == FAIL
5022 || reg_required_here (&str, 12) == FAIL
5023 || skip_past_comma (&str) == FAIL
5024 || reg_required_here (&str, 16) == FAIL))
5025 return FAIL;
5026 break;
a737bd4d 5027
e16bb312
NC
5028 case check_tmrrc:
5029 if ((reg_required_here (&str, 12) == FAIL
5030 || skip_past_comma (&str) == FAIL
5031 || reg_required_here (&str, 16) == FAIL
5032 || skip_past_comma (&str) == FAIL
5033 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5034 return FAIL;
5035 break;
a737bd4d 5036
e16bb312
NC
5037 case check_tmcr:
5038 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5039 || skip_past_comma (&str) == FAIL
5040 || reg_required_here (&str, 12) == FAIL))
5041 return FAIL;
5042 break;
a737bd4d 5043
e16bb312
NC
5044 case check_tmrc:
5045 if ((reg_required_here (&str, 12) == FAIL
5046 || skip_past_comma (&str) == FAIL
5047 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5048 return FAIL;
5049 break;
a737bd4d 5050
e16bb312
NC
5051 case check_tinsr:
5052 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5053 || skip_past_comma (&str) == FAIL
5054 || reg_required_here (&str, 12) == FAIL
5055 || skip_past_comma (&str) == FAIL))
5056 return FAIL;
5057 break;
a737bd4d 5058
e16bb312
NC
5059 case check_textrc:
5060 if ((reg_required_here (&str, 12) == FAIL
5061 || skip_past_comma (&str) == FAIL))
5062 return FAIL;
5063 break;
a737bd4d 5064
e16bb312
NC
5065 case check_waligni:
5066 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5067 || skip_past_comma (&str) == FAIL
5068 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5069 || skip_past_comma (&str) == FAIL
5070 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5071 || skip_past_comma (&str) == FAIL))
5072 return FAIL;
5073 break;
a737bd4d 5074
e16bb312
NC
5075 case check_textrm:
5076 if ((reg_required_here (&str, 12) == FAIL
5077 || skip_past_comma (&str) == FAIL
5078 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5079 || skip_past_comma (&str) == FAIL))
5080 return FAIL;
5081 break;
a737bd4d 5082
e16bb312
NC
5083 case check_wshufh:
5084 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5085 || skip_past_comma (&str) == FAIL
5086 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5087 || skip_past_comma (&str) == FAIL))
5088 return FAIL;
5089 break;
5090 }
a737bd4d 5091
e16bb312
NC
5092 if (immediate_size == 0)
5093 {
5094 end_of_line (str);
5095 inst.error = inst_error;
5096 return reg;
5097 }
5098 else
5099 {
a737bd4d
NC
5100 skip_whitespace (str);
5101
5102 /* Allow optional leading '#'. */
e16bb312
NC
5103 if (is_immediate_prefix (* str))
5104 str++;
5105
5106 memset (& expr, '\0', sizeof (expr));
a737bd4d 5107
e16bb312
NC
5108 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5109 {
5110 inst.error = _("bad or missing expression");
5111 return FAIL;
5112 }
a737bd4d 5113
e16bb312 5114 number = expr.X_add_number;
a737bd4d 5115
e16bb312
NC
5116 if (number != (number & immediate_size))
5117 {
5118 inst.error = _("immediate value out of range");
5119 return FAIL;
5120 }
5121 end_of_line (str);
5122 inst.error = inst_error;
5123 return number;
5124 }
5125}
5126
5127static void
a737bd4d 5128do_iwmmxt_byte_addr (char * str)
e16bb312
NC
5129{
5130 int op = (inst.instruction & 0x300) >> 8;
5131 int reg;
5132
5133 inst.instruction &= ~0x300;
a737bd4d 5134 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5135
5136 skip_whitespace (str);
5137
5138 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5139 || skip_past_comma (& str) == FAIL
5140 || cp_byte_address_required_here (&str) == FAIL)
5141 {
5142 if (! inst.error)
5143 inst.error = BAD_ARGS;
5144 }
5145 else
5146 end_of_line (str);
5147
5148 if (wc_register (reg))
5149 {
ece01a63 5150 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5151 inst.instruction |= 0xf0000100;
5152 inst.instruction &= ~0x00400000;
5153 }
5154}
5155
5156static void
a737bd4d 5157do_iwmmxt_tandc (char * str)
e16bb312
NC
5158{
5159 int reg;
5160
5161 reg = check_iwmmxt_insn (str, check_rd, 0);
5162
5163 if (reg != REG_PC && !inst.error)
5164 inst.error = _("only r15 allowed here");
e16bb312
NC
5165}
5166
5167static void
a737bd4d 5168do_iwmmxt_tbcst (char * str)
e16bb312
NC
5169{
5170 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
5171}
5172
5173static void
a737bd4d 5174do_iwmmxt_textrc (char * str)
e16bb312
NC
5175{
5176 unsigned long number;
5177
5178 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5179 return;
5180
5181 inst.instruction |= number & 0x7;
e16bb312
NC
5182}
5183
5184static void
a737bd4d 5185do_iwmmxt_textrm (char * str)
e16bb312
NC
5186{
5187 unsigned long number;
5188
5189 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5190 return;
5191
5192 inst.instruction |= number & 0x7;
5193}
5194
5195static void
a737bd4d 5196do_iwmmxt_tinsr (char * str)
e16bb312
NC
5197{
5198 unsigned long number;
5199
5200 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5201 return;
5202
5203 inst.instruction |= number & 0x7;
e16bb312
NC
5204}
5205
5206static void
a737bd4d 5207do_iwmmxt_tmcr (char * str)
e16bb312
NC
5208{
5209 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
5210}
5211
5212static void
a737bd4d 5213do_iwmmxt_tmcrr (char * str)
e16bb312
NC
5214{
5215 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
5216}
5217
5218static void
a737bd4d 5219do_iwmmxt_tmia (char * str)
e16bb312
NC
5220{
5221 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
5222}
5223
5224static void
a737bd4d 5225do_iwmmxt_tmovmsk (char * str)
e16bb312
NC
5226{
5227 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
5228}
5229
5230static void
a737bd4d 5231do_iwmmxt_tmrc (char * str)
e16bb312
NC
5232{
5233 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
5234}
5235
5236static void
a737bd4d 5237do_iwmmxt_tmrrc (char * str)
e16bb312
NC
5238{
5239 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
5240}
5241
5242static void
a737bd4d 5243do_iwmmxt_torc (char * str)
e16bb312
NC
5244{
5245 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
5246}
5247
5248static void
a737bd4d 5249do_iwmmxt_waligni (char * str)
e16bb312
NC
5250{
5251 unsigned long number;
5252
5253 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5254 return;
5255
5256 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
5257}
5258
5259static void
a737bd4d 5260do_iwmmxt_wmov (char * str)
e16bb312
NC
5261{
5262 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5263 return;
a737bd4d 5264
e16bb312 5265 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
5266}
5267
5268static void
a737bd4d 5269do_iwmmxt_word_addr (char * str)
e16bb312
NC
5270{
5271 int op = (inst.instruction & 0x300) >> 8;
5272 int reg;
5273
5274 inst.instruction &= ~0x300;
a737bd4d 5275 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5276
5277 skip_whitespace (str);
5278
5279 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5280 || skip_past_comma (& str) == FAIL
5281 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5282 {
5283 if (! inst.error)
5284 inst.error = BAD_ARGS;
5285 }
5286 else
5287 end_of_line (str);
5288
5289 if (wc_register (reg))
5290 {
ece01a63
ILT
5291 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5292 as_bad (_("conditional execution not supported with control register"));
5293 if (op != 2)
5294 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5295 inst.instruction |= 0xf0000100;
5296 inst.instruction &= ~0x00400000;
5297 }
5298}
5299
5300static void
a737bd4d 5301do_iwmmxt_wrwr (char * str)
e16bb312
NC
5302{
5303 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
5304}
5305
5306static void
a737bd4d 5307do_iwmmxt_wrwrwcg (char * str)
e16bb312
NC
5308{
5309 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
5310}
5311
5312static void
a737bd4d 5313do_iwmmxt_wrwrwr (char * str)
e16bb312
NC
5314{
5315 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
5316}
5317
5318static void
a737bd4d 5319do_iwmmxt_wshufh (char * str)
e16bb312
NC
5320{
5321 unsigned long number;
5322
5323 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5324 return;
5325
5326 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
5327}
5328
5329static void
a737bd4d 5330do_iwmmxt_wzero (char * str)
e16bb312
NC
5331{
5332 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5333 return;
5334
5335 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
5336}
5337
b99bd4ef
NC
5338/* Xscale multiply-accumulate (argument parse)
5339 MIAcc acc0,Rm,Rs
5340 MIAPHcc acc0,Rm,Rs
5341 MIAxycc acc0,Rm,Rs. */
5342
5343static void
a737bd4d 5344do_xsc_mia (char * str)
b99bd4ef
NC
5345{
5346 int rs;
5347 int rm;
5348
f2b7cb0a 5349 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5350 inst.error = ERR_NO_ACCUM;
5351
5352 else if (skip_past_comma (& str) == FAIL
5353 || (rm = reg_required_here (& str, 0)) == FAIL)
5354 inst.error = BAD_ARGS;
5355
5356 else if (skip_past_comma (& str) == FAIL
5357 || (rs = reg_required_here (& str, 12)) == FAIL)
5358 inst.error = BAD_ARGS;
5359
5360 /* inst.instruction has now been zapped with both rm and rs. */
5361 else if (rm == REG_PC || rs == REG_PC)
5362 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5363
5364 else
5365 end_of_line (str);
5366}
5367
5368/* Xscale move-accumulator-register (argument parse)
5369
5370 MARcc acc0,RdLo,RdHi. */
5371
5372static void
a737bd4d 5373do_xsc_mar (char * str)
b99bd4ef
NC
5374{
5375 int rdlo, rdhi;
5376
f2b7cb0a 5377 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5378 inst.error = ERR_NO_ACCUM;
5379
5380 else if (skip_past_comma (& str) == FAIL
5381 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5382 inst.error = BAD_ARGS;
5383
5384 else if (skip_past_comma (& str) == FAIL
5385 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5386 inst.error = BAD_ARGS;
5387
5388 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5389 else if (rdlo == REG_PC || rdhi == REG_PC)
5390 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5391
5392 else
5393 end_of_line (str);
5394}
5395
5396/* Xscale move-register-accumulator (argument parse)
5397
5398 MRAcc RdLo,RdHi,acc0. */
5399
5400static void
a737bd4d 5401do_xsc_mra (char * str)
b99bd4ef
NC
5402{
5403 int rdlo;
5404 int rdhi;
5405
b99bd4ef
NC
5406 skip_whitespace (str);
5407
5408 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5409 inst.error = BAD_ARGS;
5410
5411 else if (skip_past_comma (& str) == FAIL
5412 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5413 inst.error = BAD_ARGS;
5414
5415 else if (skip_past_comma (& str) == FAIL
5416 || accum0_required_here (& str) == FAIL)
5417 inst.error = ERR_NO_ACCUM;
5418
a737bd4d
NC
5419 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5420 else if (rdlo == rdhi)
5421 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5422
5423 else if (rdlo == REG_PC || rdhi == REG_PC)
5424 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5425 else
5426 end_of_line (str);
5427}
5428
5429static int
5430ldst_extend (char ** str)
5431{
5432 int add = INDEX_UP;
5433
5434 switch (**str)
5435 {
5436 case '#':
5437 case '$':
5438 (*str)++;
5439 if (my_get_expression (& inst.reloc.exp, str))
5440 return FAIL;
5441
5442 if (inst.reloc.exp.X_op == O_constant)
5443 {
5444 int value = inst.reloc.exp.X_add_number;
5445
5446 if (value < -4095 || value > 4095)
5447 {
5448 inst.error = _("address offset too large");
5449 return FAIL;
5450 }
5451
5452 if (value < 0)
5453 {
5454 value = -value;
5455 add = 0;
5456 }
5457
5458 inst.instruction |= add | value;
5459 }
5460 else
5461 {
5462 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5463 inst.reloc.pc_rel = 0;
5464 }
5465 return SUCCESS;
5466
5467 case '-':
5468 add = 0;
5469 /* Fall through. */
5470
5471 case '+':
5472 (*str)++;
5473 /* Fall through. */
5474
5475 default:
5476 if (reg_required_here (str, 0) == FAIL)
5477 return FAIL;
5478
5479 inst.instruction |= add | OFFSET_REG;
5480 if (skip_past_comma (str) == SUCCESS)
5481 return decode_shift (str, SHIFT_IMMEDIATE);
b99bd4ef 5482
a737bd4d
NC
5483 return SUCCESS;
5484 }
b99bd4ef
NC
5485}
5486
c9b604bd 5487/* ARMv5TE: Preload-Cache
b99bd4ef
NC
5488
5489 PLD <addr_mode>
5490
5491 Syntactically, like LDR with B=1, W=0, L=1. */
5492
5493static void
a737bd4d 5494do_pld (char * str)
b99bd4ef
NC
5495{
5496 int rd;
5497
b99bd4ef
NC
5498 skip_whitespace (str);
5499
5500 if (* str != '[')
5501 {
5502 inst.error = _("'[' expected after PLD mnemonic");
5503 return;
5504 }
5505
90e4755a 5506 ++str;
b99bd4ef
NC
5507 skip_whitespace (str);
5508
5509 if ((rd = reg_required_here (& str, 16)) == FAIL)
5510 return;
5511
5512 skip_whitespace (str);
5513
90e4755a 5514 if (*str == ']')
b99bd4ef
NC
5515 {
5516 /* [Rn], ... ? */
90e4755a 5517 ++str;
b99bd4ef
NC
5518 skip_whitespace (str);
5519
90e4755a
RE
5520 /* Post-indexed addressing is not allowed with PLD. */
5521 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5522 {
90e4755a
RE
5523 inst.error
5524 = _("post-indexed expression used in preload instruction");
5525 return;
b99bd4ef 5526 }
90e4755a 5527 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
5528 {
5529 inst.error = _("writeback used in preload instruction");
90e4755a 5530 ++str;
b99bd4ef
NC
5531 }
5532 else /* [Rn] */
5533 inst.instruction |= INDEX_UP | PRE_INDEX;
5534 }
5535 else /* [Rn, ...] */
5536 {
5537 if (skip_past_comma (& str) == FAIL)
5538 {
5539 inst.error = _("pre-indexed expression expected");
5540 return;
5541 }
5542
90e4755a 5543 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
5544 return;
5545
5546 skip_whitespace (str);
5547
5548 if (* str != ']')
5549 {
5550 inst.error = _("missing ]");
5551 return;
5552 }
5553
5554 ++ str;
5555 skip_whitespace (str);
5556
5557 if (* str == '!') /* [Rn]! */
5558 {
5559 inst.error = _("writeback used in preload instruction");
5560 ++ str;
5561 }
5562
5563 inst.instruction |= PRE_INDEX;
5564 }
5565
5566 end_of_line (str);
5567}
5568
c9b604bd 5569/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
5570 Mode is like LDRH.
5571
5572 LDRccD R, mode
5573 STRccD R, mode. */
5574
5575static void
a737bd4d 5576do_ldrd (char * str)
b99bd4ef
NC
5577{
5578 int rd;
5579 int rn;
5580
b99bd4ef
NC
5581 skip_whitespace (str);
5582
5583 if ((rd = reg_required_here (& str, 12)) == FAIL)
5584 {
5585 inst.error = BAD_ARGS;
5586 return;
5587 }
5588
5589 if (skip_past_comma (& str) == FAIL
5590 || (rn = ld_mode_required_here (& str)) == FAIL)
5591 {
5592 if (!inst.error)
cc8a6dd0 5593 inst.error = BAD_ARGS;
a737bd4d 5594 return;
b99bd4ef
NC
5595 }
5596
a737bd4d
NC
5597 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5598 if (rd & 1) /* Unpredictable result if Rd is odd. */
5599 {
5600 inst.error = _("destination register must be even");
5601 return;
5602 }
b99bd4ef 5603
a737bd4d 5604 if (rd == REG_LR)
b99bd4ef 5605 {
a737bd4d
NC
5606 inst.error = _("r14 not allowed here");
5607 return;
b99bd4ef 5608 }
a737bd4d
NC
5609
5610 if (((rd == rn) || (rd + 1 == rn))
5611 && ((inst.instruction & WRITE_BACK)
5612 || (!(inst.instruction & PRE_INDEX))))
5613 as_warn (_("pre/post-indexing used when modified address register is destination"));
5614
5615 /* For an index-register load, the index register must not overlap the
5616 destination (even if not write-back). */
5617 if ((inst.instruction & V4_STR_BIT) == 0
5618 && (inst.instruction & HWOFFSET_IMM) == 0)
b99bd4ef 5619 {
a737bd4d
NC
5620 int rm = inst.instruction & 0x0000000f;
5621
5622 if (rm == rd || (rm == rd + 1))
5623 as_warn (_("ldrd destination registers must not overlap index register"));
b99bd4ef
NC
5624 }
5625
a737bd4d
NC
5626 end_of_line (str);
5627}
b99bd4ef 5628
a737bd4d
NC
5629/* Returns the index into fp_values of a floating point number,
5630 or -1 if not in the table. */
b99bd4ef 5631
a737bd4d
NC
5632static int
5633my_get_float_expression (char ** str)
5634{
5635 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5636 char * save_in;
5637 expressionS exp;
5638 int i;
5639 int j;
b99bd4ef 5640
a737bd4d
NC
5641 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5642
5643 /* Look for a raw floating point number. */
5644 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5645 && is_end_of_line[(unsigned char) *save_in])
5646 {
5647 for (i = 0; i < NUM_FLOAT_VALS; i++)
b99bd4ef 5648 {
a737bd4d 5649 for (j = 0; j < MAX_LITTLENUMS; j++)
b99bd4ef 5650 {
a737bd4d
NC
5651 if (words[j] != fp_values[i][j])
5652 break;
b99bd4ef 5653 }
a737bd4d
NC
5654
5655 if (j == MAX_LITTLENUMS)
b99bd4ef 5656 {
a737bd4d
NC
5657 *str = save_in;
5658 return i;
b99bd4ef
NC
5659 }
5660 }
a737bd4d 5661 }
b99bd4ef 5662
a737bd4d
NC
5663 /* Try and parse a more complex expression, this will probably fail
5664 unless the code uses a floating point prefix (eg "0f"). */
5665 save_in = input_line_pointer;
5666 input_line_pointer = *str;
5667 if (expression (&exp) == absolute_section
5668 && exp.X_op == O_big
5669 && exp.X_add_number < 0)
5670 {
5671 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5672 Ditto for 15. */
5673 if (gen_to_words (words, 5, (long) 15) == 0)
5674 {
5675 for (i = 0; i < NUM_FLOAT_VALS; i++)
5676 {
5677 for (j = 0; j < MAX_LITTLENUMS; j++)
5678 {
5679 if (words[j] != fp_values[i][j])
5680 break;
5681 }
b99bd4ef 5682
a737bd4d
NC
5683 if (j == MAX_LITTLENUMS)
5684 {
5685 *str = input_line_pointer;
5686 input_line_pointer = save_in;
5687 return i;
5688 }
5689 }
5690 }
b99bd4ef 5691 }
a737bd4d
NC
5692
5693 *str = input_line_pointer;
5694 input_line_pointer = save_in;
5695 return -1;
5696}
5697
5698/* We handle all bad expressions here, so that we can report the faulty
5699 instruction in the error message. */
5700void
5701md_operand (expressionS * expr)
5702{
5703 if (in_my_get_expression)
b99bd4ef 5704 {
a737bd4d
NC
5705 expr->X_op = O_illegal;
5706 if (inst.error == NULL)
5707 inst.error = _("bad expression");
b99bd4ef 5708 }
b99bd4ef
NC
5709}
5710
5711/* Do those data_ops which can take a negative immediate constant
2d2255b5 5712 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
5713 MOV <-> MVN
5714 AND <-> BIC
5715 ADC <-> SBC
5716 by inverting the second operand, and
5717 ADD <-> SUB
5718 CMP <-> CMN
5719 by negating the second operand. */
5720
5721static int
a737bd4d
NC
5722negate_data_op (unsigned long * instruction,
5723 unsigned long value)
b99bd4ef
NC
5724{
5725 int op, new_inst;
5726 unsigned long negated, inverted;
5727
5728 negated = validate_immediate (-value);
5729 inverted = validate_immediate (~value);
5730
5731 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5732 switch (op)
5733 {
5734 /* First negates. */
5735 case OPCODE_SUB: /* ADD <-> SUB */
5736 new_inst = OPCODE_ADD;
5737 value = negated;
5738 break;
5739
5740 case OPCODE_ADD:
5741 new_inst = OPCODE_SUB;
5742 value = negated;
5743 break;
5744
5745 case OPCODE_CMP: /* CMP <-> CMN */
5746 new_inst = OPCODE_CMN;
5747 value = negated;
5748 break;
5749
5750 case OPCODE_CMN:
5751 new_inst = OPCODE_CMP;
5752 value = negated;
5753 break;
5754
5755 /* Now Inverted ops. */
5756 case OPCODE_MOV: /* MOV <-> MVN */
5757 new_inst = OPCODE_MVN;
5758 value = inverted;
5759 break;
5760
5761 case OPCODE_MVN:
5762 new_inst = OPCODE_MOV;
5763 value = inverted;
5764 break;
5765
5766 case OPCODE_AND: /* AND <-> BIC */
5767 new_inst = OPCODE_BIC;
5768 value = inverted;
5769 break;
5770
5771 case OPCODE_BIC:
5772 new_inst = OPCODE_AND;
5773 value = inverted;
5774 break;
5775
5776 case OPCODE_ADC: /* ADC <-> SBC */
5777 new_inst = OPCODE_SBC;
5778 value = inverted;
5779 break;
5780
5781 case OPCODE_SBC:
5782 new_inst = OPCODE_ADC;
5783 value = inverted;
5784 break;
5785
5786 /* We cannot do anything. */
5787 default:
5788 return FAIL;
5789 }
5790
5791 if (value == (unsigned) FAIL)
5792 return FAIL;
5793
5794 *instruction &= OPCODE_MASK;
5795 *instruction |= new_inst << DATA_OP_SHIFT;
5796 return value;
5797}
5798
5799static int
a737bd4d 5800data_op2 (char ** str)
b99bd4ef
NC
5801{
5802 int value;
5803 expressionS expr;
5804
5805 skip_whitespace (* str);
5806
5807 if (reg_required_here (str, 0) != FAIL)
5808 {
5809 if (skip_past_comma (str) == SUCCESS)
5810 /* Shift operation on register. */
5811 return decode_shift (str, NO_SHIFT_RESTRICT);
5812
5813 return SUCCESS;
5814 }
5815 else
5816 {
5817 /* Immediate expression. */
5818 if (is_immediate_prefix (**str))
5819 {
5820 (*str)++;
5821 inst.error = NULL;
5822
5823 if (my_get_expression (&inst.reloc.exp, str))
5824 return FAIL;
5825
5826 if (inst.reloc.exp.X_add_symbol)
5827 {
5828 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5829 inst.reloc.pc_rel = 0;
5830 }
5831 else
5832 {
5833 if (skip_past_comma (str) == SUCCESS)
5834 {
5835 /* #x, y -- ie explicit rotation by Y. */
5836 if (my_get_expression (&expr, str))
5837 return FAIL;
5838
5839 if (expr.X_op != O_constant)
5840 {
f03698e6 5841 inst.error = _("constant expression expected");
b99bd4ef
NC
5842 return FAIL;
5843 }
5844
5845 /* Rotate must be a multiple of 2. */
5846 if (((unsigned) expr.X_add_number) > 30
5847 || (expr.X_add_number & 1) != 0
5848 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5849 {
f03698e6 5850 inst.error = _("invalid constant");
b99bd4ef
NC
5851 return FAIL;
5852 }
5853 inst.instruction |= INST_IMMEDIATE;
5854 inst.instruction |= inst.reloc.exp.X_add_number;
5855 inst.instruction |= expr.X_add_number << 7;
5856 return SUCCESS;
5857 }
5858
5859 /* Implicit rotation, select a suitable one. */
5860 value = validate_immediate (inst.reloc.exp.X_add_number);
5861
5862 if (value == FAIL)
5863 {
5864 /* Can't be done. Perhaps the code reads something like
5865 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5866 if ((value = negate_data_op (&inst.instruction,
5867 inst.reloc.exp.X_add_number))
5868 == FAIL)
5869 {
f03698e6 5870 inst.error = _("invalid constant");
b99bd4ef
NC
5871 return FAIL;
5872 }
5873 }
5874
5875 inst.instruction |= value;
5876 }
5877
5878 inst.instruction |= INST_IMMEDIATE;
5879 return SUCCESS;
5880 }
5881
5882 (*str)++;
f03698e6 5883 inst.error = _("register or shift expression expected");
b99bd4ef
NC
5884 return FAIL;
5885 }
5886}
5887
5888static int
a737bd4d 5889fp_op2 (char ** str)
b99bd4ef
NC
5890{
5891 skip_whitespace (* str);
5892
5893 if (fp_reg_required_here (str, 0) != FAIL)
5894 return SUCCESS;
5895 else
5896 {
5897 /* Immediate expression. */
5898 if (*((*str)++) == '#')
5899 {
5900 int i;
5901
5902 inst.error = NULL;
5903
5904 skip_whitespace (* str);
5905
5906 /* First try and match exact strings, this is to guarantee
5907 that some formats will work even for cross assembly. */
5908
5909 for (i = 0; fp_const[i]; i++)
5910 {
5911 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5912 {
5913 char *start = *str;
5914
5915 *str += strlen (fp_const[i]);
5916 if (is_end_of_line[(unsigned char) **str])
5917 {
5918 inst.instruction |= i + 8;
5919 return SUCCESS;
5920 }
5921 *str = start;
5922 }
5923 }
5924
5925 /* Just because we didn't get a match doesn't mean that the
5926 constant isn't valid, just that it is in a format that we
5927 don't automatically recognize. Try parsing it with
5928 the standard expression routines. */
5929 if ((i = my_get_float_expression (str)) >= 0)
5930 {
5931 inst.instruction |= i + 8;
5932 return SUCCESS;
5933 }
5934
f03698e6 5935 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
5936 return FAIL;
5937 }
5938 inst.error =
f03698e6 5939 _("floating point register or immediate expression expected");
b99bd4ef
NC
5940 return FAIL;
5941 }
5942}
5943
5944static void
a737bd4d 5945do_arit (char * str)
b99bd4ef
NC
5946{
5947 skip_whitespace (str);
5948
5949 if (reg_required_here (&str, 12) == FAIL
5950 || skip_past_comma (&str) == FAIL
5951 || reg_required_here (&str, 16) == FAIL
5952 || skip_past_comma (&str) == FAIL
5953 || data_op2 (&str) == FAIL)
5954 {
5955 if (!inst.error)
5956 inst.error = BAD_ARGS;
5957 return;
5958 }
5959
b99bd4ef 5960 end_of_line (str);
b99bd4ef
NC
5961}
5962
5963static void
a737bd4d 5964do_adr (char * str)
b99bd4ef 5965{
90e4755a
RE
5966 /* This is a pseudo-op of the form "adr rd, label" to be converted
5967 into a relative address of the form "add rd, pc, #label-.-8". */
5968 skip_whitespace (str);
5969
5970 if (reg_required_here (&str, 12) == FAIL
5971 || skip_past_comma (&str) == FAIL
5972 || my_get_expression (&inst.reloc.exp, &str))
5973 {
5974 if (!inst.error)
5975 inst.error = BAD_ARGS;
5976 return;
5977 }
5978
5979 /* Frag hacking will turn this into a sub instruction if the offset turns
5980 out to be negative. */
5981 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 5982#ifndef TE_WINCE
90e4755a 5983 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 5984#endif
90e4755a
RE
5985 inst.reloc.pc_rel = 1;
5986
5987 end_of_line (str);
5988}
5989
5990static void
a737bd4d 5991do_adrl (char * str)
90e4755a
RE
5992{
5993 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5994 into a relative address of the form:
5995 add rd, pc, #low(label-.-8)"
5996 add rd, rd, #high(label-.-8)" */
5997
5998 skip_whitespace (str);
5999
6000 if (reg_required_here (&str, 12) == FAIL
6001 || skip_past_comma (&str) == FAIL
6002 || my_get_expression (&inst.reloc.exp, &str))
6003 {
6004 if (!inst.error)
6005 inst.error = BAD_ARGS;
6006
6007 return;
6008 }
6009
6010 end_of_line (str);
6011 /* Frag hacking will turn this into a sub instruction if the offset turns
6012 out to be negative. */
6013 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
a737bd4d 6014#ifndef TE_WINCE
90e4755a 6015 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 6016#endif
90e4755a
RE
6017 inst.reloc.pc_rel = 1;
6018 inst.size = INSN_SIZE * 2;
90e4755a
RE
6019}
6020
6021static void
a737bd4d 6022do_cmp (char * str)
90e4755a
RE
6023{
6024 skip_whitespace (str);
6025
6026 if (reg_required_here (&str, 16) == FAIL)
6027 {
6028 if (!inst.error)
6029 inst.error = BAD_ARGS;
6030 return;
6031 }
6032
6033 if (skip_past_comma (&str) == FAIL
6034 || data_op2 (&str) == FAIL)
6035 {
6036 if (!inst.error)
6037 inst.error = BAD_ARGS;
6038 return;
6039 }
6040
90e4755a 6041 end_of_line (str);
90e4755a
RE
6042}
6043
6044static void
a737bd4d 6045do_mov (char * str)
90e4755a
RE
6046{
6047 skip_whitespace (str);
6048
6049 if (reg_required_here (&str, 12) == FAIL)
6050 {
6051 if (!inst.error)
6052 inst.error = BAD_ARGS;
6053 return;
6054 }
6055
6056 if (skip_past_comma (&str) == FAIL
6057 || data_op2 (&str) == FAIL)
6058 {
6059 if (!inst.error)
6060 inst.error = BAD_ARGS;
6061 return;
6062 }
6063
90e4755a 6064 end_of_line (str);
90e4755a
RE
6065}
6066
90e4755a 6067static void
a737bd4d 6068do_ldst (char * str)
90e4755a
RE
6069{
6070 int pre_inc = 0;
6071 int conflict_reg;
6072 int value;
6073
b99bd4ef
NC
6074 skip_whitespace (str);
6075
90e4755a
RE
6076 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6077 {
6078 if (!inst.error)
6079 inst.error = BAD_ARGS;
6080 return;
6081 }
6082
6083 if (skip_past_comma (&str) == FAIL)
6084 {
f03698e6 6085 inst.error = _("address expected");
90e4755a
RE
6086 return;
6087 }
6088
90e4755a
RE
6089 if (*str == '[')
6090 {
6091 int reg;
6092
6093 str++;
6094
6095 skip_whitespace (str);
6096
6097 if ((reg = reg_required_here (&str, 16)) == FAIL)
6098 return;
6099
6100 /* Conflicts can occur on stores as well as loads. */
6101 conflict_reg = (conflict_reg == reg);
6102
6103 skip_whitespace (str);
6104
6105 if (*str == ']')
6106 {
6107 str ++;
6108
6109 if (skip_past_comma (&str) == SUCCESS)
6110 {
6111 /* [Rn],... (post inc) */
6112 if (ldst_extend (&str) == FAIL)
6113 return;
6114 if (conflict_reg)
6115 as_warn (_("%s register same as write-back base"),
6116 ((inst.instruction & LOAD_BIT)
6117 ? _("destination") : _("source")));
6118 }
6119 else
6120 {
6121 /* [Rn] */
6122 skip_whitespace (str);
6123
6124 if (*str == '!')
6125 {
6126 if (conflict_reg)
6127 as_warn (_("%s register same as write-back base"),
6128 ((inst.instruction & LOAD_BIT)
6129 ? _("destination") : _("source")));
6130 str++;
6131 inst.instruction |= WRITE_BACK;
6132 }
6133
6134 inst.instruction |= INDEX_UP;
6135 pre_inc = 1;
6136 }
6137 }
6138 else
6139 {
6140 /* [Rn,...] */
6141 if (skip_past_comma (&str) == FAIL)
6142 {
6143 inst.error = _("pre-indexed expression expected");
6144 return;
6145 }
6146
6147 pre_inc = 1;
6148 if (ldst_extend (&str) == FAIL)
6149 return;
6150
6151 skip_whitespace (str);
6152
6153 if (*str++ != ']')
6154 {
6155 inst.error = _("missing ]");
6156 return;
6157 }
6158
6159 skip_whitespace (str);
6160
6161 if (*str == '!')
6162 {
6163 if (conflict_reg)
6164 as_warn (_("%s register same as write-back base"),
6165 ((inst.instruction & LOAD_BIT)
6166 ? _("destination") : _("source")));
6167 str++;
6168 inst.instruction |= WRITE_BACK;
6169 }
6170 }
6171 }
6172 else if (*str == '=')
6173 {
f03698e6
RE
6174 if ((inst.instruction & LOAD_BIT) == 0)
6175 {
6176 inst.error = _("invalid pseudo operation");
6177 return;
6178 }
6179
90e4755a
RE
6180 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6181 str++;
6182
6183 skip_whitespace (str);
6184
6185 if (my_get_expression (&inst.reloc.exp, &str))
6186 return;
6187
6188 if (inst.reloc.exp.X_op != O_constant
6189 && inst.reloc.exp.X_op != O_symbol)
6190 {
f03698e6 6191 inst.error = _("constant expression expected");
90e4755a
RE
6192 return;
6193 }
6194
e28cd48c 6195 if (inst.reloc.exp.X_op == O_constant)
90e4755a 6196 {
e28cd48c
RE
6197 value = validate_immediate (inst.reloc.exp.X_add_number);
6198
6199 if (value != FAIL)
90e4755a 6200 {
e28cd48c
RE
6201 /* This can be done with a mov instruction. */
6202 inst.instruction &= LITERAL_MASK;
6203 inst.instruction |= (INST_IMMEDIATE
6204 | (OPCODE_MOV << DATA_OP_SHIFT));
6205 inst.instruction |= value & 0xfff;
6206 end_of_line (str);
90e4755a
RE
6207 return;
6208 }
b99bd4ef 6209
e28cd48c
RE
6210 value = validate_immediate (~inst.reloc.exp.X_add_number);
6211
6212 if (value != FAIL)
6213 {
6214 /* This can be done with a mvn instruction. */
6215 inst.instruction &= LITERAL_MASK;
6216 inst.instruction |= (INST_IMMEDIATE
6217 | (OPCODE_MVN << DATA_OP_SHIFT));
6218 inst.instruction |= value & 0xfff;
6219 end_of_line (str);
6220 return;
6221 }
90e4755a 6222 }
e28cd48c
RE
6223
6224 /* Insert into literal pool. */
6225 if (add_to_lit_pool () == FAIL)
6226 {
6227 if (!inst.error)
6228 inst.error = _("literal pool insertion failed");
6229 return;
6230 }
6231
6232 /* Change the instruction exp to point to the pool. */
6233 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6234 inst.reloc.pc_rel = 1;
6235 inst.instruction |= (REG_PC << 16);
6236 pre_inc = 1;
1cac9012
NC
6237 }
6238 else
6239 {
90e4755a
RE
6240 if (my_get_expression (&inst.reloc.exp, &str))
6241 return;
6242
6243 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6244#ifndef TE_WINCE
6245 /* PC rel adjust. */
6246 inst.reloc.exp.X_add_number -= 8;
6247#endif
1cac9012 6248 inst.reloc.pc_rel = 1;
90e4755a
RE
6249 inst.instruction |= (REG_PC << 16);
6250 pre_inc = 1;
b99bd4ef
NC
6251 }
6252
90e4755a 6253 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6254 end_of_line (str);
b99bd4ef
NC
6255}
6256
6257static void
a737bd4d 6258do_ldstt (char * str)
b99bd4ef 6259{
90e4755a
RE
6260 int conflict_reg;
6261
b99bd4ef
NC
6262 skip_whitespace (str);
6263
90e4755a 6264 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
6265 {
6266 if (!inst.error)
6267 inst.error = BAD_ARGS;
6268 return;
6269 }
6270
90e4755a 6271 if (skip_past_comma (& str) == FAIL)
b99bd4ef 6272 {
f03698e6 6273 inst.error = _("address expected");
b99bd4ef
NC
6274 return;
6275 }
6276
90e4755a
RE
6277 if (*str == '[')
6278 {
6279 int reg;
b99bd4ef 6280
90e4755a 6281 str++;
b99bd4ef 6282
90e4755a 6283 skip_whitespace (str);
b99bd4ef 6284
90e4755a
RE
6285 if ((reg = reg_required_here (&str, 16)) == FAIL)
6286 return;
b99bd4ef 6287
90e4755a
RE
6288 /* ldrt/strt always use post-indexed addressing, so if the base is
6289 the same as Rd, we warn. */
6290 if (conflict_reg == reg)
6291 as_warn (_("%s register same as write-back base"),
6292 ((inst.instruction & LOAD_BIT)
6293 ? _("destination") : _("source")));
6294
6295 skip_whitespace (str);
6296
6297 if (*str == ']')
6298 {
6299 str ++;
6300
6301 if (skip_past_comma (&str) == SUCCESS)
6302 {
6303 /* [Rn],... (post inc) */
6304 if (ldst_extend (&str) == FAIL)
6305 return;
6306 }
6307 else
6308 {
6309 /* [Rn] */
6310 skip_whitespace (str);
6311
6312 /* Skip a write-back '!'. */
6313 if (*str == '!')
6314 str++;
6315
6316 inst.instruction |= INDEX_UP;
6317 }
6318 }
6319 else
6320 {
6321 inst.error = _("post-indexed expression expected");
6322 return;
6323 }
6324 }
6325 else
b99bd4ef 6326 {
90e4755a 6327 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
6328 return;
6329 }
6330
b99bd4ef 6331 end_of_line (str);
b99bd4ef
NC
6332}
6333
90e4755a 6334/* Halfword and signed-byte load/store operations. */
a737bd4d 6335
b99bd4ef 6336static void
a737bd4d 6337do_ldstv4 (char * str)
b99bd4ef 6338{
b99bd4ef
NC
6339 int pre_inc = 0;
6340 int conflict_reg;
6341 int value;
6342
b99bd4ef
NC
6343 skip_whitespace (str);
6344
6345 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6346 {
6347 if (!inst.error)
6348 inst.error = BAD_ARGS;
6349 return;
6350 }
6351
6352 if (skip_past_comma (& str) == FAIL)
6353 {
f03698e6 6354 inst.error = _("address expected");
b99bd4ef
NC
6355 return;
6356 }
6357
6358 if (*str == '[')
6359 {
6360 int reg;
6361
6362 str++;
6363
6364 skip_whitespace (str);
6365
6366 if ((reg = reg_required_here (&str, 16)) == FAIL)
6367 return;
6368
6369 /* Conflicts can occur on stores as well as loads. */
6370 conflict_reg = (conflict_reg == reg);
6371
6372 skip_whitespace (str);
6373
6374 if (*str == ']')
6375 {
6376 str ++;
6377
6378 if (skip_past_comma (&str) == SUCCESS)
6379 {
6380 /* [Rn],... (post inc) */
90e4755a 6381 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6382 return;
6383 if (conflict_reg)
90e4755a
RE
6384 as_warn (_("%s register same as write-back base"),
6385 ((inst.instruction & LOAD_BIT)
6386 ? _("destination") : _("source")));
b99bd4ef
NC
6387 }
6388 else
6389 {
6390 /* [Rn] */
90e4755a 6391 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
6392
6393 skip_whitespace (str);
6394
6395 if (*str == '!')
6396 {
6397 if (conflict_reg)
6398 as_warn (_("%s register same as write-back base"),
6399 ((inst.instruction & LOAD_BIT)
6400 ? _("destination") : _("source")));
6401 str++;
6402 inst.instruction |= WRITE_BACK;
6403 }
6404
90e4755a
RE
6405 inst.instruction |= INDEX_UP;
6406 pre_inc = 1;
b99bd4ef
NC
6407 }
6408 }
6409 else
6410 {
6411 /* [Rn,...] */
6412 if (skip_past_comma (&str) == FAIL)
6413 {
6414 inst.error = _("pre-indexed expression expected");
6415 return;
6416 }
6417
6418 pre_inc = 1;
90e4755a 6419 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6420 return;
6421
6422 skip_whitespace (str);
6423
6424 if (*str++ != ']')
6425 {
6426 inst.error = _("missing ]");
6427 return;
6428 }
6429
6430 skip_whitespace (str);
6431
6432 if (*str == '!')
6433 {
6434 if (conflict_reg)
6435 as_warn (_("%s register same as write-back base"),
6436 ((inst.instruction & LOAD_BIT)
6437 ? _("destination") : _("source")));
6438 str++;
6439 inst.instruction |= WRITE_BACK;
6440 }
6441 }
6442 }
6443 else if (*str == '=')
6444 {
f03698e6
RE
6445 if ((inst.instruction & LOAD_BIT) == 0)
6446 {
6447 inst.error = _("invalid pseudo operation");
6448 return;
6449 }
6450
90e4755a 6451 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
6452 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6453 str++;
6454
6455 skip_whitespace (str);
6456
6457 if (my_get_expression (&inst.reloc.exp, &str))
6458 return;
6459
6460 if (inst.reloc.exp.X_op != O_constant
6461 && inst.reloc.exp.X_op != O_symbol)
6462 {
f03698e6 6463 inst.error = _("constant expression expected");
b99bd4ef
NC
6464 return;
6465 }
6466
d8273442 6467 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 6468 {
d8273442
NC
6469 value = validate_immediate (inst.reloc.exp.X_add_number);
6470
6471 if (value != FAIL)
b99bd4ef 6472 {
d8273442
NC
6473 /* This can be done with a mov instruction. */
6474 inst.instruction &= LITERAL_MASK;
6475 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 6476 inst.instruction |= value & 0xfff;
d8273442 6477 end_of_line (str);
b99bd4ef
NC
6478 return;
6479 }
cc8a6dd0 6480
d8273442 6481 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 6482
d8273442 6483 if (value != FAIL)
b99bd4ef 6484 {
d8273442
NC
6485 /* This can be done with a mvn instruction. */
6486 inst.instruction &= LITERAL_MASK;
6487 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 6488 inst.instruction |= value & 0xfff;
d8273442
NC
6489 end_of_line (str);
6490 return;
b99bd4ef 6491 }
b99bd4ef 6492 }
d8273442
NC
6493
6494 /* Insert into literal pool. */
6495 if (add_to_lit_pool () == FAIL)
6496 {
6497 if (!inst.error)
6498 inst.error = _("literal pool insertion failed");
6499 return;
6500 }
6501
6502 /* Change the instruction exp to point to the pool. */
90e4755a
RE
6503 inst.instruction |= HWOFFSET_IMM;
6504 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
6505 inst.reloc.pc_rel = 1;
6506 inst.instruction |= (REG_PC << 16);
6507 pre_inc = 1;
b99bd4ef
NC
6508 }
6509 else
6510 {
6511 if (my_get_expression (&inst.reloc.exp, &str))
6512 return;
6513
90e4755a
RE
6514 inst.instruction |= HWOFFSET_IMM;
6515 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
6516#ifndef TE_WINCE
6517 /* PC rel adjust. */
6518 inst.reloc.exp.X_add_number -= 8;
6519#endif
6520 inst.reloc.pc_rel = 1;
6521 inst.instruction |= (REG_PC << 16);
6522 pre_inc = 1;
6523 }
6524
90e4755a 6525 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6526 end_of_line (str);
b99bd4ef
NC
6527}
6528
6529static long
a737bd4d 6530reg_list (char ** strp)
b99bd4ef
NC
6531{
6532 char * str = * strp;
6533 long range = 0;
6534 int another_range;
6535
6536 /* We come back here if we get ranges concatenated by '+' or '|'. */
6537 do
6538 {
6539 another_range = 0;
6540
6541 if (*str == '{')
6542 {
6543 int in_range = 0;
6544 int cur_reg = -1;
6545
6546 str++;
6547 do
6548 {
6549 int reg;
6550
6551 skip_whitespace (str);
6552
6553 if ((reg = reg_required_here (& str, -1)) == FAIL)
6554 return FAIL;
6555
6556 if (in_range)
6557 {
6558 int i;
6559
6560 if (reg <= cur_reg)
6561 {
f03698e6 6562 inst.error = _("bad range in register list");
b99bd4ef
NC
6563 return FAIL;
6564 }
6565
6566 for (i = cur_reg + 1; i < reg; i++)
6567 {
6568 if (range & (1 << i))
6569 as_tsktsk
f03698e6 6570 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6571 i);
6572 else
6573 range |= 1 << i;
6574 }
6575 in_range = 0;
6576 }
6577
6578 if (range & (1 << reg))
f03698e6 6579 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6580 reg);
6581 else if (reg <= cur_reg)
f03698e6 6582 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
6583
6584 range |= 1 << reg;
6585 cur_reg = reg;
6586 }
6587 while (skip_past_comma (&str) != FAIL
6588 || (in_range = 1, *str++ == '-'));
6589 str--;
6590 skip_whitespace (str);
6591
6592 if (*str++ != '}')
6593 {
f03698e6 6594 inst.error = _("missing `}'");
b99bd4ef
NC
6595 return FAIL;
6596 }
6597 }
6598 else
6599 {
6600 expressionS expr;
6601
6602 if (my_get_expression (&expr, &str))
6603 return FAIL;
6604
6605 if (expr.X_op == O_constant)
6606 {
6607 if (expr.X_add_number
6608 != (expr.X_add_number & 0x0000ffff))
6609 {
6610 inst.error = _("invalid register mask");
6611 return FAIL;
6612 }
6613
6614 if ((range & expr.X_add_number) != 0)
6615 {
6616 int regno = range & expr.X_add_number;
6617
6618 regno &= -regno;
6619 regno = (1 << regno) - 1;
6620 as_tsktsk
f03698e6 6621 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6622 regno);
6623 }
6624
6625 range |= expr.X_add_number;
6626 }
6627 else
6628 {
6629 if (inst.reloc.type != 0)
6630 {
6631 inst.error = _("expression too complex");
6632 return FAIL;
6633 }
6634
6635 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6636 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6637 inst.reloc.pc_rel = 0;
6638 }
6639 }
6640
6641 skip_whitespace (str);
6642
6643 if (*str == '|' || *str == '+')
6644 {
6645 str++;
6646 another_range = 1;
6647 }
6648 }
6649 while (another_range);
6650
6651 *strp = str;
6652 return range;
6653}
6654
6655static void
a737bd4d 6656do_ldmstm (char * str)
b99bd4ef
NC
6657{
6658 int base_reg;
6659 long range;
6660
6661 skip_whitespace (str);
6662
6663 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6664 return;
6665
6666 if (base_reg == REG_PC)
6667 {
6668 inst.error = _("r15 not allowed as base register");
6669 return;
6670 }
6671
6672 skip_whitespace (str);
6673
6674 if (*str == '!')
6675 {
90e4755a 6676 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
6677 str++;
6678 }
6679
6680 if (skip_past_comma (&str) == FAIL
6681 || (range = reg_list (&str)) == FAIL)
6682 {
6683 if (! inst.error)
6684 inst.error = BAD_ARGS;
6685 return;
6686 }
6687
6688 if (*str == '^')
6689 {
6690 str++;
90e4755a 6691 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
6692 }
6693
6189168b
NC
6694 if (inst.instruction & WRITE_BACK)
6695 {
6696 /* Check for unpredictable uses of writeback. */
6697 if (inst.instruction & LOAD_BIT)
6698 {
6699 /* Not allowed in LDM type 2. */
6700 if ((inst.instruction & LDM_TYPE_2_OR_3)
6701 && ((range & (1 << REG_PC)) == 0))
6702 as_warn (_("writeback of base register is UNPREDICTABLE"));
6703 /* Only allowed if base reg not in list for other types. */
6704 else if (range & (1 << base_reg))
6705 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6706 }
6707 else /* STM. */
6708 {
6709 /* Not allowed for type 2. */
6710 if (inst.instruction & LDM_TYPE_2_OR_3)
6711 as_warn (_("writeback of base register is UNPREDICTABLE"));
6712 /* Only allowed if base reg not in list, or first in list. */
6713 else if ((range & (1 << base_reg))
6714 && (range & ((1 << base_reg) - 1)))
6715 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6716 }
6717 }
61b5f74b 6718
f2b7cb0a 6719 inst.instruction |= range;
b99bd4ef 6720 end_of_line (str);
b99bd4ef
NC
6721}
6722
0dd132b6
NC
6723static void
6724do_smi (char * str)
6725{
6726 skip_whitespace (str);
6727
6728 /* Allow optional leading '#'. */
6729 if (is_immediate_prefix (*str))
6730 str++;
6731
6732 if (my_get_expression (& inst.reloc.exp, & str))
6733 return;
6734
6735 inst.reloc.type = BFD_RELOC_ARM_SMI;
6736 inst.reloc.pc_rel = 0;
6737 end_of_line (str);
6738}
6739
b99bd4ef 6740static void
a737bd4d 6741do_swi (char * str)
b99bd4ef
NC
6742{
6743 skip_whitespace (str);
6744
6745 /* Allow optional leading '#'. */
6746 if (is_immediate_prefix (*str))
6747 str++;
6748
6749 if (my_get_expression (& inst.reloc.exp, & str))
6750 return;
6751
6752 inst.reloc.type = BFD_RELOC_ARM_SWI;
6753 inst.reloc.pc_rel = 0;
b99bd4ef 6754 end_of_line (str);
b99bd4ef
NC
6755}
6756
6757static void
a737bd4d 6758do_swap (char * str)
b99bd4ef
NC
6759{
6760 int reg;
6761
6762 skip_whitespace (str);
6763
6764 if ((reg = reg_required_here (&str, 12)) == FAIL)
6765 return;
6766
6767 if (reg == REG_PC)
6768 {
6769 inst.error = _("r15 not allowed in swap");
6770 return;
6771 }
6772
6773 if (skip_past_comma (&str) == FAIL
6774 || (reg = reg_required_here (&str, 0)) == FAIL)
6775 {
6776 if (!inst.error)
6777 inst.error = BAD_ARGS;
6778 return;
6779 }
6780
6781 if (reg == REG_PC)
6782 {
6783 inst.error = _("r15 not allowed in swap");
6784 return;
6785 }
6786
6787 if (skip_past_comma (&str) == FAIL
6788 || *str++ != '[')
6789 {
6790 inst.error = BAD_ARGS;
6791 return;
6792 }
6793
6794 skip_whitespace (str);
6795
6796 if ((reg = reg_required_here (&str, 16)) == FAIL)
6797 return;
6798
6799 if (reg == REG_PC)
6800 {
6801 inst.error = BAD_PC;
6802 return;
6803 }
6804
6805 skip_whitespace (str);
6806
6807 if (*str++ != ']')
6808 {
6809 inst.error = _("missing ]");
6810 return;
6811 }
6812
b99bd4ef 6813 end_of_line (str);
b99bd4ef
NC
6814}
6815
6816static void
a737bd4d 6817do_branch (char * str)
b99bd4ef
NC
6818{
6819 if (my_get_expression (&inst.reloc.exp, &str))
6820 return;
6821
6822#ifdef OBJ_ELF
6823 {
6824 char * save_in;
6825
6826 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6827 required for the instruction. */
6828
6829 /* arm_parse_reloc () works on input_line_pointer.
6830 We actually want to parse the operands to the branch instruction
6831 passed in 'str'. Save the input pointer and restore it later. */
6832 save_in = input_line_pointer;
6833 input_line_pointer = str;
6834 if (inst.reloc.exp.X_op == O_symbol
6835 && *str == '('
6836 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6837 {
6838 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6839 inst.reloc.pc_rel = 0;
6840 /* Modify str to point to after parsed operands, otherwise
6841 end_of_line() will complain about the (PLT) left in str. */
6842 str = input_line_pointer;
6843 }
6844 else
6845 {
6846 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6847 inst.reloc.pc_rel = 1;
6848 }
6849 input_line_pointer = save_in;
6850 }
6851#else
6852 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6853 inst.reloc.pc_rel = 1;
6854#endif /* OBJ_ELF */
6855
6856 end_of_line (str);
b99bd4ef
NC
6857}
6858
6859static void
a737bd4d 6860do_cdp (char * str)
b99bd4ef
NC
6861{
6862 /* Co-processor data operation.
6863 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6864 skip_whitespace (str);
6865
6866 if (co_proc_number (&str) == FAIL)
6867 {
6868 if (!inst.error)
6869 inst.error = BAD_ARGS;
6870 return;
6871 }
6872
6873 if (skip_past_comma (&str) == FAIL
6874 || cp_opc_expr (&str, 20,4) == FAIL)
6875 {
6876 if (!inst.error)
6877 inst.error = BAD_ARGS;
6878 return;
6879 }
6880
6881 if (skip_past_comma (&str) == FAIL
6882 || cp_reg_required_here (&str, 12) == FAIL)
6883 {
6884 if (!inst.error)
6885 inst.error = BAD_ARGS;
6886 return;
6887 }
6888
6889 if (skip_past_comma (&str) == FAIL
6890 || cp_reg_required_here (&str, 16) == FAIL)
6891 {
6892 if (!inst.error)
6893 inst.error = BAD_ARGS;
6894 return;
6895 }
6896
6897 if (skip_past_comma (&str) == FAIL
6898 || cp_reg_required_here (&str, 0) == FAIL)
6899 {
6900 if (!inst.error)
6901 inst.error = BAD_ARGS;
6902 return;
6903 }
6904
6905 if (skip_past_comma (&str) == SUCCESS)
6906 {
6907 if (cp_opc_expr (&str, 5, 3) == FAIL)
6908 {
6909 if (!inst.error)
6910 inst.error = BAD_ARGS;
6911 return;
6912 }
6913 }
6914
6915 end_of_line (str);
b99bd4ef
NC
6916}
6917
6918static void
a737bd4d 6919do_lstc (char * str)
b99bd4ef
NC
6920{
6921 /* Co-processor register load/store.
6922 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6923
6924 skip_whitespace (str);
6925
6926 if (co_proc_number (&str) == FAIL)
6927 {
6928 if (!inst.error)
6929 inst.error = BAD_ARGS;
6930 return;
6931 }
6932
6933 if (skip_past_comma (&str) == FAIL
6934 || cp_reg_required_here (&str, 12) == FAIL)
6935 {
6936 if (!inst.error)
6937 inst.error = BAD_ARGS;
6938 return;
6939 }
6940
6941 if (skip_past_comma (&str) == FAIL
bfae80f2 6942 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
6943 {
6944 if (! inst.error)
6945 inst.error = BAD_ARGS;
6946 return;
6947 }
6948
b99bd4ef 6949 end_of_line (str);
b99bd4ef
NC
6950}
6951
6952static void
a737bd4d 6953do_co_reg (char * str)
b99bd4ef
NC
6954{
6955 /* Co-processor register transfer.
6956 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6957
6958 skip_whitespace (str);
6959
6960 if (co_proc_number (&str) == FAIL)
6961 {
6962 if (!inst.error)
6963 inst.error = BAD_ARGS;
6964 return;
6965 }
6966
6967 if (skip_past_comma (&str) == FAIL
6968 || cp_opc_expr (&str, 21, 3) == FAIL)
6969 {
6970 if (!inst.error)
6971 inst.error = BAD_ARGS;
6972 return;
6973 }
6974
6975 if (skip_past_comma (&str) == FAIL
6976 || reg_required_here (&str, 12) == FAIL)
6977 {
6978 if (!inst.error)
6979 inst.error = BAD_ARGS;
6980 return;
6981 }
6982
6983 if (skip_past_comma (&str) == FAIL
6984 || cp_reg_required_here (&str, 16) == FAIL)
6985 {
6986 if (!inst.error)
6987 inst.error = BAD_ARGS;
6988 return;
6989 }
6990
6991 if (skip_past_comma (&str) == FAIL
6992 || cp_reg_required_here (&str, 0) == FAIL)
6993 {
6994 if (!inst.error)
6995 inst.error = BAD_ARGS;
6996 return;
6997 }
6998
6999 if (skip_past_comma (&str) == SUCCESS)
7000 {
7001 if (cp_opc_expr (&str, 5, 3) == FAIL)
7002 {
7003 if (!inst.error)
7004 inst.error = BAD_ARGS;
7005 return;
7006 }
7007 }
b99bd4ef
NC
7008
7009 end_of_line (str);
b99bd4ef
NC
7010}
7011
7012static void
a737bd4d 7013do_fpa_ctrl (char * str)
b99bd4ef
NC
7014{
7015 /* FP control registers.
7016 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7017
7018 skip_whitespace (str);
7019
7020 if (reg_required_here (&str, 12) == FAIL)
7021 {
7022 if (!inst.error)
7023 inst.error = BAD_ARGS;
7024 return;
7025 }
7026
7027 end_of_line (str);
b99bd4ef
NC
7028}
7029
7030static void
a737bd4d 7031do_fpa_ldst (char * str)
b99bd4ef
NC
7032{
7033 skip_whitespace (str);
7034
b99bd4ef
NC
7035 if (fp_reg_required_here (&str, 12) == FAIL)
7036 {
7037 if (!inst.error)
7038 inst.error = BAD_ARGS;
7039 return;
7040 }
7041
7042 if (skip_past_comma (&str) == FAIL
bfae80f2 7043 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7044 {
7045 if (!inst.error)
7046 inst.error = BAD_ARGS;
7047 return;
7048 }
7049
7050 end_of_line (str);
7051}
7052
7053static void
a737bd4d 7054do_fpa_ldmstm (char * str)
b99bd4ef
NC
7055{
7056 int num_regs;
7057
7058 skip_whitespace (str);
7059
7060 if (fp_reg_required_here (&str, 12) == FAIL)
7061 {
7062 if (! inst.error)
7063 inst.error = BAD_ARGS;
7064 return;
7065 }
7066
7067 /* Get Number of registers to transfer. */
7068 if (skip_past_comma (&str) == FAIL
7069 || my_get_expression (&inst.reloc.exp, &str))
7070 {
7071 if (! inst.error)
7072 inst.error = _("constant expression expected");
7073 return;
7074 }
7075
7076 if (inst.reloc.exp.X_op != O_constant)
7077 {
f03698e6 7078 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
7079 return;
7080 }
7081
7082 num_regs = inst.reloc.exp.X_add_number;
7083
7084 if (num_regs < 1 || num_regs > 4)
7085 {
7086 inst.error = _("number of registers must be in the range [1:4]");
7087 return;
7088 }
7089
7090 switch (num_regs)
7091 {
7092 case 1:
7093 inst.instruction |= CP_T_X;
7094 break;
7095 case 2:
7096 inst.instruction |= CP_T_Y;
7097 break;
7098 case 3:
7099 inst.instruction |= CP_T_Y | CP_T_X;
7100 break;
7101 case 4:
7102 break;
7103 default:
7104 abort ();
7105 }
7106
e28cd48c 7107 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
7108 {
7109 int reg;
7110 int write_back;
7111 int offset;
7112
7113 /* The instruction specified "ea" or "fd", so we can only accept
7114 [Rn]{!}. The instruction does not really support stacking or
7115 unstacking, so we have to emulate these by setting appropriate
7116 bits and offsets. */
7117 if (skip_past_comma (&str) == FAIL
7118 || *str != '[')
7119 {
7120 if (! inst.error)
7121 inst.error = BAD_ARGS;
7122 return;
7123 }
7124
7125 str++;
7126 skip_whitespace (str);
7127
7128 if ((reg = reg_required_here (&str, 16)) == FAIL)
7129 return;
7130
7131 skip_whitespace (str);
7132
7133 if (*str != ']')
7134 {
7135 inst.error = BAD_ARGS;
7136 return;
7137 }
7138
7139 str++;
7140 if (*str == '!')
7141 {
7142 write_back = 1;
7143 str++;
7144 if (reg == REG_PC)
7145 {
7146 inst.error =
f03698e6 7147 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
7148 return;
7149 }
7150 }
7151 else
7152 write_back = 0;
7153
90e4755a 7154 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
7155 {
7156 /* Pre-decrement. */
7157 offset = 3 * num_regs;
7158 if (write_back)
90e4755a 7159 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7160 }
7161 else
7162 {
7163 /* Post-increment. */
7164 if (write_back)
7165 {
90e4755a 7166 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7167 offset = 3 * num_regs;
7168 }
7169 else
7170 {
7171 /* No write-back, so convert this into a standard pre-increment
7172 instruction -- aesthetically more pleasing. */
90e4755a 7173 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
7174 offset = 0;
7175 }
7176 }
7177
f2b7cb0a 7178 inst.instruction |= offset;
b99bd4ef
NC
7179 }
7180 else if (skip_past_comma (&str) == FAIL
bfae80f2 7181 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7182 {
7183 if (! inst.error)
7184 inst.error = BAD_ARGS;
7185 return;
7186 }
7187
7188 end_of_line (str);
7189}
7190
7191static void
a737bd4d 7192do_fpa_dyadic (char * str)
b99bd4ef
NC
7193{
7194 skip_whitespace (str);
7195
b99bd4ef
NC
7196 if (fp_reg_required_here (&str, 12) == FAIL)
7197 {
7198 if (! inst.error)
7199 inst.error = BAD_ARGS;
7200 return;
7201 }
7202
7203 if (skip_past_comma (&str) == FAIL
7204 || fp_reg_required_here (&str, 16) == FAIL)
7205 {
7206 if (! inst.error)
7207 inst.error = BAD_ARGS;
7208 return;
7209 }
7210
7211 if (skip_past_comma (&str) == FAIL
7212 || fp_op2 (&str) == FAIL)
7213 {
7214 if (! inst.error)
7215 inst.error = BAD_ARGS;
7216 return;
7217 }
7218
b99bd4ef 7219 end_of_line (str);
b99bd4ef
NC
7220}
7221
7222static void
a737bd4d 7223do_fpa_monadic (char * str)
b99bd4ef
NC
7224{
7225 skip_whitespace (str);
7226
b99bd4ef
NC
7227 if (fp_reg_required_here (&str, 12) == FAIL)
7228 {
7229 if (! inst.error)
7230 inst.error = BAD_ARGS;
7231 return;
7232 }
7233
7234 if (skip_past_comma (&str) == FAIL
7235 || fp_op2 (&str) == FAIL)
7236 {
7237 if (! inst.error)
7238 inst.error = BAD_ARGS;
7239 return;
7240 }
7241
b99bd4ef 7242 end_of_line (str);
b99bd4ef
NC
7243}
7244
7245static void
a737bd4d 7246do_fpa_cmp (char * str)
b99bd4ef
NC
7247{
7248 skip_whitespace (str);
7249
7250 if (fp_reg_required_here (&str, 16) == FAIL)
7251 {
7252 if (! inst.error)
7253 inst.error = BAD_ARGS;
7254 return;
7255 }
7256
7257 if (skip_past_comma (&str) == FAIL
7258 || fp_op2 (&str) == FAIL)
7259 {
7260 if (! inst.error)
7261 inst.error = BAD_ARGS;
7262 return;
7263 }
7264
b99bd4ef 7265 end_of_line (str);
b99bd4ef
NC
7266}
7267
7268static void
a737bd4d 7269do_fpa_from_reg (char * str)
b99bd4ef
NC
7270{
7271 skip_whitespace (str);
7272
b99bd4ef
NC
7273 if (fp_reg_required_here (&str, 16) == FAIL)
7274 {
7275 if (! inst.error)
7276 inst.error = BAD_ARGS;
7277 return;
7278 }
7279
7280 if (skip_past_comma (&str) == FAIL
7281 || reg_required_here (&str, 12) == FAIL)
7282 {
7283 if (! inst.error)
7284 inst.error = BAD_ARGS;
7285 return;
7286 }
7287
b99bd4ef 7288 end_of_line (str);
b99bd4ef
NC
7289}
7290
7291static void
a737bd4d 7292do_fpa_to_reg (char * str)
b99bd4ef
NC
7293{
7294 skip_whitespace (str);
7295
7296 if (reg_required_here (&str, 12) == FAIL)
7297 return;
7298
7299 if (skip_past_comma (&str) == FAIL
7300 || fp_reg_required_here (&str, 0) == FAIL)
7301 {
7302 if (! inst.error)
7303 inst.error = BAD_ARGS;
7304 return;
7305 }
7306
b99bd4ef 7307 end_of_line (str);
b99bd4ef
NC
7308}
7309
7ed4c4c5
NC
7310/* Encode a VFP SP register number. */
7311
7312static void
7313vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7314{
7315 switch (pos)
7316 {
7317 case VFP_REG_Sd:
7318 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7319 break;
7320
7321 case VFP_REG_Sn:
7322 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7323 break;
7324
7325 case VFP_REG_Sm:
7326 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7327 break;
7328
7329 default:
7330 abort ();
7331 }
7332}
7333
b99bd4ef 7334static int
a737bd4d
NC
7335vfp_sp_reg_required_here (char ** str,
7336 enum vfp_sp_reg_pos pos)
b99bd4ef 7337{
bfae80f2 7338 int reg;
7ed4c4c5 7339 char * start = *str;
b99bd4ef 7340
bfae80f2 7341 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 7342 {
7ed4c4c5 7343 vfp_sp_encode_reg (reg, pos);
bfae80f2
RE
7344 return reg;
7345 }
b99bd4ef 7346
bfae80f2
RE
7347 /* In the few cases where we might be able to accept something else
7348 this error can be overridden. */
7349 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7350
7351 /* Restore the start point. */
7352 *str = start;
7353 return FAIL;
7354}
7355
7356static int
a737bd4d
NC
7357vfp_dp_reg_required_here (char ** str,
7358 enum vfp_dp_reg_pos pos)
bfae80f2 7359{
a737bd4d
NC
7360 int reg;
7361 char * start = *str;
bfae80f2
RE
7362
7363 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7364 {
7365 switch (pos)
b99bd4ef 7366 {
bfae80f2
RE
7367 case VFP_REG_Dd:
7368 inst.instruction |= reg << 12;
7369 break;
b99bd4ef 7370
bfae80f2
RE
7371 case VFP_REG_Dn:
7372 inst.instruction |= reg << 16;
7373 break;
7374
7375 case VFP_REG_Dm:
7376 inst.instruction |= reg << 0;
7377 break;
7378
7379 default:
7380 abort ();
7381 }
7382 return reg;
b99bd4ef
NC
7383 }
7384
bfae80f2
RE
7385 /* In the few cases where we might be able to accept something else
7386 this error can be overridden. */
7387 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 7388
bfae80f2
RE
7389 /* Restore the start point. */
7390 *str = start;
7391 return FAIL;
7392}
b99bd4ef
NC
7393
7394static void
a737bd4d 7395do_vfp_sp_monadic (char * str)
b99bd4ef 7396{
b99bd4ef
NC
7397 skip_whitespace (str);
7398
bfae80f2
RE
7399 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7400 return;
7401
7402 if (skip_past_comma (&str) == FAIL
7403 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
7404 {
7405 if (! inst.error)
7406 inst.error = BAD_ARGS;
7407 return;
7408 }
7409
bfae80f2 7410 end_of_line (str);
bfae80f2
RE
7411}
7412
7413static void
a737bd4d 7414do_vfp_dp_monadic (char * str)
bfae80f2
RE
7415{
7416 skip_whitespace (str);
7417
7418 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7419 return;
7420
7421 if (skip_past_comma (&str) == FAIL
7422 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 7423 {
bfae80f2
RE
7424 if (! inst.error)
7425 inst.error = BAD_ARGS;
7426 return;
b99bd4ef 7427 }
b99bd4ef 7428
bfae80f2 7429 end_of_line (str);
bfae80f2 7430}
b99bd4ef 7431
bfae80f2 7432static void
a737bd4d 7433do_vfp_sp_dyadic (char * str)
bfae80f2
RE
7434{
7435 skip_whitespace (str);
b99bd4ef 7436
bfae80f2
RE
7437 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7438 return;
b99bd4ef 7439
bfae80f2
RE
7440 if (skip_past_comma (&str) == FAIL
7441 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7442 || skip_past_comma (&str) == FAIL
7443 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 7444 {
bfae80f2
RE
7445 if (! inst.error)
7446 inst.error = BAD_ARGS;
7447 return;
7448 }
b99bd4ef 7449
bfae80f2 7450 end_of_line (str);
bfae80f2 7451}
b99bd4ef 7452
bfae80f2 7453static void
a737bd4d 7454do_vfp_dp_dyadic (char * str)
bfae80f2
RE
7455{
7456 skip_whitespace (str);
b99bd4ef 7457
bfae80f2
RE
7458 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7459 return;
b99bd4ef 7460
bfae80f2
RE
7461 if (skip_past_comma (&str) == FAIL
7462 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7463 || skip_past_comma (&str) == FAIL
7464 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7465 {
7466 if (! inst.error)
7467 inst.error = BAD_ARGS;
7468 return;
7469 }
b99bd4ef 7470
bfae80f2 7471 end_of_line (str);
bfae80f2 7472}
b99bd4ef 7473
bfae80f2 7474static void
a737bd4d 7475do_vfp_reg_from_sp (char * str)
bfae80f2
RE
7476{
7477 skip_whitespace (str);
7478
7479 if (reg_required_here (&str, 12) == FAIL)
7480 return;
7481
7482 if (skip_past_comma (&str) == FAIL
7483 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7484 {
7485 if (! inst.error)
7486 inst.error = BAD_ARGS;
7487 return;
7488 }
7489
7490 end_of_line (str);
bfae80f2
RE
7491}
7492
7ed4c4c5
NC
7493/* Parse a VFP register list. If the string is invalid return FAIL.
7494 Otherwise return the number of registers, and set PBASE to the first
7495 register. Double precision registers are matched if DP is nonzero. */
a737bd4d 7496
7ed4c4c5
NC
7497static int
7498vfp_parse_reg_list (char **str, int *pbase, int dp)
a737bd4d 7499{
7ed4c4c5 7500 int base_reg;
a737bd4d 7501 int new_base;
7ed4c4c5
NC
7502 int regtype;
7503 int max_regs;
a737bd4d 7504 int count = 0;
a737bd4d 7505 int warned = 0;
7ed4c4c5
NC
7506 unsigned long mask = 0;
7507 int i;
a737bd4d
NC
7508
7509 if (**str != '{')
7510 return FAIL;
7511
7512 (*str)++;
7513 skip_whitespace (*str);
7514
7ed4c4c5 7515 if (dp)
a737bd4d 7516 {
7ed4c4c5
NC
7517 regtype = REG_TYPE_DN;
7518 max_regs = 16;
7519 }
7520 else
7521 {
7522 regtype = REG_TYPE_SN;
7523 max_regs = 32;
7524 }
a737bd4d 7525
7ed4c4c5 7526 base_reg = max_regs;
a737bd4d 7527
7ed4c4c5
NC
7528 do
7529 {
7530 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7531 if (new_base == FAIL)
a737bd4d 7532 {
7ed4c4c5
NC
7533 inst.error = _(all_reg_maps[regtype].expected);
7534 return FAIL;
a737bd4d
NC
7535 }
7536
7ed4c4c5
NC
7537 if (new_base < base_reg)
7538 base_reg = new_base;
7539
a737bd4d
NC
7540 if (mask & (1 << new_base))
7541 {
7542 inst.error = _("invalid register list");
7543 return FAIL;
7544 }
7545
7546 if ((mask >> new_base) != 0 && ! warned)
7547 {
7548 as_tsktsk (_("register list not in ascending order"));
7549 warned = 1;
7550 }
7551
7552 mask |= 1 << new_base;
7553 count++;
7554
7555 skip_whitespace (*str);
7556
7557 if (**str == '-') /* We have the start of a range expression */
7558 {
7559 int high_range;
7560
7561 (*str)++;
7562
7563 if ((high_range
7ed4c4c5 7564 = arm_reg_parse (str, all_reg_maps[regtype].htab))
a737bd4d
NC
7565 == FAIL)
7566 {
7ed4c4c5 7567 inst.error = _(all_reg_maps[regtype].expected);
a737bd4d
NC
7568 return FAIL;
7569 }
7570
7571 if (high_range <= new_base)
7572 {
7573 inst.error = _("register range not in ascending order");
7574 return FAIL;
7575 }
7576
7577 for (new_base++; new_base <= high_range; new_base++)
7578 {
7579 if (mask & (1 << new_base))
7580 {
7581 inst.error = _("invalid register list");
7582 return FAIL;
7583 }
7584
7585 mask |= 1 << new_base;
7586 count++;
7587 }
7588 }
7589 }
7590 while (skip_past_comma (str) != FAIL);
7591
a737bd4d
NC
7592 (*str)++;
7593
a737bd4d 7594 /* Sanity check -- should have raised a parse error above. */
7ed4c4c5 7595 if (count == 0 || count > max_regs)
a737bd4d
NC
7596 abort ();
7597
7ed4c4c5
NC
7598 *pbase = base_reg;
7599
a737bd4d 7600 /* Final test -- the registers must be consecutive. */
7ed4c4c5
NC
7601 mask >>= base_reg;
7602 for (i = 0; i < count; i++)
a737bd4d 7603 {
7ed4c4c5 7604 if ((mask & (1u << i)) == 0)
a737bd4d
NC
7605 {
7606 inst.error = _("non-contiguous register range");
7607 return FAIL;
7608 }
7609 }
7610
7ed4c4c5 7611 return count;
a737bd4d
NC
7612}
7613
bfae80f2 7614static void
a737bd4d 7615do_vfp_reg2_from_sp2 (char * str)
bfae80f2 7616{
7ed4c4c5
NC
7617 int reg;
7618
bfae80f2
RE
7619 skip_whitespace (str);
7620
e45d0630
PB
7621 if (reg_required_here (&str, 12) == FAIL
7622 || skip_past_comma (&str) == FAIL
bfae80f2
RE
7623 || reg_required_here (&str, 16) == FAIL
7624 || skip_past_comma (&str) == FAIL)
7625 {
7626 if (! inst.error)
7627 inst.error = BAD_ARGS;
7628 return;
7629 }
7630
7631 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7632 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
bfae80f2
RE
7633 {
7634 if (! inst.error)
7635 inst.error = _("only two consecutive VFP SP registers allowed here");
7636 }
7ed4c4c5 7637 vfp_sp_encode_reg (reg, VFP_REG_Sm);
bfae80f2
RE
7638
7639 end_of_line (str);
bfae80f2
RE
7640}
7641
7642static void
a737bd4d 7643do_vfp_sp_from_reg (char * str)
bfae80f2
RE
7644{
7645 skip_whitespace (str);
7646
7647 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7648 return;
7649
7650 if (skip_past_comma (&str) == FAIL
7651 || reg_required_here (&str, 12) == FAIL)
7652 {
7653 if (! inst.error)
7654 inst.error = BAD_ARGS;
7655 return;
7656 }
7657
7658 end_of_line (str);
bfae80f2
RE
7659}
7660
e45d0630 7661static void
a737bd4d 7662do_vfp_sp2_from_reg2 (char * str)
e45d0630 7663{
7ed4c4c5
NC
7664 int reg;
7665
e45d0630
PB
7666 skip_whitespace (str);
7667
7668 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7669 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
e45d0630
PB
7670 {
7671 if (! inst.error)
7672 inst.error = _("only two consecutive VFP SP registers allowed here");
7673 }
7ed4c4c5 7674 vfp_sp_encode_reg (reg, VFP_REG_Sm);
e45d0630
PB
7675
7676 if (skip_past_comma (&str) == FAIL
7677 || reg_required_here (&str, 12) == FAIL
7678 || skip_past_comma (&str) == FAIL
7679 || reg_required_here (&str, 16) == FAIL)
7680 {
7681 if (! inst.error)
7682 inst.error = BAD_ARGS;
7683 return;
7684 }
7685
7686 end_of_line (str);
7687}
7688
bfae80f2 7689static void
a737bd4d 7690do_vfp_reg_from_dp (char * str)
bfae80f2
RE
7691{
7692 skip_whitespace (str);
7693
7694 if (reg_required_here (&str, 12) == FAIL)
7695 return;
7696
7697 if (skip_past_comma (&str) == FAIL
7698 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7699 {
7700 if (! inst.error)
7701 inst.error = BAD_ARGS;
7702 return;
7703 }
7704
7705 end_of_line (str);
bfae80f2
RE
7706}
7707
7708static void
a737bd4d 7709do_vfp_reg2_from_dp (char * str)
bfae80f2
RE
7710{
7711 skip_whitespace (str);
7712
7713 if (reg_required_here (&str, 12) == FAIL)
7714 return;
7715
7716 if (skip_past_comma (&str) == FAIL
7717 || reg_required_here (&str, 16) == FAIL
7718 || skip_past_comma (&str) == FAIL
7719 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7720 {
7721 if (! inst.error)
7722 inst.error = BAD_ARGS;
7723 return;
7724 }
7725
7726 end_of_line (str);
bfae80f2
RE
7727}
7728
7729static void
a737bd4d 7730do_vfp_dp_from_reg (char * str)
bfae80f2
RE
7731{
7732 skip_whitespace (str);
7733
7734 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7735 return;
7736
7737 if (skip_past_comma (&str) == FAIL
7738 || reg_required_here (&str, 12) == FAIL)
7739 {
7740 if (! inst.error)
7741 inst.error = BAD_ARGS;
7742 return;
7743 }
7744
7745 end_of_line (str);
bfae80f2
RE
7746}
7747
7748static void
a737bd4d 7749do_vfp_dp_from_reg2 (char * str)
bfae80f2
RE
7750{
7751 skip_whitespace (str);
7752
7753 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7754 return;
7755
7756 if (skip_past_comma (&str) == FAIL
7757 || reg_required_here (&str, 12) == FAIL
7758 || skip_past_comma (&str) == FAIL
e45d0630 7759 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
7760 {
7761 if (! inst.error)
7762 inst.error = BAD_ARGS;
7763 return;
7764 }
7765
7766 end_of_line (str);
bfae80f2
RE
7767}
7768
7769static const struct vfp_reg *
a737bd4d 7770vfp_psr_parse (char ** str)
bfae80f2
RE
7771{
7772 char *start = *str;
7773 char c;
7774 char *p;
7775 const struct vfp_reg *vreg;
7776
7777 p = start;
7778
7779 /* Find the end of the current token. */
7780 do
7781 {
7782 c = *p++;
7783 }
7784 while (ISALPHA (c));
7785
7786 /* Mark it. */
7787 *--p = 0;
7788
cc8a6dd0 7789 for (vreg = vfp_regs + 0;
bfae80f2
RE
7790 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7791 vreg++)
7792 {
a737bd4d 7793 if (streq (start, vreg->name))
bfae80f2
RE
7794 {
7795 *p = c;
7796 *str = p;
7797 return vreg;
7798 }
7799 }
7800
7801 *p = c;
7802 return NULL;
7803}
7804
7805static int
a737bd4d 7806vfp_psr_required_here (char ** str)
bfae80f2
RE
7807{
7808 char *start = *str;
7809 const struct vfp_reg *vreg;
7810
7811 vreg = vfp_psr_parse (str);
7812
7813 if (vreg)
7814 {
7815 inst.instruction |= vreg->regno;
7816 return SUCCESS;
7817 }
7818
7819 inst.error = _("VFP system register expected");
7820
7821 *str = start;
7822 return FAIL;
7823}
7824
7825static void
a737bd4d 7826do_vfp_reg_from_ctrl (char * str)
bfae80f2
RE
7827{
7828 skip_whitespace (str);
7829
7830 if (reg_required_here (&str, 12) == FAIL)
7831 return;
7832
7833 if (skip_past_comma (&str) == FAIL
7834 || vfp_psr_required_here (&str) == FAIL)
7835 {
7836 if (! inst.error)
7837 inst.error = BAD_ARGS;
7838 return;
7839 }
7840
7841 end_of_line (str);
bfae80f2
RE
7842}
7843
7844static void
a737bd4d 7845do_vfp_ctrl_from_reg (char * str)
bfae80f2
RE
7846{
7847 skip_whitespace (str);
7848
7849 if (vfp_psr_required_here (&str) == FAIL)
7850 return;
7851
7852 if (skip_past_comma (&str) == FAIL
7853 || reg_required_here (&str, 12) == FAIL)
7854 {
7855 if (! inst.error)
7856 inst.error = BAD_ARGS;
7857 return;
7858 }
7859
7860 end_of_line (str);
bfae80f2
RE
7861}
7862
7863static void
a737bd4d 7864do_vfp_sp_ldst (char * str)
bfae80f2
RE
7865{
7866 skip_whitespace (str);
7867
7868 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7869 {
7870 if (!inst.error)
7871 inst.error = BAD_ARGS;
7872 return;
7873 }
7874
7875 if (skip_past_comma (&str) == FAIL
7876 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7877 {
7878 if (!inst.error)
7879 inst.error = BAD_ARGS;
7880 return;
7881 }
7882
7883 end_of_line (str);
bfae80f2
RE
7884}
7885
7886static void
a737bd4d 7887do_vfp_dp_ldst (char * str)
bfae80f2
RE
7888{
7889 skip_whitespace (str);
7890
7891 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7892 {
7893 if (!inst.error)
7894 inst.error = BAD_ARGS;
7895 return;
7896 }
7897
7898 if (skip_past_comma (&str) == FAIL
7899 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7900 {
7901 if (!inst.error)
a737bd4d
NC
7902 inst.error = BAD_ARGS;
7903 return;
bfae80f2
RE
7904 }
7905
a737bd4d 7906 end_of_line (str);
bfae80f2
RE
7907}
7908
bfae80f2
RE
7909
7910static void
a737bd4d 7911vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 7912{
7ed4c4c5
NC
7913 int count;
7914 int reg;
bfae80f2
RE
7915
7916 skip_whitespace (str);
7917
7918 if (reg_required_here (&str, 16) == FAIL)
7919 return;
7920
7921 skip_whitespace (str);
7922
7923 if (*str == '!')
7924 {
7925 inst.instruction |= WRITE_BACK;
7926 str++;
7927 }
7928 else if (ldstm_type != VFP_LDSTMIA)
7929 {
7930 inst.error = _("this addressing mode requires base-register writeback");
7931 return;
7932 }
7933
7934 if (skip_past_comma (&str) == FAIL
7ed4c4c5 7935 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
bfae80f2
RE
7936 {
7937 if (!inst.error)
7938 inst.error = BAD_ARGS;
7939 return;
7940 }
7ed4c4c5 7941 vfp_sp_encode_reg (reg, VFP_REG_Sd);
bfae80f2 7942
7ed4c4c5 7943 inst.instruction |= count;
bfae80f2
RE
7944 end_of_line (str);
7945}
7946
7947static void
a737bd4d 7948vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 7949{
7ed4c4c5
NC
7950 int count;
7951 int reg;
bfae80f2
RE
7952
7953 skip_whitespace (str);
7954
7955 if (reg_required_here (&str, 16) == FAIL)
7956 return;
7957
7958 skip_whitespace (str);
7959
7960 if (*str == '!')
7961 {
7962 inst.instruction |= WRITE_BACK;
7963 str++;
7964 }
7965 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7966 {
7967 inst.error = _("this addressing mode requires base-register writeback");
7968 return;
7969 }
7970
7971 if (skip_past_comma (&str) == FAIL
7ed4c4c5 7972 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
bfae80f2
RE
7973 {
7974 if (!inst.error)
7975 inst.error = BAD_ARGS;
7976 return;
7977 }
7978
7ed4c4c5 7979 count <<= 1;
bfae80f2 7980 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7ed4c4c5 7981 count += 1;
bfae80f2 7982
7ed4c4c5 7983 inst.instruction |= (reg << 12) | count;
bfae80f2
RE
7984 end_of_line (str);
7985}
7986
7987static void
a737bd4d 7988do_vfp_sp_ldstmia (char * str)
bfae80f2
RE
7989{
7990 vfp_sp_ldstm (str, VFP_LDSTMIA);
7991}
7992
7993static void
a737bd4d 7994do_vfp_sp_ldstmdb (char * str)
bfae80f2
RE
7995{
7996 vfp_sp_ldstm (str, VFP_LDSTMDB);
7997}
7998
7999static void
a737bd4d 8000do_vfp_dp_ldstmia (char * str)
bfae80f2
RE
8001{
8002 vfp_dp_ldstm (str, VFP_LDSTMIA);
8003}
8004
8005static void
a737bd4d 8006do_vfp_dp_ldstmdb (char * str)
bfae80f2
RE
8007{
8008 vfp_dp_ldstm (str, VFP_LDSTMDB);
8009}
8010
8011static void
a737bd4d 8012do_vfp_xp_ldstmia (char *str)
bfae80f2
RE
8013{
8014 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8015}
8016
8017static void
a737bd4d 8018do_vfp_xp_ldstmdb (char * str)
bfae80f2
RE
8019{
8020 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8021}
8022
8023static void
a737bd4d 8024do_vfp_sp_compare_z (char * str)
bfae80f2
RE
8025{
8026 skip_whitespace (str);
8027
8028 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8029 {
8030 if (!inst.error)
8031 inst.error = BAD_ARGS;
8032 return;
8033 }
8034
8035 end_of_line (str);
bfae80f2
RE
8036}
8037
8038static void
a737bd4d 8039do_vfp_dp_compare_z (char * str)
bfae80f2
RE
8040{
8041 skip_whitespace (str);
8042
8043 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8044 {
8045 if (!inst.error)
8046 inst.error = BAD_ARGS;
8047 return;
8048 }
8049
8050 end_of_line (str);
bfae80f2
RE
8051}
8052
8053static void
a737bd4d 8054do_vfp_dp_sp_cvt (char * str)
bfae80f2
RE
8055{
8056 skip_whitespace (str);
8057
8058 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8059 return;
8060
8061 if (skip_past_comma (&str) == FAIL
8062 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8063 {
8064 if (! inst.error)
8065 inst.error = BAD_ARGS;
8066 return;
8067 }
8068
8069 end_of_line (str);
bfae80f2
RE
8070}
8071
8072static void
a737bd4d 8073do_vfp_sp_dp_cvt (char * str)
bfae80f2
RE
8074{
8075 skip_whitespace (str);
8076
8077 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8078 return;
8079
8080 if (skip_past_comma (&str) == FAIL
8081 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8082 {
8083 if (! inst.error)
8084 inst.error = BAD_ARGS;
8085 return;
8086 }
8087
8088 end_of_line (str);
bfae80f2
RE
8089}
8090
8091/* Thumb specific routines. */
8092
bfae80f2
RE
8093/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8094 was SUB. */
8095
8096static void
a737bd4d 8097thumb_add_sub (char * str, int subtract)
bfae80f2
RE
8098{
8099 int Rd, Rs, Rn = FAIL;
8100
8101 skip_whitespace (str);
8102
8103 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8104 || skip_past_comma (&str) == FAIL)
8105 {
8106 if (! inst.error)
8107 inst.error = BAD_ARGS;
8108 return;
8109 }
8110
8111 if (is_immediate_prefix (*str))
8112 {
8113 Rs = Rd;
8114 str++;
8115 if (my_get_expression (&inst.reloc.exp, &str))
8116 return;
8117 }
8118 else
8119 {
8120 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8121 return;
8122
8123 if (skip_past_comma (&str) == FAIL)
8124 {
8125 /* Two operand format, shuffle the registers
8126 and pretend there are 3. */
8127 Rn = Rs;
8128 Rs = Rd;
8129 }
8130 else if (is_immediate_prefix (*str))
8131 {
8132 str++;
8133 if (my_get_expression (&inst.reloc.exp, &str))
8134 return;
8135 }
8136 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8137 return;
8138 }
8139
8140 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8141 for the latter case, EXPR contains the immediate that was found. */
8142 if (Rn != FAIL)
8143 {
8144 /* All register format. */
8145 if (Rd > 7 || Rs > 7 || Rn > 7)
8146 {
8147 if (Rs != Rd)
8148 {
8149 inst.error = _("dest and source1 must be the same register");
8150 return;
8151 }
8152
8153 /* Can't do this for SUB. */
8154 if (subtract)
8155 {
8156 inst.error = _("subtract valid only on lo regs");
8157 return;
8158 }
8159
8160 inst.instruction = (T_OPCODE_ADD_HI
8161 | (Rd > 7 ? THUMB_H1 : 0)
8162 | (Rn > 7 ? THUMB_H2 : 0));
8163 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8164 }
8165 else
8166 {
8167 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8168 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8169 }
8170 }
8171 else
8172 {
8173 /* Immediate expression, now things start to get nasty. */
8174
8175 /* First deal with HI regs, only very restricted cases allowed:
8176 Adjusting SP, and using PC or SP to get an address. */
8177 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8178 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8179 {
8180 inst.error = _("invalid Hi register with immediate");
8181 return;
8182 }
8183
8184 if (inst.reloc.exp.X_op != O_constant)
8185 {
8186 /* Value isn't known yet, all we can do is store all the fragments
8187 we know about in the instruction and let the reloc hacking
8188 work it all out. */
8189 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8190 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8191 }
8192 else
8193 {
8194 int offset = inst.reloc.exp.X_add_number;
8195
8196 if (subtract)
358b94bd 8197 offset = - offset;
bfae80f2
RE
8198
8199 if (offset < 0)
8200 {
358b94bd 8201 offset = - offset;
bfae80f2
RE
8202 subtract = 1;
8203
8204 /* Quick check, in case offset is MIN_INT. */
8205 if (offset < 0)
8206 {
8207 inst.error = _("immediate value out of range");
8208 return;
8209 }
8210 }
358b94bd
NC
8211 /* Note - you cannot convert a subtract of 0 into an
8212 add of 0 because the carry flag is set differently. */
8213 else if (offset > 0)
bfae80f2
RE
8214 subtract = 0;
8215
8216 if (Rd == REG_SP)
8217 {
8218 if (offset & ~0x1fc)
8219 {
8220 inst.error = _("invalid immediate value for stack adjust");
8221 return;
b99bd4ef
NC
8222 }
8223 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8224 inst.instruction |= offset >> 2;
8225 }
8226 else if (Rs == REG_PC || Rs == REG_SP)
8227 {
8228 if (subtract
8229 || (offset & ~0x3fc))
8230 {
8231 inst.error = _("invalid immediate for address calculation");
8232 return;
8233 }
8234 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8235 : T_OPCODE_ADD_SP);
8236 inst.instruction |= (Rd << 8) | (offset >> 2);
8237 }
8238 else if (Rs == Rd)
8239 {
8240 if (offset & ~0xff)
8241 {
8242 inst.error = _("immediate value out of range");
8243 return;
8244 }
8245 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8246 inst.instruction |= (Rd << 8) | offset;
8247 }
8248 else
8249 {
8250 if (offset & ~0x7)
8251 {
8252 inst.error = _("immediate value out of range");
8253 return;
8254 }
8255 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8256 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8257 }
8258 }
8259 }
8260
8261 end_of_line (str);
8262}
8263
8264static void
a737bd4d 8265thumb_shift (char * str, int shift)
b99bd4ef
NC
8266{
8267 int Rd, Rs, Rn = FAIL;
8268
8269 skip_whitespace (str);
8270
8271 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8272 || skip_past_comma (&str) == FAIL)
8273 {
8274 if (! inst.error)
8275 inst.error = BAD_ARGS;
8276 return;
8277 }
8278
8279 if (is_immediate_prefix (*str))
8280 {
8281 /* Two operand immediate format, set Rs to Rd. */
8282 Rs = Rd;
8283 str ++;
8284 if (my_get_expression (&inst.reloc.exp, &str))
8285 return;
8286 }
8287 else
8288 {
8289 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8290 return;
8291
8292 if (skip_past_comma (&str) == FAIL)
8293 {
8294 /* Two operand format, shuffle the registers
8295 and pretend there are 3. */
8296 Rn = Rs;
8297 Rs = Rd;
8298 }
8299 else if (is_immediate_prefix (*str))
8300 {
8301 str++;
8302 if (my_get_expression (&inst.reloc.exp, &str))
8303 return;
8304 }
8305 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8306 return;
8307 }
8308
8309 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8310 for the latter case, EXPR contains the immediate that was found. */
8311
8312 if (Rn != FAIL)
8313 {
8314 if (Rs != Rd)
8315 {
8316 inst.error = _("source1 and dest must be same register");
8317 return;
8318 }
8319
8320 switch (shift)
8321 {
8322 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8323 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8324 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8325 }
8326
8327 inst.instruction |= Rd | (Rn << 3);
8328 }
8329 else
8330 {
8331 switch (shift)
8332 {
8333 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8334 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8335 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8336 }
8337
8338 if (inst.reloc.exp.X_op != O_constant)
8339 {
8340 /* Value isn't known yet, create a dummy reloc and let reloc
8341 hacking fix it up. */
8342 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8343 }
8344 else
8345 {
8346 unsigned shift_value = inst.reloc.exp.X_add_number;
8347
8348 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8349 {
f03698e6 8350 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
8351 return;
8352 }
8353
8354 /* Shifts of zero are handled by converting to LSL. */
8355 if (shift_value == 0)
8356 inst.instruction = T_OPCODE_LSL_I;
8357
8358 /* Shifts of 32 are encoded as a shift of zero. */
8359 if (shift_value == 32)
8360 shift_value = 0;
8361
8362 inst.instruction |= shift_value << 6;
8363 }
8364
8365 inst.instruction |= Rd | (Rs << 3);
8366 }
8367
8368 end_of_line (str);
8369}
8370
8371static void
a737bd4d 8372thumb_load_store (char * str, int load_store, int size)
b99bd4ef
NC
8373{
8374 int Rd, Rb, Ro = FAIL;
8375
8376 skip_whitespace (str);
8377
8378 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8379 || skip_past_comma (&str) == FAIL)
8380 {
8381 if (! inst.error)
8382 inst.error = BAD_ARGS;
8383 return;
8384 }
8385
8386 if (*str == '[')
8387 {
8388 str++;
8389 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8390 return;
8391
8392 if (skip_past_comma (&str) != FAIL)
8393 {
8394 if (is_immediate_prefix (*str))
8395 {
8396 str++;
8397 if (my_get_expression (&inst.reloc.exp, &str))
8398 return;
8399 }
8400 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8401 return;
8402 }
8403 else
8404 {
8405 inst.reloc.exp.X_op = O_constant;
8406 inst.reloc.exp.X_add_number = 0;
8407 }
8408
8409 if (*str != ']')
8410 {
8411 inst.error = _("expected ']'");
8412 return;
8413 }
8414 str++;
8415 }
8416 else if (*str == '=')
8417 {
f03698e6
RE
8418 if (load_store != THUMB_LOAD)
8419 {
8420 inst.error = _("invalid pseudo operation");
8421 return;
8422 }
8423
b99bd4ef
NC
8424 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8425 str++;
8426
8427 skip_whitespace (str);
8428
8429 if (my_get_expression (& inst.reloc.exp, & str))
8430 return;
8431
8432 end_of_line (str);
8433
8434 if ( inst.reloc.exp.X_op != O_constant
8435 && inst.reloc.exp.X_op != O_symbol)
8436 {
8437 inst.error = "Constant expression expected";
8438 return;
8439 }
8440
8441 if (inst.reloc.exp.X_op == O_constant
8442 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8443 {
8444 /* This can be done with a mov instruction. */
8445
8446 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8447 inst.instruction |= inst.reloc.exp.X_add_number;
8448 return;
8449 }
8450
8451 /* Insert into literal pool. */
8452 if (add_to_lit_pool () == FAIL)
8453 {
8454 if (!inst.error)
8455 inst.error = "literal pool insertion failed";
8456 return;
8457 }
8458
8459 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8460 inst.reloc.pc_rel = 1;
8461 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8462 /* Adjust ARM pipeline offset to Thumb. */
8463 inst.reloc.exp.X_add_number += 4;
8464
8465 return;
8466 }
8467 else
8468 {
8469 if (my_get_expression (&inst.reloc.exp, &str))
8470 return;
8471
8472 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8473 inst.reloc.pc_rel = 1;
8474 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8475 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8476 end_of_line (str);
8477 return;
8478 }
8479
8480 if (Rb == REG_PC || Rb == REG_SP)
8481 {
8482 if (size != THUMB_WORD)
8483 {
8484 inst.error = _("byte or halfword not valid for base register");
8485 return;
8486 }
8487 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8488 {
f03698e6 8489 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
8490 return;
8491 }
8492 else if (Ro != FAIL)
8493 {
f03698e6 8494 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
8495 return;
8496 }
8497
8498 if (Rb == REG_PC)
8499 inst.instruction = T_OPCODE_LDR_PC;
8500 else if (load_store == THUMB_LOAD)
8501 inst.instruction = T_OPCODE_LDR_SP;
8502 else
8503 inst.instruction = T_OPCODE_STR_SP;
8504
8505 inst.instruction |= Rd << 8;
8506 if (inst.reloc.exp.X_op == O_constant)
8507 {
8508 unsigned offset = inst.reloc.exp.X_add_number;
8509
8510 if (offset & ~0x3fc)
8511 {
8512 inst.error = _("invalid offset");
8513 return;
8514 }
8515
8516 inst.instruction |= offset >> 2;
8517 }
8518 else
8519 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8520 }
8521 else if (Rb > 7)
8522 {
8523 inst.error = _("invalid base register in load/store");
8524 return;
8525 }
8526 else if (Ro == FAIL)
8527 {
8528 /* Immediate offset. */
8529 if (size == THUMB_WORD)
8530 inst.instruction = (load_store == THUMB_LOAD
8531 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8532 else if (size == THUMB_HALFWORD)
8533 inst.instruction = (load_store == THUMB_LOAD
8534 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8535 else
8536 inst.instruction = (load_store == THUMB_LOAD
8537 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8538
8539 inst.instruction |= Rd | (Rb << 3);
8540
8541 if (inst.reloc.exp.X_op == O_constant)
8542 {
8543 unsigned offset = inst.reloc.exp.X_add_number;
8544
8545 if (offset & ~(0x1f << size))
8546 {
f03698e6 8547 inst.error = _("invalid offset");
b99bd4ef
NC
8548 return;
8549 }
8550 inst.instruction |= (offset >> size) << 6;
8551 }
8552 else
8553 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8554 }
8555 else
8556 {
8557 /* Register offset. */
8558 if (size == THUMB_WORD)
8559 inst.instruction = (load_store == THUMB_LOAD
8560 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8561 else if (size == THUMB_HALFWORD)
8562 inst.instruction = (load_store == THUMB_LOAD
8563 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8564 else
8565 inst.instruction = (load_store == THUMB_LOAD
8566 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8567
8568 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8569 }
8570
8571 end_of_line (str);
8572}
8573
404ff6b5
AH
8574/* A register must be given at this point.
8575
404ff6b5
AH
8576 Shift is the place to put it in inst.instruction.
8577
404ff6b5
AH
8578 Restores input start point on err.
8579 Returns the reg#, or FAIL. */
8580
8581static int
a737bd4d 8582mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
404ff6b5 8583{
6c43fab6
RE
8584 int reg;
8585 char *start = *str;
404ff6b5 8586
6c43fab6 8587 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 8588 {
404ff6b5
AH
8589 if (shift >= 0)
8590 inst.instruction |= reg << shift;
8591
6c43fab6 8592 return reg;
404ff6b5
AH
8593 }
8594
6c43fab6 8595 /* Restore the start point. */
404ff6b5 8596 *str = start;
cc8a6dd0 8597
3631a3c8
NC
8598 /* Try generic coprocessor name if applicable. */
8599 if (regtype == REG_TYPE_MVF ||
8600 regtype == REG_TYPE_MVD ||
8601 regtype == REG_TYPE_MVFX ||
8602 regtype == REG_TYPE_MVDX)
8603 {
8604 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8605 {
8606 if (shift >= 0)
8607 inst.instruction |= reg << shift;
8608
8609 return reg;
8610 }
8611
8612 /* Restore the start point. */
8613 *str = start;
8614 }
8615
404ff6b5
AH
8616 /* In the few cases where we might be able to accept something else
8617 this error can be overridden. */
6c43fab6 8618 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 8619
404ff6b5
AH
8620 return FAIL;
8621}
8622
a737bd4d
NC
8623/* Cirrus Maverick Instructions. */
8624
8625/* Isnsn like "foo X,Y". */
8626
8627static void
8628do_mav_binops (char * str,
8629 int mode,
8630 enum arm_reg_type reg0,
8631 enum arm_reg_type reg1)
8632{
8633 int shift0, shift1;
8634
8635 shift0 = mode & 0xff;
8636 shift1 = (mode >> 8) & 0xff;
8637
8638 skip_whitespace (str);
8639
8640 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8641 || skip_past_comma (&str) == FAIL
8642 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8643 {
8644 if (!inst.error)
8645 inst.error = BAD_ARGS;
8646 }
8647 else
8648 end_of_line (str);
8649}
8650
8651/* Isnsn like "foo X,Y,Z". */
8652
8653static void
8654do_mav_triple (char * str,
8655 int mode,
8656 enum arm_reg_type reg0,
8657 enum arm_reg_type reg1,
8658 enum arm_reg_type reg2)
8659{
8660 int shift0, shift1, shift2;
8661
8662 shift0 = mode & 0xff;
8663 shift1 = (mode >> 8) & 0xff;
8664 shift2 = (mode >> 16) & 0xff;
8665
8666 skip_whitespace (str);
8667
8668 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8669 || skip_past_comma (&str) == FAIL
8670 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8671 || skip_past_comma (&str) == FAIL
8672 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8673 {
8674 if (!inst.error)
8675 inst.error = BAD_ARGS;
8676 }
8677 else
8678 end_of_line (str);
8679}
8680
8681/* Wrapper functions. */
8682
8683static void
8684do_mav_binops_1a (char * str)
8685{
8686 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8687}
8688
8689static void
8690do_mav_binops_1b (char * str)
8691{
8692 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8693}
8694
8695static void
8696do_mav_binops_1c (char * str)
8697{
8698 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8699}
8700
8701static void
8702do_mav_binops_1d (char * str)
8703{
8704 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8705}
8706
8707static void
8708do_mav_binops_1e (char * str)
8709{
8710 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8711}
8712
8713static void
8714do_mav_binops_1f (char * str)
8715{
8716 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8717}
8718
8719static void
8720do_mav_binops_1g (char * str)
8721{
8722 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8723}
8724
8725static void
8726do_mav_binops_1h (char * str)
8727{
8728 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8729}
8730
8731static void
8732do_mav_binops_1i (char * str)
8733{
8734 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8735}
8736
8737static void
8738do_mav_binops_1j (char * str)
8739{
8740 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8741}
8742
8743static void
8744do_mav_binops_1k (char * str)
8745{
8746 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8747}
8748
8749static void
8750do_mav_binops_1l (char * str)
8751{
8752 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8753}
8754
8755static void
8756do_mav_binops_1m (char * str)
8757{
8758 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8759}
8760
8761static void
8762do_mav_binops_1n (char * str)
8763{
8764 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8765}
8766
8767static void
8768do_mav_binops_1o (char * str)
8769{
8770 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8771}
8772
8773static void
8774do_mav_binops_2a (char * str)
8775{
8776 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8777}
8778
8779static void
8780do_mav_binops_2b (char * str)
8781{
8782 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8783}
404ff6b5 8784
a737bd4d
NC
8785static void
8786do_mav_binops_2c (char * str)
8787{
8788 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8789}
404ff6b5
AH
8790
8791static void
a737bd4d 8792do_mav_binops_3a (char * str)
6c43fab6 8793{
a737bd4d 8794 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
8795}
8796
8797static void
a737bd4d 8798do_mav_binops_3b (char * str)
6c43fab6 8799{
a737bd4d 8800 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
8801}
8802
8803static void
a737bd4d 8804do_mav_binops_3c (char * str)
404ff6b5 8805{
a737bd4d 8806 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
404ff6b5
AH
8807}
8808
8809static void
a737bd4d 8810do_mav_binops_3d (char * str)
404ff6b5 8811{
a737bd4d 8812 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
404ff6b5
AH
8813}
8814
8815static void
a737bd4d 8816do_mav_triple_4a (char * str)
404ff6b5 8817{
a737bd4d 8818 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
404ff6b5
AH
8819}
8820
8821static void
a737bd4d 8822do_mav_triple_4b (char * str)
404ff6b5 8823{
a737bd4d 8824 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
404ff6b5
AH
8825}
8826
8827static void
a737bd4d 8828do_mav_triple_5a (char * str)
404ff6b5 8829{
a737bd4d 8830 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
8831}
8832
8833static void
a737bd4d 8834do_mav_triple_5b (char * str)
404ff6b5 8835{
a737bd4d 8836 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
8837}
8838
6c43fab6 8839static void
a737bd4d 8840do_mav_triple_5c (char * str)
6c43fab6 8841{
a737bd4d 8842 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8843}
8844
8845static void
a737bd4d 8846do_mav_triple_5d (char * str)
6c43fab6 8847{
a737bd4d 8848 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8849}
8850
8851static void
a737bd4d 8852do_mav_triple_5e (char * str)
6c43fab6 8853{
a737bd4d 8854 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
8855}
8856
8857static void
a737bd4d 8858do_mav_triple_5f (char * str)
6c43fab6 8859{
a737bd4d 8860 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
8861}
8862
8863static void
a737bd4d 8864do_mav_triple_5g (char * str)
6c43fab6 8865{
a737bd4d 8866 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8867}
8868
8869static void
a737bd4d 8870do_mav_triple_5h (char * str)
6c43fab6 8871{
a737bd4d 8872 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8873}
8874
a737bd4d
NC
8875/* Isnsn like "foo W,X,Y,Z".
8876 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8877
6c43fab6 8878static void
a737bd4d
NC
8879do_mav_quad (char * str,
8880 int mode,
8881 enum arm_reg_type reg0,
8882 enum arm_reg_type reg1,
8883 enum arm_reg_type reg2,
8884 enum arm_reg_type reg3)
6c43fab6 8885{
a737bd4d
NC
8886 int shift0, shift1, shift2, shift3;
8887
8888 shift0= mode & 0xff;
8889 shift1 = (mode >> 8) & 0xff;
8890 shift2 = (mode >> 16) & 0xff;
8891 shift3 = (mode >> 24) & 0xff;
8892
8893 skip_whitespace (str);
8894
8895 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8896 || skip_past_comma (&str) == FAIL
8897 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8898 || skip_past_comma (&str) == FAIL
8899 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8900 || skip_past_comma (&str) == FAIL
8901 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8902 {
8903 if (!inst.error)
8904 inst.error = BAD_ARGS;
8905 }
8906 else
8907 end_of_line (str);
6c43fab6
RE
8908}
8909
8910static void
a737bd4d 8911do_mav_quad_6a (char * str)
6c43fab6 8912{
a737bd4d
NC
8913 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8914 REG_TYPE_MVFX);
6c43fab6
RE
8915}
8916
8917static void
a737bd4d 8918do_mav_quad_6b (char * str)
6c43fab6 8919{
a737bd4d
NC
8920 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8921 REG_TYPE_MVFX);
6c43fab6
RE
8922}
8923
a737bd4d 8924/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
6c43fab6 8925static void
a737bd4d 8926do_mav_dspsc_1 (char * str)
6c43fab6 8927{
a737bd4d
NC
8928 skip_whitespace (str);
8929
8930 /* cfmvsc32. */
8931 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8932 || skip_past_comma (&str) == FAIL
8933 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8934 {
8935 if (!inst.error)
8936 inst.error = BAD_ARGS;
8937
8938 return;
8939 }
8940
8941 end_of_line (str);
6c43fab6
RE
8942}
8943
a737bd4d 8944/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
6c43fab6 8945static void
a737bd4d 8946do_mav_dspsc_2 (char * str)
6c43fab6 8947{
a737bd4d
NC
8948 skip_whitespace (str);
8949
8950 /* cfmv32sc. */
8951 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8952 || skip_past_comma (&str) == FAIL
8953 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8954 {
8955 if (!inst.error)
8956 inst.error = BAD_ARGS;
8957
8958 return;
8959 }
8960
8961 end_of_line (str);
6c43fab6
RE
8962}
8963
a737bd4d
NC
8964/* Maverick shift immediate instructions.
8965 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8966 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8967
6c43fab6 8968static void
a737bd4d
NC
8969do_mav_shift (char * str,
8970 enum arm_reg_type reg0,
8971 enum arm_reg_type reg1)
6c43fab6 8972{
a737bd4d
NC
8973 int error;
8974 int imm, neg = 0;
8975
8976 skip_whitespace (str);
8977
8978 error = 0;
8979
8980 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8981 || skip_past_comma (&str) == FAIL
8982 || mav_reg_required_here (&str, 16, reg1) == FAIL
8983 || skip_past_comma (&str) == FAIL)
8984 {
8985 if (!inst.error)
8986 inst.error = BAD_ARGS;
8987 return;
8988 }
8989
8990 /* Calculate the immediate operand.
8991 The operand is a 7bit signed number. */
8992 skip_whitespace (str);
8993
8994 if (*str == '#')
8995 ++str;
8996
8997 if (!ISDIGIT (*str) && *str != '-')
8998 {
8999 inst.error = _("expecting immediate, 7bit operand");
9000 return;
9001 }
9002
9003 if (*str == '-')
9004 {
9005 neg = 1;
9006 ++str;
9007 }
9008
9009 for (imm = 0; *str && ISDIGIT (*str); ++str)
9010 imm = imm * 10 + *str - '0';
9011
9012 if (imm > 64)
9013 {
9014 inst.error = _("immediate out of range");
9015 return;
9016 }
9017
9018 /* Make negative imm's into 7bit signed numbers. */
9019 if (neg)
9020 {
9021 imm = -imm;
9022 imm &= 0x0000007f;
9023 }
9024
9025 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9026 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9027 Bit 4 should be 0. */
9028 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9029
9030 inst.instruction |= imm;
9031 end_of_line (str);
6c43fab6
RE
9032}
9033
9034static void
a737bd4d 9035do_mav_shift_1 (char * str)
6c43fab6 9036{
a737bd4d 9037 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9038}
9039
9040static void
a737bd4d 9041do_mav_shift_2 (char * str)
6c43fab6 9042{
a737bd4d
NC
9043 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9044}
9045
9046static int
9047mav_parse_offset (char ** str, int * negative)
9048{
9049 char * p = *str;
9050 int offset;
9051
9052 *negative = 0;
9053
9054 skip_whitespace (p);
9055
9056 if (*p == '#')
9057 ++p;
9058
9059 if (*p == '-')
9060 {
9061 *negative = 1;
9062 ++p;
9063 }
9064
9065 if (!ISDIGIT (*p))
9066 {
9067 inst.error = _("offset expected");
9068 return 0;
9069 }
9070
9071 for (offset = 0; *p && ISDIGIT (*p); ++p)
9072 offset = offset * 10 + *p - '0';
9073
9074 if (offset > 0x3fc)
9075 {
9076 inst.error = _("offset out of range");
9077 return 0;
9078 }
9079 if (offset & 0x3)
9080 {
9081 inst.error = _("offset not a multiple of 4");
9082 return 0;
9083 }
9084
9085 *str = p;
9086
9087 return *negative ? -offset : offset;
6c43fab6
RE
9088}
9089
a737bd4d
NC
9090/* Maverick load/store instructions.
9091 <insn><cond> CRd,[Rn,<offset>]{!}.
9092 <insn><cond> CRd,[Rn],<offset>. */
9093
9094static void
9095do_mav_ldst (char * str, enum arm_reg_type reg0)
9096{
9097 int offset, negative;
9098
9099 skip_whitespace (str);
9100
9101 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9102 || skip_past_comma (&str) == FAIL
9103 || *str++ != '['
9104 || reg_required_here (&str, 16) == FAIL)
9105 goto fail_ldst;
9106
9107 if (skip_past_comma (&str) == SUCCESS)
9108 {
9109 /* You are here: "<offset>]{!}". */
9110 inst.instruction |= PRE_INDEX;
9111
9112 offset = mav_parse_offset (&str, &negative);
9113
9114 if (inst.error)
9115 return;
9116
9117 if (*str++ != ']')
9118 {
9119 inst.error = _("missing ]");
9120 return;
9121 }
9122
9123 if (*str == '!')
9124 {
9125 inst.instruction |= WRITE_BACK;
9126 ++str;
9127 }
9128 }
9129 else
9130 {
9131 /* You are here: "], <offset>". */
9132 if (*str++ != ']')
9133 {
9134 inst.error = _("missing ]");
9135 return;
9136 }
9137
9138 if (skip_past_comma (&str) == FAIL
9139 || (offset = mav_parse_offset (&str, &negative), inst.error))
9140 goto fail_ldst;
6c43fab6 9141
a737bd4d
NC
9142 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9143 }
6c43fab6 9144
a737bd4d
NC
9145 if (negative)
9146 offset = -offset;
9147 else
9148 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
6c43fab6 9149
a737bd4d
NC
9150 inst.instruction |= offset >> 2;
9151 end_of_line (str);
9152 return;
6c43fab6 9153
a737bd4d
NC
9154fail_ldst:
9155 if (!inst.error)
9156 inst.error = BAD_ARGS;
6c43fab6
RE
9157}
9158
9159static void
a737bd4d 9160do_mav_ldst_1 (char * str)
6c43fab6 9161{
a737bd4d 9162 do_mav_ldst (str, REG_TYPE_MVF);
6c43fab6
RE
9163}
9164
9165static void
a737bd4d 9166do_mav_ldst_2 (char * str)
6c43fab6 9167{
a737bd4d 9168 do_mav_ldst (str, REG_TYPE_MVD);
6c43fab6
RE
9169}
9170
9171static void
a737bd4d 9172do_mav_ldst_3 (char * str)
6c43fab6 9173{
a737bd4d 9174 do_mav_ldst (str, REG_TYPE_MVFX);
6c43fab6
RE
9175}
9176
9177static void
a737bd4d 9178do_mav_ldst_4 (char * str)
6c43fab6 9179{
a737bd4d 9180 do_mav_ldst (str, REG_TYPE_MVDX);
6c43fab6
RE
9181}
9182
9183static void
a737bd4d 9184do_t_nop (char * str)
6c43fab6 9185{
a737bd4d
NC
9186 /* Do nothing. */
9187 end_of_line (str);
6c43fab6
RE
9188}
9189
a737bd4d
NC
9190/* Handle the Format 4 instructions that do not have equivalents in other
9191 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9192 BIC and MVN. */
6c43fab6
RE
9193
9194static void
a737bd4d 9195do_t_arit (char * str)
6c43fab6 9196{
a737bd4d 9197 int Rd, Rs, Rn;
6c43fab6 9198
6c43fab6
RE
9199 skip_whitespace (str);
9200
a737bd4d 9201 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6c43fab6 9202 || skip_past_comma (&str) == FAIL
a737bd4d 9203 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6c43fab6 9204 {
a737bd4d 9205 inst.error = BAD_ARGS;
6c43fab6
RE
9206 return;
9207 }
9208
a737bd4d 9209 if (skip_past_comma (&str) != FAIL)
6c43fab6 9210 {
a737bd4d
NC
9211 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9212 (It isn't allowed for CMP either, but that isn't handled by this
9213 function.) */
9214 if (inst.instruction == T_OPCODE_TST
9215 || inst.instruction == T_OPCODE_CMN
9216 || inst.instruction == T_OPCODE_NEG
9217 || inst.instruction == T_OPCODE_MVN)
9218 {
9219 inst.error = BAD_ARGS;
9220 return;
9221 }
6c43fab6 9222
a737bd4d
NC
9223 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9224 return;
9225
9226 if (Rs != Rd)
9227 {
9228 inst.error = _("dest and source1 must be the same register");
9229 return;
9230 }
9231 Rs = Rn;
6c43fab6
RE
9232 }
9233
a737bd4d
NC
9234 if (inst.instruction == T_OPCODE_MUL
9235 && Rs == Rd)
9236 as_tsktsk (_("Rs and Rd must be different in MUL"));
9237
9238 inst.instruction |= Rd | (Rs << 3);
6c43fab6 9239 end_of_line (str);
404ff6b5
AH
9240}
9241
9242static void
a737bd4d 9243do_t_add (char * str)
404ff6b5 9244{
a737bd4d 9245 thumb_add_sub (str, 0);
404ff6b5
AH
9246}
9247
9248static void
a737bd4d 9249do_t_asr (char * str)
404ff6b5 9250{
a737bd4d 9251 thumb_shift (str, THUMB_ASR);
404ff6b5
AH
9252}
9253
9254static void
a737bd4d 9255do_t_branch9 (char * str)
404ff6b5 9256{
a737bd4d
NC
9257 if (my_get_expression (&inst.reloc.exp, &str))
9258 return;
9259 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9260 inst.reloc.pc_rel = 1;
9261 end_of_line (str);
404ff6b5
AH
9262}
9263
9264static void
a737bd4d 9265do_t_branch12 (char * str)
404ff6b5 9266{
a737bd4d
NC
9267 if (my_get_expression (&inst.reloc.exp, &str))
9268 return;
9269 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9270 inst.reloc.pc_rel = 1;
9271 end_of_line (str);
404ff6b5
AH
9272}
9273
a737bd4d 9274/* Find the real, Thumb encoded start of a Thumb function. */
404ff6b5 9275
a737bd4d
NC
9276static symbolS *
9277find_real_start (symbolS * symbolP)
404ff6b5 9278{
a737bd4d
NC
9279 char * real_start;
9280 const char * name = S_GET_NAME (symbolP);
9281 symbolS * new_target;
404ff6b5 9282
a737bd4d
NC
9283 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9284#define STUB_NAME ".real_start_of"
404ff6b5 9285
a737bd4d
NC
9286 if (name == NULL)
9287 abort ();
404ff6b5 9288
a737bd4d
NC
9289 /* Names that start with '.' are local labels, not function entry points.
9290 The compiler may generate BL instructions to these labels because it
9291 needs to perform a branch to a far away location. */
9292 if (name[0] == '.')
9293 return symbolP;
404ff6b5 9294
a737bd4d
NC
9295 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9296 sprintf (real_start, "%s%s", STUB_NAME, name);
404ff6b5 9297
a737bd4d
NC
9298 new_target = symbol_find (real_start);
9299
9300 if (new_target == NULL)
404ff6b5 9301 {
a737bd4d
NC
9302 as_warn ("Failed to find real start of function: %s\n", name);
9303 new_target = symbolP;
404ff6b5 9304 }
404ff6b5 9305
a737bd4d
NC
9306 free (real_start);
9307
9308 return new_target;
9309}
404ff6b5
AH
9310
9311static void
a737bd4d 9312do_t_branch23 (char * str)
404ff6b5 9313{
a737bd4d
NC
9314 if (my_get_expression (& inst.reloc.exp, & str))
9315 return;
404ff6b5 9316
a737bd4d
NC
9317 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9318 inst.reloc.pc_rel = 1;
9319 end_of_line (str);
404ff6b5 9320
a737bd4d
NC
9321 /* If the destination of the branch is a defined symbol which does not have
9322 the THUMB_FUNC attribute, then we must be calling a function which has
9323 the (interfacearm) attribute. We look for the Thumb entry point to that
9324 function and change the branch to refer to that function instead. */
9325 if ( inst.reloc.exp.X_op == O_symbol
9326 && inst.reloc.exp.X_add_symbol != NULL
9327 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9328 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9329 inst.reloc.exp.X_add_symbol =
9330 find_real_start (inst.reloc.exp.X_add_symbol);
404ff6b5
AH
9331}
9332
404ff6b5 9333static void
a737bd4d 9334do_t_bx (char * str)
404ff6b5 9335{
a737bd4d 9336 int reg;
404ff6b5
AH
9337
9338 skip_whitespace (str);
9339
a737bd4d
NC
9340 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9341 return;
9342
9343 /* This sets THUMB_H2 from the top bit of reg. */
9344 inst.instruction |= reg << 3;
9345
9346 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9347 should cause the alignment to be checked once it is known. This is
9348 because BX PC only works if the instruction is word aligned. */
9349
9350 end_of_line (str);
404ff6b5
AH
9351}
9352
a737bd4d
NC
9353static void
9354do_t_compare (char * str)
9355{
9356 thumb_mov_compare (str, THUMB_COMPARE);
9357}
404ff6b5
AH
9358
9359static void
a737bd4d 9360do_t_ldmstm (char * str)
404ff6b5 9361{
a737bd4d
NC
9362 int Rb;
9363 long range;
404ff6b5
AH
9364
9365 skip_whitespace (str);
9366
a737bd4d
NC
9367 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9368 return;
404ff6b5 9369
a737bd4d
NC
9370 if (*str != '!')
9371 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9372 else
9373 str++;
9374
9375 if (skip_past_comma (&str) == FAIL
9376 || (range = reg_list (&str)) == FAIL)
404ff6b5 9377 {
a737bd4d 9378 if (! inst.error)
404ff6b5
AH
9379 inst.error = BAD_ARGS;
9380 return;
9381 }
9382
a737bd4d 9383 if (inst.reloc.type != BFD_RELOC_NONE)
404ff6b5 9384 {
a737bd4d
NC
9385 /* This really doesn't seem worth it. */
9386 inst.reloc.type = BFD_RELOC_NONE;
9387 inst.error = _("expression too complex");
404ff6b5
AH
9388 return;
9389 }
9390
a737bd4d 9391 if (range & ~0xff)
404ff6b5 9392 {
a737bd4d 9393 inst.error = _("only lo-regs valid in load/store multiple");
404ff6b5
AH
9394 return;
9395 }
9396
a737bd4d 9397 inst.instruction |= (Rb << 8) | range;
404ff6b5 9398 end_of_line (str);
404ff6b5
AH
9399}
9400
a737bd4d
NC
9401static void
9402do_t_ldr (char * str)
404ff6b5 9403{
a737bd4d
NC
9404 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9405}
404ff6b5 9406
a737bd4d
NC
9407static void
9408do_t_ldrb (char * str)
9409{
9410 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9411}
404ff6b5 9412
a737bd4d
NC
9413static void
9414do_t_ldrh (char * str)
9415{
9416 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9417}
404ff6b5 9418
a737bd4d
NC
9419static void
9420do_t_lds (char * str)
9421{
9422 int Rd, Rb, Ro;
404ff6b5 9423
a737bd4d 9424 skip_whitespace (str);
404ff6b5 9425
a737bd4d
NC
9426 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9427 || skip_past_comma (&str) == FAIL
9428 || *str++ != '['
9429 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9430 || skip_past_comma (&str) == FAIL
9431 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9432 || *str++ != ']')
404ff6b5 9433 {
a737bd4d
NC
9434 if (! inst.error)
9435 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9436 return;
404ff6b5
AH
9437 }
9438
a737bd4d
NC
9439 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9440 end_of_line (str);
9441}
404ff6b5 9442
a737bd4d
NC
9443static void
9444do_t_lsl (char * str)
9445{
9446 thumb_shift (str, THUMB_LSL);
9447}
404ff6b5 9448
a737bd4d
NC
9449static void
9450do_t_lsr (char * str)
9451{
9452 thumb_shift (str, THUMB_LSR);
404ff6b5
AH
9453}
9454
a737bd4d
NC
9455static void
9456do_t_mov (char * str)
9457{
9458 thumb_mov_compare (str, THUMB_MOVE);
9459}
404ff6b5
AH
9460
9461static void
a737bd4d 9462do_t_push_pop (char * str)
404ff6b5 9463{
a737bd4d 9464 long range;
404ff6b5
AH
9465
9466 skip_whitespace (str);
9467
a737bd4d 9468 if ((range = reg_list (&str)) == FAIL)
404ff6b5 9469 {
a737bd4d
NC
9470 if (! inst.error)
9471 inst.error = BAD_ARGS;
9472 return;
9473 }
404ff6b5 9474
a737bd4d
NC
9475 if (inst.reloc.type != BFD_RELOC_NONE)
9476 {
9477 /* This really doesn't seem worth it. */
9478 inst.reloc.type = BFD_RELOC_NONE;
9479 inst.error = _("expression too complex");
9480 return;
9481 }
404ff6b5 9482
a737bd4d
NC
9483 if (range & ~0xff)
9484 {
9485 if ((inst.instruction == T_OPCODE_PUSH
9486 && (range & ~0xff) == 1 << REG_LR)
9487 || (inst.instruction == T_OPCODE_POP
9488 && (range & ~0xff) == 1 << REG_PC))
404ff6b5 9489 {
a737bd4d
NC
9490 inst.instruction |= THUMB_PP_PC_LR;
9491 range &= 0xff;
404ff6b5 9492 }
a737bd4d 9493 else
404ff6b5 9494 {
a737bd4d 9495 inst.error = _("invalid register list to push/pop instruction");
404ff6b5
AH
9496 return;
9497 }
404ff6b5
AH
9498 }
9499
a737bd4d 9500 inst.instruction |= range;
404ff6b5 9501 end_of_line (str);
a737bd4d 9502}
404ff6b5 9503
a737bd4d
NC
9504static void
9505do_t_str (char * str)
9506{
9507 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
404ff6b5
AH
9508}
9509
b99bd4ef 9510static void
a737bd4d 9511do_t_strb (char * str)
b99bd4ef 9512{
a737bd4d 9513 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
b99bd4ef
NC
9514}
9515
a737bd4d
NC
9516static void
9517do_t_strh (char * str)
9518{
9519 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9520}
b99bd4ef
NC
9521
9522static void
a737bd4d 9523do_t_sub (char * str)
b99bd4ef 9524{
a737bd4d
NC
9525 thumb_add_sub (str, 1);
9526}
b99bd4ef 9527
a737bd4d
NC
9528static void
9529do_t_swi (char * str)
9530{
b99bd4ef
NC
9531 skip_whitespace (str);
9532
a737bd4d
NC
9533 if (my_get_expression (&inst.reloc.exp, &str))
9534 return;
b99bd4ef 9535
a737bd4d
NC
9536 inst.reloc.type = BFD_RELOC_ARM_SWI;
9537 end_of_line (str);
9538}
b99bd4ef 9539
a737bd4d
NC
9540static void
9541do_t_adr (char * str)
9542{
9543 int reg;
b99bd4ef 9544
a737bd4d
NC
9545 /* This is a pseudo-op of the form "adr rd, label" to be converted
9546 into a relative address of the form "add rd, pc, #label-.-4". */
9547 skip_whitespace (str);
9548
9549 /* Store Rd in temporary location inside instruction. */
9550 if ((reg = reg_required_here (&str, 4)) == FAIL
9551 || (reg > 7) /* For Thumb reg must be r0..r7. */
9552 || skip_past_comma (&str) == FAIL
9553 || my_get_expression (&inst.reloc.exp, &str))
9554 {
9555 if (!inst.error)
9556 inst.error = BAD_ARGS;
9557 return;
b99bd4ef
NC
9558 }
9559
a737bd4d
NC
9560 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9561 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9562 inst.reloc.pc_rel = 1;
9563 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
b99bd4ef 9564
b99bd4ef
NC
9565 end_of_line (str);
9566}
9567
9568static void
a737bd4d
NC
9569insert_reg (const struct reg_entry * r,
9570 struct hash_control * htab)
b99bd4ef 9571{
a737bd4d
NC
9572 int len = strlen (r->name) + 2;
9573 char * buf = xmalloc (len);
9574 char * buf2 = xmalloc (len);
9575 int i = 0;
b99bd4ef 9576
a737bd4d
NC
9577#ifdef REGISTER_PREFIX
9578 buf[i++] = REGISTER_PREFIX;
9579#endif
9580
9581 strcpy (buf + i, r->name);
9582
9583 for (i = 0; buf[i]; i++)
9584 buf2[i] = TOUPPER (buf[i]);
9585
9586 buf2[i] = '\0';
9587
9588 hash_insert (htab, buf, (PTR) r);
9589 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9590}
9591
9592static void
a737bd4d 9593build_reg_hsh (struct reg_map * map)
b99bd4ef 9594{
a737bd4d
NC
9595 const struct reg_entry *r;
9596
9597 if ((map->htab = hash_new ()) == NULL)
9598 as_fatal (_("virtual memory exhausted"));
9599
9600 for (r = map->names; r->name != NULL; r++)
9601 insert_reg (r, map->htab);
b99bd4ef
NC
9602}
9603
9604static void
a737bd4d
NC
9605insert_reg_alias (char * str,
9606 int regnum,
9607 struct hash_control *htab)
b99bd4ef 9608{
a737bd4d
NC
9609 const char * error;
9610 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9611 const char * name = xmalloc (strlen (str) + 1);
9612
9613 strcpy ((char *) name, str);
9614
9615 new->name = name;
9616 new->number = regnum;
9617 new->builtin = FALSE;
9618
9619 error = hash_insert (htab, name, (PTR) new);
9620 if (error)
9621 {
9622 as_bad (_("failed to create an alias for %s, reason: %s"),
9623 str, error);
9624 free ((char *) name);
9625 free (new);
9626 }
b99bd4ef
NC
9627}
9628
a737bd4d 9629/* Look for the .req directive. This is of the form:
b99bd4ef 9630
a737bd4d
NC
9631 new_register_name .req existing_register_name
9632
9633 If we find one, or if it looks sufficiently like one that we want to
9634 handle any error here, return non-zero. Otherwise return zero. */
9635
9636static int
9637create_register_alias (char * newname, char * p)
b99bd4ef 9638{
a737bd4d
NC
9639 char * q;
9640 char c;
b99bd4ef 9641
a737bd4d
NC
9642 q = p;
9643 skip_whitespace (q);
b99bd4ef 9644
a737bd4d
NC
9645 c = *p;
9646 *p = '\0';
b99bd4ef 9647
a737bd4d
NC
9648 if (*q && !strncmp (q, ".req ", 5))
9649 {
9650 char *copy_of_str;
9651 char *r;
b99bd4ef 9652
a737bd4d
NC
9653#ifndef IGNORE_OPCODE_CASE
9654 newname = original_case_string;
9655#endif
9656 copy_of_str = newname;
b99bd4ef 9657
a737bd4d
NC
9658 q += 4;
9659 skip_whitespace (q);
b99bd4ef 9660
a737bd4d
NC
9661 for (r = q; *r != '\0'; r++)
9662 if (*r == ' ')
9663 break;
b99bd4ef 9664
a737bd4d
NC
9665 if (r != q)
9666 {
9667 enum arm_reg_type new_type, old_type;
9668 int old_regno;
9669 char d = *r;
b99bd4ef 9670
a737bd4d
NC
9671 *r = '\0';
9672 old_type = arm_reg_parse_any (q);
9673 *r = d;
9674
9675 new_type = arm_reg_parse_any (newname);
9676
9677 if (new_type == REG_TYPE_MAX)
9678 {
9679 if (old_type != REG_TYPE_MAX)
9680 {
9681 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9682 insert_reg_alias (newname, old_regno,
9683 all_reg_maps[old_type].htab);
9684 }
9685 else
9686 as_warn (_("register '%s' does not exist\n"), q);
9687 }
9688 else if (old_type == REG_TYPE_MAX)
9689 {
9690 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9691 copy_of_str, q);
9692 }
9693 else
9694 {
9695 /* Do not warn about redefinitions to the same alias. */
9696 if (new_type != old_type
9697 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9698 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9699 as_warn (_("ignoring redefinition of register alias '%s'"),
9700 copy_of_str);
9701
9702 }
9703 }
9704 else
9705 as_warn (_("ignoring incomplete .req pseuso op"));
9706
9707 *p = c;
9708 return 1;
9709 }
9710
9711 *p = c;
9712 return 0;
b99bd4ef
NC
9713}
9714
9715static void
a737bd4d 9716set_constant_flonums (void)
b99bd4ef 9717{
a737bd4d 9718 int i;
b99bd4ef 9719
a737bd4d
NC
9720 for (i = 0; i < NUM_FLOAT_VALS; i++)
9721 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9722 abort ();
b99bd4ef
NC
9723}
9724
a737bd4d
NC
9725\f
9726static const struct asm_opcode insns[] =
b99bd4ef 9727{
a737bd4d
NC
9728 /* Core ARM Instructions. */
9729 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9730 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9731 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9732 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9733 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9734 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9735 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9736 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9737 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9738 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9739 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9740 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9741 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9742 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9743 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9744 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9745 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9746 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9747 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9748 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9749
9750 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9751 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9752 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9753 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9754 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9755 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9756 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9757 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9758 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9759 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9760 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9761 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9762
9763 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9764 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9765 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9766 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9767
9768 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9769 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9770 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9771 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9772 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9773 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9774 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9775 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9776
9777 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9778 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9779 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9780 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9781 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9782 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9783 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9784 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9785
9786 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9787 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9788 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9789 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9790 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9791 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9792 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9793 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
b99bd4ef 9794
a737bd4d
NC
9795 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9796#ifdef TE_WINCE
9797 /* XXX This is the wrong place to do this. Think multi-arch. */
9798 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9799 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9800#else
9801 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9802 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9803#endif
b99bd4ef 9804
a737bd4d
NC
9805 /* Pseudo ops. */
9806 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9807 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
0dd132b6 9808 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
b99bd4ef 9809
a737bd4d
NC
9810 /* ARM 2 multiplies. */
9811 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9812 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9813 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9814 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 9815
a737bd4d
NC
9816 /* Generic coprocessor instructions. */
9817 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9818 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9819 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9820 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9821 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9822 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9823 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
b99bd4ef 9824
a737bd4d
NC
9825 /* ARM 3 - swp instructions. */
9826 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9827 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 9828
a737bd4d
NC
9829 /* ARM 6 Status register instructions. */
9830 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9831 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9832 /* ScottB: our code uses 0xe128f000 for msr.
9833 NickC: but this is wrong because the bits 16 through 19 are
9834 handled by the PSR_xxx defines above. */
b99bd4ef 9835
a737bd4d
NC
9836 /* ARM 7M long multiplies. */
9837 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9838 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9839 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9840 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9841 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9842 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9843 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9844 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
b99bd4ef 9845
a737bd4d
NC
9846 /* ARM Architecture 4. */
9847 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9848 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9849 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9850 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 9851
a737bd4d
NC
9852 /* ARM Architecture 4T. */
9853 /* Note: bx (and blx) are required on V5, even if the processor does
9854 not support Thumb. */
9855 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
b99bd4ef 9856
a737bd4d
NC
9857 /* ARM Architecture 5T. */
9858 /* Note: blx has 2 variants, so the .value is set dynamically.
9859 Only one of the variants has conditional execution. */
9860 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9861 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9862 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9863 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9864 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9865 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9866 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9867 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9868 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9869 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
b99bd4ef 9870
a737bd4d
NC
9871 /* ARM Architecture 5TExP. */
9872 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9873 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9874 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9875 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 9876
a737bd4d
NC
9877 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9878 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 9879
a737bd4d
NC
9880 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9881 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9882 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9883 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
b99bd4ef 9884
a737bd4d
NC
9885 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9886 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9887 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9888 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 9889
a737bd4d
NC
9890 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9891 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 9892
a737bd4d
NC
9893 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9894 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9895 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9896 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
b99bd4ef 9897
a737bd4d
NC
9898 /* ARM Architecture 5TE. */
9899 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9900 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9901 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
b99bd4ef 9902
a737bd4d
NC
9903 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9904 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
b99bd4ef 9905
a737bd4d
NC
9906 /* ARM Architecture 5TEJ. */
9907 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
b99bd4ef 9908
a737bd4d
NC
9909 /* ARM V6. */
9910 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9911 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9912 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9913 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9914 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9915 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9916 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9917 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9918 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9919 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9920 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9921 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9922 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9923 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9924 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9925 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9926 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9927 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9928 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9929 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9930 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9931 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9932 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9933 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9934 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9935 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9936 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9937 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9938 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9939 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9940 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9941 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9942 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9943 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9944 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9945 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9946 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9947 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9948 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9949 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9950 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9951 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9952 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9953 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9954 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9955 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9956 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9957 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9958 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9959 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9960 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9961 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9962 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9963 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9964 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9965 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
9966 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
9967 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
9968 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
9969 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
9970 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
9971 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
9972 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
9973 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
9974 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
9975 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
9976 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
9977 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
9978 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
9979 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
9980 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
9981 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
9982 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
9983 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
9984 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
9985 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
9986 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
9987 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
9988 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
9989 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
9990 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
9991 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
9992 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
9993 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
9994 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
9995 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
9996 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
9997 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
9998 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
9999 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10000 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10001 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10002 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10003 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10004 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10005 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10006 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10007 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10008 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
b99bd4ef 10009
0dd132b6
NC
10010 /* ARM V6K. */
10011 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10012 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10013 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10014 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10015 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10016 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10017 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10018 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10019 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10020 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10021 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
7ed4c4c5 10022
0dd132b6
NC
10023 /* ARM V6Z. */
10024 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10025
a737bd4d
NC
10026 /* Core FPA instruction set (V1). */
10027 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10028 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10029 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10030 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
b99bd4ef 10031
a737bd4d
NC
10032 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10033 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10034 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10035 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10036
a737bd4d
NC
10037 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10038 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10039 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10040 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10041
a737bd4d
NC
10042 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10043 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10044 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10045 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10046 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10047 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10048 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10049 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10050 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10051 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10052 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10053 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10054
a737bd4d
NC
10055 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10056 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10057 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10058 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10059 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10060 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10061 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10062 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10063 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10064 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10065 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10066 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10067
a737bd4d
NC
10068 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10069 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10070 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10071 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10072 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10073 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10074 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10075 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10076 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10077 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10078 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10079 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10080
a737bd4d
NC
10081 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10082 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10083 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10085 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10091 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10093
a737bd4d
NC
10094 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10095 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10096 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10098 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10104 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10106
a737bd4d
NC
10107 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10108 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10109 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10111 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10117 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10119
a737bd4d
NC
10120 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10121 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10122 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10124 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10130 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10132
a737bd4d
NC
10133 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10134 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10135 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10137 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10143 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10145
a737bd4d
NC
10146 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10147 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10148 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10150 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10156 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10158
a737bd4d
NC
10159 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10160 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10161 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10163 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10169 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10171
a737bd4d
NC
10172 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10173 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10174 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10176 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10182 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10184
a737bd4d
NC
10185 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10186 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10187 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10189 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10195 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10197
a737bd4d
NC
10198 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10199 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10200 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10202 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10208 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10210
a737bd4d
NC
10211 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10212 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10213 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10215 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10221 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10223
a737bd4d
NC
10224 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10225 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10226 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10228 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10234 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10236
a737bd4d
NC
10237 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10238 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10239 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10240 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10241 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10242 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10243 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10244 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10245 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10246 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10247 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10248 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10249
a737bd4d
NC
10250 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10251 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10252 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10253 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10254 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10255 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10256 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10257 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10258 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10259 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10260 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10261 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10262
a737bd4d
NC
10263 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10264 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10265 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10266 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10267 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10268 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10269 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10270 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10271 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10272 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10273 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10274 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10275
a737bd4d
NC
10276 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10277 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10278 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10279 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10280 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10281 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10282 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10283 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10284 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10285 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10286 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10287 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10288
a737bd4d
NC
10289 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10290 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10291 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10293 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10299 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10301
a737bd4d
NC
10302 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10303 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10304 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10306 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10312 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10314
a737bd4d
NC
10315 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10316 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10317 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10319 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10325 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10327
a737bd4d
NC
10328 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10329 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10330 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10332 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10338 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10340
a737bd4d
NC
10341 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10342 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10343 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10345 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10351 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10353
a737bd4d
NC
10354 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10355 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10356 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10358 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10364 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10366
a737bd4d
NC
10367 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10368 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10369 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10371 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10377 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10379
a737bd4d
NC
10380 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10381 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10382 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10384 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10390 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10392
a737bd4d
NC
10393 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10394 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10395 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10397 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10403 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10405
a737bd4d
NC
10406 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10407 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10408 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10409 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10410 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10411 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10412 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10413 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10414 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10415 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10416 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10417 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10418
a737bd4d
NC
10419 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10420 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10421 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10422 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10423 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10424 not be an optional suffix, but part of the instruction. To be
10425 compatible, we accept either. */
10426 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10427 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
b99bd4ef 10428
a737bd4d
NC
10429 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10430 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10431 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10432 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10433 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10434 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10435 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10436 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10437 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10438 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10439 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10440 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
6c43fab6 10441
a737bd4d
NC
10442 /* The implementation of the FIX instruction is broken on some
10443 assemblers, in that it accepts a precision specifier as well as a
10444 rounding specifier, despite the fact that this is meaningless.
10445 To be more compatible, we accept it as well, though of course it
10446 does not set any bits. */
10447 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10448 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10449 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10450 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10451 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10452 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10453 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10454 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10455 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10456 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10457 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10458 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10459 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
6c43fab6 10460
a737bd4d
NC
10461 /* Instructions that were new with the real FPA, call them V2. */
10462 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10463 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10464 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10465 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10466 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10467 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
6c43fab6 10468
a737bd4d
NC
10469 /* VFP V1xD (single precision). */
10470 /* Moves and type conversions. */
10471 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10472 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10473 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10474 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10475 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10476 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10477 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10478 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10479 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10480 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10481 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10482 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
6c43fab6 10483
a737bd4d
NC
10484 /* Memory operations. */
10485 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10486 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10487 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10488 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10489 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10490 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10491 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10492 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10493 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10494 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10495 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10496 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10497 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10498 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10499 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10500 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10501 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10502 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
6c43fab6 10503
a737bd4d
NC
10504 /* Monadic operations. */
10505 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10506 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10507 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
6c43fab6 10508
a737bd4d
NC
10509 /* Dyadic operations. */
10510 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10511 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10512 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10513 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10514 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10515 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10516 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10517 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10518 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
6c43fab6 10519
a737bd4d
NC
10520 /* Comparisons. */
10521 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10522 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10523 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10524 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
6c43fab6 10525
a737bd4d
NC
10526 /* VFP V1 (Double precision). */
10527 /* Moves and type conversions. */
10528 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10529 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10530 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10531 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10532 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10533 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10534 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10535 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10536 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10537 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10538 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10539 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10540 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
6c43fab6 10541
a737bd4d
NC
10542 /* Memory operations. */
10543 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10544 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10545 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10546 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10547 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10548 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10549 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10550 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10551 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10552 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
6c43fab6 10553
a737bd4d
NC
10554 /* Monadic operations. */
10555 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10556 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10557 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
6c43fab6 10558
a737bd4d
NC
10559 /* Dyadic operations. */
10560 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10561 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10562 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10563 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10564 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10565 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10566 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10567 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10568 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
6c43fab6 10569
a737bd4d
NC
10570 /* Comparisons. */
10571 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10572 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10573 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10574 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
6c43fab6 10575
a737bd4d
NC
10576 /* VFP V2. */
10577 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10578 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10579 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10580 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
6c43fab6 10581
a737bd4d
NC
10582 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10583 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10584 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10585 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10586 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10587 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10588 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10589 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10590 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
cc8a6dd0 10591
a737bd4d
NC
10592 /* Intel Wireless MMX technology instructions. */
10593 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10594 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10595 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10596 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10597 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10598 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10599 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10600 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10601 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10602 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10603 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10604 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10605 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10606 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10607 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10608 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10609 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10610 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10611 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10612 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10613 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10614 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10615 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10616 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10617 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10618 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10619 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10620 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10621 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10622 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10623 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10624 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10625 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10626 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10627 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10628 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10629 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10630 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10631 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10632 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10633 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10634 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10635 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10636 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10637 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10638 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10639 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10640 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10641 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10642 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10643 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10644 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10645 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10646 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10647 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10648 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10649 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10650 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10651 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10652 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10653 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10654 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10655 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10656 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10657 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10658 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10659 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10660 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10661 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10662 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10663 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10664 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10665 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10666 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10667 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10668 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10671 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10673 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10678 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10680 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10682 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10683 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10684 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10686 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10688 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10690 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10693 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10695 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10696 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10697 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10698 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10699 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10700 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10701 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10702 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10703 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10704 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10705 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10706 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10707 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10708 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10709 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10710 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10711 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10712 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10713 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10714 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10715 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10716 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10717 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10718 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10719 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10720 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10721 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10722 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10723 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10724 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10725 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10726 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10727 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10728 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10729 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10730 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10731 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10732 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10733 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10734 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10735 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10736 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10737 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10738 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10739 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10740 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10741 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10742 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10743 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10744 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10745 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10746 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10747 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10748 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10749 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10750 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10751 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10752 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10753 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10754 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
b99bd4ef 10755
a737bd4d
NC
10756 /* Cirrus Maverick instructions. */
10757 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10758 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10759 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10760 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10761 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10762 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10763 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10764 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10765 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10766 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10767 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10768 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10769 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10770 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10771 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10772 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10773 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10774 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10775 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10776 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10777 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10778 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10779 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10780 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10781 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10782 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10783 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10784 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10785 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10786 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10787 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10788 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10789 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10790 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10791 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10792 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10793 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10794 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10795 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10796 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10797 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10798 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10799 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10800 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10801 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10802 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10803 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10804 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10805 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10806 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10807 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10808 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10809 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10810 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10811 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10812 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10813 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10814 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10815 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10816 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10817 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10818 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10819 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10820 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10821 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10822 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10823 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10824 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10825 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10826 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10827 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10828 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10829 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10830 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10831 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10832 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10833};
b99bd4ef 10834
90e4755a 10835/* Iterate over the base tables to create the instruction patterns. */
a737bd4d 10836
90e4755a 10837static void
a737bd4d 10838build_arm_ops_hsh (void)
90e4755a
RE
10839{
10840 unsigned int i;
10841 unsigned int j;
10842 static struct obstack insn_obstack;
10843
10844 obstack_begin (&insn_obstack, 4000);
10845
10846 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10847 {
6c43fab6 10848 const struct asm_opcode *insn = insns + i;
90e4755a
RE
10849
10850 if (insn->cond_offset != 0)
10851 {
10852 /* Insn supports conditional execution. Build the varaints
10853 and insert them in the hash table. */
10854 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10855 {
10856 unsigned len = strlen (insn->template);
10857 struct asm_opcode *new;
10858 char *template;
10859
10860 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10861 /* All condition codes are two characters. */
10862 template = obstack_alloc (&insn_obstack, len + 3);
10863
10864 strncpy (template, insn->template, insn->cond_offset);
10865 strcpy (template + insn->cond_offset, conds[j].template);
10866 if (len > insn->cond_offset)
10867 strcpy (template + insn->cond_offset + 2,
10868 insn->template + insn->cond_offset);
10869 new->template = template;
10870 new->cond_offset = 0;
10871 new->variant = insn->variant;
10872 new->parms = insn->parms;
10873 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10874
10875 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10876 }
10877 }
10878 /* Finally, insert the unconditional insn in the table directly;
10879 no need to build a copy. */
10880 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10881 }
10882}
10883
0bbf2aa4 10884#if 0 /* Suppressed - for now. */
5a6c6817
NC
10885#if defined OBJ_ELF || defined OBJ_COFF
10886
10887#ifdef OBJ_ELF
10888#define arm_Note Elf_External_Note
10889#else
10890typedef struct
10891{
10892 unsigned char namesz[4]; /* Size of entry's owner string. */
10893 unsigned char descsz[4]; /* Size of the note descriptor. */
10894 unsigned char type[4]; /* Interpretation of the descriptor. */
10895 char name[1]; /* Start of the name+desc data. */
10896} arm_Note;
10897#endif
10898
10899/* The description is kept to a fix sized in order to make updating
10900 it and merging it easier. */
10901#define ARM_NOTE_DESCRIPTION_LENGTH 8
10902
10903static void
a737bd4d
NC
10904arm_add_note (const char * name,
10905 const char * description,
10906 unsigned int type)
5a6c6817
NC
10907{
10908 arm_Note note ATTRIBUTE_UNUSED;
10909 char * p;
10910 unsigned int name_len;
10911
10912 name_len = (strlen (name) + 1 + 3) & ~3;
a737bd4d 10913
5a6c6817
NC
10914 p = frag_more (sizeof (note.namesz));
10915 md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10916
10917 p = frag_more (sizeof (note.descsz));
10918 md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10919
10920 p = frag_more (sizeof (note.type));
10921 md_number_to_chars (p, (valueT) type, sizeof (note.type));
10922
10923 p = frag_more (name_len);
10924 strcpy (p, name);
10925
a737bd4d
NC
10926 p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10927 strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10928 frag_align (2, 0, 0);
10929}
10930#endif
10931#endif
10932
10933\f
10934static const struct thumb_opcode tinsns[] =
10935{
10936 /* Thumb v1 (ARMv4T). */
10937 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10938 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10939 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10940 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10941 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10942 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10943 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10944 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10945 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10946 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10947 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10948 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10949 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10950 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10951 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10952 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10953 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10954 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10955 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10956 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10957 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10958 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10959 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10960 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10961 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
10962 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
10963 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
10964 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
10965 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
10966 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
10967 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
10968 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
10969 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
10970 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10971 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10972 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10973 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10974 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
10975 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
10976 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
10977 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
10978 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
10979 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
10980 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
10981 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
10982 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
10983 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
10984 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
10985 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
10986 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
10987 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
10988 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
10989 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
10990 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
10991 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
10992 /* Pseudo ops: */
10993 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
10994 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
10995 /* Thumb v2 (ARMv5T). */
10996 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
10997 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
10998
10999 /* ARM V6. */
11000 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11001 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11002 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11003 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11004 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11005 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11006 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11007 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11008 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11009 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11010 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
11011};
5a6c6817 11012
b99bd4ef 11013void
a737bd4d 11014md_begin (void)
b99bd4ef
NC
11015{
11016 unsigned mach;
11017 unsigned int i;
11018
11019 if ( (arm_ops_hsh = hash_new ()) == NULL
11020 || (arm_tops_hsh = hash_new ()) == NULL
11021 || (arm_cond_hsh = hash_new ()) == NULL
11022 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11023 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11024 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11025
90e4755a 11026 build_arm_ops_hsh ();
b99bd4ef
NC
11027 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11028 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11029 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11030 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11031 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11032 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11033 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11034 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11035
6c43fab6
RE
11036 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11037 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11038
11039 set_constant_flonums ();
11040
03b1477f
RE
11041 /* Set the cpu variant based on the command-line options. We prefer
11042 -mcpu= over -march= if both are set (as for GCC); and we prefer
11043 -mfpu= over any other way of setting the floating point unit.
11044 Use of legacy options with new options are faulted. */
11045 if (legacy_cpu != -1)
11046 {
11047 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11048 as_bad (_("use of old and new-style options to set CPU type"));
11049
11050 mcpu_cpu_opt = legacy_cpu;
11051 }
11052 else if (mcpu_cpu_opt == -1)
11053 mcpu_cpu_opt = march_cpu_opt;
11054
11055 if (legacy_fpu != -1)
11056 {
11057 if (mfpu_opt != -1)
11058 as_bad (_("use of old and new-style options to set FPU type"));
11059
11060 mfpu_opt = legacy_fpu;
11061 }
11062 else if (mfpu_opt == -1)
11063 {
39c2da32
RE
11064#if !(defined (TE_LINUX) || defined (TE_NetBSD))
11065 /* Some environments specify a default FPU. If they don't, infer it
11066 from the processor. */
03b1477f
RE
11067 if (mcpu_fpu_opt != -1)
11068 mfpu_opt = mcpu_fpu_opt;
11069 else
11070 mfpu_opt = march_fpu_opt;
39c2da32
RE
11071#else
11072 mfpu_opt = FPU_DEFAULT;
11073#endif
03b1477f
RE
11074 }
11075
11076 if (mfpu_opt == -1)
11077 {
11078 if (mcpu_cpu_opt == -1)
11079 mfpu_opt = FPU_DEFAULT;
11080 else if (mcpu_cpu_opt & ARM_EXT_V5)
11081 mfpu_opt = FPU_ARCH_VFP_V2;
11082 else
11083 mfpu_opt = FPU_ARCH_FPA;
11084 }
11085
11086 if (mcpu_cpu_opt == -1)
11087 mcpu_cpu_opt = CPU_DEFAULT;
11088
11089 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11090
b99bd4ef 11091 {
7cc69913
NC
11092 unsigned int flags = 0;
11093
11094#if defined OBJ_ELF
11095 flags = meabi_flags;
d507cf36
PB
11096
11097 switch (meabi_flags)
33a392fb 11098 {
d507cf36 11099 case EF_ARM_EABI_UNKNOWN:
7cc69913
NC
11100#endif
11101#if defined OBJ_COFF || defined OBJ_ELF
d507cf36
PB
11102 /* Set the flags in the private structure. */
11103 if (uses_apcs_26) flags |= F_APCS26;
11104 if (support_interwork) flags |= F_INTERWORK;
11105 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11106 if (pic_code) flags |= F_PIC;
11107 if ((cpu_variant & FPU_ANY) == FPU_NONE
11108 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11109 flags |= F_SOFT_FLOAT;
11110
d507cf36
PB
11111 switch (mfloat_abi_opt)
11112 {
11113 case ARM_FLOAT_ABI_SOFT:
11114 case ARM_FLOAT_ABI_SOFTFP:
11115 flags |= F_SOFT_FLOAT;
11116 break;
33a392fb 11117
d507cf36
PB
11118 case ARM_FLOAT_ABI_HARD:
11119 if (flags & F_SOFT_FLOAT)
11120 as_bad (_("hard-float conflicts with specified fpu"));
11121 break;
11122 }
03b1477f 11123
7cc69913
NC
11124 /* Using VFP conventions (even if soft-float). */
11125 if (cpu_variant & FPU_VFP_EXT_NONE)
11126 flags |= F_VFP_FLOAT;
11127#endif
fde78edd 11128#if defined OBJ_ELF
d507cf36
PB
11129 if (cpu_variant & FPU_ARCH_MAVERICK)
11130 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11131 break;
11132
8cb51566 11133 case EF_ARM_EABI_VER4:
d507cf36
PB
11134 /* No additional flags to set. */
11135 break;
11136
11137 default:
11138 abort ();
11139 }
7cc69913
NC
11140#endif
11141#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef
NC
11142 bfd_set_private_flags (stdoutput, flags);
11143
11144 /* We have run out flags in the COFF header to encode the
11145 status of ATPCS support, so instead we create a dummy,
11146 empty, debug section called .arm.atpcs. */
11147 if (atpcs)
11148 {
11149 asection * sec;
11150
11151 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11152
11153 if (sec != NULL)
11154 {
11155 bfd_set_section_flags
11156 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11157 bfd_set_section_size (stdoutput, sec, 0);
11158 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11159 }
11160 }
b99bd4ef 11161#endif
7cc69913 11162 }
b99bd4ef
NC
11163
11164 /* Record the CPU type as well. */
11165 switch (cpu_variant & ARM_CPU_MASK)
11166 {
11167 case ARM_2:
11168 mach = bfd_mach_arm_2;
11169 break;
11170
11171 case ARM_3: /* Also ARM_250. */
11172 mach = bfd_mach_arm_2a;
11173 break;
11174
b89dddec
RE
11175 case ARM_6: /* Also ARM_7. */
11176 mach = bfd_mach_arm_3;
11177 break;
11178
b99bd4ef 11179 default:
5a6c6817 11180 mach = bfd_mach_arm_unknown;
b99bd4ef 11181 break;
b99bd4ef
NC
11182 }
11183
11184 /* Catch special cases. */
e16bb312
NC
11185 if (cpu_variant & ARM_CEXT_IWMMXT)
11186 mach = bfd_mach_arm_iWMMXt;
11187 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11188 mach = bfd_mach_arm_XScale;
fde78edd
NC
11189 else if (cpu_variant & ARM_CEXT_MAVERICK)
11190 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11191 else if (cpu_variant & ARM_EXT_V5E)
11192 mach = bfd_mach_arm_5TE;
11193 else if (cpu_variant & ARM_EXT_V5)
11194 {
b89dddec 11195 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11196 mach = bfd_mach_arm_5T;
11197 else
11198 mach = bfd_mach_arm_5;
11199 }
b89dddec 11200 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11201 {
b89dddec 11202 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11203 mach = bfd_mach_arm_4T;
11204 else
11205 mach = bfd_mach_arm_4;
11206 }
b89dddec 11207 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11208 mach = bfd_mach_arm_3M;
11209
5a6c6817 11210#if 0 /* Suppressed - for now. */
e16bb312 11211#if defined (OBJ_ELF) || defined (OBJ_COFF)
5a6c6817
NC
11212
11213 /* Create a .note section to fully identify this arm binary. */
11214
11215#define NOTE_ARCH_STRING "arch: "
11216
11217#if defined OBJ_COFF && ! defined NT_VERSION
11218#define NT_VERSION 1
11219#define NT_ARCH 2
11220#endif
a737bd4d 11221
e16bb312 11222 {
e16bb312
NC
11223 segT current_seg = now_seg;
11224 subsegT current_subseg = now_subseg;
11225 asection * arm_arch;
5a6c6817
NC
11226 const char * arch_string;
11227
e16bb312
NC
11228 arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11229
11230#ifdef OBJ_COFF
11231 bfd_set_section_flags (stdoutput, arm_arch,
11232 SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11233 | SEC_HAS_CONTENTS);
e41f12f3
DJ
11234#else
11235 bfd_set_section_flags (stdoutput, arm_arch,
11236 SEC_READONLY | SEC_HAS_CONTENTS);
e16bb312
NC
11237#endif
11238 arm_arch->output_section = arm_arch;
11239 subseg_set (arm_arch, 0);
e16bb312 11240
5a6c6817
NC
11241 switch (mach)
11242 {
11243 default:
11244 case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11245 case bfd_mach_arm_2: arch_string = "armv2"; break;
11246 case bfd_mach_arm_2a: arch_string = "armv2a"; break;
11247 case bfd_mach_arm_3: arch_string = "armv3"; break;
11248 case bfd_mach_arm_3M: arch_string = "armv3M"; break;
11249 case bfd_mach_arm_4: arch_string = "armv4"; break;
11250 case bfd_mach_arm_4T: arch_string = "armv4t"; break;
11251 case bfd_mach_arm_5: arch_string = "armv5"; break;
11252 case bfd_mach_arm_5T: arch_string = "armv5t"; break;
11253 case bfd_mach_arm_5TE: arch_string = "armv5te"; break;
11254 case bfd_mach_arm_XScale: arch_string = "XScale"; break;
11255 case bfd_mach_arm_ep9312: arch_string = "ep9312"; break;
a737bd4d 11256 case bfd_mach_arm_iWMMXt: arch_string = "iWMMXt"; break;
5a6c6817
NC
11257 }
11258
11259 arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
e16bb312
NC
11260
11261 subseg_set (current_seg, current_subseg);
11262 }
11263#endif
5a6c6817 11264#endif /* Suppressed code. */
a737bd4d 11265
b99bd4ef
NC
11266 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11267}
11268
11269/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11270 for use in the a.out file, and stores them in the array pointed to by buf.
11271 This knows about the endian-ness of the target machine and does
11272 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11273 2 (short) and 4 (long) Floating numbers are put out as a series of
11274 LITTLENUMS (shorts, here at least). */
11275
11276void
a737bd4d 11277md_number_to_chars (char * buf, valueT val, int n)
b99bd4ef
NC
11278{
11279 if (target_big_endian)
11280 number_to_chars_bigendian (buf, val, n);
11281 else
11282 number_to_chars_littleendian (buf, val, n);
11283}
11284
11285static valueT
a737bd4d 11286md_chars_to_number (char * buf, int n)
b99bd4ef
NC
11287{
11288 valueT result = 0;
11289 unsigned char * where = (unsigned char *) buf;
11290
11291 if (target_big_endian)
11292 {
11293 while (n--)
11294 {
11295 result <<= 8;
11296 result |= (*where++ & 255);
11297 }
11298 }
11299 else
11300 {
11301 while (n--)
11302 {
11303 result <<= 8;
11304 result |= (where[n] & 255);
11305 }
11306 }
11307
11308 return result;
11309}
11310
11311/* Turn a string in input_line_pointer into a floating point constant
11312 of type TYPE, and store the appropriate bytes in *LITP. The number
11313 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11314 returned, or NULL on OK.
11315
11316 Note that fp constants aren't represent in the normal way on the ARM.
11317 In big endian mode, things are as expected. However, in little endian
11318 mode fp constants are big-endian word-wise, and little-endian byte-wise
11319 within the words. For example, (double) 1.1 in big endian mode is
11320 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11321 the byte sequence 99 99 f1 3f 9a 99 99 99.
11322
11323 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11324
11325char *
a737bd4d 11326md_atof (int type, char * litP, int * sizeP)
b99bd4ef
NC
11327{
11328 int prec;
11329 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11330 char *t;
11331 int i;
11332
11333 switch (type)
11334 {
11335 case 'f':
11336 case 'F':
11337 case 's':
11338 case 'S':
11339 prec = 2;
11340 break;
11341
11342 case 'd':
11343 case 'D':
11344 case 'r':
11345 case 'R':
11346 prec = 4;
11347 break;
11348
11349 case 'x':
11350 case 'X':
11351 prec = 6;
11352 break;
11353
11354 case 'p':
11355 case 'P':
11356 prec = 6;
11357 break;
11358
11359 default:
11360 *sizeP = 0;
f03698e6 11361 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11362 }
11363
11364 t = atof_ieee (input_line_pointer, type, words);
11365 if (t)
11366 input_line_pointer = t;
11367 *sizeP = prec * 2;
11368
11369 if (target_big_endian)
11370 {
11371 for (i = 0; i < prec; i++)
11372 {
11373 md_number_to_chars (litP, (valueT) words[i], 2);
11374 litP += 2;
11375 }
11376 }
11377 else
11378 {
bfae80f2
RE
11379 if (cpu_variant & FPU_ARCH_VFP)
11380 for (i = prec - 1; i >= 0; i--)
11381 {
11382 md_number_to_chars (litP, (valueT) words[i], 2);
11383 litP += 2;
11384 }
11385 else
11386 /* For a 4 byte float the order of elements in `words' is 1 0.
11387 For an 8 byte float the order is 1 0 3 2. */
11388 for (i = 0; i < prec; i += 2)
11389 {
11390 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11391 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11392 litP += 4;
11393 }
b99bd4ef
NC
11394 }
11395
11396 return 0;
11397}
11398
11399/* The knowledge of the PC's pipeline offset is built into the insns
11400 themselves. */
11401
11402long
a737bd4d 11403md_pcrel_from (fixS * fixP)
b99bd4ef
NC
11404{
11405 if (fixP->fx_addsy
11406 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11407 && fixP->fx_subsy == NULL)
11408 return 0;
11409
11410 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11411 {
11412 /* PC relative addressing on the Thumb is slightly odd
11413 as the bottom two bits of the PC are forced to zero
11414 for the calculation. */
11415 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11416 }
11417
11418#ifdef TE_WINCE
2d2255b5
KH
11419 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11420 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11421 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11422#else
11423 return fixP->fx_where + fixP->fx_frag->fr_address;
11424#endif
11425}
11426
11427/* Round up a section size to the appropriate boundary. */
11428
11429valueT
a737bd4d
NC
11430md_section_align (segT segment ATTRIBUTE_UNUSED,
11431 valueT size)
b99bd4ef
NC
11432{
11433#ifdef OBJ_ELF
11434 return size;
11435#else
11436 /* Round all sects to multiple of 4. */
11437 return (size + 3) & ~3;
11438#endif
11439}
11440
11441/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11442 Otherwise we have no need to default values of symbols. */
11443
11444symbolS *
a737bd4d 11445md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
b99bd4ef
NC
11446{
11447#ifdef OBJ_ELF
11448 if (name[0] == '_' && name[1] == 'G'
11449 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11450 {
11451 if (!GOT_symbol)
11452 {
11453 if (symbol_find (name))
11454 as_bad ("GOT already in the symbol table");
11455
11456 GOT_symbol = symbol_new (name, undefined_section,
11457 (valueT) 0, & zero_address_frag);
11458 }
11459
11460 return GOT_symbol;
11461 }
11462#endif
11463
11464 return 0;
11465}
11466
94f592af 11467void
a737bd4d
NC
11468md_apply_fix3 (fixS * fixP,
11469 valueT * valP,
11470 segT seg)
b99bd4ef 11471{
94f592af 11472 offsetT value = * valP;
b99bd4ef
NC
11473 offsetT newval;
11474 unsigned int newimm;
11475 unsigned long temp;
11476 int sign;
11477 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11478 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11479
11480 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
11481
11482 /* Note whether this will delete the relocation. */
11483#if 0
11484 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
11485 doesn't work fully.) */
11486 if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
11487 && !fixP->fx_pcrel)
11488#else
11489 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
11490#endif
11491 fixP->fx_done = 1;
11492
11493 /* If this symbol is in a different section then we need to leave it for
11494 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11495 so we have to undo it's effects here. */
11496 if (fixP->fx_pcrel)
11497 {
11498 if (fixP->fx_addsy != NULL
11499 && S_IS_DEFINED (fixP->fx_addsy)
11500 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7f266840 11501 value += md_pcrel_from (fixP);
b99bd4ef
NC
11502 }
11503
11504 /* Remember value for emit_reloc. */
11505 fixP->fx_addnumber = value;
11506
11507 switch (fixP->fx_r_type)
11508 {
11509 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
11510 /* We claim that this fixup has been processed here,
11511 even if in fact we generate an error because we do
11512 not have a reloc for it, so tc_gen_reloc will reject it. */
11513 fixP->fx_done = 1;
11514
11515 if (fixP->fx_addsy
11516 && ! S_IS_DEFINED (fixP->fx_addsy))
11517 {
11518 as_bad_where (fixP->fx_file, fixP->fx_line,
11519 _("undefined symbol %s used as an immediate value"),
11520 S_GET_NAME (fixP->fx_addsy));
11521 break;
11522 }
11523
b99bd4ef
NC
11524 newimm = validate_immediate (value);
11525 temp = md_chars_to_number (buf, INSN_SIZE);
11526
11527 /* If the instruction will fail, see if we can fix things up by
11528 changing the opcode. */
11529 if (newimm == (unsigned int) FAIL
11530 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11531 {
11532 as_bad_where (fixP->fx_file, fixP->fx_line,
11533 _("invalid constant (%lx) after fixup"),
11534 (unsigned long) value);
11535 break;
11536 }
11537
11538 newimm |= (temp & 0xfffff000);
11539 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11540 break;
11541
11542 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11543 {
11544 unsigned int highpart = 0;
11545 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 11546
b99bd4ef
NC
11547 newimm = validate_immediate (value);
11548 temp = md_chars_to_number (buf, INSN_SIZE);
11549
11550 /* If the instruction will fail, see if we can fix things up by
11551 changing the opcode. */
11552 if (newimm == (unsigned int) FAIL
11553 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11554 {
11555 /* No ? OK - try using two ADD instructions to generate
11556 the value. */
11557 newimm = validate_immediate_twopart (value, & highpart);
11558
11559 /* Yes - then make sure that the second instruction is
11560 also an add. */
11561 if (newimm != (unsigned int) FAIL)
11562 newinsn = temp;
11563 /* Still No ? Try using a negated value. */
11564 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11565 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11566 /* Otherwise - give up. */
11567 else
11568 {
11569 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11570 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 11571 (long) value);
b99bd4ef
NC
11572 break;
11573 }
11574
11575 /* Replace the first operand in the 2nd instruction (which
11576 is the PC) with the destination register. We have
11577 already added in the PC in the first instruction and we
11578 do not want to do it again. */
11579 newinsn &= ~ 0xf0000;
11580 newinsn |= ((newinsn & 0x0f000) << 4);
11581 }
11582
11583 newimm |= (temp & 0xfffff000);
11584 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11585
11586 highpart |= (newinsn & 0xfffff000);
11587 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11588 }
11589 break;
11590
11591 case BFD_RELOC_ARM_OFFSET_IMM:
11592 sign = value >= 0;
11593
11594 if (value < 0)
11595 value = - value;
11596
11597 if (validate_offset_imm (value, 0) == FAIL)
11598 {
11599 as_bad_where (fixP->fx_file, fixP->fx_line,
11600 _("bad immediate value for offset (%ld)"),
11601 (long) value);
11602 break;
11603 }
11604
11605 newval = md_chars_to_number (buf, INSN_SIZE);
11606 newval &= 0xff7ff000;
11607 newval |= value | (sign ? INDEX_UP : 0);
11608 md_number_to_chars (buf, newval, INSN_SIZE);
11609 break;
11610
11611 case BFD_RELOC_ARM_OFFSET_IMM8:
11612 case BFD_RELOC_ARM_HWLITERAL:
11613 sign = value >= 0;
11614
11615 if (value < 0)
11616 value = - value;
11617
11618 if (validate_offset_imm (value, 1) == FAIL)
11619 {
11620 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11621 as_bad_where (fixP->fx_file, fixP->fx_line,
11622 _("invalid literal constant: pool needs to be closer"));
11623 else
11624 as_bad (_("bad immediate value for half-word offset (%ld)"),
11625 (long) value);
11626 break;
11627 }
11628
11629 newval = md_chars_to_number (buf, INSN_SIZE);
11630 newval &= 0xff7ff0f0;
11631 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11632 md_number_to_chars (buf, newval, INSN_SIZE);
11633 break;
11634
11635 case BFD_RELOC_ARM_LITERAL:
11636 sign = value >= 0;
11637
11638 if (value < 0)
11639 value = - value;
11640
11641 if (validate_offset_imm (value, 0) == FAIL)
11642 {
11643 as_bad_where (fixP->fx_file, fixP->fx_line,
11644 _("invalid literal constant: pool needs to be closer"));
11645 break;
11646 }
11647
11648 newval = md_chars_to_number (buf, INSN_SIZE);
11649 newval &= 0xff7ff000;
11650 newval |= value | (sign ? INDEX_UP : 0);
11651 md_number_to_chars (buf, newval, INSN_SIZE);
11652 break;
11653
11654 case BFD_RELOC_ARM_SHIFT_IMM:
11655 newval = md_chars_to_number (buf, INSN_SIZE);
11656 if (((unsigned long) value) > 32
11657 || (value == 32
11658 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11659 {
11660 as_bad_where (fixP->fx_file, fixP->fx_line,
11661 _("shift expression is too large"));
11662 break;
11663 }
11664
11665 if (value == 0)
11666 /* Shifts of zero must be done as lsl. */
11667 newval &= ~0x60;
11668 else if (value == 32)
11669 value = 0;
11670 newval &= 0xfffff07f;
11671 newval |= (value & 0x1f) << 7;
11672 md_number_to_chars (buf, newval, INSN_SIZE);
11673 break;
11674
0dd132b6
NC
11675 case BFD_RELOC_ARM_SMI:
11676 if (((unsigned long) value) > 0xffff)
11677 as_bad_where (fixP->fx_file, fixP->fx_line,
11678 _("invalid smi expression"));
11679 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11680 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11681 md_number_to_chars (buf, newval, INSN_SIZE);
11682 break;
11683
b99bd4ef
NC
11684 case BFD_RELOC_ARM_SWI:
11685 if (arm_data->thumb_mode)
11686 {
11687 if (((unsigned long) value) > 0xff)
11688 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11689 _("invalid swi expression"));
b99bd4ef
NC
11690 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11691 newval |= value;
11692 md_number_to_chars (buf, newval, THUMB_SIZE);
11693 }
11694 else
11695 {
11696 if (((unsigned long) value) > 0x00ffffff)
11697 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11698 _("invalid swi expression"));
b99bd4ef
NC
11699 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11700 newval |= value;
11701 md_number_to_chars (buf, newval, INSN_SIZE);
11702 }
11703 break;
11704
11705 case BFD_RELOC_ARM_MULTI:
11706 if (((unsigned long) value) > 0xffff)
11707 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11708 _("invalid expression in load/store multiple"));
b99bd4ef
NC
11709 newval = value | md_chars_to_number (buf, INSN_SIZE);
11710 md_number_to_chars (buf, newval, INSN_SIZE);
11711 break;
11712
11713 case BFD_RELOC_ARM_PCREL_BRANCH:
11714 newval = md_chars_to_number (buf, INSN_SIZE);
11715
11716 /* Sign-extend a 24-bit number. */
11717#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11718
11719#ifdef OBJ_ELF
7f266840 11720 value = fixP->fx_offset;
b99bd4ef
NC
11721#endif
11722
11723 /* We are going to store value (shifted right by two) in the
11724 instruction, in a 24 bit, signed field. Thus we need to check
11725 that none of the top 8 bits of the shifted value (top 7 bits of
11726 the unshifted, unsigned value) are set, or that they are all set. */
11727 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11728 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11729 {
11730#ifdef OBJ_ELF
11731 /* Normally we would be stuck at this point, since we cannot store
11732 the absolute address that is the destination of the branch in the
11733 24 bits of the branch instruction. If however, we happen to know
11734 that the destination of the branch is in the same section as the
2d2255b5 11735 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
11736 ourselves and not have to bother the linker with it.
11737
7f266840
DJ
11738 FIXME: The test for OBJ_ELF is only here because I have not
11739 worked out how to do this for OBJ_COFF. */
11740 if (fixP->fx_addsy != NULL
b99bd4ef
NC
11741 && S_IS_DEFINED (fixP->fx_addsy)
11742 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11743 {
11744 /* Get pc relative value to go into the branch. */
94f592af 11745 value = * valP;
b99bd4ef
NC
11746
11747 /* Permit a backward branch provided that enough bits
11748 are set. Allow a forwards branch, provided that
11749 enough bits are clear. */
11750 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11751 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11752 fixP->fx_done = 1;
11753 }
11754
11755 if (! fixP->fx_done)
11756#endif
11757 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11758 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
11759 }
11760
11761 value >>= 2;
11762 value += SEXT24 (newval);
11763
11764 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11765 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11766 as_bad_where (fixP->fx_file, fixP->fx_line,
11767 _("out of range branch"));
11768
11769 newval = (value & 0x00ffffff) | (newval & 0xff000000);
11770 md_number_to_chars (buf, newval, INSN_SIZE);
11771 break;
11772
11773 case BFD_RELOC_ARM_PCREL_BLX:
11774 {
11775 offsetT hbit;
11776 newval = md_chars_to_number (buf, INSN_SIZE);
11777
11778#ifdef OBJ_ELF
7f266840 11779 value = fixP->fx_offset;
b99bd4ef
NC
11780#endif
11781 hbit = (value >> 1) & 1;
11782 value = (value >> 2) & 0x00ffffff;
11783 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
11784 newval = value | (newval & 0xfe000000) | (hbit << 24);
11785 md_number_to_chars (buf, newval, INSN_SIZE);
11786 }
11787 break;
11788
11789 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11790 newval = md_chars_to_number (buf, THUMB_SIZE);
11791 {
11792 addressT diff = (newval & 0xff) << 1;
11793 if (diff & 0x100)
11794 diff |= ~0xff;
11795
11796 value += diff;
11797 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11798 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11799 _("branch out of range"));
b99bd4ef
NC
11800 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
11801 }
11802 md_number_to_chars (buf, newval, THUMB_SIZE);
11803 break;
11804
11805 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11806 newval = md_chars_to_number (buf, THUMB_SIZE);
11807 {
11808 addressT diff = (newval & 0x7ff) << 1;
11809 if (diff & 0x800)
11810 diff |= ~0x7ff;
11811
11812 value += diff;
11813 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11814 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11815 _("branch out of range"));
b99bd4ef
NC
11816 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
11817 }
11818 md_number_to_chars (buf, newval, THUMB_SIZE);
11819 break;
11820
11821 case BFD_RELOC_THUMB_PCREL_BLX:
11822 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11823 {
11824 offsetT newval2;
11825 addressT diff;
11826
11827 newval = md_chars_to_number (buf, THUMB_SIZE);
11828 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11829 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11830 if (diff & 0x400000)
11831 diff |= ~0x3fffff;
11832#ifdef OBJ_ELF
11833 value = fixP->fx_offset;
11834#endif
11835 value += diff;
c62e1cc3 11836
b99bd4ef
NC
11837 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11838 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11839 _("branch with link out of range"));
b99bd4ef
NC
11840
11841 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11842 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11843 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
11844 /* For a BLX instruction, make sure that the relocation is rounded up
11845 to a word boundary. This follows the semantics of the instruction
11846 which specifies that bit 1 of the target address will come from bit
11847 1 of the base address. */
11848 newval2 = (newval2 + 1) & ~ 1;
b99bd4ef
NC
11849 md_number_to_chars (buf, newval, THUMB_SIZE);
11850 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11851 }
11852 break;
11853
11854 case BFD_RELOC_8:
11855 if (fixP->fx_done || fixP->fx_pcrel)
11856 md_number_to_chars (buf, value, 1);
11857#ifdef OBJ_ELF
7f266840 11858 else
b99bd4ef
NC
11859 {
11860 value = fixP->fx_offset;
11861 md_number_to_chars (buf, value, 1);
11862 }
11863#endif
11864 break;
11865
11866 case BFD_RELOC_16:
11867 if (fixP->fx_done || fixP->fx_pcrel)
11868 md_number_to_chars (buf, value, 2);
11869#ifdef OBJ_ELF
7f266840 11870 else
b99bd4ef
NC
11871 {
11872 value = fixP->fx_offset;
11873 md_number_to_chars (buf, value, 2);
11874 }
11875#endif
11876 break;
11877
11878#ifdef OBJ_ELF
11879 case BFD_RELOC_ARM_GOT32:
11880 case BFD_RELOC_ARM_GOTOFF:
eb043451 11881 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
11882 md_number_to_chars (buf, 0, 4);
11883 break;
11884#endif
11885
11886 case BFD_RELOC_RVA:
11887 case BFD_RELOC_32:
9c504268 11888 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
11889 case BFD_RELOC_ARM_ROSEGREL32:
11890 case BFD_RELOC_ARM_SBREL32:
eb043451 11891 case BFD_RELOC_32_PCREL:
b99bd4ef
NC
11892 if (fixP->fx_done || fixP->fx_pcrel)
11893 md_number_to_chars (buf, value, 4);
11894#ifdef OBJ_ELF
7f266840 11895 else
b99bd4ef
NC
11896 {
11897 value = fixP->fx_offset;
11898 md_number_to_chars (buf, value, 4);
11899 }
11900#endif
11901 break;
11902
11903#ifdef OBJ_ELF
eb043451
PB
11904 case BFD_RELOC_ARM_PREL31:
11905 if (fixP->fx_done || fixP->fx_pcrel)
11906 {
11907 newval = md_chars_to_number (buf, 4) & 0x80000000;
11908 if ((value ^ (value >> 1)) & 0x40000000)
11909 {
11910 as_bad_where (fixP->fx_file, fixP->fx_line,
11911 _("rel31 relocation overflow"));
11912 }
11913 newval |= value & 0x7fffffff;
11914 md_number_to_chars (buf, newval, 4);
11915 }
11916 break;
11917
b99bd4ef
NC
11918 case BFD_RELOC_ARM_PLT32:
11919 /* It appears the instruction is fully prepared at this point. */
11920 break;
11921#endif
11922
b99bd4ef
NC
11923 case BFD_RELOC_ARM_CP_OFF_IMM:
11924 sign = value >= 0;
11925 if (value < -1023 || value > 1023 || (value & 3))
11926 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11927 _("illegal value for co-processor offset"));
b99bd4ef
NC
11928 if (value < 0)
11929 value = -value;
11930 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11931 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11932 md_number_to_chars (buf, newval, INSN_SIZE);
11933 break;
11934
e16bb312
NC
11935 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11936 sign = value >= 0;
11937 if (value < -255 || value > 255)
11938 as_bad_where (fixP->fx_file, fixP->fx_line,
11939 _("Illegal value for co-processor offset"));
11940 if (value < 0)
11941 value = -value;
11942 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11943 newval |= value | (sign ? INDEX_UP : 0);
11944 md_number_to_chars (buf, newval , INSN_SIZE);
11945 break;
11946
b99bd4ef
NC
11947 case BFD_RELOC_ARM_THUMB_OFFSET:
11948 newval = md_chars_to_number (buf, THUMB_SIZE);
11949 /* Exactly what ranges, and where the offset is inserted depends
11950 on the type of instruction, we can establish this from the
11951 top 4 bits. */
11952 switch (newval >> 12)
11953 {
11954 case 4: /* PC load. */
11955 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11956 forced to zero for these loads, so we will need to round
11957 up the offset if the instruction address is not word
11958 aligned (since the final address produced must be, and
11959 we can only describe word-aligned immediate offsets). */
11960
11961 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11962 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11963 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
11964 (unsigned int) (fixP->fx_frag->fr_address
11965 + fixP->fx_where + value));
11966
11967 if ((value + 2) & ~0x3fe)
11968 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11969 _("invalid offset, value too big (0x%08lX)"),
11970 (long) value);
b99bd4ef
NC
11971
11972 /* Round up, since pc will be rounded down. */
11973 newval |= (value + 2) >> 2;
11974 break;
11975
11976 case 9: /* SP load/store. */
11977 if (value & ~0x3fc)
11978 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11979 _("invalid offset, value too big (0x%08lX)"),
11980 (long) value);
b99bd4ef
NC
11981 newval |= value >> 2;
11982 break;
11983
11984 case 6: /* Word load/store. */
11985 if (value & ~0x7c)
11986 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11987 _("invalid offset, value too big (0x%08lX)"),
11988 (long) value);
b99bd4ef
NC
11989 newval |= value << 4; /* 6 - 2. */
11990 break;
11991
11992 case 7: /* Byte load/store. */
11993 if (value & ~0x1f)
11994 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11995 _("invalid offset, value too big (0x%08lX)"),
11996 (long) value);
b99bd4ef
NC
11997 newval |= value << 6;
11998 break;
11999
12000 case 8: /* Halfword load/store. */
12001 if (value & ~0x3e)
12002 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12003 _("invalid offset, value too big (0x%08lX)"),
12004 (long) value);
b99bd4ef
NC
12005 newval |= value << 5; /* 6 - 1. */
12006 break;
12007
12008 default:
12009 as_bad_where (fixP->fx_file, fixP->fx_line,
12010 "Unable to process relocation for thumb opcode: %lx",
12011 (unsigned long) newval);
12012 break;
12013 }
12014 md_number_to_chars (buf, newval, THUMB_SIZE);
12015 break;
12016
12017 case BFD_RELOC_ARM_THUMB_ADD:
12018 /* This is a complicated relocation, since we use it for all of
12019 the following immediate relocations:
12020
12021 3bit ADD/SUB
12022 8bit ADD/SUB
12023 9bit ADD/SUB SP word-aligned
12024 10bit ADD PC/SP word-aligned
12025
12026 The type of instruction being processed is encoded in the
12027 instruction field:
12028
12029 0x8000 SUB
12030 0x00F0 Rd
12031 0x000F Rs
12032 */
12033 newval = md_chars_to_number (buf, THUMB_SIZE);
12034 {
12035 int rd = (newval >> 4) & 0xf;
12036 int rs = newval & 0xf;
12037 int subtract = newval & 0x8000;
12038
12039 if (rd == REG_SP)
12040 {
12041 if (value & ~0x1fc)
12042 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12043 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12044 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12045 newval |= value >> 2;
12046 }
12047 else if (rs == REG_PC || rs == REG_SP)
12048 {
12049 if (subtract ||
12050 value & ~0x3fc)
12051 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12052 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12053 (unsigned long) value);
12054 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12055 newval |= rd << 8;
12056 newval |= value >> 2;
12057 }
12058 else if (rs == rd)
12059 {
12060 if (value & ~0xff)
12061 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12062 _("invalid 8bit immediate"));
b99bd4ef
NC
12063 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12064 newval |= (rd << 8) | value;
12065 }
12066 else
12067 {
12068 if (value & ~0x7)
12069 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12070 _("invalid 3bit immediate"));
b99bd4ef
NC
12071 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12072 newval |= rd | (rs << 3) | (value << 6);
12073 }
12074 }
12075 md_number_to_chars (buf, newval, THUMB_SIZE);
12076 break;
12077
12078 case BFD_RELOC_ARM_THUMB_IMM:
12079 newval = md_chars_to_number (buf, THUMB_SIZE);
12080 switch (newval >> 11)
12081 {
12082 case 0x04: /* 8bit immediate MOV. */
12083 case 0x05: /* 8bit immediate CMP. */
12084 if (value < 0 || value > 255)
12085 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12086 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12087 (long) value);
12088 newval |= value;
12089 break;
12090
12091 default:
12092 abort ();
12093 }
12094 md_number_to_chars (buf, newval, THUMB_SIZE);
12095 break;
12096
12097 case BFD_RELOC_ARM_THUMB_SHIFT:
12098 /* 5bit shift value (0..31). */
12099 if (value < 0 || value > 31)
12100 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12101 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12102 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12103 newval |= value << 6;
12104 md_number_to_chars (buf, newval, THUMB_SIZE);
12105 break;
12106
12107 case BFD_RELOC_VTABLE_INHERIT:
12108 case BFD_RELOC_VTABLE_ENTRY:
12109 fixP->fx_done = 0;
94f592af 12110 return;
b99bd4ef
NC
12111
12112 case BFD_RELOC_NONE:
12113 default:
12114 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12115 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12116 }
b99bd4ef
NC
12117}
12118
12119/* Translate internal representation of relocation info to BFD target
12120 format. */
12121
12122arelent *
a737bd4d
NC
12123tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12124 fixS * fixp)
b99bd4ef
NC
12125{
12126 arelent * reloc;
12127 bfd_reloc_code_real_type code;
12128
a737bd4d 12129 reloc = xmalloc (sizeof (arelent));
b99bd4ef 12130
a737bd4d 12131 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
b99bd4ef
NC
12132 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12133 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12134
12135 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12136#ifndef OBJ_ELF
12137 if (fixp->fx_pcrel == 0)
12138 reloc->addend = fixp->fx_offset;
12139 else
12140 reloc->addend = fixp->fx_offset = reloc->address;
12141#else /* OBJ_ELF */
12142 reloc->addend = fixp->fx_offset;
12143#endif
12144
12145 switch (fixp->fx_r_type)
12146 {
12147 case BFD_RELOC_8:
12148 if (fixp->fx_pcrel)
12149 {
12150 code = BFD_RELOC_8_PCREL;
12151 break;
12152 }
12153
12154 case BFD_RELOC_16:
12155 if (fixp->fx_pcrel)
12156 {
12157 code = BFD_RELOC_16_PCREL;
12158 break;
12159 }
12160
12161 case BFD_RELOC_32:
12162 if (fixp->fx_pcrel)
12163 {
12164 code = BFD_RELOC_32_PCREL;
12165 break;
12166 }
12167
12168 case BFD_RELOC_ARM_PCREL_BRANCH:
12169 case BFD_RELOC_ARM_PCREL_BLX:
12170 case BFD_RELOC_RVA:
12171 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12172 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12173 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12174 case BFD_RELOC_THUMB_PCREL_BLX:
12175 case BFD_RELOC_VTABLE_ENTRY:
12176 case BFD_RELOC_VTABLE_INHERIT:
12177 code = fixp->fx_r_type;
12178 break;
12179
12180 case BFD_RELOC_ARM_LITERAL:
12181 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12182 /* If this is called then the a literal has
12183 been referenced across a section boundary. */
b99bd4ef 12184 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12185 _("literal referenced across section boundary"));
b99bd4ef
NC
12186 return NULL;
12187
12188#ifdef OBJ_ELF
12189 case BFD_RELOC_ARM_GOT32:
12190 case BFD_RELOC_ARM_GOTOFF:
12191 case BFD_RELOC_ARM_PLT32:
9c504268 12192 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12193 case BFD_RELOC_ARM_ROSEGREL32:
12194 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12195 case BFD_RELOC_ARM_PREL31:
12196 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12197 code = fixp->fx_r_type;
12198 break;
12199#endif
12200
12201 case BFD_RELOC_ARM_IMMEDIATE:
12202 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12203 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12204 return NULL;
12205
12206 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12207 as_bad_where (fixp->fx_file, fixp->fx_line,
12208 _("ADRL used for a symbol not defined in the same file"));
12209 return NULL;
12210
12211 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12212 if (fixp->fx_addsy != NULL
12213 && !S_IS_DEFINED (fixp->fx_addsy)
12214 && S_IS_LOCAL (fixp->fx_addsy))
12215 {
12216 as_bad_where (fixp->fx_file, fixp->fx_line,
12217 _("undefined local label `%s'"),
12218 S_GET_NAME (fixp->fx_addsy));
12219 return NULL;
12220 }
12221
b99bd4ef 12222 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12223 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12224 return NULL;
12225
12226 default:
12227 {
12228 char * type;
12229
12230 switch (fixp->fx_r_type)
12231 {
b99bd4ef
NC
12232 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12233 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
0dd132b6 12234 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
b99bd4ef
NC
12235 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12236 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12237 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12238 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12239 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12240 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12241 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12242 default: type = _("<unknown>"); break;
12243 }
12244 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12245 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12246 type);
12247 return NULL;
12248 }
12249 }
12250
12251#ifdef OBJ_ELF
8df7094c 12252 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12253 && GOT_symbol
12254 && fixp->fx_addsy == GOT_symbol)
12255 {
12256 code = BFD_RELOC_ARM_GOTPC;
12257 reloc->addend = fixp->fx_offset = reloc->address;
12258 }
12259#endif
12260
12261 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12262
12263 if (reloc->howto == NULL)
12264 {
12265 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12266 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12267 bfd_get_reloc_code_name (code));
12268 return NULL;
12269 }
12270
12271 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12272 vtable entry to be used in the relocation's section offset. */
12273 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12274 reloc->address = fixp->fx_offset;
12275
12276 return reloc;
12277}
12278
12279int
a737bd4d
NC
12280md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12281 segT segtype ATTRIBUTE_UNUSED)
b99bd4ef
NC
12282{
12283 as_fatal (_("md_estimate_size_before_relax\n"));
12284 return 1;
12285}
12286
a737bd4d
NC
12287/* We need to be able to fix up arbitrary expressions in some statements.
12288 This is so that we can handle symbols that are an arbitrary distance from
12289 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12290 which returns part of an address in a form which will be valid for
12291 a data instruction. We do this by pushing the expression into a symbol
12292 in the expr_section, and creating a fix for that. */
12293
12294static void
12295fix_new_arm (fragS * frag,
12296 int where,
12297 short int size,
12298 expressionS * exp,
12299 int pc_rel,
12300 int reloc)
12301{
12302 fixS * new_fix;
12303 arm_fix_data * arm_data;
12304
12305 switch (exp->X_op)
12306 {
12307 case O_constant:
12308 case O_symbol:
12309 case O_add:
12310 case O_subtract:
12311 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12312 break;
12313
12314 default:
12315 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12316 pc_rel, reloc);
12317 break;
12318 }
12319
12320 /* Mark whether the fix is to a THUMB instruction, or an ARM
12321 instruction. */
12322 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12323 new_fix->tc_fix_data = (PTR) arm_data;
12324 arm_data->thumb_mode = thumb_mode;
12325}
12326
b99bd4ef 12327static void
a737bd4d 12328output_inst (const char * str)
b99bd4ef
NC
12329{
12330 char * to = NULL;
12331
12332 if (inst.error)
12333 {
f03698e6 12334 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12335 return;
12336 }
12337
12338 to = frag_more (inst.size);
12339
12340 if (thumb_mode && (inst.size > THUMB_SIZE))
12341 {
12342 assert (inst.size == (2 * THUMB_SIZE));
12343 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12344 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12345 }
12346 else if (inst.size > INSN_SIZE)
12347 {
12348 assert (inst.size == (2 * INSN_SIZE));
12349 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12350 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12351 }
12352 else
12353 md_number_to_chars (to, inst.instruction, inst.size);
12354
12355 if (inst.reloc.type != BFD_RELOC_NONE)
12356 fix_new_arm (frag_now, to - frag_now->fr_literal,
12357 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12358 inst.reloc.type);
12359
12360#ifdef OBJ_ELF
12361 dwarf2_emit_insn (inst.size);
12362#endif
12363}
12364
12365void
a737bd4d 12366md_assemble (char * str)
b99bd4ef 12367{
6c43fab6
RE
12368 char c;
12369 char *p;
12370 char *start;
b99bd4ef
NC
12371
12372 /* Align the instruction.
12373 This may not be the right thing to do but ... */
12374#if 0
12375 arm_align (2, 0);
12376#endif
b99bd4ef
NC
12377
12378 /* Align the previous label if needed. */
12379 if (last_label_seen != NULL)
12380 {
12381 symbol_set_frag (last_label_seen, frag_now);
12382 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12383 S_SET_SEGMENT (last_label_seen, now_seg);
12384 }
12385
12386 memset (&inst, '\0', sizeof (inst));
12387 inst.reloc.type = BFD_RELOC_NONE;
12388
12389 skip_whitespace (str);
12390
12391 /* Scan up to the end of the op-code, which must end in white space or
12392 end of string. */
12393 for (start = p = str; *p != '\0'; p++)
12394 if (*p == ' ')
12395 break;
12396
12397 if (p == str)
12398 {
f03698e6 12399 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12400 return;
12401 }
12402
12403 if (thumb_mode)
12404 {
05d2d07e 12405 const struct thumb_opcode * opcode;
b99bd4ef
NC
12406
12407 c = *p;
12408 *p = '\0';
05d2d07e 12409 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12410 *p = c;
12411
12412 if (opcode)
12413 {
12414 /* Check that this instruction is supported for this CPU. */
90e4755a 12415 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12416 {
f03698e6 12417 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12418 return;
12419 }
12420
6057a28f 12421 mapping_state (MAP_THUMB);
b99bd4ef
NC
12422 inst.instruction = opcode->value;
12423 inst.size = opcode->size;
a737bd4d 12424 opcode->parms (p);
f03698e6 12425 output_inst (str);
b99bd4ef
NC
12426 return;
12427 }
12428 }
12429 else
12430 {
05d2d07e 12431 const struct asm_opcode * opcode;
b99bd4ef 12432
90e4755a
RE
12433 c = *p;
12434 *p = '\0';
6c43fab6 12435 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12436 *p = c;
b99bd4ef 12437
90e4755a 12438 if (opcode)
b99bd4ef 12439 {
90e4755a
RE
12440 /* Check that this instruction is supported for this CPU. */
12441 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12442 {
f03698e6 12443 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12444 return;
12445 }
12446
6057a28f 12447 mapping_state (MAP_ARM);
90e4755a
RE
12448 inst.instruction = opcode->value;
12449 inst.size = INSN_SIZE;
a737bd4d 12450 opcode->parms (p);
f03698e6 12451 output_inst (str);
90e4755a 12452 return;
b99bd4ef
NC
12453 }
12454 }
12455
12456 /* It wasn't an instruction, but it might be a register alias of the form
12457 alias .req reg. */
6c43fab6
RE
12458 if (create_register_alias (str, p))
12459 return;
b99bd4ef 12460
b99bd4ef
NC
12461 as_bad (_("bad instruction `%s'"), start);
12462}
12463
12464/* md_parse_option
12465 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12466 See if it's a processor-specific option.
03b1477f
RE
12467
12468 This routine is somewhat complicated by the need for backwards
12469 compatibility (since older releases of gcc can't be changed).
12470 The new options try to make the interface as compatible as
12471 possible with GCC.
12472
12473 New options (supported) are:
12474
12475 -mcpu=<cpu name> Assemble for selected processor
12476 -march=<architecture name> Assemble for selected architecture
12477 -mfpu=<fpu architecture> Assemble for selected FPU.
12478 -EB/-mbig-endian Big-endian
12479 -EL/-mlittle-endian Little-endian
12480 -k Generate PIC code
12481 -mthumb Start in Thumb mode
12482 -mthumb-interwork Code supports ARM/Thumb interworking
12483
3d0c9500 12484 For now we will also provide support for:
03b1477f
RE
12485
12486 -mapcs-32 32-bit Program counter
12487 -mapcs-26 26-bit Program counter
12488 -macps-float Floats passed in FP registers
12489 -mapcs-reentrant Reentrant code
12490 -matpcs
12491 (sometime these will probably be replaced with -mapcs=<list of options>
12492 and -matpcs=<list of options>)
12493
12494 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
12495 Cpu variants, the arm part is optional:
12496 -m[arm]1 Currently not supported.
12497 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12498 -m[arm]3 Arm 3 processor
12499 -m[arm]6[xx], Arm 6 processors
12500 -m[arm]7[xx][t][[d]m] Arm 7 processors
12501 -m[arm]8[10] Arm 8 processors
12502 -m[arm]9[20][tdmi] Arm 9 processors
12503 -mstrongarm[110[0]] StrongARM processors
12504 -mxscale XScale processors
12505 -m[arm]v[2345[t[e]]] Arm architectures
12506 -mall All (except the ARM1)
12507 FP variants:
12508 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12509 -mfpe-old (No float load/store multiples)
bfae80f2
RE
12510 -mvfpxd VFP Single precision
12511 -mvfp All VFP
b99bd4ef 12512 -mno-fpu Disable all floating point instructions
b99bd4ef 12513
03b1477f
RE
12514 The following CPU names are recognized:
12515 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12516 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12517 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12518 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12519 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12520 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12521 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12522
12523 */
12524
5a38dc70 12525const char * md_shortopts = "m:k";
03b1477f 12526
b99bd4ef
NC
12527#ifdef ARM_BI_ENDIAN
12528#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 12529#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12530#else
21f0f23a
RE
12531#if TARGET_BYTES_BIG_ENDIAN
12532#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
12533#else
12534#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12535#endif
ce058b6c 12536#endif
03b1477f
RE
12537
12538struct option md_longopts[] =
12539{
12540#ifdef OPTION_EB
12541 {"EB", no_argument, NULL, OPTION_EB},
12542#endif
12543#ifdef OPTION_EL
12544 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
12545#endif
12546 {NULL, no_argument, NULL, 0}
12547};
12548
12549size_t md_longopts_size = sizeof (md_longopts);
12550
03b1477f 12551struct arm_option_table
b99bd4ef 12552{
03b1477f
RE
12553 char *option; /* Option name to match. */
12554 char *help; /* Help information. */
12555 int *var; /* Variable to change. */
12556 int value; /* What to change it to. */
12557 char *deprecated; /* If non-null, print this message. */
12558};
b99bd4ef 12559
cc8a6dd0 12560struct arm_option_table arm_opts[] =
03b1477f
RE
12561{
12562 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12563 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12564 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12565 &support_interwork, 1, NULL},
03b1477f
RE
12566 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12567 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12568 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12569 1, NULL},
12570 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12571 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12572 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12573 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12574 NULL},
12575
12576 /* These are recognized by the assembler, but have no affect on code. */
12577 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12578 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12579
12580 /* DON'T add any new processors to this list -- we want the whole list
12581 to go away... Add them to the processors table instead. */
12582 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12583 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12584 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12585 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12586 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12587 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12588 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12589 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12590 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12591 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12592 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12593 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12594 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12595 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12596 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12597 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12598 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12599 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12600 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12601 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12602 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12603 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12604 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12605 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12606 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12607 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12608 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12609 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12610 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12611 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12612 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12613 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12614 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12615 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12616 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12617 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12618 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12619 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12620 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12621 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12622 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12623 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12624 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12625 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12626 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12627 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12628 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12629 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12630 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12631 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12632 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12633 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12634 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12635 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12636 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12637 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12638 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12639 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12640 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12641 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12642 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12643 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12644 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12645 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12646 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12647 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12648 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12649 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12650 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12651 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12652 N_("use -mcpu=strongarm110")},
12653 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12654 N_("use -mcpu=strongarm1100")},
12655 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12656 N_("use -mcpu=strongarm1110")},
12657 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 12658 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
12659 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12660
12661 /* Architecture variants -- don't add any more to this list either. */
12662 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12663 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12664 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12665 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12666 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12667 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12668 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12669 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12670 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12671 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12672 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12673 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12674 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12675 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12676 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12677 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12678 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12679 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12680
12681 /* Floating point variants -- don't add any more to this list either. */
12682 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12683 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12684 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12685 {"mno-fpu", NULL, &legacy_fpu, 0,
12686 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12687
12688 {NULL, NULL, NULL, 0, NULL}
12689};
21f0f23a 12690
03b1477f
RE
12691struct arm_cpu_option_table
12692{
12693 char *name;
12694 int value;
12695 /* For some CPUs we assume an FPU unless the user explicitly sets
12696 -mfpu=... */
12697 int default_fpu;
12698};
12699
12700/* This list should, at a minimum, contain all the cpu names
12701 recognized by GCC. */
12702static struct arm_cpu_option_table arm_cpus[] =
12703{
12704 {"all", ARM_ANY, FPU_ARCH_FPA},
12705 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12706 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12707 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12708 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12709 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12710 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12711 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12712 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12713 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12714 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12715 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12716 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12717 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12718 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12719 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12720 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12721 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12722 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12723 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12724 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12725 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12726 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12727 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12728 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12729 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12730 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12731 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12732 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12733 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 12734 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
12735 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12736 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12737 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12738 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12739 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12740 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12741 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12742 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12743 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12744 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12745 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12746 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12747 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12748 /* For V5 or later processors we default to using VFP; but the user
12749 should really set the FPU type explicitly. */
12750 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12751 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 12752 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 12753 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 12754 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
12755 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12756 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12757 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12758 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12759 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12760 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12761 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12762 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12763 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
7de9afa2 12764 {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
8783612f 12765 {"arm1026ej-s", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
09d92015 12766 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 12767 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 12768 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 12769 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
0dd132b6
NC
12770 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12771 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12772 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12773 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
03b1477f
RE
12774 /* ??? XSCALE is really an architecture. */
12775 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 12776 /* ??? iwmmxt is not a processor. */
e16bb312 12777 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
12778 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12779 /* Maverick */
33a392fb 12780 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
12781 {NULL, 0, 0}
12782};
cc8a6dd0 12783
03b1477f
RE
12784struct arm_arch_option_table
12785{
12786 char *name;
12787 int value;
12788 int default_fpu;
12789};
12790
12791/* This list should, at a minimum, contain all the architecture names
12792 recognized by GCC. */
12793static struct arm_arch_option_table arm_archs[] =
12794{
12795 {"all", ARM_ANY, FPU_ARCH_FPA},
12796 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12797 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12798 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12799 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12800 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12801 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12802 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12803 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12804 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12805 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12806 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12807 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12808 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12809 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12810 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 12811 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 12812 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 12813 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
0dd132b6
NC
12814 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12815 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12816 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
03b1477f 12817 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 12818 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
12819 {NULL, 0, 0}
12820};
12821
12822/* ISA extensions in the co-processor space. */
12823struct arm_arch_extension_table
12824{
12825 char *name;
12826 int value;
12827};
12828
12829static struct arm_arch_extension_table arm_extensions[] =
12830{
12831 {"maverick", ARM_CEXT_MAVERICK},
12832 {"xscale", ARM_CEXT_XSCALE},
e16bb312 12833 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
12834 {NULL, 0}
12835};
b99bd4ef 12836
03b1477f
RE
12837struct arm_fpu_option_table
12838{
12839 char *name;
12840 int value;
12841};
12842
12843/* This list should, at a minimum, contain all the fpu names
12844 recognized by GCC. */
12845static struct arm_fpu_option_table arm_fpus[] =
12846{
12847 {"softfpa", FPU_NONE},
12848 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
12849 {"fpe2", FPU_ARCH_FPE},
12850 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
12851 {"fpa", FPU_ARCH_FPA},
12852 {"fpa10", FPU_ARCH_FPA},
12853 {"fpa11", FPU_ARCH_FPA},
12854 {"arm7500fe", FPU_ARCH_FPA},
12855 {"softvfp", FPU_ARCH_VFP},
12856 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12857 {"vfp", FPU_ARCH_VFP_V2},
12858 {"vfp9", FPU_ARCH_VFP_V2},
12859 {"vfp10", FPU_ARCH_VFP_V2},
12860 {"vfp10-r0", FPU_ARCH_VFP_V1},
12861 {"vfpxd", FPU_ARCH_VFP_V1xD},
12862 {"arm1020t", FPU_ARCH_VFP_V1},
12863 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 12864 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 12865 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
12866 {"maverick", FPU_ARCH_MAVERICK},
12867 {NULL, 0}
12868};
12869
12870struct arm_float_abi_option_table
12871{
12872 char *name;
12873 int value;
12874};
12875
12876static struct arm_float_abi_option_table arm_float_abis[] =
12877{
12878 {"hard", ARM_FLOAT_ABI_HARD},
12879 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12880 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
12881 {NULL, 0}
12882};
12883
d507cf36
PB
12884struct arm_eabi_option_table
12885{
12886 char *name;
12887 unsigned int value;
12888};
12889
7cc69913 12890#ifdef OBJ_ELF
8cb51566 12891/* We only know how to output GNU and ver 4 (AAELF) formats. */
d507cf36
PB
12892static struct arm_eabi_option_table arm_eabis[] =
12893{
12894 {"gnu", EF_ARM_EABI_UNKNOWN},
8cb51566 12895 {"4", EF_ARM_EABI_VER4},
d507cf36
PB
12896 {NULL, 0}
12897};
7cc69913 12898#endif
d507cf36 12899
03b1477f
RE
12900struct arm_long_option_table
12901{
a737bd4d
NC
12902 char * option; /* Substring to match. */
12903 char * help; /* Help information. */
12904 int (* func) (char * subopt); /* Function to decode sub-option. */
12905 char * deprecated; /* If non-null, print this message. */
03b1477f
RE
12906};
12907
12908static int
a737bd4d 12909arm_parse_extension (char * str, int * opt_p)
03b1477f
RE
12910{
12911 while (str != NULL && *str != 0)
12912 {
a737bd4d
NC
12913 struct arm_arch_extension_table * opt;
12914 char * ext;
03b1477f
RE
12915 int optlen;
12916
12917 if (*str != '+')
b99bd4ef 12918 {
03b1477f
RE
12919 as_bad (_("invalid architectural extension"));
12920 return 0;
12921 }
b99bd4ef 12922
03b1477f
RE
12923 str++;
12924 ext = strchr (str, '+');
b99bd4ef 12925
03b1477f
RE
12926 if (ext != NULL)
12927 optlen = ext - str;
12928 else
12929 optlen = strlen (str);
b99bd4ef 12930
03b1477f
RE
12931 if (optlen == 0)
12932 {
12933 as_bad (_("missing architectural extension"));
12934 return 0;
12935 }
b99bd4ef 12936
03b1477f
RE
12937 for (opt = arm_extensions; opt->name != NULL; opt++)
12938 if (strncmp (opt->name, str, optlen) == 0)
12939 {
12940 *opt_p |= opt->value;
12941 break;
12942 }
bfae80f2 12943
03b1477f
RE
12944 if (opt->name == NULL)
12945 {
12946 as_bad (_("unknown architectural extnsion `%s'"), str);
12947 return 0;
12948 }
b99bd4ef 12949
03b1477f
RE
12950 str = ext;
12951 };
b99bd4ef 12952
03b1477f
RE
12953 return 1;
12954}
b99bd4ef 12955
03b1477f 12956static int
a737bd4d 12957arm_parse_cpu (char * str)
03b1477f 12958{
a737bd4d
NC
12959 struct arm_cpu_option_table * opt;
12960 char * ext = strchr (str, '+');
03b1477f 12961 int optlen;
b99bd4ef 12962
03b1477f
RE
12963 if (ext != NULL)
12964 optlen = ext - str;
12965 else
12966 optlen = strlen (str);
b99bd4ef 12967
03b1477f
RE
12968 if (optlen == 0)
12969 {
12970 as_bad (_("missing cpu name `%s'"), str);
12971 return 0;
12972 }
b99bd4ef 12973
03b1477f
RE
12974 for (opt = arm_cpus; opt->name != NULL; opt++)
12975 if (strncmp (opt->name, str, optlen) == 0)
12976 {
12977 mcpu_cpu_opt = opt->value;
12978 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 12979
03b1477f
RE
12980 if (ext != NULL)
12981 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 12982
03b1477f
RE
12983 return 1;
12984 }
b99bd4ef 12985
03b1477f
RE
12986 as_bad (_("unknown cpu `%s'"), str);
12987 return 0;
12988}
b99bd4ef 12989
03b1477f 12990static int
a737bd4d 12991arm_parse_arch (char * str)
03b1477f
RE
12992{
12993 struct arm_arch_option_table *opt;
12994 char *ext = strchr (str, '+');
12995 int optlen;
b99bd4ef 12996
03b1477f
RE
12997 if (ext != NULL)
12998 optlen = ext - str;
12999 else
13000 optlen = strlen (str);
b99bd4ef 13001
03b1477f
RE
13002 if (optlen == 0)
13003 {
13004 as_bad (_("missing architecture name `%s'"), str);
13005 return 0;
13006 }
b99bd4ef 13007
b99bd4ef 13008
03b1477f 13009 for (opt = arm_archs; opt->name != NULL; opt++)
a737bd4d 13010 if (streq (opt->name, str))
03b1477f
RE
13011 {
13012 march_cpu_opt = opt->value;
13013 march_fpu_opt = opt->default_fpu;
b99bd4ef 13014
03b1477f
RE
13015 if (ext != NULL)
13016 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13017
03b1477f
RE
13018 return 1;
13019 }
b99bd4ef 13020
03b1477f
RE
13021 as_bad (_("unknown architecture `%s'\n"), str);
13022 return 0;
13023}
13024
13025static int
a737bd4d 13026arm_parse_fpu (char * str)
03b1477f 13027{
a737bd4d 13028 struct arm_fpu_option_table * opt;
b99bd4ef 13029
03b1477f 13030 for (opt = arm_fpus; opt->name != NULL; opt++)
a737bd4d 13031 if (streq (opt->name, str))
03b1477f
RE
13032 {
13033 mfpu_opt = opt->value;
13034 return 1;
13035 }
b99bd4ef 13036
03b1477f
RE
13037 as_bad (_("unknown floating point format `%s'\n"), str);
13038 return 0;
13039}
b99bd4ef 13040
33a392fb 13041static int
a737bd4d 13042arm_parse_float_abi (char * str)
33a392fb 13043{
a737bd4d 13044 struct arm_float_abi_option_table * opt;
33a392fb
PB
13045
13046 for (opt = arm_float_abis; opt->name != NULL; opt++)
a737bd4d 13047 if (streq (opt->name, str))
33a392fb
PB
13048 {
13049 mfloat_abi_opt = opt->value;
13050 return 1;
13051 }
13052
13053 as_bad (_("unknown floating point abi `%s'\n"), str);
13054 return 0;
13055}
13056
7cc69913 13057#ifdef OBJ_ELF
d507cf36 13058static int
a737bd4d 13059arm_parse_eabi (char * str)
d507cf36
PB
13060{
13061 struct arm_eabi_option_table *opt;
13062
13063 for (opt = arm_eabis; opt->name != NULL; opt++)
a737bd4d 13064 if (streq (opt->name, str))
d507cf36
PB
13065 {
13066 meabi_flags = opt->value;
13067 return 1;
13068 }
13069 as_bad (_("unknown EABI `%s'\n"), str);
13070 return 0;
13071}
7cc69913 13072#endif
d507cf36 13073
03b1477f
RE
13074struct arm_long_option_table arm_long_opts[] =
13075{
13076 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13077 arm_parse_cpu, NULL},
13078 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13079 arm_parse_arch, NULL},
13080 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13081 arm_parse_fpu, NULL},
33a392fb
PB
13082 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13083 arm_parse_float_abi, NULL},
7cc69913 13084#ifdef OBJ_ELF
d507cf36
PB
13085 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13086 arm_parse_eabi, NULL},
7cc69913 13087#endif
03b1477f
RE
13088 {NULL, NULL, 0, NULL}
13089};
b99bd4ef 13090
03b1477f 13091int
a737bd4d 13092md_parse_option (int c, char * arg)
03b1477f
RE
13093{
13094 struct arm_option_table *opt;
13095 struct arm_long_option_table *lopt;
b99bd4ef 13096
03b1477f
RE
13097 switch (c)
13098 {
13099#ifdef OPTION_EB
13100 case OPTION_EB:
13101 target_big_endian = 1;
b99bd4ef 13102 break;
03b1477f 13103#endif
b99bd4ef 13104
03b1477f
RE
13105#ifdef OPTION_EL
13106 case OPTION_EL:
13107 target_big_endian = 0;
b99bd4ef
NC
13108 break;
13109#endif
13110
03b1477f 13111 case 'a':
cc8a6dd0 13112 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13113 ones. */
13114 return 0;
13115
b99bd4ef 13116 default:
03b1477f
RE
13117 for (opt = arm_opts; opt->option != NULL; opt++)
13118 {
13119 if (c == opt->option[0]
13120 && ((arg == NULL && opt->option[1] == 0)
a737bd4d 13121 || streq (arg, opt->option + 1)))
03b1477f
RE
13122 {
13123#if WARN_DEPRECATED
13124 /* If the option is deprecated, tell the user. */
13125 if (opt->deprecated != NULL)
13126 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13127 arg ? arg : "", _(opt->deprecated));
13128#endif
13129
13130 if (opt->var != NULL)
13131 *opt->var = opt->value;
13132
13133 return 1;
13134 }
13135 }
13136
13137 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13138 {
cc8a6dd0 13139 /* These options are expected to have an argument. */
03b1477f
RE
13140 if (c == lopt->option[0]
13141 && arg != NULL
cc8a6dd0 13142 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13143 strlen (lopt->option + 1)) == 0)
13144 {
13145#if WARN_DEPRECATED
13146 /* If the option is deprecated, tell the user. */
13147 if (lopt->deprecated != NULL)
13148 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13149 _(lopt->deprecated));
13150#endif
13151
13152 /* Call the sup-option parser. */
a737bd4d 13153 return lopt->func (arg + strlen (lopt->option) - 1);
03b1477f
RE
13154 }
13155 }
13156
b99bd4ef
NC
13157 return 0;
13158 }
13159
13160 return 1;
13161}
13162
13163void
a737bd4d 13164md_show_usage (FILE * fp)
b99bd4ef 13165{
03b1477f
RE
13166 struct arm_option_table *opt;
13167 struct arm_long_option_table *lopt;
13168
13169 fprintf (fp, _(" ARM-specific assembler options:\n"));
13170
13171 for (opt = arm_opts; opt->option != NULL; opt++)
13172 if (opt->help != NULL)
13173 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13174
13175 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13176 if (lopt->help != NULL)
13177 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13178
13179#ifdef OPTION_EB
b99bd4ef 13180 fprintf (fp, _("\
03b1477f 13181 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13182#endif
03b1477f
RE
13183
13184#ifdef OPTION_EL
b99bd4ef 13185 fprintf (fp, _("\
03b1477f 13186 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13187#endif
13188}
13189
b99bd4ef
NC
13190/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13191
13192void
a737bd4d
NC
13193cons_fix_new_arm (fragS * frag,
13194 int where,
13195 int size,
13196 expressionS * exp)
b99bd4ef
NC
13197{
13198 bfd_reloc_code_real_type type;
13199 int pcrel = 0;
13200
13201 /* Pick a reloc.
13202 FIXME: @@ Should look at CPU word size. */
13203 switch (size)
13204 {
13205 case 1:
13206 type = BFD_RELOC_8;
13207 break;
13208 case 2:
13209 type = BFD_RELOC_16;
13210 break;
13211 case 4:
13212 default:
13213 type = BFD_RELOC_32;
13214 break;
13215 case 8:
13216 type = BFD_RELOC_64;
13217 break;
13218 }
13219
13220 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13221}
13222
13223/* A good place to do this, although this was probably not intended
13224 for this kind of use. We need to dump the literal pool before
13225 references are made to a null symbol pointer. */
13226
13227void
a737bd4d 13228arm_cleanup (void)
b99bd4ef 13229{
3d0c9500 13230 literal_pool * pool;
b99bd4ef 13231
3d0c9500
NC
13232 for (pool = list_of_pools; pool; pool = pool->next)
13233 {
13234 /* Put it at the end of the relevent section. */
13235 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13236#ifdef OBJ_ELF
13237 arm_elf_change_section ();
13238#endif
3d0c9500
NC
13239 s_ltorg (0);
13240 }
b99bd4ef
NC
13241}
13242
13243void
a737bd4d 13244arm_start_line_hook (void)
b99bd4ef
NC
13245{
13246 last_label_seen = NULL;
13247}
13248
13249void
a737bd4d 13250arm_frob_label (symbolS * sym)
b99bd4ef
NC
13251{
13252 last_label_seen = sym;
13253
13254 ARM_SET_THUMB (sym, thumb_mode);
13255
13256#if defined OBJ_COFF || defined OBJ_ELF
13257 ARM_SET_INTERWORK (sym, support_interwork);
13258#endif
13259
13260 /* Note - do not allow local symbols (.Lxxx) to be labeled
13261 as Thumb functions. This is because these labels, whilst
13262 they exist inside Thumb code, are not the entry points for
13263 possible ARM->Thumb calls. Also, these labels can be used
13264 as part of a computed goto or switch statement. eg gcc
13265 can generate code that looks like this:
13266
13267 ldr r2, [pc, .Laaa]
13268 lsl r3, r3, #2
13269 ldr r2, [r3, r2]
13270 mov pc, r2
cc8a6dd0 13271
b99bd4ef
NC
13272 .Lbbb: .word .Lxxx
13273 .Lccc: .word .Lyyy
13274 ..etc...
13275 .Laaa: .word Lbbb
13276
13277 The first instruction loads the address of the jump table.
13278 The second instruction converts a table index into a byte offset.
13279 The third instruction gets the jump address out of the table.
13280 The fourth instruction performs the jump.
cc8a6dd0 13281
b99bd4ef
NC
13282 If the address stored at .Laaa is that of a symbol which has the
13283 Thumb_Func bit set, then the linker will arrange for this address
13284 to have the bottom bit set, which in turn would mean that the
13285 address computation performed by the third instruction would end
13286 up with the bottom bit set. Since the ARM is capable of unaligned
13287 word loads, the instruction would then load the incorrect address
13288 out of the jump table, and chaos would ensue. */
13289 if (label_is_thumb_function_name
13290 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13291 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13292 {
13293 /* When the address of a Thumb function is taken the bottom
13294 bit of that address should be set. This will allow
13295 interworking between Arm and Thumb functions to work
13296 correctly. */
13297
13298 THUMB_SET_FUNC (sym, 1);
13299
b34976b6 13300 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13301 }
13302}
13303
13304/* Adjust the symbol table. This marks Thumb symbols as distinct from
13305 ARM ones. */
13306
13307void
a737bd4d 13308arm_adjust_symtab (void)
b99bd4ef
NC
13309{
13310#ifdef OBJ_COFF
13311 symbolS * sym;
13312
13313 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13314 {
13315 if (ARM_IS_THUMB (sym))
13316 {
13317 if (THUMB_IS_FUNC (sym))
13318 {
13319 /* Mark the symbol as a Thumb function. */
13320 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13321 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13322 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13323
13324 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13325 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13326 else
13327 as_bad (_("%s: unexpected function type: %d"),
13328 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13329 }
cc8a6dd0 13330 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13331 {
13332 case C_EXT:
13333 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13334 break;
13335 case C_STAT:
13336 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13337 break;
13338 case C_LABEL:
13339 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13340 break;
13341 default:
13342 /* Do nothing. */
13343 break;
13344 }
13345 }
13346
13347 if (ARM_IS_INTERWORK (sym))
13348 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13349 }
13350#endif
13351#ifdef OBJ_ELF
13352 symbolS * sym;
13353 char bind;
13354
13355 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13356 {
13357 if (ARM_IS_THUMB (sym))
13358 {
13359 elf_symbol_type * elf_sym;
13360
13361 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13362 bind = ELF_ST_BIND (elf_sym);
13363
13364 /* If it's a .thumb_func, declare it as so,
13365 otherwise tag label as .code 16. */
13366 if (THUMB_IS_FUNC (sym))
13367 elf_sym->internal_elf_sym.st_info =
13368 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13369 else
13370 elf_sym->internal_elf_sym.st_info =
13371 ELF_ST_INFO (bind, STT_ARM_16BIT);
13372 }
13373 }
13374#endif
13375}
13376
13377int
a737bd4d 13378arm_data_in_code (void)
b99bd4ef
NC
13379{
13380 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13381 {
13382 *input_line_pointer = '/';
13383 input_line_pointer += 5;
13384 *input_line_pointer = 0;
13385 return 1;
13386 }
13387
13388 return 0;
13389}
13390
13391char *
a737bd4d 13392arm_canonicalize_symbol_name (char * name)
b99bd4ef
NC
13393{
13394 int len;
13395
13396 if (thumb_mode && (len = strlen (name)) > 5
13397 && streq (name + len - 5, "/data"))
13398 *(name + len - 5) = 0;
13399
13400 return name;
13401}
13402
bfc866a6 13403#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13404void
a737bd4d 13405arm_validate_fix (fixS * fixP)
b99bd4ef
NC
13406{
13407 /* If the destination of the branch is a defined symbol which does not have
13408 the THUMB_FUNC attribute, then we must be calling a function which has
13409 the (interfacearm) attribute. We look for the Thumb entry point to that
13410 function and change the branch to refer to that function instead. */
13411 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13412 && fixP->fx_addsy != NULL
13413 && S_IS_DEFINED (fixP->fx_addsy)
13414 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13415 {
13416 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13417 }
b99bd4ef 13418}
bfc866a6 13419#endif
b99bd4ef 13420
114424c6 13421int
a737bd4d 13422arm_force_relocation (struct fix * fixp)
114424c6
AM
13423{
13424#if defined (OBJ_COFF) && defined (TE_PE)
13425 if (fixp->fx_r_type == BFD_RELOC_RVA)
13426 return 1;
13427#endif
13428#ifdef OBJ_ELF
ae6063d4 13429 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13430 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13431 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13432 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13433 return 1;
13434#endif
13435
13436 /* Resolve these relocations even if the symbol is extern or weak. */
13437 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13438 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13439 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13440 return 0;
13441
ae6063d4 13442 return generic_force_reloc (fixp);
114424c6
AM
13443}
13444
b99bd4ef
NC
13445#ifdef OBJ_COFF
13446/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13447 local labels from being added to the output symbol table when they
13448 are used with the ADRL pseudo op. The ADRL relocation should always
13449 be resolved before the binbary is emitted, so it is safe to say that
13450 it is adjustable. */
13451
b34976b6 13452bfd_boolean
a737bd4d 13453arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13454{
13455 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13456 return 1;
13457 return 0;
13458}
13459#endif
114424c6 13460
b99bd4ef
NC
13461#ifdef OBJ_ELF
13462/* Relocations against Thumb function names must be left unadjusted,
13463 so that the linker can use this information to correctly set the
13464 bottom bit of their addresses. The MIPS version of this function
13465 also prevents relocations that are mips-16 specific, but I do not
13466 know why it does this.
13467
13468 FIXME:
13469 There is one other problem that ought to be addressed here, but
13470 which currently is not: Taking the address of a label (rather
13471 than a function) and then later jumping to that address. Such
13472 addresses also ought to have their bottom bit set (assuming that
13473 they reside in Thumb code), but at the moment they will not. */
13474
b34976b6 13475bfd_boolean
a737bd4d 13476arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13477{
13478 if (fixP->fx_addsy == NULL)
13479 return 1;
13480
b99bd4ef
NC
13481 if (THUMB_IS_FUNC (fixP->fx_addsy)
13482 && fixP->fx_subsy == NULL)
13483 return 0;
13484
13485 /* We need the symbol name for the VTABLE entries. */
13486 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13487 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13488 return 0;
13489
a161fe53
AM
13490 /* Don't allow symbols to be discarded on GOT related relocs. */
13491 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13492 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
13493 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13494 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
13495 return 0;
13496
b99bd4ef
NC
13497 return 1;
13498}
13499
13500const char *
a737bd4d 13501elf32_arm_target_format (void)
b99bd4ef 13502{
e5a52504
MM
13503#ifdef TE_SYMBIAN
13504 return (target_big_endian
13505 ? "elf32-bigarm-symbian"
13506 : "elf32-littlearm-symbian");
a737bd4d 13507#else
b99bd4ef 13508 if (target_big_endian)
7f266840 13509 return "elf32-bigarm";
b99bd4ef 13510 else
7f266840 13511 return "elf32-littlearm";
e5a52504 13512#endif
b99bd4ef
NC
13513}
13514
13515void
a737bd4d
NC
13516armelf_frob_symbol (symbolS * symp,
13517 int * puntp)
b99bd4ef
NC
13518{
13519 elf_frob_symbol (symp, puntp);
13520}
13521
b99bd4ef 13522static void
a737bd4d 13523s_arm_elf_cons (int nbytes)
b99bd4ef
NC
13524{
13525 expressionS exp;
13526
13527#ifdef md_flush_pending_output
13528 md_flush_pending_output ();
13529#endif
13530
13531 if (is_it_end_of_statement ())
13532 {
13533 demand_empty_rest_of_line ();
13534 return;
13535 }
13536
13537#ifdef md_cons_align
13538 md_cons_align (nbytes);
13539#endif
13540
6057a28f 13541 mapping_state (MAP_DATA);
b99bd4ef
NC
13542 do
13543 {
13544 bfd_reloc_code_real_type reloc;
13545
13546 expression (& exp);
13547
13548 if (exp.X_op == O_symbol
13549 && * input_line_pointer == '('
13550 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13551 {
13552 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13553 int size = bfd_get_reloc_size (howto);
13554
13555 if (size > nbytes)
13556 as_bad ("%s relocations do not fit in %d bytes",
13557 howto->name, nbytes);
13558 else
13559 {
a737bd4d 13560 char *p = frag_more ((int) nbytes);
b99bd4ef
NC
13561 int offset = nbytes - size;
13562
13563 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13564 &exp, 0, reloc);
13565 }
13566 }
13567 else
13568 emit_expr (&exp, (unsigned int) nbytes);
13569 }
13570 while (*input_line_pointer++ == ',');
13571
13572 /* Put terminator back into stream. */
13573 input_line_pointer --;
13574 demand_empty_rest_of_line ();
13575}
13576
eb043451
PB
13577
13578/* Parse a .rel31 directive. */
13579
13580static void
13581s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13582{
13583 expressionS exp;
13584 char *p;
13585 valueT highbit;
a737bd4d 13586
eb043451
PB
13587 SKIP_WHITESPACE ();
13588
13589 highbit = 0;
13590 if (*input_line_pointer == '1')
13591 highbit = 0x80000000;
13592 else if (*input_line_pointer != '0')
13593 as_bad (_("expected 0 or 1"));
13594
13595 input_line_pointer++;
13596 SKIP_WHITESPACE ();
13597 if (*input_line_pointer != ',')
13598 as_bad (_("missing comma"));
13599 input_line_pointer++;
13600
13601#ifdef md_flush_pending_output
13602 md_flush_pending_output ();
13603#endif
13604
13605#ifdef md_cons_align
13606 md_cons_align (4);
13607#endif
13608
13609 mapping_state (MAP_DATA);
13610
13611 expression (&exp);
13612
13613 p = frag_more (4);
13614 md_number_to_chars (p, highbit, 4);
13615 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13616 BFD_RELOC_ARM_PREL31);
13617
13618 demand_empty_rest_of_line ();
13619}
7ed4c4c5
NC
13620\f
13621/* Code to deal with unwinding tables. */
13622
13623static void add_unwind_adjustsp (offsetT);
13624
13625/* Switch to section NAME and create section if necessary. It's
13626 rather ugly that we have to manipulate input_line_pointer but I
13627 don't see any other way to accomplish the same thing without
13628 changing obj-elf.c (which may be the Right Thing, in the end).
13629 Copied from tc-ia64.c. */
13630
13631static void
13632set_section (char *name)
13633{
13634 char *saved_input_line_pointer;
13635
13636 saved_input_line_pointer = input_line_pointer;
13637 input_line_pointer = name;
13638 obj_elf_section (0);
13639 input_line_pointer = saved_input_line_pointer;
13640}
13641
13642/* Cenerate and deferred unwind frame offset. */
13643
13644static void
13645flush_pending_unwind (void)
13646{
13647 offsetT offset;
13648
13649 offset = unwind.pending_offset;
13650 unwind.pending_offset = 0;
13651 if (offset != 0)
13652 add_unwind_adjustsp (offset);
13653}
13654
13655/* Add an opcode to this list for this function. Two-byte opcodes should
13656 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13657 order. */
13658
13659static void
13660add_unwind_opcode (valueT op, int length)
13661{
13662 /* Add any deferred stack adjustment. */
13663 if (unwind.pending_offset)
13664 flush_pending_unwind ();
13665
13666 unwind.sp_restored = 0;
13667
13668 if (unwind.opcode_count + length > unwind.opcode_alloc)
13669 {
13670 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13671 if (unwind.opcodes)
13672 unwind.opcodes = xrealloc (unwind.opcodes,
13673 unwind.opcode_alloc);
13674 else
13675 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13676 }
13677 while (length > 0)
13678 {
13679 length--;
13680 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13681 op >>= 8;
13682 unwind.opcode_count++;
13683 }
13684}
13685
13686/* Add unwind opcodes to adjust the stack pointer. */
13687
13688static void
13689add_unwind_adjustsp (offsetT offset)
13690{
13691 valueT op;
13692
13693 if (offset > 0x200)
13694 {
13695 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13696 char bytes[5];
13697 int n;
13698 valueT o;
13699
13700 /* Long form: 0xb2, uleb128. */
13701 /* This might not fit in a word so add the individual bytes,
13702 remembering the list is built in reverse order. */
13703 o = (valueT) ((offset - 0x204) >> 2);
13704 if (o == 0)
13705 add_unwind_opcode (0, 1);
13706
13707 /* Calculate the uleb128 encoding of the offset. */
13708 n = 0;
13709 while (o)
13710 {
13711 bytes[n] = o & 0x7f;
13712 o >>= 7;
13713 if (o)
13714 bytes[n] |= 0x80;
13715 n++;
13716 }
13717 /* Add the insn. */
13718 for (; n; n--)
13719 add_unwind_opcode (bytes[n - 1], 1);
13720 add_unwind_opcode (0xb2, 1);
13721 }
13722 else if (offset > 0x100)
13723 {
13724 /* Two short opcodes. */
13725 add_unwind_opcode (0x3f, 1);
13726 op = (offset - 0x104) >> 2;
13727 add_unwind_opcode (op, 1);
13728 }
13729 else if (offset > 0)
13730 {
13731 /* Short opcode. */
13732 op = (offset - 4) >> 2;
13733 add_unwind_opcode (op, 1);
13734 }
13735 else if (offset < 0)
13736 {
13737 offset = -offset;
13738 while (offset > 0x100)
13739 {
13740 add_unwind_opcode (0x7f, 1);
13741 offset -= 0x100;
13742 }
13743 op = ((offset - 4) >> 2) | 0x40;
13744 add_unwind_opcode (op, 1);
13745 }
13746}
13747
13748/* Finish the list of unwind opcodes for this function. */
13749static void
13750finish_unwind_opcodes (void)
13751{
13752 valueT op;
13753
13754 if (unwind.fp_used)
13755 {
13756 /* Adjust sp as neccessary. */
13757 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13758 flush_pending_unwind ();
13759
13760 /* After restoring sp from the frame pointer. */
13761 op = 0x90 | unwind.fp_reg;
13762 add_unwind_opcode (op, 1);
13763 }
13764 else
13765 flush_pending_unwind ();
13766}
13767
13768
13769/* Start an exception table entry. If idx is nonzero this is an index table
13770 entry. */
13771
13772static void
13773start_unwind_section (const segT text_seg, int idx)
13774{
13775 const char * text_name;
13776 const char * prefix;
13777 const char * prefix_once;
13778 size_t prefix_len;
13779 size_t text_len;
13780 char * sec_name;
13781 size_t sec_name_len;
13782
13783 if (idx)
13784 {
13785 prefix = ELF_STRING_ARM_unwind;
13786 prefix_once = ELF_STRING_ARM_unwind_once;
13787 }
13788 else
13789 {
13790 prefix = ELF_STRING_ARM_unwind_info;
13791 prefix_once = ELF_STRING_ARM_unwind_info_once;
13792 }
13793
13794 text_name = segment_name (text_seg);
13795 if (streq (text_name, ".text"))
13796 text_name = "";
13797
13798 if (strncmp (text_name, ".gnu.linkonce.t.",
13799 strlen (".gnu.linkonce.t.")) == 0)
13800 {
13801 prefix = prefix_once;
13802 text_name += strlen (".gnu.linkonce.t.");
13803 }
13804
13805 prefix_len = strlen (prefix);
13806 text_len = strlen (text_name);
13807 sec_name_len = prefix_len + text_len;
13808 sec_name = alloca (sec_name_len + 1);
13809 memcpy (sec_name, prefix, prefix_len);
13810 memcpy (sec_name + prefix_len, text_name, text_len);
13811 sec_name[prefix_len + text_len] = '\0';
13812
13813 /* Handle COMDAT group. */
13814 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13815 {
13816 char *section;
13817 size_t len, group_name_len;
13818 const char *group_name = elf_group_name (text_seg);
13819
13820 if (group_name == NULL)
13821 {
13822 as_bad ("Group section `%s' has no group signature",
13823 segment_name (text_seg));
13824 ignore_rest_of_line ();
13825 return;
13826 }
13827 /* We have to construct a fake section directive. */
13828 group_name_len = strlen (group_name);
13829 if (idx)
13830 prefix_len = 13;
13831 else
13832 prefix_len = 16;
13833
13834 len = (sec_name_len
13835 + prefix_len /* ,"aG",%sectiontype, */
13836 + group_name_len /* ,group_name */
13837 + 7); /* ,comdat */
13838
13839 section = alloca (len + 1);
13840 memcpy (section, sec_name, sec_name_len);
13841 if (idx)
13842 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13843 else
13844 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13845 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13846 memcpy (section + len - 7, ",comdat", 7);
13847 section [len] = '\0';
13848 set_section (section);
13849 }
13850 else
13851 {
13852 set_section (sec_name);
13853 bfd_set_section_flags (stdoutput, now_seg,
13854 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13855 }
13856
13857 /* Set the setion link for index tables. */
13858 if (idx)
13859 elf_linked_to_section (now_seg) = text_seg;
13860}
13861
13862
13863/* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13864 personality routine data. Returns zero, or the index table value for
13865 and inline entry. */
13866
13867static valueT
13868create_unwind_entry (int have_data)
13869{
13870 int size;
13871 addressT where;
13872 unsigned char *ptr;
13873 /* The current word of data. */
13874 valueT data;
13875 /* The number of bytes left in this word. */
13876 int n;
13877
13878 finish_unwind_opcodes ();
13879
13880 /* Remember the current text section. */
13881 unwind.saved_seg = now_seg;
13882 unwind.saved_subseg = now_subseg;
13883
13884 start_unwind_section (now_seg, 0);
13885
13886 if (unwind.personality_routine == NULL)
13887 {
13888 if (unwind.personality_index == -2)
13889 {
13890 if (have_data)
13891 as_bad (_("handerdata in cantunwind frame"));
13892 return 1; /* EXIDX_CANTUNWIND. */
13893 }
13894
13895 /* Use a default personality routine if none is specified. */
13896 if (unwind.personality_index == -1)
13897 {
13898 if (unwind.opcode_count > 3)
13899 unwind.personality_index = 1;
13900 else
13901 unwind.personality_index = 0;
13902 }
13903
13904 /* Space for the personality routine entry. */
13905 if (unwind.personality_index == 0)
13906 {
13907 if (unwind.opcode_count > 3)
13908 as_bad (_("too many unwind opcodes for personality routine 0"));
13909
13910 if (!have_data)
13911 {
13912 /* All the data is inline in the index table. */
13913 data = 0x80;
13914 n = 3;
13915 while (unwind.opcode_count > 0)
13916 {
13917 unwind.opcode_count--;
13918 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13919 n--;
13920 }
13921
13922 /* Pad with "finish" opcodes. */
13923 while (n--)
13924 data = (data << 8) | 0xb0;
13925
13926 return data;
13927 }
13928 size = 0;
13929 }
13930 else
13931 /* We get two opcodes "free" in the first word. */
13932 size = unwind.opcode_count - 2;
13933 }
13934 else
13935 /* An extra byte is required for the opcode count. */
13936 size = unwind.opcode_count + 1;
13937
13938 size = (size + 3) >> 2;
13939 if (size > 0xff)
13940 as_bad (_("too many unwind opcodes"));
13941
13942 frag_align (2, 0, 0);
13943 record_alignment (now_seg, 2);
13944 unwind.table_entry = expr_build_dot ();
13945
13946 /* Allocate the table entry. */
13947 ptr = frag_more ((size << 2) + 4);
13948 where = frag_now_fix () - ((size << 2) + 4);
13949
13950 switch (unwind.personality_index)
13951 {
13952 case -1:
13953 /* ??? Should this be a PLT generating relocation? */
13954 /* Custom personality routine. */
13955 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13956 BFD_RELOC_ARM_PREL31);
13957 where += 4;
13958 ptr += 4;
13959
13960 /* Set the first byte to the number of additional words. */
13961 data = size - 1;
13962 n = 3;
13963 break;
13964
13965 /* ABI defined personality routines. */
13966 /* TODO: Emit R_ARM_NONE to the personality routine. */
13967 case 0:
13968 /* Three opcodes bytes are packed into the first word. */
13969 data = 0x80;
13970 n = 3;
13971 break;
13972
13973 case 1:
13974 case 2:
13975 /* The size and first two opcode bytes go in the first word. */
13976 data = ((0x80 + unwind.personality_index) << 8) | size;
13977 n = 2;
13978 break;
13979
13980 default:
13981 /* Should never happen. */
13982 abort ();
13983 }
13984
13985 /* Pack the opcodes into words (MSB first), reversing the list at the same
13986 time. */
13987 while (unwind.opcode_count > 0)
13988 {
13989 if (n == 0)
13990 {
13991 md_number_to_chars (ptr, data, 4);
13992 ptr += 4;
13993 n = 4;
13994 data = 0;
13995 }
13996 unwind.opcode_count--;
13997 n--;
13998 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13999 }
14000
14001 /* Finish off the last word. */
14002 if (n < 4)
14003 {
14004 /* Pad with "finish" opcodes. */
14005 while (n--)
14006 data = (data << 8) | 0xb0;
14007
14008 md_number_to_chars (ptr, data, 4);
14009 }
14010
14011 if (!have_data)
14012 {
14013 /* Add an empty descriptor if there is no user-specified data. */
14014 ptr = frag_more (4);
14015 md_number_to_chars (ptr, 0, 4);
14016 }
14017
14018 return 0;
14019}
14020
14021
14022/* Parse an unwind_fnstart directive. Simply records the current location. */
14023
14024static void
14025s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14026{
14027 demand_empty_rest_of_line ();
14028 /* Mark the start of the function. */
14029 unwind.proc_start = expr_build_dot ();
14030
14031 /* Reset the rest of the unwind info. */
14032 unwind.opcode_count = 0;
14033 unwind.table_entry = NULL;
14034 unwind.personality_routine = NULL;
14035 unwind.personality_index = -1;
14036 unwind.frame_size = 0;
14037 unwind.fp_offset = 0;
14038 unwind.fp_reg = 13;
14039 unwind.fp_used = 0;
14040 unwind.sp_restored = 0;
14041}
14042
14043
14044/* Parse a handlerdata directive. Creates the exception handling table entry
14045 for the function. */
14046
14047static void
14048s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14049{
14050 demand_empty_rest_of_line ();
14051 if (unwind.table_entry)
14052 as_bad (_("dupicate .handlerdata directive"));
14053
14054 create_unwind_entry (1);
14055}
14056
14057/* Parse an unwind_fnend directive. Generates the index table entry. */
14058
14059static void
14060s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14061{
14062 long where;
14063 unsigned char *ptr;
14064 valueT val;
14065
14066 demand_empty_rest_of_line ();
14067
14068 /* Add eh table entry. */
14069 if (unwind.table_entry == NULL)
14070 val = create_unwind_entry (0);
14071 else
14072 val = 0;
14073
14074 /* Add index table entry. This is two words. */
14075 start_unwind_section (unwind.saved_seg, 1);
14076 frag_align (2, 0, 0);
14077 record_alignment (now_seg, 2);
14078
14079 ptr = frag_more (8);
14080 where = frag_now_fix () - 8;
14081
14082 /* Self relative offset of the function start. */
14083 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
14084 BFD_RELOC_32);
14085
14086 if (val)
14087 /* Inline exception table entry. */
14088 md_number_to_chars (ptr + 4, val, 4);
14089 else
14090 /* Self relative offset of the table entry. */
14091 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14092 BFD_RELOC_ARM_PREL31);
14093
14094 /* Restore the original section. */
14095 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14096}
14097
14098
14099/* Parse an unwind_cantunwind directive. */
14100
14101static void
14102s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14103{
14104 demand_empty_rest_of_line ();
14105 if (unwind.personality_routine || unwind.personality_index != -1)
14106 as_bad (_("personality routine specified for cantunwind frame"));
14107
14108 unwind.personality_index = -2;
14109}
14110
14111
14112/* Parse a personalityindex directive. */
14113
14114static void
14115s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14116{
14117 expressionS exp;
14118
14119 if (unwind.personality_routine || unwind.personality_index != -1)
14120 as_bad (_("duplicate .personalityindex directive"));
14121
14122 SKIP_WHITESPACE ();
14123
14124 expression (&exp);
14125
14126 if (exp.X_op != O_constant
14127 || exp.X_add_number < 0 || exp.X_add_number > 15)
14128 {
14129 as_bad (_("bad personality routine number"));
14130 ignore_rest_of_line ();
14131 return;
14132 }
14133
14134 unwind.personality_index = exp.X_add_number;
14135
14136 demand_empty_rest_of_line ();
14137}
14138
14139
14140/* Parse a personality directive. */
14141
14142static void
14143s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14144{
14145 char *name, *p, c;
14146
14147 if (unwind.personality_routine || unwind.personality_index != -1)
14148 as_bad (_("duplicate .personality directive"));
14149
14150 SKIP_WHITESPACE ();
14151 name = input_line_pointer;
14152 c = get_symbol_end ();
14153 p = input_line_pointer;
14154 unwind.personality_routine = symbol_find_or_make (name);
14155 *p = c;
14156 SKIP_WHITESPACE ();
14157 demand_empty_rest_of_line ();
14158}
14159
14160
14161/* Parse a directive saving core registers. */
14162
14163static void
14164s_arm_unwind_save_core (void)
14165{
14166 valueT op;
14167 long range;
14168 int n;
14169
14170 SKIP_WHITESPACE ();
14171 range = reg_list (&input_line_pointer);
14172 if (range == FAIL)
14173 {
14174 as_bad (_("expected register list"));
14175 ignore_rest_of_line ();
14176 return;
14177 }
14178
14179 demand_empty_rest_of_line ();
14180
14181 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14182 into .unwind_save {..., sp...}. We aren't bothered about the value of
14183 ip because it is clobbered by calls. */
14184 if (unwind.sp_restored && unwind.fp_reg == 12
14185 && (range & 0x3000) == 0x1000)
14186 {
14187 unwind.opcode_count--;
14188 unwind.sp_restored = 0;
14189 range = (range | 0x2000) & ~0x1000;
14190 unwind.pending_offset = 0;
14191 }
14192
14193 /* See if we can use the short opcodes. These pop a block of upto 8
14194 registers starting with r4, plus maybe r14. */
14195 for (n = 0; n < 8; n++)
14196 {
14197 /* Break at the first non-saved register. */
14198 if ((range & (1 << (n + 4))) == 0)
14199 break;
14200 }
14201 /* See if there are any other bits set. */
14202 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14203 {
14204 /* Use the long form. */
14205 op = 0x8000 | ((range >> 4) & 0xfff);
14206 add_unwind_opcode (op, 2);
14207 }
14208 else
14209 {
14210 /* Use the short form. */
14211 if (range & 0x4000)
14212 op = 0xa8; /* Pop r14. */
14213 else
14214 op = 0xa0; /* Do not pop r14. */
14215 op |= (n - 1);
14216 add_unwind_opcode (op, 1);
14217 }
14218
14219 /* Pop r0-r3. */
14220 if (range & 0xf)
14221 {
14222 op = 0xb100 | (range & 0xf);
14223 add_unwind_opcode (op, 2);
14224 }
14225
14226 /* Record the number of bytes pushed. */
14227 for (n = 0; n < 16; n++)
14228 {
14229 if (range & (1 << n))
14230 unwind.frame_size += 4;
14231 }
14232}
14233
14234
14235/* Parse a directive saving FPA registers. */
14236
14237static void
14238s_arm_unwind_save_fpa (int reg)
14239{
14240 expressionS exp;
14241 int num_regs;
14242 valueT op;
14243
14244 /* Get Number of registers to transfer. */
14245 if (skip_past_comma (&input_line_pointer) != FAIL)
14246 expression (&exp);
14247 else
14248 exp.X_op = O_illegal;
14249
14250 if (exp.X_op != O_constant)
14251 {
14252 as_bad (_("expected , <constant>"));
14253 ignore_rest_of_line ();
14254 return;
14255 }
14256
14257 num_regs = exp.X_add_number;
14258
14259 if (num_regs < 1 || num_regs > 4)
14260 {
14261 as_bad (_("number of registers must be in the range [1:4]"));
14262 ignore_rest_of_line ();
14263 return;
14264 }
14265
14266 demand_empty_rest_of_line ();
14267
14268 if (reg == 4)
14269 {
14270 /* Short form. */
14271 op = 0xb4 | (num_regs - 1);
14272 add_unwind_opcode (op, 1);
14273 }
14274 else
14275 {
14276 /* Long form. */
14277 op = 0xc800 | (reg << 4) | (num_regs - 1);
14278 add_unwind_opcode (op, 2);
14279 }
14280 unwind.frame_size += num_regs * 12;
14281}
14282
14283
14284/* Parse a directive saving VFP registers. */
14285
14286static void
14287s_arm_unwind_save_vfp (void)
14288{
14289 int count;
14290 int reg;
14291 valueT op;
14292
14293 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14294 if (count == FAIL)
14295 {
14296 as_bad (_("expected register list"));
14297 ignore_rest_of_line ();
14298 return;
14299 }
14300
14301 demand_empty_rest_of_line ();
14302
14303 if (reg == 8)
14304 {
14305 /* Short form. */
14306 op = 0xb8 | (count - 1);
14307 add_unwind_opcode (op, 1);
14308 }
14309 else
14310 {
14311 /* Long form. */
14312 op = 0xb300 | (reg << 4) | (count - 1);
14313 add_unwind_opcode (op, 2);
14314 }
14315 unwind.frame_size += count * 8 + 4;
14316}
14317
14318
14319/* Parse a directive saving iWMMXt registers. */
14320
14321static void
14322s_arm_unwind_save_wmmx (void)
14323{
14324 int reg;
14325 int hi_reg;
14326 int i;
14327 unsigned wcg_mask;
14328 unsigned wr_mask;
14329 valueT op;
14330
14331 if (*input_line_pointer == '{')
14332 input_line_pointer++;
14333
14334 wcg_mask = 0;
14335 wr_mask = 0;
14336 do
14337 {
14338 reg = arm_reg_parse (&input_line_pointer,
14339 all_reg_maps[REG_TYPE_IWMMXT].htab);
14340
14341 if (wr_register (reg))
14342 {
14343 i = reg & ~WR_PREFIX;
14344 if (wr_mask >> i)
14345 as_tsktsk (_("register list not in ascending order"));
14346 wr_mask |= 1 << i;
14347 }
14348 else if (wcg_register (reg))
14349 {
14350 i = (reg & ~WC_PREFIX) - 8;
14351 if (wcg_mask >> i)
14352 as_tsktsk (_("register list not in ascending order"));
14353 wcg_mask |= 1 << i;
14354 }
14355 else
14356 {
14357 as_bad (_("expected wr or wcgr"));
14358 goto error;
14359 }
14360
14361 SKIP_WHITESPACE ();
14362 if (*input_line_pointer == '-')
14363 {
14364 hi_reg = arm_reg_parse (&input_line_pointer,
14365 all_reg_maps[REG_TYPE_IWMMXT].htab);
14366 if (wr_register (reg) && wr_register (hi_reg))
14367 {
14368 for (; reg < hi_reg; reg++)
14369 wr_mask |= 1 << (reg & ~WR_PREFIX);
14370 }
14371 else if (wcg_register (reg) && wcg_register (hi_reg))
14372 {
14373 for (; reg < hi_reg; reg++)
14374 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14375 }
14376 else
14377 {
14378 as_bad (_("bad register range"));
14379 goto error;
14380 }
14381 }
14382 }
14383 while (skip_past_comma (&input_line_pointer) != FAIL);
14384
14385 SKIP_WHITESPACE ();
14386 if (*input_line_pointer == '}')
14387 input_line_pointer++;
14388
14389 demand_empty_rest_of_line ();
14390
14391 if (wr_mask && wcg_mask)
14392 {
14393 as_bad (_("inconsistent register types"));
14394 goto error;
14395 }
14396
14397 /* Generate any deferred opcodes becuuse we're going to be looking at
14398 the list. */
14399 flush_pending_unwind ();
14400
14401 if (wcg_mask)
14402 {
14403 for (i = 0; i < 16; i++)
14404 {
14405 if (wcg_mask & (1 << i))
14406 unwind.frame_size += 4;
14407 }
14408 op = 0xc700 | wcg_mask;
14409 add_unwind_opcode (op, 2);
14410 }
14411 else
14412 {
14413 for (i = 0; i < 16; i++)
14414 {
14415 if (wr_mask & (1 << i))
14416 unwind.frame_size += 8;
14417 }
14418 /* Attempt to combine with a previous opcode. We do this because gcc
14419 likes to output separate unwind directives for a single block of
14420 registers. */
14421 if (unwind.opcode_count > 0)
14422 {
14423 i = unwind.opcodes[unwind.opcode_count - 1];
14424 if ((i & 0xf8) == 0xc0)
14425 {
14426 i &= 7;
14427 /* Only merge if the blocks are contiguous. */
14428 if (i < 6)
14429 {
14430 if ((wr_mask & 0xfe00) == (1 << 9))
14431 {
14432 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14433 unwind.opcode_count--;
14434 }
14435 }
14436 else if (i == 6 && unwind.opcode_count >= 2)
14437 {
14438 i = unwind.opcodes[unwind.opcode_count - 2];
14439 reg = i >> 4;
14440 i &= 0xf;
14441
14442 op = 0xffff << (reg - 1);
14443 if (reg > 0
14444 || ((wr_mask & op) == (1u << (reg - 1))))
14445 {
14446 op = (1 << (reg + i + 1)) - 1;
14447 op &= ~((1 << reg) - 1);
14448 wr_mask |= op;
14449 unwind.opcode_count -= 2;
14450 }
14451 }
14452 }
14453 }
14454
14455 hi_reg = 15;
14456 /* We want to generate opcodes in the order the registers have been
14457 saved, ie. descending order. */
14458 for (reg = 15; reg >= -1; reg--)
14459 {
14460 /* Save registers in blocks. */
14461 if (reg < 0
14462 || !(wr_mask & (1 << reg)))
14463 {
14464 /* We found an unsaved reg. Generate opcodes to save the
14465 preceeding block. */
14466 if (reg != hi_reg)
14467 {
14468 if (reg == 9)
14469 {
14470 /* Short form. */
14471 op = 0xc0 | (hi_reg - 10);
14472 add_unwind_opcode (op, 1);
14473 }
14474 else
14475 {
14476 /* Long form. */
14477 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14478 add_unwind_opcode (op, 2);
14479 }
14480 }
14481 hi_reg = reg - 1;
14482 }
14483 }
14484 }
14485 return;
14486error:
14487 ignore_rest_of_line ();
14488}
14489
14490
14491/* Parse an unwind_save directive. */
14492
14493static void
14494s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14495{
14496 char *saved_ptr;
14497 int reg;
14498
14499 /* Figure out what sort of save we have. */
14500 SKIP_WHITESPACE ();
14501 saved_ptr = input_line_pointer;
14502
14503 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14504 if (reg != FAIL)
14505 {
14506 s_arm_unwind_save_fpa (reg);
14507 return;
14508 }
14509
14510 if (*input_line_pointer == '{')
14511 input_line_pointer++;
14512
14513 SKIP_WHITESPACE ();
14514
14515 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14516 if (reg != FAIL)
14517 {
14518 input_line_pointer = saved_ptr;
14519 s_arm_unwind_save_core ();
14520 return;
14521 }
14522
14523 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14524 if (reg != FAIL)
14525 {
14526 input_line_pointer = saved_ptr;
14527 s_arm_unwind_save_vfp ();
14528 return;
14529 }
14530
14531 reg = arm_reg_parse (&input_line_pointer,
14532 all_reg_maps[REG_TYPE_IWMMXT].htab);
14533 if (reg != FAIL)
14534 {
14535 input_line_pointer = saved_ptr;
14536 s_arm_unwind_save_wmmx ();
14537 return;
14538 }
14539
14540 /* TODO: Maverick registers. */
14541 as_bad (_("unrecognised register"));
14542}
14543
14544
14545/* Parse an unwind_movsp directive. */
14546
14547static void
14548s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14549{
14550 int reg;
14551 valueT op;
14552
14553 SKIP_WHITESPACE ();
14554 reg = reg_required_here (&input_line_pointer, -1);
14555 if (reg == FAIL)
14556 {
14557 as_bad (_("ARM register expected"));
14558 ignore_rest_of_line ();
14559 return;
14560 }
14561
14562 if (reg == 13 || reg == 15)
14563 {
14564 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14565 ignore_rest_of_line ();
14566 return;
14567 }
14568
14569 if (unwind.fp_reg != 13)
14570 as_bad (_("unexpected .unwind_movsp directive"));
14571
14572 /* Generate opcode to restore the value. */
14573 op = 0x90 | reg;
14574 add_unwind_opcode (op, 1);
14575
14576 /* Record the information for later. */
14577 unwind.fp_reg = reg;
14578 unwind.fp_offset = unwind.frame_size;
14579 unwind.sp_restored = 1;
14580 demand_empty_rest_of_line ();
14581}
14582
14583
14584/* Parse #<number>. */
14585
14586static int
14587require_hashconst (int * val)
14588{
14589 expressionS exp;
14590
14591 SKIP_WHITESPACE ();
14592 if (*input_line_pointer == '#')
14593 {
14594 input_line_pointer++;
14595 expression (&exp);
14596 }
14597 else
14598 exp.X_op = O_illegal;
14599
14600 if (exp.X_op != O_constant)
14601 {
14602 as_bad (_("expected #constant"));
14603 ignore_rest_of_line ();
14604 return FAIL;
14605 }
14606 *val = exp.X_add_number;
14607 return SUCCESS;
14608}
14609
14610/* Parse an unwind_pad directive. */
14611
14612static void
14613s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14614{
14615 int offset;
14616
14617 if (require_hashconst (&offset) == FAIL)
14618 return;
14619
14620 if (offset & 3)
14621 {
14622 as_bad (_("stack increment must be multiple of 4"));
14623 ignore_rest_of_line ();
14624 return;
14625 }
14626
14627 /* Don't generate any opcodes, just record the details for later. */
14628 unwind.frame_size += offset;
14629 unwind.pending_offset += offset;
14630
14631 demand_empty_rest_of_line ();
14632}
14633
14634/* Parse an unwind_setfp directive. */
14635
14636static void
14637s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14638{
14639 int sp_reg;
14640 int fp_reg;
14641 int offset;
14642
14643 fp_reg = reg_required_here (&input_line_pointer, -1);
14644 if (skip_past_comma (&input_line_pointer) == FAIL)
14645 sp_reg = FAIL;
14646 else
14647 sp_reg = reg_required_here (&input_line_pointer, -1);
14648
14649 if (fp_reg == FAIL || sp_reg == FAIL)
14650 {
14651 as_bad (_("expected <reg>, <reg>"));
14652 ignore_rest_of_line ();
14653 return;
14654 }
14655
14656 /* Optonal constant. */
14657 if (skip_past_comma (&input_line_pointer) != FAIL)
14658 {
14659 if (require_hashconst (&offset) == FAIL)
14660 return;
14661 }
14662 else
14663 offset = 0;
14664
14665 demand_empty_rest_of_line ();
14666
14667 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14668 {
14669 as_bad (_("register must be either sp or set by a previous"
14670 "unwind_movsp directive"));
14671 return;
14672 }
14673
14674 /* Don't generate any opcodes, just record the information for later. */
14675 unwind.fp_reg = fp_reg;
14676 unwind.fp_used = 1;
14677 if (sp_reg == 13)
14678 unwind.fp_offset = unwind.frame_size - offset;
14679 else
14680 unwind.fp_offset -= offset;
14681}
14682
14683/* Parse an unwind_raw directive. */
14684
14685static void
14686s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14687{
14688 expressionS exp;
14689 /* This is an arbitary limit. */
14690 unsigned char op[16];
14691 int count;
14692
14693 SKIP_WHITESPACE ();
14694 expression (&exp);
14695 if (exp.X_op == O_constant
14696 && skip_past_comma (&input_line_pointer) != FAIL)
14697 {
14698 unwind.frame_size += exp.X_add_number;
14699 expression (&exp);
14700 }
14701 else
14702 exp.X_op = O_illegal;
14703
14704 if (exp.X_op != O_constant)
14705 {
14706 as_bad (_("expected <offset>, <opcode>"));
14707 ignore_rest_of_line ();
14708 return;
14709 }
14710
14711 count = 0;
14712
14713 /* Parse the opcode. */
14714 for (;;)
14715 {
14716 if (count >= 16)
14717 {
14718 as_bad (_("unwind opcode too long"));
14719 ignore_rest_of_line ();
14720 }
14721 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14722 {
14723 as_bad (_("invalid unwind opcode"));
14724 ignore_rest_of_line ();
14725 return;
14726 }
14727 op[count++] = exp.X_add_number;
14728
14729 /* Parse the next byte. */
14730 if (skip_past_comma (&input_line_pointer) == FAIL)
14731 break;
14732
14733 expression (&exp);
14734 }
14735
14736 /* Add the opcode bytes in reverse order. */
14737 while (count--)
14738 add_unwind_opcode (op[count], 1);
14739
14740 demand_empty_rest_of_line ();
14741}
eb043451 14742
b99bd4ef
NC
14743#endif /* OBJ_ELF */
14744
14745/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14746 of an rs_align_code fragment. */
14747
14748void
a737bd4d 14749arm_handle_align (fragS * fragP)
b99bd4ef
NC
14750{
14751 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14752 static char const thumb_noop[2] = { 0xc0, 0x46 };
14753 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14754 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14755
14756 int bytes, fix, noop_size;
14757 char * p;
14758 const char * noop;
cc8a6dd0 14759
b99bd4ef
NC
14760 if (fragP->fr_type != rs_align_code)
14761 return;
14762
14763 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14764 p = fragP->fr_literal + fragP->fr_fix;
14765 fix = 0;
cc8a6dd0 14766
b99bd4ef
NC
14767 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14768 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14769
b99bd4ef
NC
14770 if (fragP->tc_frag_data)
14771 {
14772 if (target_big_endian)
14773 noop = thumb_bigend_noop;
14774 else
14775 noop = thumb_noop;
14776 noop_size = sizeof (thumb_noop);
14777 }
14778 else
14779 {
14780 if (target_big_endian)
14781 noop = arm_bigend_noop;
14782 else
14783 noop = arm_noop;
14784 noop_size = sizeof (arm_noop);
14785 }
cc8a6dd0 14786
b99bd4ef
NC
14787 if (bytes & (noop_size - 1))
14788 {
14789 fix = bytes & (noop_size - 1);
14790 memset (p, 0, fix);
14791 p += fix;
14792 bytes -= fix;
14793 }
14794
14795 while (bytes >= noop_size)
14796 {
14797 memcpy (p, noop, noop_size);
14798 p += noop_size;
14799 bytes -= noop_size;
14800 fix += noop_size;
14801 }
cc8a6dd0 14802
b99bd4ef
NC
14803 fragP->fr_fix += fix;
14804 fragP->fr_var = noop_size;
14805}
14806
14807/* Called from md_do_align. Used to create an alignment
14808 frag in a code section. */
14809
14810void
a737bd4d 14811arm_frag_align_code (int n, int max)
b99bd4ef
NC
14812{
14813 char * p;
14814
2d2255b5 14815 /* We assume that there will never be a requirement
b99bd4ef
NC
14816 to support alignments greater than 32 bytes. */
14817 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14818 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14819
b99bd4ef
NC
14820 p = frag_var (rs_align_code,
14821 MAX_MEM_FOR_RS_ALIGN_CODE,
14822 1,
14823 (relax_substateT) max,
14824 (symbolS *) NULL,
14825 (offsetT) n,
14826 (char *) NULL);
14827 *p = 0;
b99bd4ef
NC
14828}
14829
14830/* Perform target specific initialisation of a frag. */
14831
14832void
a737bd4d 14833arm_init_frag (fragS * fragP)
b99bd4ef
NC
14834{
14835 /* Record whether this frag is in an ARM or a THUMB area. */
14836 fragP->tc_frag_data = thumb_mode;
14837}
a737bd4d 14838
a394c00f
NC
14839#ifdef OBJ_ELF
14840
14841/* Convert REGNAME to a DWARF-2 register number. */
14842
14843int
14844tc_arm_regname_to_dw2regnum (const char *regname)
14845{
14846 unsigned int i;
14847
14848 for (i = 0; rn_table[i].name; i++)
14849 if (streq (regname, rn_table[i].name))
14850 return rn_table[i].number;
14851
14852 return -1;
14853}
14854
14855/* Initialize the DWARF-2 unwind information for this procedure. */
14856
14857void
14858tc_arm_frame_initial_instructions (void)
14859{
14860 cfi_add_CFA_def_cfa (REG_SP, 0);
14861}
14862#endif
14863
a737bd4d
NC
14864/* This table describes all the machine specific pseudo-ops the assembler
14865 has to support. The fields are:
14866 pseudo-op name without dot
14867 function to call to execute this pseudo-op
14868 Integer arg to pass to the function. */
14869
14870const pseudo_typeS md_pseudo_table[] =
14871{
14872 /* Never called because '.req' does not start a line. */
14873 { "req", s_req, 0 },
14874 { "unreq", s_unreq, 0 },
14875 { "bss", s_bss, 0 },
14876 { "align", s_align, 0 },
14877 { "arm", s_arm, 0 },
14878 { "thumb", s_thumb, 0 },
14879 { "code", s_code, 0 },
14880 { "force_thumb", s_force_thumb, 0 },
14881 { "thumb_func", s_thumb_func, 0 },
14882 { "thumb_set", s_thumb_set, 0 },
14883 { "even", s_even, 0 },
14884 { "ltorg", s_ltorg, 0 },
14885 { "pool", s_ltorg, 0 },
14886#ifdef OBJ_ELF
14887 { "word", s_arm_elf_cons, 4 },
14888 { "long", s_arm_elf_cons, 4 },
14889 { "rel31", s_arm_rel31, 0 },
7ed4c4c5
NC
14890 { "fnstart", s_arm_unwind_fnstart, 0 },
14891 { "fnend", s_arm_unwind_fnend, 0 },
14892 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14893 { "personality", s_arm_unwind_personality, 0 },
14894 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14895 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14896 { "save", s_arm_unwind_save, 0 },
14897 { "movsp", s_arm_unwind_movsp, 0 },
14898 { "pad", s_arm_unwind_pad, 0 },
14899 { "setfp", s_arm_unwind_setfp, 0 },
14900 { "unwind_raw", s_arm_unwind_raw, 0 },
a737bd4d
NC
14901#else
14902 { "word", cons, 4},
14903#endif
14904 { "extend", float_cons, 'x' },
14905 { "ldouble", float_cons, 'x' },
14906 { "packed", float_cons, 'p' },
14907 { 0, 0, 0 }
14908};