]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
2005-02-17 Paul Brook <paul@codesourcery.com>
[thirdparty/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
4e7fd91e
PB
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005
b99bd4ef
NC
4 Free Software Foundation, Inc.
5 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
6 Modified by David Taylor (dtaylor@armltd.co.uk)
22d9c8c5 7 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
34920d91
NC
8 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
9 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
b99bd4ef
NC
10
11 This file is part of GAS, the GNU Assembler.
12
13 GAS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
16 any later version.
17
18 GAS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with GAS; see the file COPYING. If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, USA. */
27
b99bd4ef
NC
28#include <string.h>
29#define NO_RELOC 0
30#include "as.h"
3882b010 31#include "safe-ctype.h"
b99bd4ef
NC
32
33/* Need TARGET_CPU. */
34#include "config.h"
35#include "subsegs.h"
36#include "obstack.h"
37#include "symbols.h"
38#include "listing.h"
39
f263249b
RE
40#include "opcode/arm.h"
41
b99bd4ef
NC
42#ifdef OBJ_ELF
43#include "elf/arm.h"
44#include "dwarf2dbg.h"
a394c00f 45#include "dw2gencfi.h"
b99bd4ef
NC
46#endif
47
7ed4c4c5 48/* XXX Set this to 1 after the next binutils release. */
03b1477f
RE
49#define WARN_DEPRECATED 0
50
7ed4c4c5
NC
51#ifdef OBJ_ELF
52/* Must be at least the size of the largest unwind opcode (currently two). */
53#define ARM_OPCODE_CHUNK_SIZE 8
54
55/* This structure holds the unwinding state. */
56
57static struct
58{
59 symbolS * proc_start;
60 symbolS * table_entry;
61 symbolS * personality_routine;
62 int personality_index;
63 /* The segment containing the function. */
64 segT saved_seg;
65 subsegT saved_subseg;
66 /* Opcodes generated from this function. */
67 unsigned char * opcodes;
68 int opcode_count;
69 int opcode_alloc;
70 /* The number of bytes pushed to the stack. */
71 offsetT frame_size;
72 /* We don't add stack adjustment opcodes immediately so that we can merge
73 multiple adjustments. We can also omit the final adjustment
74 when using a frame pointer. */
75 offsetT pending_offset;
76 /* These two fields are set by both unwind_movsp and unwind_setfp. They
77 hold the reg+offset to use when restoring sp from a frame pointer. */
78 offsetT fp_offset;
79 int fp_reg;
80 /* Nonzero if an unwind_setfp directive has been seen. */
81 unsigned fp_used:1;
82 /* Nonzero if the last opcode restores sp from fp_reg. */
83 unsigned sp_restored:1;
84} unwind;
85
86#endif /* OBJ_ELF */
87
33a392fb
PB
88enum arm_float_abi
89{
90 ARM_FLOAT_ABI_HARD,
91 ARM_FLOAT_ABI_SOFTFP,
92 ARM_FLOAT_ABI_SOFT
93};
94
b89dddec
RE
95/* Types of processor to assemble for. */
96#define ARM_1 ARM_ARCH_V1
97#define ARM_2 ARM_ARCH_V2
98#define ARM_3 ARM_ARCH_V2S
99#define ARM_250 ARM_ARCH_V2S
100#define ARM_6 ARM_ARCH_V3
101#define ARM_7 ARM_ARCH_V3
102#define ARM_8 ARM_ARCH_V4
103#define ARM_9 ARM_ARCH_V4T
104#define ARM_STRONG ARM_ARCH_V4
105#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
106
107#ifndef CPU_DEFAULT
108#if defined __XSCALE__
b89dddec 109#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
110#else
111#if defined __thumb__
b89dddec 112#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 113#else
03b1477f 114#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
115#endif
116#endif
117#endif
118
119#ifndef FPU_DEFAULT
c820d418
MM
120# ifdef TE_LINUX
121# define FPU_DEFAULT FPU_ARCH_FPA
122# elif defined (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
4e7fd91e
PB
129# elif defined (TE_VXWORKS)
130# define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
c820d418
MM
131# else
132 /* For backwards compatibility, default to FPA. */
133# define FPU_DEFAULT FPU_ARCH_FPA
134# endif
135#endif /* ifndef FPU_DEFAULT */
b99bd4ef
NC
136
137#define streq(a, b) (strcmp (a, b) == 0)
138#define skip_whitespace(str) while (*(str) == ' ') ++(str)
139
03b1477f 140static unsigned long cpu_variant;
b99bd4ef 141
b99bd4ef 142/* Flags stored in private area of BFD structure. */
b34976b6
AM
143static int uses_apcs_26 = FALSE;
144static int atpcs = FALSE;
145static int support_interwork = FALSE;
146static int uses_apcs_float = FALSE;
147static int pic_code = FALSE;
03b1477f
RE
148
149/* Variables that we set while parsing command-line options. Once all
150 options have been read we re-process these values to set the real
151 assembly flags. */
152static int legacy_cpu = -1;
153static int legacy_fpu = -1;
154
155static int mcpu_cpu_opt = -1;
156static int mcpu_fpu_opt = -1;
157static int march_cpu_opt = -1;
158static int march_fpu_opt = -1;
159static int mfpu_opt = -1;
33a392fb 160static int mfloat_abi_opt = -1;
7cc69913 161#ifdef OBJ_ELF
d507cf36 162static int meabi_flags = EF_ARM_EABI_UNKNOWN;
7cc69913 163#endif
b99bd4ef
NC
164
165/* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
f57c81f6 167const char comment_chars[] = "@";
b99bd4ef
NC
168
169/* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172/* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175/* Also note that comments like this one will always work. */
05d2d07e 176const char line_comment_chars[] = "#";
b99bd4ef 177
da89cce1 178const char line_separator_chars[] = ";";
b99bd4ef
NC
179
180/* Chars that can be used to separate mant
181 from exp in floating point numbers. */
05d2d07e 182const char EXP_CHARS[] = "eE";
b99bd4ef
NC
183
184/* Chars that mean this number is a floating point constant. */
185/* As in 0f12.456 */
186/* or 0d1.2345e12 */
187
05d2d07e 188const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
189
190/* Prefix characters that indicate the start of an immediate
191 value. */
192#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
193
194#ifdef OBJ_ELF
195/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196symbolS * GOT_symbol;
197#endif
198
199/* Size of relocation record. */
05d2d07e 200const int md_reloc_size = 8;
b99bd4ef
NC
201
202/* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
205 instructions. */
206static int thumb_mode = 0;
207
208typedef struct arm_fix
209{
210 int thumb_mode;
211} arm_fix_data;
212
213struct arm_it
214{
05d2d07e 215 const char * error;
b99bd4ef 216 unsigned long instruction;
b99bd4ef
NC
217 int size;
218 struct
219 {
220 bfd_reloc_code_real_type type;
221 expressionS exp;
222 int pc_rel;
223 } reloc;
224};
225
226struct arm_it inst;
227
228enum asm_shift_index
229{
230 SHIFT_LSL = 0,
231 SHIFT_LSR,
232 SHIFT_ASR,
233 SHIFT_ROR,
234 SHIFT_RRX
235};
236
237struct asm_shift_properties
238{
239 enum asm_shift_index index;
240 unsigned long bit_field;
241 unsigned int allows_0 : 1;
242 unsigned int allows_32 : 1;
243};
244
245static const struct asm_shift_properties shift_properties [] =
246{
247 { SHIFT_LSL, 0, 1, 0},
248 { SHIFT_LSR, 0x20, 0, 1},
249 { SHIFT_ASR, 0x40, 0, 1},
250 { SHIFT_ROR, 0x60, 0, 0},
251 { SHIFT_RRX, 0x60, 0, 0}
252};
253
254struct asm_shift_name
255{
256 const char * name;
257 const struct asm_shift_properties * properties;
258};
259
260static const struct asm_shift_name shift_names [] =
261{
262 { "asl", shift_properties + SHIFT_LSL },
263 { "lsl", shift_properties + SHIFT_LSL },
264 { "lsr", shift_properties + SHIFT_LSR },
265 { "asr", shift_properties + SHIFT_ASR },
266 { "ror", shift_properties + SHIFT_ROR },
267 { "rrx", shift_properties + SHIFT_RRX },
268 { "ASL", shift_properties + SHIFT_LSL },
269 { "LSL", shift_properties + SHIFT_LSL },
270 { "LSR", shift_properties + SHIFT_LSR },
271 { "ASR", shift_properties + SHIFT_ASR },
272 { "ROR", shift_properties + SHIFT_ROR },
273 { "RRX", shift_properties + SHIFT_RRX }
274};
275
09d92015 276/* Any kind of shift is accepted. */
b99bd4ef 277#define NO_SHIFT_RESTRICT 1
09d92015
MM
278/* The shift operand must be an immediate value, not a register. */
279#define SHIFT_IMMEDIATE 0
280/* The shift must be LSL or ASR and the operand must be an immediate. */
281#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
282/* The shift must be ASR and the operand must be an immediate. */
283#define SHIFT_ASR_IMMEDIATE 3
284/* The shift must be LSL and the operand must be an immediate. */
285#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
286
287#define NUM_FLOAT_VALS 8
288
05d2d07e 289const char * fp_const[] =
b99bd4ef
NC
290{
291 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
292};
293
294/* Number of littlenums required to hold an extended precision number. */
295#define MAX_LITTLENUMS 6
296
297LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
298
299#define FAIL (-1)
300#define SUCCESS (0)
301
bfae80f2
RE
302/* Whether a Co-processor load/store operation accepts write-back forms. */
303#define CP_WB_OK 1
304#define CP_NO_WB 0
305
b99bd4ef
NC
306#define SUFF_S 1
307#define SUFF_D 2
308#define SUFF_E 3
309#define SUFF_P 4
310
311#define CP_T_X 0x00008000
312#define CP_T_Y 0x00400000
313#define CP_T_Pre 0x01000000
314#define CP_T_UD 0x00800000
315#define CP_T_WB 0x00200000
316
317#define CONDS_BIT 0x00100000
318#define LOAD_BIT 0x00100000
b99bd4ef
NC
319
320#define DOUBLE_LOAD_FLAG 0x00000001
321
322struct asm_cond
323{
05d2d07e 324 const char * template;
b99bd4ef
NC
325 unsigned long value;
326};
327
b99bd4ef 328#define COND_ALWAYS 0xe0000000
90e4755a 329#define COND_MASK 0xf0000000
b99bd4ef 330
05d2d07e 331static const struct asm_cond conds[] =
b99bd4ef
NC
332{
333 {"eq", 0x00000000},
334 {"ne", 0x10000000},
335 {"cs", 0x20000000}, {"hs", 0x20000000},
336 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
337 {"mi", 0x40000000},
338 {"pl", 0x50000000},
339 {"vs", 0x60000000},
340 {"vc", 0x70000000},
341 {"hi", 0x80000000},
342 {"ls", 0x90000000},
343 {"ge", 0xa0000000},
344 {"lt", 0xb0000000},
345 {"gt", 0xc0000000},
346 {"le", 0xd0000000},
347 {"al", 0xe0000000},
348 {"nv", 0xf0000000}
349};
350
b99bd4ef
NC
351struct asm_psr
352{
b34976b6
AM
353 const char *template;
354 bfd_boolean cpsr;
b99bd4ef
NC
355 unsigned long field;
356};
357
2d2255b5 358/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
359#define SPSR_BIT (1 << 22)
360
361/* How many bits to shift the PSR_xxx bits up by. */
362#define PSR_SHIFT 16
363
364#define PSR_c (1 << 0)
365#define PSR_x (1 << 1)
366#define PSR_s (1 << 2)
367#define PSR_f (1 << 3)
368
05d2d07e 369static const struct asm_psr psrs[] =
b99bd4ef 370{
b34976b6
AM
371 {"CPSR", TRUE, PSR_c | PSR_f},
372 {"CPSR_all", TRUE, PSR_c | PSR_f},
373 {"SPSR", FALSE, PSR_c | PSR_f},
374 {"SPSR_all", FALSE, PSR_c | PSR_f},
375 {"CPSR_flg", TRUE, PSR_f},
376 {"CPSR_f", TRUE, PSR_f},
377 {"SPSR_flg", FALSE, PSR_f},
378 {"SPSR_f", FALSE, PSR_f},
379 {"CPSR_c", TRUE, PSR_c},
380 {"CPSR_ctl", TRUE, PSR_c},
381 {"SPSR_c", FALSE, PSR_c},
382 {"SPSR_ctl", FALSE, PSR_c},
383 {"CPSR_x", TRUE, PSR_x},
384 {"CPSR_s", TRUE, PSR_s},
385 {"SPSR_x", FALSE, PSR_x},
386 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 387 /* Combinations of flags. */
b34976b6
AM
388 {"CPSR_fs", TRUE, PSR_f | PSR_s},
389 {"CPSR_fx", TRUE, PSR_f | PSR_x},
390 {"CPSR_fc", TRUE, PSR_f | PSR_c},
391 {"CPSR_sf", TRUE, PSR_s | PSR_f},
392 {"CPSR_sx", TRUE, PSR_s | PSR_x},
393 {"CPSR_sc", TRUE, PSR_s | PSR_c},
394 {"CPSR_xf", TRUE, PSR_x | PSR_f},
395 {"CPSR_xs", TRUE, PSR_x | PSR_s},
396 {"CPSR_xc", TRUE, PSR_x | PSR_c},
397 {"CPSR_cf", TRUE, PSR_c | PSR_f},
398 {"CPSR_cs", TRUE, PSR_c | PSR_s},
399 {"CPSR_cx", TRUE, PSR_c | PSR_x},
400 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
401 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
402 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
403 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
404 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
405 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
406 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
407 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
408 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
409 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
410 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
411 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
412 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
413 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
414 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
415 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
416 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
417 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
418 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
419 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
420 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
421 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
422 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
423 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
424 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
425 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
426 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
427 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
428 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
429 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
430 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
431 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
432 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
433 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
434 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
435 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
436 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
437 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
438 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
439 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
440 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
441 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
442 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
443 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
444 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
445 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
446 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
447 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
448 {"SPSR_fs", FALSE, PSR_f | PSR_s},
449 {"SPSR_fx", FALSE, PSR_f | PSR_x},
450 {"SPSR_fc", FALSE, PSR_f | PSR_c},
451 {"SPSR_sf", FALSE, PSR_s | PSR_f},
452 {"SPSR_sx", FALSE, PSR_s | PSR_x},
453 {"SPSR_sc", FALSE, PSR_s | PSR_c},
454 {"SPSR_xf", FALSE, PSR_x | PSR_f},
455 {"SPSR_xs", FALSE, PSR_x | PSR_s},
456 {"SPSR_xc", FALSE, PSR_x | PSR_c},
457 {"SPSR_cf", FALSE, PSR_c | PSR_f},
458 {"SPSR_cs", FALSE, PSR_c | PSR_s},
459 {"SPSR_cx", FALSE, PSR_c | PSR_x},
460 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
461 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
462 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
463 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
464 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
465 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
466 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
467 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
468 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
469 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
470 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
471 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
472 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
473 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
474 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
475 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
476 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
477 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
478 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
479 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
480 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
481 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
482 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
483 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
484 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
485 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
486 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
487 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
488 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
489 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
490 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
491 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
492 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
493 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
494 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
495 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
496 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
497 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
498 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
499 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
500 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
501 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
502 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
503 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
504 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
505 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
506 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
507 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
508};
509
e16bb312
NC
510enum wreg_type
511 {
512 IWMMXT_REG_WR = 0,
513 IWMMXT_REG_WC = 1,
514 IWMMXT_REG_WR_OR_WC = 2,
515 IWMMXT_REG_WCG
516 };
517
518enum iwmmxt_insn_type
519{
520 check_rd,
521 check_wr,
522 check_wrwr,
523 check_wrwrwr,
524 check_wrwrwcg,
525 check_tbcst,
526 check_tmovmsk,
527 check_tmia,
528 check_tmcrr,
529 check_tmrrc,
530 check_tmcr,
531 check_tmrc,
532 check_tinsr,
533 check_textrc,
534 check_waligni,
535 check_textrm,
536 check_wshufh
537};
538
bfae80f2
RE
539enum vfp_dp_reg_pos
540{
541 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
542};
543
544enum vfp_sp_reg_pos
545{
546 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
547};
548
549enum vfp_ldstm_type
550{
551 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
552};
553
554/* VFP system registers. */
555struct vfp_reg
556{
557 const char *name;
558 unsigned long regno;
559};
560
cc8a6dd0 561static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
562{
563 {"fpsid", 0x00000000},
564 {"FPSID", 0x00000000},
565 {"fpscr", 0x00010000},
566 {"FPSCR", 0x00010000},
567 {"fpexc", 0x00080000},
568 {"FPEXC", 0x00080000}
569};
570
6c43fab6
RE
571/* Structure for a hash table entry for a register. */
572struct reg_entry
573{
574 const char * name;
575 int number;
0bbf2aa4 576 bfd_boolean builtin;
6c43fab6
RE
577};
578
e28cd48c 579/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
580#define REG_SP 13
581#define REG_LR 14
582#define REG_PC 15
583
e16bb312
NC
584#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
585#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
586#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
587
0bbf2aa4
NC
588/* These are the standard names. Users can add aliases with .req.
589 and delete them with .unreq. */
590
6c43fab6
RE
591/* Integer Register Numbers. */
592static const struct reg_entry rn_table[] =
593{
0bbf2aa4
NC
594 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
595 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
596 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
597 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 598 /* ATPCS Synonyms. */
0bbf2aa4
NC
599 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
600 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
601 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 602 /* Well-known aliases. */
0bbf2aa4
NC
603 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
604 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
605 {NULL, 0, TRUE}
6c43fab6
RE
606};
607
e16bb312
NC
608#define WR_PREFIX 0x200
609#define WC_PREFIX 0x400
610
611static const struct reg_entry iwmmxt_table[] =
612{
5a6c6817 613 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
614 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
615 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
616 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
617 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
618 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
619 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
620 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
621 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
622 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
623 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
624 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
625 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
626
627 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
628 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
629 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
630 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
631 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
632 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
633 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
634 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
635 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
636 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
637 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
638 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
639 {NULL, 0, TRUE}
e16bb312
NC
640};
641
6c43fab6
RE
642/* Co-processor Numbers. */
643static const struct reg_entry cp_table[] =
644{
0bbf2aa4
NC
645 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
646 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
647 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
648 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
649 {NULL, 0, TRUE}
6c43fab6
RE
650};
651
652/* Co-processor Register Numbers. */
653static const struct reg_entry cn_table[] =
654{
0bbf2aa4
NC
655 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
656 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
657 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
658 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 659 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
660 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
661 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
662 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
663 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
664 {NULL, 0, TRUE}
6c43fab6
RE
665};
666
667/* FPA Registers. */
668static const struct reg_entry fn_table[] =
669{
0bbf2aa4
NC
670 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
671 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
672 {NULL, 0, TRUE}
6c43fab6
RE
673};
674
bfae80f2
RE
675/* VFP SP Registers. */
676static const struct reg_entry sn_table[] =
677{
0bbf2aa4
NC
678 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
679 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
680 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
681 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
682 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
683 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
684 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
685 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
686 {NULL, 0, TRUE}
bfae80f2
RE
687};
688
689/* VFP DP Registers. */
690static const struct reg_entry dn_table[] =
691{
0bbf2aa4
NC
692 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
693 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
694 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
695 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
696 {NULL, 0, TRUE}
bfae80f2
RE
697};
698
63e63b07 699/* Maverick DSP coprocessor registers. */
6c43fab6
RE
700static const struct reg_entry mav_mvf_table[] =
701{
0bbf2aa4
NC
702 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
703 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
704 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
705 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
706 {NULL, 0, TRUE}
6c43fab6
RE
707};
708
709static const struct reg_entry mav_mvd_table[] =
710{
0bbf2aa4
NC
711 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
712 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
713 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
714 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
715 {NULL, 0, TRUE}
6c43fab6
RE
716};
717
718static const struct reg_entry mav_mvfx_table[] =
719{
0bbf2aa4
NC
720 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
721 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
722 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
723 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
724 {NULL, 0, TRUE}
6c43fab6
RE
725};
726
727static const struct reg_entry mav_mvdx_table[] =
728{
0bbf2aa4
NC
729 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
730 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
731 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
732 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
733 {NULL, 0, TRUE}
6c43fab6
RE
734};
735
736static const struct reg_entry mav_mvax_table[] =
737{
0bbf2aa4
NC
738 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
739 {NULL, 0, TRUE}
6c43fab6
RE
740};
741
742static const struct reg_entry mav_dspsc_table[] =
743{
0bbf2aa4
NC
744 {"dspsc", 0, TRUE},
745 {NULL, 0, TRUE}
6c43fab6
RE
746};
747
748struct reg_map
749{
a737bd4d
NC
750 const struct reg_entry * names;
751 int max_regno;
752 struct hash_control * htab;
753 const char * expected;
6c43fab6
RE
754};
755
756struct reg_map all_reg_maps[] =
757{
758 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
759 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
760 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 761 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
762 {sn_table, 31, NULL, N_("VFP single precision register expected")},
763 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
764 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
765 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
766 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 767 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
768 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
769 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 770 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
771};
772
773/* Enumeration matching entries in table above. */
774enum arm_reg_type
775{
776 REG_TYPE_RN = 0,
777#define REG_TYPE_FIRST REG_TYPE_RN
778 REG_TYPE_CP = 1,
779 REG_TYPE_CN = 2,
780 REG_TYPE_FN = 3,
bfae80f2
RE
781 REG_TYPE_SN = 4,
782 REG_TYPE_DN = 5,
783 REG_TYPE_MVF = 6,
784 REG_TYPE_MVD = 7,
785 REG_TYPE_MVFX = 8,
786 REG_TYPE_MVDX = 9,
787 REG_TYPE_MVAX = 10,
788 REG_TYPE_DSPSC = 11,
e16bb312 789 REG_TYPE_IWMMXT = 12,
bfae80f2 790
e16bb312 791 REG_TYPE_MAX = 13
6c43fab6 792};
404ff6b5 793
b99bd4ef
NC
794/* ARM instructions take 4bytes in the object file, Thumb instructions
795 take 2: */
796#define INSN_SIZE 4
797
404ff6b5 798/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 799#define MAV_MODE1 0x100c
404ff6b5
AH
800
801/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 802#define MAV_MODE2 0x0c10
404ff6b5 803
34920d91
NC
804/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
805#define MAV_MODE3 0x100c
404ff6b5
AH
806
807/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 808#define MAV_MODE4 0x0c0010
404ff6b5
AH
809
810/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 811#define MAV_MODE5 0x00100c
404ff6b5
AH
812
813/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 814#define MAV_MODE6 0x00100c05
b99bd4ef
NC
815
816struct asm_opcode
817{
818 /* Basic string to match. */
05d2d07e 819 const char * template;
b99bd4ef
NC
820
821 /* Basic instruction code. */
822 unsigned long value;
823
90e4755a
RE
824 /* Offset into the template where the condition code (if any) will be.
825 If zero, then the instruction is never conditional. */
826 unsigned cond_offset;
b99bd4ef 827
90e4755a
RE
828 /* Which architecture variant provides this instruction. */
829 unsigned long variant;
b99bd4ef
NC
830
831 /* Function to call to parse args. */
a737bd4d 832 void (* parms) (char *);
b99bd4ef
NC
833};
834
a737bd4d
NC
835/* Defines for various bits that we will want to toggle. */
836#define INST_IMMEDIATE 0x02000000
837#define OFFSET_REG 0x02000000
838#define HWOFFSET_IMM 0x00400000
839#define SHIFT_BY_REG 0x00000010
840#define PRE_INDEX 0x01000000
841#define INDEX_UP 0x00800000
842#define WRITE_BACK 0x00200000
843#define LDM_TYPE_2_OR_3 0x00400000
90e4755a 844
a737bd4d
NC
845#define LITERAL_MASK 0xf000f000
846#define OPCODE_MASK 0xfe1fffff
847#define V4_STR_BIT 0x00000020
90e4755a 848
a737bd4d 849#define DATA_OP_SHIFT 21
90e4755a 850
a737bd4d
NC
851/* Codes to distinguish the arithmetic instructions. */
852#define OPCODE_AND 0
853#define OPCODE_EOR 1
854#define OPCODE_SUB 2
855#define OPCODE_RSB 3
856#define OPCODE_ADD 4
857#define OPCODE_ADC 5
858#define OPCODE_SBC 6
859#define OPCODE_RSC 7
860#define OPCODE_TST 8
861#define OPCODE_TEQ 9
862#define OPCODE_CMP 10
863#define OPCODE_CMN 11
864#define OPCODE_ORR 12
865#define OPCODE_MOV 13
866#define OPCODE_BIC 14
867#define OPCODE_MVN 15
90e4755a 868
a737bd4d
NC
869#define T_OPCODE_MUL 0x4340
870#define T_OPCODE_TST 0x4200
871#define T_OPCODE_CMN 0x42c0
872#define T_OPCODE_NEG 0x4240
873#define T_OPCODE_MVN 0x43c0
90e4755a 874
a737bd4d
NC
875#define T_OPCODE_ADD_R3 0x1800
876#define T_OPCODE_SUB_R3 0x1a00
877#define T_OPCODE_ADD_HI 0x4400
878#define T_OPCODE_ADD_ST 0xb000
879#define T_OPCODE_SUB_ST 0xb080
880#define T_OPCODE_ADD_SP 0xa800
881#define T_OPCODE_ADD_PC 0xa000
882#define T_OPCODE_ADD_I8 0x3000
883#define T_OPCODE_SUB_I8 0x3800
884#define T_OPCODE_ADD_I3 0x1c00
885#define T_OPCODE_SUB_I3 0x1e00
b99bd4ef 886
a737bd4d
NC
887#define T_OPCODE_ASR_R 0x4100
888#define T_OPCODE_LSL_R 0x4080
889#define T_OPCODE_LSR_R 0x40c0
890#define T_OPCODE_ASR_I 0x1000
891#define T_OPCODE_LSL_I 0x0000
892#define T_OPCODE_LSR_I 0x0800
b99bd4ef 893
a737bd4d
NC
894#define T_OPCODE_MOV_I8 0x2000
895#define T_OPCODE_CMP_I8 0x2800
896#define T_OPCODE_CMP_LR 0x4280
897#define T_OPCODE_MOV_HR 0x4600
898#define T_OPCODE_CMP_HR 0x4500
b99bd4ef 899
a737bd4d
NC
900#define T_OPCODE_LDR_PC 0x4800
901#define T_OPCODE_LDR_SP 0x9800
902#define T_OPCODE_STR_SP 0x9000
903#define T_OPCODE_LDR_IW 0x6800
904#define T_OPCODE_STR_IW 0x6000
905#define T_OPCODE_LDR_IH 0x8800
906#define T_OPCODE_STR_IH 0x8000
907#define T_OPCODE_LDR_IB 0x7800
908#define T_OPCODE_STR_IB 0x7000
909#define T_OPCODE_LDR_RW 0x5800
910#define T_OPCODE_STR_RW 0x5000
911#define T_OPCODE_LDR_RH 0x5a00
912#define T_OPCODE_STR_RH 0x5200
913#define T_OPCODE_LDR_RB 0x5c00
914#define T_OPCODE_STR_RB 0x5400
c9b604bd 915
a737bd4d
NC
916#define T_OPCODE_PUSH 0xb400
917#define T_OPCODE_POP 0xbc00
b99bd4ef 918
a737bd4d 919#define T_OPCODE_BRANCH 0xe7fe
b99bd4ef 920
a737bd4d
NC
921#define THUMB_SIZE 2 /* Size of thumb instruction. */
922#define THUMB_REG_LO 0x1
923#define THUMB_REG_HI 0x2
924#define THUMB_REG_ANY 0x3
90e4755a 925
a737bd4d
NC
926#define THUMB_H1 0x0080
927#define THUMB_H2 0x0040
b99bd4ef 928
a737bd4d
NC
929#define THUMB_ASR 0
930#define THUMB_LSL 1
931#define THUMB_LSR 2
90e4755a 932
a737bd4d
NC
933#define THUMB_MOVE 0
934#define THUMB_COMPARE 1
935#define THUMB_CPY 2
90e4755a 936
a737bd4d
NC
937#define THUMB_LOAD 0
938#define THUMB_STORE 1
90e4755a 939
a737bd4d 940#define THUMB_PP_PC_LR 0x0100
90e4755a 941
a737bd4d
NC
942/* These three are used for immediate shifts, do not alter. */
943#define THUMB_WORD 2
944#define THUMB_HALFWORD 1
945#define THUMB_BYTE 0
90e4755a 946
a737bd4d
NC
947struct thumb_opcode
948{
949 /* Basic string to match. */
950 const char * template;
90e4755a 951
a737bd4d
NC
952 /* Basic instruction code. */
953 unsigned long value;
90e4755a 954
a737bd4d 955 int size;
b99bd4ef
NC
956
957 /* Which CPU variants this exists for. */
90e4755a 958 unsigned long variant;
b99bd4ef
NC
959
960 /* Function to call to parse args. */
a737bd4d 961 void (* parms) (char *);
b99bd4ef
NC
962};
963
f03698e6 964#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 965#define BAD_PC _("r15 not allowed here")
f03698e6 966#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
967#define ERR_NO_ACCUM _("acc0 expected")
968
969static struct hash_control * arm_ops_hsh = NULL;
970static struct hash_control * arm_tops_hsh = NULL;
971static struct hash_control * arm_cond_hsh = NULL;
972static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
973static struct hash_control * arm_psr_hsh = NULL;
974
b99bd4ef
NC
975/* Stuff needed to resolve the label ambiguity
976 As:
977 ...
978 label: <insn>
979 may differ from:
980 ...
981 label:
982 <insn>
983*/
984
985symbolS * last_label_seen;
b34976b6 986static int label_is_thumb_function_name = FALSE;
a737bd4d 987\f
3d0c9500 988/* Literal Pool stuff. */
b99bd4ef
NC
989
990#define MAX_LITERAL_POOL_SIZE 1024
991
3d0c9500
NC
992/* Literal pool structure. Held on a per-section
993 and per-sub-section basis. */
a737bd4d 994
3d0c9500 995typedef struct literal_pool
b99bd4ef 996{
3d0c9500
NC
997 expressionS literals [MAX_LITERAL_POOL_SIZE];
998 unsigned int next_free_entry;
999 unsigned int id;
1000 symbolS * symbol;
1001 segT section;
1002 subsegT sub_section;
61b5f74b 1003 struct literal_pool * next;
3d0c9500 1004} literal_pool;
b99bd4ef 1005
3d0c9500
NC
1006/* Pointer to a linked list of literal pools. */
1007literal_pool * list_of_pools = NULL;
b99bd4ef 1008
3d0c9500 1009static literal_pool *
a737bd4d 1010find_literal_pool (void)
3d0c9500
NC
1011{
1012 literal_pool * pool;
1013
1014 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1015 {
1016 if (pool->section == now_seg
1017 && pool->sub_section == now_subseg)
1018 break;
1019 }
1020
1021 return pool;
1022}
b99bd4ef 1023
3d0c9500 1024static literal_pool *
a737bd4d 1025find_or_make_literal_pool (void)
3d0c9500
NC
1026{
1027 /* Next literal pool ID number. */
1028 static unsigned int latest_pool_num = 1;
1029 literal_pool * pool;
1030
1031 pool = find_literal_pool ();
b99bd4ef 1032
3d0c9500
NC
1033 if (pool == NULL)
1034 {
1035 /* Create a new pool. */
a737bd4d 1036 pool = xmalloc (sizeof (* pool));
3d0c9500
NC
1037 if (! pool)
1038 return NULL;
1039
1040 pool->next_free_entry = 0;
1041 pool->section = now_seg;
1042 pool->sub_section = now_subseg;
1043 pool->next = list_of_pools;
1044 pool->symbol = NULL;
1045
1046 /* Add it to the list. */
1047 list_of_pools = pool;
1048 }
1049
1050 /* New pools, and emptied pools, will have a NULL symbol. */
1051 if (pool->symbol == NULL)
1052 {
1053 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1054 (valueT) 0, &zero_address_frag);
1055 pool->id = latest_pool_num ++;
1056 }
1057
1058 /* Done. */
1059 return pool;
1060}
1061
1062/* Add the literal in the global 'inst'
1063 structure to the relevent literal pool. */
a737bd4d 1064
b99bd4ef 1065static int
a737bd4d 1066add_to_lit_pool (void)
b99bd4ef 1067{
61b5f74b 1068 literal_pool * pool;
3d0c9500 1069 unsigned int entry;
b99bd4ef 1070
3d0c9500 1071 pool = find_or_make_literal_pool ();
b99bd4ef 1072
3d0c9500
NC
1073 /* Check if this literal value is already in the pool. */
1074 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1075 {
3d0c9500
NC
1076 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1077 && (inst.reloc.exp.X_op == O_constant)
1078 && (pool->literals[entry].X_add_number
b99bd4ef 1079 == inst.reloc.exp.X_add_number)
3d0c9500
NC
1080 && (pool->literals[entry].X_unsigned
1081 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
1082 break;
1083
3d0c9500
NC
1084 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1085 && (inst.reloc.exp.X_op == O_symbol)
1086 && (pool->literals[entry].X_add_number
b99bd4ef 1087 == inst.reloc.exp.X_add_number)
3d0c9500 1088 && (pool->literals[entry].X_add_symbol
b99bd4ef 1089 == inst.reloc.exp.X_add_symbol)
3d0c9500 1090 && (pool->literals[entry].X_op_symbol
b99bd4ef 1091 == inst.reloc.exp.X_op_symbol))
3d0c9500 1092 break;
b99bd4ef
NC
1093 }
1094
3d0c9500
NC
1095 /* Do we need to create a new entry? */
1096 if (entry == pool->next_free_entry)
b99bd4ef 1097 {
3d0c9500 1098 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 1099 {
ed71e111 1100 inst.error = _("literal pool overflow");
b99bd4ef
NC
1101 return FAIL;
1102 }
1103
3d0c9500
NC
1104 pool->literals[entry] = inst.reloc.exp;
1105 pool->next_free_entry += 1;
b99bd4ef
NC
1106 }
1107
3d0c9500 1108 inst.reloc.exp.X_op = O_symbol;
08df2379 1109 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 1110 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
1111
1112 return SUCCESS;
1113}
1114
1115/* Can't use symbol_new here, so have to create a symbol and then at
1116 a later date assign it a value. Thats what these functions do. */
1117
1118static void
a737bd4d
NC
1119symbol_locate (symbolS * symbolP,
1120 const char * name, /* It is copied, the caller can modify. */
1121 segT segment, /* Segment identifier (SEG_<something>). */
1122 valueT valu, /* Symbol value. */
1123 fragS * frag) /* Associated fragment. */
b99bd4ef
NC
1124{
1125 unsigned int name_length;
1126 char * preserved_copy_of_name;
1127
1128 name_length = strlen (name) + 1; /* +1 for \0. */
1129 obstack_grow (&notes, name, name_length);
1130 preserved_copy_of_name = obstack_finish (&notes);
1131#ifdef STRIP_UNDERSCORE
1132 if (preserved_copy_of_name[0] == '_')
1133 preserved_copy_of_name++;
1134#endif
1135
1136#ifdef tc_canonicalize_symbol_name
1137 preserved_copy_of_name =
1138 tc_canonicalize_symbol_name (preserved_copy_of_name);
1139#endif
1140
1141 S_SET_NAME (symbolP, preserved_copy_of_name);
1142
1143 S_SET_SEGMENT (symbolP, segment);
1144 S_SET_VALUE (symbolP, valu);
c62e1cc3 1145 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
1146
1147 symbol_set_frag (symbolP, frag);
1148
1149 /* Link to end of symbol chain. */
1150 {
1151 extern int symbol_table_frozen;
a737bd4d 1152
b99bd4ef
NC
1153 if (symbol_table_frozen)
1154 abort ();
1155 }
1156
1157 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1158
1159 obj_symbol_new_hook (symbolP);
1160
1161#ifdef tc_symbol_new_hook
1162 tc_symbol_new_hook (symbolP);
1163#endif
1164
1165#ifdef DEBUG_SYMS
1166 verify_symbol_chain (symbol_rootP, symbol_lastP);
1167#endif /* DEBUG_SYMS */
1168}
1169
1170/* Check that an immediate is valid.
1171 If so, convert it to the right format. */
1172
1173static unsigned int
a737bd4d 1174validate_immediate (unsigned int val)
b99bd4ef
NC
1175{
1176 unsigned int a;
1177 unsigned int i;
1178
1179#define rotate_left(v, n) (v << n | v >> (32 - n))
1180
1181 for (i = 0; i < 32; i += 2)
1182 if ((a = rotate_left (val, i)) <= 0xff)
1183 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1184
1185 return FAIL;
1186}
1187
2d2255b5 1188/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
1189 values, added together. We already know that this value cannot be
1190 computed by just one ARM instruction. */
1191
1192static unsigned int
a737bd4d
NC
1193validate_immediate_twopart (unsigned int val,
1194 unsigned int * highpart)
b99bd4ef
NC
1195{
1196 unsigned int a;
1197 unsigned int i;
1198
1199 for (i = 0; i < 32; i += 2)
1200 if (((a = rotate_left (val, i)) & 0xff) != 0)
1201 {
1202 if (a & 0xff00)
1203 {
1204 if (a & ~ 0xffff)
1205 continue;
1206 * highpart = (a >> 8) | ((i + 24) << 7);
1207 }
1208 else if (a & 0xff0000)
1209 {
1210 if (a & 0xff000000)
1211 continue;
1212 * highpart = (a >> 16) | ((i + 16) << 7);
1213 }
1214 else
1215 {
1216 assert (a & 0xff000000);
1217 * highpart = (a >> 24) | ((i + 8) << 7);
1218 }
1219
1220 return (a & 0xff) | (i << 7);
1221 }
1222
1223 return FAIL;
1224}
1225
1226static int
a737bd4d 1227validate_offset_imm (unsigned int val, int hwse)
b99bd4ef
NC
1228{
1229 if ((hwse && val > 255) || val > 4095)
1230 return FAIL;
1231 return val;
1232}
1233
6057a28f
NC
1234\f
1235#ifdef OBJ_ELF
6057a28f
NC
1236/* This code is to handle mapping symbols as defined in the ARM ELF spec.
1237 (This text is taken from version B-02 of the spec):
1238
1239 4.4.7 Mapping and tagging symbols
1240
1241 A section of an ARM ELF file can contain a mixture of ARM code,
1242 Thumb code, and data. There are inline transitions between code
1243 and data at literal pool boundaries. There can also be inline
1244 transitions between ARM code and Thumb code, for example in
1245 ARM-Thumb inter-working veneers. Linkers, machine-level
1246 debuggers, profiling tools, and disassembly tools need to map
1247 images accurately. For example, setting an ARM breakpoint on a
1248 Thumb location, or in a literal pool, can crash the program
1249 being debugged, ruining the debugging session.
1250
1251 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1252 tagged (see section 4.4.7.2 below) using local symbols (with
1253 binding STB_LOCAL). To assist consumers, mapping and tagging
1254 symbols should be collated first in the symbol table, before
1255 other symbols with binding STB_LOCAL.
1256
1257 To allow properly collated mapping and tagging symbols to be
1258 skipped by consumers that have no interest in them, the first
1259 such symbol should have the name $m and its st_value field equal
1260 to the total number of mapping and tagging symbols (including
1261 the $m) in the symbol table.
1262
1263 4.4.7.1 Mapping symbols
1264
1265 $a Labels the first byte of a sequence of ARM instructions.
1266 Its type is STT_FUNC.
1267
1268 $d Labels the first byte of a sequence of data items.
1269 Its type is STT_OBJECT.
1270
1271 $t Labels the first byte of a sequence of Thumb instructions.
1272 Its type is STT_FUNC.
1273
1274 This list of mapping symbols may be extended in the future.
1275
1276 Section-relative mapping symbols
1277
1278 Mapping symbols defined in a section define a sequence of
1279 half-open address intervals that cover the address range of the
1280 section. Each interval starts at the address defined by a
1281 mapping symbol, and continues up to, but not including, the
1282 address defined by the next (in address order) mapping symbol or
1283 the end of the section. A corollary is that there must be a
1284 mapping symbol defined at the beginning of each section.
1285 Consumers can ignore the size of a section-relative mapping
1286 symbol. Producers can set it to 0.
1287
1288 Absolute mapping symbols
1289
1290 Because of the need to crystallize a Thumb address with the
1291 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1292 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1293 or $t.
1294
1295 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1296 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1297 where [x, y) denotes the half-open address range from x,
1298 inclusive, to y, exclusive.
1299
1300 In the absence of a mapping symbol, a consumer can interpret a
1301 function symbol with an odd value as the Thumb code address
1302 obtained by clearing the least significant bit of the
1303 value. This interpretation is deprecated, and it may not work in
1304 the future.
1305
1306 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1307 the EABI (which is still under development), so they are not
1308 implemented here. */
1309
69b97547
NC
1310static enum mstate mapstate = MAP_UNDEFINED;
1311
6057a28f
NC
1312static void
1313mapping_state (enum mstate state)
1314{
6057a28f
NC
1315 symbolS * symbolP;
1316 const char * symname;
1317 int type;
1318
1319 if (mapstate == state)
1320 /* The mapping symbol has already been emitted.
1321 There is nothing else to do. */
1322 return;
1323
1324 mapstate = state;
1325
1326 switch (state)
1327 {
1328 case MAP_DATA:
1329 symname = "$d";
1330 type = BSF_OBJECT;
1331 break;
1332 case MAP_ARM:
1333 symname = "$a";
1334 type = BSF_FUNCTION;
1335 break;
1336 case MAP_THUMB:
1337 symname = "$t";
1338 type = BSF_FUNCTION;
1339 break;
69b97547 1340 case MAP_UNDEFINED:
a737bd4d 1341 return;
6057a28f
NC
1342 default:
1343 abort ();
1344 }
1345
69b97547
NC
1346 seg_info (now_seg)->tc_segment_info_data = state;
1347
6057a28f
NC
1348 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1349 symbol_table_insert (symbolP);
1350 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
a737bd4d 1351
6057a28f
NC
1352 switch (state)
1353 {
1354 case MAP_ARM:
1355 THUMB_SET_FUNC (symbolP, 0);
1356 ARM_SET_THUMB (symbolP, 0);
1357 ARM_SET_INTERWORK (symbolP, support_interwork);
1358 break;
a737bd4d 1359
6057a28f
NC
1360 case MAP_THUMB:
1361 THUMB_SET_FUNC (symbolP, 1);
1362 ARM_SET_THUMB (symbolP, 1);
1363 ARM_SET_INTERWORK (symbolP, support_interwork);
1364 break;
a737bd4d 1365
6057a28f
NC
1366 case MAP_DATA:
1367 default:
1368 return;
1369 }
1370}
1371
a737bd4d
NC
1372/* When we change sections we need to issue a new mapping symbol. */
1373
1374void
1375arm_elf_change_section (void)
1376{
1377 flagword flags;
1378
40a18ebd
NC
1379 /* Link an unlinked unwind index table section to the .text section. */
1380 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1381 && elf_linked_to_section (now_seg) == NULL)
1382 elf_linked_to_section (now_seg) = text_section;
1383
a737bd4d
NC
1384 if (!SEG_NORMAL (now_seg))
1385 return;
1386
1387 flags = bfd_get_section_flags (stdoutput, now_seg);
1388
1389 /* We can ignore sections that only contain debug info. */
1390 if ((flags & SEC_ALLOC) == 0)
1391 return;
1392
1393 mapstate = seg_info (now_seg)->tc_segment_info_data;
1394}
40a18ebd
NC
1395
1396int
1397arm_elf_section_type (const char * str, size_t len)
1398{
1399 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1400 return SHT_ARM_EXIDX;
1401
1402 return -1;
1403}
a737bd4d
NC
1404#else
1405#define mapping_state(a)
1406#endif /* OBJ_ELF */
1407\f
1408/* arm_reg_parse () := if it looks like a register, return its token and
1409 advance the pointer. */
1410
1411static int
1412arm_reg_parse (char ** ccp, struct hash_control * htab)
1413{
1414 char * start = * ccp;
1415 char c;
1416 char * p;
1417 struct reg_entry * reg;
1418
1419#ifdef REGISTER_PREFIX
1420 if (*start != REGISTER_PREFIX)
1421 return FAIL;
1422 p = start + 1;
1423#else
1424 p = start;
1425#ifdef OPTIONAL_REGISTER_PREFIX
1426 if (*p == OPTIONAL_REGISTER_PREFIX)
1427 p++, start++;
1428#endif
1429#endif
1430 if (!ISALPHA (*p) || !is_name_beginner (*p))
1431 return FAIL;
1432
1433 c = *p++;
1434 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1435 c = *p++;
1436
1437 *--p = 0;
1438 reg = (struct reg_entry *) hash_find (htab, start);
1439 *p = c;
1440
1441 if (reg)
1442 {
1443 *ccp = p;
1444 return reg->number;
1445 }
1446
1447 return FAIL;
1448}
1449
1450/* Search for the following register name in each of the possible reg name
1451 tables. Return the classification if found, or REG_TYPE_MAX if not
1452 present. */
6057a28f 1453
a737bd4d
NC
1454static enum arm_reg_type
1455arm_reg_parse_any (char *cp)
6057a28f 1456{
a737bd4d 1457 int i;
6057a28f 1458
a737bd4d
NC
1459 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1460 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1461 return (enum arm_reg_type) i;
6057a28f 1462
a737bd4d
NC
1463 return REG_TYPE_MAX;
1464}
6057a28f 1465
a737bd4d
NC
1466static void
1467opcode_select (int width)
1468{
1469 switch (width)
1470 {
1471 case 16:
1472 if (! thumb_mode)
1473 {
1474 if (! (cpu_variant & ARM_EXT_V4T))
1475 as_bad (_("selected processor does not support THUMB opcodes"));
6057a28f 1476
a737bd4d
NC
1477 thumb_mode = 1;
1478 /* No need to force the alignment, since we will have been
1479 coming from ARM mode, which is word-aligned. */
1480 record_alignment (now_seg, 1);
1481 }
1482 mapping_state (MAP_THUMB);
1483 break;
1484
1485 case 32:
1486 if (thumb_mode)
1487 {
1488 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1489 as_bad (_("selected processor does not support ARM opcodes"));
1490
1491 thumb_mode = 0;
1492
1493 if (!need_pass_2)
1494 frag_align (2, 0, 0);
1495
1496 record_alignment (now_seg, 1);
1497 }
1498 mapping_state (MAP_ARM);
1499 break;
1500
1501 default:
1502 as_bad (_("invalid instruction size selected (%d)"), width);
1503 }
6057a28f 1504}
6057a28f 1505
b99bd4ef 1506static void
a737bd4d 1507s_req (int a ATTRIBUTE_UNUSED)
b99bd4ef 1508{
f03698e6 1509 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
1510}
1511
0bbf2aa4
NC
1512/* The .unreq directive deletes an alias which was previously defined
1513 by .req. For example:
1514
1515 my_alias .req r11
1516 .unreq my_alias */
1517
1518static void
1519s_unreq (int a ATTRIBUTE_UNUSED)
1520{
a737bd4d 1521 char * name;
0bbf2aa4
NC
1522 char saved_char;
1523
1524 skip_whitespace (input_line_pointer);
1525 name = input_line_pointer;
1526
1527 while (*input_line_pointer != 0
1528 && *input_line_pointer != ' '
1529 && *input_line_pointer != '\n')
1530 ++input_line_pointer;
1531
1532 saved_char = *input_line_pointer;
1533 *input_line_pointer = 0;
1534
1535 if (*name)
1536 {
1537 enum arm_reg_type req_type = arm_reg_parse_any (name);
1538
1539 if (req_type != REG_TYPE_MAX)
1540 {
1541 char *temp_name = name;
1542 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1543
1544 if (req_no != FAIL)
1545 {
1546 struct reg_entry *req_entry;
1547
1548 /* Check to see if this alias is a builtin one. */
1549 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1550
1551 if (!req_entry)
1552 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1553 else if (req_entry->builtin)
67c1ffbe 1554 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
1555 points to a const data structure, so we only need to
1556 free up the memory used by the key in the hash table.
1557 Unfortunately we have not recorded this value, so this
1558 is a memory leak. */
1559 /* FIXME: Should we issue a warning message ? */
1560 ;
1561 else
1562 {
67c1ffbe 1563 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
1564 key and the value, but fortunately the key is the same
1565 as the value->name field. */
1566 free ((char *) req_entry->name);
1567 free (req_entry);
1568 }
1569 }
1570 else
1571 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1572 }
1573 else
1574 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1575 }
1576 else
1577 as_bad (_("invalid syntax for .unreq directive"));
1578
1579 *input_line_pointer = saved_char;
1580 demand_empty_rest_of_line ();
1581}
1582
b99bd4ef 1583static void
a737bd4d 1584s_bss (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1585{
1586 /* We don't support putting frags in the BSS segment, we fake it by
1587 marking in_bss, then looking at s_skip for clues. */
1588 subseg_set (bss_section, 0);
1589 demand_empty_rest_of_line ();
6057a28f 1590 mapping_state (MAP_DATA);
b99bd4ef
NC
1591}
1592
1593static void
a737bd4d 1594s_even (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1595{
1596 /* Never make frag if expect extra pass. */
1597 if (!need_pass_2)
1598 frag_align (1, 0, 0);
1599
1600 record_alignment (now_seg, 1);
1601
1602 demand_empty_rest_of_line ();
1603}
1604
1605static void
a737bd4d 1606s_ltorg (int ignored ATTRIBUTE_UNUSED)
b99bd4ef 1607{
3d0c9500
NC
1608 unsigned int entry;
1609 literal_pool * pool;
b99bd4ef
NC
1610 char sym_name[20];
1611
3d0c9500
NC
1612 pool = find_literal_pool ();
1613 if (pool == NULL
1614 || pool->symbol == NULL
1615 || pool->next_free_entry == 0)
b99bd4ef
NC
1616 return;
1617
69b97547
NC
1618 mapping_state (MAP_DATA);
1619
b99bd4ef
NC
1620 /* Align pool as you have word accesses.
1621 Only make a frag if we have to. */
1622 if (!need_pass_2)
1623 frag_align (2, 0, 0);
1624
1625 record_alignment (now_seg, 2);
1626
3d0c9500 1627 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 1628
3d0c9500 1629 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 1630 (valueT) frag_now_fix (), frag_now);
3d0c9500 1631 symbol_table_insert (pool->symbol);
b99bd4ef 1632
3d0c9500 1633 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
1634
1635#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 1636 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
1637#endif
1638
3d0c9500 1639 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1640 /* First output the expression in the instruction to the pool. */
3d0c9500 1641 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 1642
3d0c9500
NC
1643 /* Mark the pool as empty. */
1644 pool->next_free_entry = 0;
1645 pool->symbol = NULL;
b99bd4ef
NC
1646}
1647
1648/* Same as s_align_ptwo but align 0 => align 2. */
1649
1650static void
a737bd4d 1651s_align (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1652{
a737bd4d
NC
1653 int temp;
1654 long temp_fill;
b99bd4ef
NC
1655 long max_alignment = 15;
1656
1657 temp = get_absolute_expression ();
1658 if (temp > max_alignment)
f03698e6 1659 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
1660 else if (temp < 0)
1661 {
f03698e6 1662 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
1663 temp = 0;
1664 }
1665
1666 if (*input_line_pointer == ',')
1667 {
1668 input_line_pointer++;
1669 temp_fill = get_absolute_expression ();
1670 }
1671 else
1672 temp_fill = 0;
1673
1674 if (!temp)
1675 temp = 2;
1676
1677 /* Only make a frag if we HAVE to. */
1678 if (temp && !need_pass_2)
1679 frag_align (temp, (int) temp_fill, 0);
1680 demand_empty_rest_of_line ();
1681
1682 record_alignment (now_seg, temp);
1683}
1684
1685static void
a737bd4d 1686s_force_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1687{
1688 /* If we are not already in thumb mode go into it, EVEN if
1689 the target processor does not support thumb instructions.
1690 This is used by gcc/config/arm/lib1funcs.asm for example
1691 to compile interworking support functions even if the
1692 target processor should not support interworking. */
1693 if (! thumb_mode)
1694 {
1695 thumb_mode = 2;
1696
1697 record_alignment (now_seg, 1);
1698 }
1699
1700 demand_empty_rest_of_line ();
1701}
1702
1703static void
a737bd4d 1704s_thumb_func (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1705{
1706 if (! thumb_mode)
1707 opcode_select (16);
1708
1709 /* The following label is the name/address of the start of a Thumb function.
1710 We need to know this for the interworking support. */
b34976b6 1711 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
1712
1713 demand_empty_rest_of_line ();
1714}
1715
1716/* Perform a .set directive, but also mark the alias as
1717 being a thumb function. */
1718
1719static void
a737bd4d 1720s_thumb_set (int equiv)
b99bd4ef
NC
1721{
1722 /* XXX the following is a duplicate of the code for s_set() in read.c
1723 We cannot just call that code as we need to get at the symbol that
1724 is created. */
a737bd4d
NC
1725 char * name;
1726 char delim;
1727 char * end_name;
1728 symbolS * symbolP;
b99bd4ef
NC
1729
1730 /* Especial apologies for the random logic:
1731 This just grew, and could be parsed much more simply!
1732 Dean - in haste. */
1733 name = input_line_pointer;
1734 delim = get_symbol_end ();
1735 end_name = input_line_pointer;
1736 *end_name = delim;
1737
1738 SKIP_WHITESPACE ();
1739
1740 if (*input_line_pointer != ',')
1741 {
1742 *end_name = 0;
f03698e6 1743 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
1744 *end_name = delim;
1745 ignore_rest_of_line ();
1746 return;
1747 }
1748
1749 input_line_pointer++;
1750 *end_name = 0;
1751
1752 if (name[0] == '.' && name[1] == '\0')
1753 {
1754 /* XXX - this should not happen to .thumb_set. */
1755 abort ();
1756 }
1757
1758 if ((symbolP = symbol_find (name)) == NULL
1759 && (symbolP = md_undefined_symbol (name)) == NULL)
1760 {
1761#ifndef NO_LISTING
1762 /* When doing symbol listings, play games with dummy fragments living
1763 outside the normal fragment chain to record the file and line info
1764 for this symbol. */
1765 if (listing & LISTING_SYMBOLS)
1766 {
1767 extern struct list_info_struct * listing_tail;
a737bd4d 1768 fragS * dummy_frag = xmalloc (sizeof (fragS));
b99bd4ef
NC
1769
1770 memset (dummy_frag, 0, sizeof (fragS));
1771 dummy_frag->fr_type = rs_fill;
1772 dummy_frag->line = listing_tail;
1773 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1774 dummy_frag->fr_symbol = symbolP;
1775 }
1776 else
1777#endif
1778 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1779
1780#ifdef OBJ_COFF
1781 /* "set" symbols are local unless otherwise specified. */
1782 SF_SET_LOCAL (symbolP);
1783#endif /* OBJ_COFF */
1784 } /* Make a new symbol. */
1785
1786 symbol_table_insert (symbolP);
1787
1788 * end_name = delim;
1789
1790 if (equiv
1791 && S_IS_DEFINED (symbolP)
1792 && S_GET_SEGMENT (symbolP) != reg_section)
1793 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1794
1795 pseudo_set (symbolP);
1796
1797 demand_empty_rest_of_line ();
1798
1799 /* XXX Now we come to the Thumb specific bit of code. */
1800
1801 THUMB_SET_FUNC (symbolP, 1);
1802 ARM_SET_THUMB (symbolP, 1);
1803#if defined OBJ_ELF || defined OBJ_COFF
1804 ARM_SET_INTERWORK (symbolP, support_interwork);
1805#endif
1806}
1807
b99bd4ef 1808static void
a737bd4d 1809s_arm (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1810{
1811 opcode_select (32);
1812 demand_empty_rest_of_line ();
1813}
1814
1815static void
a737bd4d 1816s_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1817{
1818 opcode_select (16);
1819 demand_empty_rest_of_line ();
1820}
1821
1822static void
a737bd4d 1823s_code (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1824{
a737bd4d 1825 int temp;
b99bd4ef
NC
1826
1827 temp = get_absolute_expression ();
1828 switch (temp)
1829 {
1830 case 16:
1831 case 32:
1832 opcode_select (temp);
1833 break;
1834
1835 default:
1836 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1837 }
1838}
1839
1840static void
a737bd4d 1841end_of_line (char * str)
b99bd4ef
NC
1842{
1843 skip_whitespace (str);
1844
f03698e6
RE
1845 if (*str != '\0' && !inst.error)
1846 inst.error = _("garbage following instruction");
b99bd4ef
NC
1847}
1848
1849static int
a737bd4d 1850skip_past_comma (char ** str)
b99bd4ef
NC
1851{
1852 char * p = * str, c;
1853 int comma = 0;
1854
1855 while ((c = *p) == ' ' || c == ',')
1856 {
1857 p++;
1858 if (c == ',' && comma++)
1859 return FAIL;
1860 }
1861
1862 if (c == '\0')
1863 return FAIL;
1864
1865 *str = p;
1866 return comma ? SUCCESS : FAIL;
1867}
1868
a737bd4d
NC
1869/* Return TRUE if anything in the expression is a bignum. */
1870
1871static int
1872walk_no_bignums (symbolS * sp)
1873{
1874 if (symbol_get_value_expression (sp)->X_op == O_big)
1875 return 1;
1876
1877 if (symbol_get_value_expression (sp)->X_add_symbol)
1878 {
1879 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1880 || (symbol_get_value_expression (sp)->X_op_symbol
1881 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1882 }
1883
1884 return 0;
1885}
1886
1887static int in_my_get_expression = 0;
1888
1889static int
1890my_get_expression (expressionS * ep, char ** str)
1891{
1892 char * save_in;
1893 segT seg;
1894
1895 save_in = input_line_pointer;
1896 input_line_pointer = *str;
1897 in_my_get_expression = 1;
1898 seg = expression (ep);
1899 in_my_get_expression = 0;
1900
1901 if (ep->X_op == O_illegal)
1902 {
1903 /* We found a bad expression in md_operand(). */
1904 *str = input_line_pointer;
1905 input_line_pointer = save_in;
1906 return 1;
1907 }
1908
1909#ifdef OBJ_AOUT
1910 if (seg != absolute_section
1911 && seg != text_section
1912 && seg != data_section
1913 && seg != bss_section
1914 && seg != undefined_section)
1915 {
1916 inst.error = _("bad_segment");
1917 *str = input_line_pointer;
1918 input_line_pointer = save_in;
1919 return 1;
1920 }
1921#endif
1922
1923 /* Get rid of any bignums now, so that we don't generate an error for which
1924 we can't establish a line number later on. Big numbers are never valid
1925 in instructions, which is where this routine is always called. */
1926 if (ep->X_op == O_big
1927 || (ep->X_add_symbol
1928 && (walk_no_bignums (ep->X_add_symbol)
1929 || (ep->X_op_symbol
1930 && walk_no_bignums (ep->X_op_symbol)))))
1931 {
1932 inst.error = _("invalid constant");
1933 *str = input_line_pointer;
1934 input_line_pointer = save_in;
1935 return 1;
1936 }
1937
1938 *str = input_line_pointer;
1939 input_line_pointer = save_in;
1940 return 0;
1941}
1942
b99bd4ef
NC
1943/* A standard register must be given at this point.
1944 SHIFT is the place to put it in inst.instruction.
1945 Restores input start point on error.
1946 Returns the reg#, or FAIL. */
1947
1948static int
a737bd4d 1949reg_required_here (char ** str, int shift)
b99bd4ef
NC
1950{
1951 static char buff [128]; /* XXX */
1952 int reg;
1953 char * start = * str;
1954
6c43fab6 1955 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
1956 {
1957 if (shift >= 0)
1958 inst.instruction |= reg << shift;
1959 return reg;
1960 }
1961
1962 /* Restore the start point, we may have got a reg of the wrong class. */
1963 *str = start;
1964
1965 /* In the few cases where we might be able to accept something else
1966 this error can be overridden. */
f03698e6 1967 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
1968 inst.error = buff;
1969
1970 return FAIL;
1971}
1972
5a6c6817 1973/* A Intel Wireless MMX technology register
e16bb312
NC
1974 must be given at this point.
1975 Shift is the place to put it in inst.instruction.
1976 Restores input start point on err.
1977 Returns the reg#, or FAIL. */
1978
1979static int
a737bd4d
NC
1980wreg_required_here (char ** str,
1981 int shift,
1982 enum wreg_type reg_type)
e16bb312
NC
1983{
1984 static char buff [128];
1985 int reg;
1986 char * start = *str;
1987
1988 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
1989 {
1990 if (wr_register (reg)
1991 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
1992 {
1993 if (shift >= 0)
1994 inst.instruction |= (reg ^ WR_PREFIX) << shift;
1995 return reg;
1996 }
1997 else if (wc_register (reg)
1998 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
1999 {
2000 if (shift >= 0)
2001 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2002 return reg;
2003 }
2004 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2005 {
2006 if (shift >= 0)
2007 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2008 return reg;
2009 }
2010 }
2011
2012 /* Restore the start point, we may have got a reg of the wrong class. */
2013 *str = start;
2014
2015 /* In the few cases where we might be able to accept
2016 something else this error can be overridden. */
5a6c6817 2017 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
2018 inst.error = buff;
2019
2020 return FAIL;
2021}
2022
05d2d07e 2023static const struct asm_psr *
a737bd4d 2024arm_psr_parse (char ** ccp)
b99bd4ef
NC
2025{
2026 char * start = * ccp;
2027 char c;
2028 char * p;
05d2d07e 2029 const struct asm_psr * psr;
b99bd4ef
NC
2030
2031 p = start;
2032
2033 /* Skip to the end of the next word in the input stream. */
2034 do
2035 {
2036 c = *p++;
2037 }
3882b010 2038 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2039
2040 /* Terminate the word. */
2041 *--p = 0;
2042
2043 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2044 feature for ease of use and backwards compatibility. */
2045 if (!strncmp (start, "cpsr", 4))
2046 strncpy (start, "CPSR", 4);
2047 else if (!strncmp (start, "spsr", 4))
2048 strncpy (start, "SPSR", 4);
2049
2050 /* Now locate the word in the psr hash table. */
05d2d07e 2051 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
2052
2053 /* Restore the input stream. */
2054 *p = c;
2055
2056 /* If we found a valid match, advance the
2057 stream pointer past the end of the word. */
2058 *ccp = p;
2059
2060 return psr;
2061}
2062
2063/* Parse the input looking for a PSR flag. */
2064
2065static int
a737bd4d 2066psr_required_here (char ** str)
b99bd4ef
NC
2067{
2068 char * start = * str;
05d2d07e 2069 const struct asm_psr * psr;
b99bd4ef
NC
2070
2071 psr = arm_psr_parse (str);
2072
2073 if (psr)
2074 {
2075 /* If this is the SPSR that is being modified, set the R bit. */
2076 if (! psr->cpsr)
2077 inst.instruction |= SPSR_BIT;
2078
2079 /* Set the psr flags in the MSR instruction. */
2080 inst.instruction |= psr->field << PSR_SHIFT;
2081
2082 return SUCCESS;
2083 }
2084
2085 /* In the few cases where we might be able to accept
2086 something else this error can be overridden. */
2087 inst.error = _("flag for {c}psr instruction expected");
2088
2089 /* Restore the start point. */
2090 *str = start;
2091 return FAIL;
2092}
2093
2094static int
a737bd4d 2095co_proc_number (char ** str)
b99bd4ef
NC
2096{
2097 int processor, pchar;
6c43fab6 2098 char *start;
b99bd4ef 2099
6c43fab6
RE
2100 skip_whitespace (*str);
2101 start = *str;
b99bd4ef
NC
2102
2103 /* The data sheet seems to imply that just a number on its own is valid
2104 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2105 accept either. */
6c43fab6
RE
2106 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2107 == FAIL)
b99bd4ef 2108 {
6c43fab6
RE
2109 *str = start;
2110
2111 pchar = *(*str)++;
2112 if (pchar >= '0' && pchar <= '9')
b99bd4ef 2113 {
6c43fab6
RE
2114 processor = pchar - '0';
2115 if (**str >= '0' && **str <= '9')
b99bd4ef 2116 {
6c43fab6
RE
2117 processor = processor * 10 + *(*str)++ - '0';
2118 if (processor > 15)
2119 {
f03698e6 2120 inst.error = _("illegal co-processor number");
6c43fab6
RE
2121 return FAIL;
2122 }
b99bd4ef
NC
2123 }
2124 }
6c43fab6
RE
2125 else
2126 {
376eb240 2127 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
2128 return FAIL;
2129 }
b99bd4ef
NC
2130 }
2131
2132 inst.instruction |= processor << 8;
2133 return SUCCESS;
2134}
2135
2136static int
a737bd4d 2137cp_opc_expr (char ** str, int where, int length)
b99bd4ef
NC
2138{
2139 expressionS expr;
2140
2141 skip_whitespace (* str);
2142
2143 memset (&expr, '\0', sizeof (expr));
2144
2145 if (my_get_expression (&expr, str))
2146 return FAIL;
2147 if (expr.X_op != O_constant)
2148 {
2149 inst.error = _("bad or missing expression");
2150 return FAIL;
2151 }
2152
2153 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2154 {
2155 inst.error = _("immediate co-processor expression too large");
2156 return FAIL;
2157 }
2158
2159 inst.instruction |= expr.X_add_number << where;
2160 return SUCCESS;
2161}
2162
2163static int
a737bd4d 2164cp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2165{
2166 int reg;
2167 char * start = *str;
2168
6c43fab6 2169 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 2170 {
b99bd4ef
NC
2171 inst.instruction |= reg << where;
2172 return reg;
2173 }
2174
2175 /* In the few cases where we might be able to accept something else
2176 this error can be overridden. */
376eb240 2177 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
2178
2179 /* Restore the start point. */
2180 *str = start;
2181 return FAIL;
2182}
2183
2184static int
a737bd4d 2185fp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2186{
2187 int reg;
2188 char * start = * str;
2189
6c43fab6 2190 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 2191 {
b99bd4ef
NC
2192 inst.instruction |= reg << where;
2193 return reg;
2194 }
2195
2196 /* In the few cases where we might be able to accept something else
2197 this error can be overridden. */
376eb240 2198 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
2199
2200 /* Restore the start point. */
2201 *str = start;
2202 return FAIL;
2203}
2204
2205static int
a737bd4d 2206cp_address_offset (char ** str)
b99bd4ef
NC
2207{
2208 int offset;
2209
2210 skip_whitespace (* str);
2211
2212 if (! is_immediate_prefix (**str))
2213 {
2214 inst.error = _("immediate expression expected");
2215 return FAIL;
2216 }
2217
2218 (*str)++;
2219
2220 if (my_get_expression (& inst.reloc.exp, str))
2221 return FAIL;
2222
2223 if (inst.reloc.exp.X_op == O_constant)
2224 {
2225 offset = inst.reloc.exp.X_add_number;
2226
2227 if (offset & 3)
2228 {
2229 inst.error = _("co-processor address must be word aligned");
2230 return FAIL;
2231 }
2232
2233 if (offset > 1023 || offset < -1023)
2234 {
2235 inst.error = _("offset too large");
2236 return FAIL;
2237 }
2238
2239 if (offset >= 0)
2240 inst.instruction |= INDEX_UP;
2241 else
2242 offset = -offset;
2243
2244 inst.instruction |= offset >> 2;
2245 }
2246 else
2247 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2248
2249 return SUCCESS;
2250}
2251
2252static int
a737bd4d 2253cp_address_required_here (char ** str, int wb_ok)
b99bd4ef
NC
2254{
2255 char * p = * str;
2256 int pre_inc = 0;
2257 int write_back = 0;
2258
2259 if (*p == '[')
2260 {
2261 int reg;
2262
2263 p++;
2264 skip_whitespace (p);
2265
2266 if ((reg = reg_required_here (& p, 16)) == FAIL)
2267 return FAIL;
2268
2269 skip_whitespace (p);
2270
2271 if (*p == ']')
2272 {
2273 p++;
2274
f02232aa
NC
2275 skip_whitespace (p);
2276
2277 if (*p == '\0')
b99bd4ef 2278 {
f02232aa 2279 /* As an extension to the official ARM syntax we allow:
f02232aa 2280 [Rn]
f02232aa 2281 as a short hand for:
f02232aa
NC
2282 [Rn,#0] */
2283 inst.instruction |= PRE_INDEX | INDEX_UP;
2284 *str = p;
2285 return SUCCESS;
2286 }
a737bd4d 2287
f02232aa
NC
2288 if (skip_past_comma (& p) == FAIL)
2289 {
2290 inst.error = _("comma expected after closing square bracket");
2291 return FAIL;
2292 }
b99bd4ef 2293
f02232aa
NC
2294 skip_whitespace (p);
2295
2296 if (*p == '#')
2297 {
2298 if (wb_ok)
b99bd4ef 2299 {
f02232aa
NC
2300 /* [Rn], #expr */
2301 write_back = WRITE_BACK;
2302
2303 if (reg == REG_PC)
2304 {
2305 inst.error = _("pc may not be used in post-increment");
2306 return FAIL;
2307 }
2308
2309 if (cp_address_offset (& p) == FAIL)
2310 return FAIL;
b99bd4ef 2311 }
f02232aa
NC
2312 else
2313 pre_inc = PRE_INDEX | INDEX_UP;
2314 }
2315 else if (*p == '{')
2316 {
2317 int option;
b99bd4ef 2318
f02232aa
NC
2319 /* [Rn], {<expr>} */
2320 p++;
2321
2322 skip_whitespace (p);
2323
2324 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 2325 return FAIL;
f02232aa
NC
2326
2327 if (inst.reloc.exp.X_op == O_constant)
2328 {
2329 option = inst.reloc.exp.X_add_number;
2330
2331 if (option > 255 || option < 0)
2332 {
2333 inst.error = _("'option' field too large");
2334 return FAIL;
2335 }
2336
2337 skip_whitespace (p);
2338
2339 if (*p != '}')
2340 {
2341 inst.error = _("'}' expected at end of 'option' field");
2342 return FAIL;
2343 }
2344 else
2345 {
2346 p++;
2347 inst.instruction |= option;
2348 inst.instruction |= INDEX_UP;
2349 }
2350 }
2351 else
2352 {
2353 inst.error = _("non-constant expressions for 'option' field not supported");
2354 return FAIL;
2355 }
b99bd4ef
NC
2356 }
2357 else
f02232aa
NC
2358 {
2359 inst.error = _("# or { expected after comma");
a737bd4d 2360 return FAIL;
f02232aa 2361 }
b99bd4ef
NC
2362 }
2363 else
2364 {
2365 /* '['Rn, #expr']'[!] */
2366
2367 if (skip_past_comma (& p) == FAIL)
2368 {
2369 inst.error = _("pre-indexed expression expected");
2370 return FAIL;
2371 }
2372
2373 pre_inc = PRE_INDEX;
2374
2375 if (cp_address_offset (& p) == FAIL)
2376 return FAIL;
2377
2378 skip_whitespace (p);
2379
2380 if (*p++ != ']')
2381 {
2382 inst.error = _("missing ]");
2383 return FAIL;
2384 }
2385
2386 skip_whitespace (p);
2387
bfae80f2 2388 if (wb_ok && *p == '!')
b99bd4ef
NC
2389 {
2390 if (reg == REG_PC)
2391 {
2392 inst.error = _("pc may not be used with write-back");
2393 return FAIL;
2394 }
2395
2396 p++;
2397 write_back = WRITE_BACK;
2398 }
2399 }
2400 }
2401 else
2402 {
2403 if (my_get_expression (&inst.reloc.exp, &p))
2404 return FAIL;
2405
2406 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2407 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2408 inst.reloc.pc_rel = 1;
2409 inst.instruction |= (REG_PC << 16);
2410 pre_inc = PRE_INDEX;
2411 }
2412
2413 inst.instruction |= write_back | pre_inc;
2414 *str = p;
2415 return SUCCESS;
2416}
2417
e16bb312 2418static int
a737bd4d 2419cp_byte_address_offset (char ** str)
e16bb312
NC
2420{
2421 int offset;
2422
2423 skip_whitespace (* str);
2424
2425 if (! is_immediate_prefix (**str))
2426 {
2427 inst.error = _("immediate expression expected");
2428 return FAIL;
2429 }
2430
2431 (*str)++;
a737bd4d 2432
e16bb312
NC
2433 if (my_get_expression (& inst.reloc.exp, str))
2434 return FAIL;
a737bd4d 2435
e16bb312
NC
2436 if (inst.reloc.exp.X_op == O_constant)
2437 {
2438 offset = inst.reloc.exp.X_add_number;
a737bd4d 2439
e16bb312
NC
2440 if (offset > 255 || offset < -255)
2441 {
2442 inst.error = _("offset too large");
2443 return FAIL;
2444 }
2445
2446 if (offset >= 0)
2447 inst.instruction |= INDEX_UP;
2448 else
2449 offset = -offset;
2450
2451 inst.instruction |= offset;
2452 }
2453 else
2454 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2455
2456 return SUCCESS;
2457}
2458
2459static int
a737bd4d 2460cp_byte_address_required_here (char ** str)
e16bb312
NC
2461{
2462 char * p = * str;
2463 int pre_inc = 0;
2464 int write_back = 0;
2465
2466 if (*p == '[')
2467 {
2468 int reg;
2469
2470 p++;
2471 skip_whitespace (p);
2472
2473 if ((reg = reg_required_here (& p, 16)) == FAIL)
2474 return FAIL;
2475
2476 skip_whitespace (p);
2477
2478 if (*p == ']')
2479 {
2480 p++;
a737bd4d 2481
e16bb312
NC
2482 if (skip_past_comma (& p) == SUCCESS)
2483 {
2484 /* [Rn], #expr */
2485 write_back = WRITE_BACK;
a737bd4d 2486
e16bb312
NC
2487 if (reg == REG_PC)
2488 {
2489 inst.error = _("pc may not be used in post-increment");
2490 return FAIL;
2491 }
2492
2493 if (cp_byte_address_offset (& p) == FAIL)
2494 return FAIL;
2495 }
2496 else
2497 pre_inc = PRE_INDEX | INDEX_UP;
2498 }
2499 else
2500 {
2501 /* '['Rn, #expr']'[!] */
2502
2503 if (skip_past_comma (& p) == FAIL)
2504 {
2505 inst.error = _("pre-indexed expression expected");
2506 return FAIL;
2507 }
2508
2509 pre_inc = PRE_INDEX;
a737bd4d 2510
e16bb312
NC
2511 if (cp_byte_address_offset (& p) == FAIL)
2512 return FAIL;
2513
2514 skip_whitespace (p);
2515
2516 if (*p++ != ']')
2517 {
2518 inst.error = _("missing ]");
2519 return FAIL;
2520 }
2521
2522 skip_whitespace (p);
2523
2524 if (*p == '!')
2525 {
2526 if (reg == REG_PC)
2527 {
2528 inst.error = _("pc may not be used with write-back");
2529 return FAIL;
2530 }
2531
2532 p++;
2533 write_back = WRITE_BACK;
2534 }
2535 }
2536 }
2537 else
2538 {
2539 if (my_get_expression (&inst.reloc.exp, &p))
2540 return FAIL;
2541
2542 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2543 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2544 inst.reloc.pc_rel = 1;
2545 inst.instruction |= (REG_PC << 16);
2546 pre_inc = PRE_INDEX;
2547 }
2548
2549 inst.instruction |= write_back | pre_inc;
2550 *str = p;
2551 return SUCCESS;
2552}
2553
0dd132b6
NC
2554static void
2555do_nop (char * str)
2556{
2557 skip_whitespace (str);
2558 if (*str == '{')
2559 {
2560 str++;
2561
2562 if (my_get_expression (&inst.reloc.exp, &str))
2563 inst.reloc.exp.X_op = O_illegal;
2564 else
2565 {
2566 skip_whitespace (str);
2567 if (*str == '}')
2568 str++;
2569 else
2570 inst.reloc.exp.X_op = O_illegal;
2571 }
2572
2573 if (inst.reloc.exp.X_op != O_constant
2574 || inst.reloc.exp.X_add_number > 255
2575 || inst.reloc.exp.X_add_number < 0)
2576 {
2577 inst.error = _("Invalid NOP hint");
2578 return;
2579 }
2580
2581 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2582 inst.instruction &= 0xf0000000;
2583 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2584 }
2585
2586 end_of_line (str);
2587}
2588
b99bd4ef 2589static void
a737bd4d 2590do_empty (char * str)
b99bd4ef
NC
2591{
2592 /* Do nothing really. */
b99bd4ef 2593 end_of_line (str);
b99bd4ef
NC
2594}
2595
2596static void
a737bd4d 2597do_mrs (char * str)
b99bd4ef
NC
2598{
2599 int skip = 0;
2600
2601 /* Only one syntax. */
2602 skip_whitespace (str);
2603
2604 if (reg_required_here (&str, 12) == FAIL)
2605 {
2606 inst.error = BAD_ARGS;
2607 return;
2608 }
2609
2610 if (skip_past_comma (&str) == FAIL)
2611 {
2612 inst.error = _("comma expected after register name");
2613 return;
2614 }
2615
2616 skip_whitespace (str);
2617
a737bd4d
NC
2618 if ( streq (str, "CPSR")
2619 || streq (str, "SPSR")
2d2255b5 2620 /* Lower case versions for backwards compatibility. */
a737bd4d
NC
2621 || streq (str, "cpsr")
2622 || streq (str, "spsr"))
b99bd4ef
NC
2623 skip = 4;
2624
2d2255b5 2625 /* This is for backwards compatibility with older toolchains. */
a737bd4d
NC
2626 else if ( streq (str, "cpsr_all")
2627 || streq (str, "spsr_all"))
b99bd4ef
NC
2628 skip = 8;
2629 else
2630 {
f03698e6 2631 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
2632 return;
2633 }
2634
2635 if (* str == 's' || * str == 'S')
2636 inst.instruction |= SPSR_BIT;
2637 str += skip;
2638
b99bd4ef
NC
2639 end_of_line (str);
2640}
2641
2642/* Two possible forms:
2643 "{C|S}PSR_<field>, Rm",
2644 "{C|S}PSR_f, #expression". */
2645
2646static void
a737bd4d 2647do_msr (char * str)
b99bd4ef
NC
2648{
2649 skip_whitespace (str);
2650
2651 if (psr_required_here (& str) == FAIL)
2652 return;
2653
2654 if (skip_past_comma (& str) == FAIL)
2655 {
2656 inst.error = _("comma missing after psr flags");
2657 return;
2658 }
2659
2660 skip_whitespace (str);
2661
2662 if (reg_required_here (& str, 0) != FAIL)
2663 {
2664 inst.error = NULL;
b99bd4ef
NC
2665 end_of_line (str);
2666 return;
2667 }
2668
2669 if (! is_immediate_prefix (* str))
2670 {
2671 inst.error =
2672 _("only a register or immediate value can follow a psr flag");
2673 return;
2674 }
2675
2676 str ++;
2677 inst.error = NULL;
2678
2679 if (my_get_expression (& inst.reloc.exp, & str))
2680 {
2681 inst.error =
2682 _("only a register or immediate value can follow a psr flag");
2683 return;
2684 }
2685
f2b7cb0a 2686 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
2687
2688 if (inst.reloc.exp.X_add_symbol)
2689 {
2690 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2691 inst.reloc.pc_rel = 0;
2692 }
2693 else
2694 {
2695 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2696
2697 if (value == (unsigned) FAIL)
2698 {
f03698e6 2699 inst.error = _("invalid constant");
b99bd4ef
NC
2700 return;
2701 }
2702
2703 inst.instruction |= value;
2704 }
2705
2706 inst.error = NULL;
b99bd4ef
NC
2707 end_of_line (str);
2708}
2709
2710/* Long Multiply Parser
2711 UMULL RdLo, RdHi, Rm, Rs
2712 SMULL RdLo, RdHi, Rm, Rs
2713 UMLAL RdLo, RdHi, Rm, Rs
2714 SMLAL RdLo, RdHi, Rm, Rs. */
2715
2716static void
a737bd4d 2717do_mull (char * str)
b99bd4ef
NC
2718{
2719 int rdlo, rdhi, rm, rs;
2720
2721 /* Only one format "rdlo, rdhi, rm, rs". */
2722 skip_whitespace (str);
2723
2724 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2725 {
2726 inst.error = BAD_ARGS;
2727 return;
2728 }
2729
2730 if (skip_past_comma (&str) == FAIL
2731 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2732 {
2733 inst.error = BAD_ARGS;
2734 return;
2735 }
2736
2737 if (skip_past_comma (&str) == FAIL
2738 || (rm = reg_required_here (&str, 0)) == FAIL)
2739 {
2740 inst.error = BAD_ARGS;
2741 return;
2742 }
2743
2744 /* rdhi, rdlo and rm must all be different. */
2745 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2746 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2747
2748 if (skip_past_comma (&str) == FAIL
2749 || (rs = reg_required_here (&str, 8)) == FAIL)
2750 {
2751 inst.error = BAD_ARGS;
2752 return;
2753 }
2754
2755 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2756 {
2757 inst.error = BAD_PC;
2758 return;
2759 }
2760
b99bd4ef 2761 end_of_line (str);
b99bd4ef
NC
2762}
2763
2764static void
a737bd4d 2765do_mul (char * str)
b99bd4ef
NC
2766{
2767 int rd, rm;
2768
2769 /* Only one format "rd, rm, rs". */
2770 skip_whitespace (str);
2771
2772 if ((rd = reg_required_here (&str, 16)) == FAIL)
2773 {
2774 inst.error = BAD_ARGS;
2775 return;
2776 }
2777
2778 if (rd == REG_PC)
2779 {
2780 inst.error = BAD_PC;
2781 return;
2782 }
2783
2784 if (skip_past_comma (&str) == FAIL
2785 || (rm = reg_required_here (&str, 0)) == FAIL)
2786 {
2787 inst.error = BAD_ARGS;
2788 return;
2789 }
2790
2791 if (rm == REG_PC)
2792 {
2793 inst.error = BAD_PC;
2794 return;
2795 }
2796
2797 if (rm == rd)
2798 as_tsktsk (_("rd and rm should be different in mul"));
2799
2800 if (skip_past_comma (&str) == FAIL
2801 || (rm = reg_required_here (&str, 8)) == FAIL)
2802 {
2803 inst.error = BAD_ARGS;
2804 return;
2805 }
2806
2807 if (rm == REG_PC)
2808 {
2809 inst.error = BAD_PC;
2810 return;
2811 }
2812
b99bd4ef 2813 end_of_line (str);
b99bd4ef
NC
2814}
2815
2816static void
a737bd4d 2817do_mla (char * str)
b99bd4ef
NC
2818{
2819 int rd, rm;
2820
2821 /* Only one format "rd, rm, rs, rn". */
2822 skip_whitespace (str);
2823
2824 if ((rd = reg_required_here (&str, 16)) == FAIL)
2825 {
2826 inst.error = BAD_ARGS;
2827 return;
2828 }
2829
2830 if (rd == REG_PC)
2831 {
2832 inst.error = BAD_PC;
2833 return;
2834 }
2835
2836 if (skip_past_comma (&str) == FAIL
2837 || (rm = reg_required_here (&str, 0)) == FAIL)
2838 {
2839 inst.error = BAD_ARGS;
2840 return;
2841 }
2842
2843 if (rm == REG_PC)
2844 {
2845 inst.error = BAD_PC;
2846 return;
2847 }
2848
2849 if (rm == rd)
2850 as_tsktsk (_("rd and rm should be different in mla"));
2851
2852 if (skip_past_comma (&str) == FAIL
2853 || (rd = reg_required_here (&str, 8)) == FAIL
2854 || skip_past_comma (&str) == FAIL
2855 || (rm = reg_required_here (&str, 12)) == FAIL)
2856 {
2857 inst.error = BAD_ARGS;
2858 return;
2859 }
2860
2861 if (rd == REG_PC || rm == REG_PC)
2862 {
2863 inst.error = BAD_PC;
2864 return;
2865 }
2866
b99bd4ef 2867 end_of_line (str);
b99bd4ef
NC
2868}
2869
2870/* Expects *str -> the characters "acc0", possibly with leading blanks.
2871 Advances *str to the next non-alphanumeric.
2872 Returns 0, or else FAIL (in which case sets inst.error).
2873
2874 (In a future XScale, there may be accumulators other than zero.
2875 At that time this routine and its callers can be upgraded to suit.) */
2876
2877static int
a737bd4d 2878accum0_required_here (char ** str)
b99bd4ef
NC
2879{
2880 static char buff [128]; /* Note the address is taken. Hence, static. */
2881 char * p = * str;
2882 char c;
2883 int result = 0; /* The accum number. */
2884
2885 skip_whitespace (p);
2886
a737bd4d
NC
2887 *str = p; /* Advance caller's string pointer too. */
2888 c = *p++;
2889 while (ISALNUM (c))
2890 c = *p++;
2891
2892 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2893
2894 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2895 {
2896 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2897 inst.error = buff;
2898 result = FAIL;
2899 }
2900
2901 *p = c; /* Unzap. */
2902 *str = p; /* Caller's string pointer to after match. */
2903 return result;
2904}
2905
2906static int
2907ldst_extend_v4 (char ** str)
2908{
2909 int add = INDEX_UP;
2910
2911 switch (**str)
2912 {
2913 case '#':
2914 case '$':
2915 (*str)++;
2916 if (my_get_expression (& inst.reloc.exp, str))
2917 return FAIL;
2918
2919 if (inst.reloc.exp.X_op == O_constant)
2920 {
2921 int value = inst.reloc.exp.X_add_number;
2922
2923 if (value < -255 || value > 255)
2924 {
2925 inst.error = _("address offset too large");
2926 return FAIL;
2927 }
2928
2929 if (value < 0)
2930 {
2931 value = -value;
2932 add = 0;
2933 }
2934
2935 /* Halfword and signextension instructions have the
2936 immediate value split across bits 11..8 and bits 3..0. */
2937 inst.instruction |= (add | HWOFFSET_IMM
2938 | ((value >> 4) << 8) | (value & 0xF));
2939 }
2940 else
2941 {
2942 inst.instruction |= HWOFFSET_IMM;
2943 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2944 inst.reloc.pc_rel = 0;
2945 }
2946 return SUCCESS;
2947
2948 case '-':
2949 add = 0;
2950 /* Fall through. */
2951
2952 case '+':
2953 (*str)++;
2954 /* Fall through. */
b99bd4ef 2955
a737bd4d
NC
2956 default:
2957 if (reg_required_here (str, 0) == FAIL)
2958 return FAIL;
b99bd4ef 2959
a737bd4d
NC
2960 inst.instruction |= add;
2961 return SUCCESS;
b99bd4ef 2962 }
b99bd4ef
NC
2963}
2964
2965/* Expects **str -> after a comma. May be leading blanks.
2966 Advances *str, recognizing a load mode, and setting inst.instruction.
2967 Returns rn, or else FAIL (in which case may set inst.error
2968 and not advance str)
2969
2970 Note: doesn't know Rd, so no err checks that require such knowledge. */
2971
2972static int
a737bd4d 2973ld_mode_required_here (char ** string)
b99bd4ef
NC
2974{
2975 char * str = * string;
2976 int rn;
2977 int pre_inc = 0;
2978
2979 skip_whitespace (str);
2980
2981 if (* str == '[')
2982 {
2983 str++;
2984
2985 skip_whitespace (str);
2986
2987 if ((rn = reg_required_here (& str, 16)) == FAIL)
2988 return FAIL;
2989
2990 skip_whitespace (str);
2991
2992 if (* str == ']')
2993 {
2994 str ++;
2995
2996 if (skip_past_comma (& str) == SUCCESS)
2997 {
2998 /* [Rn],... (post inc) */
90e4755a 2999 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3000 return FAIL;
3001 }
3002 else /* [Rn] */
3003 {
cc8a6dd0 3004 skip_whitespace (str);
b99bd4ef 3005
cc8a6dd0
KH
3006 if (* str == '!')
3007 {
3008 str ++;
3009 inst.instruction |= WRITE_BACK;
3010 }
b99bd4ef
NC
3011
3012 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3013 pre_inc = 1;
3014 }
3015 }
3016 else /* [Rn,...] */
3017 {
3018 if (skip_past_comma (& str) == FAIL)
3019 {
3020 inst.error = _("pre-indexed expression expected");
3021 return FAIL;
3022 }
3023
3024 pre_inc = 1;
3025
90e4755a 3026 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3027 return FAIL;
3028
3029 skip_whitespace (str);
3030
3031 if (* str ++ != ']')
3032 {
3033 inst.error = _("missing ]");
3034 return FAIL;
3035 }
3036
3037 skip_whitespace (str);
3038
3039 if (* str == '!')
3040 {
3041 str ++;
3042 inst.instruction |= WRITE_BACK;
3043 }
3044 }
3045 }
3046 else if (* str == '=') /* ldr's "r,=label" syntax */
3047 /* We should never reach here, because <text> = <expression> is
3048 caught gas/read.c read_a_source_file() as a .set operation. */
3049 return FAIL;
3050 else /* PC +- 8 bit immediate offset. */
3051 {
3052 if (my_get_expression (& inst.reloc.exp, & str))
3053 return FAIL;
3054
3055 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3056 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3057 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3058 inst.reloc.pc_rel = 1;
3059 inst.instruction |= (REG_PC << 16);
3060
3061 rn = REG_PC;
3062 pre_inc = 1;
3063 }
3064
3065 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3066 * string = str;
3067
3068 return rn;
3069}
3070
3071/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3072 SMLAxy{cond} Rd,Rm,Rs,Rn
3073 SMLAWy{cond} Rd,Rm,Rs,Rn
3074 Error if any register is R15. */
3075
3076static void
a737bd4d 3077do_smla (char * str)
b99bd4ef
NC
3078{
3079 int rd, rm, rs, rn;
3080
3081 skip_whitespace (str);
3082
3083 if ((rd = reg_required_here (& str, 16)) == FAIL
3084 || skip_past_comma (& str) == FAIL
3085 || (rm = reg_required_here (& str, 0)) == FAIL
3086 || skip_past_comma (& str) == FAIL
3087 || (rs = reg_required_here (& str, 8)) == FAIL
3088 || skip_past_comma (& str) == FAIL
3089 || (rn = reg_required_here (& str, 12)) == FAIL)
3090 inst.error = BAD_ARGS;
3091
3092 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3093 inst.error = BAD_PC;
3094
b99bd4ef
NC
3095 else
3096 end_of_line (str);
3097}
3098
3099/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3100 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3101 Error if any register is R15.
3102 Warning if Rdlo == Rdhi. */
3103
3104static void
a737bd4d 3105do_smlal (char * str)
b99bd4ef
NC
3106{
3107 int rdlo, rdhi, rm, rs;
3108
3109 skip_whitespace (str);
3110
3111 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3112 || skip_past_comma (& str) == FAIL
3113 || (rdhi = reg_required_here (& str, 16)) == FAIL
3114 || skip_past_comma (& str) == FAIL
3115 || (rm = reg_required_here (& str, 0)) == FAIL
3116 || skip_past_comma (& str) == FAIL
3117 || (rs = reg_required_here (& str, 8)) == FAIL)
3118 {
3119 inst.error = BAD_ARGS;
3120 return;
3121 }
3122
3123 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3124 {
3125 inst.error = BAD_PC;
3126 return;
3127 }
3128
3129 if (rdlo == rdhi)
3130 as_tsktsk (_("rdhi and rdlo must be different"));
3131
f2b7cb0a 3132 end_of_line (str);
b99bd4ef
NC
3133}
3134
3135/* ARM V5E (El Segundo) signed-multiply (argument parse)
3136 SMULxy{cond} Rd,Rm,Rs
3137 Error if any register is R15. */
3138
3139static void
a737bd4d 3140do_smul (char * str)
b99bd4ef
NC
3141{
3142 int rd, rm, rs;
3143
3144 skip_whitespace (str);
3145
3146 if ((rd = reg_required_here (& str, 16)) == FAIL
3147 || skip_past_comma (& str) == FAIL
3148 || (rm = reg_required_here (& str, 0)) == FAIL
3149 || skip_past_comma (& str) == FAIL
3150 || (rs = reg_required_here (& str, 8)) == FAIL)
3151 inst.error = BAD_ARGS;
3152
3153 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3154 inst.error = BAD_PC;
3155
b99bd4ef
NC
3156 else
3157 end_of_line (str);
3158}
3159
3160/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3161 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3162 Error if any register is R15. */
3163
3164static void
a737bd4d 3165do_qadd (char * str)
b99bd4ef
NC
3166{
3167 int rd, rm, rn;
3168
3169 skip_whitespace (str);
3170
3171 if ((rd = reg_required_here (& str, 12)) == FAIL
3172 || skip_past_comma (& str) == FAIL
3173 || (rm = reg_required_here (& str, 0)) == FAIL
3174 || skip_past_comma (& str) == FAIL
3175 || (rn = reg_required_here (& str, 16)) == FAIL)
3176 inst.error = BAD_ARGS;
3177
3178 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3179 inst.error = BAD_PC;
3180
b99bd4ef
NC
3181 else
3182 end_of_line (str);
3183}
3184
3185/* ARM V5E (el Segundo)
3186 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3187 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3188
3189 These are equivalent to the XScale instructions MAR and MRA,
3190 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3191
3192 Result unpredicatable if Rd or Rn is R15. */
3193
3194static void
a737bd4d 3195do_co_reg2c (char * str)
b99bd4ef
NC
3196{
3197 int rd, rn;
3198
3199 skip_whitespace (str);
3200
3201 if (co_proc_number (& str) == FAIL)
3202 {
3203 if (!inst.error)
3204 inst.error = BAD_ARGS;
3205 return;
3206 }
3207
3208 if (skip_past_comma (& str) == FAIL
3209 || cp_opc_expr (& str, 4, 4) == FAIL)
3210 {
3211 if (!inst.error)
3212 inst.error = BAD_ARGS;
3213 return;
3214 }
3215
3216 if (skip_past_comma (& str) == FAIL
3217 || (rd = reg_required_here (& str, 12)) == FAIL)
3218 {
3219 if (!inst.error)
3220 inst.error = BAD_ARGS;
3221 return;
3222 }
3223
3224 if (skip_past_comma (& str) == FAIL
3225 || (rn = reg_required_here (& str, 16)) == FAIL)
3226 {
3227 if (!inst.error)
3228 inst.error = BAD_ARGS;
3229 return;
3230 }
3231
09d92015
MM
3232 /* Unpredictable result if rd or rn is R15. */
3233 if (rd == REG_PC || rn == REG_PC)
3234 as_tsktsk
3235 (_("Warning: instruction unpredictable when using r15"));
3236
3237 if (skip_past_comma (& str) == FAIL
3238 || cp_reg_required_here (& str, 0) == FAIL)
3239 {
3240 if (!inst.error)
3241 inst.error = BAD_ARGS;
3242 return;
3243 }
3244
3245 end_of_line (str);
3246}
3247
3248/* ARM V5 count-leading-zeroes instruction (argument parse)
3249 CLZ{<cond>} <Rd>, <Rm>
3250 Condition defaults to COND_ALWAYS.
3251 Error if Rd or Rm are R15. */
3252
3253static void
a737bd4d 3254do_clz (char * str)
09d92015
MM
3255{
3256 int rd, rm;
3257
3258 skip_whitespace (str);
3259
3260 if (((rd = reg_required_here (& str, 12)) == FAIL)
3261 || (skip_past_comma (& str) == FAIL)
3262 || ((rm = reg_required_here (& str, 0)) == FAIL))
3263 inst.error = BAD_ARGS;
3264
3265 else if (rd == REG_PC || rm == REG_PC )
3266 inst.error = BAD_PC;
3267
3268 else
3269 end_of_line (str);
3270}
3271
3272/* ARM V5 (argument parse)
3273 LDC2{L} <coproc>, <CRd>, <addressing mode>
3274 STC2{L} <coproc>, <CRd>, <addressing mode>
3275 Instruction is not conditional, and has 0xf in the condition field.
3276 Otherwise, it's the same as LDC/STC. */
3277
3278static void
a737bd4d 3279do_lstc2 (char * str)
09d92015
MM
3280{
3281 skip_whitespace (str);
3282
3283 if (co_proc_number (& str) == FAIL)
3284 {
3285 if (!inst.error)
3286 inst.error = BAD_ARGS;
3287 }
3288 else if (skip_past_comma (& str) == FAIL
3289 || cp_reg_required_here (& str, 12) == FAIL)
3290 {
3291 if (!inst.error)
3292 inst.error = BAD_ARGS;
3293 }
3294 else if (skip_past_comma (& str) == FAIL
3295 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3296 {
3297 if (! inst.error)
3298 inst.error = BAD_ARGS;
3299 }
3300 else
3301 end_of_line (str);
3302}
3303
3304/* ARM V5 (argument parse)
3305 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3306 Instruction is not conditional, and has 0xf in the condition field.
3307 Otherwise, it's the same as CDP. */
3308
3309static void
a737bd4d 3310do_cdp2 (char * str)
09d92015
MM
3311{
3312 skip_whitespace (str);
3313
3314 if (co_proc_number (& str) == FAIL)
3315 {
3316 if (!inst.error)
3317 inst.error = BAD_ARGS;
3318 return;
3319 }
3320
3321 if (skip_past_comma (& str) == FAIL
3322 || cp_opc_expr (& str, 20,4) == FAIL)
3323 {
3324 if (!inst.error)
3325 inst.error = BAD_ARGS;
3326 return;
3327 }
3328
3329 if (skip_past_comma (& str) == FAIL
3330 || cp_reg_required_here (& str, 12) == FAIL)
3331 {
3332 if (!inst.error)
3333 inst.error = BAD_ARGS;
3334 return;
3335 }
3336
3337 if (skip_past_comma (& str) == FAIL
3338 || cp_reg_required_here (& str, 16) == FAIL)
3339 {
3340 if (!inst.error)
3341 inst.error = BAD_ARGS;
3342 return;
3343 }
3344
3345 if (skip_past_comma (& str) == FAIL
3346 || cp_reg_required_here (& str, 0) == FAIL)
3347 {
3348 if (!inst.error)
3349 inst.error = BAD_ARGS;
3350 return;
3351 }
3352
3353 if (skip_past_comma (& str) == SUCCESS)
3354 {
3355 if (cp_opc_expr (& str, 5, 3) == FAIL)
3356 {
3357 if (!inst.error)
3358 inst.error = BAD_ARGS;
3359 return;
3360 }
3361 }
3362
3363 end_of_line (str);
3364}
3365
3366/* ARM V5 (argument parse)
3367 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3368 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3369 Instruction is not conditional, and has 0xf in the condition field.
3370 Otherwise, it's the same as MCR/MRC. */
3371
3372static void
a737bd4d 3373do_co_reg2 (char * str)
09d92015
MM
3374{
3375 skip_whitespace (str);
3376
3377 if (co_proc_number (& str) == FAIL)
3378 {
3379 if (!inst.error)
3380 inst.error = BAD_ARGS;
3381 return;
3382 }
3383
3384 if (skip_past_comma (& str) == FAIL
3385 || cp_opc_expr (& str, 21, 3) == FAIL)
3386 {
3387 if (!inst.error)
3388 inst.error = BAD_ARGS;
3389 return;
3390 }
3391
3392 if (skip_past_comma (& str) == FAIL
3393 || reg_required_here (& str, 12) == FAIL)
3394 {
3395 if (!inst.error)
3396 inst.error = BAD_ARGS;
3397 return;
3398 }
3399
3400 if (skip_past_comma (& str) == FAIL
3401 || cp_reg_required_here (& str, 16) == FAIL)
3402 {
3403 if (!inst.error)
3404 inst.error = BAD_ARGS;
3405 return;
3406 }
3407
3408 if (skip_past_comma (& str) == FAIL
3409 || cp_reg_required_here (& str, 0) == FAIL)
3410 {
3411 if (!inst.error)
3412 inst.error = BAD_ARGS;
3413 return;
3414 }
3415
3416 if (skip_past_comma (& str) == SUCCESS)
3417 {
3418 if (cp_opc_expr (& str, 5, 3) == FAIL)
3419 {
3420 if (!inst.error)
3421 inst.error = BAD_ARGS;
3422 return;
3423 }
3424 }
3425
3426 end_of_line (str);
3427}
3428
a737bd4d
NC
3429static void
3430do_bx (char * str)
3431{
3432 int reg;
3433
3434 skip_whitespace (str);
3435
3436 if ((reg = reg_required_here (&str, 0)) == FAIL)
3437 {
3438 inst.error = BAD_ARGS;
3439 return;
3440 }
3441
3442 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3443 if (reg == REG_PC)
3444 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3445
3446 end_of_line (str);
3447}
3448
09d92015 3449/* ARM v5TEJ. Jump to Jazelle code. */
a737bd4d 3450
09d92015 3451static void
a737bd4d 3452do_bxj (char * str)
09d92015
MM
3453{
3454 int reg;
3455
3456 skip_whitespace (str);
3457
3458 if ((reg = reg_required_here (&str, 0)) == FAIL)
3459 {
3460 inst.error = BAD_ARGS;
3461 return;
3462 }
3463
a737bd4d
NC
3464 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3465 if (reg == REG_PC)
3466 as_tsktsk (_("use of r15 in bxj is not really useful"));
3467
3468 end_of_line (str);
3469}
3470
3471/* ARM V6 umaal (argument parse). */
3472
3473static void
3474do_umaal (char * str)
3475{
3476 int rdlo, rdhi, rm, rs;
3477
3478 skip_whitespace (str);
3479 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3480 || skip_past_comma (& str) == FAIL
3481 || (rdhi = reg_required_here (& str, 16)) == FAIL
3482 || skip_past_comma (& str) == FAIL
3483 || (rm = reg_required_here (& str, 0)) == FAIL
3484 || skip_past_comma (& str) == FAIL
3485 || (rs = reg_required_here (& str, 8)) == FAIL)
3486 {
3487 inst.error = BAD_ARGS;
3488 return;
3489 }
3490
3491 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3492 {
3493 inst.error = BAD_PC;
3494 return;
3495 }
3496
3497 end_of_line (str);
3498}
3499
3500/* ARM V6 strex (argument parse). */
3501
3502static void
3503do_strex (char * str)
3504{
3505 int rd, rm, rn;
3506
3507 /* Parse Rd, Rm,. */
3508 skip_whitespace (str);
3509 if ((rd = reg_required_here (& str, 12)) == FAIL
3510 || skip_past_comma (& str) == FAIL
3511 || (rm = reg_required_here (& str, 0)) == FAIL
3512 || skip_past_comma (& str) == FAIL)
3513 {
3514 inst.error = BAD_ARGS;
3515 return;
3516 }
3517 if (rd == REG_PC || rm == REG_PC)
3518 {
3519 inst.error = BAD_PC;
3520 return;
3521 }
3522 if (rd == rm)
3523 {
3524 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3525 return;
3526 }
3527
3528 /* Skip past '['. */
3529 if ((strlen (str) >= 1)
3530 && strncmp (str, "[", 1) == 0)
3531 str += 1;
3532
3533 skip_whitespace (str);
3534
3535 /* Parse Rn. */
3536 if ((rn = reg_required_here (& str, 16)) == FAIL)
3537 {
3538 inst.error = BAD_ARGS;
3539 return;
3540 }
3541 else if (rn == REG_PC)
3542 {
3543 inst.error = BAD_PC;
3544 return;
3545 }
3546 if (rd == rn)
3547 {
3548 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3549 return;
3550 }
3551 skip_whitespace (str);
3552
3553 /* Skip past ']'. */
3554 if ((strlen (str) >= 1)
3555 && strncmp (str, "]", 1) == 0)
3556 str += 1;
3557
3558 end_of_line (str);
3559}
3560
3561/* KIND indicates what kind of shifts are accepted. */
3562
3563static int
3564decode_shift (char ** str, int kind)
3565{
3566 const struct asm_shift_name * shift;
3567 char * p;
3568 char c;
3569
3570 skip_whitespace (* str);
3571
3572 for (p = * str; ISALPHA (* p); p ++)
3573 ;
3574
3575 if (p == * str)
3576 {
3577 inst.error = _("shift expression expected");
3578 return FAIL;
3579 }
3580
3581 c = * p;
3582 * p = '\0';
3583 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3584 * p = c;
3585
3586 if (shift == NULL)
3587 {
3588 inst.error = _("shift expression expected");
3589 return FAIL;
3590 }
3591
3592 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3593
3594 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3595 && shift->properties->index != SHIFT_LSL
3596 && shift->properties->index != SHIFT_ASR)
3597 {
3598 inst.error = _("'LSL' or 'ASR' required");
3599 return FAIL;
3600 }
3601 else if (kind == SHIFT_LSL_IMMEDIATE
3602 && shift->properties->index != SHIFT_LSL)
3603 {
3604 inst.error = _("'LSL' required");
3605 return FAIL;
3606 }
3607 else if (kind == SHIFT_ASR_IMMEDIATE
3608 && shift->properties->index != SHIFT_ASR)
3609 {
3610 inst.error = _("'ASR' required");
3611 return FAIL;
3612 }
3613
3614 if (shift->properties->index == SHIFT_RRX)
3615 {
3616 * str = p;
3617 inst.instruction |= shift->properties->bit_field;
3618 return SUCCESS;
3619 }
3620
3621 skip_whitespace (p);
3622
3623 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3624 {
3625 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3626 * str = p;
3627 return SUCCESS;
3628 }
3629 else if (! is_immediate_prefix (* p))
3630 {
3631 inst.error = (NO_SHIFT_RESTRICT
3632 ? _("shift requires register or #expression")
3633 : _("shift requires #expression"));
3634 * str = p;
3635 return FAIL;
3636 }
3637
3638 inst.error = NULL;
3639 p ++;
3640
3641 if (my_get_expression (& inst.reloc.exp, & p))
3642 return FAIL;
3643
3644 /* Validate some simple #expressions. */
3645 if (inst.reloc.exp.X_op == O_constant)
3646 {
3647 unsigned num = inst.reloc.exp.X_add_number;
3648
3649 /* Reject operations greater than 32. */
3650 if (num > 32
3651 /* Reject a shift of 0 unless the mode allows it. */
3652 || (num == 0 && shift->properties->allows_0 == 0)
3653 /* Reject a shift of 32 unless the mode allows it. */
3654 || (num == 32 && shift->properties->allows_32 == 0)
3655 )
3656 {
3657 /* As a special case we allow a shift of zero for
3658 modes that do not support it to be recoded as an
3659 logical shift left of zero (ie nothing). We warn
3660 about this though. */
3661 if (num == 0)
3662 {
3663 as_warn (_("shift of 0 ignored."));
3664 shift = & shift_names[0];
3665 assert (shift->properties->index == SHIFT_LSL);
3666 }
3667 else
3668 {
3669 inst.error = _("invalid immediate shift");
3670 return FAIL;
3671 }
3672 }
3673
3674 /* Shifts of 32 are encoded as 0, for those shifts that
3675 support it. */
3676 if (num == 32)
3677 num = 0;
3678
3679 inst.instruction |= (num << 7) | shift->properties->bit_field;
3680 }
3681 else
3682 {
3683 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3684 inst.reloc.pc_rel = 0;
3685 inst.instruction |= shift->properties->bit_field;
3686 }
3687
3688 * str = p;
3689 return SUCCESS;
09d92015
MM
3690}
3691
09d92015 3692static void
a737bd4d 3693do_sat (char ** str, int bias)
09d92015 3694{
a737bd4d
NC
3695 int rd, rm;
3696 expressionS expr;
09d92015 3697
a737bd4d 3698 skip_whitespace (*str);
09d92015 3699
a737bd4d
NC
3700 /* Parse <Rd>, field. */
3701 if ((rd = reg_required_here (str, 12)) == FAIL
3702 || skip_past_comma (str) == FAIL)
09d92015
MM
3703 {
3704 inst.error = BAD_ARGS;
a737bd4d 3705 return;
09d92015 3706 }
a737bd4d 3707 if (rd == REG_PC)
09d92015
MM
3708 {
3709 inst.error = BAD_PC;
3710 return;
3711 }
3712
a737bd4d
NC
3713 /* Parse #<immed>, field. */
3714 if (is_immediate_prefix (**str))
3715 (*str)++;
3716 else
09d92015 3717 {
a737bd4d 3718 inst.error = _("immediate expression expected");
09d92015
MM
3719 return;
3720 }
a737bd4d 3721 if (my_get_expression (&expr, str))
09d92015 3722 {
a737bd4d 3723 inst.error = _("bad expression");
09d92015
MM
3724 return;
3725 }
a737bd4d 3726 if (expr.X_op != O_constant)
09d92015 3727 {
a737bd4d 3728 inst.error = _("constant expression expected");
09d92015
MM
3729 return;
3730 }
a737bd4d
NC
3731 if (expr.X_add_number + bias < 0
3732 || expr.X_add_number + bias > 31)
3733 {
3734 inst.error = _("immediate value out of range");
3735 return;
3736 }
3737 inst.instruction |= (expr.X_add_number + bias) << 16;
3738 if (skip_past_comma (str) == FAIL)
09d92015
MM
3739 {
3740 inst.error = BAD_ARGS;
3741 return;
3742 }
a737bd4d
NC
3743
3744 /* Parse <Rm> field. */
3745 if ((rm = reg_required_here (str, 0)) == FAIL)
09d92015 3746 {
a737bd4d 3747 inst.error = BAD_ARGS;
09d92015
MM
3748 return;
3749 }
a737bd4d 3750 if (rm == REG_PC)
09d92015 3751 {
a737bd4d 3752 inst.error = BAD_PC;
09d92015
MM
3753 return;
3754 }
09d92015 3755
a737bd4d
NC
3756 if (skip_past_comma (str) == SUCCESS)
3757 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
09d92015
MM
3758}
3759
a737bd4d 3760/* ARM V6 ssat (argument parse). */
09d92015
MM
3761
3762static void
a737bd4d 3763do_ssat (char * str)
09d92015
MM
3764{
3765 do_sat (&str, /*bias=*/-1);
3766 end_of_line (str);
3767}
3768
a737bd4d 3769/* ARM V6 usat (argument parse). */
09d92015
MM
3770
3771static void
a737bd4d 3772do_usat (char * str)
09d92015
MM
3773{
3774 do_sat (&str, /*bias=*/0);
3775 end_of_line (str);
3776}
3777
3778static void
a737bd4d 3779do_sat16 (char ** str, int bias)
09d92015
MM
3780{
3781 int rd, rm;
3782 expressionS expr;
3783
3784 skip_whitespace (*str);
a737bd4d
NC
3785
3786 /* Parse the <Rd> field. */
09d92015
MM
3787 if ((rd = reg_required_here (str, 12)) == FAIL
3788 || skip_past_comma (str) == FAIL)
3789 {
3790 inst.error = BAD_ARGS;
3791 return;
3792 }
3793 if (rd == REG_PC)
3794 {
3795 inst.error = BAD_PC;
3796 return;
3797 }
3798
a737bd4d 3799 /* Parse #<immed>, field. */
09d92015
MM
3800 if (is_immediate_prefix (**str))
3801 (*str)++;
3802 else
3803 {
3804 inst.error = _("immediate expression expected");
3805 return;
3806 }
3807 if (my_get_expression (&expr, str))
3808 {
3809 inst.error = _("bad expression");
3810 return;
3811 }
3812 if (expr.X_op != O_constant)
3813 {
3814 inst.error = _("constant expression expected");
3815 return;
3816 }
3817 if (expr.X_add_number + bias < 0
a737bd4d 3818 || expr.X_add_number + bias > 15)
09d92015
MM
3819 {
3820 inst.error = _("immediate value out of range");
3821 return;
3822 }
3823 inst.instruction |= (expr.X_add_number + bias) << 16;
3824 if (skip_past_comma (str) == FAIL)
3825 {
3826 inst.error = BAD_ARGS;
3827 return;
3828 }
3829
a737bd4d 3830 /* Parse <Rm> field. */
09d92015
MM
3831 if ((rm = reg_required_here (str, 0)) == FAIL)
3832 {
3833 inst.error = BAD_ARGS;
3834 return;
3835 }
3836 if (rm == REG_PC)
3837 {
3838 inst.error = BAD_PC;
3839 return;
3840 }
09d92015
MM
3841}
3842
a737bd4d 3843/* ARM V6 ssat16 (argument parse). */
09d92015
MM
3844
3845static void
a737bd4d 3846do_ssat16 (char * str)
09d92015
MM
3847{
3848 do_sat16 (&str, /*bias=*/-1);
3849 end_of_line (str);
3850}
3851
3852static void
a737bd4d 3853do_usat16 (char * str)
09d92015
MM
3854{
3855 do_sat16 (&str, /*bias=*/0);
3856 end_of_line (str);
3857}
3858
3859static void
a737bd4d 3860do_cps_mode (char ** str)
09d92015 3861{
09d92015
MM
3862 expressionS expr;
3863
3864 skip_whitespace (*str);
3865
a737bd4d 3866 if (! is_immediate_prefix (**str))
09d92015
MM
3867 {
3868 inst.error = _("immediate expression expected");
3869 return;
3870 }
a737bd4d
NC
3871
3872 (*str)++; /* Strip off the immediate signifier. */
09d92015
MM
3873 if (my_get_expression (&expr, str))
3874 {
3875 inst.error = _("bad expression");
3876 return;
3877 }
a737bd4d 3878
09d92015
MM
3879 if (expr.X_op != O_constant)
3880 {
3881 inst.error = _("constant expression expected");
3882 return;
3883 }
09d92015 3884
a737bd4d
NC
3885 /* The mode is a 5 bit field. Valid values are 0-31. */
3886 if (((unsigned) expr.X_add_number) > 31
3887 || (inst.reloc.exp.X_add_number) < 0)
09d92015 3888 {
a737bd4d 3889 inst.error = _("invalid constant");
09d92015
MM
3890 return;
3891 }
a737bd4d
NC
3892
3893 inst.instruction |= expr.X_add_number;
09d92015
MM
3894}
3895
a737bd4d 3896/* ARM V6 srs (argument parse). */
09d92015
MM
3897
3898static void
a737bd4d 3899do_srs (char * str)
09d92015
MM
3900{
3901 char *exclam;
3902 skip_whitespace (str);
3903 exclam = strchr (str, '!');
3904 if (exclam)
3905 *exclam = '\0';
3906 do_cps_mode (&str);
3907 if (exclam)
3908 *exclam = '!';
a737bd4d 3909 if (*str == '!')
09d92015
MM
3910 {
3911 inst.instruction |= WRITE_BACK;
3912 str++;
3913 }
3914 end_of_line (str);
3915}
3916
a737bd4d 3917/* ARM V6 SMMUL (argument parse). */
09d92015
MM
3918
3919static void
a737bd4d 3920do_smmul (char * str)
09d92015
MM
3921{
3922 int rd, rm, rs;
a737bd4d 3923
09d92015
MM
3924 skip_whitespace (str);
3925 if ((rd = reg_required_here (&str, 16)) == FAIL
3926 || skip_past_comma (&str) == FAIL
3927 || (rm = reg_required_here (&str, 0)) == FAIL
3928 || skip_past_comma (&str) == FAIL
3929 || (rs = reg_required_here (&str, 8)) == FAIL)
3930 {
3931 inst.error = BAD_ARGS;
3932 return;
3933 }
3934
a737bd4d 3935 if ( rd == REG_PC
09d92015
MM
3936 || rm == REG_PC
3937 || rs == REG_PC)
3938 {
3939 inst.error = BAD_PC;
3940 return;
3941 }
3942
3943 end_of_line (str);
09d92015
MM
3944}
3945
a737bd4d 3946/* ARM V6 SMLALD (argument parse). */
09d92015
MM
3947
3948static void
a737bd4d 3949do_smlald (char * str)
09d92015
MM
3950{
3951 int rdlo, rdhi, rm, rs;
a737bd4d 3952
09d92015
MM
3953 skip_whitespace (str);
3954 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3955 || skip_past_comma (&str) == FAIL
3956 || (rdhi = reg_required_here (&str, 16)) == FAIL
3957 || skip_past_comma (&str) == FAIL
3958 || (rm = reg_required_here (&str, 0)) == FAIL
3959 || skip_past_comma (&str) == FAIL
3960 || (rs = reg_required_here (&str, 8)) == FAIL)
3961 {
3962 inst.error = BAD_ARGS;
3963 return;
3964 }
3965
a737bd4d
NC
3966 if ( rdlo == REG_PC
3967 || rdhi == REG_PC
09d92015
MM
3968 || rm == REG_PC
3969 || rs == REG_PC)
3970 {
3971 inst.error = BAD_PC;
3972 return;
3973 }
3974
3975 end_of_line (str);
3976}
3977
a737bd4d 3978/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
09d92015
MM
3979 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3980
a737bd4d
NC
3981static void
3982do_smlad (char * str)
09d92015
MM
3983{
3984 int rd, rm, rs, rn;
a737bd4d 3985
09d92015
MM
3986 skip_whitespace (str);
3987 if ((rd = reg_required_here (&str, 16)) == FAIL
3988 || skip_past_comma (&str) == FAIL
3989 || (rm = reg_required_here (&str, 0)) == FAIL
3990 || skip_past_comma (&str) == FAIL
3991 || (rs = reg_required_here (&str, 8)) == FAIL
3992 || skip_past_comma (&str) == FAIL
3993 || (rn = reg_required_here (&str, 12)) == FAIL)
3994 {
3995 inst.error = BAD_ARGS;
3996 return;
3997 }
a737bd4d
NC
3998
3999 if ( rd == REG_PC
4000 || rn == REG_PC
09d92015
MM
4001 || rs == REG_PC
4002 || rm == REG_PC)
4003 {
4004 inst.error = BAD_PC;
4005 return;
4006 }
4007
4008 end_of_line (str);
09d92015
MM
4009}
4010
4011/* Returns true if the endian-specifier indicates big-endianness. */
4012
4013static int
a737bd4d 4014do_endian_specifier (char * str)
09d92015
MM
4015{
4016 int big_endian = 0;
4017
4018 skip_whitespace (str);
4019 if (strlen (str) < 2)
4020 inst.error = _("missing endian specifier");
4021 else if (strncasecmp (str, "BE", 2) == 0)
4022 {
4023 str += 2;
4024 big_endian = 1;
4025 }
4026 else if (strncasecmp (str, "LE", 2) == 0)
4027 str += 2;
4028 else
4029 inst.error = _("valid endian specifiers are be or le");
4030
4031 end_of_line (str);
4032
4033 return big_endian;
4034}
4035
a737bd4d
NC
4036/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4037 preserving the other bits.
4038
4039 setend <endian_specifier>, where <endian_specifier> is either
4040 BE or LE. */
4041
4042static void
4043do_setend (char * str)
4044{
4045 if (do_endian_specifier (str))
4046 inst.instruction |= 0x200;
4047}
4048
09d92015
MM
4049/* ARM V6 SXTH.
4050
4051 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4052 Condition defaults to COND_ALWAYS.
a737bd4d 4053 Error if any register uses R15. */
09d92015 4054
a737bd4d
NC
4055static void
4056do_sxth (char * str)
09d92015
MM
4057{
4058 int rd, rm;
4059 expressionS expr;
4060 int rotation_clear_mask = 0xfffff3ff;
4061 int rotation_eight_mask = 0x00000400;
4062 int rotation_sixteen_mask = 0x00000800;
4063 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4064
09d92015
MM
4065 skip_whitespace (str);
4066 if ((rd = reg_required_here (&str, 12)) == FAIL
4067 || skip_past_comma (&str) == FAIL
4068 || (rm = reg_required_here (&str, 0)) == FAIL)
4069 {
4070 inst.error = BAD_ARGS;
4071 return;
4072 }
4073
4074 else if (rd == REG_PC || rm == REG_PC)
4075 {
4076 inst.error = BAD_PC;
4077 return;
4078 }
a737bd4d
NC
4079
4080 /* Zero out the rotation field. */
09d92015 4081 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4082
4083 /* Check for lack of optional rotation field. */
09d92015
MM
4084 if (skip_past_comma (&str) == FAIL)
4085 {
4086 end_of_line (str);
4087 return;
4088 }
a737bd4d
NC
4089
4090 /* Move past 'ROR'. */
09d92015
MM
4091 skip_whitespace (str);
4092 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4093 str += 3;
09d92015
MM
4094 else
4095 {
4096 inst.error = _("missing rotation field after comma");
4097 return;
4098 }
a737bd4d
NC
4099
4100 /* Get the immediate constant. */
09d92015
MM
4101 skip_whitespace (str);
4102 if (is_immediate_prefix (* str))
4103 str++;
4104 else
4105 {
4106 inst.error = _("immediate expression expected");
4107 return;
4108 }
a737bd4d 4109
09d92015
MM
4110 if (my_get_expression (&expr, &str))
4111 {
4112 inst.error = _("bad expression");
4113 return;
4114 }
4115
4116 if (expr.X_op != O_constant)
4117 {
4118 inst.error = _("constant expression expected");
4119 return;
4120 }
a737bd4d
NC
4121
4122 switch (expr.X_add_number)
09d92015
MM
4123 {
4124 case 0:
a737bd4d 4125 /* Rotation field has already been zeroed. */
09d92015
MM
4126 break;
4127 case 8:
4128 inst.instruction |= rotation_eight_mask;
4129 break;
4130
4131 case 16:
4132 inst.instruction |= rotation_sixteen_mask;
4133 break;
a737bd4d 4134
09d92015
MM
4135 case 24:
4136 inst.instruction |= rotation_twenty_four_mask;
4137 break;
4138
4139 default:
4140 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4141 break;
4142 }
4143
4144 end_of_line (str);
09d92015
MM
4145}
4146
4147/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4148 extends it to 32-bits, and adds the result to a value in another
4149 register. You can specify a rotation by 0, 8, 16, or 24 bits
4150 before extracting the 16-bit value.
4151 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4152 Condition defaults to COND_ALWAYS.
a737bd4d 4153 Error if any register uses R15. */
09d92015 4154
a737bd4d
NC
4155static void
4156do_sxtah (char * str)
09d92015
MM
4157{
4158 int rd, rn, rm;
4159 expressionS expr;
4160 int rotation_clear_mask = 0xfffff3ff;
4161 int rotation_eight_mask = 0x00000400;
4162 int rotation_sixteen_mask = 0x00000800;
4163 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4164
09d92015
MM
4165 skip_whitespace (str);
4166 if ((rd = reg_required_here (&str, 12)) == FAIL
4167 || skip_past_comma (&str) == FAIL
4168 || (rn = reg_required_here (&str, 16)) == FAIL
4169 || skip_past_comma (&str) == FAIL
4170 || (rm = reg_required_here (&str, 0)) == FAIL)
4171 {
4172 inst.error = BAD_ARGS;
4173 return;
4174 }
4175
4176 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4177 {
4178 inst.error = BAD_PC;
4179 return;
4180 }
a737bd4d
NC
4181
4182 /* Zero out the rotation field. */
09d92015 4183 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4184
4185 /* Check for lack of optional rotation field. */
09d92015
MM
4186 if (skip_past_comma (&str) == FAIL)
4187 {
4188 end_of_line (str);
4189 return;
4190 }
a737bd4d
NC
4191
4192 /* Move past 'ROR'. */
09d92015
MM
4193 skip_whitespace (str);
4194 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4195 str += 3;
09d92015
MM
4196 else
4197 {
4198 inst.error = _("missing rotation field after comma");
4199 return;
4200 }
a737bd4d
NC
4201
4202 /* Get the immediate constant. */
09d92015
MM
4203 skip_whitespace (str);
4204 if (is_immediate_prefix (* str))
4205 str++;
4206 else
4207 {
4208 inst.error = _("immediate expression expected");
4209 return;
4210 }
a737bd4d 4211
09d92015
MM
4212 if (my_get_expression (&expr, &str))
4213 {
4214 inst.error = _("bad expression");
4215 return;
4216 }
4217
4218 if (expr.X_op != O_constant)
4219 {
4220 inst.error = _("constant expression expected");
4221 return;
4222 }
a737bd4d
NC
4223
4224 switch (expr.X_add_number)
09d92015
MM
4225 {
4226 case 0:
a737bd4d 4227 /* Rotation field has already been zeroed. */
09d92015
MM
4228 break;
4229
4230 case 8:
4231 inst.instruction |= rotation_eight_mask;
4232 break;
4233
4234 case 16:
4235 inst.instruction |= rotation_sixteen_mask;
4236 break;
a737bd4d 4237
09d92015
MM
4238 case 24:
4239 inst.instruction |= rotation_twenty_four_mask;
4240 break;
4241
4242 default:
4243 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4244 break;
4245 }
4246
4247 end_of_line (str);
09d92015 4248}
a737bd4d 4249
09d92015
MM
4250
4251/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4252 word at the specified address and the following word
a737bd4d 4253 respectively.
09d92015 4254 Unconditionally executed.
a737bd4d 4255 Error if Rn is R15. */
09d92015
MM
4256
4257static void
a737bd4d 4258do_rfe (char * str)
09d92015
MM
4259{
4260 int rn;
4261
4262 skip_whitespace (str);
a737bd4d 4263
09d92015
MM
4264 if ((rn = reg_required_here (&str, 16)) == FAIL)
4265 return;
b99bd4ef 4266
09d92015 4267 if (rn == REG_PC)
b99bd4ef 4268 {
09d92015 4269 inst.error = BAD_PC;
b99bd4ef
NC
4270 return;
4271 }
4272
09d92015 4273 skip_whitespace (str);
a737bd4d 4274
09d92015
MM
4275 if (*str == '!')
4276 {
4277 inst.instruction |= WRITE_BACK;
4278 str++;
4279 }
b99bd4ef
NC
4280 end_of_line (str);
4281}
4282
09d92015
MM
4283/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4284 register (argument parse).
4285 REV{<cond>} Rd, Rm.
4286 Condition defaults to COND_ALWAYS.
a737bd4d 4287 Error if Rd or Rm are R15. */
b99bd4ef
NC
4288
4289static void
a737bd4d 4290do_rev (char * str)
b99bd4ef
NC
4291{
4292 int rd, rm;
4293
b99bd4ef
NC
4294 skip_whitespace (str);
4295
09d92015
MM
4296 if ((rd = reg_required_here (&str, 12)) == FAIL
4297 || skip_past_comma (&str) == FAIL
4298 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
4299 inst.error = BAD_ARGS;
4300
09d92015 4301 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
4302 inst.error = BAD_PC;
4303
4304 else
4305 end_of_line (str);
4306}
4307
09d92015 4308/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
a737bd4d 4309 QADD16{<cond>} <Rd>, <Rn>, <Rm>
09d92015
MM
4310 Condition defaults to COND_ALWAYS.
4311 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
4312
4313static void
a737bd4d 4314do_qadd16 (char * str)
b99bd4ef 4315{
09d92015
MM
4316 int rd, rm, rn;
4317
b99bd4ef
NC
4318 skip_whitespace (str);
4319
09d92015
MM
4320 if ((rd = reg_required_here (&str, 12)) == FAIL
4321 || skip_past_comma (&str) == FAIL
4322 || (rn = reg_required_here (&str, 16)) == FAIL
4323 || skip_past_comma (&str) == FAIL
4324 || (rm = reg_required_here (&str, 0)) == FAIL)
4325 inst.error = BAD_ARGS;
4326
4327 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4328 inst.error = BAD_PC;
4329
b99bd4ef
NC
4330 else
4331 end_of_line (str);
4332}
4333
b99bd4ef 4334static void
a737bd4d 4335do_pkh_core (char * str, int shift)
b99bd4ef 4336{
09d92015 4337 int rd, rn, rm;
b99bd4ef 4338
09d92015
MM
4339 skip_whitespace (str);
4340 if (((rd = reg_required_here (&str, 12)) == FAIL)
4341 || (skip_past_comma (&str) == FAIL)
4342 || ((rn = reg_required_here (&str, 16)) == FAIL)
4343 || (skip_past_comma (&str) == FAIL)
4344 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 4345 {
09d92015 4346 inst.error = BAD_ARGS;
b99bd4ef
NC
4347 return;
4348 }
4349
09d92015 4350 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 4351 {
09d92015 4352 inst.error = BAD_PC;
b99bd4ef
NC
4353 return;
4354 }
4355
a737bd4d
NC
4356 /* Check for optional shift immediate constant. */
4357 if (skip_past_comma (&str) == FAIL)
b99bd4ef 4358 {
09d92015
MM
4359 if (shift == SHIFT_ASR_IMMEDIATE)
4360 {
4361 /* If the shift specifier is ommited, turn the instruction
4362 into pkhbt rd, rm, rn. First, switch the instruction
4363 code, and clear the rn and rm fields. */
4364 inst.instruction &= 0xfff0f010;
4365 /* Now, re-encode the registers. */
4366 inst.instruction |= (rm << 16) | rn;
4367 }
b99bd4ef
NC
4368 return;
4369 }
4370
09d92015
MM
4371 decode_shift (&str, shift);
4372}
4373
a737bd4d
NC
4374/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4375 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4376 Condition defaults to COND_ALWAYS.
4377 Error if Rd, Rn or Rm are R15. */
4378
4379static void
4380do_pkhbt (char * str)
4381{
4382 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4383}
4384
4385/* ARM V6 PKHTB (Argument Parse). */
4386
4387static void
4388do_pkhtb (char * str)
4389{
4390 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4391}
4392
09d92015 4393/* ARM V6 Load Register Exclusive instruction (argument parse).
0dd132b6 4394 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
09d92015 4395 Condition defaults to COND_ALWAYS.
a737bd4d
NC
4396 Error if Rd or Rn are R15.
4397 See ARMARMv6 A4.1.27: LDREX. */
09d92015
MM
4398
4399static void
a737bd4d 4400do_ldrex (char * str)
09d92015
MM
4401{
4402 int rd, rn;
4403
4404 skip_whitespace (str);
4405
a737bd4d 4406 /* Parse Rd. */
09d92015
MM
4407 if (((rd = reg_required_here (&str, 12)) == FAIL)
4408 || (skip_past_comma (&str) == FAIL))
b99bd4ef 4409 {
09d92015 4410 inst.error = BAD_ARGS;
b99bd4ef
NC
4411 return;
4412 }
09d92015 4413 else if (rd == REG_PC)
b99bd4ef 4414 {
09d92015 4415 inst.error = BAD_PC;
b99bd4ef
NC
4416 return;
4417 }
a737bd4d 4418 skip_whitespace (str);
b99bd4ef 4419
a737bd4d
NC
4420 /* Skip past '['. */
4421 if ((strlen (str) >= 1)
09d92015 4422 &&strncmp (str, "[", 1) == 0)
a737bd4d
NC
4423 str += 1;
4424 skip_whitespace (str);
09d92015 4425
a737bd4d 4426 /* Parse Rn. */
09d92015 4427 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 4428 {
09d92015
MM
4429 inst.error = BAD_ARGS;
4430 return;
b99bd4ef 4431 }
09d92015
MM
4432 else if (rn == REG_PC)
4433 {
4434 inst.error = BAD_PC;
4435 return;
4436 }
a737bd4d 4437 skip_whitespace (str);
b99bd4ef 4438
a737bd4d
NC
4439 /* Skip past ']'. */
4440 if ((strlen (str) >= 1)
09d92015 4441 && strncmp (str, "]", 1) == 0)
a737bd4d
NC
4442 str += 1;
4443
b99bd4ef
NC
4444 end_of_line (str);
4445}
4446
09d92015 4447/* ARM V6 change processor state instruction (argument parse)
a737bd4d 4448 CPS, CPSIE, CSPID . */
b99bd4ef
NC
4449
4450static void
a737bd4d 4451do_cps (char * str)
b99bd4ef 4452{
09d92015
MM
4453 do_cps_mode (&str);
4454 end_of_line (str);
4455}
b99bd4ef 4456
09d92015 4457static void
a737bd4d 4458do_cps_flags (char ** str, int thumb_p)
ea6ef066 4459{
a737bd4d
NC
4460 struct cps_flag
4461 {
09d92015
MM
4462 char character;
4463 unsigned long arm_value;
4464 unsigned long thumb_value;
4465 };
a737bd4d
NC
4466 static struct cps_flag flag_table[] =
4467 {
09d92015
MM
4468 {'a', 0x100, 0x4 },
4469 {'i', 0x080, 0x2 },
4470 {'f', 0x040, 0x1 }
4471 };
ea6ef066 4472
09d92015 4473 int saw_a_flag = 0;
ea6ef066 4474
09d92015
MM
4475 skip_whitespace (*str);
4476
a737bd4d 4477 /* Get the a, f and i flags. */
09d92015 4478 while (**str && **str != ',')
ea6ef066 4479 {
09d92015
MM
4480 struct cps_flag *p;
4481 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
a737bd4d 4482
09d92015
MM
4483 for (p = flag_table; p < q; ++p)
4484 if (strncasecmp (*str, &p->character, 1) == 0)
4485 {
4486 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4487 saw_a_flag = 1;
4488 break;
4489 }
4490 if (p == q)
4491 {
4492 inst.error = _("unrecognized flag");
4493 return;
4494 }
4495 (*str)++;
ea6ef066 4496 }
a737bd4d
NC
4497
4498 if (!saw_a_flag)
4499 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4500}
4501
4502static void
4503do_cpsi (char * str)
4504{
4505 do_cps_flags (&str, /*thumb_p=*/0);
4506
4507 if (skip_past_comma (&str) == SUCCESS)
4508 {
4509 skip_whitespace (str);
4510 do_cps_mode (&str);
4511 }
4512 end_of_line (str);
ea6ef066
RE
4513}
4514
b99bd4ef
NC
4515/* THUMB V5 breakpoint instruction (argument parse)
4516 BKPT <immed_8>. */
4517
4518static void
a737bd4d 4519do_t_bkpt (char * str)
b99bd4ef
NC
4520{
4521 expressionS expr;
4522 unsigned long number;
4523
4524 skip_whitespace (str);
4525
4526 /* Allow optional leading '#'. */
4527 if (is_immediate_prefix (*str))
4528 str ++;
4529
4530 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
4531 if (my_get_expression (& expr, & str)
4532 || (expr.X_op != O_constant
4533 /* As a convenience we allow 'bkpt' without an operand. */
4534 && expr.X_op != O_absent))
b99bd4ef 4535 {
143c8e19 4536 inst.error = _("bad expression");
b99bd4ef
NC
4537 return;
4538 }
4539
4540 number = expr.X_add_number;
4541
4542 /* Check it fits an 8 bit unsigned. */
4543 if (number != (number & 0xff))
4544 {
4545 inst.error = _("immediate value out of range");
4546 return;
4547 }
4548
4549 inst.instruction |= number;
4550
4551 end_of_line (str);
4552}
4553
a737bd4d
NC
4554static bfd_reloc_code_real_type
4555arm_parse_reloc (void)
4556{
4557 char id [16];
4558 char * ip;
4559 unsigned int i;
4560 static struct
4561 {
4562 char * str;
4563 int len;
4564 bfd_reloc_code_real_type reloc;
4565 }
4566 reloc_map[] =
4567 {
4568#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4569 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4570 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4571 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4572 branch instructions generated by GCC for PLT relocs. */
4573 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4574 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4575 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4576 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4577 { NULL, 0, BFD_RELOC_UNUSED }
4578#undef MAP
4579 };
4580
4581 for (i = 0, ip = input_line_pointer;
4582 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4583 i++, ip++)
4584 id[i] = TOLOWER (*ip);
4585
4586 for (i = 0; reloc_map[i].str; i++)
4587 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4588 break;
4589
4590 input_line_pointer += reloc_map[i].len;
4591
4592 return reloc_map[i].reloc;
4593}
4594
b99bd4ef
NC
4595/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4596 Expects inst.instruction is set for BLX(1).
4597 Note: this is cloned from do_branch, and the reloc changed to be a
4598 new one that can cope with setting one extra bit (the H bit). */
4599
4600static void
a737bd4d 4601do_branch25 (char * str)
b99bd4ef
NC
4602{
4603 if (my_get_expression (& inst.reloc.exp, & str))
4604 return;
4605
4606#ifdef OBJ_ELF
4607 {
4608 char * save_in;
4609
4610 /* ScottB: February 5, 1998 */
4611 /* Check to see of PLT32 reloc required for the instruction. */
4612
4613 /* arm_parse_reloc() works on input_line_pointer.
4614 We actually want to parse the operands to the branch instruction
4615 passed in 'str'. Save the input pointer and restore it later. */
4616 save_in = input_line_pointer;
4617 input_line_pointer = str;
4618
4619 if (inst.reloc.exp.X_op == O_symbol
4620 && *str == '('
4621 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4622 {
4623 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4624 inst.reloc.pc_rel = 0;
4625 /* Modify str to point to after parsed operands, otherwise
4626 end_of_line() will complain about the (PLT) left in str. */
4627 str = input_line_pointer;
4628 }
4629 else
4630 {
4631 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4632 inst.reloc.pc_rel = 1;
4633 }
4634
4635 input_line_pointer = save_in;
4636 }
4637#else
4638 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4639 inst.reloc.pc_rel = 1;
4640#endif /* OBJ_ELF */
4641
4642 end_of_line (str);
4643}
4644
4645/* ARM V5 branch-link-exchange instruction (argument parse)
4646 BLX <target_addr> ie BLX(1)
4647 BLX{<condition>} <Rm> ie BLX(2)
4648 Unfortunately, there are two different opcodes for this mnemonic.
4649 So, the insns[].value is not used, and the code here zaps values
4650 into inst.instruction.
4651 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4652
4653static void
a737bd4d 4654do_blx (char * str)
b99bd4ef
NC
4655{
4656 char * mystr = str;
4657 int rm;
4658
b99bd4ef
NC
4659 skip_whitespace (mystr);
4660 rm = reg_required_here (& mystr, 0);
4661
4662 /* The above may set inst.error. Ignore his opinion. */
4663 inst.error = 0;
4664
4665 if (rm != FAIL)
4666 {
4667 /* Arg is a register.
4668 Use the condition code our caller put in inst.instruction.
4669 Pass ourselves off as a BX with a funny opcode. */
4670 inst.instruction |= 0x012fff30;
f2b7cb0a 4671 do_bx (str);
b99bd4ef
NC
4672 }
4673 else
4674 {
4675 /* This must be is BLX <target address>, no condition allowed. */
4676 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4677 {
4678 inst.error = BAD_COND;
b99bd4ef 4679 return;
cc8a6dd0 4680 }
b99bd4ef
NC
4681
4682 inst.instruction = 0xfafffffe;
4683
4684 /* Process like a B/BL, but with a different reloc.
4685 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4686 do_branch25 (str);
b99bd4ef
NC
4687 }
4688}
4689
4690/* ARM V5 Thumb BLX (argument parse)
4691 BLX <target_addr> which is BLX(1)
4692 BLX <Rm> which is BLX(2)
4693 Unfortunately, there are two different opcodes for this mnemonic.
4694 So, the tinsns[].value is not used, and the code here zaps values
4695 into inst.instruction. */
4696
4697static void
a737bd4d 4698do_t_blx (char * str)
b99bd4ef
NC
4699{
4700 char * mystr = str;
4701 int rm;
4702
4703 skip_whitespace (mystr);
4704 inst.instruction = 0x4780;
4705
4706 /* Note that this call is to the ARM register recognizer. BLX(2)
4707 uses the ARM register space, not the Thumb one, so a call to
4708 thumb_reg() would be wrong. */
4709 rm = reg_required_here (& mystr, 3);
4710 inst.error = 0;
4711
4712 if (rm != FAIL)
4713 {
4714 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4715 inst.size = 2;
4716 }
4717 else
4718 {
4719 /* No ARM register. This must be BLX(1). Change the .instruction. */
4720 inst.instruction = 0xf7ffeffe;
4721 inst.size = 4;
4722
4723 if (my_get_expression (& inst.reloc.exp, & mystr))
4724 return;
4725
4726 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
4727 inst.reloc.pc_rel = 1;
4728 }
4729
4730 end_of_line (mystr);
4731}
4732
4733/* ARM V5 breakpoint instruction (argument parse)
4734 BKPT <16 bit unsigned immediate>
4735 Instruction is not conditional.
4736 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 4737 and it is an error if the caller tried to override that. */
b99bd4ef
NC
4738
4739static void
a737bd4d 4740do_bkpt (char * str)
b99bd4ef
NC
4741{
4742 expressionS expr;
4743 unsigned long number;
4744
4745 skip_whitespace (str);
4746
4747 /* Allow optional leading '#'. */
4748 if (is_immediate_prefix (* str))
4749 str++;
4750
4751 memset (& expr, '\0', sizeof (expr));
4752
143c8e19
NC
4753 if (my_get_expression (& expr, & str)
4754 || (expr.X_op != O_constant
4755 /* As a convenience we allow 'bkpt' without an operand. */
4756 && expr.X_op != O_absent))
b99bd4ef 4757 {
143c8e19 4758 inst.error = _("bad expression");
b99bd4ef
NC
4759 return;
4760 }
4761
4762 number = expr.X_add_number;
4763
4764 /* Check it fits a 16 bit unsigned. */
4765 if (number != (number & 0xffff))
4766 {
4767 inst.error = _("immediate value out of range");
4768 return;
4769 }
4770
4771 /* Top 12 of 16 bits to bits 19:8. */
4772 inst.instruction |= (number & 0xfff0) << 4;
4773
4774 /* Bottom 4 of 16 bits to bits 3:0. */
4775 inst.instruction |= number & 0xf;
4776
4777 end_of_line (str);
b99bd4ef
NC
4778}
4779
09d92015
MM
4780/* THUMB CPS instruction (argument parse). */
4781
4782static void
a737bd4d 4783do_t_cps (char * str)
09d92015
MM
4784{
4785 do_cps_flags (&str, /*thumb_p=*/1);
4786 end_of_line (str);
4787}
4788
a737bd4d
NC
4789/* Parse and validate that a register is of the right form, this saves
4790 repeated checking of this information in many similar cases.
4791 Unlike the 32-bit case we do not insert the register into the opcode
4792 here, since the position is often unknown until the full instruction
4793 has been parsed. */
4794
4795static int
4796thumb_reg (char ** strp, int hi_lo)
4797{
4798 int reg;
4799
4800 if ((reg = reg_required_here (strp, -1)) == FAIL)
4801 return FAIL;
4802
4803 switch (hi_lo)
4804 {
4805 case THUMB_REG_LO:
4806 if (reg > 7)
4807 {
4808 inst.error = _("lo register required");
4809 return FAIL;
4810 }
4811 break;
4812
4813 case THUMB_REG_HI:
4814 if (reg < 8)
4815 {
4816 inst.error = _("hi register required");
4817 return FAIL;
4818 }
4819 break;
4820
4821 default:
4822 break;
4823 }
4824
4825 return reg;
4826}
4827
4828static void
4829thumb_mov_compare (char * str, int move)
4830{
4831 int Rd, Rs = FAIL;
4832
4833 skip_whitespace (str);
4834
4835 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4836 || skip_past_comma (&str) == FAIL)
4837 {
4838 if (! inst.error)
4839 inst.error = BAD_ARGS;
4840 return;
4841 }
4842
4843 if (move != THUMB_CPY && is_immediate_prefix (*str))
4844 {
4845 str++;
4846 if (my_get_expression (&inst.reloc.exp, &str))
4847 return;
4848 }
4849 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4850 return;
4851
4852 if (Rs != FAIL)
4853 {
4854 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
4855 {
4856 if (move == THUMB_MOVE)
4857 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4858 since a MOV instruction produces unpredictable results. */
4859 inst.instruction = T_OPCODE_ADD_I3;
4860 else
4861 inst.instruction = T_OPCODE_CMP_LR;
4862 inst.instruction |= Rd | (Rs << 3);
4863 }
4864 else
4865 {
4866 if (move == THUMB_MOVE)
4867 inst.instruction = T_OPCODE_MOV_HR;
4868 else if (move != THUMB_CPY)
4869 inst.instruction = T_OPCODE_CMP_HR;
4870
4871 if (Rd > 7)
4872 inst.instruction |= THUMB_H1;
4873
4874 if (Rs > 7)
4875 inst.instruction |= THUMB_H2;
4876
4877 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4878 }
4879 }
4880 else
4881 {
4882 if (Rd > 7)
4883 {
4884 inst.error = _("only lo regs allowed with immediate");
4885 return;
4886 }
4887
4888 if (move == THUMB_MOVE)
4889 inst.instruction = T_OPCODE_MOV_I8;
4890 else
4891 inst.instruction = T_OPCODE_CMP_I8;
4892
4893 inst.instruction |= Rd << 8;
4894
4895 if (inst.reloc.exp.X_op != O_constant)
4896 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4897 else
4898 {
4899 unsigned value = inst.reloc.exp.X_add_number;
4900
4901 if (value > 255)
4902 {
4903 inst.error = _("invalid immediate");
4904 return;
4905 }
4906
4907 inst.instruction |= value;
4908 }
4909 }
4910
4911 end_of_line (str);
4912}
4913
09d92015
MM
4914/* THUMB CPY instruction (argument parse). */
4915
4916static void
a737bd4d 4917do_t_cpy (char * str)
09d92015
MM
4918{
4919 thumb_mov_compare (str, THUMB_CPY);
4920}
4921
4922/* THUMB SETEND instruction (argument parse). */
4923
4924static void
a737bd4d 4925do_t_setend (char * str)
09d92015
MM
4926{
4927 if (do_endian_specifier (str))
4928 inst.instruction |= 0x8;
4929}
4930
e16bb312
NC
4931/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4932
4933static unsigned long
a737bd4d
NC
4934check_iwmmxt_insn (char * str,
4935 enum iwmmxt_insn_type insn_type,
4936 int immediate_size)
e16bb312
NC
4937{
4938 int reg = 0;
4939 const char * inst_error;
4940 expressionS expr;
4941 unsigned long number;
4942
4943 inst_error = inst.error;
4944 if (!inst.error)
4945 inst.error = BAD_ARGS;
4946 skip_whitespace (str);
4947
4948 switch (insn_type)
4949 {
4950 case check_rd:
4951 if ((reg = reg_required_here (&str, 12)) == FAIL)
4952 return FAIL;
4953 break;
a737bd4d 4954
e16bb312
NC
4955 case check_wr:
4956 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4957 return FAIL;
4958 break;
a737bd4d 4959
e16bb312
NC
4960 case check_wrwr:
4961 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4962 || skip_past_comma (&str) == FAIL
4963 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4964 return FAIL;
4965 break;
a737bd4d 4966
e16bb312
NC
4967 case check_wrwrwr:
4968 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4969 || skip_past_comma (&str) == FAIL
4970 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4971 || skip_past_comma (&str) == FAIL
4972 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4973 return FAIL;
4974 break;
a737bd4d 4975
e16bb312
NC
4976 case check_wrwrwcg:
4977 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4978 || skip_past_comma (&str) == FAIL
4979 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4980 || skip_past_comma (&str) == FAIL
4981 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4982 return FAIL;
4983 break;
a737bd4d 4984
e16bb312
NC
4985 case check_tbcst:
4986 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4987 || skip_past_comma (&str) == FAIL
4988 || reg_required_here (&str, 12) == FAIL))
4989 return FAIL;
4990 break;
a737bd4d 4991
e16bb312
NC
4992 case check_tmovmsk:
4993 if ((reg_required_here (&str, 12) == FAIL
4994 || skip_past_comma (&str) == FAIL
4995 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4996 return FAIL;
4997 break;
a737bd4d 4998
e16bb312
NC
4999 case check_tmia:
5000 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5001 || skip_past_comma (&str) == FAIL
5002 || reg_required_here (&str, 0) == FAIL
5003 || skip_past_comma (&str) == FAIL
5004 || reg_required_here (&str, 12) == FAIL))
5005 return FAIL;
5006 break;
a737bd4d 5007
e16bb312
NC
5008 case check_tmcrr:
5009 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5010 || skip_past_comma (&str) == FAIL
5011 || reg_required_here (&str, 12) == FAIL
5012 || skip_past_comma (&str) == FAIL
5013 || reg_required_here (&str, 16) == FAIL))
5014 return FAIL;
5015 break;
a737bd4d 5016
e16bb312
NC
5017 case check_tmrrc:
5018 if ((reg_required_here (&str, 12) == FAIL
5019 || skip_past_comma (&str) == FAIL
5020 || reg_required_here (&str, 16) == FAIL
5021 || skip_past_comma (&str) == FAIL
5022 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5023 return FAIL;
5024 break;
a737bd4d 5025
e16bb312
NC
5026 case check_tmcr:
5027 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5028 || skip_past_comma (&str) == FAIL
5029 || reg_required_here (&str, 12) == FAIL))
5030 return FAIL;
5031 break;
a737bd4d 5032
e16bb312
NC
5033 case check_tmrc:
5034 if ((reg_required_here (&str, 12) == FAIL
5035 || skip_past_comma (&str) == FAIL
5036 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5037 return FAIL;
5038 break;
a737bd4d 5039
e16bb312
NC
5040 case check_tinsr:
5041 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5042 || skip_past_comma (&str) == FAIL
5043 || reg_required_here (&str, 12) == FAIL
5044 || skip_past_comma (&str) == FAIL))
5045 return FAIL;
5046 break;
a737bd4d 5047
e16bb312
NC
5048 case check_textrc:
5049 if ((reg_required_here (&str, 12) == FAIL
5050 || skip_past_comma (&str) == FAIL))
5051 return FAIL;
5052 break;
a737bd4d 5053
e16bb312
NC
5054 case check_waligni:
5055 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5056 || skip_past_comma (&str) == FAIL
5057 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5058 || skip_past_comma (&str) == FAIL
5059 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5060 || skip_past_comma (&str) == FAIL))
5061 return FAIL;
5062 break;
a737bd4d 5063
e16bb312
NC
5064 case check_textrm:
5065 if ((reg_required_here (&str, 12) == FAIL
5066 || skip_past_comma (&str) == FAIL
5067 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5068 || skip_past_comma (&str) == FAIL))
5069 return FAIL;
5070 break;
a737bd4d 5071
e16bb312
NC
5072 case check_wshufh:
5073 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5074 || skip_past_comma (&str) == FAIL
5075 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5076 || skip_past_comma (&str) == FAIL))
5077 return FAIL;
5078 break;
5079 }
a737bd4d 5080
e16bb312
NC
5081 if (immediate_size == 0)
5082 {
5083 end_of_line (str);
5084 inst.error = inst_error;
5085 return reg;
5086 }
5087 else
5088 {
a737bd4d
NC
5089 skip_whitespace (str);
5090
5091 /* Allow optional leading '#'. */
e16bb312
NC
5092 if (is_immediate_prefix (* str))
5093 str++;
5094
5095 memset (& expr, '\0', sizeof (expr));
a737bd4d 5096
e16bb312
NC
5097 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5098 {
5099 inst.error = _("bad or missing expression");
5100 return FAIL;
5101 }
a737bd4d 5102
e16bb312 5103 number = expr.X_add_number;
a737bd4d 5104
e16bb312
NC
5105 if (number != (number & immediate_size))
5106 {
5107 inst.error = _("immediate value out of range");
5108 return FAIL;
5109 }
5110 end_of_line (str);
5111 inst.error = inst_error;
5112 return number;
5113 }
5114}
5115
5116static void
a737bd4d 5117do_iwmmxt_byte_addr (char * str)
e16bb312
NC
5118{
5119 int op = (inst.instruction & 0x300) >> 8;
5120 int reg;
5121
5122 inst.instruction &= ~0x300;
a737bd4d 5123 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5124
5125 skip_whitespace (str);
5126
5127 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5128 || skip_past_comma (& str) == FAIL
5129 || cp_byte_address_required_here (&str) == FAIL)
5130 {
5131 if (! inst.error)
5132 inst.error = BAD_ARGS;
5133 }
5134 else
5135 end_of_line (str);
5136
5137 if (wc_register (reg))
5138 {
ece01a63 5139 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5140 inst.instruction |= 0xf0000100;
5141 inst.instruction &= ~0x00400000;
5142 }
5143}
5144
5145static void
a737bd4d 5146do_iwmmxt_tandc (char * str)
e16bb312
NC
5147{
5148 int reg;
5149
5150 reg = check_iwmmxt_insn (str, check_rd, 0);
5151
5152 if (reg != REG_PC && !inst.error)
5153 inst.error = _("only r15 allowed here");
e16bb312
NC
5154}
5155
5156static void
a737bd4d 5157do_iwmmxt_tbcst (char * str)
e16bb312
NC
5158{
5159 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
5160}
5161
5162static void
a737bd4d 5163do_iwmmxt_textrc (char * str)
e16bb312
NC
5164{
5165 unsigned long number;
5166
5167 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5168 return;
5169
5170 inst.instruction |= number & 0x7;
e16bb312
NC
5171}
5172
5173static void
a737bd4d 5174do_iwmmxt_textrm (char * str)
e16bb312
NC
5175{
5176 unsigned long number;
5177
5178 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5179 return;
5180
5181 inst.instruction |= number & 0x7;
5182}
5183
5184static void
a737bd4d 5185do_iwmmxt_tinsr (char * str)
e16bb312
NC
5186{
5187 unsigned long number;
5188
5189 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5190 return;
5191
5192 inst.instruction |= number & 0x7;
e16bb312
NC
5193}
5194
5195static void
a737bd4d 5196do_iwmmxt_tmcr (char * str)
e16bb312
NC
5197{
5198 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
5199}
5200
5201static void
a737bd4d 5202do_iwmmxt_tmcrr (char * str)
e16bb312
NC
5203{
5204 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
5205}
5206
5207static void
a737bd4d 5208do_iwmmxt_tmia (char * str)
e16bb312
NC
5209{
5210 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
5211}
5212
5213static void
a737bd4d 5214do_iwmmxt_tmovmsk (char * str)
e16bb312
NC
5215{
5216 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
5217}
5218
5219static void
a737bd4d 5220do_iwmmxt_tmrc (char * str)
e16bb312
NC
5221{
5222 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
5223}
5224
5225static void
a737bd4d 5226do_iwmmxt_tmrrc (char * str)
e16bb312
NC
5227{
5228 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
5229}
5230
5231static void
a737bd4d 5232do_iwmmxt_torc (char * str)
e16bb312
NC
5233{
5234 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
5235}
5236
5237static void
a737bd4d 5238do_iwmmxt_waligni (char * str)
e16bb312
NC
5239{
5240 unsigned long number;
5241
5242 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5243 return;
5244
5245 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
5246}
5247
5248static void
a737bd4d 5249do_iwmmxt_wmov (char * str)
e16bb312
NC
5250{
5251 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5252 return;
a737bd4d 5253
e16bb312 5254 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
5255}
5256
5257static void
a737bd4d 5258do_iwmmxt_word_addr (char * str)
e16bb312
NC
5259{
5260 int op = (inst.instruction & 0x300) >> 8;
5261 int reg;
5262
5263 inst.instruction &= ~0x300;
a737bd4d 5264 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5265
5266 skip_whitespace (str);
5267
5268 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5269 || skip_past_comma (& str) == FAIL
5270 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5271 {
5272 if (! inst.error)
5273 inst.error = BAD_ARGS;
5274 }
5275 else
5276 end_of_line (str);
5277
5278 if (wc_register (reg))
5279 {
ece01a63
ILT
5280 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5281 as_bad (_("conditional execution not supported with control register"));
5282 if (op != 2)
5283 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5284 inst.instruction |= 0xf0000100;
5285 inst.instruction &= ~0x00400000;
5286 }
5287}
5288
5289static void
a737bd4d 5290do_iwmmxt_wrwr (char * str)
e16bb312
NC
5291{
5292 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
5293}
5294
5295static void
a737bd4d 5296do_iwmmxt_wrwrwcg (char * str)
e16bb312
NC
5297{
5298 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
5299}
5300
5301static void
a737bd4d 5302do_iwmmxt_wrwrwr (char * str)
e16bb312
NC
5303{
5304 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
5305}
5306
5307static void
a737bd4d 5308do_iwmmxt_wshufh (char * str)
e16bb312
NC
5309{
5310 unsigned long number;
5311
5312 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5313 return;
5314
5315 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
5316}
5317
5318static void
a737bd4d 5319do_iwmmxt_wzero (char * str)
e16bb312
NC
5320{
5321 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5322 return;
5323
5324 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
5325}
5326
b99bd4ef
NC
5327/* Xscale multiply-accumulate (argument parse)
5328 MIAcc acc0,Rm,Rs
5329 MIAPHcc acc0,Rm,Rs
5330 MIAxycc acc0,Rm,Rs. */
5331
5332static void
a737bd4d 5333do_xsc_mia (char * str)
b99bd4ef
NC
5334{
5335 int rs;
5336 int rm;
5337
f2b7cb0a 5338 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5339 inst.error = ERR_NO_ACCUM;
5340
5341 else if (skip_past_comma (& str) == FAIL
5342 || (rm = reg_required_here (& str, 0)) == FAIL)
5343 inst.error = BAD_ARGS;
5344
5345 else if (skip_past_comma (& str) == FAIL
5346 || (rs = reg_required_here (& str, 12)) == FAIL)
5347 inst.error = BAD_ARGS;
5348
5349 /* inst.instruction has now been zapped with both rm and rs. */
5350 else if (rm == REG_PC || rs == REG_PC)
5351 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5352
5353 else
5354 end_of_line (str);
5355}
5356
5357/* Xscale move-accumulator-register (argument parse)
5358
5359 MARcc acc0,RdLo,RdHi. */
5360
5361static void
a737bd4d 5362do_xsc_mar (char * str)
b99bd4ef
NC
5363{
5364 int rdlo, rdhi;
5365
f2b7cb0a 5366 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5367 inst.error = ERR_NO_ACCUM;
5368
5369 else if (skip_past_comma (& str) == FAIL
5370 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5371 inst.error = BAD_ARGS;
5372
5373 else if (skip_past_comma (& str) == FAIL
5374 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5375 inst.error = BAD_ARGS;
5376
5377 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5378 else if (rdlo == REG_PC || rdhi == REG_PC)
5379 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5380
5381 else
5382 end_of_line (str);
5383}
5384
5385/* Xscale move-register-accumulator (argument parse)
5386
5387 MRAcc RdLo,RdHi,acc0. */
5388
5389static void
a737bd4d 5390do_xsc_mra (char * str)
b99bd4ef
NC
5391{
5392 int rdlo;
5393 int rdhi;
5394
b99bd4ef
NC
5395 skip_whitespace (str);
5396
5397 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5398 inst.error = BAD_ARGS;
5399
5400 else if (skip_past_comma (& str) == FAIL
5401 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5402 inst.error = BAD_ARGS;
5403
5404 else if (skip_past_comma (& str) == FAIL
5405 || accum0_required_here (& str) == FAIL)
5406 inst.error = ERR_NO_ACCUM;
5407
a737bd4d
NC
5408 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5409 else if (rdlo == rdhi)
5410 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5411
5412 else if (rdlo == REG_PC || rdhi == REG_PC)
5413 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5414 else
5415 end_of_line (str);
5416}
5417
5418static int
5419ldst_extend (char ** str)
5420{
5421 int add = INDEX_UP;
5422
5423 switch (**str)
5424 {
5425 case '#':
5426 case '$':
5427 (*str)++;
5428 if (my_get_expression (& inst.reloc.exp, str))
5429 return FAIL;
5430
5431 if (inst.reloc.exp.X_op == O_constant)
5432 {
5433 int value = inst.reloc.exp.X_add_number;
5434
5435 if (value < -4095 || value > 4095)
5436 {
5437 inst.error = _("address offset too large");
5438 return FAIL;
5439 }
5440
5441 if (value < 0)
5442 {
5443 value = -value;
5444 add = 0;
5445 }
5446
5447 inst.instruction |= add | value;
5448 }
5449 else
5450 {
5451 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5452 inst.reloc.pc_rel = 0;
5453 }
5454 return SUCCESS;
5455
5456 case '-':
5457 add = 0;
5458 /* Fall through. */
5459
5460 case '+':
5461 (*str)++;
5462 /* Fall through. */
5463
5464 default:
5465 if (reg_required_here (str, 0) == FAIL)
5466 return FAIL;
5467
5468 inst.instruction |= add | OFFSET_REG;
5469 if (skip_past_comma (str) == SUCCESS)
5470 return decode_shift (str, SHIFT_IMMEDIATE);
b99bd4ef 5471
a737bd4d
NC
5472 return SUCCESS;
5473 }
b99bd4ef
NC
5474}
5475
c9b604bd 5476/* ARMv5TE: Preload-Cache
b99bd4ef
NC
5477
5478 PLD <addr_mode>
5479
5480 Syntactically, like LDR with B=1, W=0, L=1. */
5481
5482static void
a737bd4d 5483do_pld (char * str)
b99bd4ef
NC
5484{
5485 int rd;
5486
b99bd4ef
NC
5487 skip_whitespace (str);
5488
5489 if (* str != '[')
5490 {
5491 inst.error = _("'[' expected after PLD mnemonic");
5492 return;
5493 }
5494
90e4755a 5495 ++str;
b99bd4ef
NC
5496 skip_whitespace (str);
5497
5498 if ((rd = reg_required_here (& str, 16)) == FAIL)
5499 return;
5500
5501 skip_whitespace (str);
5502
90e4755a 5503 if (*str == ']')
b99bd4ef
NC
5504 {
5505 /* [Rn], ... ? */
90e4755a 5506 ++str;
b99bd4ef
NC
5507 skip_whitespace (str);
5508
90e4755a
RE
5509 /* Post-indexed addressing is not allowed with PLD. */
5510 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5511 {
90e4755a
RE
5512 inst.error
5513 = _("post-indexed expression used in preload instruction");
5514 return;
b99bd4ef 5515 }
90e4755a 5516 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
5517 {
5518 inst.error = _("writeback used in preload instruction");
90e4755a 5519 ++str;
b99bd4ef
NC
5520 }
5521 else /* [Rn] */
5522 inst.instruction |= INDEX_UP | PRE_INDEX;
5523 }
5524 else /* [Rn, ...] */
5525 {
5526 if (skip_past_comma (& str) == FAIL)
5527 {
5528 inst.error = _("pre-indexed expression expected");
5529 return;
5530 }
5531
90e4755a 5532 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
5533 return;
5534
5535 skip_whitespace (str);
5536
5537 if (* str != ']')
5538 {
5539 inst.error = _("missing ]");
5540 return;
5541 }
5542
5543 ++ str;
5544 skip_whitespace (str);
5545
5546 if (* str == '!') /* [Rn]! */
5547 {
5548 inst.error = _("writeback used in preload instruction");
5549 ++ str;
5550 }
5551
5552 inst.instruction |= PRE_INDEX;
5553 }
5554
5555 end_of_line (str);
5556}
5557
c9b604bd 5558/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
5559 Mode is like LDRH.
5560
5561 LDRccD R, mode
5562 STRccD R, mode. */
5563
5564static void
a737bd4d 5565do_ldrd (char * str)
b99bd4ef
NC
5566{
5567 int rd;
5568 int rn;
5569
b99bd4ef
NC
5570 skip_whitespace (str);
5571
5572 if ((rd = reg_required_here (& str, 12)) == FAIL)
5573 {
5574 inst.error = BAD_ARGS;
5575 return;
5576 }
5577
5578 if (skip_past_comma (& str) == FAIL
5579 || (rn = ld_mode_required_here (& str)) == FAIL)
5580 {
5581 if (!inst.error)
cc8a6dd0 5582 inst.error = BAD_ARGS;
a737bd4d 5583 return;
b99bd4ef
NC
5584 }
5585
a737bd4d
NC
5586 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5587 if (rd & 1) /* Unpredictable result if Rd is odd. */
5588 {
5589 inst.error = _("destination register must be even");
5590 return;
5591 }
b99bd4ef 5592
a737bd4d 5593 if (rd == REG_LR)
b99bd4ef 5594 {
a737bd4d
NC
5595 inst.error = _("r14 not allowed here");
5596 return;
b99bd4ef 5597 }
a737bd4d
NC
5598
5599 if (((rd == rn) || (rd + 1 == rn))
5600 && ((inst.instruction & WRITE_BACK)
5601 || (!(inst.instruction & PRE_INDEX))))
5602 as_warn (_("pre/post-indexing used when modified address register is destination"));
5603
5604 /* For an index-register load, the index register must not overlap the
5605 destination (even if not write-back). */
5606 if ((inst.instruction & V4_STR_BIT) == 0
5607 && (inst.instruction & HWOFFSET_IMM) == 0)
b99bd4ef 5608 {
a737bd4d
NC
5609 int rm = inst.instruction & 0x0000000f;
5610
5611 if (rm == rd || (rm == rd + 1))
5612 as_warn (_("ldrd destination registers must not overlap index register"));
b99bd4ef
NC
5613 }
5614
a737bd4d
NC
5615 end_of_line (str);
5616}
b99bd4ef 5617
a737bd4d
NC
5618/* Returns the index into fp_values of a floating point number,
5619 or -1 if not in the table. */
b99bd4ef 5620
a737bd4d
NC
5621static int
5622my_get_float_expression (char ** str)
5623{
5624 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5625 char * save_in;
5626 expressionS exp;
5627 int i;
5628 int j;
b99bd4ef 5629
a737bd4d
NC
5630 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5631
5632 /* Look for a raw floating point number. */
5633 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5634 && is_end_of_line[(unsigned char) *save_in])
5635 {
5636 for (i = 0; i < NUM_FLOAT_VALS; i++)
b99bd4ef 5637 {
a737bd4d 5638 for (j = 0; j < MAX_LITTLENUMS; j++)
b99bd4ef 5639 {
a737bd4d
NC
5640 if (words[j] != fp_values[i][j])
5641 break;
b99bd4ef 5642 }
a737bd4d
NC
5643
5644 if (j == MAX_LITTLENUMS)
b99bd4ef 5645 {
a737bd4d
NC
5646 *str = save_in;
5647 return i;
b99bd4ef
NC
5648 }
5649 }
a737bd4d 5650 }
b99bd4ef 5651
a737bd4d
NC
5652 /* Try and parse a more complex expression, this will probably fail
5653 unless the code uses a floating point prefix (eg "0f"). */
5654 save_in = input_line_pointer;
5655 input_line_pointer = *str;
5656 if (expression (&exp) == absolute_section
5657 && exp.X_op == O_big
5658 && exp.X_add_number < 0)
5659 {
5660 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5661 Ditto for 15. */
5662 if (gen_to_words (words, 5, (long) 15) == 0)
5663 {
5664 for (i = 0; i < NUM_FLOAT_VALS; i++)
5665 {
5666 for (j = 0; j < MAX_LITTLENUMS; j++)
5667 {
5668 if (words[j] != fp_values[i][j])
5669 break;
5670 }
b99bd4ef 5671
a737bd4d
NC
5672 if (j == MAX_LITTLENUMS)
5673 {
5674 *str = input_line_pointer;
5675 input_line_pointer = save_in;
5676 return i;
5677 }
5678 }
5679 }
b99bd4ef 5680 }
a737bd4d
NC
5681
5682 *str = input_line_pointer;
5683 input_line_pointer = save_in;
5684 return -1;
5685}
5686
5687/* We handle all bad expressions here, so that we can report the faulty
5688 instruction in the error message. */
5689void
5690md_operand (expressionS * expr)
5691{
5692 if (in_my_get_expression)
b99bd4ef 5693 {
a737bd4d
NC
5694 expr->X_op = O_illegal;
5695 if (inst.error == NULL)
5696 inst.error = _("bad expression");
b99bd4ef 5697 }
b99bd4ef
NC
5698}
5699
5700/* Do those data_ops which can take a negative immediate constant
2d2255b5 5701 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
5702 MOV <-> MVN
5703 AND <-> BIC
5704 ADC <-> SBC
5705 by inverting the second operand, and
5706 ADD <-> SUB
5707 CMP <-> CMN
5708 by negating the second operand. */
5709
5710static int
a737bd4d
NC
5711negate_data_op (unsigned long * instruction,
5712 unsigned long value)
b99bd4ef
NC
5713{
5714 int op, new_inst;
5715 unsigned long negated, inverted;
5716
5717 negated = validate_immediate (-value);
5718 inverted = validate_immediate (~value);
5719
5720 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5721 switch (op)
5722 {
5723 /* First negates. */
5724 case OPCODE_SUB: /* ADD <-> SUB */
5725 new_inst = OPCODE_ADD;
5726 value = negated;
5727 break;
5728
5729 case OPCODE_ADD:
5730 new_inst = OPCODE_SUB;
5731 value = negated;
5732 break;
5733
5734 case OPCODE_CMP: /* CMP <-> CMN */
5735 new_inst = OPCODE_CMN;
5736 value = negated;
5737 break;
5738
5739 case OPCODE_CMN:
5740 new_inst = OPCODE_CMP;
5741 value = negated;
5742 break;
5743
5744 /* Now Inverted ops. */
5745 case OPCODE_MOV: /* MOV <-> MVN */
5746 new_inst = OPCODE_MVN;
5747 value = inverted;
5748 break;
5749
5750 case OPCODE_MVN:
5751 new_inst = OPCODE_MOV;
5752 value = inverted;
5753 break;
5754
5755 case OPCODE_AND: /* AND <-> BIC */
5756 new_inst = OPCODE_BIC;
5757 value = inverted;
5758 break;
5759
5760 case OPCODE_BIC:
5761 new_inst = OPCODE_AND;
5762 value = inverted;
5763 break;
5764
5765 case OPCODE_ADC: /* ADC <-> SBC */
5766 new_inst = OPCODE_SBC;
5767 value = inverted;
5768 break;
5769
5770 case OPCODE_SBC:
5771 new_inst = OPCODE_ADC;
5772 value = inverted;
5773 break;
5774
5775 /* We cannot do anything. */
5776 default:
5777 return FAIL;
5778 }
5779
5780 if (value == (unsigned) FAIL)
5781 return FAIL;
5782
5783 *instruction &= OPCODE_MASK;
5784 *instruction |= new_inst << DATA_OP_SHIFT;
5785 return value;
5786}
5787
5788static int
a737bd4d 5789data_op2 (char ** str)
b99bd4ef
NC
5790{
5791 int value;
5792 expressionS expr;
5793
5794 skip_whitespace (* str);
5795
5796 if (reg_required_here (str, 0) != FAIL)
5797 {
5798 if (skip_past_comma (str) == SUCCESS)
5799 /* Shift operation on register. */
5800 return decode_shift (str, NO_SHIFT_RESTRICT);
5801
5802 return SUCCESS;
5803 }
5804 else
5805 {
5806 /* Immediate expression. */
5807 if (is_immediate_prefix (**str))
5808 {
5809 (*str)++;
5810 inst.error = NULL;
5811
5812 if (my_get_expression (&inst.reloc.exp, str))
5813 return FAIL;
5814
5815 if (inst.reloc.exp.X_add_symbol)
5816 {
5817 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5818 inst.reloc.pc_rel = 0;
5819 }
5820 else
5821 {
5822 if (skip_past_comma (str) == SUCCESS)
5823 {
5824 /* #x, y -- ie explicit rotation by Y. */
5825 if (my_get_expression (&expr, str))
5826 return FAIL;
5827
5828 if (expr.X_op != O_constant)
5829 {
f03698e6 5830 inst.error = _("constant expression expected");
b99bd4ef
NC
5831 return FAIL;
5832 }
5833
5834 /* Rotate must be a multiple of 2. */
5835 if (((unsigned) expr.X_add_number) > 30
5836 || (expr.X_add_number & 1) != 0
5837 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5838 {
f03698e6 5839 inst.error = _("invalid constant");
b99bd4ef
NC
5840 return FAIL;
5841 }
5842 inst.instruction |= INST_IMMEDIATE;
5843 inst.instruction |= inst.reloc.exp.X_add_number;
5844 inst.instruction |= expr.X_add_number << 7;
5845 return SUCCESS;
5846 }
5847
5848 /* Implicit rotation, select a suitable one. */
5849 value = validate_immediate (inst.reloc.exp.X_add_number);
5850
5851 if (value == FAIL)
5852 {
5853 /* Can't be done. Perhaps the code reads something like
5854 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5855 if ((value = negate_data_op (&inst.instruction,
5856 inst.reloc.exp.X_add_number))
5857 == FAIL)
5858 {
f03698e6 5859 inst.error = _("invalid constant");
b99bd4ef
NC
5860 return FAIL;
5861 }
5862 }
5863
5864 inst.instruction |= value;
5865 }
5866
5867 inst.instruction |= INST_IMMEDIATE;
5868 return SUCCESS;
5869 }
5870
5871 (*str)++;
f03698e6 5872 inst.error = _("register or shift expression expected");
b99bd4ef
NC
5873 return FAIL;
5874 }
5875}
5876
5877static int
a737bd4d 5878fp_op2 (char ** str)
b99bd4ef
NC
5879{
5880 skip_whitespace (* str);
5881
5882 if (fp_reg_required_here (str, 0) != FAIL)
5883 return SUCCESS;
5884 else
5885 {
5886 /* Immediate expression. */
5887 if (*((*str)++) == '#')
5888 {
5889 int i;
5890
5891 inst.error = NULL;
5892
5893 skip_whitespace (* str);
5894
5895 /* First try and match exact strings, this is to guarantee
5896 that some formats will work even for cross assembly. */
5897
5898 for (i = 0; fp_const[i]; i++)
5899 {
5900 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5901 {
5902 char *start = *str;
5903
5904 *str += strlen (fp_const[i]);
5905 if (is_end_of_line[(unsigned char) **str])
5906 {
5907 inst.instruction |= i + 8;
5908 return SUCCESS;
5909 }
5910 *str = start;
5911 }
5912 }
5913
5914 /* Just because we didn't get a match doesn't mean that the
5915 constant isn't valid, just that it is in a format that we
5916 don't automatically recognize. Try parsing it with
5917 the standard expression routines. */
5918 if ((i = my_get_float_expression (str)) >= 0)
5919 {
5920 inst.instruction |= i + 8;
5921 return SUCCESS;
5922 }
5923
f03698e6 5924 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
5925 return FAIL;
5926 }
5927 inst.error =
f03698e6 5928 _("floating point register or immediate expression expected");
b99bd4ef
NC
5929 return FAIL;
5930 }
5931}
5932
5933static void
a737bd4d 5934do_arit (char * str)
b99bd4ef
NC
5935{
5936 skip_whitespace (str);
5937
5938 if (reg_required_here (&str, 12) == FAIL
5939 || skip_past_comma (&str) == FAIL
5940 || reg_required_here (&str, 16) == FAIL
5941 || skip_past_comma (&str) == FAIL
5942 || data_op2 (&str) == FAIL)
5943 {
5944 if (!inst.error)
5945 inst.error = BAD_ARGS;
5946 return;
5947 }
5948
b99bd4ef 5949 end_of_line (str);
b99bd4ef
NC
5950}
5951
5952static void
a737bd4d 5953do_adr (char * str)
b99bd4ef 5954{
90e4755a
RE
5955 /* This is a pseudo-op of the form "adr rd, label" to be converted
5956 into a relative address of the form "add rd, pc, #label-.-8". */
5957 skip_whitespace (str);
5958
5959 if (reg_required_here (&str, 12) == FAIL
5960 || skip_past_comma (&str) == FAIL
5961 || my_get_expression (&inst.reloc.exp, &str))
5962 {
5963 if (!inst.error)
5964 inst.error = BAD_ARGS;
5965 return;
5966 }
5967
5968 /* Frag hacking will turn this into a sub instruction if the offset turns
5969 out to be negative. */
5970 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 5971#ifndef TE_WINCE
90e4755a 5972 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 5973#endif
90e4755a
RE
5974 inst.reloc.pc_rel = 1;
5975
5976 end_of_line (str);
5977}
5978
5979static void
a737bd4d 5980do_adrl (char * str)
90e4755a
RE
5981{
5982 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5983 into a relative address of the form:
5984 add rd, pc, #low(label-.-8)"
5985 add rd, rd, #high(label-.-8)" */
5986
5987 skip_whitespace (str);
5988
5989 if (reg_required_here (&str, 12) == FAIL
5990 || skip_past_comma (&str) == FAIL
5991 || my_get_expression (&inst.reloc.exp, &str))
5992 {
5993 if (!inst.error)
5994 inst.error = BAD_ARGS;
5995
5996 return;
5997 }
5998
5999 end_of_line (str);
6000 /* Frag hacking will turn this into a sub instruction if the offset turns
6001 out to be negative. */
6002 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
a737bd4d 6003#ifndef TE_WINCE
90e4755a 6004 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 6005#endif
90e4755a
RE
6006 inst.reloc.pc_rel = 1;
6007 inst.size = INSN_SIZE * 2;
90e4755a
RE
6008}
6009
6010static void
a737bd4d 6011do_cmp (char * str)
90e4755a
RE
6012{
6013 skip_whitespace (str);
6014
6015 if (reg_required_here (&str, 16) == FAIL)
6016 {
6017 if (!inst.error)
6018 inst.error = BAD_ARGS;
6019 return;
6020 }
6021
6022 if (skip_past_comma (&str) == FAIL
6023 || data_op2 (&str) == FAIL)
6024 {
6025 if (!inst.error)
6026 inst.error = BAD_ARGS;
6027 return;
6028 }
6029
90e4755a 6030 end_of_line (str);
90e4755a
RE
6031}
6032
6033static void
a737bd4d 6034do_mov (char * str)
90e4755a
RE
6035{
6036 skip_whitespace (str);
6037
6038 if (reg_required_here (&str, 12) == FAIL)
6039 {
6040 if (!inst.error)
6041 inst.error = BAD_ARGS;
6042 return;
6043 }
6044
6045 if (skip_past_comma (&str) == FAIL
6046 || data_op2 (&str) == FAIL)
6047 {
6048 if (!inst.error)
6049 inst.error = BAD_ARGS;
6050 return;
6051 }
6052
90e4755a 6053 end_of_line (str);
90e4755a
RE
6054}
6055
90e4755a 6056static void
a737bd4d 6057do_ldst (char * str)
90e4755a
RE
6058{
6059 int pre_inc = 0;
6060 int conflict_reg;
6061 int value;
6062
b99bd4ef
NC
6063 skip_whitespace (str);
6064
90e4755a
RE
6065 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6066 {
6067 if (!inst.error)
6068 inst.error = BAD_ARGS;
6069 return;
6070 }
6071
6072 if (skip_past_comma (&str) == FAIL)
6073 {
f03698e6 6074 inst.error = _("address expected");
90e4755a
RE
6075 return;
6076 }
6077
90e4755a
RE
6078 if (*str == '[')
6079 {
6080 int reg;
6081
6082 str++;
6083
6084 skip_whitespace (str);
6085
6086 if ((reg = reg_required_here (&str, 16)) == FAIL)
6087 return;
6088
6089 /* Conflicts can occur on stores as well as loads. */
6090 conflict_reg = (conflict_reg == reg);
6091
6092 skip_whitespace (str);
6093
6094 if (*str == ']')
6095 {
6096 str ++;
6097
6098 if (skip_past_comma (&str) == SUCCESS)
6099 {
6100 /* [Rn],... (post inc) */
6101 if (ldst_extend (&str) == FAIL)
6102 return;
6103 if (conflict_reg)
6104 as_warn (_("%s register same as write-back base"),
6105 ((inst.instruction & LOAD_BIT)
6106 ? _("destination") : _("source")));
6107 }
6108 else
6109 {
6110 /* [Rn] */
6111 skip_whitespace (str);
6112
6113 if (*str == '!')
6114 {
6115 if (conflict_reg)
6116 as_warn (_("%s register same as write-back base"),
6117 ((inst.instruction & LOAD_BIT)
6118 ? _("destination") : _("source")));
6119 str++;
6120 inst.instruction |= WRITE_BACK;
6121 }
6122
6123 inst.instruction |= INDEX_UP;
6124 pre_inc = 1;
6125 }
6126 }
6127 else
6128 {
6129 /* [Rn,...] */
6130 if (skip_past_comma (&str) == FAIL)
6131 {
6132 inst.error = _("pre-indexed expression expected");
6133 return;
6134 }
6135
6136 pre_inc = 1;
6137 if (ldst_extend (&str) == FAIL)
6138 return;
6139
6140 skip_whitespace (str);
6141
6142 if (*str++ != ']')
6143 {
6144 inst.error = _("missing ]");
6145 return;
6146 }
6147
6148 skip_whitespace (str);
6149
6150 if (*str == '!')
6151 {
6152 if (conflict_reg)
6153 as_warn (_("%s register same as write-back base"),
6154 ((inst.instruction & LOAD_BIT)
6155 ? _("destination") : _("source")));
6156 str++;
6157 inst.instruction |= WRITE_BACK;
6158 }
6159 }
6160 }
6161 else if (*str == '=')
6162 {
f03698e6
RE
6163 if ((inst.instruction & LOAD_BIT) == 0)
6164 {
6165 inst.error = _("invalid pseudo operation");
6166 return;
6167 }
6168
90e4755a
RE
6169 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6170 str++;
6171
6172 skip_whitespace (str);
6173
6174 if (my_get_expression (&inst.reloc.exp, &str))
6175 return;
6176
6177 if (inst.reloc.exp.X_op != O_constant
6178 && inst.reloc.exp.X_op != O_symbol)
6179 {
f03698e6 6180 inst.error = _("constant expression expected");
90e4755a
RE
6181 return;
6182 }
6183
e28cd48c 6184 if (inst.reloc.exp.X_op == O_constant)
90e4755a 6185 {
e28cd48c
RE
6186 value = validate_immediate (inst.reloc.exp.X_add_number);
6187
6188 if (value != FAIL)
90e4755a 6189 {
e28cd48c
RE
6190 /* This can be done with a mov instruction. */
6191 inst.instruction &= LITERAL_MASK;
6192 inst.instruction |= (INST_IMMEDIATE
6193 | (OPCODE_MOV << DATA_OP_SHIFT));
6194 inst.instruction |= value & 0xfff;
6195 end_of_line (str);
90e4755a
RE
6196 return;
6197 }
b99bd4ef 6198
e28cd48c
RE
6199 value = validate_immediate (~inst.reloc.exp.X_add_number);
6200
6201 if (value != FAIL)
6202 {
6203 /* This can be done with a mvn instruction. */
6204 inst.instruction &= LITERAL_MASK;
6205 inst.instruction |= (INST_IMMEDIATE
6206 | (OPCODE_MVN << DATA_OP_SHIFT));
6207 inst.instruction |= value & 0xfff;
6208 end_of_line (str);
6209 return;
6210 }
90e4755a 6211 }
e28cd48c
RE
6212
6213 /* Insert into literal pool. */
6214 if (add_to_lit_pool () == FAIL)
6215 {
6216 if (!inst.error)
6217 inst.error = _("literal pool insertion failed");
6218 return;
6219 }
6220
6221 /* Change the instruction exp to point to the pool. */
6222 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6223 inst.reloc.pc_rel = 1;
6224 inst.instruction |= (REG_PC << 16);
6225 pre_inc = 1;
1cac9012
NC
6226 }
6227 else
6228 {
90e4755a
RE
6229 if (my_get_expression (&inst.reloc.exp, &str))
6230 return;
6231
6232 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6233#ifndef TE_WINCE
6234 /* PC rel adjust. */
6235 inst.reloc.exp.X_add_number -= 8;
6236#endif
1cac9012 6237 inst.reloc.pc_rel = 1;
90e4755a
RE
6238 inst.instruction |= (REG_PC << 16);
6239 pre_inc = 1;
b99bd4ef
NC
6240 }
6241
90e4755a 6242 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6243 end_of_line (str);
b99bd4ef
NC
6244}
6245
6246static void
a737bd4d 6247do_ldstt (char * str)
b99bd4ef 6248{
90e4755a
RE
6249 int conflict_reg;
6250
b99bd4ef
NC
6251 skip_whitespace (str);
6252
90e4755a 6253 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
6254 {
6255 if (!inst.error)
6256 inst.error = BAD_ARGS;
6257 return;
6258 }
6259
90e4755a 6260 if (skip_past_comma (& str) == FAIL)
b99bd4ef 6261 {
f03698e6 6262 inst.error = _("address expected");
b99bd4ef
NC
6263 return;
6264 }
6265
90e4755a
RE
6266 if (*str == '[')
6267 {
6268 int reg;
b99bd4ef 6269
90e4755a 6270 str++;
b99bd4ef 6271
90e4755a 6272 skip_whitespace (str);
b99bd4ef 6273
90e4755a
RE
6274 if ((reg = reg_required_here (&str, 16)) == FAIL)
6275 return;
b99bd4ef 6276
90e4755a
RE
6277 /* ldrt/strt always use post-indexed addressing, so if the base is
6278 the same as Rd, we warn. */
6279 if (conflict_reg == reg)
6280 as_warn (_("%s register same as write-back base"),
6281 ((inst.instruction & LOAD_BIT)
6282 ? _("destination") : _("source")));
6283
6284 skip_whitespace (str);
6285
6286 if (*str == ']')
6287 {
6288 str ++;
6289
6290 if (skip_past_comma (&str) == SUCCESS)
6291 {
6292 /* [Rn],... (post inc) */
6293 if (ldst_extend (&str) == FAIL)
6294 return;
6295 }
6296 else
6297 {
6298 /* [Rn] */
6299 skip_whitespace (str);
6300
6301 /* Skip a write-back '!'. */
6302 if (*str == '!')
6303 str++;
6304
6305 inst.instruction |= INDEX_UP;
6306 }
6307 }
6308 else
6309 {
6310 inst.error = _("post-indexed expression expected");
6311 return;
6312 }
6313 }
6314 else
b99bd4ef 6315 {
90e4755a 6316 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
6317 return;
6318 }
6319
b99bd4ef 6320 end_of_line (str);
b99bd4ef
NC
6321}
6322
90e4755a 6323/* Halfword and signed-byte load/store operations. */
a737bd4d 6324
b99bd4ef 6325static void
a737bd4d 6326do_ldstv4 (char * str)
b99bd4ef 6327{
b99bd4ef
NC
6328 int pre_inc = 0;
6329 int conflict_reg;
6330 int value;
6331
b99bd4ef
NC
6332 skip_whitespace (str);
6333
6334 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6335 {
6336 if (!inst.error)
6337 inst.error = BAD_ARGS;
6338 return;
6339 }
6340
6341 if (skip_past_comma (& str) == FAIL)
6342 {
f03698e6 6343 inst.error = _("address expected");
b99bd4ef
NC
6344 return;
6345 }
6346
6347 if (*str == '[')
6348 {
6349 int reg;
6350
6351 str++;
6352
6353 skip_whitespace (str);
6354
6355 if ((reg = reg_required_here (&str, 16)) == FAIL)
6356 return;
6357
6358 /* Conflicts can occur on stores as well as loads. */
6359 conflict_reg = (conflict_reg == reg);
6360
6361 skip_whitespace (str);
6362
6363 if (*str == ']')
6364 {
6365 str ++;
6366
6367 if (skip_past_comma (&str) == SUCCESS)
6368 {
6369 /* [Rn],... (post inc) */
90e4755a 6370 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6371 return;
6372 if (conflict_reg)
90e4755a
RE
6373 as_warn (_("%s register same as write-back base"),
6374 ((inst.instruction & LOAD_BIT)
6375 ? _("destination") : _("source")));
b99bd4ef
NC
6376 }
6377 else
6378 {
6379 /* [Rn] */
90e4755a 6380 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
6381
6382 skip_whitespace (str);
6383
6384 if (*str == '!')
6385 {
6386 if (conflict_reg)
6387 as_warn (_("%s register same as write-back base"),
6388 ((inst.instruction & LOAD_BIT)
6389 ? _("destination") : _("source")));
6390 str++;
6391 inst.instruction |= WRITE_BACK;
6392 }
6393
90e4755a
RE
6394 inst.instruction |= INDEX_UP;
6395 pre_inc = 1;
b99bd4ef
NC
6396 }
6397 }
6398 else
6399 {
6400 /* [Rn,...] */
6401 if (skip_past_comma (&str) == FAIL)
6402 {
6403 inst.error = _("pre-indexed expression expected");
6404 return;
6405 }
6406
6407 pre_inc = 1;
90e4755a 6408 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6409 return;
6410
6411 skip_whitespace (str);
6412
6413 if (*str++ != ']')
6414 {
6415 inst.error = _("missing ]");
6416 return;
6417 }
6418
6419 skip_whitespace (str);
6420
6421 if (*str == '!')
6422 {
6423 if (conflict_reg)
6424 as_warn (_("%s register same as write-back base"),
6425 ((inst.instruction & LOAD_BIT)
6426 ? _("destination") : _("source")));
6427 str++;
6428 inst.instruction |= WRITE_BACK;
6429 }
6430 }
6431 }
6432 else if (*str == '=')
6433 {
f03698e6
RE
6434 if ((inst.instruction & LOAD_BIT) == 0)
6435 {
6436 inst.error = _("invalid pseudo operation");
6437 return;
6438 }
6439
90e4755a 6440 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
6441 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6442 str++;
6443
6444 skip_whitespace (str);
6445
6446 if (my_get_expression (&inst.reloc.exp, &str))
6447 return;
6448
6449 if (inst.reloc.exp.X_op != O_constant
6450 && inst.reloc.exp.X_op != O_symbol)
6451 {
f03698e6 6452 inst.error = _("constant expression expected");
b99bd4ef
NC
6453 return;
6454 }
6455
d8273442 6456 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 6457 {
d8273442
NC
6458 value = validate_immediate (inst.reloc.exp.X_add_number);
6459
6460 if (value != FAIL)
b99bd4ef 6461 {
d8273442
NC
6462 /* This can be done with a mov instruction. */
6463 inst.instruction &= LITERAL_MASK;
6464 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 6465 inst.instruction |= value & 0xfff;
d8273442 6466 end_of_line (str);
b99bd4ef
NC
6467 return;
6468 }
cc8a6dd0 6469
d8273442 6470 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 6471
d8273442 6472 if (value != FAIL)
b99bd4ef 6473 {
d8273442
NC
6474 /* This can be done with a mvn instruction. */
6475 inst.instruction &= LITERAL_MASK;
6476 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 6477 inst.instruction |= value & 0xfff;
d8273442
NC
6478 end_of_line (str);
6479 return;
b99bd4ef 6480 }
b99bd4ef 6481 }
d8273442
NC
6482
6483 /* Insert into literal pool. */
6484 if (add_to_lit_pool () == FAIL)
6485 {
6486 if (!inst.error)
6487 inst.error = _("literal pool insertion failed");
6488 return;
6489 }
6490
6491 /* Change the instruction exp to point to the pool. */
90e4755a
RE
6492 inst.instruction |= HWOFFSET_IMM;
6493 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
6494 inst.reloc.pc_rel = 1;
6495 inst.instruction |= (REG_PC << 16);
6496 pre_inc = 1;
b99bd4ef
NC
6497 }
6498 else
6499 {
6500 if (my_get_expression (&inst.reloc.exp, &str))
6501 return;
6502
90e4755a
RE
6503 inst.instruction |= HWOFFSET_IMM;
6504 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
6505#ifndef TE_WINCE
6506 /* PC rel adjust. */
6507 inst.reloc.exp.X_add_number -= 8;
6508#endif
6509 inst.reloc.pc_rel = 1;
6510 inst.instruction |= (REG_PC << 16);
6511 pre_inc = 1;
6512 }
6513
90e4755a 6514 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6515 end_of_line (str);
b99bd4ef
NC
6516}
6517
6518static long
a737bd4d 6519reg_list (char ** strp)
b99bd4ef
NC
6520{
6521 char * str = * strp;
6522 long range = 0;
6523 int another_range;
6524
6525 /* We come back here if we get ranges concatenated by '+' or '|'. */
6526 do
6527 {
6528 another_range = 0;
6529
6530 if (*str == '{')
6531 {
6532 int in_range = 0;
6533 int cur_reg = -1;
6534
6535 str++;
6536 do
6537 {
6538 int reg;
6539
6540 skip_whitespace (str);
6541
6542 if ((reg = reg_required_here (& str, -1)) == FAIL)
6543 return FAIL;
6544
6545 if (in_range)
6546 {
6547 int i;
6548
6549 if (reg <= cur_reg)
6550 {
f03698e6 6551 inst.error = _("bad range in register list");
b99bd4ef
NC
6552 return FAIL;
6553 }
6554
6555 for (i = cur_reg + 1; i < reg; i++)
6556 {
6557 if (range & (1 << i))
6558 as_tsktsk
f03698e6 6559 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6560 i);
6561 else
6562 range |= 1 << i;
6563 }
6564 in_range = 0;
6565 }
6566
6567 if (range & (1 << reg))
f03698e6 6568 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6569 reg);
6570 else if (reg <= cur_reg)
f03698e6 6571 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
6572
6573 range |= 1 << reg;
6574 cur_reg = reg;
6575 }
6576 while (skip_past_comma (&str) != FAIL
6577 || (in_range = 1, *str++ == '-'));
6578 str--;
6579 skip_whitespace (str);
6580
6581 if (*str++ != '}')
6582 {
f03698e6 6583 inst.error = _("missing `}'");
b99bd4ef
NC
6584 return FAIL;
6585 }
6586 }
6587 else
6588 {
6589 expressionS expr;
6590
6591 if (my_get_expression (&expr, &str))
6592 return FAIL;
6593
6594 if (expr.X_op == O_constant)
6595 {
6596 if (expr.X_add_number
6597 != (expr.X_add_number & 0x0000ffff))
6598 {
6599 inst.error = _("invalid register mask");
6600 return FAIL;
6601 }
6602
6603 if ((range & expr.X_add_number) != 0)
6604 {
6605 int regno = range & expr.X_add_number;
6606
6607 regno &= -regno;
6608 regno = (1 << regno) - 1;
6609 as_tsktsk
f03698e6 6610 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6611 regno);
6612 }
6613
6614 range |= expr.X_add_number;
6615 }
6616 else
6617 {
6618 if (inst.reloc.type != 0)
6619 {
6620 inst.error = _("expression too complex");
6621 return FAIL;
6622 }
6623
6624 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6625 inst.reloc.type = BFD_RELOC_ARM_MULTI;
6626 inst.reloc.pc_rel = 0;
6627 }
6628 }
6629
6630 skip_whitespace (str);
6631
6632 if (*str == '|' || *str == '+')
6633 {
6634 str++;
6635 another_range = 1;
6636 }
6637 }
6638 while (another_range);
6639
6640 *strp = str;
6641 return range;
6642}
6643
6644static void
a737bd4d 6645do_ldmstm (char * str)
b99bd4ef
NC
6646{
6647 int base_reg;
6648 long range;
6649
6650 skip_whitespace (str);
6651
6652 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6653 return;
6654
6655 if (base_reg == REG_PC)
6656 {
6657 inst.error = _("r15 not allowed as base register");
6658 return;
6659 }
6660
6661 skip_whitespace (str);
6662
6663 if (*str == '!')
6664 {
90e4755a 6665 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
6666 str++;
6667 }
6668
6669 if (skip_past_comma (&str) == FAIL
6670 || (range = reg_list (&str)) == FAIL)
6671 {
6672 if (! inst.error)
6673 inst.error = BAD_ARGS;
6674 return;
6675 }
6676
6677 if (*str == '^')
6678 {
6679 str++;
90e4755a 6680 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
6681 }
6682
6189168b
NC
6683 if (inst.instruction & WRITE_BACK)
6684 {
6685 /* Check for unpredictable uses of writeback. */
6686 if (inst.instruction & LOAD_BIT)
6687 {
6688 /* Not allowed in LDM type 2. */
6689 if ((inst.instruction & LDM_TYPE_2_OR_3)
6690 && ((range & (1 << REG_PC)) == 0))
6691 as_warn (_("writeback of base register is UNPREDICTABLE"));
6692 /* Only allowed if base reg not in list for other types. */
6693 else if (range & (1 << base_reg))
6694 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6695 }
6696 else /* STM. */
6697 {
6698 /* Not allowed for type 2. */
6699 if (inst.instruction & LDM_TYPE_2_OR_3)
6700 as_warn (_("writeback of base register is UNPREDICTABLE"));
6701 /* Only allowed if base reg not in list, or first in list. */
6702 else if ((range & (1 << base_reg))
6703 && (range & ((1 << base_reg) - 1)))
6704 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6705 }
6706 }
61b5f74b 6707
f2b7cb0a 6708 inst.instruction |= range;
b99bd4ef 6709 end_of_line (str);
b99bd4ef
NC
6710}
6711
0dd132b6
NC
6712static void
6713do_smi (char * str)
6714{
6715 skip_whitespace (str);
6716
6717 /* Allow optional leading '#'. */
6718 if (is_immediate_prefix (*str))
6719 str++;
6720
6721 if (my_get_expression (& inst.reloc.exp, & str))
6722 return;
6723
6724 inst.reloc.type = BFD_RELOC_ARM_SMI;
6725 inst.reloc.pc_rel = 0;
6726 end_of_line (str);
6727}
6728
b99bd4ef 6729static void
a737bd4d 6730do_swi (char * str)
b99bd4ef
NC
6731{
6732 skip_whitespace (str);
6733
6734 /* Allow optional leading '#'. */
6735 if (is_immediate_prefix (*str))
6736 str++;
6737
6738 if (my_get_expression (& inst.reloc.exp, & str))
6739 return;
6740
6741 inst.reloc.type = BFD_RELOC_ARM_SWI;
6742 inst.reloc.pc_rel = 0;
b99bd4ef 6743 end_of_line (str);
b99bd4ef
NC
6744}
6745
6746static void
a737bd4d 6747do_swap (char * str)
b99bd4ef
NC
6748{
6749 int reg;
6750
6751 skip_whitespace (str);
6752
6753 if ((reg = reg_required_here (&str, 12)) == FAIL)
6754 return;
6755
6756 if (reg == REG_PC)
6757 {
6758 inst.error = _("r15 not allowed in swap");
6759 return;
6760 }
6761
6762 if (skip_past_comma (&str) == FAIL
6763 || (reg = reg_required_here (&str, 0)) == FAIL)
6764 {
6765 if (!inst.error)
6766 inst.error = BAD_ARGS;
6767 return;
6768 }
6769
6770 if (reg == REG_PC)
6771 {
6772 inst.error = _("r15 not allowed in swap");
6773 return;
6774 }
6775
6776 if (skip_past_comma (&str) == FAIL
6777 || *str++ != '[')
6778 {
6779 inst.error = BAD_ARGS;
6780 return;
6781 }
6782
6783 skip_whitespace (str);
6784
6785 if ((reg = reg_required_here (&str, 16)) == FAIL)
6786 return;
6787
6788 if (reg == REG_PC)
6789 {
6790 inst.error = BAD_PC;
6791 return;
6792 }
6793
6794 skip_whitespace (str);
6795
6796 if (*str++ != ']')
6797 {
6798 inst.error = _("missing ]");
6799 return;
6800 }
6801
b99bd4ef 6802 end_of_line (str);
b99bd4ef
NC
6803}
6804
6805static void
a737bd4d 6806do_branch (char * str)
b99bd4ef
NC
6807{
6808 if (my_get_expression (&inst.reloc.exp, &str))
6809 return;
6810
6811#ifdef OBJ_ELF
6812 {
6813 char * save_in;
6814
6815 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6816 required for the instruction. */
6817
6818 /* arm_parse_reloc () works on input_line_pointer.
6819 We actually want to parse the operands to the branch instruction
6820 passed in 'str'. Save the input pointer and restore it later. */
6821 save_in = input_line_pointer;
6822 input_line_pointer = str;
6823 if (inst.reloc.exp.X_op == O_symbol
6824 && *str == '('
6825 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6826 {
6827 inst.reloc.type = BFD_RELOC_ARM_PLT32;
6828 inst.reloc.pc_rel = 0;
6829 /* Modify str to point to after parsed operands, otherwise
6830 end_of_line() will complain about the (PLT) left in str. */
6831 str = input_line_pointer;
6832 }
6833 else
6834 {
6835 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6836 inst.reloc.pc_rel = 1;
6837 }
6838 input_line_pointer = save_in;
6839 }
6840#else
6841 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
6842 inst.reloc.pc_rel = 1;
6843#endif /* OBJ_ELF */
6844
6845 end_of_line (str);
b99bd4ef
NC
6846}
6847
6848static void
a737bd4d 6849do_cdp (char * str)
b99bd4ef
NC
6850{
6851 /* Co-processor data operation.
6852 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6853 skip_whitespace (str);
6854
6855 if (co_proc_number (&str) == FAIL)
6856 {
6857 if (!inst.error)
6858 inst.error = BAD_ARGS;
6859 return;
6860 }
6861
6862 if (skip_past_comma (&str) == FAIL
6863 || cp_opc_expr (&str, 20,4) == FAIL)
6864 {
6865 if (!inst.error)
6866 inst.error = BAD_ARGS;
6867 return;
6868 }
6869
6870 if (skip_past_comma (&str) == FAIL
6871 || cp_reg_required_here (&str, 12) == FAIL)
6872 {
6873 if (!inst.error)
6874 inst.error = BAD_ARGS;
6875 return;
6876 }
6877
6878 if (skip_past_comma (&str) == FAIL
6879 || cp_reg_required_here (&str, 16) == FAIL)
6880 {
6881 if (!inst.error)
6882 inst.error = BAD_ARGS;
6883 return;
6884 }
6885
6886 if (skip_past_comma (&str) == FAIL
6887 || cp_reg_required_here (&str, 0) == FAIL)
6888 {
6889 if (!inst.error)
6890 inst.error = BAD_ARGS;
6891 return;
6892 }
6893
6894 if (skip_past_comma (&str) == SUCCESS)
6895 {
6896 if (cp_opc_expr (&str, 5, 3) == FAIL)
6897 {
6898 if (!inst.error)
6899 inst.error = BAD_ARGS;
6900 return;
6901 }
6902 }
6903
6904 end_of_line (str);
b99bd4ef
NC
6905}
6906
6907static void
a737bd4d 6908do_lstc (char * str)
b99bd4ef
NC
6909{
6910 /* Co-processor register load/store.
6911 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6912
6913 skip_whitespace (str);
6914
6915 if (co_proc_number (&str) == FAIL)
6916 {
6917 if (!inst.error)
6918 inst.error = BAD_ARGS;
6919 return;
6920 }
6921
6922 if (skip_past_comma (&str) == FAIL
6923 || cp_reg_required_here (&str, 12) == FAIL)
6924 {
6925 if (!inst.error)
6926 inst.error = BAD_ARGS;
6927 return;
6928 }
6929
6930 if (skip_past_comma (&str) == FAIL
bfae80f2 6931 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
6932 {
6933 if (! inst.error)
6934 inst.error = BAD_ARGS;
6935 return;
6936 }
6937
b99bd4ef 6938 end_of_line (str);
b99bd4ef
NC
6939}
6940
6941static void
a737bd4d 6942do_co_reg (char * str)
b99bd4ef
NC
6943{
6944 /* Co-processor register transfer.
6945 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6946
6947 skip_whitespace (str);
6948
6949 if (co_proc_number (&str) == FAIL)
6950 {
6951 if (!inst.error)
6952 inst.error = BAD_ARGS;
6953 return;
6954 }
6955
6956 if (skip_past_comma (&str) == FAIL
6957 || cp_opc_expr (&str, 21, 3) == FAIL)
6958 {
6959 if (!inst.error)
6960 inst.error = BAD_ARGS;
6961 return;
6962 }
6963
6964 if (skip_past_comma (&str) == FAIL
6965 || reg_required_here (&str, 12) == FAIL)
6966 {
6967 if (!inst.error)
6968 inst.error = BAD_ARGS;
6969 return;
6970 }
6971
6972 if (skip_past_comma (&str) == FAIL
6973 || cp_reg_required_here (&str, 16) == FAIL)
6974 {
6975 if (!inst.error)
6976 inst.error = BAD_ARGS;
6977 return;
6978 }
6979
6980 if (skip_past_comma (&str) == FAIL
6981 || cp_reg_required_here (&str, 0) == FAIL)
6982 {
6983 if (!inst.error)
6984 inst.error = BAD_ARGS;
6985 return;
6986 }
6987
6988 if (skip_past_comma (&str) == SUCCESS)
6989 {
6990 if (cp_opc_expr (&str, 5, 3) == FAIL)
6991 {
6992 if (!inst.error)
6993 inst.error = BAD_ARGS;
6994 return;
6995 }
6996 }
b99bd4ef
NC
6997
6998 end_of_line (str);
b99bd4ef
NC
6999}
7000
7001static void
a737bd4d 7002do_fpa_ctrl (char * str)
b99bd4ef
NC
7003{
7004 /* FP control registers.
7005 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7006
7007 skip_whitespace (str);
7008
7009 if (reg_required_here (&str, 12) == FAIL)
7010 {
7011 if (!inst.error)
7012 inst.error = BAD_ARGS;
7013 return;
7014 }
7015
7016 end_of_line (str);
b99bd4ef
NC
7017}
7018
7019static void
a737bd4d 7020do_fpa_ldst (char * str)
b99bd4ef
NC
7021{
7022 skip_whitespace (str);
7023
b99bd4ef
NC
7024 if (fp_reg_required_here (&str, 12) == FAIL)
7025 {
7026 if (!inst.error)
7027 inst.error = BAD_ARGS;
7028 return;
7029 }
7030
7031 if (skip_past_comma (&str) == FAIL
bfae80f2 7032 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7033 {
7034 if (!inst.error)
7035 inst.error = BAD_ARGS;
7036 return;
7037 }
7038
7039 end_of_line (str);
7040}
7041
7042static void
a737bd4d 7043do_fpa_ldmstm (char * str)
b99bd4ef
NC
7044{
7045 int num_regs;
7046
7047 skip_whitespace (str);
7048
7049 if (fp_reg_required_here (&str, 12) == FAIL)
7050 {
7051 if (! inst.error)
7052 inst.error = BAD_ARGS;
7053 return;
7054 }
7055
7056 /* Get Number of registers to transfer. */
7057 if (skip_past_comma (&str) == FAIL
7058 || my_get_expression (&inst.reloc.exp, &str))
7059 {
7060 if (! inst.error)
7061 inst.error = _("constant expression expected");
7062 return;
7063 }
7064
7065 if (inst.reloc.exp.X_op != O_constant)
7066 {
f03698e6 7067 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
7068 return;
7069 }
7070
7071 num_regs = inst.reloc.exp.X_add_number;
7072
7073 if (num_regs < 1 || num_regs > 4)
7074 {
7075 inst.error = _("number of registers must be in the range [1:4]");
7076 return;
7077 }
7078
7079 switch (num_regs)
7080 {
7081 case 1:
7082 inst.instruction |= CP_T_X;
7083 break;
7084 case 2:
7085 inst.instruction |= CP_T_Y;
7086 break;
7087 case 3:
7088 inst.instruction |= CP_T_Y | CP_T_X;
7089 break;
7090 case 4:
7091 break;
7092 default:
7093 abort ();
7094 }
7095
e28cd48c 7096 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
7097 {
7098 int reg;
7099 int write_back;
7100 int offset;
7101
7102 /* The instruction specified "ea" or "fd", so we can only accept
7103 [Rn]{!}. The instruction does not really support stacking or
7104 unstacking, so we have to emulate these by setting appropriate
7105 bits and offsets. */
7106 if (skip_past_comma (&str) == FAIL
7107 || *str != '[')
7108 {
7109 if (! inst.error)
7110 inst.error = BAD_ARGS;
7111 return;
7112 }
7113
7114 str++;
7115 skip_whitespace (str);
7116
7117 if ((reg = reg_required_here (&str, 16)) == FAIL)
7118 return;
7119
7120 skip_whitespace (str);
7121
7122 if (*str != ']')
7123 {
7124 inst.error = BAD_ARGS;
7125 return;
7126 }
7127
7128 str++;
7129 if (*str == '!')
7130 {
7131 write_back = 1;
7132 str++;
7133 if (reg == REG_PC)
7134 {
7135 inst.error =
f03698e6 7136 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
7137 return;
7138 }
7139 }
7140 else
7141 write_back = 0;
7142
90e4755a 7143 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
7144 {
7145 /* Pre-decrement. */
7146 offset = 3 * num_regs;
7147 if (write_back)
90e4755a 7148 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7149 }
7150 else
7151 {
7152 /* Post-increment. */
7153 if (write_back)
7154 {
90e4755a 7155 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7156 offset = 3 * num_regs;
7157 }
7158 else
7159 {
7160 /* No write-back, so convert this into a standard pre-increment
7161 instruction -- aesthetically more pleasing. */
90e4755a 7162 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
7163 offset = 0;
7164 }
7165 }
7166
f2b7cb0a 7167 inst.instruction |= offset;
b99bd4ef
NC
7168 }
7169 else if (skip_past_comma (&str) == FAIL
bfae80f2 7170 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7171 {
7172 if (! inst.error)
7173 inst.error = BAD_ARGS;
7174 return;
7175 }
7176
7177 end_of_line (str);
7178}
7179
7180static void
a737bd4d 7181do_fpa_dyadic (char * str)
b99bd4ef
NC
7182{
7183 skip_whitespace (str);
7184
b99bd4ef
NC
7185 if (fp_reg_required_here (&str, 12) == FAIL)
7186 {
7187 if (! inst.error)
7188 inst.error = BAD_ARGS;
7189 return;
7190 }
7191
7192 if (skip_past_comma (&str) == FAIL
7193 || fp_reg_required_here (&str, 16) == FAIL)
7194 {
7195 if (! inst.error)
7196 inst.error = BAD_ARGS;
7197 return;
7198 }
7199
7200 if (skip_past_comma (&str) == FAIL
7201 || fp_op2 (&str) == FAIL)
7202 {
7203 if (! inst.error)
7204 inst.error = BAD_ARGS;
7205 return;
7206 }
7207
b99bd4ef 7208 end_of_line (str);
b99bd4ef
NC
7209}
7210
7211static void
a737bd4d 7212do_fpa_monadic (char * str)
b99bd4ef
NC
7213{
7214 skip_whitespace (str);
7215
b99bd4ef
NC
7216 if (fp_reg_required_here (&str, 12) == FAIL)
7217 {
7218 if (! inst.error)
7219 inst.error = BAD_ARGS;
7220 return;
7221 }
7222
7223 if (skip_past_comma (&str) == FAIL
7224 || fp_op2 (&str) == FAIL)
7225 {
7226 if (! inst.error)
7227 inst.error = BAD_ARGS;
7228 return;
7229 }
7230
b99bd4ef 7231 end_of_line (str);
b99bd4ef
NC
7232}
7233
7234static void
a737bd4d 7235do_fpa_cmp (char * str)
b99bd4ef
NC
7236{
7237 skip_whitespace (str);
7238
7239 if (fp_reg_required_here (&str, 16) == FAIL)
7240 {
7241 if (! inst.error)
7242 inst.error = BAD_ARGS;
7243 return;
7244 }
7245
7246 if (skip_past_comma (&str) == FAIL
7247 || fp_op2 (&str) == FAIL)
7248 {
7249 if (! inst.error)
7250 inst.error = BAD_ARGS;
7251 return;
7252 }
7253
b99bd4ef 7254 end_of_line (str);
b99bd4ef
NC
7255}
7256
7257static void
a737bd4d 7258do_fpa_from_reg (char * str)
b99bd4ef
NC
7259{
7260 skip_whitespace (str);
7261
b99bd4ef
NC
7262 if (fp_reg_required_here (&str, 16) == FAIL)
7263 {
7264 if (! inst.error)
7265 inst.error = BAD_ARGS;
7266 return;
7267 }
7268
7269 if (skip_past_comma (&str) == FAIL
7270 || reg_required_here (&str, 12) == FAIL)
7271 {
7272 if (! inst.error)
7273 inst.error = BAD_ARGS;
7274 return;
7275 }
7276
b99bd4ef 7277 end_of_line (str);
b99bd4ef
NC
7278}
7279
7280static void
a737bd4d 7281do_fpa_to_reg (char * str)
b99bd4ef
NC
7282{
7283 skip_whitespace (str);
7284
7285 if (reg_required_here (&str, 12) == FAIL)
7286 return;
7287
7288 if (skip_past_comma (&str) == FAIL
7289 || fp_reg_required_here (&str, 0) == FAIL)
7290 {
7291 if (! inst.error)
7292 inst.error = BAD_ARGS;
7293 return;
7294 }
7295
b99bd4ef 7296 end_of_line (str);
b99bd4ef
NC
7297}
7298
7ed4c4c5
NC
7299/* Encode a VFP SP register number. */
7300
7301static void
7302vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7303{
7304 switch (pos)
7305 {
7306 case VFP_REG_Sd:
7307 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7308 break;
7309
7310 case VFP_REG_Sn:
7311 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7312 break;
7313
7314 case VFP_REG_Sm:
7315 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7316 break;
7317
7318 default:
7319 abort ();
7320 }
7321}
7322
b99bd4ef 7323static int
a737bd4d
NC
7324vfp_sp_reg_required_here (char ** str,
7325 enum vfp_sp_reg_pos pos)
b99bd4ef 7326{
bfae80f2 7327 int reg;
7ed4c4c5 7328 char * start = *str;
b99bd4ef 7329
bfae80f2 7330 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 7331 {
7ed4c4c5 7332 vfp_sp_encode_reg (reg, pos);
bfae80f2
RE
7333 return reg;
7334 }
b99bd4ef 7335
bfae80f2
RE
7336 /* In the few cases where we might be able to accept something else
7337 this error can be overridden. */
7338 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7339
7340 /* Restore the start point. */
7341 *str = start;
7342 return FAIL;
7343}
7344
7345static int
a737bd4d
NC
7346vfp_dp_reg_required_here (char ** str,
7347 enum vfp_dp_reg_pos pos)
bfae80f2 7348{
a737bd4d
NC
7349 int reg;
7350 char * start = *str;
bfae80f2
RE
7351
7352 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7353 {
7354 switch (pos)
b99bd4ef 7355 {
bfae80f2
RE
7356 case VFP_REG_Dd:
7357 inst.instruction |= reg << 12;
7358 break;
b99bd4ef 7359
bfae80f2
RE
7360 case VFP_REG_Dn:
7361 inst.instruction |= reg << 16;
7362 break;
7363
7364 case VFP_REG_Dm:
7365 inst.instruction |= reg << 0;
7366 break;
7367
7368 default:
7369 abort ();
7370 }
7371 return reg;
b99bd4ef
NC
7372 }
7373
bfae80f2
RE
7374 /* In the few cases where we might be able to accept something else
7375 this error can be overridden. */
7376 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 7377
bfae80f2
RE
7378 /* Restore the start point. */
7379 *str = start;
7380 return FAIL;
7381}
b99bd4ef
NC
7382
7383static void
a737bd4d 7384do_vfp_sp_monadic (char * str)
b99bd4ef 7385{
b99bd4ef
NC
7386 skip_whitespace (str);
7387
bfae80f2
RE
7388 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7389 return;
7390
7391 if (skip_past_comma (&str) == FAIL
7392 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
7393 {
7394 if (! inst.error)
7395 inst.error = BAD_ARGS;
7396 return;
7397 }
7398
bfae80f2 7399 end_of_line (str);
bfae80f2
RE
7400}
7401
7402static void
a737bd4d 7403do_vfp_dp_monadic (char * str)
bfae80f2
RE
7404{
7405 skip_whitespace (str);
7406
7407 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7408 return;
7409
7410 if (skip_past_comma (&str) == FAIL
7411 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 7412 {
bfae80f2
RE
7413 if (! inst.error)
7414 inst.error = BAD_ARGS;
7415 return;
b99bd4ef 7416 }
b99bd4ef 7417
bfae80f2 7418 end_of_line (str);
bfae80f2 7419}
b99bd4ef 7420
bfae80f2 7421static void
a737bd4d 7422do_vfp_sp_dyadic (char * str)
bfae80f2
RE
7423{
7424 skip_whitespace (str);
b99bd4ef 7425
bfae80f2
RE
7426 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7427 return;
b99bd4ef 7428
bfae80f2
RE
7429 if (skip_past_comma (&str) == FAIL
7430 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7431 || skip_past_comma (&str) == FAIL
7432 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 7433 {
bfae80f2
RE
7434 if (! inst.error)
7435 inst.error = BAD_ARGS;
7436 return;
7437 }
b99bd4ef 7438
bfae80f2 7439 end_of_line (str);
bfae80f2 7440}
b99bd4ef 7441
bfae80f2 7442static void
a737bd4d 7443do_vfp_dp_dyadic (char * str)
bfae80f2
RE
7444{
7445 skip_whitespace (str);
b99bd4ef 7446
bfae80f2
RE
7447 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7448 return;
b99bd4ef 7449
bfae80f2
RE
7450 if (skip_past_comma (&str) == FAIL
7451 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7452 || skip_past_comma (&str) == FAIL
7453 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7454 {
7455 if (! inst.error)
7456 inst.error = BAD_ARGS;
7457 return;
7458 }
b99bd4ef 7459
bfae80f2 7460 end_of_line (str);
bfae80f2 7461}
b99bd4ef 7462
bfae80f2 7463static void
a737bd4d 7464do_vfp_reg_from_sp (char * str)
bfae80f2
RE
7465{
7466 skip_whitespace (str);
7467
7468 if (reg_required_here (&str, 12) == FAIL)
7469 return;
7470
7471 if (skip_past_comma (&str) == FAIL
7472 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7473 {
7474 if (! inst.error)
7475 inst.error = BAD_ARGS;
7476 return;
7477 }
7478
7479 end_of_line (str);
bfae80f2
RE
7480}
7481
7ed4c4c5
NC
7482/* Parse a VFP register list. If the string is invalid return FAIL.
7483 Otherwise return the number of registers, and set PBASE to the first
7484 register. Double precision registers are matched if DP is nonzero. */
a737bd4d 7485
7ed4c4c5
NC
7486static int
7487vfp_parse_reg_list (char **str, int *pbase, int dp)
a737bd4d 7488{
7ed4c4c5 7489 int base_reg;
a737bd4d 7490 int new_base;
7ed4c4c5
NC
7491 int regtype;
7492 int max_regs;
a737bd4d 7493 int count = 0;
a737bd4d 7494 int warned = 0;
7ed4c4c5
NC
7495 unsigned long mask = 0;
7496 int i;
a737bd4d
NC
7497
7498 if (**str != '{')
7499 return FAIL;
7500
7501 (*str)++;
7502 skip_whitespace (*str);
7503
7ed4c4c5 7504 if (dp)
a737bd4d 7505 {
7ed4c4c5
NC
7506 regtype = REG_TYPE_DN;
7507 max_regs = 16;
7508 }
7509 else
7510 {
7511 regtype = REG_TYPE_SN;
7512 max_regs = 32;
7513 }
a737bd4d 7514
7ed4c4c5 7515 base_reg = max_regs;
a737bd4d 7516
7ed4c4c5
NC
7517 do
7518 {
7519 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7520 if (new_base == FAIL)
a737bd4d 7521 {
7ed4c4c5
NC
7522 inst.error = _(all_reg_maps[regtype].expected);
7523 return FAIL;
a737bd4d
NC
7524 }
7525
7ed4c4c5
NC
7526 if (new_base < base_reg)
7527 base_reg = new_base;
7528
a737bd4d
NC
7529 if (mask & (1 << new_base))
7530 {
7531 inst.error = _("invalid register list");
7532 return FAIL;
7533 }
7534
7535 if ((mask >> new_base) != 0 && ! warned)
7536 {
7537 as_tsktsk (_("register list not in ascending order"));
7538 warned = 1;
7539 }
7540
7541 mask |= 1 << new_base;
7542 count++;
7543
7544 skip_whitespace (*str);
7545
7546 if (**str == '-') /* We have the start of a range expression */
7547 {
7548 int high_range;
7549
7550 (*str)++;
7551
7552 if ((high_range
7ed4c4c5 7553 = arm_reg_parse (str, all_reg_maps[regtype].htab))
a737bd4d
NC
7554 == FAIL)
7555 {
7ed4c4c5 7556 inst.error = _(all_reg_maps[regtype].expected);
a737bd4d
NC
7557 return FAIL;
7558 }
7559
7560 if (high_range <= new_base)
7561 {
7562 inst.error = _("register range not in ascending order");
7563 return FAIL;
7564 }
7565
7566 for (new_base++; new_base <= high_range; new_base++)
7567 {
7568 if (mask & (1 << new_base))
7569 {
7570 inst.error = _("invalid register list");
7571 return FAIL;
7572 }
7573
7574 mask |= 1 << new_base;
7575 count++;
7576 }
7577 }
7578 }
7579 while (skip_past_comma (str) != FAIL);
7580
a737bd4d
NC
7581 (*str)++;
7582
a737bd4d 7583 /* Sanity check -- should have raised a parse error above. */
7ed4c4c5 7584 if (count == 0 || count > max_regs)
a737bd4d
NC
7585 abort ();
7586
7ed4c4c5
NC
7587 *pbase = base_reg;
7588
a737bd4d 7589 /* Final test -- the registers must be consecutive. */
7ed4c4c5
NC
7590 mask >>= base_reg;
7591 for (i = 0; i < count; i++)
a737bd4d 7592 {
7ed4c4c5 7593 if ((mask & (1u << i)) == 0)
a737bd4d
NC
7594 {
7595 inst.error = _("non-contiguous register range");
7596 return FAIL;
7597 }
7598 }
7599
7ed4c4c5 7600 return count;
a737bd4d
NC
7601}
7602
bfae80f2 7603static void
a737bd4d 7604do_vfp_reg2_from_sp2 (char * str)
bfae80f2 7605{
7ed4c4c5
NC
7606 int reg;
7607
bfae80f2
RE
7608 skip_whitespace (str);
7609
e45d0630
PB
7610 if (reg_required_here (&str, 12) == FAIL
7611 || skip_past_comma (&str) == FAIL
bfae80f2
RE
7612 || reg_required_here (&str, 16) == FAIL
7613 || skip_past_comma (&str) == FAIL)
7614 {
7615 if (! inst.error)
7616 inst.error = BAD_ARGS;
7617 return;
7618 }
7619
7620 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7621 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
bfae80f2
RE
7622 {
7623 if (! inst.error)
7624 inst.error = _("only two consecutive VFP SP registers allowed here");
7625 }
7ed4c4c5 7626 vfp_sp_encode_reg (reg, VFP_REG_Sm);
bfae80f2
RE
7627
7628 end_of_line (str);
bfae80f2
RE
7629}
7630
7631static void
a737bd4d 7632do_vfp_sp_from_reg (char * str)
bfae80f2
RE
7633{
7634 skip_whitespace (str);
7635
7636 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7637 return;
7638
7639 if (skip_past_comma (&str) == FAIL
7640 || reg_required_here (&str, 12) == FAIL)
7641 {
7642 if (! inst.error)
7643 inst.error = BAD_ARGS;
7644 return;
7645 }
7646
7647 end_of_line (str);
bfae80f2
RE
7648}
7649
e45d0630 7650static void
a737bd4d 7651do_vfp_sp2_from_reg2 (char * str)
e45d0630 7652{
7ed4c4c5
NC
7653 int reg;
7654
e45d0630
PB
7655 skip_whitespace (str);
7656
7657 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7658 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
e45d0630
PB
7659 {
7660 if (! inst.error)
7661 inst.error = _("only two consecutive VFP SP registers allowed here");
7662 }
7ed4c4c5 7663 vfp_sp_encode_reg (reg, VFP_REG_Sm);
e45d0630
PB
7664
7665 if (skip_past_comma (&str) == FAIL
7666 || reg_required_here (&str, 12) == FAIL
7667 || skip_past_comma (&str) == FAIL
7668 || reg_required_here (&str, 16) == FAIL)
7669 {
7670 if (! inst.error)
7671 inst.error = BAD_ARGS;
7672 return;
7673 }
7674
7675 end_of_line (str);
7676}
7677
bfae80f2 7678static void
a737bd4d 7679do_vfp_reg_from_dp (char * str)
bfae80f2
RE
7680{
7681 skip_whitespace (str);
7682
7683 if (reg_required_here (&str, 12) == FAIL)
7684 return;
7685
7686 if (skip_past_comma (&str) == FAIL
7687 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7688 {
7689 if (! inst.error)
7690 inst.error = BAD_ARGS;
7691 return;
7692 }
7693
7694 end_of_line (str);
bfae80f2
RE
7695}
7696
7697static void
a737bd4d 7698do_vfp_reg2_from_dp (char * str)
bfae80f2
RE
7699{
7700 skip_whitespace (str);
7701
7702 if (reg_required_here (&str, 12) == FAIL)
7703 return;
7704
7705 if (skip_past_comma (&str) == FAIL
7706 || reg_required_here (&str, 16) == FAIL
7707 || skip_past_comma (&str) == FAIL
7708 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7709 {
7710 if (! inst.error)
7711 inst.error = BAD_ARGS;
7712 return;
7713 }
7714
7715 end_of_line (str);
bfae80f2
RE
7716}
7717
7718static void
a737bd4d 7719do_vfp_dp_from_reg (char * str)
bfae80f2
RE
7720{
7721 skip_whitespace (str);
7722
7723 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7724 return;
7725
7726 if (skip_past_comma (&str) == FAIL
7727 || reg_required_here (&str, 12) == FAIL)
7728 {
7729 if (! inst.error)
7730 inst.error = BAD_ARGS;
7731 return;
7732 }
7733
7734 end_of_line (str);
bfae80f2
RE
7735}
7736
7737static void
a737bd4d 7738do_vfp_dp_from_reg2 (char * str)
bfae80f2
RE
7739{
7740 skip_whitespace (str);
7741
7742 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7743 return;
7744
7745 if (skip_past_comma (&str) == FAIL
7746 || reg_required_here (&str, 12) == FAIL
7747 || skip_past_comma (&str) == FAIL
e45d0630 7748 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
7749 {
7750 if (! inst.error)
7751 inst.error = BAD_ARGS;
7752 return;
7753 }
7754
7755 end_of_line (str);
bfae80f2
RE
7756}
7757
7758static const struct vfp_reg *
a737bd4d 7759vfp_psr_parse (char ** str)
bfae80f2
RE
7760{
7761 char *start = *str;
7762 char c;
7763 char *p;
7764 const struct vfp_reg *vreg;
7765
7766 p = start;
7767
7768 /* Find the end of the current token. */
7769 do
7770 {
7771 c = *p++;
7772 }
7773 while (ISALPHA (c));
7774
7775 /* Mark it. */
7776 *--p = 0;
7777
cc8a6dd0 7778 for (vreg = vfp_regs + 0;
bfae80f2
RE
7779 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7780 vreg++)
7781 {
a737bd4d 7782 if (streq (start, vreg->name))
bfae80f2
RE
7783 {
7784 *p = c;
7785 *str = p;
7786 return vreg;
7787 }
7788 }
7789
7790 *p = c;
7791 return NULL;
7792}
7793
7794static int
a737bd4d 7795vfp_psr_required_here (char ** str)
bfae80f2
RE
7796{
7797 char *start = *str;
7798 const struct vfp_reg *vreg;
7799
7800 vreg = vfp_psr_parse (str);
7801
7802 if (vreg)
7803 {
7804 inst.instruction |= vreg->regno;
7805 return SUCCESS;
7806 }
7807
7808 inst.error = _("VFP system register expected");
7809
7810 *str = start;
7811 return FAIL;
7812}
7813
7814static void
a737bd4d 7815do_vfp_reg_from_ctrl (char * str)
bfae80f2
RE
7816{
7817 skip_whitespace (str);
7818
7819 if (reg_required_here (&str, 12) == FAIL)
7820 return;
7821
7822 if (skip_past_comma (&str) == FAIL
7823 || vfp_psr_required_here (&str) == FAIL)
7824 {
7825 if (! inst.error)
7826 inst.error = BAD_ARGS;
7827 return;
7828 }
7829
7830 end_of_line (str);
bfae80f2
RE
7831}
7832
7833static void
a737bd4d 7834do_vfp_ctrl_from_reg (char * str)
bfae80f2
RE
7835{
7836 skip_whitespace (str);
7837
7838 if (vfp_psr_required_here (&str) == FAIL)
7839 return;
7840
7841 if (skip_past_comma (&str) == FAIL
7842 || reg_required_here (&str, 12) == FAIL)
7843 {
7844 if (! inst.error)
7845 inst.error = BAD_ARGS;
7846 return;
7847 }
7848
7849 end_of_line (str);
bfae80f2
RE
7850}
7851
7852static void
a737bd4d 7853do_vfp_sp_ldst (char * str)
bfae80f2
RE
7854{
7855 skip_whitespace (str);
7856
7857 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7858 {
7859 if (!inst.error)
7860 inst.error = BAD_ARGS;
7861 return;
7862 }
7863
7864 if (skip_past_comma (&str) == FAIL
7865 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7866 {
7867 if (!inst.error)
7868 inst.error = BAD_ARGS;
7869 return;
7870 }
7871
7872 end_of_line (str);
bfae80f2
RE
7873}
7874
7875static void
a737bd4d 7876do_vfp_dp_ldst (char * str)
bfae80f2
RE
7877{
7878 skip_whitespace (str);
7879
7880 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7881 {
7882 if (!inst.error)
7883 inst.error = BAD_ARGS;
7884 return;
7885 }
7886
7887 if (skip_past_comma (&str) == FAIL
7888 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7889 {
7890 if (!inst.error)
a737bd4d
NC
7891 inst.error = BAD_ARGS;
7892 return;
bfae80f2
RE
7893 }
7894
a737bd4d 7895 end_of_line (str);
bfae80f2
RE
7896}
7897
bfae80f2
RE
7898
7899static void
a737bd4d 7900vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 7901{
7ed4c4c5
NC
7902 int count;
7903 int reg;
bfae80f2
RE
7904
7905 skip_whitespace (str);
7906
7907 if (reg_required_here (&str, 16) == FAIL)
7908 return;
7909
7910 skip_whitespace (str);
7911
7912 if (*str == '!')
7913 {
7914 inst.instruction |= WRITE_BACK;
7915 str++;
7916 }
7917 else if (ldstm_type != VFP_LDSTMIA)
7918 {
7919 inst.error = _("this addressing mode requires base-register writeback");
7920 return;
7921 }
7922
7923 if (skip_past_comma (&str) == FAIL
7ed4c4c5 7924 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
bfae80f2
RE
7925 {
7926 if (!inst.error)
7927 inst.error = BAD_ARGS;
7928 return;
7929 }
7ed4c4c5 7930 vfp_sp_encode_reg (reg, VFP_REG_Sd);
bfae80f2 7931
7ed4c4c5 7932 inst.instruction |= count;
bfae80f2
RE
7933 end_of_line (str);
7934}
7935
7936static void
a737bd4d 7937vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 7938{
7ed4c4c5
NC
7939 int count;
7940 int reg;
bfae80f2
RE
7941
7942 skip_whitespace (str);
7943
7944 if (reg_required_here (&str, 16) == FAIL)
7945 return;
7946
7947 skip_whitespace (str);
7948
7949 if (*str == '!')
7950 {
7951 inst.instruction |= WRITE_BACK;
7952 str++;
7953 }
7954 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
7955 {
7956 inst.error = _("this addressing mode requires base-register writeback");
7957 return;
7958 }
7959
7960 if (skip_past_comma (&str) == FAIL
7ed4c4c5 7961 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
bfae80f2
RE
7962 {
7963 if (!inst.error)
7964 inst.error = BAD_ARGS;
7965 return;
7966 }
7967
7ed4c4c5 7968 count <<= 1;
bfae80f2 7969 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7ed4c4c5 7970 count += 1;
bfae80f2 7971
7ed4c4c5 7972 inst.instruction |= (reg << 12) | count;
bfae80f2
RE
7973 end_of_line (str);
7974}
7975
7976static void
a737bd4d 7977do_vfp_sp_ldstmia (char * str)
bfae80f2
RE
7978{
7979 vfp_sp_ldstm (str, VFP_LDSTMIA);
7980}
7981
7982static void
a737bd4d 7983do_vfp_sp_ldstmdb (char * str)
bfae80f2
RE
7984{
7985 vfp_sp_ldstm (str, VFP_LDSTMDB);
7986}
7987
7988static void
a737bd4d 7989do_vfp_dp_ldstmia (char * str)
bfae80f2
RE
7990{
7991 vfp_dp_ldstm (str, VFP_LDSTMIA);
7992}
7993
7994static void
a737bd4d 7995do_vfp_dp_ldstmdb (char * str)
bfae80f2
RE
7996{
7997 vfp_dp_ldstm (str, VFP_LDSTMDB);
7998}
7999
8000static void
a737bd4d 8001do_vfp_xp_ldstmia (char *str)
bfae80f2
RE
8002{
8003 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8004}
8005
8006static void
a737bd4d 8007do_vfp_xp_ldstmdb (char * str)
bfae80f2
RE
8008{
8009 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8010}
8011
8012static void
a737bd4d 8013do_vfp_sp_compare_z (char * str)
bfae80f2
RE
8014{
8015 skip_whitespace (str);
8016
8017 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8018 {
8019 if (!inst.error)
8020 inst.error = BAD_ARGS;
8021 return;
8022 }
8023
8024 end_of_line (str);
bfae80f2
RE
8025}
8026
8027static void
a737bd4d 8028do_vfp_dp_compare_z (char * str)
bfae80f2
RE
8029{
8030 skip_whitespace (str);
8031
8032 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8033 {
8034 if (!inst.error)
8035 inst.error = BAD_ARGS;
8036 return;
8037 }
8038
8039 end_of_line (str);
bfae80f2
RE
8040}
8041
8042static void
a737bd4d 8043do_vfp_dp_sp_cvt (char * str)
bfae80f2
RE
8044{
8045 skip_whitespace (str);
8046
8047 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8048 return;
8049
8050 if (skip_past_comma (&str) == FAIL
8051 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8052 {
8053 if (! inst.error)
8054 inst.error = BAD_ARGS;
8055 return;
8056 }
8057
8058 end_of_line (str);
bfae80f2
RE
8059}
8060
8061static void
a737bd4d 8062do_vfp_sp_dp_cvt (char * str)
bfae80f2
RE
8063{
8064 skip_whitespace (str);
8065
8066 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8067 return;
8068
8069 if (skip_past_comma (&str) == FAIL
8070 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8071 {
8072 if (! inst.error)
8073 inst.error = BAD_ARGS;
8074 return;
8075 }
8076
8077 end_of_line (str);
bfae80f2
RE
8078}
8079
8080/* Thumb specific routines. */
8081
bfae80f2
RE
8082/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8083 was SUB. */
8084
8085static void
a737bd4d 8086thumb_add_sub (char * str, int subtract)
bfae80f2
RE
8087{
8088 int Rd, Rs, Rn = FAIL;
8089
8090 skip_whitespace (str);
8091
8092 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8093 || skip_past_comma (&str) == FAIL)
8094 {
8095 if (! inst.error)
8096 inst.error = BAD_ARGS;
8097 return;
8098 }
8099
8100 if (is_immediate_prefix (*str))
8101 {
8102 Rs = Rd;
8103 str++;
8104 if (my_get_expression (&inst.reloc.exp, &str))
8105 return;
8106 }
8107 else
8108 {
8109 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8110 return;
8111
8112 if (skip_past_comma (&str) == FAIL)
8113 {
8114 /* Two operand format, shuffle the registers
8115 and pretend there are 3. */
8116 Rn = Rs;
8117 Rs = Rd;
8118 }
8119 else if (is_immediate_prefix (*str))
8120 {
8121 str++;
8122 if (my_get_expression (&inst.reloc.exp, &str))
8123 return;
8124 }
8125 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8126 return;
8127 }
8128
8129 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8130 for the latter case, EXPR contains the immediate that was found. */
8131 if (Rn != FAIL)
8132 {
8133 /* All register format. */
8134 if (Rd > 7 || Rs > 7 || Rn > 7)
8135 {
8136 if (Rs != Rd)
8137 {
8138 inst.error = _("dest and source1 must be the same register");
8139 return;
8140 }
8141
8142 /* Can't do this for SUB. */
8143 if (subtract)
8144 {
8145 inst.error = _("subtract valid only on lo regs");
8146 return;
8147 }
8148
8149 inst.instruction = (T_OPCODE_ADD_HI
8150 | (Rd > 7 ? THUMB_H1 : 0)
8151 | (Rn > 7 ? THUMB_H2 : 0));
8152 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8153 }
8154 else
8155 {
8156 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8157 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8158 }
8159 }
8160 else
8161 {
8162 /* Immediate expression, now things start to get nasty. */
8163
8164 /* First deal with HI regs, only very restricted cases allowed:
8165 Adjusting SP, and using PC or SP to get an address. */
8166 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8167 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8168 {
8169 inst.error = _("invalid Hi register with immediate");
8170 return;
8171 }
8172
8173 if (inst.reloc.exp.X_op != O_constant)
8174 {
8175 /* Value isn't known yet, all we can do is store all the fragments
8176 we know about in the instruction and let the reloc hacking
8177 work it all out. */
8178 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8179 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8180 }
8181 else
8182 {
8183 int offset = inst.reloc.exp.X_add_number;
8184
8185 if (subtract)
358b94bd 8186 offset = - offset;
bfae80f2
RE
8187
8188 if (offset < 0)
8189 {
358b94bd 8190 offset = - offset;
bfae80f2
RE
8191 subtract = 1;
8192
8193 /* Quick check, in case offset is MIN_INT. */
8194 if (offset < 0)
8195 {
8196 inst.error = _("immediate value out of range");
8197 return;
8198 }
8199 }
358b94bd
NC
8200 /* Note - you cannot convert a subtract of 0 into an
8201 add of 0 because the carry flag is set differently. */
8202 else if (offset > 0)
bfae80f2
RE
8203 subtract = 0;
8204
8205 if (Rd == REG_SP)
8206 {
8207 if (offset & ~0x1fc)
8208 {
8209 inst.error = _("invalid immediate value for stack adjust");
8210 return;
b99bd4ef
NC
8211 }
8212 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8213 inst.instruction |= offset >> 2;
8214 }
8215 else if (Rs == REG_PC || Rs == REG_SP)
8216 {
8217 if (subtract
8218 || (offset & ~0x3fc))
8219 {
8220 inst.error = _("invalid immediate for address calculation");
8221 return;
8222 }
8223 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8224 : T_OPCODE_ADD_SP);
8225 inst.instruction |= (Rd << 8) | (offset >> 2);
8226 }
8227 else if (Rs == Rd)
8228 {
8229 if (offset & ~0xff)
8230 {
8231 inst.error = _("immediate value out of range");
8232 return;
8233 }
8234 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8235 inst.instruction |= (Rd << 8) | offset;
8236 }
8237 else
8238 {
8239 if (offset & ~0x7)
8240 {
8241 inst.error = _("immediate value out of range");
8242 return;
8243 }
8244 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8245 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8246 }
8247 }
8248 }
8249
8250 end_of_line (str);
8251}
8252
8253static void
a737bd4d 8254thumb_shift (char * str, int shift)
b99bd4ef
NC
8255{
8256 int Rd, Rs, Rn = FAIL;
8257
8258 skip_whitespace (str);
8259
8260 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8261 || skip_past_comma (&str) == FAIL)
8262 {
8263 if (! inst.error)
8264 inst.error = BAD_ARGS;
8265 return;
8266 }
8267
8268 if (is_immediate_prefix (*str))
8269 {
8270 /* Two operand immediate format, set Rs to Rd. */
8271 Rs = Rd;
8272 str ++;
8273 if (my_get_expression (&inst.reloc.exp, &str))
8274 return;
8275 }
8276 else
8277 {
8278 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8279 return;
8280
8281 if (skip_past_comma (&str) == FAIL)
8282 {
8283 /* Two operand format, shuffle the registers
8284 and pretend there are 3. */
8285 Rn = Rs;
8286 Rs = Rd;
8287 }
8288 else if (is_immediate_prefix (*str))
8289 {
8290 str++;
8291 if (my_get_expression (&inst.reloc.exp, &str))
8292 return;
8293 }
8294 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8295 return;
8296 }
8297
8298 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8299 for the latter case, EXPR contains the immediate that was found. */
8300
8301 if (Rn != FAIL)
8302 {
8303 if (Rs != Rd)
8304 {
8305 inst.error = _("source1 and dest must be same register");
8306 return;
8307 }
8308
8309 switch (shift)
8310 {
8311 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8312 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8313 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8314 }
8315
8316 inst.instruction |= Rd | (Rn << 3);
8317 }
8318 else
8319 {
8320 switch (shift)
8321 {
8322 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8323 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8324 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8325 }
8326
8327 if (inst.reloc.exp.X_op != O_constant)
8328 {
8329 /* Value isn't known yet, create a dummy reloc and let reloc
8330 hacking fix it up. */
8331 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8332 }
8333 else
8334 {
8335 unsigned shift_value = inst.reloc.exp.X_add_number;
8336
8337 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8338 {
f03698e6 8339 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
8340 return;
8341 }
8342
8343 /* Shifts of zero are handled by converting to LSL. */
8344 if (shift_value == 0)
8345 inst.instruction = T_OPCODE_LSL_I;
8346
8347 /* Shifts of 32 are encoded as a shift of zero. */
8348 if (shift_value == 32)
8349 shift_value = 0;
8350
8351 inst.instruction |= shift_value << 6;
8352 }
8353
8354 inst.instruction |= Rd | (Rs << 3);
8355 }
8356
8357 end_of_line (str);
8358}
8359
8360static void
a737bd4d 8361thumb_load_store (char * str, int load_store, int size)
b99bd4ef
NC
8362{
8363 int Rd, Rb, Ro = FAIL;
8364
8365 skip_whitespace (str);
8366
8367 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8368 || skip_past_comma (&str) == FAIL)
8369 {
8370 if (! inst.error)
8371 inst.error = BAD_ARGS;
8372 return;
8373 }
8374
8375 if (*str == '[')
8376 {
8377 str++;
8378 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8379 return;
8380
8381 if (skip_past_comma (&str) != FAIL)
8382 {
8383 if (is_immediate_prefix (*str))
8384 {
8385 str++;
8386 if (my_get_expression (&inst.reloc.exp, &str))
8387 return;
8388 }
8389 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8390 return;
8391 }
8392 else
8393 {
8394 inst.reloc.exp.X_op = O_constant;
8395 inst.reloc.exp.X_add_number = 0;
8396 }
8397
8398 if (*str != ']')
8399 {
8400 inst.error = _("expected ']'");
8401 return;
8402 }
8403 str++;
8404 }
8405 else if (*str == '=')
8406 {
f03698e6
RE
8407 if (load_store != THUMB_LOAD)
8408 {
8409 inst.error = _("invalid pseudo operation");
8410 return;
8411 }
8412
b99bd4ef
NC
8413 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8414 str++;
8415
8416 skip_whitespace (str);
8417
8418 if (my_get_expression (& inst.reloc.exp, & str))
8419 return;
8420
8421 end_of_line (str);
8422
8423 if ( inst.reloc.exp.X_op != O_constant
8424 && inst.reloc.exp.X_op != O_symbol)
8425 {
8426 inst.error = "Constant expression expected";
8427 return;
8428 }
8429
8430 if (inst.reloc.exp.X_op == O_constant
8431 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8432 {
8433 /* This can be done with a mov instruction. */
8434
8435 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8436 inst.instruction |= inst.reloc.exp.X_add_number;
8437 return;
8438 }
8439
8440 /* Insert into literal pool. */
8441 if (add_to_lit_pool () == FAIL)
8442 {
8443 if (!inst.error)
8444 inst.error = "literal pool insertion failed";
8445 return;
8446 }
8447
8448 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8449 inst.reloc.pc_rel = 1;
8450 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8451 /* Adjust ARM pipeline offset to Thumb. */
8452 inst.reloc.exp.X_add_number += 4;
8453
8454 return;
8455 }
8456 else
8457 {
8458 if (my_get_expression (&inst.reloc.exp, &str))
8459 return;
8460
8461 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8462 inst.reloc.pc_rel = 1;
8463 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8464 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8465 end_of_line (str);
8466 return;
8467 }
8468
8469 if (Rb == REG_PC || Rb == REG_SP)
8470 {
8471 if (size != THUMB_WORD)
8472 {
8473 inst.error = _("byte or halfword not valid for base register");
8474 return;
8475 }
8476 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8477 {
f03698e6 8478 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
8479 return;
8480 }
8481 else if (Ro != FAIL)
8482 {
f03698e6 8483 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
8484 return;
8485 }
8486
8487 if (Rb == REG_PC)
8488 inst.instruction = T_OPCODE_LDR_PC;
8489 else if (load_store == THUMB_LOAD)
8490 inst.instruction = T_OPCODE_LDR_SP;
8491 else
8492 inst.instruction = T_OPCODE_STR_SP;
8493
8494 inst.instruction |= Rd << 8;
8495 if (inst.reloc.exp.X_op == O_constant)
8496 {
8497 unsigned offset = inst.reloc.exp.X_add_number;
8498
8499 if (offset & ~0x3fc)
8500 {
8501 inst.error = _("invalid offset");
8502 return;
8503 }
8504
8505 inst.instruction |= offset >> 2;
8506 }
8507 else
8508 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8509 }
8510 else if (Rb > 7)
8511 {
8512 inst.error = _("invalid base register in load/store");
8513 return;
8514 }
8515 else if (Ro == FAIL)
8516 {
8517 /* Immediate offset. */
8518 if (size == THUMB_WORD)
8519 inst.instruction = (load_store == THUMB_LOAD
8520 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8521 else if (size == THUMB_HALFWORD)
8522 inst.instruction = (load_store == THUMB_LOAD
8523 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8524 else
8525 inst.instruction = (load_store == THUMB_LOAD
8526 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8527
8528 inst.instruction |= Rd | (Rb << 3);
8529
8530 if (inst.reloc.exp.X_op == O_constant)
8531 {
8532 unsigned offset = inst.reloc.exp.X_add_number;
8533
8534 if (offset & ~(0x1f << size))
8535 {
f03698e6 8536 inst.error = _("invalid offset");
b99bd4ef
NC
8537 return;
8538 }
8539 inst.instruction |= (offset >> size) << 6;
8540 }
8541 else
8542 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8543 }
8544 else
8545 {
8546 /* Register offset. */
8547 if (size == THUMB_WORD)
8548 inst.instruction = (load_store == THUMB_LOAD
8549 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8550 else if (size == THUMB_HALFWORD)
8551 inst.instruction = (load_store == THUMB_LOAD
8552 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8553 else
8554 inst.instruction = (load_store == THUMB_LOAD
8555 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8556
8557 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8558 }
8559
8560 end_of_line (str);
8561}
8562
404ff6b5
AH
8563/* A register must be given at this point.
8564
404ff6b5
AH
8565 Shift is the place to put it in inst.instruction.
8566
404ff6b5
AH
8567 Restores input start point on err.
8568 Returns the reg#, or FAIL. */
8569
8570static int
a737bd4d 8571mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
404ff6b5 8572{
6c43fab6
RE
8573 int reg;
8574 char *start = *str;
404ff6b5 8575
6c43fab6 8576 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 8577 {
404ff6b5
AH
8578 if (shift >= 0)
8579 inst.instruction |= reg << shift;
8580
6c43fab6 8581 return reg;
404ff6b5
AH
8582 }
8583
6c43fab6 8584 /* Restore the start point. */
404ff6b5 8585 *str = start;
cc8a6dd0 8586
3631a3c8
NC
8587 /* Try generic coprocessor name if applicable. */
8588 if (regtype == REG_TYPE_MVF ||
8589 regtype == REG_TYPE_MVD ||
8590 regtype == REG_TYPE_MVFX ||
8591 regtype == REG_TYPE_MVDX)
8592 {
8593 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8594 {
8595 if (shift >= 0)
8596 inst.instruction |= reg << shift;
8597
8598 return reg;
8599 }
8600
8601 /* Restore the start point. */
8602 *str = start;
8603 }
8604
404ff6b5
AH
8605 /* In the few cases where we might be able to accept something else
8606 this error can be overridden. */
6c43fab6 8607 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 8608
404ff6b5
AH
8609 return FAIL;
8610}
8611
a737bd4d
NC
8612/* Cirrus Maverick Instructions. */
8613
8614/* Isnsn like "foo X,Y". */
8615
8616static void
8617do_mav_binops (char * str,
8618 int mode,
8619 enum arm_reg_type reg0,
8620 enum arm_reg_type reg1)
8621{
8622 int shift0, shift1;
8623
8624 shift0 = mode & 0xff;
8625 shift1 = (mode >> 8) & 0xff;
8626
8627 skip_whitespace (str);
8628
8629 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8630 || skip_past_comma (&str) == FAIL
8631 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
8632 {
8633 if (!inst.error)
8634 inst.error = BAD_ARGS;
8635 }
8636 else
8637 end_of_line (str);
8638}
8639
8640/* Isnsn like "foo X,Y,Z". */
8641
8642static void
8643do_mav_triple (char * str,
8644 int mode,
8645 enum arm_reg_type reg0,
8646 enum arm_reg_type reg1,
8647 enum arm_reg_type reg2)
8648{
8649 int shift0, shift1, shift2;
8650
8651 shift0 = mode & 0xff;
8652 shift1 = (mode >> 8) & 0xff;
8653 shift2 = (mode >> 16) & 0xff;
8654
8655 skip_whitespace (str);
8656
8657 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8658 || skip_past_comma (&str) == FAIL
8659 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8660 || skip_past_comma (&str) == FAIL
8661 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
8662 {
8663 if (!inst.error)
8664 inst.error = BAD_ARGS;
8665 }
8666 else
8667 end_of_line (str);
8668}
8669
8670/* Wrapper functions. */
8671
8672static void
8673do_mav_binops_1a (char * str)
8674{
8675 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8676}
8677
8678static void
8679do_mav_binops_1b (char * str)
8680{
8681 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8682}
8683
8684static void
8685do_mav_binops_1c (char * str)
8686{
8687 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8688}
8689
8690static void
8691do_mav_binops_1d (char * str)
8692{
8693 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8694}
8695
8696static void
8697do_mav_binops_1e (char * str)
8698{
8699 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8700}
8701
8702static void
8703do_mav_binops_1f (char * str)
8704{
8705 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8706}
8707
8708static void
8709do_mav_binops_1g (char * str)
8710{
8711 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8712}
8713
8714static void
8715do_mav_binops_1h (char * str)
8716{
8717 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8718}
8719
8720static void
8721do_mav_binops_1i (char * str)
8722{
8723 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8724}
8725
8726static void
8727do_mav_binops_1j (char * str)
8728{
8729 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8730}
8731
8732static void
8733do_mav_binops_1k (char * str)
8734{
8735 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8736}
8737
8738static void
8739do_mav_binops_1l (char * str)
8740{
8741 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8742}
8743
8744static void
8745do_mav_binops_1m (char * str)
8746{
8747 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8748}
8749
8750static void
8751do_mav_binops_1n (char * str)
8752{
8753 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8754}
8755
8756static void
8757do_mav_binops_1o (char * str)
8758{
8759 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8760}
8761
8762static void
8763do_mav_binops_2a (char * str)
8764{
8765 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8766}
8767
8768static void
8769do_mav_binops_2b (char * str)
8770{
8771 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8772}
404ff6b5 8773
a737bd4d
NC
8774static void
8775do_mav_binops_2c (char * str)
8776{
8777 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8778}
404ff6b5
AH
8779
8780static void
a737bd4d 8781do_mav_binops_3a (char * str)
6c43fab6 8782{
a737bd4d 8783 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
8784}
8785
8786static void
a737bd4d 8787do_mav_binops_3b (char * str)
6c43fab6 8788{
a737bd4d 8789 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
8790}
8791
8792static void
a737bd4d 8793do_mav_binops_3c (char * str)
404ff6b5 8794{
a737bd4d 8795 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
404ff6b5
AH
8796}
8797
8798static void
a737bd4d 8799do_mav_binops_3d (char * str)
404ff6b5 8800{
a737bd4d 8801 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
404ff6b5
AH
8802}
8803
8804static void
a737bd4d 8805do_mav_triple_4a (char * str)
404ff6b5 8806{
a737bd4d 8807 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
404ff6b5
AH
8808}
8809
8810static void
a737bd4d 8811do_mav_triple_4b (char * str)
404ff6b5 8812{
a737bd4d 8813 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
404ff6b5
AH
8814}
8815
8816static void
a737bd4d 8817do_mav_triple_5a (char * str)
404ff6b5 8818{
a737bd4d 8819 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
8820}
8821
8822static void
a737bd4d 8823do_mav_triple_5b (char * str)
404ff6b5 8824{
a737bd4d 8825 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
8826}
8827
6c43fab6 8828static void
a737bd4d 8829do_mav_triple_5c (char * str)
6c43fab6 8830{
a737bd4d 8831 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8832}
8833
8834static void
a737bd4d 8835do_mav_triple_5d (char * str)
6c43fab6 8836{
a737bd4d 8837 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8838}
8839
8840static void
a737bd4d 8841do_mav_triple_5e (char * str)
6c43fab6 8842{
a737bd4d 8843 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
8844}
8845
8846static void
a737bd4d 8847do_mav_triple_5f (char * str)
6c43fab6 8848{
a737bd4d 8849 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
8850}
8851
8852static void
a737bd4d 8853do_mav_triple_5g (char * str)
6c43fab6 8854{
a737bd4d 8855 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
8856}
8857
8858static void
a737bd4d 8859do_mav_triple_5h (char * str)
6c43fab6 8860{
a737bd4d 8861 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
8862}
8863
a737bd4d
NC
8864/* Isnsn like "foo W,X,Y,Z".
8865 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8866
6c43fab6 8867static void
a737bd4d
NC
8868do_mav_quad (char * str,
8869 int mode,
8870 enum arm_reg_type reg0,
8871 enum arm_reg_type reg1,
8872 enum arm_reg_type reg2,
8873 enum arm_reg_type reg3)
6c43fab6 8874{
a737bd4d
NC
8875 int shift0, shift1, shift2, shift3;
8876
8877 shift0= mode & 0xff;
8878 shift1 = (mode >> 8) & 0xff;
8879 shift2 = (mode >> 16) & 0xff;
8880 shift3 = (mode >> 24) & 0xff;
8881
8882 skip_whitespace (str);
8883
8884 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
8885 || skip_past_comma (&str) == FAIL
8886 || mav_reg_required_here (&str, shift1, reg1) == FAIL
8887 || skip_past_comma (&str) == FAIL
8888 || mav_reg_required_here (&str, shift2, reg2) == FAIL
8889 || skip_past_comma (&str) == FAIL
8890 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
8891 {
8892 if (!inst.error)
8893 inst.error = BAD_ARGS;
8894 }
8895 else
8896 end_of_line (str);
6c43fab6
RE
8897}
8898
8899static void
a737bd4d 8900do_mav_quad_6a (char * str)
6c43fab6 8901{
a737bd4d
NC
8902 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
8903 REG_TYPE_MVFX);
6c43fab6
RE
8904}
8905
8906static void
a737bd4d 8907do_mav_quad_6b (char * str)
6c43fab6 8908{
a737bd4d
NC
8909 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
8910 REG_TYPE_MVFX);
6c43fab6
RE
8911}
8912
a737bd4d 8913/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
6c43fab6 8914static void
a737bd4d 8915do_mav_dspsc_1 (char * str)
6c43fab6 8916{
a737bd4d
NC
8917 skip_whitespace (str);
8918
8919 /* cfmvsc32. */
8920 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
8921 || skip_past_comma (&str) == FAIL
8922 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
8923 {
8924 if (!inst.error)
8925 inst.error = BAD_ARGS;
8926
8927 return;
8928 }
8929
8930 end_of_line (str);
6c43fab6
RE
8931}
8932
a737bd4d 8933/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
6c43fab6 8934static void
a737bd4d 8935do_mav_dspsc_2 (char * str)
6c43fab6 8936{
a737bd4d
NC
8937 skip_whitespace (str);
8938
8939 /* cfmv32sc. */
8940 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
8941 || skip_past_comma (&str) == FAIL
8942 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
8943 {
8944 if (!inst.error)
8945 inst.error = BAD_ARGS;
8946
8947 return;
8948 }
8949
8950 end_of_line (str);
6c43fab6
RE
8951}
8952
a737bd4d
NC
8953/* Maverick shift immediate instructions.
8954 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8955 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8956
6c43fab6 8957static void
a737bd4d
NC
8958do_mav_shift (char * str,
8959 enum arm_reg_type reg0,
8960 enum arm_reg_type reg1)
6c43fab6 8961{
a737bd4d
NC
8962 int error;
8963 int imm, neg = 0;
8964
8965 skip_whitespace (str);
8966
8967 error = 0;
8968
8969 if (mav_reg_required_here (&str, 12, reg0) == FAIL
8970 || skip_past_comma (&str) == FAIL
8971 || mav_reg_required_here (&str, 16, reg1) == FAIL
8972 || skip_past_comma (&str) == FAIL)
8973 {
8974 if (!inst.error)
8975 inst.error = BAD_ARGS;
8976 return;
8977 }
8978
8979 /* Calculate the immediate operand.
8980 The operand is a 7bit signed number. */
8981 skip_whitespace (str);
8982
8983 if (*str == '#')
8984 ++str;
8985
8986 if (!ISDIGIT (*str) && *str != '-')
8987 {
8988 inst.error = _("expecting immediate, 7bit operand");
8989 return;
8990 }
8991
8992 if (*str == '-')
8993 {
8994 neg = 1;
8995 ++str;
8996 }
8997
8998 for (imm = 0; *str && ISDIGIT (*str); ++str)
8999 imm = imm * 10 + *str - '0';
9000
9001 if (imm > 64)
9002 {
9003 inst.error = _("immediate out of range");
9004 return;
9005 }
9006
9007 /* Make negative imm's into 7bit signed numbers. */
9008 if (neg)
9009 {
9010 imm = -imm;
9011 imm &= 0x0000007f;
9012 }
9013
9014 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9015 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9016 Bit 4 should be 0. */
9017 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9018
9019 inst.instruction |= imm;
9020 end_of_line (str);
6c43fab6
RE
9021}
9022
9023static void
a737bd4d 9024do_mav_shift_1 (char * str)
6c43fab6 9025{
a737bd4d 9026 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9027}
9028
9029static void
a737bd4d 9030do_mav_shift_2 (char * str)
6c43fab6 9031{
a737bd4d
NC
9032 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9033}
9034
9035static int
9036mav_parse_offset (char ** str, int * negative)
9037{
9038 char * p = *str;
9039 int offset;
9040
9041 *negative = 0;
9042
9043 skip_whitespace (p);
9044
9045 if (*p == '#')
9046 ++p;
9047
9048 if (*p == '-')
9049 {
9050 *negative = 1;
9051 ++p;
9052 }
9053
9054 if (!ISDIGIT (*p))
9055 {
9056 inst.error = _("offset expected");
9057 return 0;
9058 }
9059
9060 for (offset = 0; *p && ISDIGIT (*p); ++p)
9061 offset = offset * 10 + *p - '0';
9062
9063 if (offset > 0x3fc)
9064 {
9065 inst.error = _("offset out of range");
9066 return 0;
9067 }
9068 if (offset & 0x3)
9069 {
9070 inst.error = _("offset not a multiple of 4");
9071 return 0;
9072 }
9073
9074 *str = p;
9075
9076 return *negative ? -offset : offset;
6c43fab6
RE
9077}
9078
a737bd4d
NC
9079/* Maverick load/store instructions.
9080 <insn><cond> CRd,[Rn,<offset>]{!}.
9081 <insn><cond> CRd,[Rn],<offset>. */
9082
9083static void
9084do_mav_ldst (char * str, enum arm_reg_type reg0)
9085{
9086 int offset, negative;
9087
9088 skip_whitespace (str);
9089
9090 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9091 || skip_past_comma (&str) == FAIL
9092 || *str++ != '['
9093 || reg_required_here (&str, 16) == FAIL)
9094 goto fail_ldst;
9095
9096 if (skip_past_comma (&str) == SUCCESS)
9097 {
9098 /* You are here: "<offset>]{!}". */
9099 inst.instruction |= PRE_INDEX;
9100
9101 offset = mav_parse_offset (&str, &negative);
9102
9103 if (inst.error)
9104 return;
9105
9106 if (*str++ != ']')
9107 {
9108 inst.error = _("missing ]");
9109 return;
9110 }
9111
9112 if (*str == '!')
9113 {
9114 inst.instruction |= WRITE_BACK;
9115 ++str;
9116 }
9117 }
9118 else
9119 {
9120 /* You are here: "], <offset>". */
9121 if (*str++ != ']')
9122 {
9123 inst.error = _("missing ]");
9124 return;
9125 }
9126
9127 if (skip_past_comma (&str) == FAIL
9128 || (offset = mav_parse_offset (&str, &negative), inst.error))
9129 goto fail_ldst;
6c43fab6 9130
a737bd4d
NC
9131 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9132 }
6c43fab6 9133
a737bd4d
NC
9134 if (negative)
9135 offset = -offset;
9136 else
9137 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
6c43fab6 9138
a737bd4d
NC
9139 inst.instruction |= offset >> 2;
9140 end_of_line (str);
9141 return;
6c43fab6 9142
a737bd4d
NC
9143fail_ldst:
9144 if (!inst.error)
9145 inst.error = BAD_ARGS;
6c43fab6
RE
9146}
9147
9148static void
a737bd4d 9149do_mav_ldst_1 (char * str)
6c43fab6 9150{
a737bd4d 9151 do_mav_ldst (str, REG_TYPE_MVF);
6c43fab6
RE
9152}
9153
9154static void
a737bd4d 9155do_mav_ldst_2 (char * str)
6c43fab6 9156{
a737bd4d 9157 do_mav_ldst (str, REG_TYPE_MVD);
6c43fab6
RE
9158}
9159
9160static void
a737bd4d 9161do_mav_ldst_3 (char * str)
6c43fab6 9162{
a737bd4d 9163 do_mav_ldst (str, REG_TYPE_MVFX);
6c43fab6
RE
9164}
9165
9166static void
a737bd4d 9167do_mav_ldst_4 (char * str)
6c43fab6 9168{
a737bd4d 9169 do_mav_ldst (str, REG_TYPE_MVDX);
6c43fab6
RE
9170}
9171
9172static void
a737bd4d 9173do_t_nop (char * str)
6c43fab6 9174{
a737bd4d
NC
9175 /* Do nothing. */
9176 end_of_line (str);
6c43fab6
RE
9177}
9178
a737bd4d
NC
9179/* Handle the Format 4 instructions that do not have equivalents in other
9180 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9181 BIC and MVN. */
6c43fab6
RE
9182
9183static void
a737bd4d 9184do_t_arit (char * str)
6c43fab6 9185{
a737bd4d 9186 int Rd, Rs, Rn;
6c43fab6 9187
6c43fab6
RE
9188 skip_whitespace (str);
9189
a737bd4d 9190 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6c43fab6 9191 || skip_past_comma (&str) == FAIL
a737bd4d 9192 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6c43fab6 9193 {
a737bd4d 9194 inst.error = BAD_ARGS;
6c43fab6
RE
9195 return;
9196 }
9197
a737bd4d 9198 if (skip_past_comma (&str) != FAIL)
6c43fab6 9199 {
a737bd4d
NC
9200 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9201 (It isn't allowed for CMP either, but that isn't handled by this
9202 function.) */
9203 if (inst.instruction == T_OPCODE_TST
9204 || inst.instruction == T_OPCODE_CMN
9205 || inst.instruction == T_OPCODE_NEG
9206 || inst.instruction == T_OPCODE_MVN)
9207 {
9208 inst.error = BAD_ARGS;
9209 return;
9210 }
6c43fab6 9211
a737bd4d
NC
9212 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9213 return;
9214
9215 if (Rs != Rd)
9216 {
9217 inst.error = _("dest and source1 must be the same register");
9218 return;
9219 }
9220 Rs = Rn;
6c43fab6
RE
9221 }
9222
a737bd4d
NC
9223 if (inst.instruction == T_OPCODE_MUL
9224 && Rs == Rd)
9225 as_tsktsk (_("Rs and Rd must be different in MUL"));
9226
9227 inst.instruction |= Rd | (Rs << 3);
6c43fab6 9228 end_of_line (str);
404ff6b5
AH
9229}
9230
9231static void
a737bd4d 9232do_t_add (char * str)
404ff6b5 9233{
a737bd4d 9234 thumb_add_sub (str, 0);
404ff6b5
AH
9235}
9236
9237static void
a737bd4d 9238do_t_asr (char * str)
404ff6b5 9239{
a737bd4d 9240 thumb_shift (str, THUMB_ASR);
404ff6b5
AH
9241}
9242
9243static void
a737bd4d 9244do_t_branch9 (char * str)
404ff6b5 9245{
a737bd4d
NC
9246 if (my_get_expression (&inst.reloc.exp, &str))
9247 return;
9248 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9249 inst.reloc.pc_rel = 1;
9250 end_of_line (str);
404ff6b5
AH
9251}
9252
9253static void
a737bd4d 9254do_t_branch12 (char * str)
404ff6b5 9255{
a737bd4d
NC
9256 if (my_get_expression (&inst.reloc.exp, &str))
9257 return;
9258 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9259 inst.reloc.pc_rel = 1;
9260 end_of_line (str);
404ff6b5
AH
9261}
9262
a737bd4d 9263/* Find the real, Thumb encoded start of a Thumb function. */
404ff6b5 9264
a737bd4d
NC
9265static symbolS *
9266find_real_start (symbolS * symbolP)
404ff6b5 9267{
a737bd4d
NC
9268 char * real_start;
9269 const char * name = S_GET_NAME (symbolP);
9270 symbolS * new_target;
404ff6b5 9271
a737bd4d
NC
9272 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9273#define STUB_NAME ".real_start_of"
404ff6b5 9274
a737bd4d
NC
9275 if (name == NULL)
9276 abort ();
404ff6b5 9277
a737bd4d
NC
9278 /* Names that start with '.' are local labels, not function entry points.
9279 The compiler may generate BL instructions to these labels because it
9280 needs to perform a branch to a far away location. */
9281 if (name[0] == '.')
9282 return symbolP;
404ff6b5 9283
a737bd4d
NC
9284 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9285 sprintf (real_start, "%s%s", STUB_NAME, name);
404ff6b5 9286
a737bd4d
NC
9287 new_target = symbol_find (real_start);
9288
9289 if (new_target == NULL)
404ff6b5 9290 {
a737bd4d
NC
9291 as_warn ("Failed to find real start of function: %s\n", name);
9292 new_target = symbolP;
404ff6b5 9293 }
404ff6b5 9294
a737bd4d
NC
9295 free (real_start);
9296
9297 return new_target;
9298}
404ff6b5
AH
9299
9300static void
a737bd4d 9301do_t_branch23 (char * str)
404ff6b5 9302{
a737bd4d
NC
9303 if (my_get_expression (& inst.reloc.exp, & str))
9304 return;
404ff6b5 9305
a737bd4d
NC
9306 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9307 inst.reloc.pc_rel = 1;
9308 end_of_line (str);
404ff6b5 9309
a737bd4d
NC
9310 /* If the destination of the branch is a defined symbol which does not have
9311 the THUMB_FUNC attribute, then we must be calling a function which has
9312 the (interfacearm) attribute. We look for the Thumb entry point to that
9313 function and change the branch to refer to that function instead. */
9314 if ( inst.reloc.exp.X_op == O_symbol
9315 && inst.reloc.exp.X_add_symbol != NULL
9316 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9317 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9318 inst.reloc.exp.X_add_symbol =
9319 find_real_start (inst.reloc.exp.X_add_symbol);
404ff6b5
AH
9320}
9321
404ff6b5 9322static void
a737bd4d 9323do_t_bx (char * str)
404ff6b5 9324{
a737bd4d 9325 int reg;
404ff6b5
AH
9326
9327 skip_whitespace (str);
9328
a737bd4d
NC
9329 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9330 return;
9331
9332 /* This sets THUMB_H2 from the top bit of reg. */
9333 inst.instruction |= reg << 3;
9334
9335 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9336 should cause the alignment to be checked once it is known. This is
9337 because BX PC only works if the instruction is word aligned. */
9338
9339 end_of_line (str);
404ff6b5
AH
9340}
9341
a737bd4d
NC
9342static void
9343do_t_compare (char * str)
9344{
9345 thumb_mov_compare (str, THUMB_COMPARE);
9346}
404ff6b5
AH
9347
9348static void
a737bd4d 9349do_t_ldmstm (char * str)
404ff6b5 9350{
a737bd4d
NC
9351 int Rb;
9352 long range;
404ff6b5
AH
9353
9354 skip_whitespace (str);
9355
a737bd4d
NC
9356 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9357 return;
404ff6b5 9358
a737bd4d
NC
9359 if (*str != '!')
9360 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9361 else
9362 str++;
9363
9364 if (skip_past_comma (&str) == FAIL
9365 || (range = reg_list (&str)) == FAIL)
404ff6b5 9366 {
a737bd4d 9367 if (! inst.error)
404ff6b5
AH
9368 inst.error = BAD_ARGS;
9369 return;
9370 }
9371
620b81c1 9372 if (inst.reloc.type != BFD_RELOC_UNUSED)
404ff6b5 9373 {
a737bd4d 9374 /* This really doesn't seem worth it. */
620b81c1 9375 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d 9376 inst.error = _("expression too complex");
404ff6b5
AH
9377 return;
9378 }
9379
a737bd4d 9380 if (range & ~0xff)
404ff6b5 9381 {
a737bd4d 9382 inst.error = _("only lo-regs valid in load/store multiple");
404ff6b5
AH
9383 return;
9384 }
9385
a737bd4d 9386 inst.instruction |= (Rb << 8) | range;
404ff6b5 9387 end_of_line (str);
404ff6b5
AH
9388}
9389
a737bd4d
NC
9390static void
9391do_t_ldr (char * str)
404ff6b5 9392{
a737bd4d
NC
9393 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9394}
404ff6b5 9395
a737bd4d
NC
9396static void
9397do_t_ldrb (char * str)
9398{
9399 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9400}
404ff6b5 9401
a737bd4d
NC
9402static void
9403do_t_ldrh (char * str)
9404{
9405 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9406}
404ff6b5 9407
a737bd4d
NC
9408static void
9409do_t_lds (char * str)
9410{
9411 int Rd, Rb, Ro;
404ff6b5 9412
a737bd4d 9413 skip_whitespace (str);
404ff6b5 9414
a737bd4d
NC
9415 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9416 || skip_past_comma (&str) == FAIL
9417 || *str++ != '['
9418 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9419 || skip_past_comma (&str) == FAIL
9420 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9421 || *str++ != ']')
404ff6b5 9422 {
a737bd4d
NC
9423 if (! inst.error)
9424 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9425 return;
404ff6b5
AH
9426 }
9427
a737bd4d
NC
9428 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9429 end_of_line (str);
9430}
404ff6b5 9431
a737bd4d
NC
9432static void
9433do_t_lsl (char * str)
9434{
9435 thumb_shift (str, THUMB_LSL);
9436}
404ff6b5 9437
a737bd4d
NC
9438static void
9439do_t_lsr (char * str)
9440{
9441 thumb_shift (str, THUMB_LSR);
404ff6b5
AH
9442}
9443
a737bd4d
NC
9444static void
9445do_t_mov (char * str)
9446{
9447 thumb_mov_compare (str, THUMB_MOVE);
9448}
404ff6b5
AH
9449
9450static void
a737bd4d 9451do_t_push_pop (char * str)
404ff6b5 9452{
a737bd4d 9453 long range;
404ff6b5
AH
9454
9455 skip_whitespace (str);
9456
a737bd4d 9457 if ((range = reg_list (&str)) == FAIL)
404ff6b5 9458 {
a737bd4d
NC
9459 if (! inst.error)
9460 inst.error = BAD_ARGS;
9461 return;
9462 }
404ff6b5 9463
620b81c1 9464 if (inst.reloc.type != BFD_RELOC_UNUSED)
a737bd4d
NC
9465 {
9466 /* This really doesn't seem worth it. */
620b81c1 9467 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d
NC
9468 inst.error = _("expression too complex");
9469 return;
9470 }
404ff6b5 9471
a737bd4d
NC
9472 if (range & ~0xff)
9473 {
9474 if ((inst.instruction == T_OPCODE_PUSH
9475 && (range & ~0xff) == 1 << REG_LR)
9476 || (inst.instruction == T_OPCODE_POP
9477 && (range & ~0xff) == 1 << REG_PC))
404ff6b5 9478 {
a737bd4d
NC
9479 inst.instruction |= THUMB_PP_PC_LR;
9480 range &= 0xff;
404ff6b5 9481 }
a737bd4d 9482 else
404ff6b5 9483 {
a737bd4d 9484 inst.error = _("invalid register list to push/pop instruction");
404ff6b5
AH
9485 return;
9486 }
404ff6b5
AH
9487 }
9488
a737bd4d 9489 inst.instruction |= range;
404ff6b5 9490 end_of_line (str);
a737bd4d 9491}
404ff6b5 9492
a737bd4d
NC
9493static void
9494do_t_str (char * str)
9495{
9496 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
404ff6b5
AH
9497}
9498
b99bd4ef 9499static void
a737bd4d 9500do_t_strb (char * str)
b99bd4ef 9501{
a737bd4d 9502 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
b99bd4ef
NC
9503}
9504
a737bd4d
NC
9505static void
9506do_t_strh (char * str)
9507{
9508 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9509}
b99bd4ef
NC
9510
9511static void
a737bd4d 9512do_t_sub (char * str)
b99bd4ef 9513{
a737bd4d
NC
9514 thumb_add_sub (str, 1);
9515}
b99bd4ef 9516
a737bd4d
NC
9517static void
9518do_t_swi (char * str)
9519{
b99bd4ef
NC
9520 skip_whitespace (str);
9521
a737bd4d
NC
9522 if (my_get_expression (&inst.reloc.exp, &str))
9523 return;
b99bd4ef 9524
a737bd4d
NC
9525 inst.reloc.type = BFD_RELOC_ARM_SWI;
9526 end_of_line (str);
9527}
b99bd4ef 9528
a737bd4d
NC
9529static void
9530do_t_adr (char * str)
9531{
9532 int reg;
b99bd4ef 9533
a737bd4d
NC
9534 /* This is a pseudo-op of the form "adr rd, label" to be converted
9535 into a relative address of the form "add rd, pc, #label-.-4". */
9536 skip_whitespace (str);
9537
9538 /* Store Rd in temporary location inside instruction. */
9539 if ((reg = reg_required_here (&str, 4)) == FAIL
9540 || (reg > 7) /* For Thumb reg must be r0..r7. */
9541 || skip_past_comma (&str) == FAIL
9542 || my_get_expression (&inst.reloc.exp, &str))
9543 {
9544 if (!inst.error)
9545 inst.error = BAD_ARGS;
9546 return;
b99bd4ef
NC
9547 }
9548
a737bd4d
NC
9549 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9550 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9551 inst.reloc.pc_rel = 1;
9552 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
b99bd4ef 9553
b99bd4ef
NC
9554 end_of_line (str);
9555}
9556
9557static void
a737bd4d
NC
9558insert_reg (const struct reg_entry * r,
9559 struct hash_control * htab)
b99bd4ef 9560{
a737bd4d
NC
9561 int len = strlen (r->name) + 2;
9562 char * buf = xmalloc (len);
9563 char * buf2 = xmalloc (len);
9564 int i = 0;
b99bd4ef 9565
a737bd4d
NC
9566#ifdef REGISTER_PREFIX
9567 buf[i++] = REGISTER_PREFIX;
9568#endif
9569
9570 strcpy (buf + i, r->name);
9571
9572 for (i = 0; buf[i]; i++)
9573 buf2[i] = TOUPPER (buf[i]);
9574
9575 buf2[i] = '\0';
9576
9577 hash_insert (htab, buf, (PTR) r);
9578 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9579}
9580
9581static void
a737bd4d 9582build_reg_hsh (struct reg_map * map)
b99bd4ef 9583{
a737bd4d
NC
9584 const struct reg_entry *r;
9585
9586 if ((map->htab = hash_new ()) == NULL)
9587 as_fatal (_("virtual memory exhausted"));
9588
9589 for (r = map->names; r->name != NULL; r++)
9590 insert_reg (r, map->htab);
b99bd4ef
NC
9591}
9592
9593static void
a737bd4d
NC
9594insert_reg_alias (char * str,
9595 int regnum,
9596 struct hash_control *htab)
b99bd4ef 9597{
a737bd4d
NC
9598 const char * error;
9599 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9600 const char * name = xmalloc (strlen (str) + 1);
9601
9602 strcpy ((char *) name, str);
9603
9604 new->name = name;
9605 new->number = regnum;
9606 new->builtin = FALSE;
9607
9608 error = hash_insert (htab, name, (PTR) new);
9609 if (error)
9610 {
9611 as_bad (_("failed to create an alias for %s, reason: %s"),
9612 str, error);
9613 free ((char *) name);
9614 free (new);
9615 }
b99bd4ef
NC
9616}
9617
a737bd4d 9618/* Look for the .req directive. This is of the form:
b99bd4ef 9619
a737bd4d
NC
9620 new_register_name .req existing_register_name
9621
9622 If we find one, or if it looks sufficiently like one that we want to
9623 handle any error here, return non-zero. Otherwise return zero. */
9624
9625static int
9626create_register_alias (char * newname, char * p)
b99bd4ef 9627{
a737bd4d
NC
9628 char * q;
9629 char c;
b99bd4ef 9630
a737bd4d
NC
9631 q = p;
9632 skip_whitespace (q);
b99bd4ef 9633
a737bd4d
NC
9634 c = *p;
9635 *p = '\0';
b99bd4ef 9636
a737bd4d
NC
9637 if (*q && !strncmp (q, ".req ", 5))
9638 {
9639 char *copy_of_str;
9640 char *r;
b99bd4ef 9641
a737bd4d
NC
9642#ifndef IGNORE_OPCODE_CASE
9643 newname = original_case_string;
9644#endif
9645 copy_of_str = newname;
b99bd4ef 9646
a737bd4d
NC
9647 q += 4;
9648 skip_whitespace (q);
b99bd4ef 9649
a737bd4d
NC
9650 for (r = q; *r != '\0'; r++)
9651 if (*r == ' ')
9652 break;
b99bd4ef 9653
a737bd4d
NC
9654 if (r != q)
9655 {
9656 enum arm_reg_type new_type, old_type;
9657 int old_regno;
9658 char d = *r;
b99bd4ef 9659
a737bd4d
NC
9660 *r = '\0';
9661 old_type = arm_reg_parse_any (q);
9662 *r = d;
9663
9664 new_type = arm_reg_parse_any (newname);
9665
9666 if (new_type == REG_TYPE_MAX)
9667 {
9668 if (old_type != REG_TYPE_MAX)
9669 {
9670 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9671 insert_reg_alias (newname, old_regno,
9672 all_reg_maps[old_type].htab);
9673 }
9674 else
9675 as_warn (_("register '%s' does not exist\n"), q);
9676 }
9677 else if (old_type == REG_TYPE_MAX)
9678 {
9679 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9680 copy_of_str, q);
9681 }
9682 else
9683 {
9684 /* Do not warn about redefinitions to the same alias. */
9685 if (new_type != old_type
9686 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
9687 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
9688 as_warn (_("ignoring redefinition of register alias '%s'"),
9689 copy_of_str);
9690
9691 }
9692 }
9693 else
9694 as_warn (_("ignoring incomplete .req pseuso op"));
9695
9696 *p = c;
9697 return 1;
9698 }
9699
9700 *p = c;
9701 return 0;
b99bd4ef
NC
9702}
9703
9704static void
a737bd4d 9705set_constant_flonums (void)
b99bd4ef 9706{
a737bd4d 9707 int i;
b99bd4ef 9708
a737bd4d
NC
9709 for (i = 0; i < NUM_FLOAT_VALS; i++)
9710 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
9711 abort ();
b99bd4ef
NC
9712}
9713
a737bd4d
NC
9714\f
9715static const struct asm_opcode insns[] =
b99bd4ef 9716{
a737bd4d
NC
9717 /* Core ARM Instructions. */
9718 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
9719 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
9720 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
9721 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
9722 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
9723 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
9724 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
9725 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
9726 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
9727 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
9728 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
9729 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
9730 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
9731 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
9732 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
9733 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
9734 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
9735 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
9736 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
9737 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
9738
9739 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9740 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
9741 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
9742 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9743 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
9744 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
9745 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9746 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
9747 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
9748 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9749 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
9750 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
9751
9752 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
9753 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
9754 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
9755 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
9756
9757 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
9758 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
9759 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
9760 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
9761 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
9762 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
9763 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
9764 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
9765
9766 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9767 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9768 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9769 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9770 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
9771 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
9772 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
9773 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
9774
9775 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9776 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
9777 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9778 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9779 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
9780 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
9781 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
9782 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
b99bd4ef 9783
a737bd4d
NC
9784 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
9785#ifdef TE_WINCE
9786 /* XXX This is the wrong place to do this. Think multi-arch. */
9787 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
9788 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
9789#else
9790 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
9791 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
9792#endif
b99bd4ef 9793
a737bd4d
NC
9794 /* Pseudo ops. */
9795 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
9796 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
0dd132b6 9797 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
b99bd4ef 9798
a737bd4d
NC
9799 /* ARM 2 multiplies. */
9800 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
9801 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
9802 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
9803 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 9804
a737bd4d
NC
9805 /* Generic coprocessor instructions. */
9806 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
9807 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
9808 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
9809 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
9810 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
9811 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
9812 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
b99bd4ef 9813
a737bd4d
NC
9814 /* ARM 3 - swp instructions. */
9815 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
9816 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 9817
a737bd4d
NC
9818 /* ARM 6 Status register instructions. */
9819 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
9820 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
9821 /* ScottB: our code uses 0xe128f000 for msr.
9822 NickC: but this is wrong because the bits 16 through 19 are
9823 handled by the PSR_xxx defines above. */
b99bd4ef 9824
a737bd4d
NC
9825 /* ARM 7M long multiplies. */
9826 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
9827 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
9828 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
9829 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
9830 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
9831 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
9832 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
9833 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
b99bd4ef 9834
a737bd4d
NC
9835 /* ARM Architecture 4. */
9836 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
9837 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
9838 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
9839 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 9840
a737bd4d
NC
9841 /* ARM Architecture 4T. */
9842 /* Note: bx (and blx) are required on V5, even if the processor does
9843 not support Thumb. */
9844 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
b99bd4ef 9845
a737bd4d
NC
9846 /* ARM Architecture 5T. */
9847 /* Note: blx has 2 variants, so the .value is set dynamically.
9848 Only one of the variants has conditional execution. */
9849 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
9850 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
9851 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
9852 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
9853 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
9854 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
9855 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
9856 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
9857 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
9858 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
b99bd4ef 9859
a737bd4d
NC
9860 /* ARM Architecture 5TExP. */
9861 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
9862 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
9863 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
9864 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 9865
a737bd4d
NC
9866 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
9867 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 9868
a737bd4d
NC
9869 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
9870 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
9871 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
9872 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
b99bd4ef 9873
a737bd4d
NC
9874 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
9875 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
9876 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
9877 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 9878
a737bd4d
NC
9879 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
9880 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 9881
a737bd4d
NC
9882 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
9883 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
9884 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
9885 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
b99bd4ef 9886
a737bd4d
NC
9887 /* ARM Architecture 5TE. */
9888 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
9889 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
9890 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
b99bd4ef 9891
a737bd4d
NC
9892 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
9893 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
b99bd4ef 9894
a737bd4d
NC
9895 /* ARM Architecture 5TEJ. */
9896 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
b99bd4ef 9897
a737bd4d
NC
9898 /* ARM V6. */
9899 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
9900 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
9901 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
9902 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
9903 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
9904 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
9905 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
9906 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
9907 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
9908 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
9909 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
9910 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
9911 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
9912 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
9913 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
9914 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
9915 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
9916 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
9917 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
9918 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
9919 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
9920 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
9921 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
9922 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
9923 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
9924 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
9925 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
9926 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
9927 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
9928 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
9929 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
9930 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
9931 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
9932 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
9933 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
9934 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
9935 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
9936 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
9937 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
9938 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
9939 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
9940 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
9941 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
9942 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
9943 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
9944 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
9945 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
9946 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9947 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9948 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9949 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9950 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
9951 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
9952 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
9953 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
9954 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
9955 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
9956 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
9957 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
9958 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
9959 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
9960 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
9961 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
9962 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
9963 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
9964 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
9965 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
9966 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
9967 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
9968 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
9969 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
9970 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
9971 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
9972 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
9973 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
9974 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
9975 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
9976 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
9977 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
9978 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
9979 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
9980 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
9981 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
9982 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
9983 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
9984 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
9985 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
9986 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
9987 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
9988 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
9989 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
9990 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
9991 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
9992 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
9993 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
9994 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
9995 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
9996 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
9997 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
b99bd4ef 9998
0dd132b6
NC
9999 /* ARM V6K. */
10000 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10001 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10002 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10003 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10004 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10005 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10006 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10007 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10008 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10009 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10010 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
7ed4c4c5 10011
0dd132b6
NC
10012 /* ARM V6Z. */
10013 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10014
a737bd4d
NC
10015 /* Core FPA instruction set (V1). */
10016 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10017 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10018 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10019 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
b99bd4ef 10020
a737bd4d
NC
10021 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10022 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10023 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10024 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10025
a737bd4d
NC
10026 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10027 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10028 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10029 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10030
a737bd4d
NC
10031 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10032 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10033 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10034 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10035 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10036 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10037 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10038 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10039 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10040 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10041 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10042 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10043
a737bd4d
NC
10044 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10045 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10046 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10047 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10048 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10049 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10050 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10051 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10052 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10053 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10054 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10055 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10056
a737bd4d
NC
10057 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10058 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10059 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10060 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10061 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10062 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10063 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10064 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10065 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10066 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10067 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10068 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10069
a737bd4d
NC
10070 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10071 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10072 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10073 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10074 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10075 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10076 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10077 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10078 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10079 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10080 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10081 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10082
a737bd4d
NC
10083 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10084 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10085 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10086 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10087 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10088 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10089 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10090 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10091 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10092 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10093 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10094 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10095
a737bd4d
NC
10096 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10097 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10098 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10099 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10100 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10101 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10102 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10103 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10104 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10105 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10106 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10107 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10108
a737bd4d
NC
10109 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10110 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10111 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10112 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10113 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10114 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10115 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10116 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10117 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10118 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10119 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10120 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10121
a737bd4d
NC
10122 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10123 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10124 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10125 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10126 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10127 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10128 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10129 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10130 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10131 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10132 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10133 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10134
a737bd4d
NC
10135 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10136 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10137 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10138 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10139 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10140 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10141 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10142 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10143 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10144 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10145 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10146 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10147
a737bd4d
NC
10148 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10149 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10150 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10151 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10152 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10153 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10154 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10155 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10156 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10157 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10158 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10159 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10160
a737bd4d
NC
10161 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10162 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10163 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10164 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10165 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10166 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10167 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10168 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10169 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10170 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10171 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10172 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10173
a737bd4d
NC
10174 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10175 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10176 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10177 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10178 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10179 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10180 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10181 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10182 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10183 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10184 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10185 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10186
a737bd4d
NC
10187 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10188 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10189 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10190 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10191 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10192 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10193 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10194 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10195 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10196 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10197 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10198 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10199
a737bd4d
NC
10200 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10201 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10202 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10203 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10204 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10205 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10206 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10207 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10208 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10209 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10210 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10211 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10212
a737bd4d
NC
10213 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10214 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10215 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10216 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10217 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10218 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10219 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10220 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10221 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10222 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10223 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10224 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10225
a737bd4d
NC
10226 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10227 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10228 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10229 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10230 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10231 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10232 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10233 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10234 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10235 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10236 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10237 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10238
a737bd4d
NC
10239 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10240 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10241 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10242 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10243 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10244 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10245 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10246 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10247 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10248 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10249 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10250 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10251
a737bd4d
NC
10252 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10253 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10254 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10255 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10256 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10257 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10258 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10259 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10260 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10261 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10262 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10263 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10264
a737bd4d
NC
10265 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10266 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10267 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10268 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10269 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10270 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10271 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10272 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10273 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10274 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10275 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10276 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10277
a737bd4d
NC
10278 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10279 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10280 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10281 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10282 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10283 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10284 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10285 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10286 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10287 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10288 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10289 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10290
a737bd4d
NC
10291 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10292 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10293 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10294 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10295 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10296 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10297 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10298 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10299 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10300 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10301 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10302 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10303
a737bd4d
NC
10304 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10305 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10306 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10307 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10308 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10309 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10310 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10311 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10312 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10313 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10314 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10315 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10316
a737bd4d
NC
10317 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10318 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10319 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10320 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10321 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10322 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10323 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10324 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10325 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10326 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10327 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10328 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10329
a737bd4d
NC
10330 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10331 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10332 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10333 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10334 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10335 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10336 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10337 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10338 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10339 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10340 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10341 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10342
a737bd4d
NC
10343 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10344 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10345 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10346 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10347 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10348 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10349 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10350 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10351 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10352 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10353 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10354 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10355
a737bd4d
NC
10356 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10357 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10358 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10359 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10360 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10361 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10362 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10363 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10364 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10365 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10366 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10367 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10368
a737bd4d
NC
10369 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10370 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10371 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10372 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10373 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10374 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10375 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10376 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10377 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10378 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10379 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10380 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10381
a737bd4d
NC
10382 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10383 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10384 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10385 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10386 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10387 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10388 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10389 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10390 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10391 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10392 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10393 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10394
a737bd4d
NC
10395 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10396 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10397 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10398 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10399 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10400 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10401 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10402 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10403 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10404 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10405 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10406 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10407
a737bd4d
NC
10408 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10409 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10410 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10411 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10412 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10413 not be an optional suffix, but part of the instruction. To be
10414 compatible, we accept either. */
10415 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10416 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
b99bd4ef 10417
a737bd4d
NC
10418 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10419 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10420 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10421 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10422 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10423 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10424 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10425 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10426 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10427 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10428 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10429 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
6c43fab6 10430
a737bd4d
NC
10431 /* The implementation of the FIX instruction is broken on some
10432 assemblers, in that it accepts a precision specifier as well as a
10433 rounding specifier, despite the fact that this is meaningless.
10434 To be more compatible, we accept it as well, though of course it
10435 does not set any bits. */
10436 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10437 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10438 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10439 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10440 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10441 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10442 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10443 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10444 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10445 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10446 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10447 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10448 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
6c43fab6 10449
a737bd4d
NC
10450 /* Instructions that were new with the real FPA, call them V2. */
10451 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10452 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10453 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10454 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10455 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10456 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
6c43fab6 10457
a737bd4d
NC
10458 /* VFP V1xD (single precision). */
10459 /* Moves and type conversions. */
10460 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10461 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10462 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10463 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10464 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10465 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10466 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10467 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10468 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10469 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10470 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10471 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
6c43fab6 10472
a737bd4d
NC
10473 /* Memory operations. */
10474 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10475 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10476 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10477 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10478 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10479 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10480 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10481 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10482 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10483 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10484 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10485 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10486 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10487 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10488 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10489 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10490 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10491 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
6c43fab6 10492
a737bd4d
NC
10493 /* Monadic operations. */
10494 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10495 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10496 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
6c43fab6 10497
a737bd4d
NC
10498 /* Dyadic operations. */
10499 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10500 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10501 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10502 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10503 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10504 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10505 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10506 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10507 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
6c43fab6 10508
a737bd4d
NC
10509 /* Comparisons. */
10510 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10511 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10512 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10513 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
6c43fab6 10514
a737bd4d
NC
10515 /* VFP V1 (Double precision). */
10516 /* Moves and type conversions. */
10517 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10518 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10519 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10520 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10521 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10522 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10523 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10524 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10525 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10526 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10527 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10528 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10529 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
6c43fab6 10530
a737bd4d
NC
10531 /* Memory operations. */
10532 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10533 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10534 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10535 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10536 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10537 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10538 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10539 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10540 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10541 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
6c43fab6 10542
a737bd4d
NC
10543 /* Monadic operations. */
10544 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10545 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10546 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
6c43fab6 10547
a737bd4d
NC
10548 /* Dyadic operations. */
10549 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10550 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10551 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10552 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10553 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10554 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10555 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10556 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10557 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
6c43fab6 10558
a737bd4d
NC
10559 /* Comparisons. */
10560 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10561 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10562 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10563 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
6c43fab6 10564
a737bd4d
NC
10565 /* VFP V2. */
10566 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10567 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10568 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10569 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
6c43fab6 10570
a737bd4d
NC
10571 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10572 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10573 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10574 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10575 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10576 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10577 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10578 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10579 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
cc8a6dd0 10580
a737bd4d
NC
10581 /* Intel Wireless MMX technology instructions. */
10582 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10583 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10584 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10585 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10586 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10587 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10588 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10589 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10590 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10591 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10592 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10593 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10594 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10595 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10596 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10597 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10598 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10599 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10600 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10601 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10602 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10603 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10604 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10605 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10606 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10607 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10608 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10609 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10610 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10611 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
10612 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
10613 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10614 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10615 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
10616 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10617 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10618 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10619 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10620 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10621 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10622 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10623 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10624 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10625 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10626 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10627 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10628 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
10629 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10630 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10631 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10632 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10633 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10634 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10635 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10636 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10637 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10638 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10639 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10640 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10641 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10642 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10643 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10644 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10645 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10646 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10647 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10648 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10649 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10650 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10651 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10652 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10653 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10654 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10655 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10656 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10657 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10658 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10659 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10660 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10661 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10662 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10663 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10664 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10665 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10666 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10667 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10668 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10669 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10670 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
10671 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10672 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10673 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10674 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10675 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10676 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10677 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10678 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10679 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10680 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10681 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10682 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10683 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10684 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10685 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10686 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10687 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10688 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10689 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10690 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10691 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10692 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
10693 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10694 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10695 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10696 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10697 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10698 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10699 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10700 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10701 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10702 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10703 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10704 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10705 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10706 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10707 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10708 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10709 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10710 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
10711 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10712 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
10713 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10714 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
10715 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10716 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10717 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10718 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10719 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10720 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10721 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10722 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10723 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10724 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10725 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10726 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10727 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10728 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10729 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10730 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10731 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10732 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10733 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10734 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10735 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10736 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10737 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10738 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
10739 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10740 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10741 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10742 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
10743 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
b99bd4ef 10744
a737bd4d
NC
10745 /* Cirrus Maverick instructions. */
10746 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10747 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10748 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10749 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10750 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
10751 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
10752 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
10753 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
10754 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
10755 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
10756 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10757 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10758 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
10759 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
10760 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10761 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10762 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
10763 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
10764 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10765 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10766 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10767 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10768 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10769 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10770 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
10771 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
10772 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
10773 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
10774 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
10775 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
10776 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10777 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10778 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
10779 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
10780 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
10781 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
10782 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
10783 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
10784 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10785 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10786 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
10787 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
10788 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
10789 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
10790 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
10791 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
10792 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
10793 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
10794 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
10795 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
10796 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10797 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10798 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
10799 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
10800 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10801 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10802 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10803 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10804 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
10805 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
10806 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10807 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10808 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
10809 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
10810 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10811 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10812 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10813 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10814 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10815 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
10816 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10817 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
10818 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10819 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
10820 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10821 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
10822};
b99bd4ef 10823
90e4755a 10824/* Iterate over the base tables to create the instruction patterns. */
a737bd4d 10825
90e4755a 10826static void
a737bd4d 10827build_arm_ops_hsh (void)
90e4755a
RE
10828{
10829 unsigned int i;
10830 unsigned int j;
10831 static struct obstack insn_obstack;
10832
10833 obstack_begin (&insn_obstack, 4000);
10834
10835 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10836 {
6c43fab6 10837 const struct asm_opcode *insn = insns + i;
90e4755a
RE
10838
10839 if (insn->cond_offset != 0)
10840 {
10841 /* Insn supports conditional execution. Build the varaints
10842 and insert them in the hash table. */
10843 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10844 {
10845 unsigned len = strlen (insn->template);
10846 struct asm_opcode *new;
10847 char *template;
10848
10849 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10850 /* All condition codes are two characters. */
10851 template = obstack_alloc (&insn_obstack, len + 3);
10852
10853 strncpy (template, insn->template, insn->cond_offset);
10854 strcpy (template + insn->cond_offset, conds[j].template);
10855 if (len > insn->cond_offset)
10856 strcpy (template + insn->cond_offset + 2,
10857 insn->template + insn->cond_offset);
10858 new->template = template;
10859 new->cond_offset = 0;
10860 new->variant = insn->variant;
10861 new->parms = insn->parms;
10862 new->value = (insn->value & ~COND_MASK) | conds[j].value;
10863
10864 hash_insert (arm_ops_hsh, new->template, (PTR) new);
10865 }
10866 }
10867 /* Finally, insert the unconditional insn in the table directly;
10868 no need to build a copy. */
10869 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10870 }
10871}
10872
a737bd4d
NC
10873\f
10874static const struct thumb_opcode tinsns[] =
10875{
10876 /* Thumb v1 (ARMv4T). */
10877 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
10878 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
10879 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
10880 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
10881 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
10882 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
10883 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
10884 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10885 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
10886 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10887 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10888 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
10889 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
10890 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
10891 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
10892 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
10893 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
10894 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
10895 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
10896 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
10897 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
10898 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
10899 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
10900 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
10901 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
10902 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
10903 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
10904 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
10905 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
10906 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
10907 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
10908 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
10909 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
10910 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10911 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10912 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
10913 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
10914 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
10915 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
10916 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
10917 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
10918 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
10919 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
10920 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
10921 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
10922 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
10923 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
10924 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
10925 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
10926 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
10927 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
10928 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
10929 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
10930 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
10931 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
10932 /* Pseudo ops: */
10933 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
10934 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
10935 /* Thumb v2 (ARMv5T). */
10936 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
10937 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
10938
10939 /* ARM V6. */
10940 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
10941 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
10942 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
10943 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
10944 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
10945 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
10946 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
10947 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
10948 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
10949 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
10950 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
10951};
5a6c6817 10952
b99bd4ef 10953void
a737bd4d 10954md_begin (void)
b99bd4ef
NC
10955{
10956 unsigned mach;
10957 unsigned int i;
10958
10959 if ( (arm_ops_hsh = hash_new ()) == NULL
10960 || (arm_tops_hsh = hash_new ()) == NULL
10961 || (arm_cond_hsh = hash_new ()) == NULL
10962 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 10963 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 10964 as_fatal (_("virtual memory exhausted"));
b99bd4ef 10965
90e4755a 10966 build_arm_ops_hsh ();
b99bd4ef
NC
10967 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10968 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10969 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10970 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10971 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10972 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10973 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10974 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10975
6c43fab6
RE
10976 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10977 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
10978
10979 set_constant_flonums ();
10980
03b1477f
RE
10981 /* Set the cpu variant based on the command-line options. We prefer
10982 -mcpu= over -march= if both are set (as for GCC); and we prefer
10983 -mfpu= over any other way of setting the floating point unit.
10984 Use of legacy options with new options are faulted. */
10985 if (legacy_cpu != -1)
10986 {
10987 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10988 as_bad (_("use of old and new-style options to set CPU type"));
10989
10990 mcpu_cpu_opt = legacy_cpu;
10991 }
10992 else if (mcpu_cpu_opt == -1)
10993 mcpu_cpu_opt = march_cpu_opt;
10994
10995 if (legacy_fpu != -1)
10996 {
10997 if (mfpu_opt != -1)
10998 as_bad (_("use of old and new-style options to set FPU type"));
10999
11000 mfpu_opt = legacy_fpu;
11001 }
11002 else if (mfpu_opt == -1)
11003 {
4e7fd91e 11004#if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
39c2da32
RE
11005 /* Some environments specify a default FPU. If they don't, infer it
11006 from the processor. */
03b1477f
RE
11007 if (mcpu_fpu_opt != -1)
11008 mfpu_opt = mcpu_fpu_opt;
11009 else
11010 mfpu_opt = march_fpu_opt;
39c2da32
RE
11011#else
11012 mfpu_opt = FPU_DEFAULT;
11013#endif
03b1477f
RE
11014 }
11015
11016 if (mfpu_opt == -1)
11017 {
11018 if (mcpu_cpu_opt == -1)
11019 mfpu_opt = FPU_DEFAULT;
11020 else if (mcpu_cpu_opt & ARM_EXT_V5)
11021 mfpu_opt = FPU_ARCH_VFP_V2;
11022 else
11023 mfpu_opt = FPU_ARCH_FPA;
11024 }
11025
11026 if (mcpu_cpu_opt == -1)
11027 mcpu_cpu_opt = CPU_DEFAULT;
11028
11029 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11030
b99bd4ef 11031 {
7cc69913
NC
11032 unsigned int flags = 0;
11033
11034#if defined OBJ_ELF
11035 flags = meabi_flags;
d507cf36
PB
11036
11037 switch (meabi_flags)
33a392fb 11038 {
d507cf36 11039 case EF_ARM_EABI_UNKNOWN:
7cc69913
NC
11040#endif
11041#if defined OBJ_COFF || defined OBJ_ELF
d507cf36
PB
11042 /* Set the flags in the private structure. */
11043 if (uses_apcs_26) flags |= F_APCS26;
11044 if (support_interwork) flags |= F_INTERWORK;
11045 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11046 if (pic_code) flags |= F_PIC;
11047 if ((cpu_variant & FPU_ANY) == FPU_NONE
11048 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11049 flags |= F_SOFT_FLOAT;
11050
d507cf36
PB
11051 switch (mfloat_abi_opt)
11052 {
11053 case ARM_FLOAT_ABI_SOFT:
11054 case ARM_FLOAT_ABI_SOFTFP:
11055 flags |= F_SOFT_FLOAT;
11056 break;
33a392fb 11057
d507cf36
PB
11058 case ARM_FLOAT_ABI_HARD:
11059 if (flags & F_SOFT_FLOAT)
11060 as_bad (_("hard-float conflicts with specified fpu"));
11061 break;
11062 }
03b1477f 11063
7cc69913
NC
11064 /* Using VFP conventions (even if soft-float). */
11065 if (cpu_variant & FPU_VFP_EXT_NONE)
11066 flags |= F_VFP_FLOAT;
11067#endif
fde78edd 11068#if defined OBJ_ELF
d507cf36
PB
11069 if (cpu_variant & FPU_ARCH_MAVERICK)
11070 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11071 break;
11072
8cb51566 11073 case EF_ARM_EABI_VER4:
d507cf36
PB
11074 /* No additional flags to set. */
11075 break;
11076
11077 default:
11078 abort ();
11079 }
7cc69913
NC
11080#endif
11081#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef
NC
11082 bfd_set_private_flags (stdoutput, flags);
11083
11084 /* We have run out flags in the COFF header to encode the
11085 status of ATPCS support, so instead we create a dummy,
11086 empty, debug section called .arm.atpcs. */
11087 if (atpcs)
11088 {
11089 asection * sec;
11090
11091 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11092
11093 if (sec != NULL)
11094 {
11095 bfd_set_section_flags
11096 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11097 bfd_set_section_size (stdoutput, sec, 0);
11098 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11099 }
11100 }
b99bd4ef 11101#endif
7cc69913 11102 }
b99bd4ef
NC
11103
11104 /* Record the CPU type as well. */
11105 switch (cpu_variant & ARM_CPU_MASK)
11106 {
11107 case ARM_2:
11108 mach = bfd_mach_arm_2;
11109 break;
11110
11111 case ARM_3: /* Also ARM_250. */
11112 mach = bfd_mach_arm_2a;
11113 break;
11114
b89dddec
RE
11115 case ARM_6: /* Also ARM_7. */
11116 mach = bfd_mach_arm_3;
11117 break;
11118
b99bd4ef 11119 default:
5a6c6817 11120 mach = bfd_mach_arm_unknown;
b99bd4ef 11121 break;
b99bd4ef
NC
11122 }
11123
11124 /* Catch special cases. */
e16bb312
NC
11125 if (cpu_variant & ARM_CEXT_IWMMXT)
11126 mach = bfd_mach_arm_iWMMXt;
11127 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11128 mach = bfd_mach_arm_XScale;
fde78edd
NC
11129 else if (cpu_variant & ARM_CEXT_MAVERICK)
11130 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11131 else if (cpu_variant & ARM_EXT_V5E)
11132 mach = bfd_mach_arm_5TE;
11133 else if (cpu_variant & ARM_EXT_V5)
11134 {
b89dddec 11135 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11136 mach = bfd_mach_arm_5T;
11137 else
11138 mach = bfd_mach_arm_5;
11139 }
b89dddec 11140 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11141 {
b89dddec 11142 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11143 mach = bfd_mach_arm_4T;
11144 else
11145 mach = bfd_mach_arm_4;
11146 }
b89dddec 11147 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11148 mach = bfd_mach_arm_3M;
11149
11150 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11151}
11152
11153/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11154 for use in the a.out file, and stores them in the array pointed to by buf.
11155 This knows about the endian-ness of the target machine and does
11156 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11157 2 (short) and 4 (long) Floating numbers are put out as a series of
11158 LITTLENUMS (shorts, here at least). */
11159
11160void
a737bd4d 11161md_number_to_chars (char * buf, valueT val, int n)
b99bd4ef
NC
11162{
11163 if (target_big_endian)
11164 number_to_chars_bigendian (buf, val, n);
11165 else
11166 number_to_chars_littleendian (buf, val, n);
11167}
11168
11169static valueT
a737bd4d 11170md_chars_to_number (char * buf, int n)
b99bd4ef
NC
11171{
11172 valueT result = 0;
11173 unsigned char * where = (unsigned char *) buf;
11174
11175 if (target_big_endian)
11176 {
11177 while (n--)
11178 {
11179 result <<= 8;
11180 result |= (*where++ & 255);
11181 }
11182 }
11183 else
11184 {
11185 while (n--)
11186 {
11187 result <<= 8;
11188 result |= (where[n] & 255);
11189 }
11190 }
11191
11192 return result;
11193}
11194
11195/* Turn a string in input_line_pointer into a floating point constant
11196 of type TYPE, and store the appropriate bytes in *LITP. The number
11197 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11198 returned, or NULL on OK.
11199
11200 Note that fp constants aren't represent in the normal way on the ARM.
11201 In big endian mode, things are as expected. However, in little endian
11202 mode fp constants are big-endian word-wise, and little-endian byte-wise
11203 within the words. For example, (double) 1.1 in big endian mode is
11204 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11205 the byte sequence 99 99 f1 3f 9a 99 99 99.
11206
11207 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11208
11209char *
a737bd4d 11210md_atof (int type, char * litP, int * sizeP)
b99bd4ef
NC
11211{
11212 int prec;
11213 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11214 char *t;
11215 int i;
11216
11217 switch (type)
11218 {
11219 case 'f':
11220 case 'F':
11221 case 's':
11222 case 'S':
11223 prec = 2;
11224 break;
11225
11226 case 'd':
11227 case 'D':
11228 case 'r':
11229 case 'R':
11230 prec = 4;
11231 break;
11232
11233 case 'x':
11234 case 'X':
11235 prec = 6;
11236 break;
11237
11238 case 'p':
11239 case 'P':
11240 prec = 6;
11241 break;
11242
11243 default:
11244 *sizeP = 0;
f03698e6 11245 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11246 }
11247
11248 t = atof_ieee (input_line_pointer, type, words);
11249 if (t)
11250 input_line_pointer = t;
11251 *sizeP = prec * 2;
11252
11253 if (target_big_endian)
11254 {
11255 for (i = 0; i < prec; i++)
11256 {
11257 md_number_to_chars (litP, (valueT) words[i], 2);
11258 litP += 2;
11259 }
11260 }
11261 else
11262 {
bfae80f2
RE
11263 if (cpu_variant & FPU_ARCH_VFP)
11264 for (i = prec - 1; i >= 0; i--)
11265 {
11266 md_number_to_chars (litP, (valueT) words[i], 2);
11267 litP += 2;
11268 }
11269 else
11270 /* For a 4 byte float the order of elements in `words' is 1 0.
11271 For an 8 byte float the order is 1 0 3 2. */
11272 for (i = 0; i < prec; i += 2)
11273 {
11274 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11275 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11276 litP += 4;
11277 }
b99bd4ef
NC
11278 }
11279
11280 return 0;
11281}
11282
11283/* The knowledge of the PC's pipeline offset is built into the insns
11284 themselves. */
11285
11286long
a737bd4d 11287md_pcrel_from (fixS * fixP)
b99bd4ef
NC
11288{
11289 if (fixP->fx_addsy
11290 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11291 && fixP->fx_subsy == NULL)
11292 return 0;
11293
11294 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11295 {
11296 /* PC relative addressing on the Thumb is slightly odd
11297 as the bottom two bits of the PC are forced to zero
11298 for the calculation. */
11299 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11300 }
11301
11302#ifdef TE_WINCE
2d2255b5
KH
11303 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11304 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11305 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11306#else
11307 return fixP->fx_where + fixP->fx_frag->fr_address;
11308#endif
11309}
11310
11311/* Round up a section size to the appropriate boundary. */
11312
11313valueT
a737bd4d
NC
11314md_section_align (segT segment ATTRIBUTE_UNUSED,
11315 valueT size)
b99bd4ef
NC
11316{
11317#ifdef OBJ_ELF
11318 return size;
11319#else
11320 /* Round all sects to multiple of 4. */
11321 return (size + 3) & ~3;
11322#endif
11323}
11324
11325/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11326 Otherwise we have no need to default values of symbols. */
11327
11328symbolS *
a737bd4d 11329md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
b99bd4ef
NC
11330{
11331#ifdef OBJ_ELF
11332 if (name[0] == '_' && name[1] == 'G'
11333 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11334 {
11335 if (!GOT_symbol)
11336 {
11337 if (symbol_find (name))
11338 as_bad ("GOT already in the symbol table");
11339
11340 GOT_symbol = symbol_new (name, undefined_section,
11341 (valueT) 0, & zero_address_frag);
11342 }
11343
11344 return GOT_symbol;
11345 }
11346#endif
11347
11348 return 0;
11349}
11350
94f592af 11351void
a737bd4d
NC
11352md_apply_fix3 (fixS * fixP,
11353 valueT * valP,
11354 segT seg)
b99bd4ef 11355{
94f592af 11356 offsetT value = * valP;
b99bd4ef
NC
11357 offsetT newval;
11358 unsigned int newimm;
11359 unsigned long temp;
11360 int sign;
11361 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11362 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11363
620b81c1 11364 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
b99bd4ef
NC
11365
11366 /* Note whether this will delete the relocation. */
b99bd4ef 11367 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
b99bd4ef
NC
11368 fixP->fx_done = 1;
11369
11370 /* If this symbol is in a different section then we need to leave it for
11371 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11372 so we have to undo it's effects here. */
11373 if (fixP->fx_pcrel)
11374 {
11375 if (fixP->fx_addsy != NULL
11376 && S_IS_DEFINED (fixP->fx_addsy)
11377 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7f266840 11378 value += md_pcrel_from (fixP);
b99bd4ef
NC
11379 }
11380
11381 /* Remember value for emit_reloc. */
11382 fixP->fx_addnumber = value;
11383
11384 switch (fixP->fx_r_type)
11385 {
620b81c1
JB
11386 case BFD_RELOC_NONE:
11387 /* This will need to go in the object file. */
11388 fixP->fx_done = 0;
11389 break;
11390
b99bd4ef 11391 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
11392 /* We claim that this fixup has been processed here,
11393 even if in fact we generate an error because we do
11394 not have a reloc for it, so tc_gen_reloc will reject it. */
11395 fixP->fx_done = 1;
11396
11397 if (fixP->fx_addsy
11398 && ! S_IS_DEFINED (fixP->fx_addsy))
11399 {
11400 as_bad_where (fixP->fx_file, fixP->fx_line,
11401 _("undefined symbol %s used as an immediate value"),
11402 S_GET_NAME (fixP->fx_addsy));
11403 break;
11404 }
11405
b99bd4ef
NC
11406 newimm = validate_immediate (value);
11407 temp = md_chars_to_number (buf, INSN_SIZE);
11408
11409 /* If the instruction will fail, see if we can fix things up by
11410 changing the opcode. */
11411 if (newimm == (unsigned int) FAIL
11412 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11413 {
11414 as_bad_where (fixP->fx_file, fixP->fx_line,
11415 _("invalid constant (%lx) after fixup"),
11416 (unsigned long) value);
11417 break;
11418 }
11419
11420 newimm |= (temp & 0xfffff000);
11421 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11422 break;
11423
11424 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11425 {
11426 unsigned int highpart = 0;
11427 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 11428
b99bd4ef
NC
11429 newimm = validate_immediate (value);
11430 temp = md_chars_to_number (buf, INSN_SIZE);
11431
11432 /* If the instruction will fail, see if we can fix things up by
11433 changing the opcode. */
11434 if (newimm == (unsigned int) FAIL
11435 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11436 {
11437 /* No ? OK - try using two ADD instructions to generate
11438 the value. */
11439 newimm = validate_immediate_twopart (value, & highpart);
11440
11441 /* Yes - then make sure that the second instruction is
11442 also an add. */
11443 if (newimm != (unsigned int) FAIL)
11444 newinsn = temp;
11445 /* Still No ? Try using a negated value. */
11446 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11447 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11448 /* Otherwise - give up. */
11449 else
11450 {
11451 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11452 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 11453 (long) value);
b99bd4ef
NC
11454 break;
11455 }
11456
11457 /* Replace the first operand in the 2nd instruction (which
11458 is the PC) with the destination register. We have
11459 already added in the PC in the first instruction and we
11460 do not want to do it again. */
11461 newinsn &= ~ 0xf0000;
11462 newinsn |= ((newinsn & 0x0f000) << 4);
11463 }
11464
11465 newimm |= (temp & 0xfffff000);
11466 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11467
11468 highpart |= (newinsn & 0xfffff000);
11469 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11470 }
11471 break;
11472
11473 case BFD_RELOC_ARM_OFFSET_IMM:
11474 sign = value >= 0;
11475
11476 if (value < 0)
11477 value = - value;
11478
11479 if (validate_offset_imm (value, 0) == FAIL)
11480 {
11481 as_bad_where (fixP->fx_file, fixP->fx_line,
11482 _("bad immediate value for offset (%ld)"),
11483 (long) value);
11484 break;
11485 }
11486
11487 newval = md_chars_to_number (buf, INSN_SIZE);
11488 newval &= 0xff7ff000;
11489 newval |= value | (sign ? INDEX_UP : 0);
11490 md_number_to_chars (buf, newval, INSN_SIZE);
11491 break;
11492
11493 case BFD_RELOC_ARM_OFFSET_IMM8:
11494 case BFD_RELOC_ARM_HWLITERAL:
11495 sign = value >= 0;
11496
11497 if (value < 0)
11498 value = - value;
11499
11500 if (validate_offset_imm (value, 1) == FAIL)
11501 {
11502 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11503 as_bad_where (fixP->fx_file, fixP->fx_line,
11504 _("invalid literal constant: pool needs to be closer"));
11505 else
11506 as_bad (_("bad immediate value for half-word offset (%ld)"),
11507 (long) value);
11508 break;
11509 }
11510
11511 newval = md_chars_to_number (buf, INSN_SIZE);
11512 newval &= 0xff7ff0f0;
11513 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11514 md_number_to_chars (buf, newval, INSN_SIZE);
11515 break;
11516
11517 case BFD_RELOC_ARM_LITERAL:
11518 sign = value >= 0;
11519
11520 if (value < 0)
11521 value = - value;
11522
11523 if (validate_offset_imm (value, 0) == FAIL)
11524 {
11525 as_bad_where (fixP->fx_file, fixP->fx_line,
11526 _("invalid literal constant: pool needs to be closer"));
11527 break;
11528 }
11529
11530 newval = md_chars_to_number (buf, INSN_SIZE);
11531 newval &= 0xff7ff000;
11532 newval |= value | (sign ? INDEX_UP : 0);
11533 md_number_to_chars (buf, newval, INSN_SIZE);
11534 break;
11535
11536 case BFD_RELOC_ARM_SHIFT_IMM:
11537 newval = md_chars_to_number (buf, INSN_SIZE);
11538 if (((unsigned long) value) > 32
11539 || (value == 32
11540 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11541 {
11542 as_bad_where (fixP->fx_file, fixP->fx_line,
11543 _("shift expression is too large"));
11544 break;
11545 }
11546
11547 if (value == 0)
11548 /* Shifts of zero must be done as lsl. */
11549 newval &= ~0x60;
11550 else if (value == 32)
11551 value = 0;
11552 newval &= 0xfffff07f;
11553 newval |= (value & 0x1f) << 7;
11554 md_number_to_chars (buf, newval, INSN_SIZE);
11555 break;
11556
0dd132b6
NC
11557 case BFD_RELOC_ARM_SMI:
11558 if (((unsigned long) value) > 0xffff)
11559 as_bad_where (fixP->fx_file, fixP->fx_line,
11560 _("invalid smi expression"));
11561 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11562 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11563 md_number_to_chars (buf, newval, INSN_SIZE);
11564 break;
11565
b99bd4ef
NC
11566 case BFD_RELOC_ARM_SWI:
11567 if (arm_data->thumb_mode)
11568 {
11569 if (((unsigned long) value) > 0xff)
11570 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11571 _("invalid swi expression"));
b99bd4ef
NC
11572 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11573 newval |= value;
11574 md_number_to_chars (buf, newval, THUMB_SIZE);
11575 }
11576 else
11577 {
11578 if (((unsigned long) value) > 0x00ffffff)
11579 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11580 _("invalid swi expression"));
b99bd4ef
NC
11581 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11582 newval |= value;
11583 md_number_to_chars (buf, newval, INSN_SIZE);
11584 }
11585 break;
11586
11587 case BFD_RELOC_ARM_MULTI:
11588 if (((unsigned long) value) > 0xffff)
11589 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11590 _("invalid expression in load/store multiple"));
b99bd4ef
NC
11591 newval = value | md_chars_to_number (buf, INSN_SIZE);
11592 md_number_to_chars (buf, newval, INSN_SIZE);
11593 break;
11594
11595 case BFD_RELOC_ARM_PCREL_BRANCH:
11596 newval = md_chars_to_number (buf, INSN_SIZE);
11597
11598 /* Sign-extend a 24-bit number. */
11599#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11600
11601#ifdef OBJ_ELF
7f266840 11602 value = fixP->fx_offset;
b99bd4ef
NC
11603#endif
11604
11605 /* We are going to store value (shifted right by two) in the
11606 instruction, in a 24 bit, signed field. Thus we need to check
11607 that none of the top 8 bits of the shifted value (top 7 bits of
11608 the unshifted, unsigned value) are set, or that they are all set. */
11609 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
11610 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
11611 {
11612#ifdef OBJ_ELF
11613 /* Normally we would be stuck at this point, since we cannot store
11614 the absolute address that is the destination of the branch in the
11615 24 bits of the branch instruction. If however, we happen to know
11616 that the destination of the branch is in the same section as the
2d2255b5 11617 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
11618 ourselves and not have to bother the linker with it.
11619
7f266840
DJ
11620 FIXME: The test for OBJ_ELF is only here because I have not
11621 worked out how to do this for OBJ_COFF. */
11622 if (fixP->fx_addsy != NULL
b99bd4ef
NC
11623 && S_IS_DEFINED (fixP->fx_addsy)
11624 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
11625 {
11626 /* Get pc relative value to go into the branch. */
94f592af 11627 value = * valP;
b99bd4ef
NC
11628
11629 /* Permit a backward branch provided that enough bits
11630 are set. Allow a forwards branch, provided that
11631 enough bits are clear. */
11632 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
11633 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
11634 fixP->fx_done = 1;
11635 }
11636
11637 if (! fixP->fx_done)
11638#endif
11639 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11640 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
11641 }
11642
11643 value >>= 2;
11644 value += SEXT24 (newval);
11645
11646 if ( (value & ~ ((offsetT) 0xffffff)) != 0
11647 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
11648 as_bad_where (fixP->fx_file, fixP->fx_line,
11649 _("out of range branch"));
11650
4e7fd91e
PB
11651 if (seg->use_rela_p && !fixP->fx_done)
11652 {
11653 /* Must unshift the value before storing it in the addend. */
11654 value <<= 2;
11655#ifdef OBJ_ELF
11656 fixP->fx_offset = value;
11657#endif
11658 fixP->fx_addnumber = value;
11659 newval = newval & 0xff000000;
11660 }
11661 else
11662 newval = (value & 0x00ffffff) | (newval & 0xff000000);
b99bd4ef
NC
11663 md_number_to_chars (buf, newval, INSN_SIZE);
11664 break;
11665
11666 case BFD_RELOC_ARM_PCREL_BLX:
11667 {
11668 offsetT hbit;
11669 newval = md_chars_to_number (buf, INSN_SIZE);
11670
11671#ifdef OBJ_ELF
7f266840 11672 value = fixP->fx_offset;
b99bd4ef
NC
11673#endif
11674 hbit = (value >> 1) & 1;
11675 value = (value >> 2) & 0x00ffffff;
11676 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
4e7fd91e
PB
11677
11678 if (seg->use_rela_p && !fixP->fx_done)
11679 {
11680 /* Must sign-extend and unshift the value before storing
11681 it in the addend. */
11682 value = SEXT24 (value);
11683 value = (value << 2) | hbit;
11684#ifdef OBJ_ELF
11685 fixP->fx_offset = value;
11686#endif
11687 fixP->fx_addnumber = value;
11688 newval = newval & 0xfe000000;
11689 }
11690 else
11691 newval = value | (newval & 0xfe000000) | (hbit << 24);
b99bd4ef
NC
11692 md_number_to_chars (buf, newval, INSN_SIZE);
11693 }
11694 break;
11695
11696 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
11697 newval = md_chars_to_number (buf, THUMB_SIZE);
11698 {
11699 addressT diff = (newval & 0xff) << 1;
11700 if (diff & 0x100)
11701 diff |= ~0xff;
11702
11703 value += diff;
11704 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
11705 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11706 _("branch out of range"));
4e7fd91e
PB
11707 if (seg->use_rela_p && !fixP->fx_done)
11708 {
11709#ifdef OBJ_ELF
11710 fixP->fx_offset = value;
11711#endif
11712 fixP->fx_addnumber = value;
11713 newval = newval & 0xff00;
11714 }
11715 else
11716 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
b99bd4ef
NC
11717 }
11718 md_number_to_chars (buf, newval, THUMB_SIZE);
11719 break;
11720
11721 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
11722 newval = md_chars_to_number (buf, THUMB_SIZE);
11723 {
11724 addressT diff = (newval & 0x7ff) << 1;
11725 if (diff & 0x800)
11726 diff |= ~0x7ff;
11727
11728 value += diff;
11729 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
11730 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11731 _("branch out of range"));
4e7fd91e
PB
11732 if (seg->use_rela_p && !fixP->fx_done)
11733 {
11734#ifdef OBJ_ELF
11735 fixP->fx_offset = value;
11736#endif
11737 fixP->fx_addnumber = value;
11738 newval = newval & 0xf800;
11739 }
11740 else
11741 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
b99bd4ef
NC
11742 }
11743 md_number_to_chars (buf, newval, THUMB_SIZE);
11744 break;
11745
11746 case BFD_RELOC_THUMB_PCREL_BLX:
11747 case BFD_RELOC_THUMB_PCREL_BRANCH23:
11748 {
11749 offsetT newval2;
11750 addressT diff;
11751
11752 newval = md_chars_to_number (buf, THUMB_SIZE);
11753 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
11754 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
11755 if (diff & 0x400000)
11756 diff |= ~0x3fffff;
11757#ifdef OBJ_ELF
11758 value = fixP->fx_offset;
11759#endif
11760 value += diff;
c62e1cc3 11761
b99bd4ef
NC
11762 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
11763 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11764 _("branch with link out of range"));
b99bd4ef 11765
b99bd4ef 11766 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
11767 /* For a BLX instruction, make sure that the relocation is rounded up
11768 to a word boundary. This follows the semantics of the instruction
11769 which specifies that bit 1 of the target address will come from bit
11770 1 of the base address. */
4e7fd91e
PB
11771 value = (value + 1) & ~ 1;
11772
11773 if (seg->use_rela_p && !fixP->fx_done)
11774 {
11775#ifdef OBJ_ELF
11776 fixP->fx_offset = value;
11777#endif
11778 fixP->fx_addnumber = value;
11779 newval = newval & 0xf800;
11780 newval2 = newval2 & 0xf800;
11781 }
11782 else
11783 {
11784 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
11785 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
11786 }
b99bd4ef
NC
11787 md_number_to_chars (buf, newval, THUMB_SIZE);
11788 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11789 }
11790 break;
11791
11792 case BFD_RELOC_8:
4e7fd91e
PB
11793 if (seg->use_rela_p && !fixP->fx_done)
11794 break;
b99bd4ef
NC
11795 if (fixP->fx_done || fixP->fx_pcrel)
11796 md_number_to_chars (buf, value, 1);
11797#ifdef OBJ_ELF
7f266840 11798 else
b99bd4ef
NC
11799 {
11800 value = fixP->fx_offset;
11801 md_number_to_chars (buf, value, 1);
11802 }
11803#endif
11804 break;
11805
11806 case BFD_RELOC_16:
4e7fd91e
PB
11807 if (seg->use_rela_p && !fixP->fx_done)
11808 break;
b99bd4ef
NC
11809 if (fixP->fx_done || fixP->fx_pcrel)
11810 md_number_to_chars (buf, value, 2);
11811#ifdef OBJ_ELF
7f266840 11812 else
b99bd4ef
NC
11813 {
11814 value = fixP->fx_offset;
11815 md_number_to_chars (buf, value, 2);
11816 }
11817#endif
11818 break;
11819
11820#ifdef OBJ_ELF
11821 case BFD_RELOC_ARM_GOT32:
11822 case BFD_RELOC_ARM_GOTOFF:
eb043451 11823 case BFD_RELOC_ARM_TARGET2:
4e7fd91e
PB
11824 if (seg->use_rela_p && !fixP->fx_done)
11825 break;
b99bd4ef
NC
11826 md_number_to_chars (buf, 0, 4);
11827 break;
11828#endif
11829
11830 case BFD_RELOC_RVA:
11831 case BFD_RELOC_32:
9c504268 11832 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
11833 case BFD_RELOC_ARM_ROSEGREL32:
11834 case BFD_RELOC_ARM_SBREL32:
eb043451 11835 case BFD_RELOC_32_PCREL:
4e7fd91e
PB
11836 if (seg->use_rela_p && !fixP->fx_done)
11837 break;
b99bd4ef
NC
11838 if (fixP->fx_done || fixP->fx_pcrel)
11839 md_number_to_chars (buf, value, 4);
11840#ifdef OBJ_ELF
7f266840 11841 else
b99bd4ef
NC
11842 {
11843 value = fixP->fx_offset;
11844 md_number_to_chars (buf, value, 4);
11845 }
11846#endif
11847 break;
11848
11849#ifdef OBJ_ELF
eb043451
PB
11850 case BFD_RELOC_ARM_PREL31:
11851 if (fixP->fx_done || fixP->fx_pcrel)
11852 {
11853 newval = md_chars_to_number (buf, 4) & 0x80000000;
11854 if ((value ^ (value >> 1)) & 0x40000000)
11855 {
11856 as_bad_where (fixP->fx_file, fixP->fx_line,
11857 _("rel31 relocation overflow"));
11858 }
11859 newval |= value & 0x7fffffff;
11860 md_number_to_chars (buf, newval, 4);
11861 }
11862 break;
11863
b99bd4ef
NC
11864 case BFD_RELOC_ARM_PLT32:
11865 /* It appears the instruction is fully prepared at this point. */
11866 break;
11867#endif
11868
b99bd4ef
NC
11869 case BFD_RELOC_ARM_CP_OFF_IMM:
11870 sign = value >= 0;
11871 if (value < -1023 || value > 1023 || (value & 3))
11872 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11873 _("illegal value for co-processor offset"));
b99bd4ef
NC
11874 if (value < 0)
11875 value = -value;
11876 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11877 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11878 md_number_to_chars (buf, newval, INSN_SIZE);
11879 break;
11880
e16bb312
NC
11881 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11882 sign = value >= 0;
11883 if (value < -255 || value > 255)
11884 as_bad_where (fixP->fx_file, fixP->fx_line,
11885 _("Illegal value for co-processor offset"));
11886 if (value < 0)
11887 value = -value;
11888 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11889 newval |= value | (sign ? INDEX_UP : 0);
11890 md_number_to_chars (buf, newval , INSN_SIZE);
11891 break;
11892
b99bd4ef
NC
11893 case BFD_RELOC_ARM_THUMB_OFFSET:
11894 newval = md_chars_to_number (buf, THUMB_SIZE);
11895 /* Exactly what ranges, and where the offset is inserted depends
11896 on the type of instruction, we can establish this from the
11897 top 4 bits. */
11898 switch (newval >> 12)
11899 {
11900 case 4: /* PC load. */
11901 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11902 forced to zero for these loads, so we will need to round
11903 up the offset if the instruction address is not word
11904 aligned (since the final address produced must be, and
11905 we can only describe word-aligned immediate offsets). */
11906
11907 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11908 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11909 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
11910 (unsigned int) (fixP->fx_frag->fr_address
11911 + fixP->fx_where + value));
11912
11913 if ((value + 2) & ~0x3fe)
11914 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11915 _("invalid offset, value too big (0x%08lX)"),
11916 (long) value);
b99bd4ef
NC
11917
11918 /* Round up, since pc will be rounded down. */
11919 newval |= (value + 2) >> 2;
11920 break;
11921
11922 case 9: /* SP load/store. */
11923 if (value & ~0x3fc)
11924 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11925 _("invalid offset, value too big (0x%08lX)"),
11926 (long) value);
b99bd4ef
NC
11927 newval |= value >> 2;
11928 break;
11929
11930 case 6: /* Word load/store. */
11931 if (value & ~0x7c)
11932 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11933 _("invalid offset, value too big (0x%08lX)"),
11934 (long) value);
b99bd4ef
NC
11935 newval |= value << 4; /* 6 - 2. */
11936 break;
11937
11938 case 7: /* Byte load/store. */
11939 if (value & ~0x1f)
11940 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11941 _("invalid offset, value too big (0x%08lX)"),
11942 (long) value);
b99bd4ef
NC
11943 newval |= value << 6;
11944 break;
11945
11946 case 8: /* Halfword load/store. */
11947 if (value & ~0x3e)
11948 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
11949 _("invalid offset, value too big (0x%08lX)"),
11950 (long) value);
b99bd4ef
NC
11951 newval |= value << 5; /* 6 - 1. */
11952 break;
11953
11954 default:
11955 as_bad_where (fixP->fx_file, fixP->fx_line,
11956 "Unable to process relocation for thumb opcode: %lx",
11957 (unsigned long) newval);
11958 break;
11959 }
11960 md_number_to_chars (buf, newval, THUMB_SIZE);
11961 break;
11962
11963 case BFD_RELOC_ARM_THUMB_ADD:
11964 /* This is a complicated relocation, since we use it for all of
11965 the following immediate relocations:
11966
11967 3bit ADD/SUB
11968 8bit ADD/SUB
11969 9bit ADD/SUB SP word-aligned
11970 10bit ADD PC/SP word-aligned
11971
11972 The type of instruction being processed is encoded in the
11973 instruction field:
11974
11975 0x8000 SUB
11976 0x00F0 Rd
11977 0x000F Rs
11978 */
11979 newval = md_chars_to_number (buf, THUMB_SIZE);
11980 {
11981 int rd = (newval >> 4) & 0xf;
11982 int rs = newval & 0xf;
11983 int subtract = newval & 0x8000;
11984
11985 if (rd == REG_SP)
11986 {
11987 if (value & ~0x1fc)
11988 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11989 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
11990 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11991 newval |= value >> 2;
11992 }
11993 else if (rs == REG_PC || rs == REG_SP)
11994 {
11995 if (subtract ||
11996 value & ~0x3fc)
11997 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11998 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
11999 (unsigned long) value);
12000 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12001 newval |= rd << 8;
12002 newval |= value >> 2;
12003 }
12004 else if (rs == rd)
12005 {
12006 if (value & ~0xff)
12007 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12008 _("invalid 8bit immediate"));
b99bd4ef
NC
12009 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12010 newval |= (rd << 8) | value;
12011 }
12012 else
12013 {
12014 if (value & ~0x7)
12015 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12016 _("invalid 3bit immediate"));
b99bd4ef
NC
12017 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12018 newval |= rd | (rs << 3) | (value << 6);
12019 }
12020 }
12021 md_number_to_chars (buf, newval, THUMB_SIZE);
12022 break;
12023
12024 case BFD_RELOC_ARM_THUMB_IMM:
12025 newval = md_chars_to_number (buf, THUMB_SIZE);
12026 switch (newval >> 11)
12027 {
12028 case 0x04: /* 8bit immediate MOV. */
12029 case 0x05: /* 8bit immediate CMP. */
12030 if (value < 0 || value > 255)
12031 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12032 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12033 (long) value);
12034 newval |= value;
12035 break;
12036
12037 default:
12038 abort ();
12039 }
12040 md_number_to_chars (buf, newval, THUMB_SIZE);
12041 break;
12042
12043 case BFD_RELOC_ARM_THUMB_SHIFT:
12044 /* 5bit shift value (0..31). */
12045 if (value < 0 || value > 31)
12046 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12047 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12048 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12049 newval |= value << 6;
12050 md_number_to_chars (buf, newval, THUMB_SIZE);
12051 break;
12052
12053 case BFD_RELOC_VTABLE_INHERIT:
12054 case BFD_RELOC_VTABLE_ENTRY:
12055 fixP->fx_done = 0;
94f592af 12056 return;
b99bd4ef 12057
620b81c1 12058 case BFD_RELOC_UNUSED:
b99bd4ef
NC
12059 default:
12060 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12061 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12062 }
b99bd4ef
NC
12063}
12064
12065/* Translate internal representation of relocation info to BFD target
12066 format. */
12067
12068arelent *
a737bd4d
NC
12069tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12070 fixS * fixp)
b99bd4ef
NC
12071{
12072 arelent * reloc;
12073 bfd_reloc_code_real_type code;
12074
a737bd4d 12075 reloc = xmalloc (sizeof (arelent));
b99bd4ef 12076
a737bd4d 12077 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
b99bd4ef
NC
12078 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12079 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12080
12081 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12082#ifndef OBJ_ELF
12083 if (fixp->fx_pcrel == 0)
12084 reloc->addend = fixp->fx_offset;
12085 else
12086 reloc->addend = fixp->fx_offset = reloc->address;
12087#else /* OBJ_ELF */
12088 reloc->addend = fixp->fx_offset;
12089#endif
12090
12091 switch (fixp->fx_r_type)
12092 {
12093 case BFD_RELOC_8:
12094 if (fixp->fx_pcrel)
12095 {
12096 code = BFD_RELOC_8_PCREL;
12097 break;
12098 }
12099
12100 case BFD_RELOC_16:
12101 if (fixp->fx_pcrel)
12102 {
12103 code = BFD_RELOC_16_PCREL;
12104 break;
12105 }
12106
12107 case BFD_RELOC_32:
12108 if (fixp->fx_pcrel)
12109 {
12110 code = BFD_RELOC_32_PCREL;
12111 break;
12112 }
12113
620b81c1 12114 case BFD_RELOC_NONE:
b99bd4ef
NC
12115 case BFD_RELOC_ARM_PCREL_BRANCH:
12116 case BFD_RELOC_ARM_PCREL_BLX:
12117 case BFD_RELOC_RVA:
12118 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12119 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12120 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12121 case BFD_RELOC_THUMB_PCREL_BLX:
12122 case BFD_RELOC_VTABLE_ENTRY:
12123 case BFD_RELOC_VTABLE_INHERIT:
12124 code = fixp->fx_r_type;
12125 break;
12126
12127 case BFD_RELOC_ARM_LITERAL:
12128 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12129 /* If this is called then the a literal has
12130 been referenced across a section boundary. */
b99bd4ef 12131 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12132 _("literal referenced across section boundary"));
b99bd4ef
NC
12133 return NULL;
12134
12135#ifdef OBJ_ELF
12136 case BFD_RELOC_ARM_GOT32:
12137 case BFD_RELOC_ARM_GOTOFF:
12138 case BFD_RELOC_ARM_PLT32:
9c504268 12139 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12140 case BFD_RELOC_ARM_ROSEGREL32:
12141 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12142 case BFD_RELOC_ARM_PREL31:
12143 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12144 code = fixp->fx_r_type;
12145 break;
12146#endif
12147
12148 case BFD_RELOC_ARM_IMMEDIATE:
12149 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12150 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12151 return NULL;
12152
12153 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12154 as_bad_where (fixp->fx_file, fixp->fx_line,
12155 _("ADRL used for a symbol not defined in the same file"));
12156 return NULL;
12157
12158 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12159 if (fixp->fx_addsy != NULL
12160 && !S_IS_DEFINED (fixp->fx_addsy)
12161 && S_IS_LOCAL (fixp->fx_addsy))
12162 {
12163 as_bad_where (fixp->fx_file, fixp->fx_line,
12164 _("undefined local label `%s'"),
12165 S_GET_NAME (fixp->fx_addsy));
12166 return NULL;
12167 }
12168
b99bd4ef 12169 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12170 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12171 return NULL;
12172
12173 default:
12174 {
12175 char * type;
12176
12177 switch (fixp->fx_r_type)
12178 {
620b81c1 12179 case BFD_RELOC_NONE: type = "NONE"; break;
b99bd4ef
NC
12180 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12181 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
0dd132b6 12182 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
b99bd4ef
NC
12183 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12184 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12185 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12186 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12187 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12188 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12189 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12190 default: type = _("<unknown>"); break;
12191 }
12192 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12193 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12194 type);
12195 return NULL;
12196 }
12197 }
12198
12199#ifdef OBJ_ELF
8df7094c 12200 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12201 && GOT_symbol
12202 && fixp->fx_addsy == GOT_symbol)
12203 {
12204 code = BFD_RELOC_ARM_GOTPC;
12205 reloc->addend = fixp->fx_offset = reloc->address;
12206 }
12207#endif
12208
12209 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12210
12211 if (reloc->howto == NULL)
12212 {
12213 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12214 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12215 bfd_get_reloc_code_name (code));
12216 return NULL;
12217 }
12218
12219 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12220 vtable entry to be used in the relocation's section offset. */
12221 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12222 reloc->address = fixp->fx_offset;
12223
12224 return reloc;
12225}
12226
12227int
a737bd4d
NC
12228md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12229 segT segtype ATTRIBUTE_UNUSED)
b99bd4ef
NC
12230{
12231 as_fatal (_("md_estimate_size_before_relax\n"));
12232 return 1;
12233}
12234
a737bd4d
NC
12235/* We need to be able to fix up arbitrary expressions in some statements.
12236 This is so that we can handle symbols that are an arbitrary distance from
12237 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12238 which returns part of an address in a form which will be valid for
12239 a data instruction. We do this by pushing the expression into a symbol
12240 in the expr_section, and creating a fix for that. */
12241
12242static void
12243fix_new_arm (fragS * frag,
12244 int where,
12245 short int size,
12246 expressionS * exp,
12247 int pc_rel,
12248 int reloc)
12249{
12250 fixS * new_fix;
12251 arm_fix_data * arm_data;
12252
12253 switch (exp->X_op)
12254 {
12255 case O_constant:
12256 case O_symbol:
12257 case O_add:
12258 case O_subtract:
12259 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12260 break;
12261
12262 default:
12263 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12264 pc_rel, reloc);
12265 break;
12266 }
12267
12268 /* Mark whether the fix is to a THUMB instruction, or an ARM
12269 instruction. */
12270 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12271 new_fix->tc_fix_data = (PTR) arm_data;
12272 arm_data->thumb_mode = thumb_mode;
12273}
12274
b99bd4ef 12275static void
a737bd4d 12276output_inst (const char * str)
b99bd4ef
NC
12277{
12278 char * to = NULL;
12279
12280 if (inst.error)
12281 {
f03698e6 12282 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12283 return;
12284 }
12285
12286 to = frag_more (inst.size);
12287
12288 if (thumb_mode && (inst.size > THUMB_SIZE))
12289 {
12290 assert (inst.size == (2 * THUMB_SIZE));
12291 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12292 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12293 }
12294 else if (inst.size > INSN_SIZE)
12295 {
12296 assert (inst.size == (2 * INSN_SIZE));
12297 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12298 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12299 }
12300 else
12301 md_number_to_chars (to, inst.instruction, inst.size);
12302
620b81c1 12303 if (inst.reloc.type != BFD_RELOC_UNUSED)
b99bd4ef
NC
12304 fix_new_arm (frag_now, to - frag_now->fr_literal,
12305 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12306 inst.reloc.type);
12307
12308#ifdef OBJ_ELF
12309 dwarf2_emit_insn (inst.size);
12310#endif
12311}
12312
12313void
a737bd4d 12314md_assemble (char * str)
b99bd4ef 12315{
6c43fab6
RE
12316 char c;
12317 char *p;
12318 char *start;
b99bd4ef 12319
b99bd4ef
NC
12320 /* Align the previous label if needed. */
12321 if (last_label_seen != NULL)
12322 {
12323 symbol_set_frag (last_label_seen, frag_now);
12324 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12325 S_SET_SEGMENT (last_label_seen, now_seg);
12326 }
12327
12328 memset (&inst, '\0', sizeof (inst));
620b81c1 12329 inst.reloc.type = BFD_RELOC_UNUSED;
b99bd4ef
NC
12330
12331 skip_whitespace (str);
12332
12333 /* Scan up to the end of the op-code, which must end in white space or
12334 end of string. */
12335 for (start = p = str; *p != '\0'; p++)
12336 if (*p == ' ')
12337 break;
12338
12339 if (p == str)
12340 {
f03698e6 12341 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12342 return;
12343 }
12344
12345 if (thumb_mode)
12346 {
05d2d07e 12347 const struct thumb_opcode * opcode;
b99bd4ef
NC
12348
12349 c = *p;
12350 *p = '\0';
05d2d07e 12351 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12352 *p = c;
12353
12354 if (opcode)
12355 {
12356 /* Check that this instruction is supported for this CPU. */
90e4755a 12357 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12358 {
f03698e6 12359 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12360 return;
12361 }
12362
6057a28f 12363 mapping_state (MAP_THUMB);
b99bd4ef
NC
12364 inst.instruction = opcode->value;
12365 inst.size = opcode->size;
a737bd4d 12366 opcode->parms (p);
f03698e6 12367 output_inst (str);
b99bd4ef
NC
12368 return;
12369 }
12370 }
12371 else
12372 {
05d2d07e 12373 const struct asm_opcode * opcode;
b99bd4ef 12374
90e4755a
RE
12375 c = *p;
12376 *p = '\0';
6c43fab6 12377 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12378 *p = c;
b99bd4ef 12379
90e4755a 12380 if (opcode)
b99bd4ef 12381 {
90e4755a
RE
12382 /* Check that this instruction is supported for this CPU. */
12383 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12384 {
f03698e6 12385 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12386 return;
12387 }
12388
6057a28f 12389 mapping_state (MAP_ARM);
90e4755a
RE
12390 inst.instruction = opcode->value;
12391 inst.size = INSN_SIZE;
a737bd4d 12392 opcode->parms (p);
f03698e6 12393 output_inst (str);
90e4755a 12394 return;
b99bd4ef
NC
12395 }
12396 }
12397
12398 /* It wasn't an instruction, but it might be a register alias of the form
12399 alias .req reg. */
6c43fab6
RE
12400 if (create_register_alias (str, p))
12401 return;
b99bd4ef 12402
b99bd4ef
NC
12403 as_bad (_("bad instruction `%s'"), start);
12404}
12405
12406/* md_parse_option
12407 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12408 See if it's a processor-specific option.
03b1477f
RE
12409
12410 This routine is somewhat complicated by the need for backwards
12411 compatibility (since older releases of gcc can't be changed).
12412 The new options try to make the interface as compatible as
12413 possible with GCC.
12414
12415 New options (supported) are:
12416
12417 -mcpu=<cpu name> Assemble for selected processor
12418 -march=<architecture name> Assemble for selected architecture
12419 -mfpu=<fpu architecture> Assemble for selected FPU.
12420 -EB/-mbig-endian Big-endian
12421 -EL/-mlittle-endian Little-endian
12422 -k Generate PIC code
12423 -mthumb Start in Thumb mode
12424 -mthumb-interwork Code supports ARM/Thumb interworking
12425
3d0c9500 12426 For now we will also provide support for:
03b1477f
RE
12427
12428 -mapcs-32 32-bit Program counter
12429 -mapcs-26 26-bit Program counter
12430 -macps-float Floats passed in FP registers
12431 -mapcs-reentrant Reentrant code
12432 -matpcs
12433 (sometime these will probably be replaced with -mapcs=<list of options>
12434 and -matpcs=<list of options>)
12435
12436 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
12437 Cpu variants, the arm part is optional:
12438 -m[arm]1 Currently not supported.
12439 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12440 -m[arm]3 Arm 3 processor
12441 -m[arm]6[xx], Arm 6 processors
12442 -m[arm]7[xx][t][[d]m] Arm 7 processors
12443 -m[arm]8[10] Arm 8 processors
12444 -m[arm]9[20][tdmi] Arm 9 processors
12445 -mstrongarm[110[0]] StrongARM processors
12446 -mxscale XScale processors
12447 -m[arm]v[2345[t[e]]] Arm architectures
12448 -mall All (except the ARM1)
12449 FP variants:
12450 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12451 -mfpe-old (No float load/store multiples)
bfae80f2
RE
12452 -mvfpxd VFP Single precision
12453 -mvfp All VFP
b99bd4ef 12454 -mno-fpu Disable all floating point instructions
b99bd4ef 12455
03b1477f
RE
12456 The following CPU names are recognized:
12457 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12458 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12459 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12460 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12461 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12462 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12463 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12464
12465 */
12466
5a38dc70 12467const char * md_shortopts = "m:k";
03b1477f 12468
b99bd4ef
NC
12469#ifdef ARM_BI_ENDIAN
12470#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 12471#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12472#else
21f0f23a
RE
12473#if TARGET_BYTES_BIG_ENDIAN
12474#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
12475#else
12476#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12477#endif
ce058b6c 12478#endif
03b1477f
RE
12479
12480struct option md_longopts[] =
12481{
12482#ifdef OPTION_EB
12483 {"EB", no_argument, NULL, OPTION_EB},
12484#endif
12485#ifdef OPTION_EL
12486 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
12487#endif
12488 {NULL, no_argument, NULL, 0}
12489};
12490
12491size_t md_longopts_size = sizeof (md_longopts);
12492
03b1477f 12493struct arm_option_table
b99bd4ef 12494{
03b1477f
RE
12495 char *option; /* Option name to match. */
12496 char *help; /* Help information. */
12497 int *var; /* Variable to change. */
12498 int value; /* What to change it to. */
12499 char *deprecated; /* If non-null, print this message. */
12500};
b99bd4ef 12501
cc8a6dd0 12502struct arm_option_table arm_opts[] =
03b1477f
RE
12503{
12504 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12505 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12506 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12507 &support_interwork, 1, NULL},
03b1477f
RE
12508 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12509 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12510 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12511 1, NULL},
12512 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12513 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12514 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12515 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12516 NULL},
12517
12518 /* These are recognized by the assembler, but have no affect on code. */
12519 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12520 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12521
12522 /* DON'T add any new processors to this list -- we want the whole list
12523 to go away... Add them to the processors table instead. */
12524 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12525 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12526 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12527 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12528 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12529 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12530 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12531 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12532 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12533 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12534 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12535 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12536 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12537 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12538 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12539 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12540 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12541 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12542 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12543 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12544 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12545 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12546 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12547 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12548 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12549 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12550 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12551 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12552 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12553 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12554 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12555 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12556 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12557 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12558 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12559 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12560 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12561 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12562 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12563 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12564 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12565 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12566 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12567 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12568 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12569 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12570 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12571 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12572 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12573 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12574 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12575 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12576 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12577 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12578 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12579 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12580 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12581 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12582 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12583 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12584 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12585 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12586 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12587 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12588 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12589 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12590 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12591 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12592 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12593 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12594 N_("use -mcpu=strongarm110")},
12595 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12596 N_("use -mcpu=strongarm1100")},
12597 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12598 N_("use -mcpu=strongarm1110")},
12599 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 12600 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
12601 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12602
12603 /* Architecture variants -- don't add any more to this list either. */
12604 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12605 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12606 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12607 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
12608 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12609 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
12610 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12611 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
12612 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12613 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
12614 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12615 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
12616 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12617 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
12618 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12619 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
12620 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12621 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
12622
12623 /* Floating point variants -- don't add any more to this list either. */
12624 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
12625 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
12626 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
12627 {"mno-fpu", NULL, &legacy_fpu, 0,
12628 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
12629
12630 {NULL, NULL, NULL, 0, NULL}
12631};
21f0f23a 12632
03b1477f
RE
12633struct arm_cpu_option_table
12634{
12635 char *name;
12636 int value;
12637 /* For some CPUs we assume an FPU unless the user explicitly sets
12638 -mfpu=... */
12639 int default_fpu;
12640};
12641
12642/* This list should, at a minimum, contain all the cpu names
12643 recognized by GCC. */
12644static struct arm_cpu_option_table arm_cpus[] =
12645{
12646 {"all", ARM_ANY, FPU_ARCH_FPA},
12647 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
12648 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
12649 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
12650 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
12651 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
12652 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
12653 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
12654 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
12655 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
12656 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
12657 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12658 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
12659 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
12660 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
12661 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
12662 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
12663 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
12664 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
12665 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
12666 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12667 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
12668 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12669 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12670 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
12671 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
12672 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
12673 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
12674 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12675 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 12676 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
12677 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
12678 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
12679 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
12680 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
12681 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
12682 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
12683 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
12684 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
12685 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
12686 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12687 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12688 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12689 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
12690 /* For V5 or later processors we default to using VFP; but the user
12691 should really set the FPU type explicitly. */
12692 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12693 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 12694 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 12695 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 12696 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
12697 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12698 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12699 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
12700 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12701 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12702 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12703 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
12704 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
12705 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
5dc1606f
PB
12706 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
12707 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
09d92015 12708 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 12709 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 12710 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 12711 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
0dd132b6
NC
12712 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
12713 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
12714 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
12715 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
03b1477f
RE
12716 /* ??? XSCALE is really an architecture. */
12717 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 12718 /* ??? iwmmxt is not a processor. */
e16bb312 12719 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
12720 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
12721 /* Maverick */
33a392fb 12722 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
12723 {NULL, 0, 0}
12724};
cc8a6dd0 12725
03b1477f
RE
12726struct arm_arch_option_table
12727{
12728 char *name;
12729 int value;
12730 int default_fpu;
12731};
12732
12733/* This list should, at a minimum, contain all the architecture names
12734 recognized by GCC. */
12735static struct arm_arch_option_table arm_archs[] =
12736{
12737 {"all", ARM_ANY, FPU_ARCH_FPA},
12738 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
12739 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
12740 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
12741 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
12742 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
12743 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
12744 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
12745 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
12746 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
12747 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
12748 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
12749 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
12750 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
12751 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
12752 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 12753 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 12754 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 12755 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
0dd132b6
NC
12756 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
12757 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
12758 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
03b1477f 12759 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 12760 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
12761 {NULL, 0, 0}
12762};
12763
12764/* ISA extensions in the co-processor space. */
12765struct arm_arch_extension_table
12766{
12767 char *name;
12768 int value;
12769};
12770
12771static struct arm_arch_extension_table arm_extensions[] =
12772{
12773 {"maverick", ARM_CEXT_MAVERICK},
12774 {"xscale", ARM_CEXT_XSCALE},
e16bb312 12775 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
12776 {NULL, 0}
12777};
b99bd4ef 12778
03b1477f
RE
12779struct arm_fpu_option_table
12780{
12781 char *name;
12782 int value;
12783};
12784
12785/* This list should, at a minimum, contain all the fpu names
12786 recognized by GCC. */
12787static struct arm_fpu_option_table arm_fpus[] =
12788{
12789 {"softfpa", FPU_NONE},
12790 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
12791 {"fpe2", FPU_ARCH_FPE},
12792 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
12793 {"fpa", FPU_ARCH_FPA},
12794 {"fpa10", FPU_ARCH_FPA},
12795 {"fpa11", FPU_ARCH_FPA},
12796 {"arm7500fe", FPU_ARCH_FPA},
12797 {"softvfp", FPU_ARCH_VFP},
12798 {"softvfp+vfp", FPU_ARCH_VFP_V2},
12799 {"vfp", FPU_ARCH_VFP_V2},
12800 {"vfp9", FPU_ARCH_VFP_V2},
12801 {"vfp10", FPU_ARCH_VFP_V2},
12802 {"vfp10-r0", FPU_ARCH_VFP_V1},
12803 {"vfpxd", FPU_ARCH_VFP_V1xD},
12804 {"arm1020t", FPU_ARCH_VFP_V1},
12805 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 12806 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 12807 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
12808 {"maverick", FPU_ARCH_MAVERICK},
12809 {NULL, 0}
12810};
12811
12812struct arm_float_abi_option_table
12813{
12814 char *name;
12815 int value;
12816};
12817
12818static struct arm_float_abi_option_table arm_float_abis[] =
12819{
12820 {"hard", ARM_FLOAT_ABI_HARD},
12821 {"softfp", ARM_FLOAT_ABI_SOFTFP},
12822 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
12823 {NULL, 0}
12824};
12825
d507cf36
PB
12826struct arm_eabi_option_table
12827{
12828 char *name;
12829 unsigned int value;
12830};
12831
7cc69913 12832#ifdef OBJ_ELF
8cb51566 12833/* We only know how to output GNU and ver 4 (AAELF) formats. */
d507cf36
PB
12834static struct arm_eabi_option_table arm_eabis[] =
12835{
12836 {"gnu", EF_ARM_EABI_UNKNOWN},
8cb51566 12837 {"4", EF_ARM_EABI_VER4},
d507cf36
PB
12838 {NULL, 0}
12839};
7cc69913 12840#endif
d507cf36 12841
03b1477f
RE
12842struct arm_long_option_table
12843{
a737bd4d
NC
12844 char * option; /* Substring to match. */
12845 char * help; /* Help information. */
12846 int (* func) (char * subopt); /* Function to decode sub-option. */
12847 char * deprecated; /* If non-null, print this message. */
03b1477f
RE
12848};
12849
12850static int
a737bd4d 12851arm_parse_extension (char * str, int * opt_p)
03b1477f
RE
12852{
12853 while (str != NULL && *str != 0)
12854 {
a737bd4d
NC
12855 struct arm_arch_extension_table * opt;
12856 char * ext;
03b1477f
RE
12857 int optlen;
12858
12859 if (*str != '+')
b99bd4ef 12860 {
03b1477f
RE
12861 as_bad (_("invalid architectural extension"));
12862 return 0;
12863 }
b99bd4ef 12864
03b1477f
RE
12865 str++;
12866 ext = strchr (str, '+');
b99bd4ef 12867
03b1477f
RE
12868 if (ext != NULL)
12869 optlen = ext - str;
12870 else
12871 optlen = strlen (str);
b99bd4ef 12872
03b1477f
RE
12873 if (optlen == 0)
12874 {
12875 as_bad (_("missing architectural extension"));
12876 return 0;
12877 }
b99bd4ef 12878
03b1477f
RE
12879 for (opt = arm_extensions; opt->name != NULL; opt++)
12880 if (strncmp (opt->name, str, optlen) == 0)
12881 {
12882 *opt_p |= opt->value;
12883 break;
12884 }
bfae80f2 12885
03b1477f
RE
12886 if (opt->name == NULL)
12887 {
12888 as_bad (_("unknown architectural extnsion `%s'"), str);
12889 return 0;
12890 }
b99bd4ef 12891
03b1477f
RE
12892 str = ext;
12893 };
b99bd4ef 12894
03b1477f
RE
12895 return 1;
12896}
b99bd4ef 12897
03b1477f 12898static int
a737bd4d 12899arm_parse_cpu (char * str)
03b1477f 12900{
a737bd4d
NC
12901 struct arm_cpu_option_table * opt;
12902 char * ext = strchr (str, '+');
03b1477f 12903 int optlen;
b99bd4ef 12904
03b1477f
RE
12905 if (ext != NULL)
12906 optlen = ext - str;
12907 else
12908 optlen = strlen (str);
b99bd4ef 12909
03b1477f
RE
12910 if (optlen == 0)
12911 {
12912 as_bad (_("missing cpu name `%s'"), str);
12913 return 0;
12914 }
b99bd4ef 12915
03b1477f
RE
12916 for (opt = arm_cpus; opt->name != NULL; opt++)
12917 if (strncmp (opt->name, str, optlen) == 0)
12918 {
12919 mcpu_cpu_opt = opt->value;
12920 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 12921
03b1477f
RE
12922 if (ext != NULL)
12923 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 12924
03b1477f
RE
12925 return 1;
12926 }
b99bd4ef 12927
03b1477f
RE
12928 as_bad (_("unknown cpu `%s'"), str);
12929 return 0;
12930}
b99bd4ef 12931
03b1477f 12932static int
a737bd4d 12933arm_parse_arch (char * str)
03b1477f
RE
12934{
12935 struct arm_arch_option_table *opt;
12936 char *ext = strchr (str, '+');
12937 int optlen;
b99bd4ef 12938
03b1477f
RE
12939 if (ext != NULL)
12940 optlen = ext - str;
12941 else
12942 optlen = strlen (str);
b99bd4ef 12943
03b1477f
RE
12944 if (optlen == 0)
12945 {
12946 as_bad (_("missing architecture name `%s'"), str);
12947 return 0;
12948 }
b99bd4ef 12949
b99bd4ef 12950
03b1477f 12951 for (opt = arm_archs; opt->name != NULL; opt++)
a737bd4d 12952 if (streq (opt->name, str))
03b1477f
RE
12953 {
12954 march_cpu_opt = opt->value;
12955 march_fpu_opt = opt->default_fpu;
b99bd4ef 12956
03b1477f
RE
12957 if (ext != NULL)
12958 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 12959
03b1477f
RE
12960 return 1;
12961 }
b99bd4ef 12962
03b1477f
RE
12963 as_bad (_("unknown architecture `%s'\n"), str);
12964 return 0;
12965}
12966
12967static int
a737bd4d 12968arm_parse_fpu (char * str)
03b1477f 12969{
a737bd4d 12970 struct arm_fpu_option_table * opt;
b99bd4ef 12971
03b1477f 12972 for (opt = arm_fpus; opt->name != NULL; opt++)
a737bd4d 12973 if (streq (opt->name, str))
03b1477f
RE
12974 {
12975 mfpu_opt = opt->value;
12976 return 1;
12977 }
b99bd4ef 12978
03b1477f
RE
12979 as_bad (_("unknown floating point format `%s'\n"), str);
12980 return 0;
12981}
b99bd4ef 12982
33a392fb 12983static int
a737bd4d 12984arm_parse_float_abi (char * str)
33a392fb 12985{
a737bd4d 12986 struct arm_float_abi_option_table * opt;
33a392fb
PB
12987
12988 for (opt = arm_float_abis; opt->name != NULL; opt++)
a737bd4d 12989 if (streq (opt->name, str))
33a392fb
PB
12990 {
12991 mfloat_abi_opt = opt->value;
12992 return 1;
12993 }
12994
12995 as_bad (_("unknown floating point abi `%s'\n"), str);
12996 return 0;
12997}
12998
7cc69913 12999#ifdef OBJ_ELF
d507cf36 13000static int
a737bd4d 13001arm_parse_eabi (char * str)
d507cf36
PB
13002{
13003 struct arm_eabi_option_table *opt;
13004
13005 for (opt = arm_eabis; opt->name != NULL; opt++)
a737bd4d 13006 if (streq (opt->name, str))
d507cf36
PB
13007 {
13008 meabi_flags = opt->value;
13009 return 1;
13010 }
13011 as_bad (_("unknown EABI `%s'\n"), str);
13012 return 0;
13013}
7cc69913 13014#endif
d507cf36 13015
03b1477f
RE
13016struct arm_long_option_table arm_long_opts[] =
13017{
13018 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13019 arm_parse_cpu, NULL},
13020 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13021 arm_parse_arch, NULL},
13022 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13023 arm_parse_fpu, NULL},
33a392fb
PB
13024 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13025 arm_parse_float_abi, NULL},
7cc69913 13026#ifdef OBJ_ELF
d507cf36
PB
13027 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13028 arm_parse_eabi, NULL},
7cc69913 13029#endif
03b1477f
RE
13030 {NULL, NULL, 0, NULL}
13031};
b99bd4ef 13032
03b1477f 13033int
a737bd4d 13034md_parse_option (int c, char * arg)
03b1477f
RE
13035{
13036 struct arm_option_table *opt;
13037 struct arm_long_option_table *lopt;
b99bd4ef 13038
03b1477f
RE
13039 switch (c)
13040 {
13041#ifdef OPTION_EB
13042 case OPTION_EB:
13043 target_big_endian = 1;
b99bd4ef 13044 break;
03b1477f 13045#endif
b99bd4ef 13046
03b1477f
RE
13047#ifdef OPTION_EL
13048 case OPTION_EL:
13049 target_big_endian = 0;
b99bd4ef
NC
13050 break;
13051#endif
13052
03b1477f 13053 case 'a':
cc8a6dd0 13054 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13055 ones. */
13056 return 0;
13057
b99bd4ef 13058 default:
03b1477f
RE
13059 for (opt = arm_opts; opt->option != NULL; opt++)
13060 {
13061 if (c == opt->option[0]
13062 && ((arg == NULL && opt->option[1] == 0)
a737bd4d 13063 || streq (arg, opt->option + 1)))
03b1477f
RE
13064 {
13065#if WARN_DEPRECATED
13066 /* If the option is deprecated, tell the user. */
13067 if (opt->deprecated != NULL)
13068 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13069 arg ? arg : "", _(opt->deprecated));
13070#endif
13071
13072 if (opt->var != NULL)
13073 *opt->var = opt->value;
13074
13075 return 1;
13076 }
13077 }
13078
13079 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13080 {
cc8a6dd0 13081 /* These options are expected to have an argument. */
03b1477f
RE
13082 if (c == lopt->option[0]
13083 && arg != NULL
cc8a6dd0 13084 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13085 strlen (lopt->option + 1)) == 0)
13086 {
13087#if WARN_DEPRECATED
13088 /* If the option is deprecated, tell the user. */
13089 if (lopt->deprecated != NULL)
13090 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13091 _(lopt->deprecated));
13092#endif
13093
13094 /* Call the sup-option parser. */
a737bd4d 13095 return lopt->func (arg + strlen (lopt->option) - 1);
03b1477f
RE
13096 }
13097 }
13098
b99bd4ef
NC
13099 return 0;
13100 }
13101
13102 return 1;
13103}
13104
13105void
a737bd4d 13106md_show_usage (FILE * fp)
b99bd4ef 13107{
03b1477f
RE
13108 struct arm_option_table *opt;
13109 struct arm_long_option_table *lopt;
13110
13111 fprintf (fp, _(" ARM-specific assembler options:\n"));
13112
13113 for (opt = arm_opts; opt->option != NULL; opt++)
13114 if (opt->help != NULL)
13115 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13116
13117 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13118 if (lopt->help != NULL)
13119 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13120
13121#ifdef OPTION_EB
b99bd4ef 13122 fprintf (fp, _("\
03b1477f 13123 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13124#endif
03b1477f
RE
13125
13126#ifdef OPTION_EL
b99bd4ef 13127 fprintf (fp, _("\
03b1477f 13128 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13129#endif
13130}
13131
b99bd4ef
NC
13132/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13133
13134void
a737bd4d
NC
13135cons_fix_new_arm (fragS * frag,
13136 int where,
13137 int size,
13138 expressionS * exp)
b99bd4ef
NC
13139{
13140 bfd_reloc_code_real_type type;
13141 int pcrel = 0;
13142
13143 /* Pick a reloc.
13144 FIXME: @@ Should look at CPU word size. */
13145 switch (size)
13146 {
13147 case 1:
13148 type = BFD_RELOC_8;
13149 break;
13150 case 2:
13151 type = BFD_RELOC_16;
13152 break;
13153 case 4:
13154 default:
13155 type = BFD_RELOC_32;
13156 break;
13157 case 8:
13158 type = BFD_RELOC_64;
13159 break;
13160 }
13161
13162 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13163}
13164
13165/* A good place to do this, although this was probably not intended
13166 for this kind of use. We need to dump the literal pool before
13167 references are made to a null symbol pointer. */
13168
13169void
a737bd4d 13170arm_cleanup (void)
b99bd4ef 13171{
3d0c9500 13172 literal_pool * pool;
b99bd4ef 13173
3d0c9500
NC
13174 for (pool = list_of_pools; pool; pool = pool->next)
13175 {
13176 /* Put it at the end of the relevent section. */
13177 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13178#ifdef OBJ_ELF
13179 arm_elf_change_section ();
13180#endif
3d0c9500
NC
13181 s_ltorg (0);
13182 }
b99bd4ef
NC
13183}
13184
13185void
a737bd4d 13186arm_start_line_hook (void)
b99bd4ef
NC
13187{
13188 last_label_seen = NULL;
13189}
13190
13191void
a737bd4d 13192arm_frob_label (symbolS * sym)
b99bd4ef
NC
13193{
13194 last_label_seen = sym;
13195
13196 ARM_SET_THUMB (sym, thumb_mode);
13197
13198#if defined OBJ_COFF || defined OBJ_ELF
13199 ARM_SET_INTERWORK (sym, support_interwork);
13200#endif
13201
13202 /* Note - do not allow local symbols (.Lxxx) to be labeled
13203 as Thumb functions. This is because these labels, whilst
13204 they exist inside Thumb code, are not the entry points for
13205 possible ARM->Thumb calls. Also, these labels can be used
13206 as part of a computed goto or switch statement. eg gcc
13207 can generate code that looks like this:
13208
13209 ldr r2, [pc, .Laaa]
13210 lsl r3, r3, #2
13211 ldr r2, [r3, r2]
13212 mov pc, r2
cc8a6dd0 13213
b99bd4ef
NC
13214 .Lbbb: .word .Lxxx
13215 .Lccc: .word .Lyyy
13216 ..etc...
13217 .Laaa: .word Lbbb
13218
13219 The first instruction loads the address of the jump table.
13220 The second instruction converts a table index into a byte offset.
13221 The third instruction gets the jump address out of the table.
13222 The fourth instruction performs the jump.
cc8a6dd0 13223
b99bd4ef
NC
13224 If the address stored at .Laaa is that of a symbol which has the
13225 Thumb_Func bit set, then the linker will arrange for this address
13226 to have the bottom bit set, which in turn would mean that the
13227 address computation performed by the third instruction would end
13228 up with the bottom bit set. Since the ARM is capable of unaligned
13229 word loads, the instruction would then load the incorrect address
13230 out of the jump table, and chaos would ensue. */
13231 if (label_is_thumb_function_name
13232 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13233 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13234 {
13235 /* When the address of a Thumb function is taken the bottom
13236 bit of that address should be set. This will allow
13237 interworking between Arm and Thumb functions to work
13238 correctly. */
13239
13240 THUMB_SET_FUNC (sym, 1);
13241
b34976b6 13242 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13243 }
13244}
13245
13246/* Adjust the symbol table. This marks Thumb symbols as distinct from
13247 ARM ones. */
13248
13249void
a737bd4d 13250arm_adjust_symtab (void)
b99bd4ef
NC
13251{
13252#ifdef OBJ_COFF
13253 symbolS * sym;
13254
13255 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13256 {
13257 if (ARM_IS_THUMB (sym))
13258 {
13259 if (THUMB_IS_FUNC (sym))
13260 {
13261 /* Mark the symbol as a Thumb function. */
13262 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13263 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13264 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13265
13266 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13267 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13268 else
13269 as_bad (_("%s: unexpected function type: %d"),
13270 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13271 }
cc8a6dd0 13272 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13273 {
13274 case C_EXT:
13275 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13276 break;
13277 case C_STAT:
13278 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13279 break;
13280 case C_LABEL:
13281 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13282 break;
13283 default:
13284 /* Do nothing. */
13285 break;
13286 }
13287 }
13288
13289 if (ARM_IS_INTERWORK (sym))
13290 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13291 }
13292#endif
13293#ifdef OBJ_ELF
13294 symbolS * sym;
13295 char bind;
13296
13297 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13298 {
13299 if (ARM_IS_THUMB (sym))
13300 {
13301 elf_symbol_type * elf_sym;
13302
13303 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13304 bind = ELF_ST_BIND (elf_sym);
13305
13306 /* If it's a .thumb_func, declare it as so,
13307 otherwise tag label as .code 16. */
13308 if (THUMB_IS_FUNC (sym))
13309 elf_sym->internal_elf_sym.st_info =
13310 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13311 else
13312 elf_sym->internal_elf_sym.st_info =
13313 ELF_ST_INFO (bind, STT_ARM_16BIT);
13314 }
13315 }
13316#endif
13317}
13318
13319int
a737bd4d 13320arm_data_in_code (void)
b99bd4ef
NC
13321{
13322 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13323 {
13324 *input_line_pointer = '/';
13325 input_line_pointer += 5;
13326 *input_line_pointer = 0;
13327 return 1;
13328 }
13329
13330 return 0;
13331}
13332
13333char *
a737bd4d 13334arm_canonicalize_symbol_name (char * name)
b99bd4ef
NC
13335{
13336 int len;
13337
13338 if (thumb_mode && (len = strlen (name)) > 5
13339 && streq (name + len - 5, "/data"))
13340 *(name + len - 5) = 0;
13341
13342 return name;
13343}
13344
bfc866a6 13345#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13346void
a737bd4d 13347arm_validate_fix (fixS * fixP)
b99bd4ef
NC
13348{
13349 /* If the destination of the branch is a defined symbol which does not have
13350 the THUMB_FUNC attribute, then we must be calling a function which has
13351 the (interfacearm) attribute. We look for the Thumb entry point to that
13352 function and change the branch to refer to that function instead. */
13353 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13354 && fixP->fx_addsy != NULL
13355 && S_IS_DEFINED (fixP->fx_addsy)
13356 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13357 {
13358 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13359 }
b99bd4ef 13360}
bfc866a6 13361#endif
b99bd4ef 13362
114424c6 13363int
a737bd4d 13364arm_force_relocation (struct fix * fixp)
114424c6
AM
13365{
13366#if defined (OBJ_COFF) && defined (TE_PE)
13367 if (fixp->fx_r_type == BFD_RELOC_RVA)
13368 return 1;
13369#endif
13370#ifdef OBJ_ELF
ae6063d4 13371 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13372 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13373 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13374 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13375 return 1;
13376#endif
13377
13378 /* Resolve these relocations even if the symbol is extern or weak. */
13379 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13380 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13381 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13382 return 0;
13383
ae6063d4 13384 return generic_force_reloc (fixp);
114424c6
AM
13385}
13386
b99bd4ef
NC
13387#ifdef OBJ_COFF
13388/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13389 local labels from being added to the output symbol table when they
13390 are used with the ADRL pseudo op. The ADRL relocation should always
13391 be resolved before the binbary is emitted, so it is safe to say that
13392 it is adjustable. */
13393
b34976b6 13394bfd_boolean
a737bd4d 13395arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13396{
13397 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13398 return 1;
13399 return 0;
13400}
13401#endif
114424c6 13402
b99bd4ef
NC
13403#ifdef OBJ_ELF
13404/* Relocations against Thumb function names must be left unadjusted,
13405 so that the linker can use this information to correctly set the
13406 bottom bit of their addresses. The MIPS version of this function
13407 also prevents relocations that are mips-16 specific, but I do not
13408 know why it does this.
13409
13410 FIXME:
13411 There is one other problem that ought to be addressed here, but
13412 which currently is not: Taking the address of a label (rather
13413 than a function) and then later jumping to that address. Such
13414 addresses also ought to have their bottom bit set (assuming that
13415 they reside in Thumb code), but at the moment they will not. */
13416
b34976b6 13417bfd_boolean
a737bd4d 13418arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13419{
13420 if (fixP->fx_addsy == NULL)
13421 return 1;
13422
b99bd4ef
NC
13423 if (THUMB_IS_FUNC (fixP->fx_addsy)
13424 && fixP->fx_subsy == NULL)
13425 return 0;
13426
13427 /* We need the symbol name for the VTABLE entries. */
13428 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13429 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13430 return 0;
13431
a161fe53
AM
13432 /* Don't allow symbols to be discarded on GOT related relocs. */
13433 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13434 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
13435 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13436 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
13437 return 0;
13438
b99bd4ef
NC
13439 return 1;
13440}
13441
13442const char *
a737bd4d 13443elf32_arm_target_format (void)
b99bd4ef 13444{
e5a52504
MM
13445#ifdef TE_SYMBIAN
13446 return (target_big_endian
13447 ? "elf32-bigarm-symbian"
13448 : "elf32-littlearm-symbian");
4e7fd91e
PB
13449#elif defined (TE_VXWORKS)
13450 return (target_big_endian
13451 ? "elf32-bigarm-vxworks"
13452 : "elf32-littlearm-vxworks");
a737bd4d 13453#else
b99bd4ef 13454 if (target_big_endian)
7f266840 13455 return "elf32-bigarm";
b99bd4ef 13456 else
7f266840 13457 return "elf32-littlearm";
e5a52504 13458#endif
b99bd4ef
NC
13459}
13460
13461void
a737bd4d
NC
13462armelf_frob_symbol (symbolS * symp,
13463 int * puntp)
b99bd4ef
NC
13464{
13465 elf_frob_symbol (symp, puntp);
13466}
13467
b99bd4ef 13468static void
a737bd4d 13469s_arm_elf_cons (int nbytes)
b99bd4ef
NC
13470{
13471 expressionS exp;
13472
13473#ifdef md_flush_pending_output
13474 md_flush_pending_output ();
13475#endif
13476
13477 if (is_it_end_of_statement ())
13478 {
13479 demand_empty_rest_of_line ();
13480 return;
13481 }
13482
13483#ifdef md_cons_align
13484 md_cons_align (nbytes);
13485#endif
13486
6057a28f 13487 mapping_state (MAP_DATA);
b99bd4ef
NC
13488 do
13489 {
13490 bfd_reloc_code_real_type reloc;
13491
13492 expression (& exp);
13493
13494 if (exp.X_op == O_symbol
13495 && * input_line_pointer == '('
13496 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13497 {
13498 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13499 int size = bfd_get_reloc_size (howto);
13500
13501 if (size > nbytes)
13502 as_bad ("%s relocations do not fit in %d bytes",
13503 howto->name, nbytes);
13504 else
13505 {
a737bd4d 13506 char *p = frag_more ((int) nbytes);
b99bd4ef
NC
13507 int offset = nbytes - size;
13508
13509 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13510 &exp, 0, reloc);
13511 }
13512 }
13513 else
13514 emit_expr (&exp, (unsigned int) nbytes);
13515 }
13516 while (*input_line_pointer++ == ',');
13517
13518 /* Put terminator back into stream. */
13519 input_line_pointer --;
13520 demand_empty_rest_of_line ();
13521}
13522
eb043451
PB
13523
13524/* Parse a .rel31 directive. */
13525
13526static void
13527s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13528{
13529 expressionS exp;
13530 char *p;
13531 valueT highbit;
a737bd4d 13532
eb043451
PB
13533 SKIP_WHITESPACE ();
13534
13535 highbit = 0;
13536 if (*input_line_pointer == '1')
13537 highbit = 0x80000000;
13538 else if (*input_line_pointer != '0')
13539 as_bad (_("expected 0 or 1"));
13540
13541 input_line_pointer++;
13542 SKIP_WHITESPACE ();
13543 if (*input_line_pointer != ',')
13544 as_bad (_("missing comma"));
13545 input_line_pointer++;
13546
13547#ifdef md_flush_pending_output
13548 md_flush_pending_output ();
13549#endif
13550
13551#ifdef md_cons_align
13552 md_cons_align (4);
13553#endif
13554
13555 mapping_state (MAP_DATA);
13556
13557 expression (&exp);
13558
13559 p = frag_more (4);
13560 md_number_to_chars (p, highbit, 4);
13561 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13562 BFD_RELOC_ARM_PREL31);
13563
13564 demand_empty_rest_of_line ();
13565}
7ed4c4c5
NC
13566\f
13567/* Code to deal with unwinding tables. */
13568
13569static void add_unwind_adjustsp (offsetT);
13570
13571/* Switch to section NAME and create section if necessary. It's
13572 rather ugly that we have to manipulate input_line_pointer but I
13573 don't see any other way to accomplish the same thing without
13574 changing obj-elf.c (which may be the Right Thing, in the end).
13575 Copied from tc-ia64.c. */
13576
13577static void
13578set_section (char *name)
13579{
13580 char *saved_input_line_pointer;
13581
13582 saved_input_line_pointer = input_line_pointer;
13583 input_line_pointer = name;
13584 obj_elf_section (0);
13585 input_line_pointer = saved_input_line_pointer;
13586}
13587
13588/* Cenerate and deferred unwind frame offset. */
13589
13590static void
13591flush_pending_unwind (void)
13592{
13593 offsetT offset;
13594
13595 offset = unwind.pending_offset;
13596 unwind.pending_offset = 0;
13597 if (offset != 0)
13598 add_unwind_adjustsp (offset);
13599}
13600
13601/* Add an opcode to this list for this function. Two-byte opcodes should
13602 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
13603 order. */
13604
13605static void
13606add_unwind_opcode (valueT op, int length)
13607{
13608 /* Add any deferred stack adjustment. */
13609 if (unwind.pending_offset)
13610 flush_pending_unwind ();
13611
13612 unwind.sp_restored = 0;
13613
13614 if (unwind.opcode_count + length > unwind.opcode_alloc)
13615 {
13616 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
13617 if (unwind.opcodes)
13618 unwind.opcodes = xrealloc (unwind.opcodes,
13619 unwind.opcode_alloc);
13620 else
13621 unwind.opcodes = xmalloc (unwind.opcode_alloc);
13622 }
13623 while (length > 0)
13624 {
13625 length--;
13626 unwind.opcodes[unwind.opcode_count] = op & 0xff;
13627 op >>= 8;
13628 unwind.opcode_count++;
13629 }
13630}
13631
13632/* Add unwind opcodes to adjust the stack pointer. */
13633
13634static void
13635add_unwind_adjustsp (offsetT offset)
13636{
13637 valueT op;
13638
13639 if (offset > 0x200)
13640 {
13641 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
13642 char bytes[5];
13643 int n;
13644 valueT o;
13645
13646 /* Long form: 0xb2, uleb128. */
13647 /* This might not fit in a word so add the individual bytes,
13648 remembering the list is built in reverse order. */
13649 o = (valueT) ((offset - 0x204) >> 2);
13650 if (o == 0)
13651 add_unwind_opcode (0, 1);
13652
13653 /* Calculate the uleb128 encoding of the offset. */
13654 n = 0;
13655 while (o)
13656 {
13657 bytes[n] = o & 0x7f;
13658 o >>= 7;
13659 if (o)
13660 bytes[n] |= 0x80;
13661 n++;
13662 }
13663 /* Add the insn. */
13664 for (; n; n--)
13665 add_unwind_opcode (bytes[n - 1], 1);
13666 add_unwind_opcode (0xb2, 1);
13667 }
13668 else if (offset > 0x100)
13669 {
13670 /* Two short opcodes. */
13671 add_unwind_opcode (0x3f, 1);
13672 op = (offset - 0x104) >> 2;
13673 add_unwind_opcode (op, 1);
13674 }
13675 else if (offset > 0)
13676 {
13677 /* Short opcode. */
13678 op = (offset - 4) >> 2;
13679 add_unwind_opcode (op, 1);
13680 }
13681 else if (offset < 0)
13682 {
13683 offset = -offset;
13684 while (offset > 0x100)
13685 {
13686 add_unwind_opcode (0x7f, 1);
13687 offset -= 0x100;
13688 }
13689 op = ((offset - 4) >> 2) | 0x40;
13690 add_unwind_opcode (op, 1);
13691 }
13692}
13693
13694/* Finish the list of unwind opcodes for this function. */
13695static void
13696finish_unwind_opcodes (void)
13697{
13698 valueT op;
13699
13700 if (unwind.fp_used)
13701 {
13702 /* Adjust sp as neccessary. */
13703 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
13704 flush_pending_unwind ();
13705
13706 /* After restoring sp from the frame pointer. */
13707 op = 0x90 | unwind.fp_reg;
13708 add_unwind_opcode (op, 1);
13709 }
13710 else
13711 flush_pending_unwind ();
13712}
13713
13714
13715/* Start an exception table entry. If idx is nonzero this is an index table
13716 entry. */
13717
13718static void
13719start_unwind_section (const segT text_seg, int idx)
13720{
13721 const char * text_name;
13722 const char * prefix;
13723 const char * prefix_once;
13724 size_t prefix_len;
13725 size_t text_len;
13726 char * sec_name;
13727 size_t sec_name_len;
13728
13729 if (idx)
13730 {
13731 prefix = ELF_STRING_ARM_unwind;
13732 prefix_once = ELF_STRING_ARM_unwind_once;
13733 }
13734 else
13735 {
13736 prefix = ELF_STRING_ARM_unwind_info;
13737 prefix_once = ELF_STRING_ARM_unwind_info_once;
13738 }
13739
13740 text_name = segment_name (text_seg);
13741 if (streq (text_name, ".text"))
13742 text_name = "";
13743
13744 if (strncmp (text_name, ".gnu.linkonce.t.",
13745 strlen (".gnu.linkonce.t.")) == 0)
13746 {
13747 prefix = prefix_once;
13748 text_name += strlen (".gnu.linkonce.t.");
13749 }
13750
13751 prefix_len = strlen (prefix);
13752 text_len = strlen (text_name);
13753 sec_name_len = prefix_len + text_len;
13754 sec_name = alloca (sec_name_len + 1);
13755 memcpy (sec_name, prefix, prefix_len);
13756 memcpy (sec_name + prefix_len, text_name, text_len);
13757 sec_name[prefix_len + text_len] = '\0';
13758
13759 /* Handle COMDAT group. */
13760 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
13761 {
13762 char *section;
13763 size_t len, group_name_len;
13764 const char *group_name = elf_group_name (text_seg);
13765
13766 if (group_name == NULL)
13767 {
13768 as_bad ("Group section `%s' has no group signature",
13769 segment_name (text_seg));
13770 ignore_rest_of_line ();
13771 return;
13772 }
13773 /* We have to construct a fake section directive. */
13774 group_name_len = strlen (group_name);
13775 if (idx)
13776 prefix_len = 13;
13777 else
13778 prefix_len = 16;
13779
13780 len = (sec_name_len
13781 + prefix_len /* ,"aG",%sectiontype, */
13782 + group_name_len /* ,group_name */
13783 + 7); /* ,comdat */
13784
13785 section = alloca (len + 1);
13786 memcpy (section, sec_name, sec_name_len);
13787 if (idx)
13788 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
13789 else
13790 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
13791 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
13792 memcpy (section + len - 7, ",comdat", 7);
13793 section [len] = '\0';
13794 set_section (section);
13795 }
13796 else
13797 {
13798 set_section (sec_name);
13799 bfd_set_section_flags (stdoutput, now_seg,
13800 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
13801 }
13802
13803 /* Set the setion link for index tables. */
13804 if (idx)
13805 elf_linked_to_section (now_seg) = text_seg;
13806}
13807
13808
13809/* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
13810 personality routine data. Returns zero, or the index table value for
13811 and inline entry. */
13812
13813static valueT
13814create_unwind_entry (int have_data)
13815{
13816 int size;
13817 addressT where;
13818 unsigned char *ptr;
13819 /* The current word of data. */
13820 valueT data;
13821 /* The number of bytes left in this word. */
13822 int n;
13823
13824 finish_unwind_opcodes ();
13825
13826 /* Remember the current text section. */
13827 unwind.saved_seg = now_seg;
13828 unwind.saved_subseg = now_subseg;
13829
13830 start_unwind_section (now_seg, 0);
13831
13832 if (unwind.personality_routine == NULL)
13833 {
13834 if (unwind.personality_index == -2)
13835 {
13836 if (have_data)
13837 as_bad (_("handerdata in cantunwind frame"));
13838 return 1; /* EXIDX_CANTUNWIND. */
13839 }
13840
13841 /* Use a default personality routine if none is specified. */
13842 if (unwind.personality_index == -1)
13843 {
13844 if (unwind.opcode_count > 3)
13845 unwind.personality_index = 1;
13846 else
13847 unwind.personality_index = 0;
13848 }
13849
13850 /* Space for the personality routine entry. */
13851 if (unwind.personality_index == 0)
13852 {
13853 if (unwind.opcode_count > 3)
13854 as_bad (_("too many unwind opcodes for personality routine 0"));
13855
13856 if (!have_data)
13857 {
13858 /* All the data is inline in the index table. */
13859 data = 0x80;
13860 n = 3;
13861 while (unwind.opcode_count > 0)
13862 {
13863 unwind.opcode_count--;
13864 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13865 n--;
13866 }
13867
13868 /* Pad with "finish" opcodes. */
13869 while (n--)
13870 data = (data << 8) | 0xb0;
13871
13872 return data;
13873 }
13874 size = 0;
13875 }
13876 else
13877 /* We get two opcodes "free" in the first word. */
13878 size = unwind.opcode_count - 2;
13879 }
13880 else
13881 /* An extra byte is required for the opcode count. */
13882 size = unwind.opcode_count + 1;
13883
13884 size = (size + 3) >> 2;
13885 if (size > 0xff)
13886 as_bad (_("too many unwind opcodes"));
13887
13888 frag_align (2, 0, 0);
13889 record_alignment (now_seg, 2);
13890 unwind.table_entry = expr_build_dot ();
13891
13892 /* Allocate the table entry. */
13893 ptr = frag_more ((size << 2) + 4);
13894 where = frag_now_fix () - ((size << 2) + 4);
13895
13896 switch (unwind.personality_index)
13897 {
13898 case -1:
13899 /* ??? Should this be a PLT generating relocation? */
13900 /* Custom personality routine. */
13901 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
13902 BFD_RELOC_ARM_PREL31);
620b81c1
JB
13903
13904 /* Indicate dependency to linker. */
13905 {
13906 char *name = "__aeabi_unwind_cpp_pr0";
13907 symbolS *pr = symbol_find_or_make (name);
13908 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
13909 }
13910
7ed4c4c5
NC
13911 where += 4;
13912 ptr += 4;
13913
13914 /* Set the first byte to the number of additional words. */
13915 data = size - 1;
13916 n = 3;
13917 break;
13918
13919 /* ABI defined personality routines. */
7ed4c4c5
NC
13920 case 0:
13921 /* Three opcodes bytes are packed into the first word. */
13922 data = 0x80;
13923 n = 3;
620b81c1 13924 goto emit_reloc;
7ed4c4c5
NC
13925
13926 case 1:
13927 case 2:
13928 /* The size and first two opcode bytes go in the first word. */
13929 data = ((0x80 + unwind.personality_index) << 8) | size;
13930 n = 2;
620b81c1
JB
13931 goto emit_reloc;
13932
13933 emit_reloc:
13934 {
13935 /* Indicate dependency to linker. */
13936 char *name[] = { "__aeabi_unwind_cpp_pr0",
13937 "__aeabi_unwind_cpp_pr1",
13938 "__aeabi_unwind_cpp_pr2" };
13939 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
13940 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
13941 }
7ed4c4c5
NC
13942 break;
13943
13944 default:
13945 /* Should never happen. */
13946 abort ();
13947 }
13948
13949 /* Pack the opcodes into words (MSB first), reversing the list at the same
13950 time. */
13951 while (unwind.opcode_count > 0)
13952 {
13953 if (n == 0)
13954 {
13955 md_number_to_chars (ptr, data, 4);
13956 ptr += 4;
13957 n = 4;
13958 data = 0;
13959 }
13960 unwind.opcode_count--;
13961 n--;
13962 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
13963 }
13964
13965 /* Finish off the last word. */
13966 if (n < 4)
13967 {
13968 /* Pad with "finish" opcodes. */
13969 while (n--)
13970 data = (data << 8) | 0xb0;
13971
13972 md_number_to_chars (ptr, data, 4);
13973 }
13974
13975 if (!have_data)
13976 {
13977 /* Add an empty descriptor if there is no user-specified data. */
13978 ptr = frag_more (4);
13979 md_number_to_chars (ptr, 0, 4);
13980 }
13981
13982 return 0;
13983}
13984
13985
13986/* Parse an unwind_fnstart directive. Simply records the current location. */
13987
13988static void
13989s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
13990{
13991 demand_empty_rest_of_line ();
13992 /* Mark the start of the function. */
13993 unwind.proc_start = expr_build_dot ();
13994
13995 /* Reset the rest of the unwind info. */
13996 unwind.opcode_count = 0;
13997 unwind.table_entry = NULL;
13998 unwind.personality_routine = NULL;
13999 unwind.personality_index = -1;
14000 unwind.frame_size = 0;
14001 unwind.fp_offset = 0;
14002 unwind.fp_reg = 13;
14003 unwind.fp_used = 0;
14004 unwind.sp_restored = 0;
14005}
14006
14007
14008/* Parse a handlerdata directive. Creates the exception handling table entry
14009 for the function. */
14010
14011static void
14012s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14013{
14014 demand_empty_rest_of_line ();
14015 if (unwind.table_entry)
14016 as_bad (_("dupicate .handlerdata directive"));
14017
14018 create_unwind_entry (1);
14019}
14020
14021/* Parse an unwind_fnend directive. Generates the index table entry. */
14022
14023static void
14024s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14025{
14026 long where;
14027 unsigned char *ptr;
14028 valueT val;
14029
14030 demand_empty_rest_of_line ();
14031
14032 /* Add eh table entry. */
14033 if (unwind.table_entry == NULL)
14034 val = create_unwind_entry (0);
14035 else
14036 val = 0;
14037
14038 /* Add index table entry. This is two words. */
14039 start_unwind_section (unwind.saved_seg, 1);
14040 frag_align (2, 0, 0);
14041 record_alignment (now_seg, 2);
14042
14043 ptr = frag_more (8);
14044 where = frag_now_fix () - 8;
14045
14046 /* Self relative offset of the function start. */
14047 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
be1b2b4b 14048 BFD_RELOC_ARM_PREL31);
7ed4c4c5
NC
14049
14050 if (val)
14051 /* Inline exception table entry. */
14052 md_number_to_chars (ptr + 4, val, 4);
14053 else
14054 /* Self relative offset of the table entry. */
14055 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14056 BFD_RELOC_ARM_PREL31);
14057
14058 /* Restore the original section. */
14059 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14060}
14061
14062
14063/* Parse an unwind_cantunwind directive. */
14064
14065static void
14066s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14067{
14068 demand_empty_rest_of_line ();
14069 if (unwind.personality_routine || unwind.personality_index != -1)
14070 as_bad (_("personality routine specified for cantunwind frame"));
14071
14072 unwind.personality_index = -2;
14073}
14074
14075
14076/* Parse a personalityindex directive. */
14077
14078static void
14079s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14080{
14081 expressionS exp;
14082
14083 if (unwind.personality_routine || unwind.personality_index != -1)
14084 as_bad (_("duplicate .personalityindex directive"));
14085
14086 SKIP_WHITESPACE ();
14087
14088 expression (&exp);
14089
14090 if (exp.X_op != O_constant
14091 || exp.X_add_number < 0 || exp.X_add_number > 15)
14092 {
14093 as_bad (_("bad personality routine number"));
14094 ignore_rest_of_line ();
14095 return;
14096 }
14097
14098 unwind.personality_index = exp.X_add_number;
14099
14100 demand_empty_rest_of_line ();
14101}
14102
14103
14104/* Parse a personality directive. */
14105
14106static void
14107s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14108{
14109 char *name, *p, c;
14110
14111 if (unwind.personality_routine || unwind.personality_index != -1)
14112 as_bad (_("duplicate .personality directive"));
14113
14114 SKIP_WHITESPACE ();
14115 name = input_line_pointer;
14116 c = get_symbol_end ();
14117 p = input_line_pointer;
14118 unwind.personality_routine = symbol_find_or_make (name);
14119 *p = c;
14120 SKIP_WHITESPACE ();
14121 demand_empty_rest_of_line ();
14122}
14123
14124
14125/* Parse a directive saving core registers. */
14126
14127static void
14128s_arm_unwind_save_core (void)
14129{
14130 valueT op;
14131 long range;
14132 int n;
14133
14134 SKIP_WHITESPACE ();
14135 range = reg_list (&input_line_pointer);
14136 if (range == FAIL)
14137 {
14138 as_bad (_("expected register list"));
14139 ignore_rest_of_line ();
14140 return;
14141 }
14142
14143 demand_empty_rest_of_line ();
14144
14145 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14146 into .unwind_save {..., sp...}. We aren't bothered about the value of
14147 ip because it is clobbered by calls. */
14148 if (unwind.sp_restored && unwind.fp_reg == 12
14149 && (range & 0x3000) == 0x1000)
14150 {
14151 unwind.opcode_count--;
14152 unwind.sp_restored = 0;
14153 range = (range | 0x2000) & ~0x1000;
14154 unwind.pending_offset = 0;
14155 }
14156
14157 /* See if we can use the short opcodes. These pop a block of upto 8
14158 registers starting with r4, plus maybe r14. */
14159 for (n = 0; n < 8; n++)
14160 {
14161 /* Break at the first non-saved register. */
14162 if ((range & (1 << (n + 4))) == 0)
14163 break;
14164 }
14165 /* See if there are any other bits set. */
14166 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14167 {
14168 /* Use the long form. */
14169 op = 0x8000 | ((range >> 4) & 0xfff);
14170 add_unwind_opcode (op, 2);
14171 }
14172 else
14173 {
14174 /* Use the short form. */
14175 if (range & 0x4000)
14176 op = 0xa8; /* Pop r14. */
14177 else
14178 op = 0xa0; /* Do not pop r14. */
14179 op |= (n - 1);
14180 add_unwind_opcode (op, 1);
14181 }
14182
14183 /* Pop r0-r3. */
14184 if (range & 0xf)
14185 {
14186 op = 0xb100 | (range & 0xf);
14187 add_unwind_opcode (op, 2);
14188 }
14189
14190 /* Record the number of bytes pushed. */
14191 for (n = 0; n < 16; n++)
14192 {
14193 if (range & (1 << n))
14194 unwind.frame_size += 4;
14195 }
14196}
14197
14198
14199/* Parse a directive saving FPA registers. */
14200
14201static void
14202s_arm_unwind_save_fpa (int reg)
14203{
14204 expressionS exp;
14205 int num_regs;
14206 valueT op;
14207
14208 /* Get Number of registers to transfer. */
14209 if (skip_past_comma (&input_line_pointer) != FAIL)
14210 expression (&exp);
14211 else
14212 exp.X_op = O_illegal;
14213
14214 if (exp.X_op != O_constant)
14215 {
14216 as_bad (_("expected , <constant>"));
14217 ignore_rest_of_line ();
14218 return;
14219 }
14220
14221 num_regs = exp.X_add_number;
14222
14223 if (num_regs < 1 || num_regs > 4)
14224 {
14225 as_bad (_("number of registers must be in the range [1:4]"));
14226 ignore_rest_of_line ();
14227 return;
14228 }
14229
14230 demand_empty_rest_of_line ();
14231
14232 if (reg == 4)
14233 {
14234 /* Short form. */
14235 op = 0xb4 | (num_regs - 1);
14236 add_unwind_opcode (op, 1);
14237 }
14238 else
14239 {
14240 /* Long form. */
14241 op = 0xc800 | (reg << 4) | (num_regs - 1);
14242 add_unwind_opcode (op, 2);
14243 }
14244 unwind.frame_size += num_regs * 12;
14245}
14246
14247
14248/* Parse a directive saving VFP registers. */
14249
14250static void
14251s_arm_unwind_save_vfp (void)
14252{
14253 int count;
14254 int reg;
14255 valueT op;
14256
14257 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14258 if (count == FAIL)
14259 {
14260 as_bad (_("expected register list"));
14261 ignore_rest_of_line ();
14262 return;
14263 }
14264
14265 demand_empty_rest_of_line ();
14266
14267 if (reg == 8)
14268 {
14269 /* Short form. */
14270 op = 0xb8 | (count - 1);
14271 add_unwind_opcode (op, 1);
14272 }
14273 else
14274 {
14275 /* Long form. */
14276 op = 0xb300 | (reg << 4) | (count - 1);
14277 add_unwind_opcode (op, 2);
14278 }
14279 unwind.frame_size += count * 8 + 4;
14280}
14281
14282
14283/* Parse a directive saving iWMMXt registers. */
14284
14285static void
14286s_arm_unwind_save_wmmx (void)
14287{
14288 int reg;
14289 int hi_reg;
14290 int i;
14291 unsigned wcg_mask;
14292 unsigned wr_mask;
14293 valueT op;
14294
14295 if (*input_line_pointer == '{')
14296 input_line_pointer++;
14297
14298 wcg_mask = 0;
14299 wr_mask = 0;
14300 do
14301 {
14302 reg = arm_reg_parse (&input_line_pointer,
14303 all_reg_maps[REG_TYPE_IWMMXT].htab);
14304
14305 if (wr_register (reg))
14306 {
14307 i = reg & ~WR_PREFIX;
14308 if (wr_mask >> i)
14309 as_tsktsk (_("register list not in ascending order"));
14310 wr_mask |= 1 << i;
14311 }
14312 else if (wcg_register (reg))
14313 {
14314 i = (reg & ~WC_PREFIX) - 8;
14315 if (wcg_mask >> i)
14316 as_tsktsk (_("register list not in ascending order"));
14317 wcg_mask |= 1 << i;
14318 }
14319 else
14320 {
14321 as_bad (_("expected wr or wcgr"));
14322 goto error;
14323 }
14324
14325 SKIP_WHITESPACE ();
14326 if (*input_line_pointer == '-')
14327 {
14328 hi_reg = arm_reg_parse (&input_line_pointer,
14329 all_reg_maps[REG_TYPE_IWMMXT].htab);
14330 if (wr_register (reg) && wr_register (hi_reg))
14331 {
14332 for (; reg < hi_reg; reg++)
14333 wr_mask |= 1 << (reg & ~WR_PREFIX);
14334 }
14335 else if (wcg_register (reg) && wcg_register (hi_reg))
14336 {
14337 for (; reg < hi_reg; reg++)
14338 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14339 }
14340 else
14341 {
14342 as_bad (_("bad register range"));
14343 goto error;
14344 }
14345 }
14346 }
14347 while (skip_past_comma (&input_line_pointer) != FAIL);
14348
14349 SKIP_WHITESPACE ();
14350 if (*input_line_pointer == '}')
14351 input_line_pointer++;
14352
14353 demand_empty_rest_of_line ();
14354
14355 if (wr_mask && wcg_mask)
14356 {
14357 as_bad (_("inconsistent register types"));
14358 goto error;
14359 }
14360
14361 /* Generate any deferred opcodes becuuse we're going to be looking at
14362 the list. */
14363 flush_pending_unwind ();
14364
14365 if (wcg_mask)
14366 {
14367 for (i = 0; i < 16; i++)
14368 {
14369 if (wcg_mask & (1 << i))
14370 unwind.frame_size += 4;
14371 }
14372 op = 0xc700 | wcg_mask;
14373 add_unwind_opcode (op, 2);
14374 }
14375 else
14376 {
14377 for (i = 0; i < 16; i++)
14378 {
14379 if (wr_mask & (1 << i))
14380 unwind.frame_size += 8;
14381 }
14382 /* Attempt to combine with a previous opcode. We do this because gcc
14383 likes to output separate unwind directives for a single block of
14384 registers. */
14385 if (unwind.opcode_count > 0)
14386 {
14387 i = unwind.opcodes[unwind.opcode_count - 1];
14388 if ((i & 0xf8) == 0xc0)
14389 {
14390 i &= 7;
14391 /* Only merge if the blocks are contiguous. */
14392 if (i < 6)
14393 {
14394 if ((wr_mask & 0xfe00) == (1 << 9))
14395 {
14396 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14397 unwind.opcode_count--;
14398 }
14399 }
14400 else if (i == 6 && unwind.opcode_count >= 2)
14401 {
14402 i = unwind.opcodes[unwind.opcode_count - 2];
14403 reg = i >> 4;
14404 i &= 0xf;
14405
14406 op = 0xffff << (reg - 1);
14407 if (reg > 0
14408 || ((wr_mask & op) == (1u << (reg - 1))))
14409 {
14410 op = (1 << (reg + i + 1)) - 1;
14411 op &= ~((1 << reg) - 1);
14412 wr_mask |= op;
14413 unwind.opcode_count -= 2;
14414 }
14415 }
14416 }
14417 }
14418
14419 hi_reg = 15;
14420 /* We want to generate opcodes in the order the registers have been
14421 saved, ie. descending order. */
14422 for (reg = 15; reg >= -1; reg--)
14423 {
14424 /* Save registers in blocks. */
14425 if (reg < 0
14426 || !(wr_mask & (1 << reg)))
14427 {
14428 /* We found an unsaved reg. Generate opcodes to save the
14429 preceeding block. */
14430 if (reg != hi_reg)
14431 {
14432 if (reg == 9)
14433 {
14434 /* Short form. */
14435 op = 0xc0 | (hi_reg - 10);
14436 add_unwind_opcode (op, 1);
14437 }
14438 else
14439 {
14440 /* Long form. */
14441 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14442 add_unwind_opcode (op, 2);
14443 }
14444 }
14445 hi_reg = reg - 1;
14446 }
14447 }
14448 }
14449 return;
14450error:
14451 ignore_rest_of_line ();
14452}
14453
14454
14455/* Parse an unwind_save directive. */
14456
14457static void
14458s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14459{
14460 char *saved_ptr;
14461 int reg;
14462
14463 /* Figure out what sort of save we have. */
14464 SKIP_WHITESPACE ();
14465 saved_ptr = input_line_pointer;
14466
14467 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14468 if (reg != FAIL)
14469 {
14470 s_arm_unwind_save_fpa (reg);
14471 return;
14472 }
14473
14474 if (*input_line_pointer == '{')
14475 input_line_pointer++;
14476
14477 SKIP_WHITESPACE ();
14478
14479 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14480 if (reg != FAIL)
14481 {
14482 input_line_pointer = saved_ptr;
14483 s_arm_unwind_save_core ();
14484 return;
14485 }
14486
14487 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14488 if (reg != FAIL)
14489 {
14490 input_line_pointer = saved_ptr;
14491 s_arm_unwind_save_vfp ();
14492 return;
14493 }
14494
14495 reg = arm_reg_parse (&input_line_pointer,
14496 all_reg_maps[REG_TYPE_IWMMXT].htab);
14497 if (reg != FAIL)
14498 {
14499 input_line_pointer = saved_ptr;
14500 s_arm_unwind_save_wmmx ();
14501 return;
14502 }
14503
14504 /* TODO: Maverick registers. */
14505 as_bad (_("unrecognised register"));
14506}
14507
14508
14509/* Parse an unwind_movsp directive. */
14510
14511static void
14512s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14513{
14514 int reg;
14515 valueT op;
14516
14517 SKIP_WHITESPACE ();
14518 reg = reg_required_here (&input_line_pointer, -1);
14519 if (reg == FAIL)
14520 {
14521 as_bad (_("ARM register expected"));
14522 ignore_rest_of_line ();
14523 return;
14524 }
14525
14526 if (reg == 13 || reg == 15)
14527 {
14528 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14529 ignore_rest_of_line ();
14530 return;
14531 }
14532
14533 if (unwind.fp_reg != 13)
14534 as_bad (_("unexpected .unwind_movsp directive"));
14535
14536 /* Generate opcode to restore the value. */
14537 op = 0x90 | reg;
14538 add_unwind_opcode (op, 1);
14539
14540 /* Record the information for later. */
14541 unwind.fp_reg = reg;
14542 unwind.fp_offset = unwind.frame_size;
14543 unwind.sp_restored = 1;
14544 demand_empty_rest_of_line ();
14545}
14546
14547
14548/* Parse #<number>. */
14549
14550static int
14551require_hashconst (int * val)
14552{
14553 expressionS exp;
14554
14555 SKIP_WHITESPACE ();
14556 if (*input_line_pointer == '#')
14557 {
14558 input_line_pointer++;
14559 expression (&exp);
14560 }
14561 else
14562 exp.X_op = O_illegal;
14563
14564 if (exp.X_op != O_constant)
14565 {
14566 as_bad (_("expected #constant"));
14567 ignore_rest_of_line ();
14568 return FAIL;
14569 }
14570 *val = exp.X_add_number;
14571 return SUCCESS;
14572}
14573
14574/* Parse an unwind_pad directive. */
14575
14576static void
14577s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14578{
14579 int offset;
14580
14581 if (require_hashconst (&offset) == FAIL)
14582 return;
14583
14584 if (offset & 3)
14585 {
14586 as_bad (_("stack increment must be multiple of 4"));
14587 ignore_rest_of_line ();
14588 return;
14589 }
14590
14591 /* Don't generate any opcodes, just record the details for later. */
14592 unwind.frame_size += offset;
14593 unwind.pending_offset += offset;
14594
14595 demand_empty_rest_of_line ();
14596}
14597
14598/* Parse an unwind_setfp directive. */
14599
14600static void
14601s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
14602{
14603 int sp_reg;
14604 int fp_reg;
14605 int offset;
14606
14607 fp_reg = reg_required_here (&input_line_pointer, -1);
14608 if (skip_past_comma (&input_line_pointer) == FAIL)
14609 sp_reg = FAIL;
14610 else
14611 sp_reg = reg_required_here (&input_line_pointer, -1);
14612
14613 if (fp_reg == FAIL || sp_reg == FAIL)
14614 {
14615 as_bad (_("expected <reg>, <reg>"));
14616 ignore_rest_of_line ();
14617 return;
14618 }
14619
14620 /* Optonal constant. */
14621 if (skip_past_comma (&input_line_pointer) != FAIL)
14622 {
14623 if (require_hashconst (&offset) == FAIL)
14624 return;
14625 }
14626 else
14627 offset = 0;
14628
14629 demand_empty_rest_of_line ();
14630
14631 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
14632 {
14633 as_bad (_("register must be either sp or set by a previous"
14634 "unwind_movsp directive"));
14635 return;
14636 }
14637
14638 /* Don't generate any opcodes, just record the information for later. */
14639 unwind.fp_reg = fp_reg;
14640 unwind.fp_used = 1;
14641 if (sp_reg == 13)
14642 unwind.fp_offset = unwind.frame_size - offset;
14643 else
14644 unwind.fp_offset -= offset;
14645}
14646
14647/* Parse an unwind_raw directive. */
14648
14649static void
14650s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
14651{
14652 expressionS exp;
14653 /* This is an arbitary limit. */
14654 unsigned char op[16];
14655 int count;
14656
14657 SKIP_WHITESPACE ();
14658 expression (&exp);
14659 if (exp.X_op == O_constant
14660 && skip_past_comma (&input_line_pointer) != FAIL)
14661 {
14662 unwind.frame_size += exp.X_add_number;
14663 expression (&exp);
14664 }
14665 else
14666 exp.X_op = O_illegal;
14667
14668 if (exp.X_op != O_constant)
14669 {
14670 as_bad (_("expected <offset>, <opcode>"));
14671 ignore_rest_of_line ();
14672 return;
14673 }
14674
14675 count = 0;
14676
14677 /* Parse the opcode. */
14678 for (;;)
14679 {
14680 if (count >= 16)
14681 {
14682 as_bad (_("unwind opcode too long"));
14683 ignore_rest_of_line ();
14684 }
14685 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
14686 {
14687 as_bad (_("invalid unwind opcode"));
14688 ignore_rest_of_line ();
14689 return;
14690 }
14691 op[count++] = exp.X_add_number;
14692
14693 /* Parse the next byte. */
14694 if (skip_past_comma (&input_line_pointer) == FAIL)
14695 break;
14696
14697 expression (&exp);
14698 }
14699
14700 /* Add the opcode bytes in reverse order. */
14701 while (count--)
14702 add_unwind_opcode (op[count], 1);
14703
14704 demand_empty_rest_of_line ();
14705}
eb043451 14706
b99bd4ef
NC
14707#endif /* OBJ_ELF */
14708
14709/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14710 of an rs_align_code fragment. */
14711
14712void
a737bd4d 14713arm_handle_align (fragS * fragP)
b99bd4ef
NC
14714{
14715 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14716 static char const thumb_noop[2] = { 0xc0, 0x46 };
14717 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14718 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14719
14720 int bytes, fix, noop_size;
14721 char * p;
14722 const char * noop;
cc8a6dd0 14723
b99bd4ef
NC
14724 if (fragP->fr_type != rs_align_code)
14725 return;
14726
14727 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14728 p = fragP->fr_literal + fragP->fr_fix;
14729 fix = 0;
cc8a6dd0 14730
b99bd4ef
NC
14731 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14732 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 14733
b99bd4ef
NC
14734 if (fragP->tc_frag_data)
14735 {
14736 if (target_big_endian)
14737 noop = thumb_bigend_noop;
14738 else
14739 noop = thumb_noop;
14740 noop_size = sizeof (thumb_noop);
14741 }
14742 else
14743 {
14744 if (target_big_endian)
14745 noop = arm_bigend_noop;
14746 else
14747 noop = arm_noop;
14748 noop_size = sizeof (arm_noop);
14749 }
cc8a6dd0 14750
b99bd4ef
NC
14751 if (bytes & (noop_size - 1))
14752 {
14753 fix = bytes & (noop_size - 1);
14754 memset (p, 0, fix);
14755 p += fix;
14756 bytes -= fix;
14757 }
14758
14759 while (bytes >= noop_size)
14760 {
14761 memcpy (p, noop, noop_size);
14762 p += noop_size;
14763 bytes -= noop_size;
14764 fix += noop_size;
14765 }
cc8a6dd0 14766
b99bd4ef
NC
14767 fragP->fr_fix += fix;
14768 fragP->fr_var = noop_size;
14769}
14770
14771/* Called from md_do_align. Used to create an alignment
14772 frag in a code section. */
14773
14774void
a737bd4d 14775arm_frag_align_code (int n, int max)
b99bd4ef
NC
14776{
14777 char * p;
14778
2d2255b5 14779 /* We assume that there will never be a requirement
b99bd4ef
NC
14780 to support alignments greater than 32 bytes. */
14781 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14782 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 14783
b99bd4ef
NC
14784 p = frag_var (rs_align_code,
14785 MAX_MEM_FOR_RS_ALIGN_CODE,
14786 1,
14787 (relax_substateT) max,
14788 (symbolS *) NULL,
14789 (offsetT) n,
14790 (char *) NULL);
14791 *p = 0;
b99bd4ef
NC
14792}
14793
14794/* Perform target specific initialisation of a frag. */
14795
14796void
a737bd4d 14797arm_init_frag (fragS * fragP)
b99bd4ef
NC
14798{
14799 /* Record whether this frag is in an ARM or a THUMB area. */
14800 fragP->tc_frag_data = thumb_mode;
14801}
a737bd4d 14802
a394c00f
NC
14803#ifdef OBJ_ELF
14804
14805/* Convert REGNAME to a DWARF-2 register number. */
14806
14807int
14808tc_arm_regname_to_dw2regnum (const char *regname)
14809{
14810 unsigned int i;
14811
14812 for (i = 0; rn_table[i].name; i++)
14813 if (streq (regname, rn_table[i].name))
14814 return rn_table[i].number;
14815
14816 return -1;
14817}
14818
14819/* Initialize the DWARF-2 unwind information for this procedure. */
14820
14821void
14822tc_arm_frame_initial_instructions (void)
14823{
14824 cfi_add_CFA_def_cfa (REG_SP, 0);
14825}
14826#endif
14827
a737bd4d
NC
14828/* This table describes all the machine specific pseudo-ops the assembler
14829 has to support. The fields are:
14830 pseudo-op name without dot
14831 function to call to execute this pseudo-op
14832 Integer arg to pass to the function. */
14833
14834const pseudo_typeS md_pseudo_table[] =
14835{
14836 /* Never called because '.req' does not start a line. */
14837 { "req", s_req, 0 },
14838 { "unreq", s_unreq, 0 },
14839 { "bss", s_bss, 0 },
14840 { "align", s_align, 0 },
14841 { "arm", s_arm, 0 },
14842 { "thumb", s_thumb, 0 },
14843 { "code", s_code, 0 },
14844 { "force_thumb", s_force_thumb, 0 },
14845 { "thumb_func", s_thumb_func, 0 },
14846 { "thumb_set", s_thumb_set, 0 },
14847 { "even", s_even, 0 },
14848 { "ltorg", s_ltorg, 0 },
14849 { "pool", s_ltorg, 0 },
14850#ifdef OBJ_ELF
14851 { "word", s_arm_elf_cons, 4 },
14852 { "long", s_arm_elf_cons, 4 },
14853 { "rel31", s_arm_rel31, 0 },
7ed4c4c5
NC
14854 { "fnstart", s_arm_unwind_fnstart, 0 },
14855 { "fnend", s_arm_unwind_fnend, 0 },
14856 { "cantunwind", s_arm_unwind_cantunwind, 0 },
14857 { "personality", s_arm_unwind_personality, 0 },
14858 { "personalityindex", s_arm_unwind_personalityindex, 0 },
14859 { "handlerdata", s_arm_unwind_handlerdata, 0 },
14860 { "save", s_arm_unwind_save, 0 },
14861 { "movsp", s_arm_unwind_movsp, 0 },
14862 { "pad", s_arm_unwind_pad, 0 },
14863 { "setfp", s_arm_unwind_setfp, 0 },
14864 { "unwind_raw", s_arm_unwind_raw, 0 },
a737bd4d
NC
14865#else
14866 { "word", cons, 4},
14867#endif
14868 { "extend", float_cons, 'x' },
14869 { "ldouble", float_cons, 'x' },
14870 { "packed", float_cons, 'p' },
14871 { 0, 0, 0 }
14872};