]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-arm.c
Fix typo introduced by previous delta
[thirdparty/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
b99bd4ef 1/* tc-arm.c -- Assemble for the ARM
f17c130b
AM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 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
b05fe5cf 2817do_mlas (char * str, bfd_boolean is_mls)
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
b05fe5cf
ZW
2849 /* This restriction does not apply to mls (nor to mla in v6, but
2850 that's hard to detect at present). */
2851 if (rm == rd && !is_mls)
b99bd4ef
NC
2852 as_tsktsk (_("rd and rm should be different in mla"));
2853
2854 if (skip_past_comma (&str) == FAIL
2855 || (rd = reg_required_here (&str, 8)) == FAIL
2856 || skip_past_comma (&str) == FAIL
2857 || (rm = reg_required_here (&str, 12)) == FAIL)
2858 {
2859 inst.error = BAD_ARGS;
2860 return;
2861 }
2862
2863 if (rd == REG_PC || rm == REG_PC)
2864 {
2865 inst.error = BAD_PC;
2866 return;
2867 }
2868
b99bd4ef 2869 end_of_line (str);
b99bd4ef
NC
2870}
2871
b05fe5cf
ZW
2872static void
2873do_mla (char *str)
2874{
2875 do_mlas (str, FALSE);
2876}
2877
2878static void
2879do_mls (char *str)
2880{
2881 do_mlas (str, TRUE);
2882}
2883
b99bd4ef
NC
2884/* Expects *str -> the characters "acc0", possibly with leading blanks.
2885 Advances *str to the next non-alphanumeric.
2886 Returns 0, or else FAIL (in which case sets inst.error).
2887
2888 (In a future XScale, there may be accumulators other than zero.
2889 At that time this routine and its callers can be upgraded to suit.) */
2890
2891static int
a737bd4d 2892accum0_required_here (char ** str)
b99bd4ef
NC
2893{
2894 static char buff [128]; /* Note the address is taken. Hence, static. */
2895 char * p = * str;
2896 char c;
2897 int result = 0; /* The accum number. */
2898
2899 skip_whitespace (p);
2900
a737bd4d
NC
2901 *str = p; /* Advance caller's string pointer too. */
2902 c = *p++;
2903 while (ISALNUM (c))
2904 c = *p++;
2905
2906 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2907
2908 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2909 {
2910 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2911 inst.error = buff;
2912 result = FAIL;
2913 }
2914
2915 *p = c; /* Unzap. */
2916 *str = p; /* Caller's string pointer to after match. */
2917 return result;
2918}
2919
2920static int
2921ldst_extend_v4 (char ** str)
2922{
2923 int add = INDEX_UP;
2924
2925 switch (**str)
2926 {
2927 case '#':
2928 case '$':
2929 (*str)++;
2930 if (my_get_expression (& inst.reloc.exp, str))
2931 return FAIL;
2932
2933 if (inst.reloc.exp.X_op == O_constant)
2934 {
2935 int value = inst.reloc.exp.X_add_number;
2936
2937 if (value < -255 || value > 255)
2938 {
2939 inst.error = _("address offset too large");
2940 return FAIL;
2941 }
2942
2943 if (value < 0)
2944 {
2945 value = -value;
2946 add = 0;
2947 }
2948
2949 /* Halfword and signextension instructions have the
2950 immediate value split across bits 11..8 and bits 3..0. */
2951 inst.instruction |= (add | HWOFFSET_IMM
2952 | ((value >> 4) << 8) | (value & 0xF));
2953 }
2954 else
2955 {
2956 inst.instruction |= HWOFFSET_IMM;
2957 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2958 inst.reloc.pc_rel = 0;
2959 }
2960 return SUCCESS;
2961
2962 case '-':
2963 add = 0;
2964 /* Fall through. */
2965
2966 case '+':
2967 (*str)++;
2968 /* Fall through. */
b99bd4ef 2969
a737bd4d
NC
2970 default:
2971 if (reg_required_here (str, 0) == FAIL)
2972 return FAIL;
b99bd4ef 2973
a737bd4d
NC
2974 inst.instruction |= add;
2975 return SUCCESS;
b99bd4ef 2976 }
b99bd4ef
NC
2977}
2978
2979/* Expects **str -> after a comma. May be leading blanks.
2980 Advances *str, recognizing a load mode, and setting inst.instruction.
2981 Returns rn, or else FAIL (in which case may set inst.error
2982 and not advance str)
2983
2984 Note: doesn't know Rd, so no err checks that require such knowledge. */
2985
2986static int
a737bd4d 2987ld_mode_required_here (char ** string)
b99bd4ef
NC
2988{
2989 char * str = * string;
2990 int rn;
2991 int pre_inc = 0;
2992
2993 skip_whitespace (str);
2994
2995 if (* str == '[')
2996 {
2997 str++;
2998
2999 skip_whitespace (str);
3000
3001 if ((rn = reg_required_here (& str, 16)) == FAIL)
3002 return FAIL;
3003
3004 skip_whitespace (str);
3005
3006 if (* str == ']')
3007 {
3008 str ++;
3009
3010 if (skip_past_comma (& str) == SUCCESS)
3011 {
3012 /* [Rn],... (post inc) */
90e4755a 3013 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3014 return FAIL;
3015 }
3016 else /* [Rn] */
3017 {
cc8a6dd0 3018 skip_whitespace (str);
b99bd4ef 3019
cc8a6dd0
KH
3020 if (* str == '!')
3021 {
3022 str ++;
3023 inst.instruction |= WRITE_BACK;
3024 }
b99bd4ef
NC
3025
3026 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3027 pre_inc = 1;
3028 }
3029 }
3030 else /* [Rn,...] */
3031 {
3032 if (skip_past_comma (& str) == FAIL)
3033 {
3034 inst.error = _("pre-indexed expression expected");
3035 return FAIL;
3036 }
3037
3038 pre_inc = 1;
3039
90e4755a 3040 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3041 return FAIL;
3042
3043 skip_whitespace (str);
3044
3045 if (* str ++ != ']')
3046 {
3047 inst.error = _("missing ]");
3048 return FAIL;
3049 }
3050
3051 skip_whitespace (str);
3052
3053 if (* str == '!')
3054 {
3055 str ++;
3056 inst.instruction |= WRITE_BACK;
3057 }
3058 }
3059 }
3060 else if (* str == '=') /* ldr's "r,=label" syntax */
3061 /* We should never reach here, because <text> = <expression> is
3062 caught gas/read.c read_a_source_file() as a .set operation. */
3063 return FAIL;
3064 else /* PC +- 8 bit immediate offset. */
3065 {
3066 if (my_get_expression (& inst.reloc.exp, & str))
3067 return FAIL;
3068
3069 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3070 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3071 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3072 inst.reloc.pc_rel = 1;
3073 inst.instruction |= (REG_PC << 16);
3074
3075 rn = REG_PC;
3076 pre_inc = 1;
3077 }
3078
3079 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3080 * string = str;
3081
3082 return rn;
3083}
3084
3085/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3086 SMLAxy{cond} Rd,Rm,Rs,Rn
3087 SMLAWy{cond} Rd,Rm,Rs,Rn
3088 Error if any register is R15. */
3089
3090static void
a737bd4d 3091do_smla (char * str)
b99bd4ef
NC
3092{
3093 int rd, rm, rs, rn;
3094
3095 skip_whitespace (str);
3096
3097 if ((rd = reg_required_here (& str, 16)) == FAIL
3098 || skip_past_comma (& str) == FAIL
3099 || (rm = reg_required_here (& str, 0)) == FAIL
3100 || skip_past_comma (& str) == FAIL
3101 || (rs = reg_required_here (& str, 8)) == FAIL
3102 || skip_past_comma (& str) == FAIL
3103 || (rn = reg_required_here (& str, 12)) == FAIL)
3104 inst.error = BAD_ARGS;
3105
3106 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3107 inst.error = BAD_PC;
3108
b99bd4ef
NC
3109 else
3110 end_of_line (str);
3111}
3112
3113/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3114 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3115 Error if any register is R15.
3116 Warning if Rdlo == Rdhi. */
3117
3118static void
a737bd4d 3119do_smlal (char * str)
b99bd4ef
NC
3120{
3121 int rdlo, rdhi, rm, rs;
3122
3123 skip_whitespace (str);
3124
3125 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3126 || skip_past_comma (& str) == FAIL
3127 || (rdhi = reg_required_here (& str, 16)) == FAIL
3128 || skip_past_comma (& str) == FAIL
3129 || (rm = reg_required_here (& str, 0)) == FAIL
3130 || skip_past_comma (& str) == FAIL
3131 || (rs = reg_required_here (& str, 8)) == FAIL)
3132 {
3133 inst.error = BAD_ARGS;
3134 return;
3135 }
3136
3137 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3138 {
3139 inst.error = BAD_PC;
3140 return;
3141 }
3142
3143 if (rdlo == rdhi)
3144 as_tsktsk (_("rdhi and rdlo must be different"));
3145
f2b7cb0a 3146 end_of_line (str);
b99bd4ef
NC
3147}
3148
3149/* ARM V5E (El Segundo) signed-multiply (argument parse)
3150 SMULxy{cond} Rd,Rm,Rs
3151 Error if any register is R15. */
3152
3153static void
a737bd4d 3154do_smul (char * str)
b99bd4ef
NC
3155{
3156 int rd, rm, rs;
3157
3158 skip_whitespace (str);
3159
3160 if ((rd = reg_required_here (& str, 16)) == FAIL
3161 || skip_past_comma (& str) == FAIL
3162 || (rm = reg_required_here (& str, 0)) == FAIL
3163 || skip_past_comma (& str) == FAIL
3164 || (rs = reg_required_here (& str, 8)) == FAIL)
3165 inst.error = BAD_ARGS;
3166
3167 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3168 inst.error = BAD_PC;
3169
b99bd4ef
NC
3170 else
3171 end_of_line (str);
3172}
3173
3174/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3175 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3176 Error if any register is R15. */
3177
3178static void
a737bd4d 3179do_qadd (char * str)
b99bd4ef
NC
3180{
3181 int rd, rm, rn;
3182
3183 skip_whitespace (str);
3184
3185 if ((rd = reg_required_here (& str, 12)) == FAIL
3186 || skip_past_comma (& str) == FAIL
3187 || (rm = reg_required_here (& str, 0)) == FAIL
3188 || skip_past_comma (& str) == FAIL
3189 || (rn = reg_required_here (& str, 16)) == FAIL)
3190 inst.error = BAD_ARGS;
3191
3192 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3193 inst.error = BAD_PC;
3194
b99bd4ef
NC
3195 else
3196 end_of_line (str);
3197}
3198
3199/* ARM V5E (el Segundo)
3200 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3201 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3202
3203 These are equivalent to the XScale instructions MAR and MRA,
3204 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3205
3206 Result unpredicatable if Rd or Rn is R15. */
3207
3208static void
a737bd4d 3209do_co_reg2c (char * str)
b99bd4ef
NC
3210{
3211 int rd, rn;
3212
3213 skip_whitespace (str);
3214
3215 if (co_proc_number (& str) == FAIL)
3216 {
3217 if (!inst.error)
3218 inst.error = BAD_ARGS;
3219 return;
3220 }
3221
3222 if (skip_past_comma (& str) == FAIL
3223 || cp_opc_expr (& str, 4, 4) == FAIL)
3224 {
3225 if (!inst.error)
3226 inst.error = BAD_ARGS;
3227 return;
3228 }
3229
3230 if (skip_past_comma (& str) == FAIL
3231 || (rd = reg_required_here (& str, 12)) == FAIL)
3232 {
3233 if (!inst.error)
3234 inst.error = BAD_ARGS;
3235 return;
3236 }
3237
3238 if (skip_past_comma (& str) == FAIL
3239 || (rn = reg_required_here (& str, 16)) == FAIL)
3240 {
3241 if (!inst.error)
3242 inst.error = BAD_ARGS;
3243 return;
3244 }
3245
09d92015
MM
3246 /* Unpredictable result if rd or rn is R15. */
3247 if (rd == REG_PC || rn == REG_PC)
3248 as_tsktsk
3249 (_("Warning: instruction unpredictable when using r15"));
3250
3251 if (skip_past_comma (& str) == FAIL
3252 || cp_reg_required_here (& str, 0) == FAIL)
3253 {
3254 if (!inst.error)
3255 inst.error = BAD_ARGS;
3256 return;
3257 }
3258
3259 end_of_line (str);
3260}
3261
3262/* ARM V5 count-leading-zeroes instruction (argument parse)
3263 CLZ{<cond>} <Rd>, <Rm>
3264 Condition defaults to COND_ALWAYS.
3265 Error if Rd or Rm are R15. */
3266
3267static void
a737bd4d 3268do_clz (char * str)
09d92015
MM
3269{
3270 int rd, rm;
3271
3272 skip_whitespace (str);
3273
3274 if (((rd = reg_required_here (& str, 12)) == FAIL)
3275 || (skip_past_comma (& str) == FAIL)
3276 || ((rm = reg_required_here (& str, 0)) == FAIL))
3277 inst.error = BAD_ARGS;
3278
3279 else if (rd == REG_PC || rm == REG_PC )
3280 inst.error = BAD_PC;
3281
3282 else
3283 end_of_line (str);
3284}
3285
3286/* ARM V5 (argument parse)
3287 LDC2{L} <coproc>, <CRd>, <addressing mode>
3288 STC2{L} <coproc>, <CRd>, <addressing mode>
3289 Instruction is not conditional, and has 0xf in the condition field.
3290 Otherwise, it's the same as LDC/STC. */
3291
3292static void
a737bd4d 3293do_lstc2 (char * str)
09d92015
MM
3294{
3295 skip_whitespace (str);
3296
3297 if (co_proc_number (& str) == FAIL)
3298 {
3299 if (!inst.error)
3300 inst.error = BAD_ARGS;
3301 }
3302 else if (skip_past_comma (& str) == FAIL
3303 || cp_reg_required_here (& str, 12) == FAIL)
3304 {
3305 if (!inst.error)
3306 inst.error = BAD_ARGS;
3307 }
3308 else if (skip_past_comma (& str) == FAIL
3309 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3310 {
3311 if (! inst.error)
3312 inst.error = BAD_ARGS;
3313 }
3314 else
3315 end_of_line (str);
3316}
3317
3318/* ARM V5 (argument parse)
3319 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3320 Instruction is not conditional, and has 0xf in the condition field.
3321 Otherwise, it's the same as CDP. */
3322
3323static void
a737bd4d 3324do_cdp2 (char * str)
09d92015
MM
3325{
3326 skip_whitespace (str);
3327
3328 if (co_proc_number (& str) == FAIL)
3329 {
3330 if (!inst.error)
3331 inst.error = BAD_ARGS;
3332 return;
3333 }
3334
3335 if (skip_past_comma (& str) == FAIL
3336 || cp_opc_expr (& str, 20,4) == FAIL)
3337 {
3338 if (!inst.error)
3339 inst.error = BAD_ARGS;
3340 return;
3341 }
3342
3343 if (skip_past_comma (& str) == FAIL
3344 || cp_reg_required_here (& str, 12) == FAIL)
3345 {
3346 if (!inst.error)
3347 inst.error = BAD_ARGS;
3348 return;
3349 }
3350
3351 if (skip_past_comma (& str) == FAIL
3352 || cp_reg_required_here (& str, 16) == FAIL)
3353 {
3354 if (!inst.error)
3355 inst.error = BAD_ARGS;
3356 return;
3357 }
3358
3359 if (skip_past_comma (& str) == FAIL
3360 || cp_reg_required_here (& str, 0) == FAIL)
3361 {
3362 if (!inst.error)
3363 inst.error = BAD_ARGS;
3364 return;
3365 }
3366
3367 if (skip_past_comma (& str) == SUCCESS)
3368 {
3369 if (cp_opc_expr (& str, 5, 3) == FAIL)
3370 {
3371 if (!inst.error)
3372 inst.error = BAD_ARGS;
3373 return;
3374 }
3375 }
3376
3377 end_of_line (str);
3378}
3379
3380/* ARM V5 (argument parse)
3381 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3382 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3383 Instruction is not conditional, and has 0xf in the condition field.
3384 Otherwise, it's the same as MCR/MRC. */
3385
3386static void
a737bd4d 3387do_co_reg2 (char * str)
09d92015
MM
3388{
3389 skip_whitespace (str);
3390
3391 if (co_proc_number (& str) == FAIL)
3392 {
3393 if (!inst.error)
3394 inst.error = BAD_ARGS;
3395 return;
3396 }
3397
3398 if (skip_past_comma (& str) == FAIL
3399 || cp_opc_expr (& str, 21, 3) == FAIL)
3400 {
3401 if (!inst.error)
3402 inst.error = BAD_ARGS;
3403 return;
3404 }
3405
3406 if (skip_past_comma (& str) == FAIL
3407 || reg_required_here (& str, 12) == FAIL)
3408 {
3409 if (!inst.error)
3410 inst.error = BAD_ARGS;
3411 return;
3412 }
3413
3414 if (skip_past_comma (& str) == FAIL
3415 || cp_reg_required_here (& str, 16) == FAIL)
3416 {
3417 if (!inst.error)
3418 inst.error = BAD_ARGS;
3419 return;
3420 }
3421
3422 if (skip_past_comma (& str) == FAIL
3423 || cp_reg_required_here (& str, 0) == FAIL)
3424 {
3425 if (!inst.error)
3426 inst.error = BAD_ARGS;
3427 return;
3428 }
3429
3430 if (skip_past_comma (& str) == SUCCESS)
3431 {
3432 if (cp_opc_expr (& str, 5, 3) == FAIL)
3433 {
3434 if (!inst.error)
3435 inst.error = BAD_ARGS;
3436 return;
3437 }
3438 }
3439
3440 end_of_line (str);
3441}
3442
a737bd4d
NC
3443static void
3444do_bx (char * str)
3445{
3446 int reg;
3447
3448 skip_whitespace (str);
3449
3450 if ((reg = reg_required_here (&str, 0)) == FAIL)
3451 {
3452 inst.error = BAD_ARGS;
3453 return;
3454 }
3455
3456 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3457 if (reg == REG_PC)
3458 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3459
3460 end_of_line (str);
3461}
3462
09d92015 3463/* ARM v5TEJ. Jump to Jazelle code. */
a737bd4d 3464
09d92015 3465static void
a737bd4d 3466do_bxj (char * str)
09d92015
MM
3467{
3468 int reg;
3469
3470 skip_whitespace (str);
3471
3472 if ((reg = reg_required_here (&str, 0)) == FAIL)
3473 {
3474 inst.error = BAD_ARGS;
3475 return;
3476 }
3477
a737bd4d
NC
3478 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3479 if (reg == REG_PC)
3480 as_tsktsk (_("use of r15 in bxj is not really useful"));
3481
3482 end_of_line (str);
3483}
3484
3485/* ARM V6 umaal (argument parse). */
3486
3487static void
3488do_umaal (char * str)
3489{
3490 int rdlo, rdhi, rm, rs;
3491
3492 skip_whitespace (str);
3493 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3494 || skip_past_comma (& str) == FAIL
3495 || (rdhi = reg_required_here (& str, 16)) == FAIL
3496 || skip_past_comma (& str) == FAIL
3497 || (rm = reg_required_here (& str, 0)) == FAIL
3498 || skip_past_comma (& str) == FAIL
3499 || (rs = reg_required_here (& str, 8)) == FAIL)
3500 {
3501 inst.error = BAD_ARGS;
3502 return;
3503 }
3504
3505 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3506 {
3507 inst.error = BAD_PC;
3508 return;
3509 }
3510
3511 end_of_line (str);
3512}
3513
3514/* ARM V6 strex (argument parse). */
3515
3516static void
3517do_strex (char * str)
3518{
3519 int rd, rm, rn;
3520
3521 /* Parse Rd, Rm,. */
3522 skip_whitespace (str);
3523 if ((rd = reg_required_here (& str, 12)) == FAIL
3524 || skip_past_comma (& str) == FAIL
3525 || (rm = reg_required_here (& str, 0)) == FAIL
3526 || skip_past_comma (& str) == FAIL)
3527 {
3528 inst.error = BAD_ARGS;
3529 return;
3530 }
3531 if (rd == REG_PC || rm == REG_PC)
3532 {
3533 inst.error = BAD_PC;
3534 return;
3535 }
3536 if (rd == rm)
3537 {
3538 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3539 return;
3540 }
3541
3542 /* Skip past '['. */
3543 if ((strlen (str) >= 1)
3544 && strncmp (str, "[", 1) == 0)
3545 str += 1;
3546
3547 skip_whitespace (str);
3548
3549 /* Parse Rn. */
3550 if ((rn = reg_required_here (& str, 16)) == FAIL)
3551 {
3552 inst.error = BAD_ARGS;
3553 return;
3554 }
3555 else if (rn == REG_PC)
3556 {
3557 inst.error = BAD_PC;
3558 return;
3559 }
3560 if (rd == rn)
3561 {
3562 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3563 return;
3564 }
3565 skip_whitespace (str);
3566
3567 /* Skip past ']'. */
3568 if ((strlen (str) >= 1)
3569 && strncmp (str, "]", 1) == 0)
3570 str += 1;
3571
3572 end_of_line (str);
3573}
3574
3575/* KIND indicates what kind of shifts are accepted. */
3576
3577static int
3578decode_shift (char ** str, int kind)
3579{
3580 const struct asm_shift_name * shift;
3581 char * p;
3582 char c;
3583
3584 skip_whitespace (* str);
3585
3586 for (p = * str; ISALPHA (* p); p ++)
3587 ;
3588
3589 if (p == * str)
3590 {
3591 inst.error = _("shift expression expected");
3592 return FAIL;
3593 }
3594
3595 c = * p;
3596 * p = '\0';
3597 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3598 * p = c;
3599
3600 if (shift == NULL)
3601 {
3602 inst.error = _("shift expression expected");
3603 return FAIL;
3604 }
3605
3606 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3607
3608 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3609 && shift->properties->index != SHIFT_LSL
3610 && shift->properties->index != SHIFT_ASR)
3611 {
3612 inst.error = _("'LSL' or 'ASR' required");
3613 return FAIL;
3614 }
3615 else if (kind == SHIFT_LSL_IMMEDIATE
3616 && shift->properties->index != SHIFT_LSL)
3617 {
3618 inst.error = _("'LSL' required");
3619 return FAIL;
3620 }
3621 else if (kind == SHIFT_ASR_IMMEDIATE
3622 && shift->properties->index != SHIFT_ASR)
3623 {
3624 inst.error = _("'ASR' required");
3625 return FAIL;
3626 }
3627
3628 if (shift->properties->index == SHIFT_RRX)
3629 {
3630 * str = p;
3631 inst.instruction |= shift->properties->bit_field;
3632 return SUCCESS;
3633 }
3634
3635 skip_whitespace (p);
3636
3637 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3638 {
3639 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3640 * str = p;
3641 return SUCCESS;
3642 }
3643 else if (! is_immediate_prefix (* p))
3644 {
3645 inst.error = (NO_SHIFT_RESTRICT
3646 ? _("shift requires register or #expression")
3647 : _("shift requires #expression"));
3648 * str = p;
3649 return FAIL;
3650 }
3651
3652 inst.error = NULL;
3653 p ++;
3654
3655 if (my_get_expression (& inst.reloc.exp, & p))
3656 return FAIL;
3657
3658 /* Validate some simple #expressions. */
3659 if (inst.reloc.exp.X_op == O_constant)
3660 {
3661 unsigned num = inst.reloc.exp.X_add_number;
3662
3663 /* Reject operations greater than 32. */
3664 if (num > 32
3665 /* Reject a shift of 0 unless the mode allows it. */
3666 || (num == 0 && shift->properties->allows_0 == 0)
3667 /* Reject a shift of 32 unless the mode allows it. */
3668 || (num == 32 && shift->properties->allows_32 == 0)
3669 )
3670 {
3671 /* As a special case we allow a shift of zero for
3672 modes that do not support it to be recoded as an
3673 logical shift left of zero (ie nothing). We warn
3674 about this though. */
3675 if (num == 0)
3676 {
3677 as_warn (_("shift of 0 ignored."));
3678 shift = & shift_names[0];
3679 assert (shift->properties->index == SHIFT_LSL);
3680 }
3681 else
3682 {
3683 inst.error = _("invalid immediate shift");
3684 return FAIL;
3685 }
3686 }
3687
3688 /* Shifts of 32 are encoded as 0, for those shifts that
3689 support it. */
3690 if (num == 32)
3691 num = 0;
3692
3693 inst.instruction |= (num << 7) | shift->properties->bit_field;
3694 }
3695 else
3696 {
3697 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3698 inst.reloc.pc_rel = 0;
3699 inst.instruction |= shift->properties->bit_field;
3700 }
3701
3702 * str = p;
3703 return SUCCESS;
09d92015
MM
3704}
3705
09d92015 3706static void
a737bd4d 3707do_sat (char ** str, int bias)
09d92015 3708{
a737bd4d
NC
3709 int rd, rm;
3710 expressionS expr;
09d92015 3711
a737bd4d 3712 skip_whitespace (*str);
09d92015 3713
a737bd4d
NC
3714 /* Parse <Rd>, field. */
3715 if ((rd = reg_required_here (str, 12)) == FAIL
3716 || skip_past_comma (str) == FAIL)
09d92015
MM
3717 {
3718 inst.error = BAD_ARGS;
a737bd4d 3719 return;
09d92015 3720 }
a737bd4d 3721 if (rd == REG_PC)
09d92015
MM
3722 {
3723 inst.error = BAD_PC;
3724 return;
3725 }
3726
a737bd4d
NC
3727 /* Parse #<immed>, field. */
3728 if (is_immediate_prefix (**str))
3729 (*str)++;
3730 else
09d92015 3731 {
a737bd4d 3732 inst.error = _("immediate expression expected");
09d92015
MM
3733 return;
3734 }
a737bd4d 3735 if (my_get_expression (&expr, str))
09d92015 3736 {
a737bd4d 3737 inst.error = _("bad expression");
09d92015
MM
3738 return;
3739 }
a737bd4d 3740 if (expr.X_op != O_constant)
09d92015 3741 {
a737bd4d 3742 inst.error = _("constant expression expected");
09d92015
MM
3743 return;
3744 }
a737bd4d
NC
3745 if (expr.X_add_number + bias < 0
3746 || expr.X_add_number + bias > 31)
3747 {
3748 inst.error = _("immediate value out of range");
3749 return;
3750 }
3751 inst.instruction |= (expr.X_add_number + bias) << 16;
3752 if (skip_past_comma (str) == FAIL)
09d92015
MM
3753 {
3754 inst.error = BAD_ARGS;
3755 return;
3756 }
a737bd4d
NC
3757
3758 /* Parse <Rm> field. */
3759 if ((rm = reg_required_here (str, 0)) == FAIL)
09d92015 3760 {
a737bd4d 3761 inst.error = BAD_ARGS;
09d92015
MM
3762 return;
3763 }
a737bd4d 3764 if (rm == REG_PC)
09d92015 3765 {
a737bd4d 3766 inst.error = BAD_PC;
09d92015
MM
3767 return;
3768 }
09d92015 3769
a737bd4d
NC
3770 if (skip_past_comma (str) == SUCCESS)
3771 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
09d92015
MM
3772}
3773
a737bd4d 3774/* ARM V6 ssat (argument parse). */
09d92015
MM
3775
3776static void
a737bd4d 3777do_ssat (char * str)
09d92015
MM
3778{
3779 do_sat (&str, /*bias=*/-1);
3780 end_of_line (str);
3781}
3782
a737bd4d 3783/* ARM V6 usat (argument parse). */
09d92015
MM
3784
3785static void
a737bd4d 3786do_usat (char * str)
09d92015
MM
3787{
3788 do_sat (&str, /*bias=*/0);
3789 end_of_line (str);
3790}
3791
3792static void
a737bd4d 3793do_sat16 (char ** str, int bias)
09d92015
MM
3794{
3795 int rd, rm;
3796 expressionS expr;
3797
3798 skip_whitespace (*str);
a737bd4d
NC
3799
3800 /* Parse the <Rd> field. */
09d92015
MM
3801 if ((rd = reg_required_here (str, 12)) == FAIL
3802 || skip_past_comma (str) == FAIL)
3803 {
3804 inst.error = BAD_ARGS;
3805 return;
3806 }
3807 if (rd == REG_PC)
3808 {
3809 inst.error = BAD_PC;
3810 return;
3811 }
3812
a737bd4d 3813 /* Parse #<immed>, field. */
09d92015
MM
3814 if (is_immediate_prefix (**str))
3815 (*str)++;
3816 else
3817 {
3818 inst.error = _("immediate expression expected");
3819 return;
3820 }
3821 if (my_get_expression (&expr, str))
3822 {
3823 inst.error = _("bad expression");
3824 return;
3825 }
3826 if (expr.X_op != O_constant)
3827 {
3828 inst.error = _("constant expression expected");
3829 return;
3830 }
3831 if (expr.X_add_number + bias < 0
a737bd4d 3832 || expr.X_add_number + bias > 15)
09d92015
MM
3833 {
3834 inst.error = _("immediate value out of range");
3835 return;
3836 }
3837 inst.instruction |= (expr.X_add_number + bias) << 16;
3838 if (skip_past_comma (str) == FAIL)
3839 {
3840 inst.error = BAD_ARGS;
3841 return;
3842 }
3843
a737bd4d 3844 /* Parse <Rm> field. */
09d92015
MM
3845 if ((rm = reg_required_here (str, 0)) == FAIL)
3846 {
3847 inst.error = BAD_ARGS;
3848 return;
3849 }
3850 if (rm == REG_PC)
3851 {
3852 inst.error = BAD_PC;
3853 return;
3854 }
09d92015
MM
3855}
3856
a737bd4d 3857/* ARM V6 ssat16 (argument parse). */
09d92015
MM
3858
3859static void
a737bd4d 3860do_ssat16 (char * str)
09d92015
MM
3861{
3862 do_sat16 (&str, /*bias=*/-1);
3863 end_of_line (str);
3864}
3865
3866static void
a737bd4d 3867do_usat16 (char * str)
09d92015
MM
3868{
3869 do_sat16 (&str, /*bias=*/0);
3870 end_of_line (str);
3871}
3872
3873static void
a737bd4d 3874do_cps_mode (char ** str)
09d92015 3875{
09d92015
MM
3876 expressionS expr;
3877
3878 skip_whitespace (*str);
3879
a737bd4d 3880 if (! is_immediate_prefix (**str))
09d92015
MM
3881 {
3882 inst.error = _("immediate expression expected");
3883 return;
3884 }
a737bd4d
NC
3885
3886 (*str)++; /* Strip off the immediate signifier. */
09d92015
MM
3887 if (my_get_expression (&expr, str))
3888 {
3889 inst.error = _("bad expression");
3890 return;
3891 }
a737bd4d 3892
09d92015
MM
3893 if (expr.X_op != O_constant)
3894 {
3895 inst.error = _("constant expression expected");
3896 return;
3897 }
09d92015 3898
a737bd4d
NC
3899 /* The mode is a 5 bit field. Valid values are 0-31. */
3900 if (((unsigned) expr.X_add_number) > 31
3901 || (inst.reloc.exp.X_add_number) < 0)
09d92015 3902 {
a737bd4d 3903 inst.error = _("invalid constant");
09d92015
MM
3904 return;
3905 }
a737bd4d
NC
3906
3907 inst.instruction |= expr.X_add_number;
09d92015
MM
3908}
3909
a737bd4d 3910/* ARM V6 srs (argument parse). */
09d92015
MM
3911
3912static void
a737bd4d 3913do_srs (char * str)
09d92015
MM
3914{
3915 char *exclam;
3916 skip_whitespace (str);
3917 exclam = strchr (str, '!');
3918 if (exclam)
3919 *exclam = '\0';
3920 do_cps_mode (&str);
3921 if (exclam)
3922 *exclam = '!';
a737bd4d 3923 if (*str == '!')
09d92015
MM
3924 {
3925 inst.instruction |= WRITE_BACK;
3926 str++;
3927 }
3928 end_of_line (str);
3929}
3930
a737bd4d 3931/* ARM V6 SMMUL (argument parse). */
09d92015
MM
3932
3933static void
a737bd4d 3934do_smmul (char * str)
09d92015
MM
3935{
3936 int rd, rm, rs;
a737bd4d 3937
09d92015
MM
3938 skip_whitespace (str);
3939 if ((rd = reg_required_here (&str, 16)) == FAIL
3940 || skip_past_comma (&str) == FAIL
3941 || (rm = reg_required_here (&str, 0)) == FAIL
3942 || skip_past_comma (&str) == FAIL
3943 || (rs = reg_required_here (&str, 8)) == FAIL)
3944 {
3945 inst.error = BAD_ARGS;
3946 return;
3947 }
3948
a737bd4d 3949 if ( rd == REG_PC
09d92015
MM
3950 || rm == REG_PC
3951 || rs == REG_PC)
3952 {
3953 inst.error = BAD_PC;
3954 return;
3955 }
3956
3957 end_of_line (str);
09d92015
MM
3958}
3959
a737bd4d 3960/* ARM V6 SMLALD (argument parse). */
09d92015
MM
3961
3962static void
a737bd4d 3963do_smlald (char * str)
09d92015
MM
3964{
3965 int rdlo, rdhi, rm, rs;
a737bd4d 3966
09d92015
MM
3967 skip_whitespace (str);
3968 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3969 || skip_past_comma (&str) == FAIL
3970 || (rdhi = reg_required_here (&str, 16)) == FAIL
3971 || skip_past_comma (&str) == FAIL
3972 || (rm = reg_required_here (&str, 0)) == FAIL
3973 || skip_past_comma (&str) == FAIL
3974 || (rs = reg_required_here (&str, 8)) == FAIL)
3975 {
3976 inst.error = BAD_ARGS;
3977 return;
3978 }
3979
a737bd4d
NC
3980 if ( rdlo == REG_PC
3981 || rdhi == REG_PC
09d92015
MM
3982 || rm == REG_PC
3983 || rs == REG_PC)
3984 {
3985 inst.error = BAD_PC;
3986 return;
3987 }
3988
3989 end_of_line (str);
3990}
3991
a737bd4d 3992/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
09d92015
MM
3993 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
3994
a737bd4d
NC
3995static void
3996do_smlad (char * str)
09d92015
MM
3997{
3998 int rd, rm, rs, rn;
a737bd4d 3999
09d92015
MM
4000 skip_whitespace (str);
4001 if ((rd = reg_required_here (&str, 16)) == FAIL
4002 || skip_past_comma (&str) == FAIL
4003 || (rm = reg_required_here (&str, 0)) == FAIL
4004 || skip_past_comma (&str) == FAIL
4005 || (rs = reg_required_here (&str, 8)) == FAIL
4006 || skip_past_comma (&str) == FAIL
4007 || (rn = reg_required_here (&str, 12)) == FAIL)
4008 {
4009 inst.error = BAD_ARGS;
4010 return;
4011 }
a737bd4d
NC
4012
4013 if ( rd == REG_PC
4014 || rn == REG_PC
09d92015
MM
4015 || rs == REG_PC
4016 || rm == REG_PC)
4017 {
4018 inst.error = BAD_PC;
4019 return;
4020 }
4021
4022 end_of_line (str);
09d92015
MM
4023}
4024
4025/* Returns true if the endian-specifier indicates big-endianness. */
4026
4027static int
a737bd4d 4028do_endian_specifier (char * str)
09d92015
MM
4029{
4030 int big_endian = 0;
4031
4032 skip_whitespace (str);
4033 if (strlen (str) < 2)
4034 inst.error = _("missing endian specifier");
4035 else if (strncasecmp (str, "BE", 2) == 0)
4036 {
4037 str += 2;
4038 big_endian = 1;
4039 }
4040 else if (strncasecmp (str, "LE", 2) == 0)
4041 str += 2;
4042 else
4043 inst.error = _("valid endian specifiers are be or le");
4044
4045 end_of_line (str);
4046
4047 return big_endian;
4048}
4049
a737bd4d
NC
4050/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4051 preserving the other bits.
4052
4053 setend <endian_specifier>, where <endian_specifier> is either
4054 BE or LE. */
4055
4056static void
4057do_setend (char * str)
4058{
4059 if (do_endian_specifier (str))
4060 inst.instruction |= 0x200;
4061}
4062
09d92015
MM
4063/* ARM V6 SXTH.
4064
4065 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4066 Condition defaults to COND_ALWAYS.
a737bd4d 4067 Error if any register uses R15. */
09d92015 4068
a737bd4d
NC
4069static void
4070do_sxth (char * str)
09d92015
MM
4071{
4072 int rd, rm;
4073 expressionS expr;
4074 int rotation_clear_mask = 0xfffff3ff;
4075 int rotation_eight_mask = 0x00000400;
4076 int rotation_sixteen_mask = 0x00000800;
4077 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4078
09d92015
MM
4079 skip_whitespace (str);
4080 if ((rd = reg_required_here (&str, 12)) == FAIL
4081 || skip_past_comma (&str) == FAIL
4082 || (rm = reg_required_here (&str, 0)) == FAIL)
4083 {
4084 inst.error = BAD_ARGS;
4085 return;
4086 }
4087
4088 else if (rd == REG_PC || rm == REG_PC)
4089 {
4090 inst.error = BAD_PC;
4091 return;
4092 }
a737bd4d
NC
4093
4094 /* Zero out the rotation field. */
09d92015 4095 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4096
4097 /* Check for lack of optional rotation field. */
09d92015
MM
4098 if (skip_past_comma (&str) == FAIL)
4099 {
4100 end_of_line (str);
4101 return;
4102 }
a737bd4d
NC
4103
4104 /* Move past 'ROR'. */
09d92015
MM
4105 skip_whitespace (str);
4106 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4107 str += 3;
09d92015
MM
4108 else
4109 {
4110 inst.error = _("missing rotation field after comma");
4111 return;
4112 }
a737bd4d
NC
4113
4114 /* Get the immediate constant. */
09d92015
MM
4115 skip_whitespace (str);
4116 if (is_immediate_prefix (* str))
4117 str++;
4118 else
4119 {
4120 inst.error = _("immediate expression expected");
4121 return;
4122 }
a737bd4d 4123
09d92015
MM
4124 if (my_get_expression (&expr, &str))
4125 {
4126 inst.error = _("bad expression");
4127 return;
4128 }
4129
4130 if (expr.X_op != O_constant)
4131 {
4132 inst.error = _("constant expression expected");
4133 return;
4134 }
a737bd4d
NC
4135
4136 switch (expr.X_add_number)
09d92015
MM
4137 {
4138 case 0:
a737bd4d 4139 /* Rotation field has already been zeroed. */
09d92015
MM
4140 break;
4141 case 8:
4142 inst.instruction |= rotation_eight_mask;
4143 break;
4144
4145 case 16:
4146 inst.instruction |= rotation_sixteen_mask;
4147 break;
a737bd4d 4148
09d92015
MM
4149 case 24:
4150 inst.instruction |= rotation_twenty_four_mask;
4151 break;
4152
4153 default:
4154 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4155 break;
4156 }
4157
4158 end_of_line (str);
09d92015
MM
4159}
4160
4161/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4162 extends it to 32-bits, and adds the result to a value in another
4163 register. You can specify a rotation by 0, 8, 16, or 24 bits
4164 before extracting the 16-bit value.
4165 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4166 Condition defaults to COND_ALWAYS.
a737bd4d 4167 Error if any register uses R15. */
09d92015 4168
a737bd4d
NC
4169static void
4170do_sxtah (char * str)
09d92015
MM
4171{
4172 int rd, rn, rm;
4173 expressionS expr;
4174 int rotation_clear_mask = 0xfffff3ff;
4175 int rotation_eight_mask = 0x00000400;
4176 int rotation_sixteen_mask = 0x00000800;
4177 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4178
09d92015
MM
4179 skip_whitespace (str);
4180 if ((rd = reg_required_here (&str, 12)) == FAIL
4181 || skip_past_comma (&str) == FAIL
4182 || (rn = reg_required_here (&str, 16)) == FAIL
4183 || skip_past_comma (&str) == FAIL
4184 || (rm = reg_required_here (&str, 0)) == FAIL)
4185 {
4186 inst.error = BAD_ARGS;
4187 return;
4188 }
4189
4190 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4191 {
4192 inst.error = BAD_PC;
4193 return;
4194 }
a737bd4d
NC
4195
4196 /* Zero out the rotation field. */
09d92015 4197 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4198
4199 /* Check for lack of optional rotation field. */
09d92015
MM
4200 if (skip_past_comma (&str) == FAIL)
4201 {
4202 end_of_line (str);
4203 return;
4204 }
a737bd4d
NC
4205
4206 /* Move past 'ROR'. */
09d92015
MM
4207 skip_whitespace (str);
4208 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4209 str += 3;
09d92015
MM
4210 else
4211 {
4212 inst.error = _("missing rotation field after comma");
4213 return;
4214 }
a737bd4d
NC
4215
4216 /* Get the immediate constant. */
09d92015
MM
4217 skip_whitespace (str);
4218 if (is_immediate_prefix (* str))
4219 str++;
4220 else
4221 {
4222 inst.error = _("immediate expression expected");
4223 return;
4224 }
a737bd4d 4225
09d92015
MM
4226 if (my_get_expression (&expr, &str))
4227 {
4228 inst.error = _("bad expression");
4229 return;
4230 }
4231
4232 if (expr.X_op != O_constant)
4233 {
4234 inst.error = _("constant expression expected");
4235 return;
4236 }
a737bd4d
NC
4237
4238 switch (expr.X_add_number)
09d92015
MM
4239 {
4240 case 0:
a737bd4d 4241 /* Rotation field has already been zeroed. */
09d92015
MM
4242 break;
4243
4244 case 8:
4245 inst.instruction |= rotation_eight_mask;
4246 break;
4247
4248 case 16:
4249 inst.instruction |= rotation_sixteen_mask;
4250 break;
a737bd4d 4251
09d92015
MM
4252 case 24:
4253 inst.instruction |= rotation_twenty_four_mask;
4254 break;
4255
4256 default:
4257 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4258 break;
4259 }
4260
4261 end_of_line (str);
09d92015 4262}
a737bd4d 4263
09d92015
MM
4264
4265/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4266 word at the specified address and the following word
a737bd4d 4267 respectively.
09d92015 4268 Unconditionally executed.
a737bd4d 4269 Error if Rn is R15. */
09d92015
MM
4270
4271static void
a737bd4d 4272do_rfe (char * str)
09d92015
MM
4273{
4274 int rn;
4275
4276 skip_whitespace (str);
a737bd4d 4277
09d92015
MM
4278 if ((rn = reg_required_here (&str, 16)) == FAIL)
4279 return;
b99bd4ef 4280
09d92015 4281 if (rn == REG_PC)
b99bd4ef 4282 {
09d92015 4283 inst.error = BAD_PC;
b99bd4ef
NC
4284 return;
4285 }
4286
09d92015 4287 skip_whitespace (str);
a737bd4d 4288
09d92015
MM
4289 if (*str == '!')
4290 {
4291 inst.instruction |= WRITE_BACK;
4292 str++;
4293 }
b99bd4ef
NC
4294 end_of_line (str);
4295}
4296
09d92015
MM
4297/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4298 register (argument parse).
4299 REV{<cond>} Rd, Rm.
4300 Condition defaults to COND_ALWAYS.
a737bd4d 4301 Error if Rd or Rm are R15. */
b99bd4ef
NC
4302
4303static void
a737bd4d 4304do_rev (char * str)
b99bd4ef
NC
4305{
4306 int rd, rm;
4307
b99bd4ef
NC
4308 skip_whitespace (str);
4309
09d92015
MM
4310 if ((rd = reg_required_here (&str, 12)) == FAIL
4311 || skip_past_comma (&str) == FAIL
4312 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
4313 inst.error = BAD_ARGS;
4314
09d92015 4315 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
4316 inst.error = BAD_PC;
4317
4318 else
4319 end_of_line (str);
4320}
4321
09d92015 4322/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
a737bd4d 4323 QADD16{<cond>} <Rd>, <Rn>, <Rm>
09d92015
MM
4324 Condition defaults to COND_ALWAYS.
4325 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
4326
4327static void
a737bd4d 4328do_qadd16 (char * str)
b99bd4ef 4329{
09d92015
MM
4330 int rd, rm, rn;
4331
b99bd4ef
NC
4332 skip_whitespace (str);
4333
09d92015
MM
4334 if ((rd = reg_required_here (&str, 12)) == FAIL
4335 || skip_past_comma (&str) == FAIL
4336 || (rn = reg_required_here (&str, 16)) == FAIL
4337 || skip_past_comma (&str) == FAIL
4338 || (rm = reg_required_here (&str, 0)) == FAIL)
4339 inst.error = BAD_ARGS;
4340
4341 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4342 inst.error = BAD_PC;
4343
b99bd4ef
NC
4344 else
4345 end_of_line (str);
4346}
4347
b99bd4ef 4348static void
a737bd4d 4349do_pkh_core (char * str, int shift)
b99bd4ef 4350{
09d92015 4351 int rd, rn, rm;
b99bd4ef 4352
09d92015
MM
4353 skip_whitespace (str);
4354 if (((rd = reg_required_here (&str, 12)) == FAIL)
4355 || (skip_past_comma (&str) == FAIL)
4356 || ((rn = reg_required_here (&str, 16)) == FAIL)
4357 || (skip_past_comma (&str) == FAIL)
4358 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 4359 {
09d92015 4360 inst.error = BAD_ARGS;
b99bd4ef
NC
4361 return;
4362 }
4363
09d92015 4364 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 4365 {
09d92015 4366 inst.error = BAD_PC;
b99bd4ef
NC
4367 return;
4368 }
4369
a737bd4d
NC
4370 /* Check for optional shift immediate constant. */
4371 if (skip_past_comma (&str) == FAIL)
b99bd4ef 4372 {
09d92015
MM
4373 if (shift == SHIFT_ASR_IMMEDIATE)
4374 {
4375 /* If the shift specifier is ommited, turn the instruction
4376 into pkhbt rd, rm, rn. First, switch the instruction
4377 code, and clear the rn and rm fields. */
4378 inst.instruction &= 0xfff0f010;
4379 /* Now, re-encode the registers. */
4380 inst.instruction |= (rm << 16) | rn;
4381 }
b99bd4ef
NC
4382 return;
4383 }
4384
09d92015
MM
4385 decode_shift (&str, shift);
4386}
4387
a737bd4d
NC
4388/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4389 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4390 Condition defaults to COND_ALWAYS.
4391 Error if Rd, Rn or Rm are R15. */
4392
4393static void
4394do_pkhbt (char * str)
4395{
4396 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4397}
4398
4399/* ARM V6 PKHTB (Argument Parse). */
4400
4401static void
4402do_pkhtb (char * str)
4403{
4404 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4405}
4406
09d92015 4407/* ARM V6 Load Register Exclusive instruction (argument parse).
0dd132b6 4408 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
09d92015 4409 Condition defaults to COND_ALWAYS.
a737bd4d
NC
4410 Error if Rd or Rn are R15.
4411 See ARMARMv6 A4.1.27: LDREX. */
09d92015
MM
4412
4413static void
a737bd4d 4414do_ldrex (char * str)
09d92015
MM
4415{
4416 int rd, rn;
4417
4418 skip_whitespace (str);
4419
a737bd4d 4420 /* Parse Rd. */
09d92015
MM
4421 if (((rd = reg_required_here (&str, 12)) == FAIL)
4422 || (skip_past_comma (&str) == FAIL))
b99bd4ef 4423 {
09d92015 4424 inst.error = BAD_ARGS;
b99bd4ef
NC
4425 return;
4426 }
09d92015 4427 else if (rd == REG_PC)
b99bd4ef 4428 {
09d92015 4429 inst.error = BAD_PC;
b99bd4ef
NC
4430 return;
4431 }
a737bd4d 4432 skip_whitespace (str);
b99bd4ef 4433
a737bd4d
NC
4434 /* Skip past '['. */
4435 if ((strlen (str) >= 1)
09d92015 4436 &&strncmp (str, "[", 1) == 0)
a737bd4d
NC
4437 str += 1;
4438 skip_whitespace (str);
09d92015 4439
a737bd4d 4440 /* Parse Rn. */
09d92015 4441 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 4442 {
09d92015
MM
4443 inst.error = BAD_ARGS;
4444 return;
b99bd4ef 4445 }
09d92015
MM
4446 else if (rn == REG_PC)
4447 {
4448 inst.error = BAD_PC;
4449 return;
4450 }
a737bd4d 4451 skip_whitespace (str);
b99bd4ef 4452
a737bd4d
NC
4453 /* Skip past ']'. */
4454 if ((strlen (str) >= 1)
09d92015 4455 && strncmp (str, "]", 1) == 0)
a737bd4d
NC
4456 str += 1;
4457
b99bd4ef
NC
4458 end_of_line (str);
4459}
4460
09d92015 4461/* ARM V6 change processor state instruction (argument parse)
a737bd4d 4462 CPS, CPSIE, CSPID . */
b99bd4ef
NC
4463
4464static void
a737bd4d 4465do_cps (char * str)
b99bd4ef 4466{
09d92015
MM
4467 do_cps_mode (&str);
4468 end_of_line (str);
4469}
b99bd4ef 4470
09d92015 4471static void
a737bd4d 4472do_cps_flags (char ** str, int thumb_p)
ea6ef066 4473{
a737bd4d
NC
4474 struct cps_flag
4475 {
09d92015
MM
4476 char character;
4477 unsigned long arm_value;
4478 unsigned long thumb_value;
4479 };
a737bd4d
NC
4480 static struct cps_flag flag_table[] =
4481 {
09d92015
MM
4482 {'a', 0x100, 0x4 },
4483 {'i', 0x080, 0x2 },
4484 {'f', 0x040, 0x1 }
4485 };
ea6ef066 4486
09d92015 4487 int saw_a_flag = 0;
ea6ef066 4488
09d92015
MM
4489 skip_whitespace (*str);
4490
a737bd4d 4491 /* Get the a, f and i flags. */
09d92015 4492 while (**str && **str != ',')
ea6ef066 4493 {
09d92015
MM
4494 struct cps_flag *p;
4495 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
a737bd4d 4496
09d92015
MM
4497 for (p = flag_table; p < q; ++p)
4498 if (strncasecmp (*str, &p->character, 1) == 0)
4499 {
4500 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4501 saw_a_flag = 1;
4502 break;
4503 }
4504 if (p == q)
4505 {
4506 inst.error = _("unrecognized flag");
4507 return;
4508 }
4509 (*str)++;
ea6ef066 4510 }
a737bd4d
NC
4511
4512 if (!saw_a_flag)
4513 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4514}
4515
4516static void
4517do_cpsi (char * str)
4518{
4519 do_cps_flags (&str, /*thumb_p=*/0);
4520
4521 if (skip_past_comma (&str) == SUCCESS)
4522 {
4523 skip_whitespace (str);
4524 do_cps_mode (&str);
4525 }
4526 end_of_line (str);
ea6ef066
RE
4527}
4528
b05fe5cf
ZW
4529/* ARM V6T2 bitfield manipulation instructions. */
4530
4531static int
4532five_bit_unsigned_immediate (char **str)
4533{
4534 expressionS expr;
4535
4536 skip_whitespace (*str);
4537 if (!is_immediate_prefix (**str))
4538 {
4539 inst.error = _("immediate expression expected");
4540 return -1;
4541 }
4542 (*str)++;
4543 if (my_get_expression (&expr, str))
4544 {
4545 inst.error = _("bad expression");
4546 return -1;
4547 }
4548 if (expr.X_op != O_constant)
4549 {
4550 inst.error = _("constant expression expected");
4551 return -1;
4552 }
4553 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4554 {
4555 inst.error = _("immediate value out of range");
4556 return -1;
4557 }
4558
4559 return expr.X_add_number;
4560}
4561
4562static void
4563bfci_lsb_and_width (char *str)
4564{
4565 int lsb, width;
4566
4567 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4568 return;
4569
4570 if (skip_past_comma (&str) == FAIL)
4571 {
4572 inst.error = BAD_ARGS;
4573 return;
4574 }
4575 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4576 return;
4577
4578 end_of_line (str);
4579
4580 if (width == 0 || lsb == 32)
4581 {
4582 inst.error = _("immediate value out of range");
4583 return;
4584 }
4585 else if (width + lsb > 32)
4586 {
4587 inst.error = _("bit-field extends past end of register");
4588 return;
4589 }
4590
4591 /* Convert to LSB/MSB and write to register. */
4592 inst.instruction |= lsb << 7;
4593 inst.instruction |= (width + lsb - 1) << 16;
4594}
4595
4596static void
4597do_bfc (char *str)
4598{
4599 int rd;
4600
4601 /* Rd. */
4602 skip_whitespace (str);
4603 if (((rd = reg_required_here (&str, 12)) == FAIL)
4604 || (skip_past_comma (&str) == FAIL))
4605 {
4606 inst.error = BAD_ARGS;
4607 return;
4608 }
4609 else if (rd == REG_PC)
4610 {
4611 inst.error = BAD_PC;
4612 return;
4613 }
4614
4615 bfci_lsb_and_width (str);
4616}
4617
4618static void
4619do_bfi (char *str)
4620{
4621 int rd, rm;
4622
4623 /* Rd. */
4624 skip_whitespace (str);
4625 if (((rd = reg_required_here (&str, 12)) == FAIL)
4626 || (skip_past_comma (&str) == FAIL))
4627 {
4628 inst.error = BAD_ARGS;
4629 return;
4630 }
4631 else if (rd == REG_PC)
4632 {
4633 inst.error = BAD_PC;
4634 return;
4635 }
4636
4637 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4638 skip_whitespace (str);
4639 if (is_immediate_prefix (*str))
4640 {
4641 expressionS expr;
4642 str++;
4643 if (my_get_expression (&expr, &str))
4644 {
4645 inst.error = _("bad expression");
4646 return;
4647 }
4648 if (expr.X_op != O_constant)
4649 {
4650 inst.error = _("constant expression expected");
4651 return;
4652 }
4653 if (expr.X_add_number != 0)
4654 {
4655 inst.error = _("immediate value out of range");
4656 return;
4657 }
4658 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4659 }
4660 else
4661 {
4662 if ((rm = reg_required_here (&str, 0)) == FAIL)
4663 {
4664 inst.error = BAD_ARGS;
4665 return;
4666 }
4667 else if (rm == REG_PC)
4668 {
4669 inst.error = BAD_PC;
4670 return;
4671 }
4672 }
4673 if (skip_past_comma (&str) == FAIL)
4674 {
4675 inst.error = BAD_ARGS;
4676 return;
4677 }
4678
4679 bfci_lsb_and_width (str);
4680}
4681
4682static void
4683do_bfx (char *str)
4684{
4685 int lsb, width;
4686
4687 /* Rd. */
4688 skip_whitespace (str);
4689 if (reg_required_here (&str, 12) == FAIL
4690 || skip_past_comma (&str) == FAIL)
4691 {
4692 inst.error = BAD_ARGS;
4693 return;
4694 }
4695
4696 /* Rm. */
4697 skip_whitespace (str);
4698 if (reg_required_here (&str, 0) == FAIL
4699 || skip_past_comma (&str) == FAIL)
4700 {
4701 inst.error = BAD_ARGS;
4702 return;
4703 }
4704
4705 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4706 return;
4707
4708 if (skip_past_comma (&str) == FAIL)
4709 {
4710 inst.error = BAD_ARGS;
4711 return;
4712 }
4713 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4714 return;
4715
4716 end_of_line (str);
4717
4718 if (width == 0 || lsb == 32)
4719 {
4720 inst.error = _("immediate value out of range");
4721 return;
4722 }
4723 else if (width + lsb > 32)
4724 {
4725 inst.error = _("bit-field extends past end of register");
4726 return;
4727 }
4728
4729 inst.instruction |= lsb << 7;
4730 inst.instruction |= (width - 1) << 16;
4731}
4732
4733static void
4734do_rbit (char *str)
4735{
4736 /* Rd. */
4737 skip_whitespace (str);
4738 if (reg_required_here (&str, 12) == FAIL
4739 || skip_past_comma (&str) == FAIL)
4740 {
4741 inst.error = BAD_ARGS;
4742 return;
4743 }
4744
4745 /* Rm. */
4746 skip_whitespace (str);
4747 if (reg_required_here (&str, 0) == FAIL)
4748 {
4749 inst.error = BAD_ARGS;
4750 return;
4751 }
4752
4753 end_of_line (str);
4754}
4755
4756/* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4757static void
4758do_mov16 (char *str)
4759{
4760 int rd;
4761 expressionS expr;
4762
4763 /* Rd. */
4764 skip_whitespace (str);
4765 if (((rd = reg_required_here (&str, 12)) == FAIL)
4766 || (skip_past_comma (&str) == FAIL))
4767 {
4768 inst.error = BAD_ARGS;
4769 return;
4770 }
4771 else if (rd == REG_PC)
4772 {
4773 inst.error = BAD_PC;
4774 return;
4775 }
4776
4777 /* Imm16. */
4778 skip_whitespace (str);
4779 if (!is_immediate_prefix (*str))
4780 {
4781 inst.error = _("immediate expression expected");
4782 return;
4783 }
4784 str++;
4785 if (my_get_expression (&expr, &str))
4786 {
4787 inst.error = _("bad expression");
4788 return;
4789 }
4790 if (expr.X_op != O_constant)
4791 {
4792 inst.error = _("constant expression expected");
4793 return;
4794 }
4795 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4796 {
4797 inst.error = _("immediate value out of range");
4798 return;
4799 }
4800
4801 end_of_line (str);
4802
4803 /* The value is in two pieces: 0:11, 16:19. */
4804 inst.instruction |= (expr.X_add_number & 0x00000fff);
4805 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4806}
4807
4808
b99bd4ef
NC
4809/* THUMB V5 breakpoint instruction (argument parse)
4810 BKPT <immed_8>. */
4811
4812static void
a737bd4d 4813do_t_bkpt (char * str)
b99bd4ef
NC
4814{
4815 expressionS expr;
4816 unsigned long number;
4817
4818 skip_whitespace (str);
4819
4820 /* Allow optional leading '#'. */
4821 if (is_immediate_prefix (*str))
4822 str ++;
4823
4824 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
4825 if (my_get_expression (& expr, & str)
4826 || (expr.X_op != O_constant
4827 /* As a convenience we allow 'bkpt' without an operand. */
4828 && expr.X_op != O_absent))
b99bd4ef 4829 {
143c8e19 4830 inst.error = _("bad expression");
b99bd4ef
NC
4831 return;
4832 }
4833
4834 number = expr.X_add_number;
4835
4836 /* Check it fits an 8 bit unsigned. */
4837 if (number != (number & 0xff))
4838 {
4839 inst.error = _("immediate value out of range");
4840 return;
4841 }
4842
4843 inst.instruction |= number;
4844
4845 end_of_line (str);
4846}
4847
f17c130b 4848#ifdef OBJ_ELF
a737bd4d
NC
4849static bfd_reloc_code_real_type
4850arm_parse_reloc (void)
4851{
4852 char id [16];
4853 char * ip;
4854 unsigned int i;
4855 static struct
4856 {
4857 char * str;
4858 int len;
4859 bfd_reloc_code_real_type reloc;
4860 }
4861 reloc_map[] =
4862 {
4863#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4864 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4865 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4866 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4867 branch instructions generated by GCC for PLT relocs. */
4868 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4869 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4870 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4871 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4872 { NULL, 0, BFD_RELOC_UNUSED }
4873#undef MAP
4874 };
4875
4876 for (i = 0, ip = input_line_pointer;
4877 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4878 i++, ip++)
4879 id[i] = TOLOWER (*ip);
4880
4881 for (i = 0; reloc_map[i].str; i++)
4882 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4883 break;
4884
4885 input_line_pointer += reloc_map[i].len;
4886
4887 return reloc_map[i].reloc;
4888}
f17c130b 4889#endif
a737bd4d 4890
b99bd4ef
NC
4891/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4892 Expects inst.instruction is set for BLX(1).
4893 Note: this is cloned from do_branch, and the reloc changed to be a
4894 new one that can cope with setting one extra bit (the H bit). */
4895
4896static void
a737bd4d 4897do_branch25 (char * str)
b99bd4ef
NC
4898{
4899 if (my_get_expression (& inst.reloc.exp, & str))
4900 return;
4901
4902#ifdef OBJ_ELF
4903 {
4904 char * save_in;
4905
4906 /* ScottB: February 5, 1998 */
4907 /* Check to see of PLT32 reloc required for the instruction. */
4908
4909 /* arm_parse_reloc() works on input_line_pointer.
4910 We actually want to parse the operands to the branch instruction
4911 passed in 'str'. Save the input pointer and restore it later. */
4912 save_in = input_line_pointer;
4913 input_line_pointer = str;
4914
4915 if (inst.reloc.exp.X_op == O_symbol
4916 && *str == '('
4917 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4918 {
4919 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4920 inst.reloc.pc_rel = 0;
4921 /* Modify str to point to after parsed operands, otherwise
4922 end_of_line() will complain about the (PLT) left in str. */
4923 str = input_line_pointer;
4924 }
4925 else
4926 {
4927 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4928 inst.reloc.pc_rel = 1;
4929 }
4930
4931 input_line_pointer = save_in;
4932 }
4933#else
4934 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4935 inst.reloc.pc_rel = 1;
4936#endif /* OBJ_ELF */
4937
4938 end_of_line (str);
4939}
4940
4941/* ARM V5 branch-link-exchange instruction (argument parse)
4942 BLX <target_addr> ie BLX(1)
4943 BLX{<condition>} <Rm> ie BLX(2)
4944 Unfortunately, there are two different opcodes for this mnemonic.
4945 So, the insns[].value is not used, and the code here zaps values
4946 into inst.instruction.
4947 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4948
4949static void
a737bd4d 4950do_blx (char * str)
b99bd4ef
NC
4951{
4952 char * mystr = str;
4953 int rm;
4954
b99bd4ef
NC
4955 skip_whitespace (mystr);
4956 rm = reg_required_here (& mystr, 0);
4957
4958 /* The above may set inst.error. Ignore his opinion. */
4959 inst.error = 0;
4960
4961 if (rm != FAIL)
4962 {
4963 /* Arg is a register.
4964 Use the condition code our caller put in inst.instruction.
4965 Pass ourselves off as a BX with a funny opcode. */
4966 inst.instruction |= 0x012fff30;
f2b7cb0a 4967 do_bx (str);
b99bd4ef
NC
4968 }
4969 else
4970 {
4971 /* This must be is BLX <target address>, no condition allowed. */
4972 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4973 {
4974 inst.error = BAD_COND;
b99bd4ef 4975 return;
cc8a6dd0 4976 }
b99bd4ef
NC
4977
4978 inst.instruction = 0xfafffffe;
4979
4980 /* Process like a B/BL, but with a different reloc.
4981 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4982 do_branch25 (str);
b99bd4ef
NC
4983 }
4984}
4985
4986/* ARM V5 Thumb BLX (argument parse)
4987 BLX <target_addr> which is BLX(1)
4988 BLX <Rm> which is BLX(2)
4989 Unfortunately, there are two different opcodes for this mnemonic.
4990 So, the tinsns[].value is not used, and the code here zaps values
4991 into inst.instruction. */
4992
4993static void
a737bd4d 4994do_t_blx (char * str)
b99bd4ef
NC
4995{
4996 char * mystr = str;
4997 int rm;
4998
4999 skip_whitespace (mystr);
5000 inst.instruction = 0x4780;
5001
5002 /* Note that this call is to the ARM register recognizer. BLX(2)
5003 uses the ARM register space, not the Thumb one, so a call to
5004 thumb_reg() would be wrong. */
5005 rm = reg_required_here (& mystr, 3);
5006 inst.error = 0;
5007
5008 if (rm != FAIL)
5009 {
5010 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5011 inst.size = 2;
5012 }
5013 else
5014 {
5015 /* No ARM register. This must be BLX(1). Change the .instruction. */
5016 inst.instruction = 0xf7ffeffe;
5017 inst.size = 4;
5018
5019 if (my_get_expression (& inst.reloc.exp, & mystr))
5020 return;
5021
5022 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5023 inst.reloc.pc_rel = 1;
5024 }
5025
5026 end_of_line (mystr);
5027}
5028
5029/* ARM V5 breakpoint instruction (argument parse)
5030 BKPT <16 bit unsigned immediate>
5031 Instruction is not conditional.
5032 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5033 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5034
5035static void
a737bd4d 5036do_bkpt (char * str)
b99bd4ef
NC
5037{
5038 expressionS expr;
5039 unsigned long number;
5040
5041 skip_whitespace (str);
5042
5043 /* Allow optional leading '#'. */
5044 if (is_immediate_prefix (* str))
5045 str++;
5046
5047 memset (& expr, '\0', sizeof (expr));
5048
143c8e19
NC
5049 if (my_get_expression (& expr, & str)
5050 || (expr.X_op != O_constant
5051 /* As a convenience we allow 'bkpt' without an operand. */
5052 && expr.X_op != O_absent))
b99bd4ef 5053 {
143c8e19 5054 inst.error = _("bad expression");
b99bd4ef
NC
5055 return;
5056 }
5057
5058 number = expr.X_add_number;
5059
5060 /* Check it fits a 16 bit unsigned. */
5061 if (number != (number & 0xffff))
5062 {
5063 inst.error = _("immediate value out of range");
5064 return;
5065 }
5066
5067 /* Top 12 of 16 bits to bits 19:8. */
5068 inst.instruction |= (number & 0xfff0) << 4;
5069
5070 /* Bottom 4 of 16 bits to bits 3:0. */
5071 inst.instruction |= number & 0xf;
5072
5073 end_of_line (str);
b99bd4ef
NC
5074}
5075
09d92015
MM
5076/* THUMB CPS instruction (argument parse). */
5077
5078static void
a737bd4d 5079do_t_cps (char * str)
09d92015
MM
5080{
5081 do_cps_flags (&str, /*thumb_p=*/1);
5082 end_of_line (str);
5083}
5084
a737bd4d
NC
5085/* Parse and validate that a register is of the right form, this saves
5086 repeated checking of this information in many similar cases.
5087 Unlike the 32-bit case we do not insert the register into the opcode
5088 here, since the position is often unknown until the full instruction
5089 has been parsed. */
5090
5091static int
5092thumb_reg (char ** strp, int hi_lo)
5093{
5094 int reg;
5095
5096 if ((reg = reg_required_here (strp, -1)) == FAIL)
5097 return FAIL;
5098
5099 switch (hi_lo)
5100 {
5101 case THUMB_REG_LO:
5102 if (reg > 7)
5103 {
5104 inst.error = _("lo register required");
5105 return FAIL;
5106 }
5107 break;
5108
5109 case THUMB_REG_HI:
5110 if (reg < 8)
5111 {
5112 inst.error = _("hi register required");
5113 return FAIL;
5114 }
5115 break;
5116
5117 default:
5118 break;
5119 }
5120
5121 return reg;
5122}
5123
5124static void
5125thumb_mov_compare (char * str, int move)
5126{
5127 int Rd, Rs = FAIL;
5128
5129 skip_whitespace (str);
5130
5131 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5132 || skip_past_comma (&str) == FAIL)
5133 {
5134 if (! inst.error)
5135 inst.error = BAD_ARGS;
5136 return;
5137 }
5138
5139 if (move != THUMB_CPY && is_immediate_prefix (*str))
5140 {
5141 str++;
5142 if (my_get_expression (&inst.reloc.exp, &str))
5143 return;
5144 }
5145 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5146 return;
5147
5148 if (Rs != FAIL)
5149 {
5150 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5151 {
5152 if (move == THUMB_MOVE)
5153 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5154 since a MOV instruction produces unpredictable results. */
5155 inst.instruction = T_OPCODE_ADD_I3;
5156 else
5157 inst.instruction = T_OPCODE_CMP_LR;
5158 inst.instruction |= Rd | (Rs << 3);
5159 }
5160 else
5161 {
5162 if (move == THUMB_MOVE)
5163 inst.instruction = T_OPCODE_MOV_HR;
5164 else if (move != THUMB_CPY)
5165 inst.instruction = T_OPCODE_CMP_HR;
5166
5167 if (Rd > 7)
5168 inst.instruction |= THUMB_H1;
5169
5170 if (Rs > 7)
5171 inst.instruction |= THUMB_H2;
5172
5173 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5174 }
5175 }
5176 else
5177 {
5178 if (Rd > 7)
5179 {
5180 inst.error = _("only lo regs allowed with immediate");
5181 return;
5182 }
5183
5184 if (move == THUMB_MOVE)
5185 inst.instruction = T_OPCODE_MOV_I8;
5186 else
5187 inst.instruction = T_OPCODE_CMP_I8;
5188
5189 inst.instruction |= Rd << 8;
5190
5191 if (inst.reloc.exp.X_op != O_constant)
5192 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5193 else
5194 {
5195 unsigned value = inst.reloc.exp.X_add_number;
5196
5197 if (value > 255)
5198 {
5199 inst.error = _("invalid immediate");
5200 return;
5201 }
5202
5203 inst.instruction |= value;
5204 }
5205 }
5206
5207 end_of_line (str);
5208}
5209
09d92015
MM
5210/* THUMB CPY instruction (argument parse). */
5211
5212static void
a737bd4d 5213do_t_cpy (char * str)
09d92015
MM
5214{
5215 thumb_mov_compare (str, THUMB_CPY);
5216}
5217
5218/* THUMB SETEND instruction (argument parse). */
5219
5220static void
a737bd4d 5221do_t_setend (char * str)
09d92015
MM
5222{
5223 if (do_endian_specifier (str))
5224 inst.instruction |= 0x8;
5225}
5226
e16bb312
NC
5227/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5228
5229static unsigned long
a737bd4d
NC
5230check_iwmmxt_insn (char * str,
5231 enum iwmmxt_insn_type insn_type,
5232 int immediate_size)
e16bb312
NC
5233{
5234 int reg = 0;
5235 const char * inst_error;
5236 expressionS expr;
5237 unsigned long number;
5238
5239 inst_error = inst.error;
5240 if (!inst.error)
5241 inst.error = BAD_ARGS;
5242 skip_whitespace (str);
5243
5244 switch (insn_type)
5245 {
5246 case check_rd:
5247 if ((reg = reg_required_here (&str, 12)) == FAIL)
5248 return FAIL;
5249 break;
a737bd4d 5250
e16bb312
NC
5251 case check_wr:
5252 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5253 return FAIL;
5254 break;
a737bd4d 5255
e16bb312
NC
5256 case check_wrwr:
5257 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5258 || skip_past_comma (&str) == FAIL
5259 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5260 return FAIL;
5261 break;
a737bd4d 5262
e16bb312
NC
5263 case check_wrwrwr:
5264 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5265 || skip_past_comma (&str) == FAIL
5266 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5267 || skip_past_comma (&str) == FAIL
5268 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5269 return FAIL;
5270 break;
a737bd4d 5271
e16bb312
NC
5272 case check_wrwrwcg:
5273 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5274 || skip_past_comma (&str) == FAIL
5275 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5276 || skip_past_comma (&str) == FAIL
5277 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5278 return FAIL;
5279 break;
a737bd4d 5280
e16bb312
NC
5281 case check_tbcst:
5282 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5283 || skip_past_comma (&str) == FAIL
5284 || reg_required_here (&str, 12) == FAIL))
5285 return FAIL;
5286 break;
a737bd4d 5287
e16bb312
NC
5288 case check_tmovmsk:
5289 if ((reg_required_here (&str, 12) == FAIL
5290 || skip_past_comma (&str) == FAIL
5291 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5292 return FAIL;
5293 break;
a737bd4d 5294
e16bb312
NC
5295 case check_tmia:
5296 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5297 || skip_past_comma (&str) == FAIL
5298 || reg_required_here (&str, 0) == FAIL
5299 || skip_past_comma (&str) == FAIL
5300 || reg_required_here (&str, 12) == FAIL))
5301 return FAIL;
5302 break;
a737bd4d 5303
e16bb312
NC
5304 case check_tmcrr:
5305 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5306 || skip_past_comma (&str) == FAIL
5307 || reg_required_here (&str, 12) == FAIL
5308 || skip_past_comma (&str) == FAIL
5309 || reg_required_here (&str, 16) == FAIL))
5310 return FAIL;
5311 break;
a737bd4d 5312
e16bb312
NC
5313 case check_tmrrc:
5314 if ((reg_required_here (&str, 12) == FAIL
5315 || skip_past_comma (&str) == FAIL
5316 || reg_required_here (&str, 16) == FAIL
5317 || skip_past_comma (&str) == FAIL
5318 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5319 return FAIL;
5320 break;
a737bd4d 5321
e16bb312
NC
5322 case check_tmcr:
5323 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5324 || skip_past_comma (&str) == FAIL
5325 || reg_required_here (&str, 12) == FAIL))
5326 return FAIL;
5327 break;
a737bd4d 5328
e16bb312
NC
5329 case check_tmrc:
5330 if ((reg_required_here (&str, 12) == FAIL
5331 || skip_past_comma (&str) == FAIL
5332 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5333 return FAIL;
5334 break;
a737bd4d 5335
e16bb312
NC
5336 case check_tinsr:
5337 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5338 || skip_past_comma (&str) == FAIL
5339 || reg_required_here (&str, 12) == FAIL
5340 || skip_past_comma (&str) == FAIL))
5341 return FAIL;
5342 break;
a737bd4d 5343
e16bb312
NC
5344 case check_textrc:
5345 if ((reg_required_here (&str, 12) == FAIL
5346 || skip_past_comma (&str) == FAIL))
5347 return FAIL;
5348 break;
a737bd4d 5349
e16bb312
NC
5350 case check_waligni:
5351 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5352 || skip_past_comma (&str) == FAIL
5353 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5354 || skip_past_comma (&str) == FAIL
5355 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5356 || skip_past_comma (&str) == FAIL))
5357 return FAIL;
5358 break;
a737bd4d 5359
e16bb312
NC
5360 case check_textrm:
5361 if ((reg_required_here (&str, 12) == FAIL
5362 || skip_past_comma (&str) == FAIL
5363 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5364 || skip_past_comma (&str) == FAIL))
5365 return FAIL;
5366 break;
a737bd4d 5367
e16bb312
NC
5368 case check_wshufh:
5369 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5370 || skip_past_comma (&str) == FAIL
5371 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5372 || skip_past_comma (&str) == FAIL))
5373 return FAIL;
5374 break;
5375 }
a737bd4d 5376
e16bb312
NC
5377 if (immediate_size == 0)
5378 {
5379 end_of_line (str);
5380 inst.error = inst_error;
5381 return reg;
5382 }
5383 else
5384 {
a737bd4d
NC
5385 skip_whitespace (str);
5386
5387 /* Allow optional leading '#'. */
e16bb312
NC
5388 if (is_immediate_prefix (* str))
5389 str++;
5390
5391 memset (& expr, '\0', sizeof (expr));
a737bd4d 5392
e16bb312
NC
5393 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5394 {
5395 inst.error = _("bad or missing expression");
5396 return FAIL;
5397 }
a737bd4d 5398
e16bb312 5399 number = expr.X_add_number;
a737bd4d 5400
e16bb312
NC
5401 if (number != (number & immediate_size))
5402 {
5403 inst.error = _("immediate value out of range");
5404 return FAIL;
5405 }
5406 end_of_line (str);
5407 inst.error = inst_error;
5408 return number;
5409 }
5410}
5411
5412static void
a737bd4d 5413do_iwmmxt_byte_addr (char * str)
e16bb312
NC
5414{
5415 int op = (inst.instruction & 0x300) >> 8;
5416 int reg;
5417
5418 inst.instruction &= ~0x300;
a737bd4d 5419 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5420
5421 skip_whitespace (str);
5422
5423 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5424 || skip_past_comma (& str) == FAIL
5425 || cp_byte_address_required_here (&str) == FAIL)
5426 {
5427 if (! inst.error)
5428 inst.error = BAD_ARGS;
5429 }
5430 else
5431 end_of_line (str);
5432
5433 if (wc_register (reg))
5434 {
ece01a63 5435 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5436 inst.instruction |= 0xf0000100;
5437 inst.instruction &= ~0x00400000;
5438 }
5439}
5440
5441static void
a737bd4d 5442do_iwmmxt_tandc (char * str)
e16bb312
NC
5443{
5444 int reg;
5445
5446 reg = check_iwmmxt_insn (str, check_rd, 0);
5447
5448 if (reg != REG_PC && !inst.error)
5449 inst.error = _("only r15 allowed here");
e16bb312
NC
5450}
5451
5452static void
a737bd4d 5453do_iwmmxt_tbcst (char * str)
e16bb312
NC
5454{
5455 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
5456}
5457
5458static void
a737bd4d 5459do_iwmmxt_textrc (char * str)
e16bb312
NC
5460{
5461 unsigned long number;
5462
5463 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5464 return;
5465
5466 inst.instruction |= number & 0x7;
e16bb312
NC
5467}
5468
5469static void
a737bd4d 5470do_iwmmxt_textrm (char * str)
e16bb312
NC
5471{
5472 unsigned long number;
5473
5474 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5475 return;
5476
5477 inst.instruction |= number & 0x7;
5478}
5479
5480static void
a737bd4d 5481do_iwmmxt_tinsr (char * str)
e16bb312
NC
5482{
5483 unsigned long number;
5484
5485 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5486 return;
5487
5488 inst.instruction |= number & 0x7;
e16bb312
NC
5489}
5490
5491static void
a737bd4d 5492do_iwmmxt_tmcr (char * str)
e16bb312
NC
5493{
5494 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
5495}
5496
5497static void
a737bd4d 5498do_iwmmxt_tmcrr (char * str)
e16bb312
NC
5499{
5500 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
5501}
5502
5503static void
a737bd4d 5504do_iwmmxt_tmia (char * str)
e16bb312
NC
5505{
5506 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
5507}
5508
5509static void
a737bd4d 5510do_iwmmxt_tmovmsk (char * str)
e16bb312
NC
5511{
5512 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
5513}
5514
5515static void
a737bd4d 5516do_iwmmxt_tmrc (char * str)
e16bb312
NC
5517{
5518 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
5519}
5520
5521static void
a737bd4d 5522do_iwmmxt_tmrrc (char * str)
e16bb312
NC
5523{
5524 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
5525}
5526
5527static void
a737bd4d 5528do_iwmmxt_torc (char * str)
e16bb312
NC
5529{
5530 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
5531}
5532
5533static void
a737bd4d 5534do_iwmmxt_waligni (char * str)
e16bb312
NC
5535{
5536 unsigned long number;
5537
5538 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5539 return;
5540
5541 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
5542}
5543
5544static void
a737bd4d 5545do_iwmmxt_wmov (char * str)
e16bb312
NC
5546{
5547 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5548 return;
a737bd4d 5549
e16bb312 5550 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
5551}
5552
5553static void
a737bd4d 5554do_iwmmxt_word_addr (char * str)
e16bb312
NC
5555{
5556 int op = (inst.instruction & 0x300) >> 8;
5557 int reg;
5558
5559 inst.instruction &= ~0x300;
a737bd4d 5560 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5561
5562 skip_whitespace (str);
5563
5564 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5565 || skip_past_comma (& str) == FAIL
5566 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5567 {
5568 if (! inst.error)
5569 inst.error = BAD_ARGS;
5570 }
5571 else
5572 end_of_line (str);
5573
5574 if (wc_register (reg))
5575 {
ece01a63
ILT
5576 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5577 as_bad (_("conditional execution not supported with control register"));
5578 if (op != 2)
5579 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5580 inst.instruction |= 0xf0000100;
5581 inst.instruction &= ~0x00400000;
5582 }
5583}
5584
5585static void
a737bd4d 5586do_iwmmxt_wrwr (char * str)
e16bb312
NC
5587{
5588 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
5589}
5590
5591static void
a737bd4d 5592do_iwmmxt_wrwrwcg (char * str)
e16bb312
NC
5593{
5594 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
5595}
5596
5597static void
a737bd4d 5598do_iwmmxt_wrwrwr (char * str)
e16bb312
NC
5599{
5600 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
5601}
5602
5603static void
a737bd4d 5604do_iwmmxt_wshufh (char * str)
e16bb312
NC
5605{
5606 unsigned long number;
5607
5608 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5609 return;
5610
5611 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
5612}
5613
5614static void
a737bd4d 5615do_iwmmxt_wzero (char * str)
e16bb312
NC
5616{
5617 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5618 return;
5619
5620 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
5621}
5622
b99bd4ef
NC
5623/* Xscale multiply-accumulate (argument parse)
5624 MIAcc acc0,Rm,Rs
5625 MIAPHcc acc0,Rm,Rs
5626 MIAxycc acc0,Rm,Rs. */
5627
5628static void
a737bd4d 5629do_xsc_mia (char * str)
b99bd4ef
NC
5630{
5631 int rs;
5632 int rm;
5633
f2b7cb0a 5634 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5635 inst.error = ERR_NO_ACCUM;
5636
5637 else if (skip_past_comma (& str) == FAIL
5638 || (rm = reg_required_here (& str, 0)) == FAIL)
5639 inst.error = BAD_ARGS;
5640
5641 else if (skip_past_comma (& str) == FAIL
5642 || (rs = reg_required_here (& str, 12)) == FAIL)
5643 inst.error = BAD_ARGS;
5644
5645 /* inst.instruction has now been zapped with both rm and rs. */
5646 else if (rm == REG_PC || rs == REG_PC)
5647 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5648
5649 else
5650 end_of_line (str);
5651}
5652
5653/* Xscale move-accumulator-register (argument parse)
5654
5655 MARcc acc0,RdLo,RdHi. */
5656
5657static void
a737bd4d 5658do_xsc_mar (char * str)
b99bd4ef
NC
5659{
5660 int rdlo, rdhi;
5661
f2b7cb0a 5662 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5663 inst.error = ERR_NO_ACCUM;
5664
5665 else if (skip_past_comma (& str) == FAIL
5666 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5667 inst.error = BAD_ARGS;
5668
5669 else if (skip_past_comma (& str) == FAIL
5670 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5671 inst.error = BAD_ARGS;
5672
5673 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5674 else if (rdlo == REG_PC || rdhi == REG_PC)
5675 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5676
5677 else
5678 end_of_line (str);
5679}
5680
5681/* Xscale move-register-accumulator (argument parse)
5682
5683 MRAcc RdLo,RdHi,acc0. */
5684
5685static void
a737bd4d 5686do_xsc_mra (char * str)
b99bd4ef
NC
5687{
5688 int rdlo;
5689 int rdhi;
5690
b99bd4ef
NC
5691 skip_whitespace (str);
5692
5693 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5694 inst.error = BAD_ARGS;
5695
5696 else if (skip_past_comma (& str) == FAIL
5697 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5698 inst.error = BAD_ARGS;
5699
5700 else if (skip_past_comma (& str) == FAIL
5701 || accum0_required_here (& str) == FAIL)
5702 inst.error = ERR_NO_ACCUM;
5703
a737bd4d
NC
5704 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5705 else if (rdlo == rdhi)
5706 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5707
5708 else if (rdlo == REG_PC || rdhi == REG_PC)
5709 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5710 else
5711 end_of_line (str);
5712}
5713
5714static int
5715ldst_extend (char ** str)
5716{
5717 int add = INDEX_UP;
5718
5719 switch (**str)
5720 {
5721 case '#':
5722 case '$':
5723 (*str)++;
5724 if (my_get_expression (& inst.reloc.exp, str))
5725 return FAIL;
5726
5727 if (inst.reloc.exp.X_op == O_constant)
5728 {
5729 int value = inst.reloc.exp.X_add_number;
5730
5731 if (value < -4095 || value > 4095)
5732 {
5733 inst.error = _("address offset too large");
5734 return FAIL;
5735 }
5736
5737 if (value < 0)
5738 {
5739 value = -value;
5740 add = 0;
5741 }
5742
5743 inst.instruction |= add | value;
5744 }
5745 else
5746 {
5747 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5748 inst.reloc.pc_rel = 0;
5749 }
5750 return SUCCESS;
5751
5752 case '-':
5753 add = 0;
5754 /* Fall through. */
5755
5756 case '+':
5757 (*str)++;
5758 /* Fall through. */
5759
5760 default:
5761 if (reg_required_here (str, 0) == FAIL)
5762 return FAIL;
5763
5764 inst.instruction |= add | OFFSET_REG;
5765 if (skip_past_comma (str) == SUCCESS)
5766 return decode_shift (str, SHIFT_IMMEDIATE);
b99bd4ef 5767
a737bd4d
NC
5768 return SUCCESS;
5769 }
b99bd4ef
NC
5770}
5771
c9b604bd 5772/* ARMv5TE: Preload-Cache
b99bd4ef
NC
5773
5774 PLD <addr_mode>
5775
5776 Syntactically, like LDR with B=1, W=0, L=1. */
5777
5778static void
a737bd4d 5779do_pld (char * str)
b99bd4ef
NC
5780{
5781 int rd;
5782
b99bd4ef
NC
5783 skip_whitespace (str);
5784
5785 if (* str != '[')
5786 {
5787 inst.error = _("'[' expected after PLD mnemonic");
5788 return;
5789 }
5790
90e4755a 5791 ++str;
b99bd4ef
NC
5792 skip_whitespace (str);
5793
5794 if ((rd = reg_required_here (& str, 16)) == FAIL)
5795 return;
5796
5797 skip_whitespace (str);
5798
90e4755a 5799 if (*str == ']')
b99bd4ef
NC
5800 {
5801 /* [Rn], ... ? */
90e4755a 5802 ++str;
b99bd4ef
NC
5803 skip_whitespace (str);
5804
90e4755a
RE
5805 /* Post-indexed addressing is not allowed with PLD. */
5806 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5807 {
90e4755a
RE
5808 inst.error
5809 = _("post-indexed expression used in preload instruction");
5810 return;
b99bd4ef 5811 }
90e4755a 5812 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
5813 {
5814 inst.error = _("writeback used in preload instruction");
90e4755a 5815 ++str;
b99bd4ef
NC
5816 }
5817 else /* [Rn] */
5818 inst.instruction |= INDEX_UP | PRE_INDEX;
5819 }
5820 else /* [Rn, ...] */
5821 {
5822 if (skip_past_comma (& str) == FAIL)
5823 {
5824 inst.error = _("pre-indexed expression expected");
5825 return;
5826 }
5827
90e4755a 5828 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
5829 return;
5830
5831 skip_whitespace (str);
5832
5833 if (* str != ']')
5834 {
5835 inst.error = _("missing ]");
5836 return;
5837 }
5838
5839 ++ str;
5840 skip_whitespace (str);
5841
5842 if (* str == '!') /* [Rn]! */
5843 {
5844 inst.error = _("writeback used in preload instruction");
5845 ++ str;
5846 }
5847
5848 inst.instruction |= PRE_INDEX;
5849 }
5850
5851 end_of_line (str);
5852}
5853
c9b604bd 5854/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
5855 Mode is like LDRH.
5856
5857 LDRccD R, mode
5858 STRccD R, mode. */
5859
5860static void
a737bd4d 5861do_ldrd (char * str)
b99bd4ef
NC
5862{
5863 int rd;
5864 int rn;
5865
b99bd4ef
NC
5866 skip_whitespace (str);
5867
5868 if ((rd = reg_required_here (& str, 12)) == FAIL)
5869 {
5870 inst.error = BAD_ARGS;
5871 return;
5872 }
5873
5874 if (skip_past_comma (& str) == FAIL
5875 || (rn = ld_mode_required_here (& str)) == FAIL)
5876 {
5877 if (!inst.error)
cc8a6dd0 5878 inst.error = BAD_ARGS;
a737bd4d 5879 return;
b99bd4ef
NC
5880 }
5881
a737bd4d
NC
5882 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5883 if (rd & 1) /* Unpredictable result if Rd is odd. */
5884 {
5885 inst.error = _("destination register must be even");
5886 return;
5887 }
b99bd4ef 5888
a737bd4d 5889 if (rd == REG_LR)
b99bd4ef 5890 {
a737bd4d
NC
5891 inst.error = _("r14 not allowed here");
5892 return;
b99bd4ef 5893 }
a737bd4d
NC
5894
5895 if (((rd == rn) || (rd + 1 == rn))
5896 && ((inst.instruction & WRITE_BACK)
5897 || (!(inst.instruction & PRE_INDEX))))
5898 as_warn (_("pre/post-indexing used when modified address register is destination"));
5899
5900 /* For an index-register load, the index register must not overlap the
5901 destination (even if not write-back). */
5902 if ((inst.instruction & V4_STR_BIT) == 0
5903 && (inst.instruction & HWOFFSET_IMM) == 0)
b99bd4ef 5904 {
a737bd4d
NC
5905 int rm = inst.instruction & 0x0000000f;
5906
5907 if (rm == rd || (rm == rd + 1))
5908 as_warn (_("ldrd destination registers must not overlap index register"));
b99bd4ef
NC
5909 }
5910
a737bd4d
NC
5911 end_of_line (str);
5912}
b99bd4ef 5913
a737bd4d
NC
5914/* Returns the index into fp_values of a floating point number,
5915 or -1 if not in the table. */
b99bd4ef 5916
a737bd4d
NC
5917static int
5918my_get_float_expression (char ** str)
5919{
5920 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5921 char * save_in;
5922 expressionS exp;
5923 int i;
5924 int j;
b99bd4ef 5925
a737bd4d
NC
5926 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5927
5928 /* Look for a raw floating point number. */
5929 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5930 && is_end_of_line[(unsigned char) *save_in])
5931 {
5932 for (i = 0; i < NUM_FLOAT_VALS; i++)
b99bd4ef 5933 {
a737bd4d 5934 for (j = 0; j < MAX_LITTLENUMS; j++)
b99bd4ef 5935 {
a737bd4d
NC
5936 if (words[j] != fp_values[i][j])
5937 break;
b99bd4ef 5938 }
a737bd4d
NC
5939
5940 if (j == MAX_LITTLENUMS)
b99bd4ef 5941 {
a737bd4d
NC
5942 *str = save_in;
5943 return i;
b99bd4ef
NC
5944 }
5945 }
a737bd4d 5946 }
b99bd4ef 5947
a737bd4d
NC
5948 /* Try and parse a more complex expression, this will probably fail
5949 unless the code uses a floating point prefix (eg "0f"). */
5950 save_in = input_line_pointer;
5951 input_line_pointer = *str;
5952 if (expression (&exp) == absolute_section
5953 && exp.X_op == O_big
5954 && exp.X_add_number < 0)
5955 {
5956 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5957 Ditto for 15. */
5958 if (gen_to_words (words, 5, (long) 15) == 0)
5959 {
5960 for (i = 0; i < NUM_FLOAT_VALS; i++)
5961 {
5962 for (j = 0; j < MAX_LITTLENUMS; j++)
5963 {
5964 if (words[j] != fp_values[i][j])
5965 break;
5966 }
b99bd4ef 5967
a737bd4d
NC
5968 if (j == MAX_LITTLENUMS)
5969 {
5970 *str = input_line_pointer;
5971 input_line_pointer = save_in;
5972 return i;
5973 }
5974 }
5975 }
b99bd4ef 5976 }
a737bd4d
NC
5977
5978 *str = input_line_pointer;
5979 input_line_pointer = save_in;
5980 return -1;
5981}
5982
5983/* We handle all bad expressions here, so that we can report the faulty
5984 instruction in the error message. */
5985void
5986md_operand (expressionS * expr)
5987{
5988 if (in_my_get_expression)
b99bd4ef 5989 {
a737bd4d
NC
5990 expr->X_op = O_illegal;
5991 if (inst.error == NULL)
5992 inst.error = _("bad expression");
b99bd4ef 5993 }
b99bd4ef
NC
5994}
5995
5996/* Do those data_ops which can take a negative immediate constant
2d2255b5 5997 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
5998 MOV <-> MVN
5999 AND <-> BIC
6000 ADC <-> SBC
6001 by inverting the second operand, and
6002 ADD <-> SUB
6003 CMP <-> CMN
6004 by negating the second operand. */
6005
6006static int
a737bd4d
NC
6007negate_data_op (unsigned long * instruction,
6008 unsigned long value)
b99bd4ef
NC
6009{
6010 int op, new_inst;
6011 unsigned long negated, inverted;
6012
6013 negated = validate_immediate (-value);
6014 inverted = validate_immediate (~value);
6015
6016 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6017 switch (op)
6018 {
6019 /* First negates. */
6020 case OPCODE_SUB: /* ADD <-> SUB */
6021 new_inst = OPCODE_ADD;
6022 value = negated;
6023 break;
6024
6025 case OPCODE_ADD:
6026 new_inst = OPCODE_SUB;
6027 value = negated;
6028 break;
6029
6030 case OPCODE_CMP: /* CMP <-> CMN */
6031 new_inst = OPCODE_CMN;
6032 value = negated;
6033 break;
6034
6035 case OPCODE_CMN:
6036 new_inst = OPCODE_CMP;
6037 value = negated;
6038 break;
6039
6040 /* Now Inverted ops. */
6041 case OPCODE_MOV: /* MOV <-> MVN */
6042 new_inst = OPCODE_MVN;
6043 value = inverted;
6044 break;
6045
6046 case OPCODE_MVN:
6047 new_inst = OPCODE_MOV;
6048 value = inverted;
6049 break;
6050
6051 case OPCODE_AND: /* AND <-> BIC */
6052 new_inst = OPCODE_BIC;
6053 value = inverted;
6054 break;
6055
6056 case OPCODE_BIC:
6057 new_inst = OPCODE_AND;
6058 value = inverted;
6059 break;
6060
6061 case OPCODE_ADC: /* ADC <-> SBC */
6062 new_inst = OPCODE_SBC;
6063 value = inverted;
6064 break;
6065
6066 case OPCODE_SBC:
6067 new_inst = OPCODE_ADC;
6068 value = inverted;
6069 break;
6070
6071 /* We cannot do anything. */
6072 default:
6073 return FAIL;
6074 }
6075
6076 if (value == (unsigned) FAIL)
6077 return FAIL;
6078
6079 *instruction &= OPCODE_MASK;
6080 *instruction |= new_inst << DATA_OP_SHIFT;
6081 return value;
6082}
6083
6084static int
a737bd4d 6085data_op2 (char ** str)
b99bd4ef
NC
6086{
6087 int value;
6088 expressionS expr;
6089
6090 skip_whitespace (* str);
6091
6092 if (reg_required_here (str, 0) != FAIL)
6093 {
6094 if (skip_past_comma (str) == SUCCESS)
6095 /* Shift operation on register. */
6096 return decode_shift (str, NO_SHIFT_RESTRICT);
6097
6098 return SUCCESS;
6099 }
6100 else
6101 {
6102 /* Immediate expression. */
6103 if (is_immediate_prefix (**str))
6104 {
6105 (*str)++;
6106 inst.error = NULL;
6107
6108 if (my_get_expression (&inst.reloc.exp, str))
6109 return FAIL;
6110
6111 if (inst.reloc.exp.X_add_symbol)
6112 {
6113 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6114 inst.reloc.pc_rel = 0;
6115 }
6116 else
6117 {
6118 if (skip_past_comma (str) == SUCCESS)
6119 {
6120 /* #x, y -- ie explicit rotation by Y. */
6121 if (my_get_expression (&expr, str))
6122 return FAIL;
6123
6124 if (expr.X_op != O_constant)
6125 {
f03698e6 6126 inst.error = _("constant expression expected");
b99bd4ef
NC
6127 return FAIL;
6128 }
6129
6130 /* Rotate must be a multiple of 2. */
6131 if (((unsigned) expr.X_add_number) > 30
6132 || (expr.X_add_number & 1) != 0
6133 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6134 {
f03698e6 6135 inst.error = _("invalid constant");
b99bd4ef
NC
6136 return FAIL;
6137 }
6138 inst.instruction |= INST_IMMEDIATE;
6139 inst.instruction |= inst.reloc.exp.X_add_number;
6140 inst.instruction |= expr.X_add_number << 7;
6141 return SUCCESS;
6142 }
6143
6144 /* Implicit rotation, select a suitable one. */
6145 value = validate_immediate (inst.reloc.exp.X_add_number);
6146
6147 if (value == FAIL)
6148 {
6149 /* Can't be done. Perhaps the code reads something like
6150 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6151 if ((value = negate_data_op (&inst.instruction,
6152 inst.reloc.exp.X_add_number))
6153 == FAIL)
6154 {
f03698e6 6155 inst.error = _("invalid constant");
b99bd4ef
NC
6156 return FAIL;
6157 }
6158 }
6159
6160 inst.instruction |= value;
6161 }
6162
6163 inst.instruction |= INST_IMMEDIATE;
6164 return SUCCESS;
6165 }
6166
6167 (*str)++;
f03698e6 6168 inst.error = _("register or shift expression expected");
b99bd4ef
NC
6169 return FAIL;
6170 }
6171}
6172
6173static int
a737bd4d 6174fp_op2 (char ** str)
b99bd4ef
NC
6175{
6176 skip_whitespace (* str);
6177
6178 if (fp_reg_required_here (str, 0) != FAIL)
6179 return SUCCESS;
6180 else
6181 {
6182 /* Immediate expression. */
6183 if (*((*str)++) == '#')
6184 {
6185 int i;
6186
6187 inst.error = NULL;
6188
6189 skip_whitespace (* str);
6190
6191 /* First try and match exact strings, this is to guarantee
6192 that some formats will work even for cross assembly. */
6193
6194 for (i = 0; fp_const[i]; i++)
6195 {
6196 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6197 {
6198 char *start = *str;
6199
6200 *str += strlen (fp_const[i]);
6201 if (is_end_of_line[(unsigned char) **str])
6202 {
6203 inst.instruction |= i + 8;
6204 return SUCCESS;
6205 }
6206 *str = start;
6207 }
6208 }
6209
6210 /* Just because we didn't get a match doesn't mean that the
6211 constant isn't valid, just that it is in a format that we
6212 don't automatically recognize. Try parsing it with
6213 the standard expression routines. */
6214 if ((i = my_get_float_expression (str)) >= 0)
6215 {
6216 inst.instruction |= i + 8;
6217 return SUCCESS;
6218 }
6219
f03698e6 6220 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
6221 return FAIL;
6222 }
6223 inst.error =
f03698e6 6224 _("floating point register or immediate expression expected");
b99bd4ef
NC
6225 return FAIL;
6226 }
6227}
6228
6229static void
a737bd4d 6230do_arit (char * str)
b99bd4ef
NC
6231{
6232 skip_whitespace (str);
6233
6234 if (reg_required_here (&str, 12) == FAIL
6235 || skip_past_comma (&str) == FAIL
6236 || reg_required_here (&str, 16) == FAIL
6237 || skip_past_comma (&str) == FAIL
6238 || data_op2 (&str) == FAIL)
6239 {
6240 if (!inst.error)
6241 inst.error = BAD_ARGS;
6242 return;
6243 }
6244
b99bd4ef 6245 end_of_line (str);
b99bd4ef
NC
6246}
6247
6248static void
a737bd4d 6249do_adr (char * str)
b99bd4ef 6250{
90e4755a
RE
6251 /* This is a pseudo-op of the form "adr rd, label" to be converted
6252 into a relative address of the form "add rd, pc, #label-.-8". */
6253 skip_whitespace (str);
6254
6255 if (reg_required_here (&str, 12) == FAIL
6256 || skip_past_comma (&str) == FAIL
6257 || my_get_expression (&inst.reloc.exp, &str))
6258 {
6259 if (!inst.error)
6260 inst.error = BAD_ARGS;
6261 return;
6262 }
6263
6264 /* Frag hacking will turn this into a sub instruction if the offset turns
6265 out to be negative. */
6266 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 6267#ifndef TE_WINCE
90e4755a 6268 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 6269#endif
90e4755a
RE
6270 inst.reloc.pc_rel = 1;
6271
6272 end_of_line (str);
6273}
6274
6275static void
a737bd4d 6276do_adrl (char * str)
90e4755a
RE
6277{
6278 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6279 into a relative address of the form:
6280 add rd, pc, #low(label-.-8)"
6281 add rd, rd, #high(label-.-8)" */
6282
6283 skip_whitespace (str);
6284
6285 if (reg_required_here (&str, 12) == FAIL
6286 || skip_past_comma (&str) == FAIL
6287 || my_get_expression (&inst.reloc.exp, &str))
6288 {
6289 if (!inst.error)
6290 inst.error = BAD_ARGS;
6291
6292 return;
6293 }
6294
6295 end_of_line (str);
6296 /* Frag hacking will turn this into a sub instruction if the offset turns
6297 out to be negative. */
6298 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
a737bd4d 6299#ifndef TE_WINCE
90e4755a 6300 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 6301#endif
90e4755a
RE
6302 inst.reloc.pc_rel = 1;
6303 inst.size = INSN_SIZE * 2;
90e4755a
RE
6304}
6305
6306static void
a737bd4d 6307do_cmp (char * str)
90e4755a
RE
6308{
6309 skip_whitespace (str);
6310
6311 if (reg_required_here (&str, 16) == FAIL)
6312 {
6313 if (!inst.error)
6314 inst.error = BAD_ARGS;
6315 return;
6316 }
6317
6318 if (skip_past_comma (&str) == FAIL
6319 || data_op2 (&str) == FAIL)
6320 {
6321 if (!inst.error)
6322 inst.error = BAD_ARGS;
6323 return;
6324 }
6325
90e4755a 6326 end_of_line (str);
90e4755a
RE
6327}
6328
6329static void
a737bd4d 6330do_mov (char * str)
90e4755a
RE
6331{
6332 skip_whitespace (str);
6333
6334 if (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 || data_op2 (&str) == FAIL)
6343 {
6344 if (!inst.error)
6345 inst.error = BAD_ARGS;
6346 return;
6347 }
6348
90e4755a 6349 end_of_line (str);
90e4755a
RE
6350}
6351
90e4755a 6352static void
a737bd4d 6353do_ldst (char * str)
90e4755a
RE
6354{
6355 int pre_inc = 0;
6356 int conflict_reg;
6357 int value;
6358
b99bd4ef
NC
6359 skip_whitespace (str);
6360
90e4755a
RE
6361 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6362 {
6363 if (!inst.error)
6364 inst.error = BAD_ARGS;
6365 return;
6366 }
6367
6368 if (skip_past_comma (&str) == FAIL)
6369 {
f03698e6 6370 inst.error = _("address expected");
90e4755a
RE
6371 return;
6372 }
6373
90e4755a
RE
6374 if (*str == '[')
6375 {
6376 int reg;
6377
6378 str++;
6379
6380 skip_whitespace (str);
6381
6382 if ((reg = reg_required_here (&str, 16)) == FAIL)
6383 return;
6384
6385 /* Conflicts can occur on stores as well as loads. */
6386 conflict_reg = (conflict_reg == reg);
6387
6388 skip_whitespace (str);
6389
6390 if (*str == ']')
6391 {
6392 str ++;
6393
6394 if (skip_past_comma (&str) == SUCCESS)
6395 {
6396 /* [Rn],... (post inc) */
6397 if (ldst_extend (&str) == FAIL)
6398 return;
6399 if (conflict_reg)
6400 as_warn (_("%s register same as write-back base"),
6401 ((inst.instruction & LOAD_BIT)
6402 ? _("destination") : _("source")));
6403 }
6404 else
6405 {
6406 /* [Rn] */
6407 skip_whitespace (str);
6408
6409 if (*str == '!')
6410 {
6411 if (conflict_reg)
6412 as_warn (_("%s register same as write-back base"),
6413 ((inst.instruction & LOAD_BIT)
6414 ? _("destination") : _("source")));
6415 str++;
6416 inst.instruction |= WRITE_BACK;
6417 }
6418
6419 inst.instruction |= INDEX_UP;
6420 pre_inc = 1;
6421 }
6422 }
6423 else
6424 {
6425 /* [Rn,...] */
6426 if (skip_past_comma (&str) == FAIL)
6427 {
6428 inst.error = _("pre-indexed expression expected");
6429 return;
6430 }
6431
6432 pre_inc = 1;
6433 if (ldst_extend (&str) == FAIL)
6434 return;
6435
6436 skip_whitespace (str);
6437
6438 if (*str++ != ']')
6439 {
6440 inst.error = _("missing ]");
6441 return;
6442 }
6443
6444 skip_whitespace (str);
6445
6446 if (*str == '!')
6447 {
6448 if (conflict_reg)
6449 as_warn (_("%s register same as write-back base"),
6450 ((inst.instruction & LOAD_BIT)
6451 ? _("destination") : _("source")));
6452 str++;
6453 inst.instruction |= WRITE_BACK;
6454 }
6455 }
6456 }
6457 else if (*str == '=')
6458 {
f03698e6
RE
6459 if ((inst.instruction & LOAD_BIT) == 0)
6460 {
6461 inst.error = _("invalid pseudo operation");
6462 return;
6463 }
6464
90e4755a
RE
6465 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6466 str++;
6467
6468 skip_whitespace (str);
6469
6470 if (my_get_expression (&inst.reloc.exp, &str))
6471 return;
6472
6473 if (inst.reloc.exp.X_op != O_constant
6474 && inst.reloc.exp.X_op != O_symbol)
6475 {
f03698e6 6476 inst.error = _("constant expression expected");
90e4755a
RE
6477 return;
6478 }
6479
e28cd48c 6480 if (inst.reloc.exp.X_op == O_constant)
90e4755a 6481 {
e28cd48c
RE
6482 value = validate_immediate (inst.reloc.exp.X_add_number);
6483
6484 if (value != FAIL)
90e4755a 6485 {
e28cd48c
RE
6486 /* This can be done with a mov instruction. */
6487 inst.instruction &= LITERAL_MASK;
6488 inst.instruction |= (INST_IMMEDIATE
6489 | (OPCODE_MOV << DATA_OP_SHIFT));
6490 inst.instruction |= value & 0xfff;
6491 end_of_line (str);
90e4755a
RE
6492 return;
6493 }
b99bd4ef 6494
e28cd48c
RE
6495 value = validate_immediate (~inst.reloc.exp.X_add_number);
6496
6497 if (value != FAIL)
6498 {
6499 /* This can be done with a mvn instruction. */
6500 inst.instruction &= LITERAL_MASK;
6501 inst.instruction |= (INST_IMMEDIATE
6502 | (OPCODE_MVN << DATA_OP_SHIFT));
6503 inst.instruction |= value & 0xfff;
6504 end_of_line (str);
6505 return;
6506 }
90e4755a 6507 }
e28cd48c
RE
6508
6509 /* Insert into literal pool. */
6510 if (add_to_lit_pool () == FAIL)
6511 {
6512 if (!inst.error)
6513 inst.error = _("literal pool insertion failed");
6514 return;
6515 }
6516
6517 /* Change the instruction exp to point to the pool. */
6518 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6519 inst.reloc.pc_rel = 1;
6520 inst.instruction |= (REG_PC << 16);
6521 pre_inc = 1;
1cac9012
NC
6522 }
6523 else
6524 {
90e4755a
RE
6525 if (my_get_expression (&inst.reloc.exp, &str))
6526 return;
6527
6528 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6529#ifndef TE_WINCE
6530 /* PC rel adjust. */
6531 inst.reloc.exp.X_add_number -= 8;
6532#endif
1cac9012 6533 inst.reloc.pc_rel = 1;
90e4755a
RE
6534 inst.instruction |= (REG_PC << 16);
6535 pre_inc = 1;
b99bd4ef
NC
6536 }
6537
90e4755a 6538 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6539 end_of_line (str);
b99bd4ef
NC
6540}
6541
6542static void
a737bd4d 6543do_ldstt (char * str)
b99bd4ef 6544{
90e4755a
RE
6545 int conflict_reg;
6546
b99bd4ef
NC
6547 skip_whitespace (str);
6548
90e4755a 6549 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
6550 {
6551 if (!inst.error)
6552 inst.error = BAD_ARGS;
6553 return;
6554 }
6555
90e4755a 6556 if (skip_past_comma (& str) == FAIL)
b99bd4ef 6557 {
f03698e6 6558 inst.error = _("address expected");
b99bd4ef
NC
6559 return;
6560 }
6561
90e4755a
RE
6562 if (*str == '[')
6563 {
6564 int reg;
b99bd4ef 6565
90e4755a 6566 str++;
b99bd4ef 6567
90e4755a 6568 skip_whitespace (str);
b99bd4ef 6569
90e4755a
RE
6570 if ((reg = reg_required_here (&str, 16)) == FAIL)
6571 return;
b99bd4ef 6572
90e4755a
RE
6573 /* ldrt/strt always use post-indexed addressing, so if the base is
6574 the same as Rd, we warn. */
6575 if (conflict_reg == reg)
6576 as_warn (_("%s register same as write-back base"),
6577 ((inst.instruction & LOAD_BIT)
6578 ? _("destination") : _("source")));
6579
6580 skip_whitespace (str);
6581
6582 if (*str == ']')
6583 {
6584 str ++;
6585
6586 if (skip_past_comma (&str) == SUCCESS)
6587 {
6588 /* [Rn],... (post inc) */
6589 if (ldst_extend (&str) == FAIL)
6590 return;
6591 }
6592 else
6593 {
6594 /* [Rn] */
6595 skip_whitespace (str);
6596
6597 /* Skip a write-back '!'. */
6598 if (*str == '!')
6599 str++;
6600
6601 inst.instruction |= INDEX_UP;
6602 }
6603 }
6604 else
6605 {
6606 inst.error = _("post-indexed expression expected");
6607 return;
6608 }
6609 }
6610 else
b99bd4ef 6611 {
90e4755a 6612 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
6613 return;
6614 }
6615
b99bd4ef 6616 end_of_line (str);
b99bd4ef
NC
6617}
6618
90e4755a 6619/* Halfword and signed-byte load/store operations. */
a737bd4d 6620
b99bd4ef 6621static void
a737bd4d 6622do_ldstv4 (char * str)
b99bd4ef 6623{
b99bd4ef
NC
6624 int pre_inc = 0;
6625 int conflict_reg;
6626 int value;
6627
b99bd4ef
NC
6628 skip_whitespace (str);
6629
6630 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6631 {
6632 if (!inst.error)
6633 inst.error = BAD_ARGS;
6634 return;
6635 }
6636
6637 if (skip_past_comma (& str) == FAIL)
6638 {
f03698e6 6639 inst.error = _("address expected");
b99bd4ef
NC
6640 return;
6641 }
6642
6643 if (*str == '[')
6644 {
6645 int reg;
6646
6647 str++;
6648
6649 skip_whitespace (str);
6650
6651 if ((reg = reg_required_here (&str, 16)) == FAIL)
6652 return;
6653
6654 /* Conflicts can occur on stores as well as loads. */
6655 conflict_reg = (conflict_reg == reg);
6656
6657 skip_whitespace (str);
6658
6659 if (*str == ']')
6660 {
6661 str ++;
6662
6663 if (skip_past_comma (&str) == SUCCESS)
6664 {
6665 /* [Rn],... (post inc) */
90e4755a 6666 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6667 return;
6668 if (conflict_reg)
90e4755a
RE
6669 as_warn (_("%s register same as write-back base"),
6670 ((inst.instruction & LOAD_BIT)
6671 ? _("destination") : _("source")));
b99bd4ef
NC
6672 }
6673 else
6674 {
6675 /* [Rn] */
90e4755a 6676 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
6677
6678 skip_whitespace (str);
6679
6680 if (*str == '!')
6681 {
6682 if (conflict_reg)
6683 as_warn (_("%s register same as write-back base"),
6684 ((inst.instruction & LOAD_BIT)
6685 ? _("destination") : _("source")));
6686 str++;
6687 inst.instruction |= WRITE_BACK;
6688 }
6689
90e4755a
RE
6690 inst.instruction |= INDEX_UP;
6691 pre_inc = 1;
b99bd4ef
NC
6692 }
6693 }
6694 else
6695 {
6696 /* [Rn,...] */
6697 if (skip_past_comma (&str) == FAIL)
6698 {
6699 inst.error = _("pre-indexed expression expected");
6700 return;
6701 }
6702
6703 pre_inc = 1;
90e4755a 6704 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6705 return;
6706
6707 skip_whitespace (str);
6708
6709 if (*str++ != ']')
6710 {
6711 inst.error = _("missing ]");
6712 return;
6713 }
6714
6715 skip_whitespace (str);
6716
6717 if (*str == '!')
6718 {
6719 if (conflict_reg)
6720 as_warn (_("%s register same as write-back base"),
6721 ((inst.instruction & LOAD_BIT)
6722 ? _("destination") : _("source")));
6723 str++;
6724 inst.instruction |= WRITE_BACK;
6725 }
6726 }
6727 }
6728 else if (*str == '=')
6729 {
f03698e6
RE
6730 if ((inst.instruction & LOAD_BIT) == 0)
6731 {
6732 inst.error = _("invalid pseudo operation");
6733 return;
6734 }
6735
90e4755a 6736 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
6737 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6738 str++;
6739
6740 skip_whitespace (str);
6741
6742 if (my_get_expression (&inst.reloc.exp, &str))
6743 return;
6744
6745 if (inst.reloc.exp.X_op != O_constant
6746 && inst.reloc.exp.X_op != O_symbol)
6747 {
f03698e6 6748 inst.error = _("constant expression expected");
b99bd4ef
NC
6749 return;
6750 }
6751
d8273442 6752 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 6753 {
d8273442
NC
6754 value = validate_immediate (inst.reloc.exp.X_add_number);
6755
6756 if (value != FAIL)
b99bd4ef 6757 {
d8273442
NC
6758 /* This can be done with a mov instruction. */
6759 inst.instruction &= LITERAL_MASK;
6760 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 6761 inst.instruction |= value & 0xfff;
d8273442 6762 end_of_line (str);
b99bd4ef
NC
6763 return;
6764 }
cc8a6dd0 6765
d8273442 6766 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 6767
d8273442 6768 if (value != FAIL)
b99bd4ef 6769 {
d8273442
NC
6770 /* This can be done with a mvn instruction. */
6771 inst.instruction &= LITERAL_MASK;
6772 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 6773 inst.instruction |= value & 0xfff;
d8273442
NC
6774 end_of_line (str);
6775 return;
b99bd4ef 6776 }
b99bd4ef 6777 }
d8273442
NC
6778
6779 /* Insert into literal pool. */
6780 if (add_to_lit_pool () == FAIL)
6781 {
6782 if (!inst.error)
6783 inst.error = _("literal pool insertion failed");
6784 return;
6785 }
6786
6787 /* Change the instruction exp to point to the pool. */
90e4755a
RE
6788 inst.instruction |= HWOFFSET_IMM;
6789 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
6790 inst.reloc.pc_rel = 1;
6791 inst.instruction |= (REG_PC << 16);
6792 pre_inc = 1;
b99bd4ef
NC
6793 }
6794 else
6795 {
6796 if (my_get_expression (&inst.reloc.exp, &str))
6797 return;
6798
90e4755a
RE
6799 inst.instruction |= HWOFFSET_IMM;
6800 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
6801#ifndef TE_WINCE
6802 /* PC rel adjust. */
6803 inst.reloc.exp.X_add_number -= 8;
6804#endif
6805 inst.reloc.pc_rel = 1;
6806 inst.instruction |= (REG_PC << 16);
6807 pre_inc = 1;
6808 }
6809
90e4755a 6810 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6811 end_of_line (str);
b99bd4ef
NC
6812}
6813
b05fe5cf
ZW
6814static void
6815do_ldsttv4 (char * str)
6816{
6817 int conflict_reg;
6818
6819 skip_whitespace (str);
6820
6821 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6822 {
6823 if (!inst.error)
6824 inst.error = BAD_ARGS;
6825 return;
6826 }
6827
6828 if (skip_past_comma (& str) == FAIL)
6829 {
6830 inst.error = _("address expected");
6831 return;
6832 }
6833
6834 if (*str == '[')
6835 {
6836 int reg;
6837
6838 str++;
6839
6840 skip_whitespace (str);
6841
6842 if ((reg = reg_required_here (&str, 16)) == FAIL)
6843 return;
6844
6845 /* ldrt/strt always use post-indexed addressing, so if the base is
6846 the same as Rd, we warn. */
6847 if (conflict_reg == reg)
6848 as_warn (_("%s register same as write-back base"),
6849 ((inst.instruction & LOAD_BIT)
6850 ? _("destination") : _("source")));
6851
6852 skip_whitespace (str);
6853
6854 if (*str == ']')
6855 {
6856 str ++;
6857
6858 if (skip_past_comma (&str) == SUCCESS)
6859 {
6860 /* [Rn],... (post inc) */
6861 if (ldst_extend_v4 (&str) == FAIL)
6862 return;
6863 }
6864 else
6865 {
6866 /* [Rn] */
6867 skip_whitespace (str);
6868
6869 /* Skip a write-back '!'. */
6870 if (*str == '!')
6871 str++;
6872
6873 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6874 }
6875 }
6876 else
6877 {
6878 inst.error = _("post-indexed expression expected");
6879 return;
6880 }
6881 }
6882 else
6883 {
6884 inst.error = _("post-indexed expression expected");
6885 return;
6886 }
6887
6888 end_of_line (str);
6889}
6890
6891
b99bd4ef 6892static long
a737bd4d 6893reg_list (char ** strp)
b99bd4ef
NC
6894{
6895 char * str = * strp;
6896 long range = 0;
6897 int another_range;
6898
6899 /* We come back here if we get ranges concatenated by '+' or '|'. */
6900 do
6901 {
6902 another_range = 0;
6903
6904 if (*str == '{')
6905 {
6906 int in_range = 0;
6907 int cur_reg = -1;
6908
6909 str++;
6910 do
6911 {
6912 int reg;
6913
6914 skip_whitespace (str);
6915
6916 if ((reg = reg_required_here (& str, -1)) == FAIL)
6917 return FAIL;
6918
6919 if (in_range)
6920 {
6921 int i;
6922
6923 if (reg <= cur_reg)
6924 {
f03698e6 6925 inst.error = _("bad range in register list");
b99bd4ef
NC
6926 return FAIL;
6927 }
6928
6929 for (i = cur_reg + 1; i < reg; i++)
6930 {
6931 if (range & (1 << i))
6932 as_tsktsk
f03698e6 6933 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6934 i);
6935 else
6936 range |= 1 << i;
6937 }
6938 in_range = 0;
6939 }
6940
6941 if (range & (1 << reg))
f03698e6 6942 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6943 reg);
6944 else if (reg <= cur_reg)
f03698e6 6945 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
6946
6947 range |= 1 << reg;
6948 cur_reg = reg;
6949 }
6950 while (skip_past_comma (&str) != FAIL
6951 || (in_range = 1, *str++ == '-'));
6952 str--;
6953 skip_whitespace (str);
6954
6955 if (*str++ != '}')
6956 {
f03698e6 6957 inst.error = _("missing `}'");
b99bd4ef
NC
6958 return FAIL;
6959 }
6960 }
6961 else
6962 {
6963 expressionS expr;
6964
6965 if (my_get_expression (&expr, &str))
6966 return FAIL;
6967
6968 if (expr.X_op == O_constant)
6969 {
6970 if (expr.X_add_number
6971 != (expr.X_add_number & 0x0000ffff))
6972 {
6973 inst.error = _("invalid register mask");
6974 return FAIL;
6975 }
6976
6977 if ((range & expr.X_add_number) != 0)
6978 {
6979 int regno = range & expr.X_add_number;
6980
6981 regno &= -regno;
6982 regno = (1 << regno) - 1;
6983 as_tsktsk
f03698e6 6984 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6985 regno);
6986 }
6987
6988 range |= expr.X_add_number;
6989 }
6990 else
6991 {
6992 if (inst.reloc.type != 0)
6993 {
6994 inst.error = _("expression too complex");
6995 return FAIL;
6996 }
6997
6998 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6999 inst.reloc.type = BFD_RELOC_ARM_MULTI;
7000 inst.reloc.pc_rel = 0;
7001 }
7002 }
7003
7004 skip_whitespace (str);
7005
7006 if (*str == '|' || *str == '+')
7007 {
7008 str++;
7009 another_range = 1;
7010 }
7011 }
7012 while (another_range);
7013
7014 *strp = str;
7015 return range;
7016}
7017
7018static void
a737bd4d 7019do_ldmstm (char * str)
b99bd4ef
NC
7020{
7021 int base_reg;
7022 long range;
7023
7024 skip_whitespace (str);
7025
7026 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
7027 return;
7028
7029 if (base_reg == REG_PC)
7030 {
7031 inst.error = _("r15 not allowed as base register");
7032 return;
7033 }
7034
7035 skip_whitespace (str);
7036
7037 if (*str == '!')
7038 {
90e4755a 7039 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
7040 str++;
7041 }
7042
7043 if (skip_past_comma (&str) == FAIL
7044 || (range = reg_list (&str)) == FAIL)
7045 {
7046 if (! inst.error)
7047 inst.error = BAD_ARGS;
7048 return;
7049 }
7050
7051 if (*str == '^')
7052 {
7053 str++;
90e4755a 7054 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
7055 }
7056
6189168b
NC
7057 if (inst.instruction & WRITE_BACK)
7058 {
7059 /* Check for unpredictable uses of writeback. */
7060 if (inst.instruction & LOAD_BIT)
7061 {
7062 /* Not allowed in LDM type 2. */
7063 if ((inst.instruction & LDM_TYPE_2_OR_3)
7064 && ((range & (1 << REG_PC)) == 0))
7065 as_warn (_("writeback of base register is UNPREDICTABLE"));
7066 /* Only allowed if base reg not in list for other types. */
7067 else if (range & (1 << base_reg))
7068 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7069 }
7070 else /* STM. */
7071 {
7072 /* Not allowed for type 2. */
7073 if (inst.instruction & LDM_TYPE_2_OR_3)
7074 as_warn (_("writeback of base register is UNPREDICTABLE"));
7075 /* Only allowed if base reg not in list, or first in list. */
7076 else if ((range & (1 << base_reg))
7077 && (range & ((1 << base_reg) - 1)))
7078 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7079 }
7080 }
61b5f74b 7081
f2b7cb0a 7082 inst.instruction |= range;
b99bd4ef 7083 end_of_line (str);
b99bd4ef
NC
7084}
7085
0dd132b6
NC
7086static void
7087do_smi (char * str)
7088{
7089 skip_whitespace (str);
7090
7091 /* Allow optional leading '#'. */
7092 if (is_immediate_prefix (*str))
7093 str++;
7094
7095 if (my_get_expression (& inst.reloc.exp, & str))
7096 return;
7097
7098 inst.reloc.type = BFD_RELOC_ARM_SMI;
7099 inst.reloc.pc_rel = 0;
7100 end_of_line (str);
7101}
7102
b99bd4ef 7103static void
a737bd4d 7104do_swi (char * str)
b99bd4ef
NC
7105{
7106 skip_whitespace (str);
7107
7108 /* Allow optional leading '#'. */
7109 if (is_immediate_prefix (*str))
7110 str++;
7111
7112 if (my_get_expression (& inst.reloc.exp, & str))
7113 return;
7114
7115 inst.reloc.type = BFD_RELOC_ARM_SWI;
7116 inst.reloc.pc_rel = 0;
b99bd4ef 7117 end_of_line (str);
b99bd4ef
NC
7118}
7119
7120static void
a737bd4d 7121do_swap (char * str)
b99bd4ef
NC
7122{
7123 int reg;
7124
7125 skip_whitespace (str);
7126
7127 if ((reg = reg_required_here (&str, 12)) == FAIL)
7128 return;
7129
7130 if (reg == REG_PC)
7131 {
7132 inst.error = _("r15 not allowed in swap");
7133 return;
7134 }
7135
7136 if (skip_past_comma (&str) == FAIL
7137 || (reg = reg_required_here (&str, 0)) == FAIL)
7138 {
7139 if (!inst.error)
7140 inst.error = BAD_ARGS;
7141 return;
7142 }
7143
7144 if (reg == REG_PC)
7145 {
7146 inst.error = _("r15 not allowed in swap");
7147 return;
7148 }
7149
7150 if (skip_past_comma (&str) == FAIL
7151 || *str++ != '[')
7152 {
7153 inst.error = BAD_ARGS;
7154 return;
7155 }
7156
7157 skip_whitespace (str);
7158
7159 if ((reg = reg_required_here (&str, 16)) == FAIL)
7160 return;
7161
7162 if (reg == REG_PC)
7163 {
7164 inst.error = BAD_PC;
7165 return;
7166 }
7167
7168 skip_whitespace (str);
7169
7170 if (*str++ != ']')
7171 {
7172 inst.error = _("missing ]");
7173 return;
7174 }
7175
b99bd4ef 7176 end_of_line (str);
b99bd4ef
NC
7177}
7178
7179static void
a737bd4d 7180do_branch (char * str)
b99bd4ef
NC
7181{
7182 if (my_get_expression (&inst.reloc.exp, &str))
7183 return;
7184
7185#ifdef OBJ_ELF
7186 {
7187 char * save_in;
7188
7189 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7190 required for the instruction. */
7191
7192 /* arm_parse_reloc () works on input_line_pointer.
7193 We actually want to parse the operands to the branch instruction
7194 passed in 'str'. Save the input pointer and restore it later. */
7195 save_in = input_line_pointer;
7196 input_line_pointer = str;
7197 if (inst.reloc.exp.X_op == O_symbol
7198 && *str == '('
7199 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7200 {
7201 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7202 inst.reloc.pc_rel = 0;
7203 /* Modify str to point to after parsed operands, otherwise
7204 end_of_line() will complain about the (PLT) left in str. */
7205 str = input_line_pointer;
7206 }
7207 else
7208 {
7209 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7210 inst.reloc.pc_rel = 1;
7211 }
7212 input_line_pointer = save_in;
7213 }
7214#else
7215 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7216 inst.reloc.pc_rel = 1;
7217#endif /* OBJ_ELF */
7218
7219 end_of_line (str);
b99bd4ef
NC
7220}
7221
7222static void
a737bd4d 7223do_cdp (char * str)
b99bd4ef
NC
7224{
7225 /* Co-processor data operation.
7226 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7227 skip_whitespace (str);
7228
7229 if (co_proc_number (&str) == FAIL)
7230 {
7231 if (!inst.error)
7232 inst.error = BAD_ARGS;
7233 return;
7234 }
7235
7236 if (skip_past_comma (&str) == FAIL
7237 || cp_opc_expr (&str, 20,4) == FAIL)
7238 {
7239 if (!inst.error)
7240 inst.error = BAD_ARGS;
7241 return;
7242 }
7243
7244 if (skip_past_comma (&str) == FAIL
7245 || cp_reg_required_here (&str, 12) == FAIL)
7246 {
7247 if (!inst.error)
7248 inst.error = BAD_ARGS;
7249 return;
7250 }
7251
7252 if (skip_past_comma (&str) == FAIL
7253 || cp_reg_required_here (&str, 16) == FAIL)
7254 {
7255 if (!inst.error)
7256 inst.error = BAD_ARGS;
7257 return;
7258 }
7259
7260 if (skip_past_comma (&str) == FAIL
7261 || cp_reg_required_here (&str, 0) == FAIL)
7262 {
7263 if (!inst.error)
7264 inst.error = BAD_ARGS;
7265 return;
7266 }
7267
7268 if (skip_past_comma (&str) == SUCCESS)
7269 {
7270 if (cp_opc_expr (&str, 5, 3) == FAIL)
7271 {
7272 if (!inst.error)
7273 inst.error = BAD_ARGS;
7274 return;
7275 }
7276 }
7277
7278 end_of_line (str);
b99bd4ef
NC
7279}
7280
7281static void
a737bd4d 7282do_lstc (char * str)
b99bd4ef
NC
7283{
7284 /* Co-processor register load/store.
7285 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7286
7287 skip_whitespace (str);
7288
7289 if (co_proc_number (&str) == FAIL)
7290 {
7291 if (!inst.error)
7292 inst.error = BAD_ARGS;
7293 return;
7294 }
7295
7296 if (skip_past_comma (&str) == FAIL
7297 || cp_reg_required_here (&str, 12) == FAIL)
7298 {
7299 if (!inst.error)
7300 inst.error = BAD_ARGS;
7301 return;
7302 }
7303
7304 if (skip_past_comma (&str) == FAIL
bfae80f2 7305 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7306 {
7307 if (! inst.error)
7308 inst.error = BAD_ARGS;
7309 return;
7310 }
7311
b99bd4ef 7312 end_of_line (str);
b99bd4ef
NC
7313}
7314
7315static void
a737bd4d 7316do_co_reg (char * str)
b99bd4ef
NC
7317{
7318 /* Co-processor register transfer.
7319 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7320
7321 skip_whitespace (str);
7322
7323 if (co_proc_number (&str) == FAIL)
7324 {
7325 if (!inst.error)
7326 inst.error = BAD_ARGS;
7327 return;
7328 }
7329
7330 if (skip_past_comma (&str) == FAIL
7331 || cp_opc_expr (&str, 21, 3) == FAIL)
7332 {
7333 if (!inst.error)
7334 inst.error = BAD_ARGS;
7335 return;
7336 }
7337
7338 if (skip_past_comma (&str) == FAIL
7339 || reg_required_here (&str, 12) == FAIL)
7340 {
7341 if (!inst.error)
7342 inst.error = BAD_ARGS;
7343 return;
7344 }
7345
7346 if (skip_past_comma (&str) == FAIL
7347 || cp_reg_required_here (&str, 16) == FAIL)
7348 {
7349 if (!inst.error)
7350 inst.error = BAD_ARGS;
7351 return;
7352 }
7353
7354 if (skip_past_comma (&str) == FAIL
7355 || cp_reg_required_here (&str, 0) == FAIL)
7356 {
7357 if (!inst.error)
7358 inst.error = BAD_ARGS;
7359 return;
7360 }
7361
7362 if (skip_past_comma (&str) == SUCCESS)
7363 {
7364 if (cp_opc_expr (&str, 5, 3) == FAIL)
7365 {
7366 if (!inst.error)
7367 inst.error = BAD_ARGS;
7368 return;
7369 }
7370 }
b99bd4ef
NC
7371
7372 end_of_line (str);
b99bd4ef
NC
7373}
7374
7375static void
a737bd4d 7376do_fpa_ctrl (char * str)
b99bd4ef
NC
7377{
7378 /* FP control registers.
7379 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7380
7381 skip_whitespace (str);
7382
7383 if (reg_required_here (&str, 12) == FAIL)
7384 {
7385 if (!inst.error)
7386 inst.error = BAD_ARGS;
7387 return;
7388 }
7389
7390 end_of_line (str);
b99bd4ef
NC
7391}
7392
7393static void
a737bd4d 7394do_fpa_ldst (char * str)
b99bd4ef
NC
7395{
7396 skip_whitespace (str);
7397
b99bd4ef
NC
7398 if (fp_reg_required_here (&str, 12) == FAIL)
7399 {
7400 if (!inst.error)
7401 inst.error = BAD_ARGS;
7402 return;
7403 }
7404
7405 if (skip_past_comma (&str) == FAIL
bfae80f2 7406 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7407 {
7408 if (!inst.error)
7409 inst.error = BAD_ARGS;
7410 return;
7411 }
7412
7413 end_of_line (str);
7414}
7415
7416static void
a737bd4d 7417do_fpa_ldmstm (char * str)
b99bd4ef
NC
7418{
7419 int num_regs;
7420
7421 skip_whitespace (str);
7422
7423 if (fp_reg_required_here (&str, 12) == FAIL)
7424 {
7425 if (! inst.error)
7426 inst.error = BAD_ARGS;
7427 return;
7428 }
7429
7430 /* Get Number of registers to transfer. */
7431 if (skip_past_comma (&str) == FAIL
7432 || my_get_expression (&inst.reloc.exp, &str))
7433 {
7434 if (! inst.error)
7435 inst.error = _("constant expression expected");
7436 return;
7437 }
7438
7439 if (inst.reloc.exp.X_op != O_constant)
7440 {
f03698e6 7441 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
7442 return;
7443 }
7444
7445 num_regs = inst.reloc.exp.X_add_number;
7446
7447 if (num_regs < 1 || num_regs > 4)
7448 {
7449 inst.error = _("number of registers must be in the range [1:4]");
7450 return;
7451 }
7452
7453 switch (num_regs)
7454 {
7455 case 1:
7456 inst.instruction |= CP_T_X;
7457 break;
7458 case 2:
7459 inst.instruction |= CP_T_Y;
7460 break;
7461 case 3:
7462 inst.instruction |= CP_T_Y | CP_T_X;
7463 break;
7464 case 4:
7465 break;
7466 default:
7467 abort ();
7468 }
7469
e28cd48c 7470 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
7471 {
7472 int reg;
7473 int write_back;
7474 int offset;
7475
7476 /* The instruction specified "ea" or "fd", so we can only accept
7477 [Rn]{!}. The instruction does not really support stacking or
7478 unstacking, so we have to emulate these by setting appropriate
7479 bits and offsets. */
7480 if (skip_past_comma (&str) == FAIL
7481 || *str != '[')
7482 {
7483 if (! inst.error)
7484 inst.error = BAD_ARGS;
7485 return;
7486 }
7487
7488 str++;
7489 skip_whitespace (str);
7490
7491 if ((reg = reg_required_here (&str, 16)) == FAIL)
7492 return;
7493
7494 skip_whitespace (str);
7495
7496 if (*str != ']')
7497 {
7498 inst.error = BAD_ARGS;
7499 return;
7500 }
7501
7502 str++;
7503 if (*str == '!')
7504 {
7505 write_back = 1;
7506 str++;
7507 if (reg == REG_PC)
7508 {
7509 inst.error =
f03698e6 7510 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
7511 return;
7512 }
7513 }
7514 else
7515 write_back = 0;
7516
90e4755a 7517 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
7518 {
7519 /* Pre-decrement. */
7520 offset = 3 * num_regs;
7521 if (write_back)
90e4755a 7522 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7523 }
7524 else
7525 {
7526 /* Post-increment. */
7527 if (write_back)
7528 {
90e4755a 7529 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7530 offset = 3 * num_regs;
7531 }
7532 else
7533 {
7534 /* No write-back, so convert this into a standard pre-increment
7535 instruction -- aesthetically more pleasing. */
90e4755a 7536 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
7537 offset = 0;
7538 }
7539 }
7540
f2b7cb0a 7541 inst.instruction |= offset;
b99bd4ef
NC
7542 }
7543 else if (skip_past_comma (&str) == FAIL
bfae80f2 7544 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7545 {
7546 if (! inst.error)
7547 inst.error = BAD_ARGS;
7548 return;
7549 }
7550
7551 end_of_line (str);
7552}
7553
7554static void
a737bd4d 7555do_fpa_dyadic (char * str)
b99bd4ef
NC
7556{
7557 skip_whitespace (str);
7558
b99bd4ef
NC
7559 if (fp_reg_required_here (&str, 12) == FAIL)
7560 {
7561 if (! inst.error)
7562 inst.error = BAD_ARGS;
7563 return;
7564 }
7565
7566 if (skip_past_comma (&str) == FAIL
7567 || fp_reg_required_here (&str, 16) == FAIL)
7568 {
7569 if (! inst.error)
7570 inst.error = BAD_ARGS;
7571 return;
7572 }
7573
7574 if (skip_past_comma (&str) == FAIL
7575 || fp_op2 (&str) == FAIL)
7576 {
7577 if (! inst.error)
7578 inst.error = BAD_ARGS;
7579 return;
7580 }
7581
b99bd4ef 7582 end_of_line (str);
b99bd4ef
NC
7583}
7584
7585static void
a737bd4d 7586do_fpa_monadic (char * str)
b99bd4ef
NC
7587{
7588 skip_whitespace (str);
7589
b99bd4ef
NC
7590 if (fp_reg_required_here (&str, 12) == FAIL)
7591 {
7592 if (! inst.error)
7593 inst.error = BAD_ARGS;
7594 return;
7595 }
7596
7597 if (skip_past_comma (&str) == FAIL
7598 || fp_op2 (&str) == FAIL)
7599 {
7600 if (! inst.error)
7601 inst.error = BAD_ARGS;
7602 return;
7603 }
7604
b99bd4ef 7605 end_of_line (str);
b99bd4ef
NC
7606}
7607
7608static void
a737bd4d 7609do_fpa_cmp (char * str)
b99bd4ef
NC
7610{
7611 skip_whitespace (str);
7612
7613 if (fp_reg_required_here (&str, 16) == FAIL)
7614 {
7615 if (! inst.error)
7616 inst.error = BAD_ARGS;
7617 return;
7618 }
7619
7620 if (skip_past_comma (&str) == FAIL
7621 || fp_op2 (&str) == FAIL)
7622 {
7623 if (! inst.error)
7624 inst.error = BAD_ARGS;
7625 return;
7626 }
7627
b99bd4ef 7628 end_of_line (str);
b99bd4ef
NC
7629}
7630
7631static void
a737bd4d 7632do_fpa_from_reg (char * str)
b99bd4ef
NC
7633{
7634 skip_whitespace (str);
7635
b99bd4ef
NC
7636 if (fp_reg_required_here (&str, 16) == FAIL)
7637 {
7638 if (! inst.error)
7639 inst.error = BAD_ARGS;
7640 return;
7641 }
7642
7643 if (skip_past_comma (&str) == FAIL
7644 || reg_required_here (&str, 12) == FAIL)
7645 {
7646 if (! inst.error)
7647 inst.error = BAD_ARGS;
7648 return;
7649 }
7650
b99bd4ef 7651 end_of_line (str);
b99bd4ef
NC
7652}
7653
7654static void
a737bd4d 7655do_fpa_to_reg (char * str)
b99bd4ef
NC
7656{
7657 skip_whitespace (str);
7658
7659 if (reg_required_here (&str, 12) == FAIL)
7660 return;
7661
7662 if (skip_past_comma (&str) == FAIL
7663 || fp_reg_required_here (&str, 0) == FAIL)
7664 {
7665 if (! inst.error)
7666 inst.error = BAD_ARGS;
7667 return;
7668 }
7669
b99bd4ef 7670 end_of_line (str);
b99bd4ef
NC
7671}
7672
7ed4c4c5
NC
7673/* Encode a VFP SP register number. */
7674
7675static void
7676vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7677{
7678 switch (pos)
7679 {
7680 case VFP_REG_Sd:
7681 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7682 break;
7683
7684 case VFP_REG_Sn:
7685 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7686 break;
7687
7688 case VFP_REG_Sm:
7689 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7690 break;
7691
7692 default:
7693 abort ();
7694 }
7695}
7696
b99bd4ef 7697static int
a737bd4d
NC
7698vfp_sp_reg_required_here (char ** str,
7699 enum vfp_sp_reg_pos pos)
b99bd4ef 7700{
bfae80f2 7701 int reg;
7ed4c4c5 7702 char * start = *str;
b99bd4ef 7703
bfae80f2 7704 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 7705 {
7ed4c4c5 7706 vfp_sp_encode_reg (reg, pos);
bfae80f2
RE
7707 return reg;
7708 }
b99bd4ef 7709
bfae80f2
RE
7710 /* In the few cases where we might be able to accept something else
7711 this error can be overridden. */
7712 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7713
7714 /* Restore the start point. */
7715 *str = start;
7716 return FAIL;
7717}
7718
7719static int
a737bd4d
NC
7720vfp_dp_reg_required_here (char ** str,
7721 enum vfp_dp_reg_pos pos)
bfae80f2 7722{
a737bd4d
NC
7723 int reg;
7724 char * start = *str;
bfae80f2
RE
7725
7726 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7727 {
7728 switch (pos)
b99bd4ef 7729 {
bfae80f2
RE
7730 case VFP_REG_Dd:
7731 inst.instruction |= reg << 12;
7732 break;
b99bd4ef 7733
bfae80f2
RE
7734 case VFP_REG_Dn:
7735 inst.instruction |= reg << 16;
7736 break;
7737
7738 case VFP_REG_Dm:
7739 inst.instruction |= reg << 0;
7740 break;
7741
7742 default:
7743 abort ();
7744 }
7745 return reg;
b99bd4ef
NC
7746 }
7747
bfae80f2
RE
7748 /* In the few cases where we might be able to accept something else
7749 this error can be overridden. */
7750 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 7751
bfae80f2
RE
7752 /* Restore the start point. */
7753 *str = start;
7754 return FAIL;
7755}
b99bd4ef
NC
7756
7757static void
a737bd4d 7758do_vfp_sp_monadic (char * str)
b99bd4ef 7759{
b99bd4ef
NC
7760 skip_whitespace (str);
7761
bfae80f2
RE
7762 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7763 return;
7764
7765 if (skip_past_comma (&str) == FAIL
7766 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
7767 {
7768 if (! inst.error)
7769 inst.error = BAD_ARGS;
7770 return;
7771 }
7772
bfae80f2 7773 end_of_line (str);
bfae80f2
RE
7774}
7775
7776static void
a737bd4d 7777do_vfp_dp_monadic (char * str)
bfae80f2
RE
7778{
7779 skip_whitespace (str);
7780
7781 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7782 return;
7783
7784 if (skip_past_comma (&str) == FAIL
7785 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 7786 {
bfae80f2
RE
7787 if (! inst.error)
7788 inst.error = BAD_ARGS;
7789 return;
b99bd4ef 7790 }
b99bd4ef 7791
bfae80f2 7792 end_of_line (str);
bfae80f2 7793}
b99bd4ef 7794
bfae80f2 7795static void
a737bd4d 7796do_vfp_sp_dyadic (char * str)
bfae80f2
RE
7797{
7798 skip_whitespace (str);
b99bd4ef 7799
bfae80f2
RE
7800 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7801 return;
b99bd4ef 7802
bfae80f2
RE
7803 if (skip_past_comma (&str) == FAIL
7804 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7805 || skip_past_comma (&str) == FAIL
7806 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 7807 {
bfae80f2
RE
7808 if (! inst.error)
7809 inst.error = BAD_ARGS;
7810 return;
7811 }
b99bd4ef 7812
bfae80f2 7813 end_of_line (str);
bfae80f2 7814}
b99bd4ef 7815
bfae80f2 7816static void
a737bd4d 7817do_vfp_dp_dyadic (char * str)
bfae80f2
RE
7818{
7819 skip_whitespace (str);
b99bd4ef 7820
bfae80f2
RE
7821 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7822 return;
b99bd4ef 7823
bfae80f2
RE
7824 if (skip_past_comma (&str) == FAIL
7825 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7826 || skip_past_comma (&str) == FAIL
7827 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7828 {
7829 if (! inst.error)
7830 inst.error = BAD_ARGS;
7831 return;
7832 }
b99bd4ef 7833
bfae80f2 7834 end_of_line (str);
bfae80f2 7835}
b99bd4ef 7836
bfae80f2 7837static void
a737bd4d 7838do_vfp_reg_from_sp (char * str)
bfae80f2
RE
7839{
7840 skip_whitespace (str);
7841
7842 if (reg_required_here (&str, 12) == FAIL)
7843 return;
7844
7845 if (skip_past_comma (&str) == FAIL
7846 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7847 {
7848 if (! inst.error)
7849 inst.error = BAD_ARGS;
7850 return;
7851 }
7852
7853 end_of_line (str);
bfae80f2
RE
7854}
7855
7ed4c4c5
NC
7856/* Parse a VFP register list. If the string is invalid return FAIL.
7857 Otherwise return the number of registers, and set PBASE to the first
7858 register. Double precision registers are matched if DP is nonzero. */
a737bd4d 7859
7ed4c4c5
NC
7860static int
7861vfp_parse_reg_list (char **str, int *pbase, int dp)
a737bd4d 7862{
7ed4c4c5 7863 int base_reg;
a737bd4d 7864 int new_base;
7ed4c4c5
NC
7865 int regtype;
7866 int max_regs;
a737bd4d 7867 int count = 0;
a737bd4d 7868 int warned = 0;
7ed4c4c5
NC
7869 unsigned long mask = 0;
7870 int i;
a737bd4d
NC
7871
7872 if (**str != '{')
7873 return FAIL;
7874
7875 (*str)++;
7876 skip_whitespace (*str);
7877
7ed4c4c5 7878 if (dp)
a737bd4d 7879 {
7ed4c4c5
NC
7880 regtype = REG_TYPE_DN;
7881 max_regs = 16;
7882 }
7883 else
7884 {
7885 regtype = REG_TYPE_SN;
7886 max_regs = 32;
7887 }
a737bd4d 7888
7ed4c4c5 7889 base_reg = max_regs;
a737bd4d 7890
7ed4c4c5
NC
7891 do
7892 {
7893 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7894 if (new_base == FAIL)
a737bd4d 7895 {
7ed4c4c5
NC
7896 inst.error = _(all_reg_maps[regtype].expected);
7897 return FAIL;
a737bd4d
NC
7898 }
7899
7ed4c4c5
NC
7900 if (new_base < base_reg)
7901 base_reg = new_base;
7902
a737bd4d
NC
7903 if (mask & (1 << new_base))
7904 {
7905 inst.error = _("invalid register list");
7906 return FAIL;
7907 }
7908
7909 if ((mask >> new_base) != 0 && ! warned)
7910 {
7911 as_tsktsk (_("register list not in ascending order"));
7912 warned = 1;
7913 }
7914
7915 mask |= 1 << new_base;
7916 count++;
7917
7918 skip_whitespace (*str);
7919
7920 if (**str == '-') /* We have the start of a range expression */
7921 {
7922 int high_range;
7923
7924 (*str)++;
7925
7926 if ((high_range
7ed4c4c5 7927 = arm_reg_parse (str, all_reg_maps[regtype].htab))
a737bd4d
NC
7928 == FAIL)
7929 {
7ed4c4c5 7930 inst.error = _(all_reg_maps[regtype].expected);
a737bd4d
NC
7931 return FAIL;
7932 }
7933
7934 if (high_range <= new_base)
7935 {
7936 inst.error = _("register range not in ascending order");
7937 return FAIL;
7938 }
7939
7940 for (new_base++; new_base <= high_range; new_base++)
7941 {
7942 if (mask & (1 << new_base))
7943 {
7944 inst.error = _("invalid register list");
7945 return FAIL;
7946 }
7947
7948 mask |= 1 << new_base;
7949 count++;
7950 }
7951 }
7952 }
7953 while (skip_past_comma (str) != FAIL);
7954
a737bd4d
NC
7955 (*str)++;
7956
a737bd4d 7957 /* Sanity check -- should have raised a parse error above. */
7ed4c4c5 7958 if (count == 0 || count > max_regs)
a737bd4d
NC
7959 abort ();
7960
7ed4c4c5
NC
7961 *pbase = base_reg;
7962
a737bd4d 7963 /* Final test -- the registers must be consecutive. */
7ed4c4c5
NC
7964 mask >>= base_reg;
7965 for (i = 0; i < count; i++)
a737bd4d 7966 {
7ed4c4c5 7967 if ((mask & (1u << i)) == 0)
a737bd4d
NC
7968 {
7969 inst.error = _("non-contiguous register range");
7970 return FAIL;
7971 }
7972 }
7973
7ed4c4c5 7974 return count;
a737bd4d
NC
7975}
7976
bfae80f2 7977static void
a737bd4d 7978do_vfp_reg2_from_sp2 (char * str)
bfae80f2 7979{
7ed4c4c5
NC
7980 int reg;
7981
bfae80f2
RE
7982 skip_whitespace (str);
7983
e45d0630
PB
7984 if (reg_required_here (&str, 12) == FAIL
7985 || skip_past_comma (&str) == FAIL
bfae80f2
RE
7986 || reg_required_here (&str, 16) == FAIL
7987 || skip_past_comma (&str) == FAIL)
7988 {
7989 if (! inst.error)
7990 inst.error = BAD_ARGS;
7991 return;
7992 }
7993
7994 /* We require exactly two consecutive SP registers. */
7ed4c4c5 7995 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
bfae80f2
RE
7996 {
7997 if (! inst.error)
7998 inst.error = _("only two consecutive VFP SP registers allowed here");
7999 }
7ed4c4c5 8000 vfp_sp_encode_reg (reg, VFP_REG_Sm);
bfae80f2
RE
8001
8002 end_of_line (str);
bfae80f2
RE
8003}
8004
8005static void
a737bd4d 8006do_vfp_sp_from_reg (char * str)
bfae80f2
RE
8007{
8008 skip_whitespace (str);
8009
8010 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8011 return;
8012
8013 if (skip_past_comma (&str) == FAIL
8014 || reg_required_here (&str, 12) == FAIL)
8015 {
8016 if (! inst.error)
8017 inst.error = BAD_ARGS;
8018 return;
8019 }
8020
8021 end_of_line (str);
bfae80f2
RE
8022}
8023
e45d0630 8024static void
a737bd4d 8025do_vfp_sp2_from_reg2 (char * str)
e45d0630 8026{
7ed4c4c5
NC
8027 int reg;
8028
e45d0630
PB
8029 skip_whitespace (str);
8030
8031 /* We require exactly two consecutive SP registers. */
7ed4c4c5 8032 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
e45d0630
PB
8033 {
8034 if (! inst.error)
8035 inst.error = _("only two consecutive VFP SP registers allowed here");
8036 }
7ed4c4c5 8037 vfp_sp_encode_reg (reg, VFP_REG_Sm);
e45d0630
PB
8038
8039 if (skip_past_comma (&str) == FAIL
8040 || reg_required_here (&str, 12) == FAIL
8041 || skip_past_comma (&str) == FAIL
8042 || reg_required_here (&str, 16) == FAIL)
8043 {
8044 if (! inst.error)
8045 inst.error = BAD_ARGS;
8046 return;
8047 }
8048
8049 end_of_line (str);
8050}
8051
bfae80f2 8052static void
a737bd4d 8053do_vfp_reg_from_dp (char * str)
bfae80f2
RE
8054{
8055 skip_whitespace (str);
8056
8057 if (reg_required_here (&str, 12) == FAIL)
8058 return;
8059
8060 if (skip_past_comma (&str) == FAIL
8061 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8062 {
8063 if (! inst.error)
8064 inst.error = BAD_ARGS;
8065 return;
8066 }
8067
8068 end_of_line (str);
bfae80f2
RE
8069}
8070
8071static void
a737bd4d 8072do_vfp_reg2_from_dp (char * str)
bfae80f2
RE
8073{
8074 skip_whitespace (str);
8075
8076 if (reg_required_here (&str, 12) == FAIL)
8077 return;
8078
8079 if (skip_past_comma (&str) == FAIL
8080 || reg_required_here (&str, 16) == FAIL
8081 || skip_past_comma (&str) == FAIL
8082 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8083 {
8084 if (! inst.error)
8085 inst.error = BAD_ARGS;
8086 return;
8087 }
8088
8089 end_of_line (str);
bfae80f2
RE
8090}
8091
8092static void
a737bd4d 8093do_vfp_dp_from_reg (char * str)
bfae80f2
RE
8094{
8095 skip_whitespace (str);
8096
8097 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8098 return;
8099
8100 if (skip_past_comma (&str) == FAIL
8101 || reg_required_here (&str, 12) == FAIL)
8102 {
8103 if (! inst.error)
8104 inst.error = BAD_ARGS;
8105 return;
8106 }
8107
8108 end_of_line (str);
bfae80f2
RE
8109}
8110
8111static void
a737bd4d 8112do_vfp_dp_from_reg2 (char * str)
bfae80f2
RE
8113{
8114 skip_whitespace (str);
8115
8116 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8117 return;
8118
8119 if (skip_past_comma (&str) == FAIL
8120 || reg_required_here (&str, 12) == FAIL
8121 || skip_past_comma (&str) == FAIL
e45d0630 8122 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
8123 {
8124 if (! inst.error)
8125 inst.error = BAD_ARGS;
8126 return;
8127 }
8128
8129 end_of_line (str);
bfae80f2
RE
8130}
8131
8132static const struct vfp_reg *
a737bd4d 8133vfp_psr_parse (char ** str)
bfae80f2
RE
8134{
8135 char *start = *str;
8136 char c;
8137 char *p;
8138 const struct vfp_reg *vreg;
8139
8140 p = start;
8141
8142 /* Find the end of the current token. */
8143 do
8144 {
8145 c = *p++;
8146 }
8147 while (ISALPHA (c));
8148
8149 /* Mark it. */
8150 *--p = 0;
8151
cc8a6dd0 8152 for (vreg = vfp_regs + 0;
bfae80f2
RE
8153 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8154 vreg++)
8155 {
a737bd4d 8156 if (streq (start, vreg->name))
bfae80f2
RE
8157 {
8158 *p = c;
8159 *str = p;
8160 return vreg;
8161 }
8162 }
8163
8164 *p = c;
8165 return NULL;
8166}
8167
8168static int
a737bd4d 8169vfp_psr_required_here (char ** str)
bfae80f2
RE
8170{
8171 char *start = *str;
8172 const struct vfp_reg *vreg;
8173
8174 vreg = vfp_psr_parse (str);
8175
8176 if (vreg)
8177 {
8178 inst.instruction |= vreg->regno;
8179 return SUCCESS;
8180 }
8181
8182 inst.error = _("VFP system register expected");
8183
8184 *str = start;
8185 return FAIL;
8186}
8187
8188static void
a737bd4d 8189do_vfp_reg_from_ctrl (char * str)
bfae80f2
RE
8190{
8191 skip_whitespace (str);
8192
8193 if (reg_required_here (&str, 12) == FAIL)
8194 return;
8195
8196 if (skip_past_comma (&str) == FAIL
8197 || vfp_psr_required_here (&str) == FAIL)
8198 {
8199 if (! inst.error)
8200 inst.error = BAD_ARGS;
8201 return;
8202 }
8203
8204 end_of_line (str);
bfae80f2
RE
8205}
8206
8207static void
a737bd4d 8208do_vfp_ctrl_from_reg (char * str)
bfae80f2
RE
8209{
8210 skip_whitespace (str);
8211
8212 if (vfp_psr_required_here (&str) == FAIL)
8213 return;
8214
8215 if (skip_past_comma (&str) == FAIL
8216 || reg_required_here (&str, 12) == FAIL)
8217 {
8218 if (! inst.error)
8219 inst.error = BAD_ARGS;
8220 return;
8221 }
8222
8223 end_of_line (str);
bfae80f2
RE
8224}
8225
8226static void
a737bd4d 8227do_vfp_sp_ldst (char * str)
bfae80f2
RE
8228{
8229 skip_whitespace (str);
8230
8231 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8232 {
8233 if (!inst.error)
8234 inst.error = BAD_ARGS;
8235 return;
8236 }
8237
8238 if (skip_past_comma (&str) == FAIL
8239 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8240 {
8241 if (!inst.error)
8242 inst.error = BAD_ARGS;
8243 return;
8244 }
8245
8246 end_of_line (str);
bfae80f2
RE
8247}
8248
8249static void
a737bd4d 8250do_vfp_dp_ldst (char * str)
bfae80f2
RE
8251{
8252 skip_whitespace (str);
8253
8254 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8255 {
8256 if (!inst.error)
8257 inst.error = BAD_ARGS;
8258 return;
8259 }
8260
8261 if (skip_past_comma (&str) == FAIL
8262 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8263 {
8264 if (!inst.error)
a737bd4d
NC
8265 inst.error = BAD_ARGS;
8266 return;
bfae80f2
RE
8267 }
8268
a737bd4d 8269 end_of_line (str);
bfae80f2
RE
8270}
8271
bfae80f2
RE
8272
8273static void
a737bd4d 8274vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 8275{
7ed4c4c5
NC
8276 int count;
8277 int reg;
bfae80f2
RE
8278
8279 skip_whitespace (str);
8280
8281 if (reg_required_here (&str, 16) == FAIL)
8282 return;
8283
8284 skip_whitespace (str);
8285
8286 if (*str == '!')
8287 {
8288 inst.instruction |= WRITE_BACK;
8289 str++;
8290 }
8291 else if (ldstm_type != VFP_LDSTMIA)
8292 {
8293 inst.error = _("this addressing mode requires base-register writeback");
8294 return;
8295 }
8296
8297 if (skip_past_comma (&str) == FAIL
7ed4c4c5 8298 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
bfae80f2
RE
8299 {
8300 if (!inst.error)
8301 inst.error = BAD_ARGS;
8302 return;
8303 }
7ed4c4c5 8304 vfp_sp_encode_reg (reg, VFP_REG_Sd);
bfae80f2 8305
7ed4c4c5 8306 inst.instruction |= count;
bfae80f2
RE
8307 end_of_line (str);
8308}
8309
8310static void
a737bd4d 8311vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 8312{
7ed4c4c5
NC
8313 int count;
8314 int reg;
bfae80f2
RE
8315
8316 skip_whitespace (str);
8317
8318 if (reg_required_here (&str, 16) == FAIL)
8319 return;
8320
8321 skip_whitespace (str);
8322
8323 if (*str == '!')
8324 {
8325 inst.instruction |= WRITE_BACK;
8326 str++;
8327 }
8328 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8329 {
8330 inst.error = _("this addressing mode requires base-register writeback");
8331 return;
8332 }
8333
8334 if (skip_past_comma (&str) == FAIL
7ed4c4c5 8335 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
bfae80f2
RE
8336 {
8337 if (!inst.error)
8338 inst.error = BAD_ARGS;
8339 return;
8340 }
8341
7ed4c4c5 8342 count <<= 1;
bfae80f2 8343 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7ed4c4c5 8344 count += 1;
bfae80f2 8345
7ed4c4c5 8346 inst.instruction |= (reg << 12) | count;
bfae80f2
RE
8347 end_of_line (str);
8348}
8349
8350static void
a737bd4d 8351do_vfp_sp_ldstmia (char * str)
bfae80f2
RE
8352{
8353 vfp_sp_ldstm (str, VFP_LDSTMIA);
8354}
8355
8356static void
a737bd4d 8357do_vfp_sp_ldstmdb (char * str)
bfae80f2
RE
8358{
8359 vfp_sp_ldstm (str, VFP_LDSTMDB);
8360}
8361
8362static void
a737bd4d 8363do_vfp_dp_ldstmia (char * str)
bfae80f2
RE
8364{
8365 vfp_dp_ldstm (str, VFP_LDSTMIA);
8366}
8367
8368static void
a737bd4d 8369do_vfp_dp_ldstmdb (char * str)
bfae80f2
RE
8370{
8371 vfp_dp_ldstm (str, VFP_LDSTMDB);
8372}
8373
8374static void
a737bd4d 8375do_vfp_xp_ldstmia (char *str)
bfae80f2
RE
8376{
8377 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8378}
8379
8380static void
a737bd4d 8381do_vfp_xp_ldstmdb (char * str)
bfae80f2
RE
8382{
8383 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8384}
8385
8386static void
a737bd4d 8387do_vfp_sp_compare_z (char * str)
bfae80f2
RE
8388{
8389 skip_whitespace (str);
8390
8391 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8392 {
8393 if (!inst.error)
8394 inst.error = BAD_ARGS;
8395 return;
8396 }
8397
8398 end_of_line (str);
bfae80f2
RE
8399}
8400
8401static void
a737bd4d 8402do_vfp_dp_compare_z (char * str)
bfae80f2
RE
8403{
8404 skip_whitespace (str);
8405
8406 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8407 {
8408 if (!inst.error)
8409 inst.error = BAD_ARGS;
8410 return;
8411 }
8412
8413 end_of_line (str);
bfae80f2
RE
8414}
8415
8416static void
a737bd4d 8417do_vfp_dp_sp_cvt (char * str)
bfae80f2
RE
8418{
8419 skip_whitespace (str);
8420
8421 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8422 return;
8423
8424 if (skip_past_comma (&str) == FAIL
8425 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8426 {
8427 if (! inst.error)
8428 inst.error = BAD_ARGS;
8429 return;
8430 }
8431
8432 end_of_line (str);
bfae80f2
RE
8433}
8434
8435static void
a737bd4d 8436do_vfp_sp_dp_cvt (char * str)
bfae80f2
RE
8437{
8438 skip_whitespace (str);
8439
8440 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8441 return;
8442
8443 if (skip_past_comma (&str) == FAIL
8444 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8445 {
8446 if (! inst.error)
8447 inst.error = BAD_ARGS;
8448 return;
8449 }
8450
8451 end_of_line (str);
bfae80f2
RE
8452}
8453
8454/* Thumb specific routines. */
8455
bfae80f2
RE
8456/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8457 was SUB. */
8458
8459static void
a737bd4d 8460thumb_add_sub (char * str, int subtract)
bfae80f2
RE
8461{
8462 int Rd, Rs, Rn = FAIL;
8463
8464 skip_whitespace (str);
8465
8466 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8467 || skip_past_comma (&str) == FAIL)
8468 {
8469 if (! inst.error)
8470 inst.error = BAD_ARGS;
8471 return;
8472 }
8473
8474 if (is_immediate_prefix (*str))
8475 {
8476 Rs = Rd;
8477 str++;
8478 if (my_get_expression (&inst.reloc.exp, &str))
8479 return;
8480 }
8481 else
8482 {
8483 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8484 return;
8485
8486 if (skip_past_comma (&str) == FAIL)
8487 {
8488 /* Two operand format, shuffle the registers
8489 and pretend there are 3. */
8490 Rn = Rs;
8491 Rs = Rd;
8492 }
8493 else if (is_immediate_prefix (*str))
8494 {
8495 str++;
8496 if (my_get_expression (&inst.reloc.exp, &str))
8497 return;
8498 }
8499 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8500 return;
8501 }
8502
8503 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8504 for the latter case, EXPR contains the immediate that was found. */
8505 if (Rn != FAIL)
8506 {
8507 /* All register format. */
8508 if (Rd > 7 || Rs > 7 || Rn > 7)
8509 {
8510 if (Rs != Rd)
8511 {
8512 inst.error = _("dest and source1 must be the same register");
8513 return;
8514 }
8515
8516 /* Can't do this for SUB. */
8517 if (subtract)
8518 {
8519 inst.error = _("subtract valid only on lo regs");
8520 return;
8521 }
8522
8523 inst.instruction = (T_OPCODE_ADD_HI
8524 | (Rd > 7 ? THUMB_H1 : 0)
8525 | (Rn > 7 ? THUMB_H2 : 0));
8526 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8527 }
8528 else
8529 {
8530 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8531 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8532 }
8533 }
8534 else
8535 {
8536 /* Immediate expression, now things start to get nasty. */
8537
8538 /* First deal with HI regs, only very restricted cases allowed:
8539 Adjusting SP, and using PC or SP to get an address. */
8540 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8541 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8542 {
8543 inst.error = _("invalid Hi register with immediate");
8544 return;
8545 }
8546
8547 if (inst.reloc.exp.X_op != O_constant)
8548 {
8549 /* Value isn't known yet, all we can do is store all the fragments
8550 we know about in the instruction and let the reloc hacking
8551 work it all out. */
8552 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8553 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8554 }
8555 else
8556 {
8557 int offset = inst.reloc.exp.X_add_number;
8558
8559 if (subtract)
358b94bd 8560 offset = - offset;
bfae80f2
RE
8561
8562 if (offset < 0)
8563 {
358b94bd 8564 offset = - offset;
bfae80f2
RE
8565 subtract = 1;
8566
8567 /* Quick check, in case offset is MIN_INT. */
8568 if (offset < 0)
8569 {
8570 inst.error = _("immediate value out of range");
8571 return;
8572 }
8573 }
358b94bd
NC
8574 /* Note - you cannot convert a subtract of 0 into an
8575 add of 0 because the carry flag is set differently. */
8576 else if (offset > 0)
bfae80f2
RE
8577 subtract = 0;
8578
8579 if (Rd == REG_SP)
8580 {
8581 if (offset & ~0x1fc)
8582 {
8583 inst.error = _("invalid immediate value for stack adjust");
8584 return;
b99bd4ef
NC
8585 }
8586 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8587 inst.instruction |= offset >> 2;
8588 }
8589 else if (Rs == REG_PC || Rs == REG_SP)
8590 {
8591 if (subtract
8592 || (offset & ~0x3fc))
8593 {
8594 inst.error = _("invalid immediate for address calculation");
8595 return;
8596 }
8597 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8598 : T_OPCODE_ADD_SP);
8599 inst.instruction |= (Rd << 8) | (offset >> 2);
8600 }
8601 else if (Rs == Rd)
8602 {
8603 if (offset & ~0xff)
8604 {
8605 inst.error = _("immediate value out of range");
8606 return;
8607 }
8608 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8609 inst.instruction |= (Rd << 8) | offset;
8610 }
8611 else
8612 {
8613 if (offset & ~0x7)
8614 {
8615 inst.error = _("immediate value out of range");
8616 return;
8617 }
8618 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8619 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8620 }
8621 }
8622 }
8623
8624 end_of_line (str);
8625}
8626
8627static void
a737bd4d 8628thumb_shift (char * str, int shift)
b99bd4ef
NC
8629{
8630 int Rd, Rs, Rn = FAIL;
8631
8632 skip_whitespace (str);
8633
8634 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8635 || skip_past_comma (&str) == FAIL)
8636 {
8637 if (! inst.error)
8638 inst.error = BAD_ARGS;
8639 return;
8640 }
8641
8642 if (is_immediate_prefix (*str))
8643 {
8644 /* Two operand immediate format, set Rs to Rd. */
8645 Rs = Rd;
8646 str ++;
8647 if (my_get_expression (&inst.reloc.exp, &str))
8648 return;
8649 }
8650 else
8651 {
8652 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8653 return;
8654
8655 if (skip_past_comma (&str) == FAIL)
8656 {
8657 /* Two operand format, shuffle the registers
8658 and pretend there are 3. */
8659 Rn = Rs;
8660 Rs = Rd;
8661 }
8662 else if (is_immediate_prefix (*str))
8663 {
8664 str++;
8665 if (my_get_expression (&inst.reloc.exp, &str))
8666 return;
8667 }
8668 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8669 return;
8670 }
8671
8672 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8673 for the latter case, EXPR contains the immediate that was found. */
8674
8675 if (Rn != FAIL)
8676 {
8677 if (Rs != Rd)
8678 {
8679 inst.error = _("source1 and dest must be same register");
8680 return;
8681 }
8682
8683 switch (shift)
8684 {
8685 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8686 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8687 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8688 }
8689
8690 inst.instruction |= Rd | (Rn << 3);
8691 }
8692 else
8693 {
8694 switch (shift)
8695 {
8696 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8697 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8698 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8699 }
8700
8701 if (inst.reloc.exp.X_op != O_constant)
8702 {
8703 /* Value isn't known yet, create a dummy reloc and let reloc
8704 hacking fix it up. */
8705 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8706 }
8707 else
8708 {
8709 unsigned shift_value = inst.reloc.exp.X_add_number;
8710
8711 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8712 {
f03698e6 8713 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
8714 return;
8715 }
8716
8717 /* Shifts of zero are handled by converting to LSL. */
8718 if (shift_value == 0)
8719 inst.instruction = T_OPCODE_LSL_I;
8720
8721 /* Shifts of 32 are encoded as a shift of zero. */
8722 if (shift_value == 32)
8723 shift_value = 0;
8724
8725 inst.instruction |= shift_value << 6;
8726 }
8727
8728 inst.instruction |= Rd | (Rs << 3);
8729 }
8730
8731 end_of_line (str);
8732}
8733
8734static void
a737bd4d 8735thumb_load_store (char * str, int load_store, int size)
b99bd4ef
NC
8736{
8737 int Rd, Rb, Ro = FAIL;
8738
8739 skip_whitespace (str);
8740
8741 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8742 || skip_past_comma (&str) == FAIL)
8743 {
8744 if (! inst.error)
8745 inst.error = BAD_ARGS;
8746 return;
8747 }
8748
8749 if (*str == '[')
8750 {
8751 str++;
8752 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8753 return;
8754
8755 if (skip_past_comma (&str) != FAIL)
8756 {
8757 if (is_immediate_prefix (*str))
8758 {
8759 str++;
8760 if (my_get_expression (&inst.reloc.exp, &str))
8761 return;
8762 }
8763 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8764 return;
8765 }
8766 else
8767 {
8768 inst.reloc.exp.X_op = O_constant;
8769 inst.reloc.exp.X_add_number = 0;
8770 }
8771
8772 if (*str != ']')
8773 {
8774 inst.error = _("expected ']'");
8775 return;
8776 }
8777 str++;
8778 }
8779 else if (*str == '=')
8780 {
f03698e6
RE
8781 if (load_store != THUMB_LOAD)
8782 {
8783 inst.error = _("invalid pseudo operation");
8784 return;
8785 }
8786
b99bd4ef
NC
8787 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8788 str++;
8789
8790 skip_whitespace (str);
8791
8792 if (my_get_expression (& inst.reloc.exp, & str))
8793 return;
8794
8795 end_of_line (str);
8796
8797 if ( inst.reloc.exp.X_op != O_constant
8798 && inst.reloc.exp.X_op != O_symbol)
8799 {
8800 inst.error = "Constant expression expected";
8801 return;
8802 }
8803
8804 if (inst.reloc.exp.X_op == O_constant
8805 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8806 {
8807 /* This can be done with a mov instruction. */
8808
8809 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8810 inst.instruction |= inst.reloc.exp.X_add_number;
8811 return;
8812 }
8813
8814 /* Insert into literal pool. */
8815 if (add_to_lit_pool () == FAIL)
8816 {
8817 if (!inst.error)
8818 inst.error = "literal pool insertion failed";
8819 return;
8820 }
8821
8822 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8823 inst.reloc.pc_rel = 1;
8824 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8825 /* Adjust ARM pipeline offset to Thumb. */
8826 inst.reloc.exp.X_add_number += 4;
8827
8828 return;
8829 }
8830 else
8831 {
8832 if (my_get_expression (&inst.reloc.exp, &str))
8833 return;
8834
8835 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8836 inst.reloc.pc_rel = 1;
8837 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8838 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8839 end_of_line (str);
8840 return;
8841 }
8842
8843 if (Rb == REG_PC || Rb == REG_SP)
8844 {
8845 if (size != THUMB_WORD)
8846 {
8847 inst.error = _("byte or halfword not valid for base register");
8848 return;
8849 }
8850 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8851 {
f03698e6 8852 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
8853 return;
8854 }
8855 else if (Ro != FAIL)
8856 {
f03698e6 8857 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
8858 return;
8859 }
8860
8861 if (Rb == REG_PC)
8862 inst.instruction = T_OPCODE_LDR_PC;
8863 else if (load_store == THUMB_LOAD)
8864 inst.instruction = T_OPCODE_LDR_SP;
8865 else
8866 inst.instruction = T_OPCODE_STR_SP;
8867
8868 inst.instruction |= Rd << 8;
8869 if (inst.reloc.exp.X_op == O_constant)
8870 {
8871 unsigned offset = inst.reloc.exp.X_add_number;
8872
8873 if (offset & ~0x3fc)
8874 {
8875 inst.error = _("invalid offset");
8876 return;
8877 }
8878
8879 inst.instruction |= offset >> 2;
8880 }
8881 else
8882 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8883 }
8884 else if (Rb > 7)
8885 {
8886 inst.error = _("invalid base register in load/store");
8887 return;
8888 }
8889 else if (Ro == FAIL)
8890 {
8891 /* Immediate offset. */
8892 if (size == THUMB_WORD)
8893 inst.instruction = (load_store == THUMB_LOAD
8894 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8895 else if (size == THUMB_HALFWORD)
8896 inst.instruction = (load_store == THUMB_LOAD
8897 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8898 else
8899 inst.instruction = (load_store == THUMB_LOAD
8900 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8901
8902 inst.instruction |= Rd | (Rb << 3);
8903
8904 if (inst.reloc.exp.X_op == O_constant)
8905 {
8906 unsigned offset = inst.reloc.exp.X_add_number;
8907
8908 if (offset & ~(0x1f << size))
8909 {
f03698e6 8910 inst.error = _("invalid offset");
b99bd4ef
NC
8911 return;
8912 }
8913 inst.instruction |= (offset >> size) << 6;
8914 }
8915 else
8916 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8917 }
8918 else
8919 {
8920 /* Register offset. */
8921 if (size == THUMB_WORD)
8922 inst.instruction = (load_store == THUMB_LOAD
8923 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8924 else if (size == THUMB_HALFWORD)
8925 inst.instruction = (load_store == THUMB_LOAD
8926 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8927 else
8928 inst.instruction = (load_store == THUMB_LOAD
8929 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8930
8931 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8932 }
8933
8934 end_of_line (str);
8935}
8936
404ff6b5
AH
8937/* A register must be given at this point.
8938
404ff6b5
AH
8939 Shift is the place to put it in inst.instruction.
8940
404ff6b5
AH
8941 Restores input start point on err.
8942 Returns the reg#, or FAIL. */
8943
8944static int
a737bd4d 8945mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
404ff6b5 8946{
6c43fab6
RE
8947 int reg;
8948 char *start = *str;
404ff6b5 8949
6c43fab6 8950 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 8951 {
404ff6b5
AH
8952 if (shift >= 0)
8953 inst.instruction |= reg << shift;
8954
6c43fab6 8955 return reg;
404ff6b5
AH
8956 }
8957
6c43fab6 8958 /* Restore the start point. */
404ff6b5 8959 *str = start;
cc8a6dd0 8960
3631a3c8
NC
8961 /* Try generic coprocessor name if applicable. */
8962 if (regtype == REG_TYPE_MVF ||
8963 regtype == REG_TYPE_MVD ||
8964 regtype == REG_TYPE_MVFX ||
8965 regtype == REG_TYPE_MVDX)
8966 {
8967 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8968 {
8969 if (shift >= 0)
8970 inst.instruction |= reg << shift;
8971
8972 return reg;
8973 }
8974
8975 /* Restore the start point. */
8976 *str = start;
8977 }
8978
404ff6b5
AH
8979 /* In the few cases where we might be able to accept something else
8980 this error can be overridden. */
6c43fab6 8981 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 8982
404ff6b5
AH
8983 return FAIL;
8984}
8985
a737bd4d
NC
8986/* Cirrus Maverick Instructions. */
8987
8988/* Isnsn like "foo X,Y". */
8989
8990static void
8991do_mav_binops (char * str,
8992 int mode,
8993 enum arm_reg_type reg0,
8994 enum arm_reg_type reg1)
8995{
8996 int shift0, shift1;
8997
8998 shift0 = mode & 0xff;
8999 shift1 = (mode >> 8) & 0xff;
9000
9001 skip_whitespace (str);
9002
9003 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9004 || skip_past_comma (&str) == FAIL
9005 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9006 {
9007 if (!inst.error)
9008 inst.error = BAD_ARGS;
9009 }
9010 else
9011 end_of_line (str);
9012}
9013
9014/* Isnsn like "foo X,Y,Z". */
9015
9016static void
9017do_mav_triple (char * str,
9018 int mode,
9019 enum arm_reg_type reg0,
9020 enum arm_reg_type reg1,
9021 enum arm_reg_type reg2)
9022{
9023 int shift0, shift1, shift2;
9024
9025 shift0 = mode & 0xff;
9026 shift1 = (mode >> 8) & 0xff;
9027 shift2 = (mode >> 16) & 0xff;
9028
9029 skip_whitespace (str);
9030
9031 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9032 || skip_past_comma (&str) == FAIL
9033 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9034 || skip_past_comma (&str) == FAIL
9035 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9036 {
9037 if (!inst.error)
9038 inst.error = BAD_ARGS;
9039 }
9040 else
9041 end_of_line (str);
9042}
9043
9044/* Wrapper functions. */
9045
9046static void
9047do_mav_binops_1a (char * str)
9048{
9049 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9050}
9051
9052static void
9053do_mav_binops_1b (char * str)
9054{
9055 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9056}
9057
9058static void
9059do_mav_binops_1c (char * str)
9060{
9061 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9062}
9063
9064static void
9065do_mav_binops_1d (char * str)
9066{
9067 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9068}
9069
9070static void
9071do_mav_binops_1e (char * str)
9072{
9073 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9074}
9075
9076static void
9077do_mav_binops_1f (char * str)
9078{
9079 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9080}
9081
9082static void
9083do_mav_binops_1g (char * str)
9084{
9085 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9086}
9087
9088static void
9089do_mav_binops_1h (char * str)
9090{
9091 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9092}
9093
9094static void
9095do_mav_binops_1i (char * str)
9096{
9097 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9098}
9099
9100static void
9101do_mav_binops_1j (char * str)
9102{
9103 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9104}
9105
9106static void
9107do_mav_binops_1k (char * str)
9108{
9109 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9110}
9111
9112static void
9113do_mav_binops_1l (char * str)
9114{
9115 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9116}
9117
9118static void
9119do_mav_binops_1m (char * str)
9120{
9121 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9122}
9123
9124static void
9125do_mav_binops_1n (char * str)
9126{
9127 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9128}
9129
9130static void
9131do_mav_binops_1o (char * str)
9132{
9133 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9134}
9135
9136static void
9137do_mav_binops_2a (char * str)
9138{
9139 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9140}
9141
9142static void
9143do_mav_binops_2b (char * str)
9144{
9145 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9146}
404ff6b5 9147
a737bd4d
NC
9148static void
9149do_mav_binops_2c (char * str)
9150{
9151 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9152}
404ff6b5
AH
9153
9154static void
a737bd4d 9155do_mav_binops_3a (char * str)
6c43fab6 9156{
a737bd4d 9157 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
9158}
9159
9160static void
a737bd4d 9161do_mav_binops_3b (char * str)
6c43fab6 9162{
a737bd4d 9163 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
9164}
9165
9166static void
a737bd4d 9167do_mav_binops_3c (char * str)
404ff6b5 9168{
a737bd4d 9169 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
404ff6b5
AH
9170}
9171
9172static void
a737bd4d 9173do_mav_binops_3d (char * str)
404ff6b5 9174{
a737bd4d 9175 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
404ff6b5
AH
9176}
9177
9178static void
a737bd4d 9179do_mav_triple_4a (char * str)
404ff6b5 9180{
a737bd4d 9181 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
404ff6b5
AH
9182}
9183
9184static void
a737bd4d 9185do_mav_triple_4b (char * str)
404ff6b5 9186{
a737bd4d 9187 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
404ff6b5
AH
9188}
9189
9190static void
a737bd4d 9191do_mav_triple_5a (char * str)
404ff6b5 9192{
a737bd4d 9193 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
9194}
9195
9196static void
a737bd4d 9197do_mav_triple_5b (char * str)
404ff6b5 9198{
a737bd4d 9199 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
9200}
9201
6c43fab6 9202static void
a737bd4d 9203do_mav_triple_5c (char * str)
6c43fab6 9204{
a737bd4d 9205 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9206}
9207
9208static void
a737bd4d 9209do_mav_triple_5d (char * str)
6c43fab6 9210{
a737bd4d 9211 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
9212}
9213
9214static void
a737bd4d 9215do_mav_triple_5e (char * str)
6c43fab6 9216{
a737bd4d 9217 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
9218}
9219
9220static void
a737bd4d 9221do_mav_triple_5f (char * str)
6c43fab6 9222{
a737bd4d 9223 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
9224}
9225
9226static void
a737bd4d 9227do_mav_triple_5g (char * str)
6c43fab6 9228{
a737bd4d 9229 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9230}
9231
9232static void
a737bd4d 9233do_mav_triple_5h (char * str)
6c43fab6 9234{
a737bd4d 9235 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
9236}
9237
a737bd4d
NC
9238/* Isnsn like "foo W,X,Y,Z".
9239 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9240
6c43fab6 9241static void
a737bd4d
NC
9242do_mav_quad (char * str,
9243 int mode,
9244 enum arm_reg_type reg0,
9245 enum arm_reg_type reg1,
9246 enum arm_reg_type reg2,
9247 enum arm_reg_type reg3)
6c43fab6 9248{
a737bd4d
NC
9249 int shift0, shift1, shift2, shift3;
9250
9251 shift0= mode & 0xff;
9252 shift1 = (mode >> 8) & 0xff;
9253 shift2 = (mode >> 16) & 0xff;
9254 shift3 = (mode >> 24) & 0xff;
9255
9256 skip_whitespace (str);
9257
9258 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9259 || skip_past_comma (&str) == FAIL
9260 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9261 || skip_past_comma (&str) == FAIL
9262 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9263 || skip_past_comma (&str) == FAIL
9264 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9265 {
9266 if (!inst.error)
9267 inst.error = BAD_ARGS;
9268 }
9269 else
9270 end_of_line (str);
6c43fab6
RE
9271}
9272
9273static void
a737bd4d 9274do_mav_quad_6a (char * str)
6c43fab6 9275{
a737bd4d
NC
9276 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9277 REG_TYPE_MVFX);
6c43fab6
RE
9278}
9279
9280static void
a737bd4d 9281do_mav_quad_6b (char * str)
6c43fab6 9282{
a737bd4d
NC
9283 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9284 REG_TYPE_MVFX);
6c43fab6
RE
9285}
9286
a737bd4d 9287/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
6c43fab6 9288static void
a737bd4d 9289do_mav_dspsc_1 (char * str)
6c43fab6 9290{
a737bd4d
NC
9291 skip_whitespace (str);
9292
9293 /* cfmvsc32. */
9294 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9295 || skip_past_comma (&str) == FAIL
9296 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9297 {
9298 if (!inst.error)
9299 inst.error = BAD_ARGS;
9300
9301 return;
9302 }
9303
9304 end_of_line (str);
6c43fab6
RE
9305}
9306
a737bd4d 9307/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
6c43fab6 9308static void
a737bd4d 9309do_mav_dspsc_2 (char * str)
6c43fab6 9310{
a737bd4d
NC
9311 skip_whitespace (str);
9312
9313 /* cfmv32sc. */
9314 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9315 || skip_past_comma (&str) == FAIL
9316 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9317 {
9318 if (!inst.error)
9319 inst.error = BAD_ARGS;
9320
9321 return;
9322 }
9323
9324 end_of_line (str);
6c43fab6
RE
9325}
9326
a737bd4d
NC
9327/* Maverick shift immediate instructions.
9328 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9329 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9330
6c43fab6 9331static void
a737bd4d
NC
9332do_mav_shift (char * str,
9333 enum arm_reg_type reg0,
9334 enum arm_reg_type reg1)
6c43fab6 9335{
a737bd4d
NC
9336 int error;
9337 int imm, neg = 0;
9338
9339 skip_whitespace (str);
9340
9341 error = 0;
9342
9343 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9344 || skip_past_comma (&str) == FAIL
9345 || mav_reg_required_here (&str, 16, reg1) == FAIL
9346 || skip_past_comma (&str) == FAIL)
9347 {
9348 if (!inst.error)
9349 inst.error = BAD_ARGS;
9350 return;
9351 }
9352
9353 /* Calculate the immediate operand.
9354 The operand is a 7bit signed number. */
9355 skip_whitespace (str);
9356
9357 if (*str == '#')
9358 ++str;
9359
9360 if (!ISDIGIT (*str) && *str != '-')
9361 {
9362 inst.error = _("expecting immediate, 7bit operand");
9363 return;
9364 }
9365
9366 if (*str == '-')
9367 {
9368 neg = 1;
9369 ++str;
9370 }
9371
9372 for (imm = 0; *str && ISDIGIT (*str); ++str)
9373 imm = imm * 10 + *str - '0';
9374
9375 if (imm > 64)
9376 {
9377 inst.error = _("immediate out of range");
9378 return;
9379 }
9380
9381 /* Make negative imm's into 7bit signed numbers. */
9382 if (neg)
9383 {
9384 imm = -imm;
9385 imm &= 0x0000007f;
9386 }
9387
9388 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9389 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9390 Bit 4 should be 0. */
9391 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9392
9393 inst.instruction |= imm;
9394 end_of_line (str);
6c43fab6
RE
9395}
9396
9397static void
a737bd4d 9398do_mav_shift_1 (char * str)
6c43fab6 9399{
a737bd4d 9400 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9401}
9402
9403static void
a737bd4d 9404do_mav_shift_2 (char * str)
6c43fab6 9405{
a737bd4d
NC
9406 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9407}
9408
9409static int
9410mav_parse_offset (char ** str, int * negative)
9411{
9412 char * p = *str;
9413 int offset;
9414
9415 *negative = 0;
9416
9417 skip_whitespace (p);
9418
9419 if (*p == '#')
9420 ++p;
9421
9422 if (*p == '-')
9423 {
9424 *negative = 1;
9425 ++p;
9426 }
9427
9428 if (!ISDIGIT (*p))
9429 {
9430 inst.error = _("offset expected");
9431 return 0;
9432 }
9433
9434 for (offset = 0; *p && ISDIGIT (*p); ++p)
9435 offset = offset * 10 + *p - '0';
9436
9437 if (offset > 0x3fc)
9438 {
9439 inst.error = _("offset out of range");
9440 return 0;
9441 }
9442 if (offset & 0x3)
9443 {
9444 inst.error = _("offset not a multiple of 4");
9445 return 0;
9446 }
9447
9448 *str = p;
9449
9450 return *negative ? -offset : offset;
6c43fab6
RE
9451}
9452
a737bd4d
NC
9453/* Maverick load/store instructions.
9454 <insn><cond> CRd,[Rn,<offset>]{!}.
9455 <insn><cond> CRd,[Rn],<offset>. */
9456
9457static void
9458do_mav_ldst (char * str, enum arm_reg_type reg0)
9459{
9460 int offset, negative;
9461
9462 skip_whitespace (str);
9463
9464 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9465 || skip_past_comma (&str) == FAIL
9466 || *str++ != '['
9467 || reg_required_here (&str, 16) == FAIL)
9468 goto fail_ldst;
9469
9470 if (skip_past_comma (&str) == SUCCESS)
9471 {
9472 /* You are here: "<offset>]{!}". */
9473 inst.instruction |= PRE_INDEX;
9474
9475 offset = mav_parse_offset (&str, &negative);
9476
9477 if (inst.error)
9478 return;
9479
9480 if (*str++ != ']')
9481 {
9482 inst.error = _("missing ]");
9483 return;
9484 }
9485
9486 if (*str == '!')
9487 {
9488 inst.instruction |= WRITE_BACK;
9489 ++str;
9490 }
9491 }
9492 else
9493 {
9494 /* You are here: "], <offset>". */
9495 if (*str++ != ']')
9496 {
9497 inst.error = _("missing ]");
9498 return;
9499 }
9500
9501 if (skip_past_comma (&str) == FAIL
9502 || (offset = mav_parse_offset (&str, &negative), inst.error))
9503 goto fail_ldst;
6c43fab6 9504
a737bd4d
NC
9505 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9506 }
6c43fab6 9507
a737bd4d
NC
9508 if (negative)
9509 offset = -offset;
9510 else
9511 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
6c43fab6 9512
a737bd4d
NC
9513 inst.instruction |= offset >> 2;
9514 end_of_line (str);
9515 return;
6c43fab6 9516
a737bd4d
NC
9517fail_ldst:
9518 if (!inst.error)
9519 inst.error = BAD_ARGS;
6c43fab6
RE
9520}
9521
9522static void
a737bd4d 9523do_mav_ldst_1 (char * str)
6c43fab6 9524{
a737bd4d 9525 do_mav_ldst (str, REG_TYPE_MVF);
6c43fab6
RE
9526}
9527
9528static void
a737bd4d 9529do_mav_ldst_2 (char * str)
6c43fab6 9530{
a737bd4d 9531 do_mav_ldst (str, REG_TYPE_MVD);
6c43fab6
RE
9532}
9533
9534static void
a737bd4d 9535do_mav_ldst_3 (char * str)
6c43fab6 9536{
a737bd4d 9537 do_mav_ldst (str, REG_TYPE_MVFX);
6c43fab6
RE
9538}
9539
9540static void
a737bd4d 9541do_mav_ldst_4 (char * str)
6c43fab6 9542{
a737bd4d 9543 do_mav_ldst (str, REG_TYPE_MVDX);
6c43fab6
RE
9544}
9545
9546static void
a737bd4d 9547do_t_nop (char * str)
6c43fab6 9548{
a737bd4d
NC
9549 /* Do nothing. */
9550 end_of_line (str);
6c43fab6
RE
9551}
9552
a737bd4d
NC
9553/* Handle the Format 4 instructions that do not have equivalents in other
9554 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9555 BIC and MVN. */
6c43fab6
RE
9556
9557static void
a737bd4d 9558do_t_arit (char * str)
6c43fab6 9559{
a737bd4d 9560 int Rd, Rs, Rn;
6c43fab6 9561
6c43fab6
RE
9562 skip_whitespace (str);
9563
a737bd4d 9564 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6c43fab6 9565 || skip_past_comma (&str) == FAIL
a737bd4d 9566 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6c43fab6 9567 {
a737bd4d 9568 inst.error = BAD_ARGS;
6c43fab6
RE
9569 return;
9570 }
9571
a737bd4d 9572 if (skip_past_comma (&str) != FAIL)
6c43fab6 9573 {
a737bd4d
NC
9574 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9575 (It isn't allowed for CMP either, but that isn't handled by this
9576 function.) */
9577 if (inst.instruction == T_OPCODE_TST
9578 || inst.instruction == T_OPCODE_CMN
9579 || inst.instruction == T_OPCODE_NEG
9580 || inst.instruction == T_OPCODE_MVN)
9581 {
9582 inst.error = BAD_ARGS;
9583 return;
9584 }
6c43fab6 9585
a737bd4d
NC
9586 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9587 return;
9588
9589 if (Rs != Rd)
9590 {
9591 inst.error = _("dest and source1 must be the same register");
9592 return;
9593 }
9594 Rs = Rn;
6c43fab6
RE
9595 }
9596
a737bd4d
NC
9597 if (inst.instruction == T_OPCODE_MUL
9598 && Rs == Rd)
9599 as_tsktsk (_("Rs and Rd must be different in MUL"));
9600
9601 inst.instruction |= Rd | (Rs << 3);
6c43fab6 9602 end_of_line (str);
404ff6b5
AH
9603}
9604
9605static void
a737bd4d 9606do_t_add (char * str)
404ff6b5 9607{
a737bd4d 9608 thumb_add_sub (str, 0);
404ff6b5
AH
9609}
9610
9611static void
a737bd4d 9612do_t_asr (char * str)
404ff6b5 9613{
a737bd4d 9614 thumb_shift (str, THUMB_ASR);
404ff6b5
AH
9615}
9616
9617static void
a737bd4d 9618do_t_branch9 (char * str)
404ff6b5 9619{
a737bd4d
NC
9620 if (my_get_expression (&inst.reloc.exp, &str))
9621 return;
9622 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9623 inst.reloc.pc_rel = 1;
9624 end_of_line (str);
404ff6b5
AH
9625}
9626
9627static void
a737bd4d 9628do_t_branch12 (char * str)
404ff6b5 9629{
a737bd4d
NC
9630 if (my_get_expression (&inst.reloc.exp, &str))
9631 return;
9632 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9633 inst.reloc.pc_rel = 1;
9634 end_of_line (str);
404ff6b5
AH
9635}
9636
a737bd4d 9637/* Find the real, Thumb encoded start of a Thumb function. */
404ff6b5 9638
a737bd4d
NC
9639static symbolS *
9640find_real_start (symbolS * symbolP)
404ff6b5 9641{
a737bd4d
NC
9642 char * real_start;
9643 const char * name = S_GET_NAME (symbolP);
9644 symbolS * new_target;
404ff6b5 9645
a737bd4d
NC
9646 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9647#define STUB_NAME ".real_start_of"
404ff6b5 9648
a737bd4d
NC
9649 if (name == NULL)
9650 abort ();
404ff6b5 9651
a737bd4d
NC
9652 /* Names that start with '.' are local labels, not function entry points.
9653 The compiler may generate BL instructions to these labels because it
9654 needs to perform a branch to a far away location. */
9655 if (name[0] == '.')
9656 return symbolP;
404ff6b5 9657
a737bd4d
NC
9658 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9659 sprintf (real_start, "%s%s", STUB_NAME, name);
404ff6b5 9660
a737bd4d
NC
9661 new_target = symbol_find (real_start);
9662
9663 if (new_target == NULL)
404ff6b5 9664 {
a737bd4d
NC
9665 as_warn ("Failed to find real start of function: %s\n", name);
9666 new_target = symbolP;
404ff6b5 9667 }
404ff6b5 9668
a737bd4d
NC
9669 free (real_start);
9670
9671 return new_target;
9672}
404ff6b5
AH
9673
9674static void
a737bd4d 9675do_t_branch23 (char * str)
404ff6b5 9676{
a737bd4d
NC
9677 if (my_get_expression (& inst.reloc.exp, & str))
9678 return;
404ff6b5 9679
a737bd4d
NC
9680 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9681 inst.reloc.pc_rel = 1;
9682 end_of_line (str);
404ff6b5 9683
a737bd4d
NC
9684 /* If the destination of the branch is a defined symbol which does not have
9685 the THUMB_FUNC attribute, then we must be calling a function which has
9686 the (interfacearm) attribute. We look for the Thumb entry point to that
9687 function and change the branch to refer to that function instead. */
9688 if ( inst.reloc.exp.X_op == O_symbol
9689 && inst.reloc.exp.X_add_symbol != NULL
9690 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9691 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9692 inst.reloc.exp.X_add_symbol =
9693 find_real_start (inst.reloc.exp.X_add_symbol);
404ff6b5
AH
9694}
9695
404ff6b5 9696static void
a737bd4d 9697do_t_bx (char * str)
404ff6b5 9698{
a737bd4d 9699 int reg;
404ff6b5
AH
9700
9701 skip_whitespace (str);
9702
a737bd4d
NC
9703 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9704 return;
9705
9706 /* This sets THUMB_H2 from the top bit of reg. */
9707 inst.instruction |= reg << 3;
9708
9709 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9710 should cause the alignment to be checked once it is known. This is
9711 because BX PC only works if the instruction is word aligned. */
9712
9713 end_of_line (str);
404ff6b5
AH
9714}
9715
a737bd4d
NC
9716static void
9717do_t_compare (char * str)
9718{
9719 thumb_mov_compare (str, THUMB_COMPARE);
9720}
404ff6b5
AH
9721
9722static void
a737bd4d 9723do_t_ldmstm (char * str)
404ff6b5 9724{
a737bd4d
NC
9725 int Rb;
9726 long range;
404ff6b5
AH
9727
9728 skip_whitespace (str);
9729
a737bd4d
NC
9730 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9731 return;
404ff6b5 9732
a737bd4d
NC
9733 if (*str != '!')
9734 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9735 else
9736 str++;
9737
9738 if (skip_past_comma (&str) == FAIL
9739 || (range = reg_list (&str)) == FAIL)
404ff6b5 9740 {
a737bd4d 9741 if (! inst.error)
404ff6b5
AH
9742 inst.error = BAD_ARGS;
9743 return;
9744 }
9745
620b81c1 9746 if (inst.reloc.type != BFD_RELOC_UNUSED)
404ff6b5 9747 {
a737bd4d 9748 /* This really doesn't seem worth it. */
620b81c1 9749 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d 9750 inst.error = _("expression too complex");
404ff6b5
AH
9751 return;
9752 }
9753
a737bd4d 9754 if (range & ~0xff)
404ff6b5 9755 {
a737bd4d 9756 inst.error = _("only lo-regs valid in load/store multiple");
404ff6b5
AH
9757 return;
9758 }
9759
a737bd4d 9760 inst.instruction |= (Rb << 8) | range;
404ff6b5 9761 end_of_line (str);
404ff6b5
AH
9762}
9763
a737bd4d
NC
9764static void
9765do_t_ldr (char * str)
404ff6b5 9766{
a737bd4d
NC
9767 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9768}
404ff6b5 9769
a737bd4d
NC
9770static void
9771do_t_ldrb (char * str)
9772{
9773 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9774}
404ff6b5 9775
a737bd4d
NC
9776static void
9777do_t_ldrh (char * str)
9778{
9779 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9780}
404ff6b5 9781
a737bd4d
NC
9782static void
9783do_t_lds (char * str)
9784{
9785 int Rd, Rb, Ro;
404ff6b5 9786
a737bd4d 9787 skip_whitespace (str);
404ff6b5 9788
a737bd4d
NC
9789 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9790 || skip_past_comma (&str) == FAIL
9791 || *str++ != '['
9792 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9793 || skip_past_comma (&str) == FAIL
9794 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9795 || *str++ != ']')
404ff6b5 9796 {
a737bd4d
NC
9797 if (! inst.error)
9798 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9799 return;
404ff6b5
AH
9800 }
9801
a737bd4d
NC
9802 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9803 end_of_line (str);
9804}
404ff6b5 9805
a737bd4d
NC
9806static void
9807do_t_lsl (char * str)
9808{
9809 thumb_shift (str, THUMB_LSL);
9810}
404ff6b5 9811
a737bd4d
NC
9812static void
9813do_t_lsr (char * str)
9814{
9815 thumb_shift (str, THUMB_LSR);
404ff6b5
AH
9816}
9817
a737bd4d
NC
9818static void
9819do_t_mov (char * str)
9820{
9821 thumb_mov_compare (str, THUMB_MOVE);
9822}
404ff6b5
AH
9823
9824static void
a737bd4d 9825do_t_push_pop (char * str)
404ff6b5 9826{
a737bd4d 9827 long range;
404ff6b5
AH
9828
9829 skip_whitespace (str);
9830
a737bd4d 9831 if ((range = reg_list (&str)) == FAIL)
404ff6b5 9832 {
a737bd4d
NC
9833 if (! inst.error)
9834 inst.error = BAD_ARGS;
9835 return;
9836 }
404ff6b5 9837
620b81c1 9838 if (inst.reloc.type != BFD_RELOC_UNUSED)
a737bd4d
NC
9839 {
9840 /* This really doesn't seem worth it. */
620b81c1 9841 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d
NC
9842 inst.error = _("expression too complex");
9843 return;
9844 }
404ff6b5 9845
a737bd4d
NC
9846 if (range & ~0xff)
9847 {
9848 if ((inst.instruction == T_OPCODE_PUSH
9849 && (range & ~0xff) == 1 << REG_LR)
9850 || (inst.instruction == T_OPCODE_POP
9851 && (range & ~0xff) == 1 << REG_PC))
404ff6b5 9852 {
a737bd4d
NC
9853 inst.instruction |= THUMB_PP_PC_LR;
9854 range &= 0xff;
404ff6b5 9855 }
a737bd4d 9856 else
404ff6b5 9857 {
a737bd4d 9858 inst.error = _("invalid register list to push/pop instruction");
404ff6b5
AH
9859 return;
9860 }
404ff6b5
AH
9861 }
9862
a737bd4d 9863 inst.instruction |= range;
404ff6b5 9864 end_of_line (str);
a737bd4d 9865}
404ff6b5 9866
a737bd4d
NC
9867static void
9868do_t_str (char * str)
9869{
9870 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
404ff6b5
AH
9871}
9872
b99bd4ef 9873static void
a737bd4d 9874do_t_strb (char * str)
b99bd4ef 9875{
a737bd4d 9876 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
b99bd4ef
NC
9877}
9878
a737bd4d
NC
9879static void
9880do_t_strh (char * str)
9881{
9882 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9883}
b99bd4ef
NC
9884
9885static void
a737bd4d 9886do_t_sub (char * str)
b99bd4ef 9887{
a737bd4d
NC
9888 thumb_add_sub (str, 1);
9889}
b99bd4ef 9890
a737bd4d
NC
9891static void
9892do_t_swi (char * str)
9893{
b99bd4ef
NC
9894 skip_whitespace (str);
9895
a737bd4d
NC
9896 if (my_get_expression (&inst.reloc.exp, &str))
9897 return;
b99bd4ef 9898
a737bd4d
NC
9899 inst.reloc.type = BFD_RELOC_ARM_SWI;
9900 end_of_line (str);
9901}
b99bd4ef 9902
a737bd4d
NC
9903static void
9904do_t_adr (char * str)
9905{
9906 int reg;
b99bd4ef 9907
a737bd4d
NC
9908 /* This is a pseudo-op of the form "adr rd, label" to be converted
9909 into a relative address of the form "add rd, pc, #label-.-4". */
9910 skip_whitespace (str);
9911
9912 /* Store Rd in temporary location inside instruction. */
9913 if ((reg = reg_required_here (&str, 4)) == FAIL
9914 || (reg > 7) /* For Thumb reg must be r0..r7. */
9915 || skip_past_comma (&str) == FAIL
9916 || my_get_expression (&inst.reloc.exp, &str))
9917 {
9918 if (!inst.error)
9919 inst.error = BAD_ARGS;
9920 return;
b99bd4ef
NC
9921 }
9922
a737bd4d
NC
9923 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9924 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9925 inst.reloc.pc_rel = 1;
9926 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
b99bd4ef 9927
b99bd4ef
NC
9928 end_of_line (str);
9929}
9930
9931static void
a737bd4d
NC
9932insert_reg (const struct reg_entry * r,
9933 struct hash_control * htab)
b99bd4ef 9934{
a737bd4d
NC
9935 int len = strlen (r->name) + 2;
9936 char * buf = xmalloc (len);
9937 char * buf2 = xmalloc (len);
9938 int i = 0;
b99bd4ef 9939
a737bd4d
NC
9940#ifdef REGISTER_PREFIX
9941 buf[i++] = REGISTER_PREFIX;
9942#endif
9943
9944 strcpy (buf + i, r->name);
9945
9946 for (i = 0; buf[i]; i++)
9947 buf2[i] = TOUPPER (buf[i]);
9948
9949 buf2[i] = '\0';
9950
9951 hash_insert (htab, buf, (PTR) r);
9952 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9953}
9954
9955static void
a737bd4d 9956build_reg_hsh (struct reg_map * map)
b99bd4ef 9957{
a737bd4d
NC
9958 const struct reg_entry *r;
9959
9960 if ((map->htab = hash_new ()) == NULL)
9961 as_fatal (_("virtual memory exhausted"));
9962
9963 for (r = map->names; r->name != NULL; r++)
9964 insert_reg (r, map->htab);
b99bd4ef
NC
9965}
9966
9967static void
a737bd4d
NC
9968insert_reg_alias (char * str,
9969 int regnum,
9970 struct hash_control *htab)
b99bd4ef 9971{
a737bd4d
NC
9972 const char * error;
9973 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9974 const char * name = xmalloc (strlen (str) + 1);
9975
9976 strcpy ((char *) name, str);
9977
9978 new->name = name;
9979 new->number = regnum;
9980 new->builtin = FALSE;
9981
9982 error = hash_insert (htab, name, (PTR) new);
9983 if (error)
9984 {
9985 as_bad (_("failed to create an alias for %s, reason: %s"),
9986 str, error);
9987 free ((char *) name);
9988 free (new);
9989 }
b99bd4ef
NC
9990}
9991
a737bd4d 9992/* Look for the .req directive. This is of the form:
b99bd4ef 9993
a737bd4d
NC
9994 new_register_name .req existing_register_name
9995
9996 If we find one, or if it looks sufficiently like one that we want to
9997 handle any error here, return non-zero. Otherwise return zero. */
9998
9999static int
10000create_register_alias (char * newname, char * p)
b99bd4ef 10001{
a737bd4d
NC
10002 char * q;
10003 char c;
b99bd4ef 10004
a737bd4d
NC
10005 q = p;
10006 skip_whitespace (q);
b99bd4ef 10007
a737bd4d
NC
10008 c = *p;
10009 *p = '\0';
b99bd4ef 10010
a737bd4d
NC
10011 if (*q && !strncmp (q, ".req ", 5))
10012 {
10013 char *copy_of_str;
10014 char *r;
b99bd4ef 10015
a737bd4d
NC
10016#ifndef IGNORE_OPCODE_CASE
10017 newname = original_case_string;
10018#endif
10019 copy_of_str = newname;
b99bd4ef 10020
a737bd4d
NC
10021 q += 4;
10022 skip_whitespace (q);
b99bd4ef 10023
a737bd4d
NC
10024 for (r = q; *r != '\0'; r++)
10025 if (*r == ' ')
10026 break;
b99bd4ef 10027
a737bd4d
NC
10028 if (r != q)
10029 {
10030 enum arm_reg_type new_type, old_type;
10031 int old_regno;
10032 char d = *r;
b99bd4ef 10033
a737bd4d
NC
10034 *r = '\0';
10035 old_type = arm_reg_parse_any (q);
10036 *r = d;
10037
10038 new_type = arm_reg_parse_any (newname);
10039
10040 if (new_type == REG_TYPE_MAX)
10041 {
10042 if (old_type != REG_TYPE_MAX)
10043 {
10044 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10045 insert_reg_alias (newname, old_regno,
10046 all_reg_maps[old_type].htab);
10047 }
10048 else
10049 as_warn (_("register '%s' does not exist\n"), q);
10050 }
10051 else if (old_type == REG_TYPE_MAX)
10052 {
10053 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10054 copy_of_str, q);
10055 }
10056 else
10057 {
10058 /* Do not warn about redefinitions to the same alias. */
10059 if (new_type != old_type
10060 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10061 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10062 as_warn (_("ignoring redefinition of register alias '%s'"),
10063 copy_of_str);
10064
10065 }
10066 }
10067 else
10068 as_warn (_("ignoring incomplete .req pseuso op"));
10069
10070 *p = c;
10071 return 1;
10072 }
10073
10074 *p = c;
10075 return 0;
b99bd4ef
NC
10076}
10077
10078static void
a737bd4d 10079set_constant_flonums (void)
b99bd4ef 10080{
a737bd4d 10081 int i;
b99bd4ef 10082
a737bd4d
NC
10083 for (i = 0; i < NUM_FLOAT_VALS; i++)
10084 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10085 abort ();
b99bd4ef
NC
10086}
10087
a737bd4d
NC
10088\f
10089static const struct asm_opcode insns[] =
b99bd4ef 10090{
a737bd4d
NC
10091 /* Core ARM Instructions. */
10092 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10093 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10094 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10095 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10096 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10097 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10098 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10099 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10100 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10101 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10102 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10103 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10104 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10105 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10106 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10107 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10108 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10109 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10110 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10111 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10112
10113 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10114 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10115 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10116 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10117 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10118 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10119 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10120 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10121 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10122 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10123 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10124 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10125
10126 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10127 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10128 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10129 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10130
10131 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10132 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10133 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10134 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10135 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10136 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10137 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10138 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10139
10140 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10141 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10142 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10143 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10144 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10145 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10146 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10147 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10148
10149 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10150 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10151 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10152 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10153 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10154 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10155 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10156 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
b99bd4ef 10157
a737bd4d
NC
10158 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10159#ifdef TE_WINCE
10160 /* XXX This is the wrong place to do this. Think multi-arch. */
10161 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10162 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10163#else
10164 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10165 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10166#endif
b99bd4ef 10167
a737bd4d
NC
10168 /* Pseudo ops. */
10169 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10170 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
0dd132b6 10171 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
b99bd4ef 10172
a737bd4d
NC
10173 /* ARM 2 multiplies. */
10174 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10175 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10176 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10177 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 10178
a737bd4d
NC
10179 /* Generic coprocessor instructions. */
10180 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10181 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10182 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10183 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10184 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10185 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10186 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
b99bd4ef 10187
a737bd4d
NC
10188 /* ARM 3 - swp instructions. */
10189 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10190 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 10191
a737bd4d
NC
10192 /* ARM 6 Status register instructions. */
10193 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10194 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10195 /* ScottB: our code uses 0xe128f000 for msr.
10196 NickC: but this is wrong because the bits 16 through 19 are
10197 handled by the PSR_xxx defines above. */
b99bd4ef 10198
a737bd4d
NC
10199 /* ARM 7M long multiplies. */
10200 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10201 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10202 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10203 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10204 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10205 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10206 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10207 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
b99bd4ef 10208
a737bd4d
NC
10209 /* ARM Architecture 4. */
10210 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10211 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10212 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10213 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 10214
a737bd4d
NC
10215 /* ARM Architecture 4T. */
10216 /* Note: bx (and blx) are required on V5, even if the processor does
10217 not support Thumb. */
10218 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
b99bd4ef 10219
a737bd4d
NC
10220 /* ARM Architecture 5T. */
10221 /* Note: blx has 2 variants, so the .value is set dynamically.
10222 Only one of the variants has conditional execution. */
10223 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10224 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10225 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10226 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10227 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10228 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10229 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10230 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10231 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10232 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
b99bd4ef 10233
a737bd4d
NC
10234 /* ARM Architecture 5TExP. */
10235 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10236 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10237 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10238 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 10239
a737bd4d
NC
10240 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10241 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 10242
a737bd4d
NC
10243 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10244 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10245 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10246 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
b99bd4ef 10247
a737bd4d
NC
10248 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10249 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10250 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10251 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 10252
a737bd4d
NC
10253 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10254 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 10255
a737bd4d
NC
10256 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10257 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10258 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10259 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
b99bd4ef 10260
a737bd4d
NC
10261 /* ARM Architecture 5TE. */
10262 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10263 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10264 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
b99bd4ef 10265
a737bd4d
NC
10266 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10267 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
b99bd4ef 10268
a737bd4d
NC
10269 /* ARM Architecture 5TEJ. */
10270 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
b99bd4ef 10271
a737bd4d
NC
10272 /* ARM V6. */
10273 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10274 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10275 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10276 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10277 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10278 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10279 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10280 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10281 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10282 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10283 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10284 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10285 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10286 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10287 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10288 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10289 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10290 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10291 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10292 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10293 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10294 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10295 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10296 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10297 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10298 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10299 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10300 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10301 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10302 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10303 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10304 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10305 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10306 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10307 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10308 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10309 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10310 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10311 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10312 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10313 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10314 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10315 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10316 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10317 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10318 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10319 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10320 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10321 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10322 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10323 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10324 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10325 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10326 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10327 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10328 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10329 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10330 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10331 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10332 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10333 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10334 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10335 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10336 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10337 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10338 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10339 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10340 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10341 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10342 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10343 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10344 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10345 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10346 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10347 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10348 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10349 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10350 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10351 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10352 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10353 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10354 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10355 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10356 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10357 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10358 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10359 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10360 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10361 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10362 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10363 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10364 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10365 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10366 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10367 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10368 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10369 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10370 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10371 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
b99bd4ef 10372
0dd132b6
NC
10373 /* ARM V6K. */
10374 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10375 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10376 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10377 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10378 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10379 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10380 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10381 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10382 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10383 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10384 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
7ed4c4c5 10385
0dd132b6
NC
10386 /* ARM V6Z. */
10387 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10388
b05fe5cf
ZW
10389 /* ARM V6T2. */
10390 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10391 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10392 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10393 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10394 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10395 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10396 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10397 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10398
10399 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10400 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10401 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10402 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10403
a737bd4d
NC
10404 /* Core FPA instruction set (V1). */
10405 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10406 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10407 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10408 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
b99bd4ef 10409
a737bd4d
NC
10410 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10411 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10412 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10413 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10414
a737bd4d
NC
10415 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10416 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10417 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10418 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10419
a737bd4d
NC
10420 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10421 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10422 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10423 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10424 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10425 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10426 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10427 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10428 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10429 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10430 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10431 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10432
a737bd4d
NC
10433 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10444 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10445
a737bd4d
NC
10446 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10457 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10458
a737bd4d
NC
10459 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10470 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10471
a737bd4d
NC
10472 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10483 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10484
a737bd4d
NC
10485 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10496 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10497
a737bd4d
NC
10498 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10509 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10510
a737bd4d
NC
10511 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10522 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10523
a737bd4d
NC
10524 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10535 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10536
a737bd4d
NC
10537 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10548 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10549
a737bd4d
NC
10550 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10561 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10562
a737bd4d
NC
10563 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10573 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10574 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10575
a737bd4d
NC
10576 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10577 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10578 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10579 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10580 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10581 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10582 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10583 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10584 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10585 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10586 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10587 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10588
a737bd4d
NC
10589 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10590 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10591 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10592 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10593 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10594 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10595 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10596 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10597 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10598 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10599 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10600 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10601
a737bd4d
NC
10602 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10603 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10604 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10605 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10606 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10607 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10608 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10609 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10610 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10611 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10612 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10613 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10614
a737bd4d
NC
10615 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10616 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10617 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10618 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10619 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10620 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10621 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10622 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10623 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10624 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10625 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10626 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10627
a737bd4d
NC
10628 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10629 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10630 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10631 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10632 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10633 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10634 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10635 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10636 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10637 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10638 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10639 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10640
a737bd4d
NC
10641 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10652 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10653
a737bd4d
NC
10654 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10665 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10666
a737bd4d
NC
10667 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10678 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10679
a737bd4d
NC
10680 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10691 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10692
a737bd4d
NC
10693 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10704 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10705
a737bd4d
NC
10706 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10717 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10718
a737bd4d
NC
10719 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10730 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10731
a737bd4d
NC
10732 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10742 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10743 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10744
a737bd4d
NC
10745 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10746 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10747 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10748 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10749 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10750 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10751 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10752 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10753 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10754 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10755 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10756 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10757
a737bd4d
NC
10758 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10759 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10760 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10761 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10762 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10763 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10764 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10765 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10766 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10767 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10768 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10769 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10770
a737bd4d
NC
10771 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10772 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10773 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10774 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10775 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10776 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10777 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10778 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10779 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10780 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10781 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10782 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10783
a737bd4d
NC
10784 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10785 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10786 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10787 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10788 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10789 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10790 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10791 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10792 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10793 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10794 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10795 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10796
a737bd4d
NC
10797 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10798 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10799 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10800 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10801 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10802 not be an optional suffix, but part of the instruction. To be
10803 compatible, we accept either. */
10804 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10805 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
b99bd4ef 10806
a737bd4d
NC
10807 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10808 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10809 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10810 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10811 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10812 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10813 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10814 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10815 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10816 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10817 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10818 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
6c43fab6 10819
a737bd4d
NC
10820 /* The implementation of the FIX instruction is broken on some
10821 assemblers, in that it accepts a precision specifier as well as a
10822 rounding specifier, despite the fact that this is meaningless.
10823 To be more compatible, we accept it as well, though of course it
10824 does not set any bits. */
10825 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10826 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10827 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10828 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10829 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10830 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10831 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10832 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10833 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10834 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10835 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10836 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10837 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
6c43fab6 10838
a737bd4d
NC
10839 /* Instructions that were new with the real FPA, call them V2. */
10840 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10841 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10842 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10843 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10844 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10845 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
6c43fab6 10846
a737bd4d
NC
10847 /* VFP V1xD (single precision). */
10848 /* Moves and type conversions. */
10849 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10850 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10851 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10852 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10853 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10854 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10855 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10856 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10857 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10858 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10859 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10860 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
6c43fab6 10861
a737bd4d
NC
10862 /* Memory operations. */
10863 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10864 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10865 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10866 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10867 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10868 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10869 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10870 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10871 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10872 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10873 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10874 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10875 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10876 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10877 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10878 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10879 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10880 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
6c43fab6 10881
a737bd4d
NC
10882 /* Monadic operations. */
10883 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10884 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10885 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
6c43fab6 10886
a737bd4d
NC
10887 /* Dyadic operations. */
10888 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10889 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10890 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10891 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10892 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10893 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10894 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10895 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10896 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
6c43fab6 10897
a737bd4d
NC
10898 /* Comparisons. */
10899 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10900 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10901 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10902 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
6c43fab6 10903
a737bd4d
NC
10904 /* VFP V1 (Double precision). */
10905 /* Moves and type conversions. */
10906 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10907 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10908 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10909 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10910 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10911 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10912 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10913 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10914 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10915 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10916 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10917 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10918 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
6c43fab6 10919
a737bd4d
NC
10920 /* Memory operations. */
10921 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10922 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10923 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10924 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10925 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10926 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10927 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10928 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10929 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10930 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
6c43fab6 10931
a737bd4d
NC
10932 /* Monadic operations. */
10933 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10934 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10935 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
6c43fab6 10936
a737bd4d
NC
10937 /* Dyadic operations. */
10938 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10939 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10940 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10941 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10942 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10943 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10944 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10945 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10946 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
6c43fab6 10947
a737bd4d
NC
10948 /* Comparisons. */
10949 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10950 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10951 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10952 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
6c43fab6 10953
a737bd4d
NC
10954 /* VFP V2. */
10955 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10956 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10957 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10958 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
6c43fab6 10959
a737bd4d
NC
10960 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10961 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10962 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10963 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10964 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10965 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10966 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10967 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10968 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
cc8a6dd0 10969
a737bd4d
NC
10970 /* Intel Wireless MMX technology instructions. */
10971 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10972 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10973 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10974 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10975 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10976 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10977 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10978 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10979 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10980 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10981 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10982 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10983 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10984 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10985 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10986 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10987 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10988 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10989 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
10990 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
10991 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10992 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10993 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10994 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10995 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10996 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
10997 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10998 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
10999 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11000 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
11001 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
11002 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11003 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11004 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11005 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11006 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11007 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11008 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11009 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11010 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11011 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11012 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11013 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11014 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11015 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11016 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11017 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
11018 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11019 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11020 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11021 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11026 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11028 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11030 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11032 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11034 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11036 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11038 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11039 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11040 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11041 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11042 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11044 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11045 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11046 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11047 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11048 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11050 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11051 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11052 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11053 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11058 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11059 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11060 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11061 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11062 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11063 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11064 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11067 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11068 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11069 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11070 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11071 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11072 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11073 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11075 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11077 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11078 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11079 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11080 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11081 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11082 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11083 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11084 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11085 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11086 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11087 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11088 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11089 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11090 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11091 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11092 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11093 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11094 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11095 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11096 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11097 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11098 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11099 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11100 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11101 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11102 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11103 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11104 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11105 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11106 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11107 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11108 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11109 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11110 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11111 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11112 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11113 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11114 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11115 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11116 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11117 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11118 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11119 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11120 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11121 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11122 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11123 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11124 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11125 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11126 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11127 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11128 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11129 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11130 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11131 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11132 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
b99bd4ef 11133
a737bd4d
NC
11134 /* Cirrus Maverick instructions. */
11135 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11136 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11137 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11138 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11139 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11140 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11141 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11142 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11143 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11144 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11145 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11146 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11147 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11148 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11149 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11150 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11151 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11152 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11153 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11154 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11155 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11156 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11157 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11158 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11159 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11160 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11161 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11162 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11163 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11164 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11165 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11166 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11167 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11168 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11169 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11170 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11171 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11172 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11173 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11174 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11175 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11176 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11177 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11178 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11179 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11180 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11181 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11182 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11183 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11184 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11185 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11186 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11187 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11188 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11189 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11190 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11191 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11192 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11193 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11194 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11195 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11196 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11197 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11198 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11199 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11200 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11201 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11202 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11203 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11204 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11205 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11206 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11207 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11208 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11209 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11210 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11211};
b99bd4ef 11212
90e4755a 11213/* Iterate over the base tables to create the instruction patterns. */
a737bd4d 11214
90e4755a 11215static void
a737bd4d 11216build_arm_ops_hsh (void)
90e4755a
RE
11217{
11218 unsigned int i;
11219 unsigned int j;
11220 static struct obstack insn_obstack;
11221
11222 obstack_begin (&insn_obstack, 4000);
11223
11224 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11225 {
6c43fab6 11226 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11227
11228 if (insn->cond_offset != 0)
11229 {
11230 /* Insn supports conditional execution. Build the varaints
11231 and insert them in the hash table. */
11232 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11233 {
11234 unsigned len = strlen (insn->template);
11235 struct asm_opcode *new;
11236 char *template;
11237
11238 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11239 /* All condition codes are two characters. */
11240 template = obstack_alloc (&insn_obstack, len + 3);
11241
11242 strncpy (template, insn->template, insn->cond_offset);
11243 strcpy (template + insn->cond_offset, conds[j].template);
11244 if (len > insn->cond_offset)
11245 strcpy (template + insn->cond_offset + 2,
11246 insn->template + insn->cond_offset);
11247 new->template = template;
11248 new->cond_offset = 0;
11249 new->variant = insn->variant;
11250 new->parms = insn->parms;
11251 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11252
11253 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11254 }
11255 }
11256 /* Finally, insert the unconditional insn in the table directly;
11257 no need to build a copy. */
11258 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11259 }
11260}
11261
a737bd4d
NC
11262\f
11263static const struct thumb_opcode tinsns[] =
11264{
11265 /* Thumb v1 (ARMv4T). */
11266 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11267 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11268 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11269 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11270 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11271 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11272 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11273 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11274 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11275 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11276 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11277 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11278 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11279 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11280 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11281 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11282 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11283 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11284 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11285 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11286 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11287 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11288 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11289 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11290 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11291 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11292 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11293 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11294 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11295 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11296 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11297 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11298 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11299 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11300 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11301 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11302 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11303 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11304 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11305 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11306 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11307 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11308 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11309 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11310 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11311 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11312 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11313 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11314 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11315 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11316 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11317 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11318 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11319 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11320 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11321 /* Pseudo ops: */
11322 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11323 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11324 /* Thumb v2 (ARMv5T). */
11325 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11326 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11327
11328 /* ARM V6. */
11329 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11330 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11331 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11332 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11333 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11334 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11335 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11336 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11337 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11338 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11339 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
885fc257
ZW
11340
11341 /* ARM V6K. */
11342 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11343 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11344 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11345 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
a737bd4d 11346};
5a6c6817 11347
b99bd4ef 11348void
a737bd4d 11349md_begin (void)
b99bd4ef
NC
11350{
11351 unsigned mach;
11352 unsigned int i;
11353
11354 if ( (arm_ops_hsh = hash_new ()) == NULL
11355 || (arm_tops_hsh = hash_new ()) == NULL
11356 || (arm_cond_hsh = hash_new ()) == NULL
11357 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11358 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11359 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11360
90e4755a 11361 build_arm_ops_hsh ();
b99bd4ef
NC
11362 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11363 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11364 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11365 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11366 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11367 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11368 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11369 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11370
6c43fab6
RE
11371 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11372 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11373
11374 set_constant_flonums ();
11375
03b1477f
RE
11376 /* Set the cpu variant based on the command-line options. We prefer
11377 -mcpu= over -march= if both are set (as for GCC); and we prefer
11378 -mfpu= over any other way of setting the floating point unit.
11379 Use of legacy options with new options are faulted. */
11380 if (legacy_cpu != -1)
11381 {
11382 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11383 as_bad (_("use of old and new-style options to set CPU type"));
11384
11385 mcpu_cpu_opt = legacy_cpu;
11386 }
11387 else if (mcpu_cpu_opt == -1)
11388 mcpu_cpu_opt = march_cpu_opt;
11389
11390 if (legacy_fpu != -1)
11391 {
11392 if (mfpu_opt != -1)
11393 as_bad (_("use of old and new-style options to set FPU type"));
11394
11395 mfpu_opt = legacy_fpu;
11396 }
11397 else if (mfpu_opt == -1)
11398 {
4e7fd91e 11399#if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
39c2da32
RE
11400 /* Some environments specify a default FPU. If they don't, infer it
11401 from the processor. */
03b1477f
RE
11402 if (mcpu_fpu_opt != -1)
11403 mfpu_opt = mcpu_fpu_opt;
11404 else
11405 mfpu_opt = march_fpu_opt;
39c2da32
RE
11406#else
11407 mfpu_opt = FPU_DEFAULT;
11408#endif
03b1477f
RE
11409 }
11410
11411 if (mfpu_opt == -1)
11412 {
11413 if (mcpu_cpu_opt == -1)
11414 mfpu_opt = FPU_DEFAULT;
11415 else if (mcpu_cpu_opt & ARM_EXT_V5)
11416 mfpu_opt = FPU_ARCH_VFP_V2;
11417 else
11418 mfpu_opt = FPU_ARCH_FPA;
11419 }
11420
11421 if (mcpu_cpu_opt == -1)
11422 mcpu_cpu_opt = CPU_DEFAULT;
11423
11424 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11425
f17c130b 11426#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef 11427 {
7cc69913
NC
11428 unsigned int flags = 0;
11429
11430#if defined OBJ_ELF
11431 flags = meabi_flags;
d507cf36
PB
11432
11433 switch (meabi_flags)
33a392fb 11434 {
d507cf36 11435 case EF_ARM_EABI_UNKNOWN:
7cc69913 11436#endif
d507cf36
PB
11437 /* Set the flags in the private structure. */
11438 if (uses_apcs_26) flags |= F_APCS26;
11439 if (support_interwork) flags |= F_INTERWORK;
11440 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11441 if (pic_code) flags |= F_PIC;
11442 if ((cpu_variant & FPU_ANY) == FPU_NONE
11443 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11444 flags |= F_SOFT_FLOAT;
11445
d507cf36
PB
11446 switch (mfloat_abi_opt)
11447 {
11448 case ARM_FLOAT_ABI_SOFT:
11449 case ARM_FLOAT_ABI_SOFTFP:
11450 flags |= F_SOFT_FLOAT;
11451 break;
33a392fb 11452
d507cf36
PB
11453 case ARM_FLOAT_ABI_HARD:
11454 if (flags & F_SOFT_FLOAT)
11455 as_bad (_("hard-float conflicts with specified fpu"));
11456 break;
11457 }
03b1477f 11458
7cc69913
NC
11459 /* Using VFP conventions (even if soft-float). */
11460 if (cpu_variant & FPU_VFP_EXT_NONE)
11461 flags |= F_VFP_FLOAT;
f17c130b 11462
fde78edd 11463#if defined OBJ_ELF
d507cf36
PB
11464 if (cpu_variant & FPU_ARCH_MAVERICK)
11465 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11466 break;
11467
8cb51566 11468 case EF_ARM_EABI_VER4:
d507cf36
PB
11469 /* No additional flags to set. */
11470 break;
11471
11472 default:
11473 abort ();
11474 }
7cc69913 11475#endif
b99bd4ef
NC
11476 bfd_set_private_flags (stdoutput, flags);
11477
11478 /* We have run out flags in the COFF header to encode the
11479 status of ATPCS support, so instead we create a dummy,
11480 empty, debug section called .arm.atpcs. */
11481 if (atpcs)
11482 {
11483 asection * sec;
11484
11485 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11486
11487 if (sec != NULL)
11488 {
11489 bfd_set_section_flags
11490 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11491 bfd_set_section_size (stdoutput, sec, 0);
11492 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11493 }
11494 }
7cc69913 11495 }
f17c130b 11496#endif
b99bd4ef
NC
11497
11498 /* Record the CPU type as well. */
11499 switch (cpu_variant & ARM_CPU_MASK)
11500 {
11501 case ARM_2:
11502 mach = bfd_mach_arm_2;
11503 break;
11504
11505 case ARM_3: /* Also ARM_250. */
11506 mach = bfd_mach_arm_2a;
11507 break;
11508
b89dddec
RE
11509 case ARM_6: /* Also ARM_7. */
11510 mach = bfd_mach_arm_3;
11511 break;
11512
b99bd4ef 11513 default:
5a6c6817 11514 mach = bfd_mach_arm_unknown;
b99bd4ef 11515 break;
b99bd4ef
NC
11516 }
11517
11518 /* Catch special cases. */
e16bb312
NC
11519 if (cpu_variant & ARM_CEXT_IWMMXT)
11520 mach = bfd_mach_arm_iWMMXt;
11521 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11522 mach = bfd_mach_arm_XScale;
fde78edd
NC
11523 else if (cpu_variant & ARM_CEXT_MAVERICK)
11524 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11525 else if (cpu_variant & ARM_EXT_V5E)
11526 mach = bfd_mach_arm_5TE;
11527 else if (cpu_variant & ARM_EXT_V5)
11528 {
b89dddec 11529 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11530 mach = bfd_mach_arm_5T;
11531 else
11532 mach = bfd_mach_arm_5;
11533 }
b89dddec 11534 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11535 {
b89dddec 11536 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11537 mach = bfd_mach_arm_4T;
11538 else
11539 mach = bfd_mach_arm_4;
11540 }
b89dddec 11541 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11542 mach = bfd_mach_arm_3M;
11543
11544 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11545}
11546
11547/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11548 for use in the a.out file, and stores them in the array pointed to by buf.
11549 This knows about the endian-ness of the target machine and does
11550 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11551 2 (short) and 4 (long) Floating numbers are put out as a series of
11552 LITTLENUMS (shorts, here at least). */
11553
11554void
a737bd4d 11555md_number_to_chars (char * buf, valueT val, int n)
b99bd4ef
NC
11556{
11557 if (target_big_endian)
11558 number_to_chars_bigendian (buf, val, n);
11559 else
11560 number_to_chars_littleendian (buf, val, n);
11561}
11562
11563static valueT
a737bd4d 11564md_chars_to_number (char * buf, int n)
b99bd4ef
NC
11565{
11566 valueT result = 0;
11567 unsigned char * where = (unsigned char *) buf;
11568
11569 if (target_big_endian)
11570 {
11571 while (n--)
11572 {
11573 result <<= 8;
11574 result |= (*where++ & 255);
11575 }
11576 }
11577 else
11578 {
11579 while (n--)
11580 {
11581 result <<= 8;
11582 result |= (where[n] & 255);
11583 }
11584 }
11585
11586 return result;
11587}
11588
11589/* Turn a string in input_line_pointer into a floating point constant
11590 of type TYPE, and store the appropriate bytes in *LITP. The number
11591 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11592 returned, or NULL on OK.
11593
11594 Note that fp constants aren't represent in the normal way on the ARM.
11595 In big endian mode, things are as expected. However, in little endian
11596 mode fp constants are big-endian word-wise, and little-endian byte-wise
11597 within the words. For example, (double) 1.1 in big endian mode is
11598 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11599 the byte sequence 99 99 f1 3f 9a 99 99 99.
11600
11601 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11602
11603char *
a737bd4d 11604md_atof (int type, char * litP, int * sizeP)
b99bd4ef
NC
11605{
11606 int prec;
11607 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11608 char *t;
11609 int i;
11610
11611 switch (type)
11612 {
11613 case 'f':
11614 case 'F':
11615 case 's':
11616 case 'S':
11617 prec = 2;
11618 break;
11619
11620 case 'd':
11621 case 'D':
11622 case 'r':
11623 case 'R':
11624 prec = 4;
11625 break;
11626
11627 case 'x':
11628 case 'X':
11629 prec = 6;
11630 break;
11631
11632 case 'p':
11633 case 'P':
11634 prec = 6;
11635 break;
11636
11637 default:
11638 *sizeP = 0;
f03698e6 11639 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11640 }
11641
11642 t = atof_ieee (input_line_pointer, type, words);
11643 if (t)
11644 input_line_pointer = t;
11645 *sizeP = prec * 2;
11646
11647 if (target_big_endian)
11648 {
11649 for (i = 0; i < prec; i++)
11650 {
11651 md_number_to_chars (litP, (valueT) words[i], 2);
11652 litP += 2;
11653 }
11654 }
11655 else
11656 {
bfae80f2
RE
11657 if (cpu_variant & FPU_ARCH_VFP)
11658 for (i = prec - 1; i >= 0; i--)
11659 {
11660 md_number_to_chars (litP, (valueT) words[i], 2);
11661 litP += 2;
11662 }
11663 else
11664 /* For a 4 byte float the order of elements in `words' is 1 0.
11665 For an 8 byte float the order is 1 0 3 2. */
11666 for (i = 0; i < prec; i += 2)
11667 {
11668 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11669 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11670 litP += 4;
11671 }
b99bd4ef
NC
11672 }
11673
11674 return 0;
11675}
11676
11677/* The knowledge of the PC's pipeline offset is built into the insns
11678 themselves. */
11679
11680long
a737bd4d 11681md_pcrel_from (fixS * fixP)
b99bd4ef
NC
11682{
11683 if (fixP->fx_addsy
11684 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11685 && fixP->fx_subsy == NULL)
11686 return 0;
11687
11688 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11689 {
11690 /* PC relative addressing on the Thumb is slightly odd
11691 as the bottom two bits of the PC are forced to zero
11692 for the calculation. */
11693 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11694 }
11695
11696#ifdef TE_WINCE
2d2255b5
KH
11697 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11698 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11699 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11700#else
11701 return fixP->fx_where + fixP->fx_frag->fr_address;
11702#endif
11703}
11704
11705/* Round up a section size to the appropriate boundary. */
11706
11707valueT
a737bd4d
NC
11708md_section_align (segT segment ATTRIBUTE_UNUSED,
11709 valueT size)
b99bd4ef
NC
11710{
11711#ifdef OBJ_ELF
11712 return size;
11713#else
11714 /* Round all sects to multiple of 4. */
11715 return (size + 3) & ~3;
11716#endif
11717}
11718
11719/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11720 Otherwise we have no need to default values of symbols. */
11721
11722symbolS *
a737bd4d 11723md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
b99bd4ef
NC
11724{
11725#ifdef OBJ_ELF
11726 if (name[0] == '_' && name[1] == 'G'
11727 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11728 {
11729 if (!GOT_symbol)
11730 {
11731 if (symbol_find (name))
11732 as_bad ("GOT already in the symbol table");
11733
11734 GOT_symbol = symbol_new (name, undefined_section,
11735 (valueT) 0, & zero_address_frag);
11736 }
11737
11738 return GOT_symbol;
11739 }
11740#endif
11741
11742 return 0;
11743}
11744
94f592af 11745void
a737bd4d
NC
11746md_apply_fix3 (fixS * fixP,
11747 valueT * valP,
11748 segT seg)
b99bd4ef 11749{
94f592af 11750 offsetT value = * valP;
b99bd4ef
NC
11751 offsetT newval;
11752 unsigned int newimm;
11753 unsigned long temp;
11754 int sign;
11755 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11756 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11757
620b81c1 11758 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
b99bd4ef
NC
11759
11760 /* Note whether this will delete the relocation. */
b99bd4ef 11761 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
b99bd4ef
NC
11762 fixP->fx_done = 1;
11763
11764 /* If this symbol is in a different section then we need to leave it for
11765 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11766 so we have to undo it's effects here. */
11767 if (fixP->fx_pcrel)
11768 {
11769 if (fixP->fx_addsy != NULL
11770 && S_IS_DEFINED (fixP->fx_addsy)
11771 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7f266840 11772 value += md_pcrel_from (fixP);
b99bd4ef
NC
11773 }
11774
11775 /* Remember value for emit_reloc. */
11776 fixP->fx_addnumber = value;
11777
11778 switch (fixP->fx_r_type)
11779 {
620b81c1
JB
11780 case BFD_RELOC_NONE:
11781 /* This will need to go in the object file. */
11782 fixP->fx_done = 0;
11783 break;
11784
b99bd4ef 11785 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
11786 /* We claim that this fixup has been processed here,
11787 even if in fact we generate an error because we do
11788 not have a reloc for it, so tc_gen_reloc will reject it. */
11789 fixP->fx_done = 1;
11790
11791 if (fixP->fx_addsy
11792 && ! S_IS_DEFINED (fixP->fx_addsy))
11793 {
11794 as_bad_where (fixP->fx_file, fixP->fx_line,
11795 _("undefined symbol %s used as an immediate value"),
11796 S_GET_NAME (fixP->fx_addsy));
11797 break;
11798 }
11799
b99bd4ef
NC
11800 newimm = validate_immediate (value);
11801 temp = md_chars_to_number (buf, INSN_SIZE);
11802
11803 /* If the instruction will fail, see if we can fix things up by
11804 changing the opcode. */
11805 if (newimm == (unsigned int) FAIL
11806 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11807 {
11808 as_bad_where (fixP->fx_file, fixP->fx_line,
11809 _("invalid constant (%lx) after fixup"),
11810 (unsigned long) value);
11811 break;
11812 }
11813
11814 newimm |= (temp & 0xfffff000);
11815 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11816 break;
11817
11818 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11819 {
11820 unsigned int highpart = 0;
11821 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 11822
b99bd4ef
NC
11823 newimm = validate_immediate (value);
11824 temp = md_chars_to_number (buf, INSN_SIZE);
11825
11826 /* If the instruction will fail, see if we can fix things up by
11827 changing the opcode. */
11828 if (newimm == (unsigned int) FAIL
11829 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11830 {
11831 /* No ? OK - try using two ADD instructions to generate
11832 the value. */
11833 newimm = validate_immediate_twopart (value, & highpart);
11834
11835 /* Yes - then make sure that the second instruction is
11836 also an add. */
11837 if (newimm != (unsigned int) FAIL)
11838 newinsn = temp;
11839 /* Still No ? Try using a negated value. */
11840 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11841 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11842 /* Otherwise - give up. */
11843 else
11844 {
11845 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11846 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 11847 (long) value);
b99bd4ef
NC
11848 break;
11849 }
11850
11851 /* Replace the first operand in the 2nd instruction (which
11852 is the PC) with the destination register. We have
11853 already added in the PC in the first instruction and we
11854 do not want to do it again. */
11855 newinsn &= ~ 0xf0000;
11856 newinsn |= ((newinsn & 0x0f000) << 4);
11857 }
11858
11859 newimm |= (temp & 0xfffff000);
11860 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11861
11862 highpart |= (newinsn & 0xfffff000);
11863 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11864 }
11865 break;
11866
11867 case BFD_RELOC_ARM_OFFSET_IMM:
11868 sign = value >= 0;
11869
11870 if (value < 0)
11871 value = - value;
11872
11873 if (validate_offset_imm (value, 0) == FAIL)
11874 {
11875 as_bad_where (fixP->fx_file, fixP->fx_line,
11876 _("bad immediate value for offset (%ld)"),
11877 (long) value);
11878 break;
11879 }
11880
11881 newval = md_chars_to_number (buf, INSN_SIZE);
11882 newval &= 0xff7ff000;
11883 newval |= value | (sign ? INDEX_UP : 0);
11884 md_number_to_chars (buf, newval, INSN_SIZE);
11885 break;
11886
11887 case BFD_RELOC_ARM_OFFSET_IMM8:
11888 case BFD_RELOC_ARM_HWLITERAL:
11889 sign = value >= 0;
11890
11891 if (value < 0)
11892 value = - value;
11893
11894 if (validate_offset_imm (value, 1) == FAIL)
11895 {
11896 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11897 as_bad_where (fixP->fx_file, fixP->fx_line,
11898 _("invalid literal constant: pool needs to be closer"));
11899 else
11900 as_bad (_("bad immediate value for half-word offset (%ld)"),
11901 (long) value);
11902 break;
11903 }
11904
11905 newval = md_chars_to_number (buf, INSN_SIZE);
11906 newval &= 0xff7ff0f0;
11907 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11908 md_number_to_chars (buf, newval, INSN_SIZE);
11909 break;
11910
11911 case BFD_RELOC_ARM_LITERAL:
11912 sign = value >= 0;
11913
11914 if (value < 0)
11915 value = - value;
11916
11917 if (validate_offset_imm (value, 0) == FAIL)
11918 {
11919 as_bad_where (fixP->fx_file, fixP->fx_line,
11920 _("invalid literal constant: pool needs to be closer"));
11921 break;
11922 }
11923
11924 newval = md_chars_to_number (buf, INSN_SIZE);
11925 newval &= 0xff7ff000;
11926 newval |= value | (sign ? INDEX_UP : 0);
11927 md_number_to_chars (buf, newval, INSN_SIZE);
11928 break;
11929
11930 case BFD_RELOC_ARM_SHIFT_IMM:
11931 newval = md_chars_to_number (buf, INSN_SIZE);
11932 if (((unsigned long) value) > 32
11933 || (value == 32
11934 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11935 {
11936 as_bad_where (fixP->fx_file, fixP->fx_line,
11937 _("shift expression is too large"));
11938 break;
11939 }
11940
11941 if (value == 0)
11942 /* Shifts of zero must be done as lsl. */
11943 newval &= ~0x60;
11944 else if (value == 32)
11945 value = 0;
11946 newval &= 0xfffff07f;
11947 newval |= (value & 0x1f) << 7;
11948 md_number_to_chars (buf, newval, INSN_SIZE);
11949 break;
11950
0dd132b6
NC
11951 case BFD_RELOC_ARM_SMI:
11952 if (((unsigned long) value) > 0xffff)
11953 as_bad_where (fixP->fx_file, fixP->fx_line,
11954 _("invalid smi expression"));
11955 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11956 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11957 md_number_to_chars (buf, newval, INSN_SIZE);
11958 break;
11959
b99bd4ef
NC
11960 case BFD_RELOC_ARM_SWI:
11961 if (arm_data->thumb_mode)
11962 {
11963 if (((unsigned long) value) > 0xff)
11964 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11965 _("invalid swi expression"));
b99bd4ef
NC
11966 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11967 newval |= value;
11968 md_number_to_chars (buf, newval, THUMB_SIZE);
11969 }
11970 else
11971 {
11972 if (((unsigned long) value) > 0x00ffffff)
11973 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11974 _("invalid swi expression"));
b99bd4ef
NC
11975 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11976 newval |= value;
11977 md_number_to_chars (buf, newval, INSN_SIZE);
11978 }
11979 break;
11980
11981 case BFD_RELOC_ARM_MULTI:
11982 if (((unsigned long) value) > 0xffff)
11983 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11984 _("invalid expression in load/store multiple"));
b99bd4ef
NC
11985 newval = value | md_chars_to_number (buf, INSN_SIZE);
11986 md_number_to_chars (buf, newval, INSN_SIZE);
11987 break;
11988
11989 case BFD_RELOC_ARM_PCREL_BRANCH:
11990 newval = md_chars_to_number (buf, INSN_SIZE);
11991
11992 /* Sign-extend a 24-bit number. */
11993#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
11994
11995#ifdef OBJ_ELF
7f266840 11996 value = fixP->fx_offset;
b99bd4ef
NC
11997#endif
11998
11999 /* We are going to store value (shifted right by two) in the
12000 instruction, in a 24 bit, signed field. Thus we need to check
12001 that none of the top 8 bits of the shifted value (top 7 bits of
12002 the unshifted, unsigned value) are set, or that they are all set. */
12003 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12004 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12005 {
12006#ifdef OBJ_ELF
12007 /* Normally we would be stuck at this point, since we cannot store
12008 the absolute address that is the destination of the branch in the
12009 24 bits of the branch instruction. If however, we happen to know
12010 that the destination of the branch is in the same section as the
2d2255b5 12011 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12012 ourselves and not have to bother the linker with it.
12013
7f266840
DJ
12014 FIXME: The test for OBJ_ELF is only here because I have not
12015 worked out how to do this for OBJ_COFF. */
12016 if (fixP->fx_addsy != NULL
b99bd4ef
NC
12017 && S_IS_DEFINED (fixP->fx_addsy)
12018 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12019 {
12020 /* Get pc relative value to go into the branch. */
94f592af 12021 value = * valP;
b99bd4ef
NC
12022
12023 /* Permit a backward branch provided that enough bits
12024 are set. Allow a forwards branch, provided that
12025 enough bits are clear. */
12026 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12027 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12028 fixP->fx_done = 1;
12029 }
12030
12031 if (! fixP->fx_done)
12032#endif
12033 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12034 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12035 }
12036
12037 value >>= 2;
12038 value += SEXT24 (newval);
12039
12040 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12041 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12042 as_bad_where (fixP->fx_file, fixP->fx_line,
12043 _("out of range branch"));
12044
4e7fd91e
PB
12045 if (seg->use_rela_p && !fixP->fx_done)
12046 {
12047 /* Must unshift the value before storing it in the addend. */
12048 value <<= 2;
12049#ifdef OBJ_ELF
12050 fixP->fx_offset = value;
12051#endif
12052 fixP->fx_addnumber = value;
12053 newval = newval & 0xff000000;
12054 }
12055 else
12056 newval = (value & 0x00ffffff) | (newval & 0xff000000);
b99bd4ef
NC
12057 md_number_to_chars (buf, newval, INSN_SIZE);
12058 break;
12059
12060 case BFD_RELOC_ARM_PCREL_BLX:
12061 {
12062 offsetT hbit;
12063 newval = md_chars_to_number (buf, INSN_SIZE);
12064
12065#ifdef OBJ_ELF
7f266840 12066 value = fixP->fx_offset;
b99bd4ef
NC
12067#endif
12068 hbit = (value >> 1) & 1;
12069 value = (value >> 2) & 0x00ffffff;
12070 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
4e7fd91e
PB
12071
12072 if (seg->use_rela_p && !fixP->fx_done)
12073 {
12074 /* Must sign-extend and unshift the value before storing
12075 it in the addend. */
12076 value = SEXT24 (value);
12077 value = (value << 2) | hbit;
12078#ifdef OBJ_ELF
12079 fixP->fx_offset = value;
12080#endif
12081 fixP->fx_addnumber = value;
12082 newval = newval & 0xfe000000;
12083 }
12084 else
12085 newval = value | (newval & 0xfe000000) | (hbit << 24);
b99bd4ef
NC
12086 md_number_to_chars (buf, newval, INSN_SIZE);
12087 }
12088 break;
12089
12090 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12091 newval = md_chars_to_number (buf, THUMB_SIZE);
12092 {
12093 addressT diff = (newval & 0xff) << 1;
12094 if (diff & 0x100)
12095 diff |= ~0xff;
12096
12097 value += diff;
12098 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12099 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12100 _("branch out of range"));
4e7fd91e
PB
12101 if (seg->use_rela_p && !fixP->fx_done)
12102 {
12103#ifdef OBJ_ELF
12104 fixP->fx_offset = value;
12105#endif
12106 fixP->fx_addnumber = value;
12107 newval = newval & 0xff00;
12108 }
12109 else
12110 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
b99bd4ef
NC
12111 }
12112 md_number_to_chars (buf, newval, THUMB_SIZE);
12113 break;
12114
12115 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12116 newval = md_chars_to_number (buf, THUMB_SIZE);
12117 {
12118 addressT diff = (newval & 0x7ff) << 1;
12119 if (diff & 0x800)
12120 diff |= ~0x7ff;
12121
12122 value += diff;
12123 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12124 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12125 _("branch out of range"));
4e7fd91e
PB
12126 if (seg->use_rela_p && !fixP->fx_done)
12127 {
12128#ifdef OBJ_ELF
12129 fixP->fx_offset = value;
12130#endif
12131 fixP->fx_addnumber = value;
12132 newval = newval & 0xf800;
12133 }
12134 else
12135 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
b99bd4ef
NC
12136 }
12137 md_number_to_chars (buf, newval, THUMB_SIZE);
12138 break;
12139
12140 case BFD_RELOC_THUMB_PCREL_BLX:
12141 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12142 {
12143 offsetT newval2;
12144 addressT diff;
12145
12146 newval = md_chars_to_number (buf, THUMB_SIZE);
12147 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12148 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12149 if (diff & 0x400000)
12150 diff |= ~0x3fffff;
12151#ifdef OBJ_ELF
12152 value = fixP->fx_offset;
12153#endif
12154 value += diff;
c62e1cc3 12155
b99bd4ef
NC
12156 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12157 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12158 _("branch with link out of range"));
b99bd4ef 12159
b99bd4ef 12160 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12161 /* For a BLX instruction, make sure that the relocation is rounded up
12162 to a word boundary. This follows the semantics of the instruction
12163 which specifies that bit 1 of the target address will come from bit
12164 1 of the base address. */
4e7fd91e
PB
12165 value = (value + 1) & ~ 1;
12166
12167 if (seg->use_rela_p && !fixP->fx_done)
12168 {
12169#ifdef OBJ_ELF
12170 fixP->fx_offset = value;
12171#endif
12172 fixP->fx_addnumber = value;
12173 newval = newval & 0xf800;
12174 newval2 = newval2 & 0xf800;
12175 }
12176 else
12177 {
12178 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12179 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12180 }
b99bd4ef
NC
12181 md_number_to_chars (buf, newval, THUMB_SIZE);
12182 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12183 }
12184 break;
12185
12186 case BFD_RELOC_8:
4e7fd91e
PB
12187 if (seg->use_rela_p && !fixP->fx_done)
12188 break;
b99bd4ef
NC
12189 if (fixP->fx_done || fixP->fx_pcrel)
12190 md_number_to_chars (buf, value, 1);
12191#ifdef OBJ_ELF
7f266840 12192 else
b99bd4ef
NC
12193 {
12194 value = fixP->fx_offset;
12195 md_number_to_chars (buf, value, 1);
12196 }
12197#endif
12198 break;
12199
12200 case BFD_RELOC_16:
4e7fd91e
PB
12201 if (seg->use_rela_p && !fixP->fx_done)
12202 break;
b99bd4ef
NC
12203 if (fixP->fx_done || fixP->fx_pcrel)
12204 md_number_to_chars (buf, value, 2);
12205#ifdef OBJ_ELF
7f266840 12206 else
b99bd4ef
NC
12207 {
12208 value = fixP->fx_offset;
12209 md_number_to_chars (buf, value, 2);
12210 }
12211#endif
12212 break;
12213
12214#ifdef OBJ_ELF
12215 case BFD_RELOC_ARM_GOT32:
12216 case BFD_RELOC_ARM_GOTOFF:
eb043451 12217 case BFD_RELOC_ARM_TARGET2:
4e7fd91e
PB
12218 if (seg->use_rela_p && !fixP->fx_done)
12219 break;
b99bd4ef
NC
12220 md_number_to_chars (buf, 0, 4);
12221 break;
12222#endif
12223
12224 case BFD_RELOC_RVA:
12225 case BFD_RELOC_32:
9c504268 12226 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12227 case BFD_RELOC_ARM_ROSEGREL32:
12228 case BFD_RELOC_ARM_SBREL32:
eb043451 12229 case BFD_RELOC_32_PCREL:
4e7fd91e
PB
12230 if (seg->use_rela_p && !fixP->fx_done)
12231 break;
b99bd4ef
NC
12232 if (fixP->fx_done || fixP->fx_pcrel)
12233 md_number_to_chars (buf, value, 4);
12234#ifdef OBJ_ELF
7f266840 12235 else
b99bd4ef
NC
12236 {
12237 value = fixP->fx_offset;
12238 md_number_to_chars (buf, value, 4);
12239 }
12240#endif
12241 break;
12242
12243#ifdef OBJ_ELF
eb043451
PB
12244 case BFD_RELOC_ARM_PREL31:
12245 if (fixP->fx_done || fixP->fx_pcrel)
12246 {
12247 newval = md_chars_to_number (buf, 4) & 0x80000000;
12248 if ((value ^ (value >> 1)) & 0x40000000)
12249 {
12250 as_bad_where (fixP->fx_file, fixP->fx_line,
12251 _("rel31 relocation overflow"));
12252 }
12253 newval |= value & 0x7fffffff;
12254 md_number_to_chars (buf, newval, 4);
12255 }
12256 break;
12257
b99bd4ef
NC
12258 case BFD_RELOC_ARM_PLT32:
12259 /* It appears the instruction is fully prepared at this point. */
12260 break;
12261#endif
12262
b99bd4ef
NC
12263 case BFD_RELOC_ARM_CP_OFF_IMM:
12264 sign = value >= 0;
12265 if (value < -1023 || value > 1023 || (value & 3))
12266 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12267 _("illegal value for co-processor offset"));
b99bd4ef
NC
12268 if (value < 0)
12269 value = -value;
12270 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12271 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12272 md_number_to_chars (buf, newval, INSN_SIZE);
12273 break;
12274
e16bb312
NC
12275 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12276 sign = value >= 0;
12277 if (value < -255 || value > 255)
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
12279 _("Illegal value for co-processor offset"));
12280 if (value < 0)
12281 value = -value;
12282 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12283 newval |= value | (sign ? INDEX_UP : 0);
12284 md_number_to_chars (buf, newval , INSN_SIZE);
12285 break;
12286
b99bd4ef
NC
12287 case BFD_RELOC_ARM_THUMB_OFFSET:
12288 newval = md_chars_to_number (buf, THUMB_SIZE);
12289 /* Exactly what ranges, and where the offset is inserted depends
12290 on the type of instruction, we can establish this from the
12291 top 4 bits. */
12292 switch (newval >> 12)
12293 {
12294 case 4: /* PC load. */
12295 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12296 forced to zero for these loads, so we will need to round
12297 up the offset if the instruction address is not word
12298 aligned (since the final address produced must be, and
12299 we can only describe word-aligned immediate offsets). */
12300
12301 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12302 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12303 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12304 (unsigned int) (fixP->fx_frag->fr_address
12305 + fixP->fx_where + value));
12306
12307 if ((value + 2) & ~0x3fe)
12308 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12309 _("invalid offset, value too big (0x%08lX)"),
12310 (long) value);
b99bd4ef
NC
12311
12312 /* Round up, since pc will be rounded down. */
12313 newval |= (value + 2) >> 2;
12314 break;
12315
12316 case 9: /* SP load/store. */
12317 if (value & ~0x3fc)
12318 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12319 _("invalid offset, value too big (0x%08lX)"),
12320 (long) value);
b99bd4ef
NC
12321 newval |= value >> 2;
12322 break;
12323
12324 case 6: /* Word load/store. */
12325 if (value & ~0x7c)
12326 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12327 _("invalid offset, value too big (0x%08lX)"),
12328 (long) value);
b99bd4ef
NC
12329 newval |= value << 4; /* 6 - 2. */
12330 break;
12331
12332 case 7: /* Byte load/store. */
12333 if (value & ~0x1f)
12334 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12335 _("invalid offset, value too big (0x%08lX)"),
12336 (long) value);
b99bd4ef
NC
12337 newval |= value << 6;
12338 break;
12339
12340 case 8: /* Halfword load/store. */
12341 if (value & ~0x3e)
12342 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12343 _("invalid offset, value too big (0x%08lX)"),
12344 (long) value);
b99bd4ef
NC
12345 newval |= value << 5; /* 6 - 1. */
12346 break;
12347
12348 default:
12349 as_bad_where (fixP->fx_file, fixP->fx_line,
12350 "Unable to process relocation for thumb opcode: %lx",
12351 (unsigned long) newval);
12352 break;
12353 }
12354 md_number_to_chars (buf, newval, THUMB_SIZE);
12355 break;
12356
12357 case BFD_RELOC_ARM_THUMB_ADD:
12358 /* This is a complicated relocation, since we use it for all of
12359 the following immediate relocations:
12360
12361 3bit ADD/SUB
12362 8bit ADD/SUB
12363 9bit ADD/SUB SP word-aligned
12364 10bit ADD PC/SP word-aligned
12365
12366 The type of instruction being processed is encoded in the
12367 instruction field:
12368
12369 0x8000 SUB
12370 0x00F0 Rd
12371 0x000F Rs
12372 */
12373 newval = md_chars_to_number (buf, THUMB_SIZE);
12374 {
12375 int rd = (newval >> 4) & 0xf;
12376 int rs = newval & 0xf;
12377 int subtract = newval & 0x8000;
12378
12379 if (rd == REG_SP)
12380 {
12381 if (value & ~0x1fc)
12382 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12383 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12384 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12385 newval |= value >> 2;
12386 }
12387 else if (rs == REG_PC || rs == REG_SP)
12388 {
12389 if (subtract ||
12390 value & ~0x3fc)
12391 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12392 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12393 (unsigned long) value);
12394 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12395 newval |= rd << 8;
12396 newval |= value >> 2;
12397 }
12398 else if (rs == rd)
12399 {
12400 if (value & ~0xff)
12401 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12402 _("invalid 8bit immediate"));
b99bd4ef
NC
12403 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12404 newval |= (rd << 8) | value;
12405 }
12406 else
12407 {
12408 if (value & ~0x7)
12409 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12410 _("invalid 3bit immediate"));
b99bd4ef
NC
12411 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12412 newval |= rd | (rs << 3) | (value << 6);
12413 }
12414 }
12415 md_number_to_chars (buf, newval, THUMB_SIZE);
12416 break;
12417
12418 case BFD_RELOC_ARM_THUMB_IMM:
12419 newval = md_chars_to_number (buf, THUMB_SIZE);
12420 switch (newval >> 11)
12421 {
12422 case 0x04: /* 8bit immediate MOV. */
12423 case 0x05: /* 8bit immediate CMP. */
12424 if (value < 0 || value > 255)
12425 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12426 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12427 (long) value);
12428 newval |= value;
12429 break;
12430
12431 default:
12432 abort ();
12433 }
12434 md_number_to_chars (buf, newval, THUMB_SIZE);
12435 break;
12436
12437 case BFD_RELOC_ARM_THUMB_SHIFT:
12438 /* 5bit shift value (0..31). */
12439 if (value < 0 || value > 31)
12440 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12441 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12442 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12443 newval |= value << 6;
12444 md_number_to_chars (buf, newval, THUMB_SIZE);
12445 break;
12446
12447 case BFD_RELOC_VTABLE_INHERIT:
12448 case BFD_RELOC_VTABLE_ENTRY:
12449 fixP->fx_done = 0;
94f592af 12450 return;
b99bd4ef 12451
620b81c1 12452 case BFD_RELOC_UNUSED:
b99bd4ef
NC
12453 default:
12454 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12455 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12456 }
b99bd4ef
NC
12457}
12458
12459/* Translate internal representation of relocation info to BFD target
12460 format. */
12461
12462arelent *
a737bd4d
NC
12463tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12464 fixS * fixp)
b99bd4ef
NC
12465{
12466 arelent * reloc;
12467 bfd_reloc_code_real_type code;
12468
a737bd4d 12469 reloc = xmalloc (sizeof (arelent));
b99bd4ef 12470
a737bd4d 12471 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
b99bd4ef
NC
12472 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12473 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12474
12475 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12476#ifndef OBJ_ELF
12477 if (fixp->fx_pcrel == 0)
12478 reloc->addend = fixp->fx_offset;
12479 else
12480 reloc->addend = fixp->fx_offset = reloc->address;
12481#else /* OBJ_ELF */
12482 reloc->addend = fixp->fx_offset;
12483#endif
12484
12485 switch (fixp->fx_r_type)
12486 {
12487 case BFD_RELOC_8:
12488 if (fixp->fx_pcrel)
12489 {
12490 code = BFD_RELOC_8_PCREL;
12491 break;
12492 }
12493
12494 case BFD_RELOC_16:
12495 if (fixp->fx_pcrel)
12496 {
12497 code = BFD_RELOC_16_PCREL;
12498 break;
12499 }
12500
12501 case BFD_RELOC_32:
12502 if (fixp->fx_pcrel)
12503 {
12504 code = BFD_RELOC_32_PCREL;
12505 break;
12506 }
12507
620b81c1 12508 case BFD_RELOC_NONE:
b99bd4ef
NC
12509 case BFD_RELOC_ARM_PCREL_BRANCH:
12510 case BFD_RELOC_ARM_PCREL_BLX:
12511 case BFD_RELOC_RVA:
12512 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12513 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12514 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12515 case BFD_RELOC_THUMB_PCREL_BLX:
12516 case BFD_RELOC_VTABLE_ENTRY:
12517 case BFD_RELOC_VTABLE_INHERIT:
12518 code = fixp->fx_r_type;
12519 break;
12520
12521 case BFD_RELOC_ARM_LITERAL:
12522 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12523 /* If this is called then the a literal has
12524 been referenced across a section boundary. */
b99bd4ef 12525 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12526 _("literal referenced across section boundary"));
b99bd4ef
NC
12527 return NULL;
12528
12529#ifdef OBJ_ELF
12530 case BFD_RELOC_ARM_GOT32:
12531 case BFD_RELOC_ARM_GOTOFF:
12532 case BFD_RELOC_ARM_PLT32:
9c504268 12533 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12534 case BFD_RELOC_ARM_ROSEGREL32:
12535 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12536 case BFD_RELOC_ARM_PREL31:
12537 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12538 code = fixp->fx_r_type;
12539 break;
12540#endif
12541
12542 case BFD_RELOC_ARM_IMMEDIATE:
12543 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12544 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12545 return NULL;
12546
12547 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12548 as_bad_where (fixp->fx_file, fixp->fx_line,
12549 _("ADRL used for a symbol not defined in the same file"));
12550 return NULL;
12551
12552 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12553 if (fixp->fx_addsy != NULL
12554 && !S_IS_DEFINED (fixp->fx_addsy)
12555 && S_IS_LOCAL (fixp->fx_addsy))
12556 {
12557 as_bad_where (fixp->fx_file, fixp->fx_line,
12558 _("undefined local label `%s'"),
12559 S_GET_NAME (fixp->fx_addsy));
12560 return NULL;
12561 }
12562
b99bd4ef 12563 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12564 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12565 return NULL;
12566
12567 default:
12568 {
12569 char * type;
12570
12571 switch (fixp->fx_r_type)
12572 {
620b81c1 12573 case BFD_RELOC_NONE: type = "NONE"; break;
b99bd4ef
NC
12574 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12575 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
0dd132b6 12576 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
b99bd4ef
NC
12577 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12578 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12579 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12580 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12581 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12582 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12583 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12584 default: type = _("<unknown>"); break;
12585 }
12586 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12587 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12588 type);
12589 return NULL;
12590 }
12591 }
12592
12593#ifdef OBJ_ELF
8df7094c 12594 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12595 && GOT_symbol
12596 && fixp->fx_addsy == GOT_symbol)
12597 {
12598 code = BFD_RELOC_ARM_GOTPC;
12599 reloc->addend = fixp->fx_offset = reloc->address;
12600 }
12601#endif
12602
12603 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12604
12605 if (reloc->howto == NULL)
12606 {
12607 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12608 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12609 bfd_get_reloc_code_name (code));
12610 return NULL;
12611 }
12612
12613 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12614 vtable entry to be used in the relocation's section offset. */
12615 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12616 reloc->address = fixp->fx_offset;
12617
12618 return reloc;
12619}
12620
12621int
a737bd4d
NC
12622md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12623 segT segtype ATTRIBUTE_UNUSED)
b99bd4ef
NC
12624{
12625 as_fatal (_("md_estimate_size_before_relax\n"));
12626 return 1;
12627}
12628
a737bd4d
NC
12629/* We need to be able to fix up arbitrary expressions in some statements.
12630 This is so that we can handle symbols that are an arbitrary distance from
12631 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12632 which returns part of an address in a form which will be valid for
12633 a data instruction. We do this by pushing the expression into a symbol
12634 in the expr_section, and creating a fix for that. */
12635
12636static void
12637fix_new_arm (fragS * frag,
12638 int where,
12639 short int size,
12640 expressionS * exp,
12641 int pc_rel,
12642 int reloc)
12643{
12644 fixS * new_fix;
12645 arm_fix_data * arm_data;
12646
12647 switch (exp->X_op)
12648 {
12649 case O_constant:
12650 case O_symbol:
12651 case O_add:
12652 case O_subtract:
12653 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12654 break;
12655
12656 default:
12657 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12658 pc_rel, reloc);
12659 break;
12660 }
12661
12662 /* Mark whether the fix is to a THUMB instruction, or an ARM
12663 instruction. */
12664 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12665 new_fix->tc_fix_data = (PTR) arm_data;
12666 arm_data->thumb_mode = thumb_mode;
12667}
12668
b99bd4ef 12669static void
a737bd4d 12670output_inst (const char * str)
b99bd4ef
NC
12671{
12672 char * to = NULL;
12673
12674 if (inst.error)
12675 {
f03698e6 12676 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12677 return;
12678 }
12679
12680 to = frag_more (inst.size);
12681
12682 if (thumb_mode && (inst.size > THUMB_SIZE))
12683 {
12684 assert (inst.size == (2 * THUMB_SIZE));
12685 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12686 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12687 }
12688 else if (inst.size > INSN_SIZE)
12689 {
12690 assert (inst.size == (2 * INSN_SIZE));
12691 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12692 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12693 }
12694 else
12695 md_number_to_chars (to, inst.instruction, inst.size);
12696
620b81c1 12697 if (inst.reloc.type != BFD_RELOC_UNUSED)
b99bd4ef
NC
12698 fix_new_arm (frag_now, to - frag_now->fr_literal,
12699 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12700 inst.reloc.type);
12701
12702#ifdef OBJ_ELF
12703 dwarf2_emit_insn (inst.size);
12704#endif
12705}
12706
12707void
a737bd4d 12708md_assemble (char * str)
b99bd4ef 12709{
6c43fab6
RE
12710 char c;
12711 char *p;
12712 char *start;
b99bd4ef 12713
b99bd4ef
NC
12714 /* Align the previous label if needed. */
12715 if (last_label_seen != NULL)
12716 {
12717 symbol_set_frag (last_label_seen, frag_now);
12718 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12719 S_SET_SEGMENT (last_label_seen, now_seg);
12720 }
12721
12722 memset (&inst, '\0', sizeof (inst));
620b81c1 12723 inst.reloc.type = BFD_RELOC_UNUSED;
b99bd4ef
NC
12724
12725 skip_whitespace (str);
12726
12727 /* Scan up to the end of the op-code, which must end in white space or
12728 end of string. */
12729 for (start = p = str; *p != '\0'; p++)
12730 if (*p == ' ')
12731 break;
12732
12733 if (p == str)
12734 {
f03698e6 12735 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12736 return;
12737 }
12738
12739 if (thumb_mode)
12740 {
05d2d07e 12741 const struct thumb_opcode * opcode;
b99bd4ef
NC
12742
12743 c = *p;
12744 *p = '\0';
05d2d07e 12745 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12746 *p = c;
12747
12748 if (opcode)
12749 {
12750 /* Check that this instruction is supported for this CPU. */
90e4755a 12751 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12752 {
f03698e6 12753 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12754 return;
12755 }
12756
6057a28f 12757 mapping_state (MAP_THUMB);
b99bd4ef
NC
12758 inst.instruction = opcode->value;
12759 inst.size = opcode->size;
a737bd4d 12760 opcode->parms (p);
f03698e6 12761 output_inst (str);
b99bd4ef
NC
12762 return;
12763 }
12764 }
12765 else
12766 {
05d2d07e 12767 const struct asm_opcode * opcode;
b99bd4ef 12768
90e4755a
RE
12769 c = *p;
12770 *p = '\0';
6c43fab6 12771 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12772 *p = c;
b99bd4ef 12773
90e4755a 12774 if (opcode)
b99bd4ef 12775 {
90e4755a
RE
12776 /* Check that this instruction is supported for this CPU. */
12777 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12778 {
f03698e6 12779 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12780 return;
12781 }
12782
6057a28f 12783 mapping_state (MAP_ARM);
90e4755a
RE
12784 inst.instruction = opcode->value;
12785 inst.size = INSN_SIZE;
a737bd4d 12786 opcode->parms (p);
f03698e6 12787 output_inst (str);
90e4755a 12788 return;
b99bd4ef
NC
12789 }
12790 }
12791
12792 /* It wasn't an instruction, but it might be a register alias of the form
12793 alias .req reg. */
6c43fab6
RE
12794 if (create_register_alias (str, p))
12795 return;
b99bd4ef 12796
b99bd4ef
NC
12797 as_bad (_("bad instruction `%s'"), start);
12798}
12799
12800/* md_parse_option
12801 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12802 See if it's a processor-specific option.
03b1477f
RE
12803
12804 This routine is somewhat complicated by the need for backwards
12805 compatibility (since older releases of gcc can't be changed).
12806 The new options try to make the interface as compatible as
12807 possible with GCC.
12808
12809 New options (supported) are:
12810
12811 -mcpu=<cpu name> Assemble for selected processor
12812 -march=<architecture name> Assemble for selected architecture
12813 -mfpu=<fpu architecture> Assemble for selected FPU.
12814 -EB/-mbig-endian Big-endian
12815 -EL/-mlittle-endian Little-endian
12816 -k Generate PIC code
12817 -mthumb Start in Thumb mode
12818 -mthumb-interwork Code supports ARM/Thumb interworking
12819
3d0c9500 12820 For now we will also provide support for:
03b1477f
RE
12821
12822 -mapcs-32 32-bit Program counter
12823 -mapcs-26 26-bit Program counter
12824 -macps-float Floats passed in FP registers
12825 -mapcs-reentrant Reentrant code
12826 -matpcs
12827 (sometime these will probably be replaced with -mapcs=<list of options>
12828 and -matpcs=<list of options>)
12829
12830 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
12831 Cpu variants, the arm part is optional:
12832 -m[arm]1 Currently not supported.
12833 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12834 -m[arm]3 Arm 3 processor
12835 -m[arm]6[xx], Arm 6 processors
12836 -m[arm]7[xx][t][[d]m] Arm 7 processors
12837 -m[arm]8[10] Arm 8 processors
12838 -m[arm]9[20][tdmi] Arm 9 processors
12839 -mstrongarm[110[0]] StrongARM processors
12840 -mxscale XScale processors
12841 -m[arm]v[2345[t[e]]] Arm architectures
12842 -mall All (except the ARM1)
12843 FP variants:
12844 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12845 -mfpe-old (No float load/store multiples)
bfae80f2
RE
12846 -mvfpxd VFP Single precision
12847 -mvfp All VFP
b99bd4ef 12848 -mno-fpu Disable all floating point instructions
b99bd4ef 12849
03b1477f
RE
12850 The following CPU names are recognized:
12851 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12852 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12853 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12854 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12855 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12856 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12857 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12858
12859 */
12860
5a38dc70 12861const char * md_shortopts = "m:k";
03b1477f 12862
b99bd4ef
NC
12863#ifdef ARM_BI_ENDIAN
12864#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 12865#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12866#else
21f0f23a
RE
12867#if TARGET_BYTES_BIG_ENDIAN
12868#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
12869#else
12870#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12871#endif
ce058b6c 12872#endif
03b1477f
RE
12873
12874struct option md_longopts[] =
12875{
12876#ifdef OPTION_EB
12877 {"EB", no_argument, NULL, OPTION_EB},
12878#endif
12879#ifdef OPTION_EL
12880 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
12881#endif
12882 {NULL, no_argument, NULL, 0}
12883};
12884
12885size_t md_longopts_size = sizeof (md_longopts);
12886
03b1477f 12887struct arm_option_table
b99bd4ef 12888{
03b1477f
RE
12889 char *option; /* Option name to match. */
12890 char *help; /* Help information. */
12891 int *var; /* Variable to change. */
12892 int value; /* What to change it to. */
12893 char *deprecated; /* If non-null, print this message. */
12894};
b99bd4ef 12895
cc8a6dd0 12896struct arm_option_table arm_opts[] =
03b1477f
RE
12897{
12898 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12899 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12900 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12901 &support_interwork, 1, NULL},
03b1477f
RE
12902 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12903 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12904 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12905 1, NULL},
12906 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12907 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12908 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12909 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12910 NULL},
12911
12912 /* These are recognized by the assembler, but have no affect on code. */
12913 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12914 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12915
12916 /* DON'T add any new processors to this list -- we want the whole list
12917 to go away... Add them to the processors table instead. */
12918 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12919 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12920 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12921 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12922 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12923 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12924 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12925 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12926 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12927 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12928 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12929 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12930 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12931 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12932 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12933 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12934 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12935 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12936 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12937 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12938 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12939 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12940 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12941 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12942 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12943 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12944 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12945 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12946 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12947 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12948 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12949 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12950 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12951 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12952 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12953 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12954 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12955 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12956 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12957 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12958 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12959 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12960 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12961 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12962 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12963 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12964 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12965 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12966 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12967 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12968 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12969 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12970 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12971 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12972 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12973 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12974 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12975 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12976 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12977 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12978 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12979 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12980 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12981 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12982 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12983 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12984 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12985 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12986 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12987 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
12988 N_("use -mcpu=strongarm110")},
12989 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
12990 N_("use -mcpu=strongarm1100")},
12991 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
12992 N_("use -mcpu=strongarm1110")},
12993 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 12994 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
12995 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
12996
12997 /* Architecture variants -- don't add any more to this list either. */
12998 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
12999 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13000 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13001 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13002 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13003 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13004 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13005 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13006 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13007 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13008 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13009 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13010 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13011 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13012 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13013 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13014 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13015 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13016
13017 /* Floating point variants -- don't add any more to this list either. */
13018 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13019 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13020 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13021 {"mno-fpu", NULL, &legacy_fpu, 0,
13022 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13023
13024 {NULL, NULL, NULL, 0, NULL}
13025};
21f0f23a 13026
03b1477f
RE
13027struct arm_cpu_option_table
13028{
13029 char *name;
13030 int value;
13031 /* For some CPUs we assume an FPU unless the user explicitly sets
13032 -mfpu=... */
13033 int default_fpu;
13034};
13035
13036/* This list should, at a minimum, contain all the cpu names
13037 recognized by GCC. */
13038static struct arm_cpu_option_table arm_cpus[] =
13039{
13040 {"all", ARM_ANY, FPU_ARCH_FPA},
13041 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13042 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13043 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13044 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13045 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13046 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13047 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13048 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13049 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13050 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13051 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13052 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13053 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13054 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13055 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13056 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13057 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13058 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13059 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13060 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13061 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13062 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13063 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13064 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13065 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13066 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13067 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13068 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13069 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 13070 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
13071 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13072 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13073 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13074 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13075 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13076 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13077 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13078 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13079 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13080 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13081 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13082 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13083 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13084 /* For V5 or later processors we default to using VFP; but the user
13085 should really set the FPU type explicitly. */
13086 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13087 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13088 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13089 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 13090 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13091 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13092 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13093 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13094 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13095 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13096 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13097 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13098 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13099 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
5dc1606f
PB
13100 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13101 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
09d92015 13102 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 13103 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 13104 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 13105 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
0dd132b6
NC
13106 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13107 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13108 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13109 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
03b1477f
RE
13110 /* ??? XSCALE is really an architecture. */
13111 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13112 /* ??? iwmmxt is not a processor. */
e16bb312 13113 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13114 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13115 /* Maverick */
33a392fb 13116 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13117 {NULL, 0, 0}
13118};
cc8a6dd0 13119
03b1477f
RE
13120struct arm_arch_option_table
13121{
13122 char *name;
13123 int value;
13124 int default_fpu;
13125};
13126
13127/* This list should, at a minimum, contain all the architecture names
13128 recognized by GCC. */
13129static struct arm_arch_option_table arm_archs[] =
13130{
13131 {"all", ARM_ANY, FPU_ARCH_FPA},
13132 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13133 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13134 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13135 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13136 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13137 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13138 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13139 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13140 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13141 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13142 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13143 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13144 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13145 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13146 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13147 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13148 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13149 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
0dd132b6
NC
13150 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13151 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13152 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
b05fe5cf
ZW
13153 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13154 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13155 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13156 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
03b1477f 13157 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13158 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13159 {NULL, 0, 0}
13160};
13161
13162/* ISA extensions in the co-processor space. */
13163struct arm_arch_extension_table
13164{
13165 char *name;
13166 int value;
13167};
13168
13169static struct arm_arch_extension_table arm_extensions[] =
13170{
13171 {"maverick", ARM_CEXT_MAVERICK},
13172 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13173 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13174 {NULL, 0}
13175};
b99bd4ef 13176
03b1477f
RE
13177struct arm_fpu_option_table
13178{
13179 char *name;
13180 int value;
13181};
13182
13183/* This list should, at a minimum, contain all the fpu names
13184 recognized by GCC. */
13185static struct arm_fpu_option_table arm_fpus[] =
13186{
13187 {"softfpa", FPU_NONE},
13188 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13189 {"fpe2", FPU_ARCH_FPE},
13190 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13191 {"fpa", FPU_ARCH_FPA},
13192 {"fpa10", FPU_ARCH_FPA},
13193 {"fpa11", FPU_ARCH_FPA},
13194 {"arm7500fe", FPU_ARCH_FPA},
13195 {"softvfp", FPU_ARCH_VFP},
13196 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13197 {"vfp", FPU_ARCH_VFP_V2},
13198 {"vfp9", FPU_ARCH_VFP_V2},
13199 {"vfp10", FPU_ARCH_VFP_V2},
13200 {"vfp10-r0", FPU_ARCH_VFP_V1},
13201 {"vfpxd", FPU_ARCH_VFP_V1xD},
13202 {"arm1020t", FPU_ARCH_VFP_V1},
13203 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13204 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 13205 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
13206 {"maverick", FPU_ARCH_MAVERICK},
13207 {NULL, 0}
13208};
13209
13210struct arm_float_abi_option_table
13211{
13212 char *name;
13213 int value;
13214};
13215
13216static struct arm_float_abi_option_table arm_float_abis[] =
13217{
13218 {"hard", ARM_FLOAT_ABI_HARD},
13219 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13220 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13221 {NULL, 0}
13222};
13223
d507cf36
PB
13224struct arm_eabi_option_table
13225{
13226 char *name;
13227 unsigned int value;
13228};
13229
7cc69913 13230#ifdef OBJ_ELF
8cb51566 13231/* We only know how to output GNU and ver 4 (AAELF) formats. */
d507cf36
PB
13232static struct arm_eabi_option_table arm_eabis[] =
13233{
13234 {"gnu", EF_ARM_EABI_UNKNOWN},
8cb51566 13235 {"4", EF_ARM_EABI_VER4},
d507cf36
PB
13236 {NULL, 0}
13237};
7cc69913 13238#endif
d507cf36 13239
03b1477f
RE
13240struct arm_long_option_table
13241{
a737bd4d
NC
13242 char * option; /* Substring to match. */
13243 char * help; /* Help information. */
13244 int (* func) (char * subopt); /* Function to decode sub-option. */
13245 char * deprecated; /* If non-null, print this message. */
03b1477f
RE
13246};
13247
13248static int
a737bd4d 13249arm_parse_extension (char * str, int * opt_p)
03b1477f
RE
13250{
13251 while (str != NULL && *str != 0)
13252 {
a737bd4d
NC
13253 struct arm_arch_extension_table * opt;
13254 char * ext;
03b1477f
RE
13255 int optlen;
13256
13257 if (*str != '+')
b99bd4ef 13258 {
03b1477f
RE
13259 as_bad (_("invalid architectural extension"));
13260 return 0;
13261 }
b99bd4ef 13262
03b1477f
RE
13263 str++;
13264 ext = strchr (str, '+');
b99bd4ef 13265
03b1477f
RE
13266 if (ext != NULL)
13267 optlen = ext - str;
13268 else
13269 optlen = strlen (str);
b99bd4ef 13270
03b1477f
RE
13271 if (optlen == 0)
13272 {
13273 as_bad (_("missing architectural extension"));
13274 return 0;
13275 }
b99bd4ef 13276
03b1477f
RE
13277 for (opt = arm_extensions; opt->name != NULL; opt++)
13278 if (strncmp (opt->name, str, optlen) == 0)
13279 {
13280 *opt_p |= opt->value;
13281 break;
13282 }
bfae80f2 13283
03b1477f
RE
13284 if (opt->name == NULL)
13285 {
13286 as_bad (_("unknown architectural extnsion `%s'"), str);
13287 return 0;
13288 }
b99bd4ef 13289
03b1477f
RE
13290 str = ext;
13291 };
b99bd4ef 13292
03b1477f
RE
13293 return 1;
13294}
b99bd4ef 13295
03b1477f 13296static int
a737bd4d 13297arm_parse_cpu (char * str)
03b1477f 13298{
a737bd4d
NC
13299 struct arm_cpu_option_table * opt;
13300 char * ext = strchr (str, '+');
03b1477f 13301 int optlen;
b99bd4ef 13302
03b1477f
RE
13303 if (ext != NULL)
13304 optlen = ext - str;
13305 else
13306 optlen = strlen (str);
b99bd4ef 13307
03b1477f
RE
13308 if (optlen == 0)
13309 {
13310 as_bad (_("missing cpu name `%s'"), str);
13311 return 0;
13312 }
b99bd4ef 13313
03b1477f
RE
13314 for (opt = arm_cpus; opt->name != NULL; opt++)
13315 if (strncmp (opt->name, str, optlen) == 0)
13316 {
13317 mcpu_cpu_opt = opt->value;
13318 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13319
03b1477f
RE
13320 if (ext != NULL)
13321 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13322
03b1477f
RE
13323 return 1;
13324 }
b99bd4ef 13325
03b1477f
RE
13326 as_bad (_("unknown cpu `%s'"), str);
13327 return 0;
13328}
b99bd4ef 13329
03b1477f 13330static int
a737bd4d 13331arm_parse_arch (char * str)
03b1477f
RE
13332{
13333 struct arm_arch_option_table *opt;
13334 char *ext = strchr (str, '+');
13335 int optlen;
b99bd4ef 13336
03b1477f
RE
13337 if (ext != NULL)
13338 optlen = ext - str;
13339 else
13340 optlen = strlen (str);
b99bd4ef 13341
03b1477f
RE
13342 if (optlen == 0)
13343 {
13344 as_bad (_("missing architecture name `%s'"), str);
13345 return 0;
13346 }
b99bd4ef 13347
b99bd4ef 13348
03b1477f 13349 for (opt = arm_archs; opt->name != NULL; opt++)
a737bd4d 13350 if (streq (opt->name, str))
03b1477f
RE
13351 {
13352 march_cpu_opt = opt->value;
13353 march_fpu_opt = opt->default_fpu;
b99bd4ef 13354
03b1477f
RE
13355 if (ext != NULL)
13356 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13357
03b1477f
RE
13358 return 1;
13359 }
b99bd4ef 13360
03b1477f
RE
13361 as_bad (_("unknown architecture `%s'\n"), str);
13362 return 0;
13363}
13364
13365static int
a737bd4d 13366arm_parse_fpu (char * str)
03b1477f 13367{
a737bd4d 13368 struct arm_fpu_option_table * opt;
b99bd4ef 13369
03b1477f 13370 for (opt = arm_fpus; opt->name != NULL; opt++)
a737bd4d 13371 if (streq (opt->name, str))
03b1477f
RE
13372 {
13373 mfpu_opt = opt->value;
13374 return 1;
13375 }
b99bd4ef 13376
03b1477f
RE
13377 as_bad (_("unknown floating point format `%s'\n"), str);
13378 return 0;
13379}
b99bd4ef 13380
33a392fb 13381static int
a737bd4d 13382arm_parse_float_abi (char * str)
33a392fb 13383{
a737bd4d 13384 struct arm_float_abi_option_table * opt;
33a392fb
PB
13385
13386 for (opt = arm_float_abis; opt->name != NULL; opt++)
a737bd4d 13387 if (streq (opt->name, str))
33a392fb
PB
13388 {
13389 mfloat_abi_opt = opt->value;
13390 return 1;
13391 }
13392
13393 as_bad (_("unknown floating point abi `%s'\n"), str);
13394 return 0;
13395}
13396
7cc69913 13397#ifdef OBJ_ELF
d507cf36 13398static int
a737bd4d 13399arm_parse_eabi (char * str)
d507cf36
PB
13400{
13401 struct arm_eabi_option_table *opt;
13402
13403 for (opt = arm_eabis; opt->name != NULL; opt++)
a737bd4d 13404 if (streq (opt->name, str))
d507cf36
PB
13405 {
13406 meabi_flags = opt->value;
13407 return 1;
13408 }
13409 as_bad (_("unknown EABI `%s'\n"), str);
13410 return 0;
13411}
7cc69913 13412#endif
d507cf36 13413
03b1477f
RE
13414struct arm_long_option_table arm_long_opts[] =
13415{
13416 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13417 arm_parse_cpu, NULL},
13418 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13419 arm_parse_arch, NULL},
13420 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13421 arm_parse_fpu, NULL},
33a392fb
PB
13422 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13423 arm_parse_float_abi, NULL},
7cc69913 13424#ifdef OBJ_ELF
d507cf36
PB
13425 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13426 arm_parse_eabi, NULL},
7cc69913 13427#endif
03b1477f
RE
13428 {NULL, NULL, 0, NULL}
13429};
b99bd4ef 13430
03b1477f 13431int
a737bd4d 13432md_parse_option (int c, char * arg)
03b1477f
RE
13433{
13434 struct arm_option_table *opt;
13435 struct arm_long_option_table *lopt;
b99bd4ef 13436
03b1477f
RE
13437 switch (c)
13438 {
13439#ifdef OPTION_EB
13440 case OPTION_EB:
13441 target_big_endian = 1;
b99bd4ef 13442 break;
03b1477f 13443#endif
b99bd4ef 13444
03b1477f
RE
13445#ifdef OPTION_EL
13446 case OPTION_EL:
13447 target_big_endian = 0;
b99bd4ef
NC
13448 break;
13449#endif
13450
03b1477f 13451 case 'a':
cc8a6dd0 13452 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13453 ones. */
13454 return 0;
13455
b99bd4ef 13456 default:
03b1477f
RE
13457 for (opt = arm_opts; opt->option != NULL; opt++)
13458 {
13459 if (c == opt->option[0]
13460 && ((arg == NULL && opt->option[1] == 0)
a737bd4d 13461 || streq (arg, opt->option + 1)))
03b1477f
RE
13462 {
13463#if WARN_DEPRECATED
13464 /* If the option is deprecated, tell the user. */
13465 if (opt->deprecated != NULL)
13466 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13467 arg ? arg : "", _(opt->deprecated));
13468#endif
13469
13470 if (opt->var != NULL)
13471 *opt->var = opt->value;
13472
13473 return 1;
13474 }
13475 }
13476
13477 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13478 {
cc8a6dd0 13479 /* These options are expected to have an argument. */
03b1477f
RE
13480 if (c == lopt->option[0]
13481 && arg != NULL
cc8a6dd0 13482 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13483 strlen (lopt->option + 1)) == 0)
13484 {
13485#if WARN_DEPRECATED
13486 /* If the option is deprecated, tell the user. */
13487 if (lopt->deprecated != NULL)
13488 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13489 _(lopt->deprecated));
13490#endif
13491
13492 /* Call the sup-option parser. */
a737bd4d 13493 return lopt->func (arg + strlen (lopt->option) - 1);
03b1477f
RE
13494 }
13495 }
13496
b99bd4ef
NC
13497 return 0;
13498 }
13499
13500 return 1;
13501}
13502
13503void
a737bd4d 13504md_show_usage (FILE * fp)
b99bd4ef 13505{
03b1477f
RE
13506 struct arm_option_table *opt;
13507 struct arm_long_option_table *lopt;
13508
13509 fprintf (fp, _(" ARM-specific assembler options:\n"));
13510
13511 for (opt = arm_opts; opt->option != NULL; opt++)
13512 if (opt->help != NULL)
13513 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13514
13515 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13516 if (lopt->help != NULL)
13517 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13518
13519#ifdef OPTION_EB
b99bd4ef 13520 fprintf (fp, _("\
03b1477f 13521 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13522#endif
03b1477f
RE
13523
13524#ifdef OPTION_EL
b99bd4ef 13525 fprintf (fp, _("\
03b1477f 13526 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13527#endif
13528}
13529
b99bd4ef
NC
13530/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13531
13532void
a737bd4d
NC
13533cons_fix_new_arm (fragS * frag,
13534 int where,
13535 int size,
13536 expressionS * exp)
b99bd4ef
NC
13537{
13538 bfd_reloc_code_real_type type;
13539 int pcrel = 0;
13540
13541 /* Pick a reloc.
13542 FIXME: @@ Should look at CPU word size. */
13543 switch (size)
13544 {
13545 case 1:
13546 type = BFD_RELOC_8;
13547 break;
13548 case 2:
13549 type = BFD_RELOC_16;
13550 break;
13551 case 4:
13552 default:
13553 type = BFD_RELOC_32;
13554 break;
13555 case 8:
13556 type = BFD_RELOC_64;
13557 break;
13558 }
13559
13560 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13561}
13562
13563/* A good place to do this, although this was probably not intended
13564 for this kind of use. We need to dump the literal pool before
13565 references are made to a null symbol pointer. */
13566
13567void
a737bd4d 13568arm_cleanup (void)
b99bd4ef 13569{
3d0c9500 13570 literal_pool * pool;
b99bd4ef 13571
3d0c9500
NC
13572 for (pool = list_of_pools; pool; pool = pool->next)
13573 {
13574 /* Put it at the end of the relevent section. */
13575 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13576#ifdef OBJ_ELF
13577 arm_elf_change_section ();
13578#endif
3d0c9500
NC
13579 s_ltorg (0);
13580 }
b99bd4ef
NC
13581}
13582
13583void
a737bd4d 13584arm_start_line_hook (void)
b99bd4ef
NC
13585{
13586 last_label_seen = NULL;
13587}
13588
13589void
a737bd4d 13590arm_frob_label (symbolS * sym)
b99bd4ef
NC
13591{
13592 last_label_seen = sym;
13593
13594 ARM_SET_THUMB (sym, thumb_mode);
13595
13596#if defined OBJ_COFF || defined OBJ_ELF
13597 ARM_SET_INTERWORK (sym, support_interwork);
13598#endif
13599
13600 /* Note - do not allow local symbols (.Lxxx) to be labeled
13601 as Thumb functions. This is because these labels, whilst
13602 they exist inside Thumb code, are not the entry points for
13603 possible ARM->Thumb calls. Also, these labels can be used
13604 as part of a computed goto or switch statement. eg gcc
13605 can generate code that looks like this:
13606
13607 ldr r2, [pc, .Laaa]
13608 lsl r3, r3, #2
13609 ldr r2, [r3, r2]
13610 mov pc, r2
cc8a6dd0 13611
b99bd4ef
NC
13612 .Lbbb: .word .Lxxx
13613 .Lccc: .word .Lyyy
13614 ..etc...
13615 .Laaa: .word Lbbb
13616
13617 The first instruction loads the address of the jump table.
13618 The second instruction converts a table index into a byte offset.
13619 The third instruction gets the jump address out of the table.
13620 The fourth instruction performs the jump.
cc8a6dd0 13621
b99bd4ef
NC
13622 If the address stored at .Laaa is that of a symbol which has the
13623 Thumb_Func bit set, then the linker will arrange for this address
13624 to have the bottom bit set, which in turn would mean that the
13625 address computation performed by the third instruction would end
13626 up with the bottom bit set. Since the ARM is capable of unaligned
13627 word loads, the instruction would then load the incorrect address
13628 out of the jump table, and chaos would ensue. */
13629 if (label_is_thumb_function_name
13630 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13631 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13632 {
13633 /* When the address of a Thumb function is taken the bottom
13634 bit of that address should be set. This will allow
13635 interworking between Arm and Thumb functions to work
13636 correctly. */
13637
13638 THUMB_SET_FUNC (sym, 1);
13639
b34976b6 13640 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13641 }
13642}
13643
13644/* Adjust the symbol table. This marks Thumb symbols as distinct from
13645 ARM ones. */
13646
13647void
a737bd4d 13648arm_adjust_symtab (void)
b99bd4ef
NC
13649{
13650#ifdef OBJ_COFF
13651 symbolS * sym;
13652
13653 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13654 {
13655 if (ARM_IS_THUMB (sym))
13656 {
13657 if (THUMB_IS_FUNC (sym))
13658 {
13659 /* Mark the symbol as a Thumb function. */
13660 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13661 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13662 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13663
13664 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13665 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13666 else
13667 as_bad (_("%s: unexpected function type: %d"),
13668 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13669 }
cc8a6dd0 13670 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13671 {
13672 case C_EXT:
13673 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13674 break;
13675 case C_STAT:
13676 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13677 break;
13678 case C_LABEL:
13679 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13680 break;
13681 default:
13682 /* Do nothing. */
13683 break;
13684 }
13685 }
13686
13687 if (ARM_IS_INTERWORK (sym))
13688 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13689 }
13690#endif
13691#ifdef OBJ_ELF
13692 symbolS * sym;
13693 char bind;
13694
13695 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13696 {
13697 if (ARM_IS_THUMB (sym))
13698 {
13699 elf_symbol_type * elf_sym;
13700
13701 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13702 bind = ELF_ST_BIND (elf_sym);
13703
13704 /* If it's a .thumb_func, declare it as so,
13705 otherwise tag label as .code 16. */
13706 if (THUMB_IS_FUNC (sym))
13707 elf_sym->internal_elf_sym.st_info =
13708 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13709 else
13710 elf_sym->internal_elf_sym.st_info =
13711 ELF_ST_INFO (bind, STT_ARM_16BIT);
13712 }
13713 }
13714#endif
13715}
13716
13717int
a737bd4d 13718arm_data_in_code (void)
b99bd4ef
NC
13719{
13720 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13721 {
13722 *input_line_pointer = '/';
13723 input_line_pointer += 5;
13724 *input_line_pointer = 0;
13725 return 1;
13726 }
13727
13728 return 0;
13729}
13730
13731char *
a737bd4d 13732arm_canonicalize_symbol_name (char * name)
b99bd4ef
NC
13733{
13734 int len;
13735
13736 if (thumb_mode && (len = strlen (name)) > 5
13737 && streq (name + len - 5, "/data"))
13738 *(name + len - 5) = 0;
13739
13740 return name;
13741}
13742
bfc866a6 13743#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13744void
a737bd4d 13745arm_validate_fix (fixS * fixP)
b99bd4ef
NC
13746{
13747 /* If the destination of the branch is a defined symbol which does not have
13748 the THUMB_FUNC attribute, then we must be calling a function which has
13749 the (interfacearm) attribute. We look for the Thumb entry point to that
13750 function and change the branch to refer to that function instead. */
13751 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13752 && fixP->fx_addsy != NULL
13753 && S_IS_DEFINED (fixP->fx_addsy)
13754 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13755 {
13756 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13757 }
b99bd4ef 13758}
bfc866a6 13759#endif
b99bd4ef 13760
114424c6 13761int
a737bd4d 13762arm_force_relocation (struct fix * fixp)
114424c6
AM
13763{
13764#if defined (OBJ_COFF) && defined (TE_PE)
13765 if (fixp->fx_r_type == BFD_RELOC_RVA)
13766 return 1;
13767#endif
13768#ifdef OBJ_ELF
ae6063d4 13769 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13770 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13771 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13772 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13773 return 1;
13774#endif
13775
13776 /* Resolve these relocations even if the symbol is extern or weak. */
13777 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13778 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13779 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13780 return 0;
13781
ae6063d4 13782 return generic_force_reloc (fixp);
114424c6
AM
13783}
13784
b99bd4ef
NC
13785#ifdef OBJ_COFF
13786/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13787 local labels from being added to the output symbol table when they
13788 are used with the ADRL pseudo op. The ADRL relocation should always
13789 be resolved before the binbary is emitted, so it is safe to say that
13790 it is adjustable. */
13791
b34976b6 13792bfd_boolean
a737bd4d 13793arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13794{
13795 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13796 return 1;
13797 return 0;
13798}
13799#endif
114424c6 13800
b99bd4ef
NC
13801#ifdef OBJ_ELF
13802/* Relocations against Thumb function names must be left unadjusted,
13803 so that the linker can use this information to correctly set the
13804 bottom bit of their addresses. The MIPS version of this function
13805 also prevents relocations that are mips-16 specific, but I do not
13806 know why it does this.
13807
13808 FIXME:
13809 There is one other problem that ought to be addressed here, but
13810 which currently is not: Taking the address of a label (rather
13811 than a function) and then later jumping to that address. Such
13812 addresses also ought to have their bottom bit set (assuming that
13813 they reside in Thumb code), but at the moment they will not. */
13814
b34976b6 13815bfd_boolean
a737bd4d 13816arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13817{
13818 if (fixP->fx_addsy == NULL)
13819 return 1;
13820
b99bd4ef
NC
13821 if (THUMB_IS_FUNC (fixP->fx_addsy)
13822 && fixP->fx_subsy == NULL)
13823 return 0;
13824
13825 /* We need the symbol name for the VTABLE entries. */
13826 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13827 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13828 return 0;
13829
a161fe53
AM
13830 /* Don't allow symbols to be discarded on GOT related relocs. */
13831 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13832 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
13833 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13834 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
13835 return 0;
13836
b99bd4ef
NC
13837 return 1;
13838}
13839
13840const char *
a737bd4d 13841elf32_arm_target_format (void)
b99bd4ef 13842{
e5a52504
MM
13843#ifdef TE_SYMBIAN
13844 return (target_big_endian
13845 ? "elf32-bigarm-symbian"
13846 : "elf32-littlearm-symbian");
4e7fd91e
PB
13847#elif defined (TE_VXWORKS)
13848 return (target_big_endian
13849 ? "elf32-bigarm-vxworks"
13850 : "elf32-littlearm-vxworks");
a737bd4d 13851#else
b99bd4ef 13852 if (target_big_endian)
7f266840 13853 return "elf32-bigarm";
b99bd4ef 13854 else
7f266840 13855 return "elf32-littlearm";
e5a52504 13856#endif
b99bd4ef
NC
13857}
13858
13859void
a737bd4d
NC
13860armelf_frob_symbol (symbolS * symp,
13861 int * puntp)
b99bd4ef
NC
13862{
13863 elf_frob_symbol (symp, puntp);
13864}
13865
b99bd4ef 13866static void
a737bd4d 13867s_arm_elf_cons (int nbytes)
b99bd4ef
NC
13868{
13869 expressionS exp;
13870
13871#ifdef md_flush_pending_output
13872 md_flush_pending_output ();
13873#endif
13874
13875 if (is_it_end_of_statement ())
13876 {
13877 demand_empty_rest_of_line ();
13878 return;
13879 }
13880
13881#ifdef md_cons_align
13882 md_cons_align (nbytes);
13883#endif
13884
6057a28f 13885 mapping_state (MAP_DATA);
b99bd4ef
NC
13886 do
13887 {
13888 bfd_reloc_code_real_type reloc;
13889
13890 expression (& exp);
13891
13892 if (exp.X_op == O_symbol
13893 && * input_line_pointer == '('
13894 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13895 {
13896 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13897 int size = bfd_get_reloc_size (howto);
13898
13899 if (size > nbytes)
13900 as_bad ("%s relocations do not fit in %d bytes",
13901 howto->name, nbytes);
13902 else
13903 {
a737bd4d 13904 char *p = frag_more ((int) nbytes);
b99bd4ef
NC
13905 int offset = nbytes - size;
13906
13907 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13908 &exp, 0, reloc);
13909 }
13910 }
13911 else
13912 emit_expr (&exp, (unsigned int) nbytes);
13913 }
13914 while (*input_line_pointer++ == ',');
13915
13916 /* Put terminator back into stream. */
13917 input_line_pointer --;
13918 demand_empty_rest_of_line ();
13919}
13920
eb043451
PB
13921
13922/* Parse a .rel31 directive. */
13923
13924static void
13925s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13926{
13927 expressionS exp;
13928 char *p;
13929 valueT highbit;
a737bd4d 13930
eb043451
PB
13931 SKIP_WHITESPACE ();
13932
13933 highbit = 0;
13934 if (*input_line_pointer == '1')
13935 highbit = 0x80000000;
13936 else if (*input_line_pointer != '0')
13937 as_bad (_("expected 0 or 1"));
13938
13939 input_line_pointer++;
13940 SKIP_WHITESPACE ();
13941 if (*input_line_pointer != ',')
13942 as_bad (_("missing comma"));
13943 input_line_pointer++;
13944
13945#ifdef md_flush_pending_output
13946 md_flush_pending_output ();
13947#endif
13948
13949#ifdef md_cons_align
13950 md_cons_align (4);
13951#endif
13952
13953 mapping_state (MAP_DATA);
13954
13955 expression (&exp);
13956
13957 p = frag_more (4);
13958 md_number_to_chars (p, highbit, 4);
13959 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13960 BFD_RELOC_ARM_PREL31);
13961
13962 demand_empty_rest_of_line ();
13963}
7ed4c4c5
NC
13964\f
13965/* Code to deal with unwinding tables. */
13966
13967static void add_unwind_adjustsp (offsetT);
13968
13969/* Switch to section NAME and create section if necessary. It's
13970 rather ugly that we have to manipulate input_line_pointer but I
13971 don't see any other way to accomplish the same thing without
13972 changing obj-elf.c (which may be the Right Thing, in the end).
13973 Copied from tc-ia64.c. */
13974
13975static void
13976set_section (char *name)
13977{
13978 char *saved_input_line_pointer;
13979
13980 saved_input_line_pointer = input_line_pointer;
13981 input_line_pointer = name;
13982 obj_elf_section (0);
13983 input_line_pointer = saved_input_line_pointer;
13984}
13985
13986/* Cenerate and deferred unwind frame offset. */
13987
13988static void
13989flush_pending_unwind (void)
13990{
13991 offsetT offset;
13992
13993 offset = unwind.pending_offset;
13994 unwind.pending_offset = 0;
13995 if (offset != 0)
13996 add_unwind_adjustsp (offset);
13997}
13998
13999/* Add an opcode to this list for this function. Two-byte opcodes should
14000 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14001 order. */
14002
14003static void
14004add_unwind_opcode (valueT op, int length)
14005{
14006 /* Add any deferred stack adjustment. */
14007 if (unwind.pending_offset)
14008 flush_pending_unwind ();
14009
14010 unwind.sp_restored = 0;
14011
14012 if (unwind.opcode_count + length > unwind.opcode_alloc)
14013 {
14014 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14015 if (unwind.opcodes)
14016 unwind.opcodes = xrealloc (unwind.opcodes,
14017 unwind.opcode_alloc);
14018 else
14019 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14020 }
14021 while (length > 0)
14022 {
14023 length--;
14024 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14025 op >>= 8;
14026 unwind.opcode_count++;
14027 }
14028}
14029
14030/* Add unwind opcodes to adjust the stack pointer. */
14031
14032static void
14033add_unwind_adjustsp (offsetT offset)
14034{
14035 valueT op;
14036
14037 if (offset > 0x200)
14038 {
14039 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14040 char bytes[5];
14041 int n;
14042 valueT o;
14043
14044 /* Long form: 0xb2, uleb128. */
14045 /* This might not fit in a word so add the individual bytes,
14046 remembering the list is built in reverse order. */
14047 o = (valueT) ((offset - 0x204) >> 2);
14048 if (o == 0)
14049 add_unwind_opcode (0, 1);
14050
14051 /* Calculate the uleb128 encoding of the offset. */
14052 n = 0;
14053 while (o)
14054 {
14055 bytes[n] = o & 0x7f;
14056 o >>= 7;
14057 if (o)
14058 bytes[n] |= 0x80;
14059 n++;
14060 }
14061 /* Add the insn. */
14062 for (; n; n--)
14063 add_unwind_opcode (bytes[n - 1], 1);
14064 add_unwind_opcode (0xb2, 1);
14065 }
14066 else if (offset > 0x100)
14067 {
14068 /* Two short opcodes. */
14069 add_unwind_opcode (0x3f, 1);
14070 op = (offset - 0x104) >> 2;
14071 add_unwind_opcode (op, 1);
14072 }
14073 else if (offset > 0)
14074 {
14075 /* Short opcode. */
14076 op = (offset - 4) >> 2;
14077 add_unwind_opcode (op, 1);
14078 }
14079 else if (offset < 0)
14080 {
14081 offset = -offset;
14082 while (offset > 0x100)
14083 {
14084 add_unwind_opcode (0x7f, 1);
14085 offset -= 0x100;
14086 }
14087 op = ((offset - 4) >> 2) | 0x40;
14088 add_unwind_opcode (op, 1);
14089 }
14090}
14091
14092/* Finish the list of unwind opcodes for this function. */
14093static void
14094finish_unwind_opcodes (void)
14095{
14096 valueT op;
14097
14098 if (unwind.fp_used)
14099 {
14100 /* Adjust sp as neccessary. */
14101 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14102 flush_pending_unwind ();
14103
14104 /* After restoring sp from the frame pointer. */
14105 op = 0x90 | unwind.fp_reg;
14106 add_unwind_opcode (op, 1);
14107 }
14108 else
14109 flush_pending_unwind ();
14110}
14111
14112
14113/* Start an exception table entry. If idx is nonzero this is an index table
14114 entry. */
14115
14116static void
14117start_unwind_section (const segT text_seg, int idx)
14118{
14119 const char * text_name;
14120 const char * prefix;
14121 const char * prefix_once;
14122 size_t prefix_len;
14123 size_t text_len;
14124 char * sec_name;
14125 size_t sec_name_len;
14126
14127 if (idx)
14128 {
14129 prefix = ELF_STRING_ARM_unwind;
14130 prefix_once = ELF_STRING_ARM_unwind_once;
14131 }
14132 else
14133 {
14134 prefix = ELF_STRING_ARM_unwind_info;
14135 prefix_once = ELF_STRING_ARM_unwind_info_once;
14136 }
14137
14138 text_name = segment_name (text_seg);
14139 if (streq (text_name, ".text"))
14140 text_name = "";
14141
14142 if (strncmp (text_name, ".gnu.linkonce.t.",
14143 strlen (".gnu.linkonce.t.")) == 0)
14144 {
14145 prefix = prefix_once;
14146 text_name += strlen (".gnu.linkonce.t.");
14147 }
14148
14149 prefix_len = strlen (prefix);
14150 text_len = strlen (text_name);
14151 sec_name_len = prefix_len + text_len;
14152 sec_name = alloca (sec_name_len + 1);
14153 memcpy (sec_name, prefix, prefix_len);
14154 memcpy (sec_name + prefix_len, text_name, text_len);
14155 sec_name[prefix_len + text_len] = '\0';
14156
14157 /* Handle COMDAT group. */
14158 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14159 {
14160 char *section;
14161 size_t len, group_name_len;
14162 const char *group_name = elf_group_name (text_seg);
14163
14164 if (group_name == NULL)
14165 {
14166 as_bad ("Group section `%s' has no group signature",
14167 segment_name (text_seg));
14168 ignore_rest_of_line ();
14169 return;
14170 }
14171 /* We have to construct a fake section directive. */
14172 group_name_len = strlen (group_name);
14173 if (idx)
14174 prefix_len = 13;
14175 else
14176 prefix_len = 16;
14177
14178 len = (sec_name_len
14179 + prefix_len /* ,"aG",%sectiontype, */
14180 + group_name_len /* ,group_name */
14181 + 7); /* ,comdat */
14182
14183 section = alloca (len + 1);
14184 memcpy (section, sec_name, sec_name_len);
14185 if (idx)
14186 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14187 else
14188 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14189 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14190 memcpy (section + len - 7, ",comdat", 7);
14191 section [len] = '\0';
14192 set_section (section);
14193 }
14194 else
14195 {
14196 set_section (sec_name);
14197 bfd_set_section_flags (stdoutput, now_seg,
14198 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14199 }
14200
14201 /* Set the setion link for index tables. */
14202 if (idx)
14203 elf_linked_to_section (now_seg) = text_seg;
14204}
14205
14206
14207/* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14208 personality routine data. Returns zero, or the index table value for
14209 and inline entry. */
14210
14211static valueT
14212create_unwind_entry (int have_data)
14213{
14214 int size;
14215 addressT where;
2132e3a3 14216 char *ptr;
7ed4c4c5
NC
14217 /* The current word of data. */
14218 valueT data;
14219 /* The number of bytes left in this word. */
14220 int n;
14221
14222 finish_unwind_opcodes ();
14223
14224 /* Remember the current text section. */
14225 unwind.saved_seg = now_seg;
14226 unwind.saved_subseg = now_subseg;
14227
14228 start_unwind_section (now_seg, 0);
14229
14230 if (unwind.personality_routine == NULL)
14231 {
14232 if (unwind.personality_index == -2)
14233 {
14234 if (have_data)
14235 as_bad (_("handerdata in cantunwind frame"));
14236 return 1; /* EXIDX_CANTUNWIND. */
14237 }
14238
14239 /* Use a default personality routine if none is specified. */
14240 if (unwind.personality_index == -1)
14241 {
14242 if (unwind.opcode_count > 3)
14243 unwind.personality_index = 1;
14244 else
14245 unwind.personality_index = 0;
14246 }
14247
14248 /* Space for the personality routine entry. */
14249 if (unwind.personality_index == 0)
14250 {
14251 if (unwind.opcode_count > 3)
14252 as_bad (_("too many unwind opcodes for personality routine 0"));
14253
14254 if (!have_data)
14255 {
14256 /* All the data is inline in the index table. */
14257 data = 0x80;
14258 n = 3;
14259 while (unwind.opcode_count > 0)
14260 {
14261 unwind.opcode_count--;
14262 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14263 n--;
14264 }
14265
14266 /* Pad with "finish" opcodes. */
14267 while (n--)
14268 data = (data << 8) | 0xb0;
14269
14270 return data;
14271 }
14272 size = 0;
14273 }
14274 else
14275 /* We get two opcodes "free" in the first word. */
14276 size = unwind.opcode_count - 2;
14277 }
14278 else
14279 /* An extra byte is required for the opcode count. */
14280 size = unwind.opcode_count + 1;
14281
14282 size = (size + 3) >> 2;
14283 if (size > 0xff)
14284 as_bad (_("too many unwind opcodes"));
14285
14286 frag_align (2, 0, 0);
14287 record_alignment (now_seg, 2);
14288 unwind.table_entry = expr_build_dot ();
14289
14290 /* Allocate the table entry. */
14291 ptr = frag_more ((size << 2) + 4);
14292 where = frag_now_fix () - ((size << 2) + 4);
14293
14294 switch (unwind.personality_index)
14295 {
14296 case -1:
14297 /* ??? Should this be a PLT generating relocation? */
14298 /* Custom personality routine. */
14299 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14300 BFD_RELOC_ARM_PREL31);
620b81c1
JB
14301
14302 /* Indicate dependency to linker. */
14303 {
14304 char *name = "__aeabi_unwind_cpp_pr0";
14305 symbolS *pr = symbol_find_or_make (name);
14306 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14307 }
14308
7ed4c4c5
NC
14309 where += 4;
14310 ptr += 4;
14311
14312 /* Set the first byte to the number of additional words. */
14313 data = size - 1;
14314 n = 3;
14315 break;
14316
14317 /* ABI defined personality routines. */
7ed4c4c5
NC
14318 case 0:
14319 /* Three opcodes bytes are packed into the first word. */
14320 data = 0x80;
14321 n = 3;
620b81c1 14322 goto emit_reloc;
7ed4c4c5
NC
14323
14324 case 1:
14325 case 2:
14326 /* The size and first two opcode bytes go in the first word. */
14327 data = ((0x80 + unwind.personality_index) << 8) | size;
14328 n = 2;
620b81c1
JB
14329 goto emit_reloc;
14330
14331 emit_reloc:
14332 {
14333 /* Indicate dependency to linker. */
14334 char *name[] = { "__aeabi_unwind_cpp_pr0",
14335 "__aeabi_unwind_cpp_pr1",
14336 "__aeabi_unwind_cpp_pr2" };
14337 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14338 fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
14339 }
7ed4c4c5
NC
14340 break;
14341
14342 default:
14343 /* Should never happen. */
14344 abort ();
14345 }
14346
14347 /* Pack the opcodes into words (MSB first), reversing the list at the same
14348 time. */
14349 while (unwind.opcode_count > 0)
14350 {
14351 if (n == 0)
14352 {
14353 md_number_to_chars (ptr, data, 4);
14354 ptr += 4;
14355 n = 4;
14356 data = 0;
14357 }
14358 unwind.opcode_count--;
14359 n--;
14360 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14361 }
14362
14363 /* Finish off the last word. */
14364 if (n < 4)
14365 {
14366 /* Pad with "finish" opcodes. */
14367 while (n--)
14368 data = (data << 8) | 0xb0;
14369
14370 md_number_to_chars (ptr, data, 4);
14371 }
14372
14373 if (!have_data)
14374 {
14375 /* Add an empty descriptor if there is no user-specified data. */
14376 ptr = frag_more (4);
14377 md_number_to_chars (ptr, 0, 4);
14378 }
14379
14380 return 0;
14381}
14382
14383
14384/* Parse an unwind_fnstart directive. Simply records the current location. */
14385
14386static void
14387s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14388{
14389 demand_empty_rest_of_line ();
14390 /* Mark the start of the function. */
14391 unwind.proc_start = expr_build_dot ();
14392
14393 /* Reset the rest of the unwind info. */
14394 unwind.opcode_count = 0;
14395 unwind.table_entry = NULL;
14396 unwind.personality_routine = NULL;
14397 unwind.personality_index = -1;
14398 unwind.frame_size = 0;
14399 unwind.fp_offset = 0;
14400 unwind.fp_reg = 13;
14401 unwind.fp_used = 0;
14402 unwind.sp_restored = 0;
14403}
14404
14405
14406/* Parse a handlerdata directive. Creates the exception handling table entry
14407 for the function. */
14408
14409static void
14410s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14411{
14412 demand_empty_rest_of_line ();
14413 if (unwind.table_entry)
14414 as_bad (_("dupicate .handlerdata directive"));
14415
14416 create_unwind_entry (1);
14417}
14418
14419/* Parse an unwind_fnend directive. Generates the index table entry. */
14420
14421static void
14422s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14423{
14424 long where;
2132e3a3 14425 char *ptr;
7ed4c4c5
NC
14426 valueT val;
14427
14428 demand_empty_rest_of_line ();
14429
14430 /* Add eh table entry. */
14431 if (unwind.table_entry == NULL)
14432 val = create_unwind_entry (0);
14433 else
14434 val = 0;
14435
14436 /* Add index table entry. This is two words. */
14437 start_unwind_section (unwind.saved_seg, 1);
14438 frag_align (2, 0, 0);
14439 record_alignment (now_seg, 2);
14440
14441 ptr = frag_more (8);
14442 where = frag_now_fix () - 8;
14443
14444 /* Self relative offset of the function start. */
14445 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
be1b2b4b 14446 BFD_RELOC_ARM_PREL31);
7ed4c4c5
NC
14447
14448 if (val)
14449 /* Inline exception table entry. */
14450 md_number_to_chars (ptr + 4, val, 4);
14451 else
14452 /* Self relative offset of the table entry. */
14453 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14454 BFD_RELOC_ARM_PREL31);
14455
14456 /* Restore the original section. */
14457 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14458}
14459
14460
14461/* Parse an unwind_cantunwind directive. */
14462
14463static void
14464s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14465{
14466 demand_empty_rest_of_line ();
14467 if (unwind.personality_routine || unwind.personality_index != -1)
14468 as_bad (_("personality routine specified for cantunwind frame"));
14469
14470 unwind.personality_index = -2;
14471}
14472
14473
14474/* Parse a personalityindex directive. */
14475
14476static void
14477s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14478{
14479 expressionS exp;
14480
14481 if (unwind.personality_routine || unwind.personality_index != -1)
14482 as_bad (_("duplicate .personalityindex directive"));
14483
14484 SKIP_WHITESPACE ();
14485
14486 expression (&exp);
14487
14488 if (exp.X_op != O_constant
14489 || exp.X_add_number < 0 || exp.X_add_number > 15)
14490 {
14491 as_bad (_("bad personality routine number"));
14492 ignore_rest_of_line ();
14493 return;
14494 }
14495
14496 unwind.personality_index = exp.X_add_number;
14497
14498 demand_empty_rest_of_line ();
14499}
14500
14501
14502/* Parse a personality directive. */
14503
14504static void
14505s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14506{
14507 char *name, *p, c;
14508
14509 if (unwind.personality_routine || unwind.personality_index != -1)
14510 as_bad (_("duplicate .personality directive"));
14511
14512 SKIP_WHITESPACE ();
14513 name = input_line_pointer;
14514 c = get_symbol_end ();
14515 p = input_line_pointer;
14516 unwind.personality_routine = symbol_find_or_make (name);
14517 *p = c;
14518 SKIP_WHITESPACE ();
14519 demand_empty_rest_of_line ();
14520}
14521
14522
14523/* Parse a directive saving core registers. */
14524
14525static void
14526s_arm_unwind_save_core (void)
14527{
14528 valueT op;
14529 long range;
14530 int n;
14531
14532 SKIP_WHITESPACE ();
14533 range = reg_list (&input_line_pointer);
14534 if (range == FAIL)
14535 {
14536 as_bad (_("expected register list"));
14537 ignore_rest_of_line ();
14538 return;
14539 }
14540
14541 demand_empty_rest_of_line ();
14542
14543 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14544 into .unwind_save {..., sp...}. We aren't bothered about the value of
14545 ip because it is clobbered by calls. */
14546 if (unwind.sp_restored && unwind.fp_reg == 12
14547 && (range & 0x3000) == 0x1000)
14548 {
14549 unwind.opcode_count--;
14550 unwind.sp_restored = 0;
14551 range = (range | 0x2000) & ~0x1000;
14552 unwind.pending_offset = 0;
14553 }
14554
14555 /* See if we can use the short opcodes. These pop a block of upto 8
14556 registers starting with r4, plus maybe r14. */
14557 for (n = 0; n < 8; n++)
14558 {
14559 /* Break at the first non-saved register. */
14560 if ((range & (1 << (n + 4))) == 0)
14561 break;
14562 }
14563 /* See if there are any other bits set. */
14564 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14565 {
14566 /* Use the long form. */
14567 op = 0x8000 | ((range >> 4) & 0xfff);
14568 add_unwind_opcode (op, 2);
14569 }
14570 else
14571 {
14572 /* Use the short form. */
14573 if (range & 0x4000)
14574 op = 0xa8; /* Pop r14. */
14575 else
14576 op = 0xa0; /* Do not pop r14. */
14577 op |= (n - 1);
14578 add_unwind_opcode (op, 1);
14579 }
14580
14581 /* Pop r0-r3. */
14582 if (range & 0xf)
14583 {
14584 op = 0xb100 | (range & 0xf);
14585 add_unwind_opcode (op, 2);
14586 }
14587
14588 /* Record the number of bytes pushed. */
14589 for (n = 0; n < 16; n++)
14590 {
14591 if (range & (1 << n))
14592 unwind.frame_size += 4;
14593 }
14594}
14595
14596
14597/* Parse a directive saving FPA registers. */
14598
14599static void
14600s_arm_unwind_save_fpa (int reg)
14601{
14602 expressionS exp;
14603 int num_regs;
14604 valueT op;
14605
14606 /* Get Number of registers to transfer. */
14607 if (skip_past_comma (&input_line_pointer) != FAIL)
14608 expression (&exp);
14609 else
14610 exp.X_op = O_illegal;
14611
14612 if (exp.X_op != O_constant)
14613 {
14614 as_bad (_("expected , <constant>"));
14615 ignore_rest_of_line ();
14616 return;
14617 }
14618
14619 num_regs = exp.X_add_number;
14620
14621 if (num_regs < 1 || num_regs > 4)
14622 {
14623 as_bad (_("number of registers must be in the range [1:4]"));
14624 ignore_rest_of_line ();
14625 return;
14626 }
14627
14628 demand_empty_rest_of_line ();
14629
14630 if (reg == 4)
14631 {
14632 /* Short form. */
14633 op = 0xb4 | (num_regs - 1);
14634 add_unwind_opcode (op, 1);
14635 }
14636 else
14637 {
14638 /* Long form. */
14639 op = 0xc800 | (reg << 4) | (num_regs - 1);
14640 add_unwind_opcode (op, 2);
14641 }
14642 unwind.frame_size += num_regs * 12;
14643}
14644
14645
14646/* Parse a directive saving VFP registers. */
14647
14648static void
14649s_arm_unwind_save_vfp (void)
14650{
14651 int count;
14652 int reg;
14653 valueT op;
14654
14655 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14656 if (count == FAIL)
14657 {
14658 as_bad (_("expected register list"));
14659 ignore_rest_of_line ();
14660 return;
14661 }
14662
14663 demand_empty_rest_of_line ();
14664
14665 if (reg == 8)
14666 {
14667 /* Short form. */
14668 op = 0xb8 | (count - 1);
14669 add_unwind_opcode (op, 1);
14670 }
14671 else
14672 {
14673 /* Long form. */
14674 op = 0xb300 | (reg << 4) | (count - 1);
14675 add_unwind_opcode (op, 2);
14676 }
14677 unwind.frame_size += count * 8 + 4;
14678}
14679
14680
14681/* Parse a directive saving iWMMXt registers. */
14682
14683static void
14684s_arm_unwind_save_wmmx (void)
14685{
14686 int reg;
14687 int hi_reg;
14688 int i;
14689 unsigned wcg_mask;
14690 unsigned wr_mask;
14691 valueT op;
14692
14693 if (*input_line_pointer == '{')
14694 input_line_pointer++;
14695
14696 wcg_mask = 0;
14697 wr_mask = 0;
14698 do
14699 {
14700 reg = arm_reg_parse (&input_line_pointer,
14701 all_reg_maps[REG_TYPE_IWMMXT].htab);
14702
14703 if (wr_register (reg))
14704 {
14705 i = reg & ~WR_PREFIX;
14706 if (wr_mask >> i)
14707 as_tsktsk (_("register list not in ascending order"));
14708 wr_mask |= 1 << i;
14709 }
14710 else if (wcg_register (reg))
14711 {
14712 i = (reg & ~WC_PREFIX) - 8;
14713 if (wcg_mask >> i)
14714 as_tsktsk (_("register list not in ascending order"));
14715 wcg_mask |= 1 << i;
14716 }
14717 else
14718 {
14719 as_bad (_("expected wr or wcgr"));
14720 goto error;
14721 }
14722
14723 SKIP_WHITESPACE ();
14724 if (*input_line_pointer == '-')
14725 {
14726 hi_reg = arm_reg_parse (&input_line_pointer,
14727 all_reg_maps[REG_TYPE_IWMMXT].htab);
14728 if (wr_register (reg) && wr_register (hi_reg))
14729 {
14730 for (; reg < hi_reg; reg++)
14731 wr_mask |= 1 << (reg & ~WR_PREFIX);
14732 }
14733 else if (wcg_register (reg) && wcg_register (hi_reg))
14734 {
14735 for (; reg < hi_reg; reg++)
14736 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14737 }
14738 else
14739 {
14740 as_bad (_("bad register range"));
14741 goto error;
14742 }
14743 }
14744 }
14745 while (skip_past_comma (&input_line_pointer) != FAIL);
14746
14747 SKIP_WHITESPACE ();
14748 if (*input_line_pointer == '}')
14749 input_line_pointer++;
14750
14751 demand_empty_rest_of_line ();
14752
14753 if (wr_mask && wcg_mask)
14754 {
14755 as_bad (_("inconsistent register types"));
14756 goto error;
14757 }
14758
14759 /* Generate any deferred opcodes becuuse we're going to be looking at
14760 the list. */
14761 flush_pending_unwind ();
14762
14763 if (wcg_mask)
14764 {
14765 for (i = 0; i < 16; i++)
14766 {
14767 if (wcg_mask & (1 << i))
14768 unwind.frame_size += 4;
14769 }
14770 op = 0xc700 | wcg_mask;
14771 add_unwind_opcode (op, 2);
14772 }
14773 else
14774 {
14775 for (i = 0; i < 16; i++)
14776 {
14777 if (wr_mask & (1 << i))
14778 unwind.frame_size += 8;
14779 }
14780 /* Attempt to combine with a previous opcode. We do this because gcc
14781 likes to output separate unwind directives for a single block of
14782 registers. */
14783 if (unwind.opcode_count > 0)
14784 {
14785 i = unwind.opcodes[unwind.opcode_count - 1];
14786 if ((i & 0xf8) == 0xc0)
14787 {
14788 i &= 7;
14789 /* Only merge if the blocks are contiguous. */
14790 if (i < 6)
14791 {
14792 if ((wr_mask & 0xfe00) == (1 << 9))
14793 {
14794 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14795 unwind.opcode_count--;
14796 }
14797 }
14798 else if (i == 6 && unwind.opcode_count >= 2)
14799 {
14800 i = unwind.opcodes[unwind.opcode_count - 2];
14801 reg = i >> 4;
14802 i &= 0xf;
14803
14804 op = 0xffff << (reg - 1);
14805 if (reg > 0
14806 || ((wr_mask & op) == (1u << (reg - 1))))
14807 {
14808 op = (1 << (reg + i + 1)) - 1;
14809 op &= ~((1 << reg) - 1);
14810 wr_mask |= op;
14811 unwind.opcode_count -= 2;
14812 }
14813 }
14814 }
14815 }
14816
14817 hi_reg = 15;
14818 /* We want to generate opcodes in the order the registers have been
14819 saved, ie. descending order. */
14820 for (reg = 15; reg >= -1; reg--)
14821 {
14822 /* Save registers in blocks. */
14823 if (reg < 0
14824 || !(wr_mask & (1 << reg)))
14825 {
14826 /* We found an unsaved reg. Generate opcodes to save the
14827 preceeding block. */
14828 if (reg != hi_reg)
14829 {
14830 if (reg == 9)
14831 {
14832 /* Short form. */
14833 op = 0xc0 | (hi_reg - 10);
14834 add_unwind_opcode (op, 1);
14835 }
14836 else
14837 {
14838 /* Long form. */
14839 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14840 add_unwind_opcode (op, 2);
14841 }
14842 }
14843 hi_reg = reg - 1;
14844 }
14845 }
14846 }
14847 return;
14848error:
14849 ignore_rest_of_line ();
14850}
14851
14852
14853/* Parse an unwind_save directive. */
14854
14855static void
14856s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14857{
14858 char *saved_ptr;
14859 int reg;
14860
14861 /* Figure out what sort of save we have. */
14862 SKIP_WHITESPACE ();
14863 saved_ptr = input_line_pointer;
14864
14865 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14866 if (reg != FAIL)
14867 {
14868 s_arm_unwind_save_fpa (reg);
14869 return;
14870 }
14871
14872 if (*input_line_pointer == '{')
14873 input_line_pointer++;
14874
14875 SKIP_WHITESPACE ();
14876
14877 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14878 if (reg != FAIL)
14879 {
14880 input_line_pointer = saved_ptr;
14881 s_arm_unwind_save_core ();
14882 return;
14883 }
14884
14885 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14886 if (reg != FAIL)
14887 {
14888 input_line_pointer = saved_ptr;
14889 s_arm_unwind_save_vfp ();
14890 return;
14891 }
14892
14893 reg = arm_reg_parse (&input_line_pointer,
14894 all_reg_maps[REG_TYPE_IWMMXT].htab);
14895 if (reg != FAIL)
14896 {
14897 input_line_pointer = saved_ptr;
14898 s_arm_unwind_save_wmmx ();
14899 return;
14900 }
14901
14902 /* TODO: Maverick registers. */
14903 as_bad (_("unrecognised register"));
14904}
14905
14906
14907/* Parse an unwind_movsp directive. */
14908
14909static void
14910s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14911{
14912 int reg;
14913 valueT op;
14914
14915 SKIP_WHITESPACE ();
14916 reg = reg_required_here (&input_line_pointer, -1);
14917 if (reg == FAIL)
14918 {
14919 as_bad (_("ARM register expected"));
14920 ignore_rest_of_line ();
14921 return;
14922 }
14923
14924 if (reg == 13 || reg == 15)
14925 {
14926 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14927 ignore_rest_of_line ();
14928 return;
14929 }
14930
14931 if (unwind.fp_reg != 13)
14932 as_bad (_("unexpected .unwind_movsp directive"));
14933
14934 /* Generate opcode to restore the value. */
14935 op = 0x90 | reg;
14936 add_unwind_opcode (op, 1);
14937
14938 /* Record the information for later. */
14939 unwind.fp_reg = reg;
14940 unwind.fp_offset = unwind.frame_size;
14941 unwind.sp_restored = 1;
14942 demand_empty_rest_of_line ();
14943}
14944
14945
14946/* Parse #<number>. */
14947
14948static int
14949require_hashconst (int * val)
14950{
14951 expressionS exp;
14952
14953 SKIP_WHITESPACE ();
14954 if (*input_line_pointer == '#')
14955 {
14956 input_line_pointer++;
14957 expression (&exp);
14958 }
14959 else
14960 exp.X_op = O_illegal;
14961
14962 if (exp.X_op != O_constant)
14963 {
14964 as_bad (_("expected #constant"));
14965 ignore_rest_of_line ();
14966 return FAIL;
14967 }
14968 *val = exp.X_add_number;
14969 return SUCCESS;
14970}
14971
14972/* Parse an unwind_pad directive. */
14973
14974static void
14975s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14976{
14977 int offset;
14978
14979 if (require_hashconst (&offset) == FAIL)
14980 return;
14981
14982 if (offset & 3)
14983 {
14984 as_bad (_("stack increment must be multiple of 4"));
14985 ignore_rest_of_line ();
14986 return;
14987 }
14988
14989 /* Don't generate any opcodes, just record the details for later. */
14990 unwind.frame_size += offset;
14991 unwind.pending_offset += offset;
14992
14993 demand_empty_rest_of_line ();
14994}
14995
14996/* Parse an unwind_setfp directive. */
14997
14998static void
14999s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
15000{
15001 int sp_reg;
15002 int fp_reg;
15003 int offset;
15004
15005 fp_reg = reg_required_here (&input_line_pointer, -1);
15006 if (skip_past_comma (&input_line_pointer) == FAIL)
15007 sp_reg = FAIL;
15008 else
15009 sp_reg = reg_required_here (&input_line_pointer, -1);
15010
15011 if (fp_reg == FAIL || sp_reg == FAIL)
15012 {
15013 as_bad (_("expected <reg>, <reg>"));
15014 ignore_rest_of_line ();
15015 return;
15016 }
15017
15018 /* Optonal constant. */
15019 if (skip_past_comma (&input_line_pointer) != FAIL)
15020 {
15021 if (require_hashconst (&offset) == FAIL)
15022 return;
15023 }
15024 else
15025 offset = 0;
15026
15027 demand_empty_rest_of_line ();
15028
15029 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15030 {
15031 as_bad (_("register must be either sp or set by a previous"
15032 "unwind_movsp directive"));
15033 return;
15034 }
15035
15036 /* Don't generate any opcodes, just record the information for later. */
15037 unwind.fp_reg = fp_reg;
15038 unwind.fp_used = 1;
15039 if (sp_reg == 13)
15040 unwind.fp_offset = unwind.frame_size - offset;
15041 else
15042 unwind.fp_offset -= offset;
15043}
15044
15045/* Parse an unwind_raw directive. */
15046
15047static void
15048s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15049{
15050 expressionS exp;
15051 /* This is an arbitary limit. */
15052 unsigned char op[16];
15053 int count;
15054
15055 SKIP_WHITESPACE ();
15056 expression (&exp);
15057 if (exp.X_op == O_constant
15058 && skip_past_comma (&input_line_pointer) != FAIL)
15059 {
15060 unwind.frame_size += exp.X_add_number;
15061 expression (&exp);
15062 }
15063 else
15064 exp.X_op = O_illegal;
15065
15066 if (exp.X_op != O_constant)
15067 {
15068 as_bad (_("expected <offset>, <opcode>"));
15069 ignore_rest_of_line ();
15070 return;
15071 }
15072
15073 count = 0;
15074
15075 /* Parse the opcode. */
15076 for (;;)
15077 {
15078 if (count >= 16)
15079 {
15080 as_bad (_("unwind opcode too long"));
15081 ignore_rest_of_line ();
15082 }
15083 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15084 {
15085 as_bad (_("invalid unwind opcode"));
15086 ignore_rest_of_line ();
15087 return;
15088 }
15089 op[count++] = exp.X_add_number;
15090
15091 /* Parse the next byte. */
15092 if (skip_past_comma (&input_line_pointer) == FAIL)
15093 break;
15094
15095 expression (&exp);
15096 }
15097
15098 /* Add the opcode bytes in reverse order. */
15099 while (count--)
15100 add_unwind_opcode (op[count], 1);
15101
15102 demand_empty_rest_of_line ();
15103}
eb043451 15104
b99bd4ef
NC
15105#endif /* OBJ_ELF */
15106
15107/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15108 of an rs_align_code fragment. */
15109
15110void
a737bd4d 15111arm_handle_align (fragS * fragP)
b99bd4ef
NC
15112{
15113 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15114 static char const thumb_noop[2] = { 0xc0, 0x46 };
15115 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15116 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15117
15118 int bytes, fix, noop_size;
15119 char * p;
15120 const char * noop;
cc8a6dd0 15121
b99bd4ef
NC
15122 if (fragP->fr_type != rs_align_code)
15123 return;
15124
15125 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15126 p = fragP->fr_literal + fragP->fr_fix;
15127 fix = 0;
cc8a6dd0 15128
b99bd4ef
NC
15129 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15130 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 15131
b99bd4ef
NC
15132 if (fragP->tc_frag_data)
15133 {
15134 if (target_big_endian)
15135 noop = thumb_bigend_noop;
15136 else
15137 noop = thumb_noop;
15138 noop_size = sizeof (thumb_noop);
15139 }
15140 else
15141 {
15142 if (target_big_endian)
15143 noop = arm_bigend_noop;
15144 else
15145 noop = arm_noop;
15146 noop_size = sizeof (arm_noop);
15147 }
cc8a6dd0 15148
b99bd4ef
NC
15149 if (bytes & (noop_size - 1))
15150 {
15151 fix = bytes & (noop_size - 1);
15152 memset (p, 0, fix);
15153 p += fix;
15154 bytes -= fix;
15155 }
15156
15157 while (bytes >= noop_size)
15158 {
15159 memcpy (p, noop, noop_size);
15160 p += noop_size;
15161 bytes -= noop_size;
15162 fix += noop_size;
15163 }
cc8a6dd0 15164
b99bd4ef
NC
15165 fragP->fr_fix += fix;
15166 fragP->fr_var = noop_size;
15167}
15168
15169/* Called from md_do_align. Used to create an alignment
15170 frag in a code section. */
15171
15172void
a737bd4d 15173arm_frag_align_code (int n, int max)
b99bd4ef
NC
15174{
15175 char * p;
15176
2d2255b5 15177 /* We assume that there will never be a requirement
b99bd4ef
NC
15178 to support alignments greater than 32 bytes. */
15179 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15180 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 15181
b99bd4ef
NC
15182 p = frag_var (rs_align_code,
15183 MAX_MEM_FOR_RS_ALIGN_CODE,
15184 1,
15185 (relax_substateT) max,
15186 (symbolS *) NULL,
15187 (offsetT) n,
15188 (char *) NULL);
15189 *p = 0;
b99bd4ef
NC
15190}
15191
15192/* Perform target specific initialisation of a frag. */
15193
15194void
a737bd4d 15195arm_init_frag (fragS * fragP)
b99bd4ef
NC
15196{
15197 /* Record whether this frag is in an ARM or a THUMB area. */
15198 fragP->tc_frag_data = thumb_mode;
15199}
a737bd4d 15200
a394c00f
NC
15201#ifdef OBJ_ELF
15202
15203/* Convert REGNAME to a DWARF-2 register number. */
15204
15205int
15206tc_arm_regname_to_dw2regnum (const char *regname)
15207{
15208 unsigned int i;
15209
15210 for (i = 0; rn_table[i].name; i++)
15211 if (streq (regname, rn_table[i].name))
15212 return rn_table[i].number;
15213
15214 return -1;
15215}
15216
15217/* Initialize the DWARF-2 unwind information for this procedure. */
15218
15219void
15220tc_arm_frame_initial_instructions (void)
15221{
15222 cfi_add_CFA_def_cfa (REG_SP, 0);
15223}
15224#endif
15225
a737bd4d
NC
15226/* This table describes all the machine specific pseudo-ops the assembler
15227 has to support. The fields are:
15228 pseudo-op name without dot
15229 function to call to execute this pseudo-op
15230 Integer arg to pass to the function. */
15231
15232const pseudo_typeS md_pseudo_table[] =
15233{
15234 /* Never called because '.req' does not start a line. */
15235 { "req", s_req, 0 },
15236 { "unreq", s_unreq, 0 },
15237 { "bss", s_bss, 0 },
15238 { "align", s_align, 0 },
15239 { "arm", s_arm, 0 },
15240 { "thumb", s_thumb, 0 },
15241 { "code", s_code, 0 },
15242 { "force_thumb", s_force_thumb, 0 },
15243 { "thumb_func", s_thumb_func, 0 },
15244 { "thumb_set", s_thumb_set, 0 },
15245 { "even", s_even, 0 },
15246 { "ltorg", s_ltorg, 0 },
15247 { "pool", s_ltorg, 0 },
15248#ifdef OBJ_ELF
15249 { "word", s_arm_elf_cons, 4 },
15250 { "long", s_arm_elf_cons, 4 },
15251 { "rel31", s_arm_rel31, 0 },
7ed4c4c5
NC
15252 { "fnstart", s_arm_unwind_fnstart, 0 },
15253 { "fnend", s_arm_unwind_fnend, 0 },
15254 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15255 { "personality", s_arm_unwind_personality, 0 },
15256 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15257 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15258 { "save", s_arm_unwind_save, 0 },
15259 { "movsp", s_arm_unwind_movsp, 0 },
15260 { "pad", s_arm_unwind_pad, 0 },
15261 { "setfp", s_arm_unwind_setfp, 0 },
15262 { "unwind_raw", s_arm_unwind_raw, 0 },
a737bd4d
NC
15263#else
15264 { "word", cons, 4},
15265#endif
15266 { "extend", float_cons, 'x' },
15267 { "ldouble", float_cons, 'x' },
15268 { "packed", float_cons, 'p' },
15269 { 0, 0, 0 }
15270};