* elf32-arm.c (elf32_arm_check_relocs): Increment count for all
[deliverable/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
84798bd6
JB
86/* Bit N indicates that an R_ARM_NONE relocation has been output for
87 __aeabi_unwind_cpp_prN already if set. This enables dependencies to be
88 emitted only once per section, to save unnecessary bloat. */
89static unsigned int marked_pr_dependency = 0;
90
7ed4c4c5
NC
91#endif /* OBJ_ELF */
92
33a392fb
PB
93enum arm_float_abi
94{
95 ARM_FLOAT_ABI_HARD,
96 ARM_FLOAT_ABI_SOFTFP,
97 ARM_FLOAT_ABI_SOFT
98};
99
b89dddec
RE
100/* Types of processor to assemble for. */
101#define ARM_1 ARM_ARCH_V1
102#define ARM_2 ARM_ARCH_V2
103#define ARM_3 ARM_ARCH_V2S
104#define ARM_250 ARM_ARCH_V2S
105#define ARM_6 ARM_ARCH_V3
106#define ARM_7 ARM_ARCH_V3
107#define ARM_8 ARM_ARCH_V4
108#define ARM_9 ARM_ARCH_V4T
109#define ARM_STRONG ARM_ARCH_V4
110#define ARM_CPU_MASK 0x0000000f /* XXX? */
b99bd4ef
NC
111
112#ifndef CPU_DEFAULT
113#if defined __XSCALE__
b89dddec 114#define CPU_DEFAULT (ARM_ARCH_XSCALE)
b99bd4ef
NC
115#else
116#if defined __thumb__
b89dddec 117#define CPU_DEFAULT (ARM_ARCH_V5T)
b99bd4ef 118#else
03b1477f 119#define CPU_DEFAULT ARM_ANY
b99bd4ef
NC
120#endif
121#endif
122#endif
123
124#ifndef FPU_DEFAULT
c820d418
MM
125# ifdef TE_LINUX
126# define FPU_DEFAULT FPU_ARCH_FPA
127# elif defined (TE_NetBSD)
128# ifdef OBJ_ELF
129# define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
130# else
131 /* Legacy a.out format. */
132# define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
133# endif
4e7fd91e
PB
134# elif defined (TE_VXWORKS)
135# define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, VFP order. */
c820d418
MM
136# else
137 /* For backwards compatibility, default to FPA. */
138# define FPU_DEFAULT FPU_ARCH_FPA
139# endif
140#endif /* ifndef FPU_DEFAULT */
b99bd4ef
NC
141
142#define streq(a, b) (strcmp (a, b) == 0)
143#define skip_whitespace(str) while (*(str) == ' ') ++(str)
144
03b1477f 145static unsigned long cpu_variant;
b99bd4ef 146
b99bd4ef 147/* Flags stored in private area of BFD structure. */
b34976b6
AM
148static int uses_apcs_26 = FALSE;
149static int atpcs = FALSE;
150static int support_interwork = FALSE;
151static int uses_apcs_float = FALSE;
152static int pic_code = FALSE;
03b1477f
RE
153
154/* Variables that we set while parsing command-line options. Once all
155 options have been read we re-process these values to set the real
156 assembly flags. */
157static int legacy_cpu = -1;
158static int legacy_fpu = -1;
159
160static int mcpu_cpu_opt = -1;
161static int mcpu_fpu_opt = -1;
162static int march_cpu_opt = -1;
163static int march_fpu_opt = -1;
164static int mfpu_opt = -1;
33a392fb 165static int mfloat_abi_opt = -1;
7cc69913 166#ifdef OBJ_ELF
deeaaff8
DJ
167# ifdef EABI_DEFAULT
168static int meabi_flags = EABI_DEFAULT;
169# else
d507cf36 170static int meabi_flags = EF_ARM_EABI_UNKNOWN;
deeaaff8 171# endif
7cc69913 172#endif
b99bd4ef
NC
173
174/* This array holds the chars that always start a comment. If the
175 pre-processor is disabled, these aren't very useful. */
f57c81f6 176const char comment_chars[] = "@";
b99bd4ef
NC
177
178/* This array holds the chars that only start a comment at the beginning of
179 a line. If the line seems to have the form '# 123 filename'
180 .line and .file directives will appear in the pre-processed output. */
181/* Note that input_file.c hand checks for '#' at the beginning of the
182 first line of the input file. This is because the compiler outputs
183 #NO_APP at the beginning of its output. */
184/* Also note that comments like this one will always work. */
05d2d07e 185const char line_comment_chars[] = "#";
b99bd4ef 186
da89cce1 187const char line_separator_chars[] = ";";
b99bd4ef
NC
188
189/* Chars that can be used to separate mant
190 from exp in floating point numbers. */
05d2d07e 191const char EXP_CHARS[] = "eE";
b99bd4ef
NC
192
193/* Chars that mean this number is a floating point constant. */
194/* As in 0f12.456 */
195/* or 0d1.2345e12 */
196
05d2d07e 197const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
b99bd4ef
NC
198
199/* Prefix characters that indicate the start of an immediate
200 value. */
201#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
202
203#ifdef OBJ_ELF
204/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
205symbolS * GOT_symbol;
206#endif
207
208/* Size of relocation record. */
05d2d07e 209const int md_reloc_size = 8;
b99bd4ef
NC
210
211/* 0: assemble for ARM,
212 1: assemble for Thumb,
213 2: assemble for Thumb even though target CPU does not support thumb
214 instructions. */
215static int thumb_mode = 0;
216
217typedef struct arm_fix
218{
219 int thumb_mode;
220} arm_fix_data;
221
222struct arm_it
223{
05d2d07e 224 const char * error;
b99bd4ef 225 unsigned long instruction;
b99bd4ef
NC
226 int size;
227 struct
228 {
229 bfd_reloc_code_real_type type;
230 expressionS exp;
231 int pc_rel;
232 } reloc;
233};
234
235struct arm_it inst;
236
237enum asm_shift_index
238{
239 SHIFT_LSL = 0,
240 SHIFT_LSR,
241 SHIFT_ASR,
242 SHIFT_ROR,
243 SHIFT_RRX
244};
245
246struct asm_shift_properties
247{
248 enum asm_shift_index index;
249 unsigned long bit_field;
250 unsigned int allows_0 : 1;
251 unsigned int allows_32 : 1;
252};
253
254static const struct asm_shift_properties shift_properties [] =
255{
256 { SHIFT_LSL, 0, 1, 0},
257 { SHIFT_LSR, 0x20, 0, 1},
258 { SHIFT_ASR, 0x40, 0, 1},
259 { SHIFT_ROR, 0x60, 0, 0},
260 { SHIFT_RRX, 0x60, 0, 0}
261};
262
263struct asm_shift_name
264{
265 const char * name;
266 const struct asm_shift_properties * properties;
267};
268
269static const struct asm_shift_name shift_names [] =
270{
271 { "asl", shift_properties + SHIFT_LSL },
272 { "lsl", shift_properties + SHIFT_LSL },
273 { "lsr", shift_properties + SHIFT_LSR },
274 { "asr", shift_properties + SHIFT_ASR },
275 { "ror", shift_properties + SHIFT_ROR },
276 { "rrx", shift_properties + SHIFT_RRX },
277 { "ASL", shift_properties + SHIFT_LSL },
278 { "LSL", shift_properties + SHIFT_LSL },
279 { "LSR", shift_properties + SHIFT_LSR },
280 { "ASR", shift_properties + SHIFT_ASR },
281 { "ROR", shift_properties + SHIFT_ROR },
282 { "RRX", shift_properties + SHIFT_RRX }
283};
284
09d92015 285/* Any kind of shift is accepted. */
b99bd4ef 286#define NO_SHIFT_RESTRICT 1
09d92015
MM
287/* The shift operand must be an immediate value, not a register. */
288#define SHIFT_IMMEDIATE 0
289/* The shift must be LSL or ASR and the operand must be an immediate. */
290#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
291/* The shift must be ASR and the operand must be an immediate. */
292#define SHIFT_ASR_IMMEDIATE 3
293/* The shift must be LSL and the operand must be an immediate. */
294#define SHIFT_LSL_IMMEDIATE 4
b99bd4ef
NC
295
296#define NUM_FLOAT_VALS 8
297
05d2d07e 298const char * fp_const[] =
b99bd4ef
NC
299{
300 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301};
302
303/* Number of littlenums required to hold an extended precision number. */
304#define MAX_LITTLENUMS 6
305
306LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
307
308#define FAIL (-1)
309#define SUCCESS (0)
310
bfae80f2
RE
311/* Whether a Co-processor load/store operation accepts write-back forms. */
312#define CP_WB_OK 1
313#define CP_NO_WB 0
314
b99bd4ef
NC
315#define SUFF_S 1
316#define SUFF_D 2
317#define SUFF_E 3
318#define SUFF_P 4
319
320#define CP_T_X 0x00008000
321#define CP_T_Y 0x00400000
322#define CP_T_Pre 0x01000000
323#define CP_T_UD 0x00800000
324#define CP_T_WB 0x00200000
325
326#define CONDS_BIT 0x00100000
327#define LOAD_BIT 0x00100000
b99bd4ef
NC
328
329#define DOUBLE_LOAD_FLAG 0x00000001
330
331struct asm_cond
332{
05d2d07e 333 const char * template;
b99bd4ef
NC
334 unsigned long value;
335};
336
b99bd4ef 337#define COND_ALWAYS 0xe0000000
90e4755a 338#define COND_MASK 0xf0000000
b99bd4ef 339
05d2d07e 340static const struct asm_cond conds[] =
b99bd4ef
NC
341{
342 {"eq", 0x00000000},
343 {"ne", 0x10000000},
344 {"cs", 0x20000000}, {"hs", 0x20000000},
345 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
346 {"mi", 0x40000000},
347 {"pl", 0x50000000},
348 {"vs", 0x60000000},
349 {"vc", 0x70000000},
350 {"hi", 0x80000000},
351 {"ls", 0x90000000},
352 {"ge", 0xa0000000},
353 {"lt", 0xb0000000},
354 {"gt", 0xc0000000},
355 {"le", 0xd0000000},
356 {"al", 0xe0000000},
357 {"nv", 0xf0000000}
358};
359
b99bd4ef
NC
360struct asm_psr
361{
b34976b6
AM
362 const char *template;
363 bfd_boolean cpsr;
b99bd4ef
NC
364 unsigned long field;
365};
366
2d2255b5 367/* The bit that distinguishes CPSR and SPSR. */
b99bd4ef
NC
368#define SPSR_BIT (1 << 22)
369
370/* How many bits to shift the PSR_xxx bits up by. */
371#define PSR_SHIFT 16
372
373#define PSR_c (1 << 0)
374#define PSR_x (1 << 1)
375#define PSR_s (1 << 2)
376#define PSR_f (1 << 3)
377
05d2d07e 378static const struct asm_psr psrs[] =
b99bd4ef 379{
b34976b6
AM
380 {"CPSR", TRUE, PSR_c | PSR_f},
381 {"CPSR_all", TRUE, PSR_c | PSR_f},
382 {"SPSR", FALSE, PSR_c | PSR_f},
383 {"SPSR_all", FALSE, PSR_c | PSR_f},
384 {"CPSR_flg", TRUE, PSR_f},
385 {"CPSR_f", TRUE, PSR_f},
386 {"SPSR_flg", FALSE, PSR_f},
387 {"SPSR_f", FALSE, PSR_f},
388 {"CPSR_c", TRUE, PSR_c},
389 {"CPSR_ctl", TRUE, PSR_c},
390 {"SPSR_c", FALSE, PSR_c},
391 {"SPSR_ctl", FALSE, PSR_c},
392 {"CPSR_x", TRUE, PSR_x},
393 {"CPSR_s", TRUE, PSR_s},
394 {"SPSR_x", FALSE, PSR_x},
395 {"SPSR_s", FALSE, PSR_s},
b99bd4ef 396 /* Combinations of flags. */
b34976b6
AM
397 {"CPSR_fs", TRUE, PSR_f | PSR_s},
398 {"CPSR_fx", TRUE, PSR_f | PSR_x},
399 {"CPSR_fc", TRUE, PSR_f | PSR_c},
400 {"CPSR_sf", TRUE, PSR_s | PSR_f},
401 {"CPSR_sx", TRUE, PSR_s | PSR_x},
402 {"CPSR_sc", TRUE, PSR_s | PSR_c},
403 {"CPSR_xf", TRUE, PSR_x | PSR_f},
404 {"CPSR_xs", TRUE, PSR_x | PSR_s},
405 {"CPSR_xc", TRUE, PSR_x | PSR_c},
406 {"CPSR_cf", TRUE, PSR_c | PSR_f},
407 {"CPSR_cs", TRUE, PSR_c | PSR_s},
408 {"CPSR_cx", TRUE, PSR_c | PSR_x},
409 {"CPSR_fsx", TRUE, PSR_f | PSR_s | PSR_x},
410 {"CPSR_fsc", TRUE, PSR_f | PSR_s | PSR_c},
411 {"CPSR_fxs", TRUE, PSR_f | PSR_x | PSR_s},
412 {"CPSR_fxc", TRUE, PSR_f | PSR_x | PSR_c},
413 {"CPSR_fcs", TRUE, PSR_f | PSR_c | PSR_s},
414 {"CPSR_fcx", TRUE, PSR_f | PSR_c | PSR_x},
415 {"CPSR_sfx", TRUE, PSR_s | PSR_f | PSR_x},
416 {"CPSR_sfc", TRUE, PSR_s | PSR_f | PSR_c},
417 {"CPSR_sxf", TRUE, PSR_s | PSR_x | PSR_f},
418 {"CPSR_sxc", TRUE, PSR_s | PSR_x | PSR_c},
419 {"CPSR_scf", TRUE, PSR_s | PSR_c | PSR_f},
420 {"CPSR_scx", TRUE, PSR_s | PSR_c | PSR_x},
421 {"CPSR_xfs", TRUE, PSR_x | PSR_f | PSR_s},
422 {"CPSR_xfc", TRUE, PSR_x | PSR_f | PSR_c},
423 {"CPSR_xsf", TRUE, PSR_x | PSR_s | PSR_f},
424 {"CPSR_xsc", TRUE, PSR_x | PSR_s | PSR_c},
425 {"CPSR_xcf", TRUE, PSR_x | PSR_c | PSR_f},
426 {"CPSR_xcs", TRUE, PSR_x | PSR_c | PSR_s},
427 {"CPSR_cfs", TRUE, PSR_c | PSR_f | PSR_s},
428 {"CPSR_cfx", TRUE, PSR_c | PSR_f | PSR_x},
429 {"CPSR_csf", TRUE, PSR_c | PSR_s | PSR_f},
430 {"CPSR_csx", TRUE, PSR_c | PSR_s | PSR_x},
431 {"CPSR_cxf", TRUE, PSR_c | PSR_x | PSR_f},
432 {"CPSR_cxs", TRUE, PSR_c | PSR_x | PSR_s},
433 {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
434 {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
435 {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
436 {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
437 {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
438 {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
439 {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
440 {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
441 {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
442 {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
443 {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
444 {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
445 {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
446 {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
447 {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
448 {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
449 {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
450 {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
451 {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
452 {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
453 {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
454 {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
455 {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
456 {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
457 {"SPSR_fs", FALSE, PSR_f | PSR_s},
458 {"SPSR_fx", FALSE, PSR_f | PSR_x},
459 {"SPSR_fc", FALSE, PSR_f | PSR_c},
460 {"SPSR_sf", FALSE, PSR_s | PSR_f},
461 {"SPSR_sx", FALSE, PSR_s | PSR_x},
462 {"SPSR_sc", FALSE, PSR_s | PSR_c},
463 {"SPSR_xf", FALSE, PSR_x | PSR_f},
464 {"SPSR_xs", FALSE, PSR_x | PSR_s},
465 {"SPSR_xc", FALSE, PSR_x | PSR_c},
466 {"SPSR_cf", FALSE, PSR_c | PSR_f},
467 {"SPSR_cs", FALSE, PSR_c | PSR_s},
468 {"SPSR_cx", FALSE, PSR_c | PSR_x},
469 {"SPSR_fsx", FALSE, PSR_f | PSR_s | PSR_x},
470 {"SPSR_fsc", FALSE, PSR_f | PSR_s | PSR_c},
471 {"SPSR_fxs", FALSE, PSR_f | PSR_x | PSR_s},
472 {"SPSR_fxc", FALSE, PSR_f | PSR_x | PSR_c},
473 {"SPSR_fcs", FALSE, PSR_f | PSR_c | PSR_s},
474 {"SPSR_fcx", FALSE, PSR_f | PSR_c | PSR_x},
475 {"SPSR_sfx", FALSE, PSR_s | PSR_f | PSR_x},
476 {"SPSR_sfc", FALSE, PSR_s | PSR_f | PSR_c},
477 {"SPSR_sxf", FALSE, PSR_s | PSR_x | PSR_f},
478 {"SPSR_sxc", FALSE, PSR_s | PSR_x | PSR_c},
479 {"SPSR_scf", FALSE, PSR_s | PSR_c | PSR_f},
480 {"SPSR_scx", FALSE, PSR_s | PSR_c | PSR_x},
481 {"SPSR_xfs", FALSE, PSR_x | PSR_f | PSR_s},
482 {"SPSR_xfc", FALSE, PSR_x | PSR_f | PSR_c},
483 {"SPSR_xsf", FALSE, PSR_x | PSR_s | PSR_f},
484 {"SPSR_xsc", FALSE, PSR_x | PSR_s | PSR_c},
485 {"SPSR_xcf", FALSE, PSR_x | PSR_c | PSR_f},
486 {"SPSR_xcs", FALSE, PSR_x | PSR_c | PSR_s},
487 {"SPSR_cfs", FALSE, PSR_c | PSR_f | PSR_s},
488 {"SPSR_cfx", FALSE, PSR_c | PSR_f | PSR_x},
489 {"SPSR_csf", FALSE, PSR_c | PSR_s | PSR_f},
490 {"SPSR_csx", FALSE, PSR_c | PSR_s | PSR_x},
491 {"SPSR_cxf", FALSE, PSR_c | PSR_x | PSR_f},
492 {"SPSR_cxs", FALSE, PSR_c | PSR_x | PSR_s},
493 {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
494 {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
495 {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
496 {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
497 {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
498 {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
499 {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
500 {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
501 {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
502 {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
503 {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
504 {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
505 {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
506 {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
507 {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
508 {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
509 {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
510 {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
511 {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
512 {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
513 {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
514 {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
515 {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
516 {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
b99bd4ef
NC
517};
518
e16bb312
NC
519enum wreg_type
520 {
521 IWMMXT_REG_WR = 0,
522 IWMMXT_REG_WC = 1,
523 IWMMXT_REG_WR_OR_WC = 2,
524 IWMMXT_REG_WCG
525 };
526
527enum iwmmxt_insn_type
528{
529 check_rd,
530 check_wr,
531 check_wrwr,
532 check_wrwrwr,
533 check_wrwrwcg,
534 check_tbcst,
535 check_tmovmsk,
536 check_tmia,
537 check_tmcrr,
538 check_tmrrc,
539 check_tmcr,
540 check_tmrc,
541 check_tinsr,
542 check_textrc,
543 check_waligni,
544 check_textrm,
545 check_wshufh
546};
547
bfae80f2
RE
548enum vfp_dp_reg_pos
549{
550 VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
551};
552
553enum vfp_sp_reg_pos
554{
555 VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
556};
557
558enum vfp_ldstm_type
559{
560 VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
561};
562
563/* VFP system registers. */
564struct vfp_reg
565{
566 const char *name;
567 unsigned long regno;
568};
569
cc8a6dd0 570static const struct vfp_reg vfp_regs[] =
bfae80f2
RE
571{
572 {"fpsid", 0x00000000},
573 {"FPSID", 0x00000000},
574 {"fpscr", 0x00010000},
575 {"FPSCR", 0x00010000},
576 {"fpexc", 0x00080000},
577 {"FPEXC", 0x00080000}
578};
579
6c43fab6
RE
580/* Structure for a hash table entry for a register. */
581struct reg_entry
582{
583 const char * name;
584 int number;
0bbf2aa4 585 bfd_boolean builtin;
6c43fab6
RE
586};
587
e28cd48c 588/* Some well known registers that we refer to directly elsewhere. */
6c43fab6
RE
589#define REG_SP 13
590#define REG_LR 14
591#define REG_PC 15
592
e16bb312
NC
593#define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
594#define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
595#define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
596
0bbf2aa4
NC
597/* These are the standard names. Users can add aliases with .req.
598 and delete them with .unreq. */
599
6c43fab6
RE
600/* Integer Register Numbers. */
601static const struct reg_entry rn_table[] =
602{
0bbf2aa4
NC
603 {"r0", 0, TRUE}, {"r1", 1, TRUE}, {"r2", 2, TRUE}, {"r3", 3, TRUE},
604 {"r4", 4, TRUE}, {"r5", 5, TRUE}, {"r6", 6, TRUE}, {"r7", 7, TRUE},
605 {"r8", 8, TRUE}, {"r9", 9, TRUE}, {"r10", 10, TRUE}, {"r11", 11, TRUE},
606 {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
6c43fab6 607 /* ATPCS Synonyms. */
0bbf2aa4
NC
608 {"a1", 0, TRUE}, {"a2", 1, TRUE}, {"a3", 2, TRUE}, {"a4", 3, TRUE},
609 {"v1", 4, TRUE}, {"v2", 5, TRUE}, {"v3", 6, TRUE}, {"v4", 7, TRUE},
610 {"v5", 8, TRUE}, {"v6", 9, TRUE}, {"v7", 10, TRUE}, {"v8", 11, TRUE},
6c43fab6 611 /* Well-known aliases. */
0bbf2aa4
NC
612 {"wr", 7, TRUE}, {"sb", 9, TRUE}, {"sl", 10, TRUE}, {"fp", 11, TRUE},
613 {"ip", 12, TRUE}, {"sp", REG_SP, TRUE}, {"lr", REG_LR, TRUE}, {"pc", REG_PC, TRUE},
614 {NULL, 0, TRUE}
6c43fab6
RE
615};
616
e16bb312
NC
617#define WR_PREFIX 0x200
618#define WC_PREFIX 0x400
619
620static const struct reg_entry iwmmxt_table[] =
621{
5a6c6817 622 /* Intel Wireless MMX technology register names. */
0bbf2aa4
NC
623 { "wr0", 0x0 | WR_PREFIX, TRUE}, {"wr1", 0x1 | WR_PREFIX, TRUE},
624 { "wr2", 0x2 | WR_PREFIX, TRUE}, {"wr3", 0x3 | WR_PREFIX, TRUE},
625 { "wr4", 0x4 | WR_PREFIX, TRUE}, {"wr5", 0x5 | WR_PREFIX, TRUE},
626 { "wr6", 0x6 | WR_PREFIX, TRUE}, {"wr7", 0x7 | WR_PREFIX, TRUE},
627 { "wr8", 0x8 | WR_PREFIX, TRUE}, {"wr9", 0x9 | WR_PREFIX, TRUE},
628 { "wr10", 0xa | WR_PREFIX, TRUE}, {"wr11", 0xb | WR_PREFIX, TRUE},
629 { "wr12", 0xc | WR_PREFIX, TRUE}, {"wr13", 0xd | WR_PREFIX, TRUE},
630 { "wr14", 0xe | WR_PREFIX, TRUE}, {"wr15", 0xf | WR_PREFIX, TRUE},
631 { "wcid", 0x0 | WC_PREFIX, TRUE}, {"wcon", 0x1 | WC_PREFIX, TRUE},
632 {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
633 {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
634 {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
635
636 { "wR0", 0x0 | WR_PREFIX, TRUE}, {"wR1", 0x1 | WR_PREFIX, TRUE},
637 { "wR2", 0x2 | WR_PREFIX, TRUE}, {"wR3", 0x3 | WR_PREFIX, TRUE},
638 { "wR4", 0x4 | WR_PREFIX, TRUE}, {"wR5", 0x5 | WR_PREFIX, TRUE},
639 { "wR6", 0x6 | WR_PREFIX, TRUE}, {"wR7", 0x7 | WR_PREFIX, TRUE},
640 { "wR8", 0x8 | WR_PREFIX, TRUE}, {"wR9", 0x9 | WR_PREFIX, TRUE},
641 { "wR10", 0xa | WR_PREFIX, TRUE}, {"wR11", 0xb | WR_PREFIX, TRUE},
642 { "wR12", 0xc | WR_PREFIX, TRUE}, {"wR13", 0xd | WR_PREFIX, TRUE},
643 { "wR14", 0xe | WR_PREFIX, TRUE}, {"wR15", 0xf | WR_PREFIX, TRUE},
644 { "wCID", 0x0 | WC_PREFIX, TRUE}, {"wCon", 0x1 | WC_PREFIX, TRUE},
645 {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
646 {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
647 {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
648 {NULL, 0, TRUE}
e16bb312
NC
649};
650
6c43fab6
RE
651/* Co-processor Numbers. */
652static const struct reg_entry cp_table[] =
653{
0bbf2aa4
NC
654 {"p0", 0, TRUE}, {"p1", 1, TRUE}, {"p2", 2, TRUE}, {"p3", 3, TRUE},
655 {"p4", 4, TRUE}, {"p5", 5, TRUE}, {"p6", 6, TRUE}, {"p7", 7, TRUE},
656 {"p8", 8, TRUE}, {"p9", 9, TRUE}, {"p10", 10, TRUE}, {"p11", 11, TRUE},
657 {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
658 {NULL, 0, TRUE}
6c43fab6
RE
659};
660
661/* Co-processor Register Numbers. */
662static const struct reg_entry cn_table[] =
663{
0bbf2aa4
NC
664 {"c0", 0, TRUE}, {"c1", 1, TRUE}, {"c2", 2, TRUE}, {"c3", 3, TRUE},
665 {"c4", 4, TRUE}, {"c5", 5, TRUE}, {"c6", 6, TRUE}, {"c7", 7, TRUE},
666 {"c8", 8, TRUE}, {"c9", 9, TRUE}, {"c10", 10, TRUE}, {"c11", 11, TRUE},
667 {"c12", 12, TRUE}, {"c13", 13, TRUE}, {"c14", 14, TRUE}, {"c15", 15, TRUE},
6c43fab6 668 /* Not really valid, but kept for back-wards compatibility. */
0bbf2aa4
NC
669 {"cr0", 0, TRUE}, {"cr1", 1, TRUE}, {"cr2", 2, TRUE}, {"cr3", 3, TRUE},
670 {"cr4", 4, TRUE}, {"cr5", 5, TRUE}, {"cr6", 6, TRUE}, {"cr7", 7, TRUE},
671 {"cr8", 8, TRUE}, {"cr9", 9, TRUE}, {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
672 {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
673 {NULL, 0, TRUE}
6c43fab6
RE
674};
675
676/* FPA Registers. */
677static const struct reg_entry fn_table[] =
678{
0bbf2aa4
NC
679 {"f0", 0, TRUE}, {"f1", 1, TRUE}, {"f2", 2, TRUE}, {"f3", 3, TRUE},
680 {"f4", 4, TRUE}, {"f5", 5, TRUE}, {"f6", 6, TRUE}, {"f7", 7, TRUE},
681 {NULL, 0, TRUE}
6c43fab6
RE
682};
683
bfae80f2
RE
684/* VFP SP Registers. */
685static const struct reg_entry sn_table[] =
686{
0bbf2aa4
NC
687 {"s0", 0, TRUE}, {"s1", 1, TRUE}, {"s2", 2, TRUE}, {"s3", 3, TRUE},
688 {"s4", 4, TRUE}, {"s5", 5, TRUE}, {"s6", 6, TRUE}, {"s7", 7, TRUE},
689 {"s8", 8, TRUE}, {"s9", 9, TRUE}, {"s10", 10, TRUE}, {"s11", 11, TRUE},
690 {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
691 {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
692 {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
693 {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
694 {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
695 {NULL, 0, TRUE}
bfae80f2
RE
696};
697
698/* VFP DP Registers. */
699static const struct reg_entry dn_table[] =
700{
0bbf2aa4
NC
701 {"d0", 0, TRUE}, {"d1", 1, TRUE}, {"d2", 2, TRUE}, {"d3", 3, TRUE},
702 {"d4", 4, TRUE}, {"d5", 5, TRUE}, {"d6", 6, TRUE}, {"d7", 7, TRUE},
703 {"d8", 8, TRUE}, {"d9", 9, TRUE}, {"d10", 10, TRUE}, {"d11", 11, TRUE},
704 {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
705 {NULL, 0, TRUE}
bfae80f2
RE
706};
707
63e63b07 708/* Maverick DSP coprocessor registers. */
6c43fab6
RE
709static const struct reg_entry mav_mvf_table[] =
710{
0bbf2aa4
NC
711 {"mvf0", 0, TRUE}, {"mvf1", 1, TRUE}, {"mvf2", 2, TRUE}, {"mvf3", 3, TRUE},
712 {"mvf4", 4, TRUE}, {"mvf5", 5, TRUE}, {"mvf6", 6, TRUE}, {"mvf7", 7, TRUE},
713 {"mvf8", 8, TRUE}, {"mvf9", 9, TRUE}, {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
714 {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
715 {NULL, 0, TRUE}
6c43fab6
RE
716};
717
718static const struct reg_entry mav_mvd_table[] =
719{
0bbf2aa4
NC
720 {"mvd0", 0, TRUE}, {"mvd1", 1, TRUE}, {"mvd2", 2, TRUE}, {"mvd3", 3, TRUE},
721 {"mvd4", 4, TRUE}, {"mvd5", 5, TRUE}, {"mvd6", 6, TRUE}, {"mvd7", 7, TRUE},
722 {"mvd8", 8, TRUE}, {"mvd9", 9, TRUE}, {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
723 {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
724 {NULL, 0, TRUE}
6c43fab6
RE
725};
726
727static const struct reg_entry mav_mvfx_table[] =
728{
0bbf2aa4
NC
729 {"mvfx0", 0, TRUE}, {"mvfx1", 1, TRUE}, {"mvfx2", 2, TRUE}, {"mvfx3", 3, TRUE},
730 {"mvfx4", 4, TRUE}, {"mvfx5", 5, TRUE}, {"mvfx6", 6, TRUE}, {"mvfx7", 7, TRUE},
731 {"mvfx8", 8, TRUE}, {"mvfx9", 9, TRUE}, {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
732 {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
733 {NULL, 0, TRUE}
6c43fab6
RE
734};
735
736static const struct reg_entry mav_mvdx_table[] =
737{
0bbf2aa4
NC
738 {"mvdx0", 0, TRUE}, {"mvdx1", 1, TRUE}, {"mvdx2", 2, TRUE}, {"mvdx3", 3, TRUE},
739 {"mvdx4", 4, TRUE}, {"mvdx5", 5, TRUE}, {"mvdx6", 6, TRUE}, {"mvdx7", 7, TRUE},
740 {"mvdx8", 8, TRUE}, {"mvdx9", 9, TRUE}, {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
741 {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
742 {NULL, 0, TRUE}
6c43fab6
RE
743};
744
745static const struct reg_entry mav_mvax_table[] =
746{
0bbf2aa4
NC
747 {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
748 {NULL, 0, TRUE}
6c43fab6
RE
749};
750
751static const struct reg_entry mav_dspsc_table[] =
752{
0bbf2aa4
NC
753 {"dspsc", 0, TRUE},
754 {NULL, 0, TRUE}
6c43fab6
RE
755};
756
757struct reg_map
758{
a737bd4d
NC
759 const struct reg_entry * names;
760 int max_regno;
761 struct hash_control * htab;
762 const char * expected;
6c43fab6
RE
763};
764
765struct reg_map all_reg_maps[] =
766{
767 {rn_table, 15, NULL, N_("ARM register expected")},
f03698e6
RE
768 {cp_table, 15, NULL, N_("bad or missing co-processor number")},
769 {cn_table, 15, NULL, N_("co-processor register expected")},
6c43fab6 770 {fn_table, 7, NULL, N_("FPA register expected")},
bfae80f2
RE
771 {sn_table, 31, NULL, N_("VFP single precision register expected")},
772 {dn_table, 15, NULL, N_("VFP double precision register expected")},
6c43fab6
RE
773 {mav_mvf_table, 15, NULL, N_("Maverick MVF register expected")},
774 {mav_mvd_table, 15, NULL, N_("Maverick MVD register expected")},
775 {mav_mvfx_table, 15, NULL, N_("Maverick MVFX register expected")},
5a21e886 776 {mav_mvdx_table, 15, NULL, N_("Maverick MVDX register expected")},
6c43fab6
RE
777 {mav_mvax_table, 3, NULL, N_("Maverick MVAX register expected")},
778 {mav_dspsc_table, 0, NULL, N_("Maverick DSPSC register expected")},
5a6c6817 779 {iwmmxt_table, 23, NULL, N_("Intel Wireless MMX technology register expected")},
6c43fab6
RE
780};
781
782/* Enumeration matching entries in table above. */
783enum arm_reg_type
784{
785 REG_TYPE_RN = 0,
786#define REG_TYPE_FIRST REG_TYPE_RN
787 REG_TYPE_CP = 1,
788 REG_TYPE_CN = 2,
789 REG_TYPE_FN = 3,
bfae80f2
RE
790 REG_TYPE_SN = 4,
791 REG_TYPE_DN = 5,
792 REG_TYPE_MVF = 6,
793 REG_TYPE_MVD = 7,
794 REG_TYPE_MVFX = 8,
795 REG_TYPE_MVDX = 9,
796 REG_TYPE_MVAX = 10,
797 REG_TYPE_DSPSC = 11,
e16bb312 798 REG_TYPE_IWMMXT = 12,
bfae80f2 799
e16bb312 800 REG_TYPE_MAX = 13
6c43fab6 801};
404ff6b5 802
b99bd4ef
NC
803/* ARM instructions take 4bytes in the object file, Thumb instructions
804 take 2: */
805#define INSN_SIZE 4
806
404ff6b5 807/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
63e63b07 808#define MAV_MODE1 0x100c
404ff6b5
AH
809
810/* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
63e63b07 811#define MAV_MODE2 0x0c10
404ff6b5 812
34920d91
NC
813/* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
814#define MAV_MODE3 0x100c
404ff6b5
AH
815
816/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
63e63b07 817#define MAV_MODE4 0x0c0010
404ff6b5
AH
818
819/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
63e63b07 820#define MAV_MODE5 0x00100c
404ff6b5
AH
821
822/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
63e63b07 823#define MAV_MODE6 0x00100c05
b99bd4ef
NC
824
825struct asm_opcode
826{
827 /* Basic string to match. */
05d2d07e 828 const char * template;
b99bd4ef
NC
829
830 /* Basic instruction code. */
831 unsigned long value;
832
90e4755a
RE
833 /* Offset into the template where the condition code (if any) will be.
834 If zero, then the instruction is never conditional. */
835 unsigned cond_offset;
b99bd4ef 836
90e4755a
RE
837 /* Which architecture variant provides this instruction. */
838 unsigned long variant;
b99bd4ef
NC
839
840 /* Function to call to parse args. */
a737bd4d 841 void (* parms) (char *);
b99bd4ef
NC
842};
843
a737bd4d
NC
844/* Defines for various bits that we will want to toggle. */
845#define INST_IMMEDIATE 0x02000000
846#define OFFSET_REG 0x02000000
847#define HWOFFSET_IMM 0x00400000
848#define SHIFT_BY_REG 0x00000010
849#define PRE_INDEX 0x01000000
850#define INDEX_UP 0x00800000
851#define WRITE_BACK 0x00200000
852#define LDM_TYPE_2_OR_3 0x00400000
90e4755a 853
a737bd4d
NC
854#define LITERAL_MASK 0xf000f000
855#define OPCODE_MASK 0xfe1fffff
856#define V4_STR_BIT 0x00000020
90e4755a 857
a737bd4d 858#define DATA_OP_SHIFT 21
90e4755a 859
a737bd4d
NC
860/* Codes to distinguish the arithmetic instructions. */
861#define OPCODE_AND 0
862#define OPCODE_EOR 1
863#define OPCODE_SUB 2
864#define OPCODE_RSB 3
865#define OPCODE_ADD 4
866#define OPCODE_ADC 5
867#define OPCODE_SBC 6
868#define OPCODE_RSC 7
869#define OPCODE_TST 8
870#define OPCODE_TEQ 9
871#define OPCODE_CMP 10
872#define OPCODE_CMN 11
873#define OPCODE_ORR 12
874#define OPCODE_MOV 13
875#define OPCODE_BIC 14
876#define OPCODE_MVN 15
90e4755a 877
a737bd4d
NC
878#define T_OPCODE_MUL 0x4340
879#define T_OPCODE_TST 0x4200
880#define T_OPCODE_CMN 0x42c0
881#define T_OPCODE_NEG 0x4240
882#define T_OPCODE_MVN 0x43c0
90e4755a 883
a737bd4d
NC
884#define T_OPCODE_ADD_R3 0x1800
885#define T_OPCODE_SUB_R3 0x1a00
886#define T_OPCODE_ADD_HI 0x4400
887#define T_OPCODE_ADD_ST 0xb000
888#define T_OPCODE_SUB_ST 0xb080
889#define T_OPCODE_ADD_SP 0xa800
890#define T_OPCODE_ADD_PC 0xa000
891#define T_OPCODE_ADD_I8 0x3000
892#define T_OPCODE_SUB_I8 0x3800
893#define T_OPCODE_ADD_I3 0x1c00
894#define T_OPCODE_SUB_I3 0x1e00
b99bd4ef 895
a737bd4d
NC
896#define T_OPCODE_ASR_R 0x4100
897#define T_OPCODE_LSL_R 0x4080
898#define T_OPCODE_LSR_R 0x40c0
899#define T_OPCODE_ASR_I 0x1000
900#define T_OPCODE_LSL_I 0x0000
901#define T_OPCODE_LSR_I 0x0800
b99bd4ef 902
a737bd4d
NC
903#define T_OPCODE_MOV_I8 0x2000
904#define T_OPCODE_CMP_I8 0x2800
905#define T_OPCODE_CMP_LR 0x4280
906#define T_OPCODE_MOV_HR 0x4600
907#define T_OPCODE_CMP_HR 0x4500
b99bd4ef 908
a737bd4d
NC
909#define T_OPCODE_LDR_PC 0x4800
910#define T_OPCODE_LDR_SP 0x9800
911#define T_OPCODE_STR_SP 0x9000
912#define T_OPCODE_LDR_IW 0x6800
913#define T_OPCODE_STR_IW 0x6000
914#define T_OPCODE_LDR_IH 0x8800
915#define T_OPCODE_STR_IH 0x8000
916#define T_OPCODE_LDR_IB 0x7800
917#define T_OPCODE_STR_IB 0x7000
918#define T_OPCODE_LDR_RW 0x5800
919#define T_OPCODE_STR_RW 0x5000
920#define T_OPCODE_LDR_RH 0x5a00
921#define T_OPCODE_STR_RH 0x5200
922#define T_OPCODE_LDR_RB 0x5c00
923#define T_OPCODE_STR_RB 0x5400
c9b604bd 924
a737bd4d
NC
925#define T_OPCODE_PUSH 0xb400
926#define T_OPCODE_POP 0xbc00
b99bd4ef 927
a737bd4d 928#define T_OPCODE_BRANCH 0xe7fe
b99bd4ef 929
a737bd4d
NC
930#define THUMB_SIZE 2 /* Size of thumb instruction. */
931#define THUMB_REG_LO 0x1
932#define THUMB_REG_HI 0x2
933#define THUMB_REG_ANY 0x3
90e4755a 934
a737bd4d
NC
935#define THUMB_H1 0x0080
936#define THUMB_H2 0x0040
b99bd4ef 937
a737bd4d
NC
938#define THUMB_ASR 0
939#define THUMB_LSL 1
940#define THUMB_LSR 2
90e4755a 941
a737bd4d
NC
942#define THUMB_MOVE 0
943#define THUMB_COMPARE 1
944#define THUMB_CPY 2
90e4755a 945
a737bd4d
NC
946#define THUMB_LOAD 0
947#define THUMB_STORE 1
90e4755a 948
a737bd4d 949#define THUMB_PP_PC_LR 0x0100
90e4755a 950
a737bd4d
NC
951/* These three are used for immediate shifts, do not alter. */
952#define THUMB_WORD 2
953#define THUMB_HALFWORD 1
954#define THUMB_BYTE 0
90e4755a 955
a737bd4d
NC
956struct thumb_opcode
957{
958 /* Basic string to match. */
959 const char * template;
90e4755a 960
a737bd4d
NC
961 /* Basic instruction code. */
962 unsigned long value;
90e4755a 963
a737bd4d 964 int size;
b99bd4ef
NC
965
966 /* Which CPU variants this exists for. */
90e4755a 967 unsigned long variant;
b99bd4ef
NC
968
969 /* Function to call to parse args. */
a737bd4d 970 void (* parms) (char *);
b99bd4ef
NC
971};
972
f03698e6 973#define BAD_ARGS _("bad arguments to instruction")
b99bd4ef 974#define BAD_PC _("r15 not allowed here")
f03698e6 975#define BAD_COND _("instruction is not conditional")
b99bd4ef
NC
976#define ERR_NO_ACCUM _("acc0 expected")
977
978static struct hash_control * arm_ops_hsh = NULL;
979static struct hash_control * arm_tops_hsh = NULL;
980static struct hash_control * arm_cond_hsh = NULL;
981static struct hash_control * arm_shift_hsh = NULL;
b99bd4ef
NC
982static struct hash_control * arm_psr_hsh = NULL;
983
b99bd4ef
NC
984/* Stuff needed to resolve the label ambiguity
985 As:
986 ...
987 label: <insn>
988 may differ from:
989 ...
990 label:
991 <insn>
992*/
993
994symbolS * last_label_seen;
b34976b6 995static int label_is_thumb_function_name = FALSE;
a737bd4d 996\f
3d0c9500 997/* Literal Pool stuff. */
b99bd4ef
NC
998
999#define MAX_LITERAL_POOL_SIZE 1024
1000
3d0c9500
NC
1001/* Literal pool structure. Held on a per-section
1002 and per-sub-section basis. */
a737bd4d 1003
3d0c9500 1004typedef struct literal_pool
b99bd4ef 1005{
3d0c9500
NC
1006 expressionS literals [MAX_LITERAL_POOL_SIZE];
1007 unsigned int next_free_entry;
1008 unsigned int id;
1009 symbolS * symbol;
1010 segT section;
1011 subsegT sub_section;
61b5f74b 1012 struct literal_pool * next;
3d0c9500 1013} literal_pool;
b99bd4ef 1014
3d0c9500
NC
1015/* Pointer to a linked list of literal pools. */
1016literal_pool * list_of_pools = NULL;
b99bd4ef 1017
3d0c9500 1018static literal_pool *
a737bd4d 1019find_literal_pool (void)
3d0c9500
NC
1020{
1021 literal_pool * pool;
1022
1023 for (pool = list_of_pools; pool != NULL; pool = pool->next)
1024 {
1025 if (pool->section == now_seg
1026 && pool->sub_section == now_subseg)
1027 break;
1028 }
1029
1030 return pool;
1031}
b99bd4ef 1032
3d0c9500 1033static literal_pool *
a737bd4d 1034find_or_make_literal_pool (void)
3d0c9500
NC
1035{
1036 /* Next literal pool ID number. */
1037 static unsigned int latest_pool_num = 1;
1038 literal_pool * pool;
1039
1040 pool = find_literal_pool ();
b99bd4ef 1041
3d0c9500
NC
1042 if (pool == NULL)
1043 {
1044 /* Create a new pool. */
a737bd4d 1045 pool = xmalloc (sizeof (* pool));
3d0c9500
NC
1046 if (! pool)
1047 return NULL;
1048
1049 pool->next_free_entry = 0;
1050 pool->section = now_seg;
1051 pool->sub_section = now_subseg;
1052 pool->next = list_of_pools;
1053 pool->symbol = NULL;
1054
1055 /* Add it to the list. */
1056 list_of_pools = pool;
1057 }
1058
1059 /* New pools, and emptied pools, will have a NULL symbol. */
1060 if (pool->symbol == NULL)
1061 {
1062 pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
1063 (valueT) 0, &zero_address_frag);
1064 pool->id = latest_pool_num ++;
1065 }
1066
1067 /* Done. */
1068 return pool;
1069}
1070
1071/* Add the literal in the global 'inst'
1072 structure to the relevent literal pool. */
a737bd4d 1073
b99bd4ef 1074static int
a737bd4d 1075add_to_lit_pool (void)
b99bd4ef 1076{
61b5f74b 1077 literal_pool * pool;
3d0c9500 1078 unsigned int entry;
b99bd4ef 1079
3d0c9500 1080 pool = find_or_make_literal_pool ();
b99bd4ef 1081
3d0c9500
NC
1082 /* Check if this literal value is already in the pool. */
1083 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1084 {
3d0c9500
NC
1085 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1086 && (inst.reloc.exp.X_op == O_constant)
1087 && (pool->literals[entry].X_add_number
b99bd4ef 1088 == inst.reloc.exp.X_add_number)
3d0c9500
NC
1089 && (pool->literals[entry].X_unsigned
1090 == inst.reloc.exp.X_unsigned))
b99bd4ef
NC
1091 break;
1092
3d0c9500
NC
1093 if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
1094 && (inst.reloc.exp.X_op == O_symbol)
1095 && (pool->literals[entry].X_add_number
b99bd4ef 1096 == inst.reloc.exp.X_add_number)
3d0c9500 1097 && (pool->literals[entry].X_add_symbol
b99bd4ef 1098 == inst.reloc.exp.X_add_symbol)
3d0c9500 1099 && (pool->literals[entry].X_op_symbol
b99bd4ef 1100 == inst.reloc.exp.X_op_symbol))
3d0c9500 1101 break;
b99bd4ef
NC
1102 }
1103
3d0c9500
NC
1104 /* Do we need to create a new entry? */
1105 if (entry == pool->next_free_entry)
b99bd4ef 1106 {
3d0c9500 1107 if (entry >= MAX_LITERAL_POOL_SIZE)
b99bd4ef 1108 {
ed71e111 1109 inst.error = _("literal pool overflow");
b99bd4ef
NC
1110 return FAIL;
1111 }
1112
3d0c9500
NC
1113 pool->literals[entry] = inst.reloc.exp;
1114 pool->next_free_entry += 1;
b99bd4ef
NC
1115 }
1116
3d0c9500 1117 inst.reloc.exp.X_op = O_symbol;
08df2379 1118 inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
3d0c9500 1119 inst.reloc.exp.X_add_symbol = pool->symbol;
b99bd4ef
NC
1120
1121 return SUCCESS;
1122}
1123
1124/* Can't use symbol_new here, so have to create a symbol and then at
1125 a later date assign it a value. Thats what these functions do. */
1126
1127static void
a737bd4d
NC
1128symbol_locate (symbolS * symbolP,
1129 const char * name, /* It is copied, the caller can modify. */
1130 segT segment, /* Segment identifier (SEG_<something>). */
1131 valueT valu, /* Symbol value. */
1132 fragS * frag) /* Associated fragment. */
b99bd4ef
NC
1133{
1134 unsigned int name_length;
1135 char * preserved_copy_of_name;
1136
1137 name_length = strlen (name) + 1; /* +1 for \0. */
1138 obstack_grow (&notes, name, name_length);
1139 preserved_copy_of_name = obstack_finish (&notes);
1140#ifdef STRIP_UNDERSCORE
1141 if (preserved_copy_of_name[0] == '_')
1142 preserved_copy_of_name++;
1143#endif
1144
1145#ifdef tc_canonicalize_symbol_name
1146 preserved_copy_of_name =
1147 tc_canonicalize_symbol_name (preserved_copy_of_name);
1148#endif
1149
1150 S_SET_NAME (symbolP, preserved_copy_of_name);
1151
1152 S_SET_SEGMENT (symbolP, segment);
1153 S_SET_VALUE (symbolP, valu);
c62e1cc3 1154 symbol_clear_list_pointers (symbolP);
b99bd4ef
NC
1155
1156 symbol_set_frag (symbolP, frag);
1157
1158 /* Link to end of symbol chain. */
1159 {
1160 extern int symbol_table_frozen;
a737bd4d 1161
b99bd4ef
NC
1162 if (symbol_table_frozen)
1163 abort ();
1164 }
1165
1166 symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
1167
1168 obj_symbol_new_hook (symbolP);
1169
1170#ifdef tc_symbol_new_hook
1171 tc_symbol_new_hook (symbolP);
1172#endif
1173
1174#ifdef DEBUG_SYMS
1175 verify_symbol_chain (symbol_rootP, symbol_lastP);
1176#endif /* DEBUG_SYMS */
1177}
1178
1179/* Check that an immediate is valid.
1180 If so, convert it to the right format. */
1181
1182static unsigned int
a737bd4d 1183validate_immediate (unsigned int val)
b99bd4ef
NC
1184{
1185 unsigned int a;
1186 unsigned int i;
1187
1188#define rotate_left(v, n) (v << n | v >> (32 - n))
1189
1190 for (i = 0; i < 32; i += 2)
1191 if ((a = rotate_left (val, i)) <= 0xff)
1192 return a | (i << 7); /* 12-bit pack: [shift-cnt,const]. */
1193
1194 return FAIL;
1195}
1196
2d2255b5 1197/* Check to see if an immediate can be computed as two separate immediate
b99bd4ef
NC
1198 values, added together. We already know that this value cannot be
1199 computed by just one ARM instruction. */
1200
1201static unsigned int
a737bd4d
NC
1202validate_immediate_twopart (unsigned int val,
1203 unsigned int * highpart)
b99bd4ef
NC
1204{
1205 unsigned int a;
1206 unsigned int i;
1207
1208 for (i = 0; i < 32; i += 2)
1209 if (((a = rotate_left (val, i)) & 0xff) != 0)
1210 {
1211 if (a & 0xff00)
1212 {
1213 if (a & ~ 0xffff)
1214 continue;
1215 * highpart = (a >> 8) | ((i + 24) << 7);
1216 }
1217 else if (a & 0xff0000)
1218 {
1219 if (a & 0xff000000)
1220 continue;
1221 * highpart = (a >> 16) | ((i + 16) << 7);
1222 }
1223 else
1224 {
1225 assert (a & 0xff000000);
1226 * highpart = (a >> 24) | ((i + 8) << 7);
1227 }
1228
1229 return (a & 0xff) | (i << 7);
1230 }
1231
1232 return FAIL;
1233}
1234
1235static int
a737bd4d 1236validate_offset_imm (unsigned int val, int hwse)
b99bd4ef
NC
1237{
1238 if ((hwse && val > 255) || val > 4095)
1239 return FAIL;
1240 return val;
1241}
1242
6057a28f
NC
1243\f
1244#ifdef OBJ_ELF
6057a28f
NC
1245/* This code is to handle mapping symbols as defined in the ARM ELF spec.
1246 (This text is taken from version B-02 of the spec):
1247
1248 4.4.7 Mapping and tagging symbols
1249
1250 A section of an ARM ELF file can contain a mixture of ARM code,
1251 Thumb code, and data. There are inline transitions between code
1252 and data at literal pool boundaries. There can also be inline
1253 transitions between ARM code and Thumb code, for example in
1254 ARM-Thumb inter-working veneers. Linkers, machine-level
1255 debuggers, profiling tools, and disassembly tools need to map
1256 images accurately. For example, setting an ARM breakpoint on a
1257 Thumb location, or in a literal pool, can crash the program
1258 being debugged, ruining the debugging session.
1259
1260 ARM ELF entities are mapped (see section 4.4.7.1 below) and
1261 tagged (see section 4.4.7.2 below) using local symbols (with
1262 binding STB_LOCAL). To assist consumers, mapping and tagging
1263 symbols should be collated first in the symbol table, before
1264 other symbols with binding STB_LOCAL.
1265
1266 To allow properly collated mapping and tagging symbols to be
1267 skipped by consumers that have no interest in them, the first
1268 such symbol should have the name $m and its st_value field equal
1269 to the total number of mapping and tagging symbols (including
1270 the $m) in the symbol table.
1271
1272 4.4.7.1 Mapping symbols
1273
1274 $a Labels the first byte of a sequence of ARM instructions.
1275 Its type is STT_FUNC.
1276
1277 $d Labels the first byte of a sequence of data items.
1278 Its type is STT_OBJECT.
1279
1280 $t Labels the first byte of a sequence of Thumb instructions.
1281 Its type is STT_FUNC.
1282
1283 This list of mapping symbols may be extended in the future.
1284
1285 Section-relative mapping symbols
1286
1287 Mapping symbols defined in a section define a sequence of
1288 half-open address intervals that cover the address range of the
1289 section. Each interval starts at the address defined by a
1290 mapping symbol, and continues up to, but not including, the
1291 address defined by the next (in address order) mapping symbol or
1292 the end of the section. A corollary is that there must be a
1293 mapping symbol defined at the beginning of each section.
1294 Consumers can ignore the size of a section-relative mapping
1295 symbol. Producers can set it to 0.
1296
1297 Absolute mapping symbols
1298
1299 Because of the need to crystallize a Thumb address with the
1300 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
1301 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
1302 or $t.
1303
1304 The extent of a mapping symbol defined in SHN_ABS is [st_value,
1305 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
1306 where [x, y) denotes the half-open address range from x,
1307 inclusive, to y, exclusive.
1308
1309 In the absence of a mapping symbol, a consumer can interpret a
1310 function symbol with an odd value as the Thumb code address
1311 obtained by clearing the least significant bit of the
1312 value. This interpretation is deprecated, and it may not work in
1313 the future.
1314
1315 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
1316 the EABI (which is still under development), so they are not
1317 implemented here. */
1318
69b97547
NC
1319static enum mstate mapstate = MAP_UNDEFINED;
1320
6057a28f
NC
1321static void
1322mapping_state (enum mstate state)
1323{
6057a28f
NC
1324 symbolS * symbolP;
1325 const char * symname;
1326 int type;
1327
1328 if (mapstate == state)
1329 /* The mapping symbol has already been emitted.
1330 There is nothing else to do. */
1331 return;
1332
1333 mapstate = state;
1334
1335 switch (state)
1336 {
1337 case MAP_DATA:
1338 symname = "$d";
1339 type = BSF_OBJECT;
1340 break;
1341 case MAP_ARM:
1342 symname = "$a";
1343 type = BSF_FUNCTION;
1344 break;
1345 case MAP_THUMB:
1346 symname = "$t";
1347 type = BSF_FUNCTION;
1348 break;
69b97547 1349 case MAP_UNDEFINED:
a737bd4d 1350 return;
6057a28f
NC
1351 default:
1352 abort ();
1353 }
1354
84798bd6 1355 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
69b97547 1356
6057a28f
NC
1357 symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
1358 symbol_table_insert (symbolP);
1359 symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
a737bd4d 1360
6057a28f
NC
1361 switch (state)
1362 {
1363 case MAP_ARM:
1364 THUMB_SET_FUNC (symbolP, 0);
1365 ARM_SET_THUMB (symbolP, 0);
1366 ARM_SET_INTERWORK (symbolP, support_interwork);
1367 break;
a737bd4d 1368
6057a28f
NC
1369 case MAP_THUMB:
1370 THUMB_SET_FUNC (symbolP, 1);
1371 ARM_SET_THUMB (symbolP, 1);
1372 ARM_SET_INTERWORK (symbolP, support_interwork);
1373 break;
a737bd4d 1374
6057a28f
NC
1375 case MAP_DATA:
1376 default:
1377 return;
1378 }
1379}
1380
a737bd4d
NC
1381/* When we change sections we need to issue a new mapping symbol. */
1382
1383void
1384arm_elf_change_section (void)
1385{
1386 flagword flags;
84798bd6 1387 segment_info_type *seginfo;
a737bd4d 1388
40a18ebd
NC
1389 /* Link an unlinked unwind index table section to the .text section. */
1390 if (elf_section_type (now_seg) == SHT_ARM_EXIDX
1391 && elf_linked_to_section (now_seg) == NULL)
1392 elf_linked_to_section (now_seg) = text_section;
1393
a737bd4d
NC
1394 if (!SEG_NORMAL (now_seg))
1395 return;
1396
1397 flags = bfd_get_section_flags (stdoutput, now_seg);
1398
1399 /* We can ignore sections that only contain debug info. */
1400 if ((flags & SEC_ALLOC) == 0)
1401 return;
1402
84798bd6
JB
1403 seginfo = seg_info (now_seg);
1404 mapstate = seginfo->tc_segment_info_data.mapstate;
1405 marked_pr_dependency = seginfo->tc_segment_info_data.marked_pr_dependency;
a737bd4d 1406}
40a18ebd
NC
1407
1408int
1409arm_elf_section_type (const char * str, size_t len)
1410{
1411 if (len == 5 && strncmp (str, "exidx", 5) == 0)
1412 return SHT_ARM_EXIDX;
1413
1414 return -1;
1415}
a737bd4d
NC
1416#else
1417#define mapping_state(a)
1418#endif /* OBJ_ELF */
1419\f
1420/* arm_reg_parse () := if it looks like a register, return its token and
1421 advance the pointer. */
1422
1423static int
1424arm_reg_parse (char ** ccp, struct hash_control * htab)
1425{
1426 char * start = * ccp;
1427 char c;
1428 char * p;
1429 struct reg_entry * reg;
1430
1431#ifdef REGISTER_PREFIX
1432 if (*start != REGISTER_PREFIX)
1433 return FAIL;
1434 p = start + 1;
1435#else
1436 p = start;
1437#ifdef OPTIONAL_REGISTER_PREFIX
1438 if (*p == OPTIONAL_REGISTER_PREFIX)
1439 p++, start++;
1440#endif
1441#endif
1442 if (!ISALPHA (*p) || !is_name_beginner (*p))
1443 return FAIL;
1444
1445 c = *p++;
1446 while (ISALPHA (c) || ISDIGIT (c) || c == '_')
1447 c = *p++;
1448
1449 *--p = 0;
1450 reg = (struct reg_entry *) hash_find (htab, start);
1451 *p = c;
1452
1453 if (reg)
1454 {
1455 *ccp = p;
1456 return reg->number;
1457 }
1458
1459 return FAIL;
1460}
1461
1462/* Search for the following register name in each of the possible reg name
1463 tables. Return the classification if found, or REG_TYPE_MAX if not
1464 present. */
6057a28f 1465
a737bd4d
NC
1466static enum arm_reg_type
1467arm_reg_parse_any (char *cp)
6057a28f 1468{
a737bd4d 1469 int i;
6057a28f 1470
a737bd4d
NC
1471 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
1472 if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
1473 return (enum arm_reg_type) i;
6057a28f 1474
a737bd4d
NC
1475 return REG_TYPE_MAX;
1476}
6057a28f 1477
a737bd4d
NC
1478static void
1479opcode_select (int width)
1480{
1481 switch (width)
1482 {
1483 case 16:
1484 if (! thumb_mode)
1485 {
1486 if (! (cpu_variant & ARM_EXT_V4T))
1487 as_bad (_("selected processor does not support THUMB opcodes"));
6057a28f 1488
a737bd4d
NC
1489 thumb_mode = 1;
1490 /* No need to force the alignment, since we will have been
1491 coming from ARM mode, which is word-aligned. */
1492 record_alignment (now_seg, 1);
1493 }
1494 mapping_state (MAP_THUMB);
1495 break;
1496
1497 case 32:
1498 if (thumb_mode)
1499 {
1500 if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
1501 as_bad (_("selected processor does not support ARM opcodes"));
1502
1503 thumb_mode = 0;
1504
1505 if (!need_pass_2)
1506 frag_align (2, 0, 0);
1507
1508 record_alignment (now_seg, 1);
1509 }
1510 mapping_state (MAP_ARM);
1511 break;
1512
1513 default:
1514 as_bad (_("invalid instruction size selected (%d)"), width);
1515 }
6057a28f 1516}
6057a28f 1517
b99bd4ef 1518static void
a737bd4d 1519s_req (int a ATTRIBUTE_UNUSED)
b99bd4ef 1520{
f03698e6 1521 as_bad (_("invalid syntax for .req directive"));
b99bd4ef
NC
1522}
1523
0bbf2aa4
NC
1524/* The .unreq directive deletes an alias which was previously defined
1525 by .req. For example:
1526
1527 my_alias .req r11
1528 .unreq my_alias */
1529
1530static void
1531s_unreq (int a ATTRIBUTE_UNUSED)
1532{
a737bd4d 1533 char * name;
0bbf2aa4
NC
1534 char saved_char;
1535
1536 skip_whitespace (input_line_pointer);
1537 name = input_line_pointer;
1538
1539 while (*input_line_pointer != 0
1540 && *input_line_pointer != ' '
1541 && *input_line_pointer != '\n')
1542 ++input_line_pointer;
1543
1544 saved_char = *input_line_pointer;
1545 *input_line_pointer = 0;
1546
1547 if (*name)
1548 {
1549 enum arm_reg_type req_type = arm_reg_parse_any (name);
1550
1551 if (req_type != REG_TYPE_MAX)
1552 {
1553 char *temp_name = name;
1554 int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
1555
1556 if (req_no != FAIL)
1557 {
1558 struct reg_entry *req_entry;
1559
1560 /* Check to see if this alias is a builtin one. */
1561 req_entry = hash_delete (all_reg_maps[req_type].htab, name);
1562
1563 if (!req_entry)
1564 as_bad (_("unreq: missing hash entry for \"%s\""), name);
1565 else if (req_entry->builtin)
67c1ffbe 1566 /* FIXME: We are deleting a built in register alias which
0bbf2aa4
NC
1567 points to a const data structure, so we only need to
1568 free up the memory used by the key in the hash table.
1569 Unfortunately we have not recorded this value, so this
1570 is a memory leak. */
1571 /* FIXME: Should we issue a warning message ? */
1572 ;
1573 else
1574 {
67c1ffbe 1575 /* Deleting a user defined alias. We need to free the
0bbf2aa4
NC
1576 key and the value, but fortunately the key is the same
1577 as the value->name field. */
1578 free ((char *) req_entry->name);
1579 free (req_entry);
1580 }
1581 }
1582 else
1583 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1584 }
1585 else
1586 as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
1587 }
1588 else
1589 as_bad (_("invalid syntax for .unreq directive"));
1590
1591 *input_line_pointer = saved_char;
1592 demand_empty_rest_of_line ();
1593}
1594
b99bd4ef 1595static void
a737bd4d 1596s_bss (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1597{
1598 /* We don't support putting frags in the BSS segment, we fake it by
1599 marking in_bss, then looking at s_skip for clues. */
1600 subseg_set (bss_section, 0);
1601 demand_empty_rest_of_line ();
6057a28f 1602 mapping_state (MAP_DATA);
b99bd4ef
NC
1603}
1604
1605static void
a737bd4d 1606s_even (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1607{
1608 /* Never make frag if expect extra pass. */
1609 if (!need_pass_2)
1610 frag_align (1, 0, 0);
1611
1612 record_alignment (now_seg, 1);
1613
1614 demand_empty_rest_of_line ();
1615}
1616
1617static void
a737bd4d 1618s_ltorg (int ignored ATTRIBUTE_UNUSED)
b99bd4ef 1619{
3d0c9500
NC
1620 unsigned int entry;
1621 literal_pool * pool;
b99bd4ef
NC
1622 char sym_name[20];
1623
3d0c9500
NC
1624 pool = find_literal_pool ();
1625 if (pool == NULL
1626 || pool->symbol == NULL
1627 || pool->next_free_entry == 0)
b99bd4ef
NC
1628 return;
1629
69b97547
NC
1630 mapping_state (MAP_DATA);
1631
b99bd4ef
NC
1632 /* Align pool as you have word accesses.
1633 Only make a frag if we have to. */
1634 if (!need_pass_2)
1635 frag_align (2, 0, 0);
1636
1637 record_alignment (now_seg, 2);
1638
3d0c9500 1639 sprintf (sym_name, "$$lit_\002%x", pool->id);
b99bd4ef 1640
3d0c9500 1641 symbol_locate (pool->symbol, sym_name, now_seg,
b99bd4ef 1642 (valueT) frag_now_fix (), frag_now);
3d0c9500 1643 symbol_table_insert (pool->symbol);
b99bd4ef 1644
3d0c9500 1645 ARM_SET_THUMB (pool->symbol, thumb_mode);
b99bd4ef
NC
1646
1647#if defined OBJ_COFF || defined OBJ_ELF
3d0c9500 1648 ARM_SET_INTERWORK (pool->symbol, support_interwork);
b99bd4ef
NC
1649#endif
1650
3d0c9500 1651 for (entry = 0; entry < pool->next_free_entry; entry ++)
b99bd4ef 1652 /* First output the expression in the instruction to the pool. */
3d0c9500 1653 emit_expr (&(pool->literals[entry]), 4); /* .word */
b99bd4ef 1654
3d0c9500
NC
1655 /* Mark the pool as empty. */
1656 pool->next_free_entry = 0;
1657 pool->symbol = NULL;
b99bd4ef
NC
1658}
1659
1660/* Same as s_align_ptwo but align 0 => align 2. */
1661
1662static void
a737bd4d 1663s_align (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1664{
a737bd4d
NC
1665 int temp;
1666 long temp_fill;
b99bd4ef
NC
1667 long max_alignment = 15;
1668
1669 temp = get_absolute_expression ();
1670 if (temp > max_alignment)
f03698e6 1671 as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
b99bd4ef
NC
1672 else if (temp < 0)
1673 {
f03698e6 1674 as_bad (_("alignment negative. 0 assumed."));
b99bd4ef
NC
1675 temp = 0;
1676 }
1677
1678 if (*input_line_pointer == ',')
1679 {
1680 input_line_pointer++;
1681 temp_fill = get_absolute_expression ();
1682 }
1683 else
1684 temp_fill = 0;
1685
1686 if (!temp)
1687 temp = 2;
1688
1689 /* Only make a frag if we HAVE to. */
1690 if (temp && !need_pass_2)
1691 frag_align (temp, (int) temp_fill, 0);
1692 demand_empty_rest_of_line ();
1693
1694 record_alignment (now_seg, temp);
1695}
1696
1697static void
a737bd4d 1698s_force_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1699{
1700 /* If we are not already in thumb mode go into it, EVEN if
1701 the target processor does not support thumb instructions.
1702 This is used by gcc/config/arm/lib1funcs.asm for example
1703 to compile interworking support functions even if the
1704 target processor should not support interworking. */
1705 if (! thumb_mode)
1706 {
1707 thumb_mode = 2;
1708
1709 record_alignment (now_seg, 1);
1710 }
1711
1712 demand_empty_rest_of_line ();
1713}
1714
1715static void
a737bd4d 1716s_thumb_func (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1717{
1718 if (! thumb_mode)
1719 opcode_select (16);
1720
1721 /* The following label is the name/address of the start of a Thumb function.
1722 We need to know this for the interworking support. */
b34976b6 1723 label_is_thumb_function_name = TRUE;
b99bd4ef
NC
1724
1725 demand_empty_rest_of_line ();
1726}
1727
1728/* Perform a .set directive, but also mark the alias as
1729 being a thumb function. */
1730
1731static void
a737bd4d 1732s_thumb_set (int equiv)
b99bd4ef
NC
1733{
1734 /* XXX the following is a duplicate of the code for s_set() in read.c
1735 We cannot just call that code as we need to get at the symbol that
1736 is created. */
a737bd4d
NC
1737 char * name;
1738 char delim;
1739 char * end_name;
1740 symbolS * symbolP;
b99bd4ef
NC
1741
1742 /* Especial apologies for the random logic:
1743 This just grew, and could be parsed much more simply!
1744 Dean - in haste. */
1745 name = input_line_pointer;
1746 delim = get_symbol_end ();
1747 end_name = input_line_pointer;
1748 *end_name = delim;
1749
1750 SKIP_WHITESPACE ();
1751
1752 if (*input_line_pointer != ',')
1753 {
1754 *end_name = 0;
f03698e6 1755 as_bad (_("expected comma after name \"%s\""), name);
b99bd4ef
NC
1756 *end_name = delim;
1757 ignore_rest_of_line ();
1758 return;
1759 }
1760
1761 input_line_pointer++;
1762 *end_name = 0;
1763
1764 if (name[0] == '.' && name[1] == '\0')
1765 {
1766 /* XXX - this should not happen to .thumb_set. */
1767 abort ();
1768 }
1769
1770 if ((symbolP = symbol_find (name)) == NULL
1771 && (symbolP = md_undefined_symbol (name)) == NULL)
1772 {
1773#ifndef NO_LISTING
1774 /* When doing symbol listings, play games with dummy fragments living
1775 outside the normal fragment chain to record the file and line info
1776 for this symbol. */
1777 if (listing & LISTING_SYMBOLS)
1778 {
1779 extern struct list_info_struct * listing_tail;
a737bd4d 1780 fragS * dummy_frag = xmalloc (sizeof (fragS));
b99bd4ef
NC
1781
1782 memset (dummy_frag, 0, sizeof (fragS));
1783 dummy_frag->fr_type = rs_fill;
1784 dummy_frag->line = listing_tail;
1785 symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
1786 dummy_frag->fr_symbol = symbolP;
1787 }
1788 else
1789#endif
1790 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
1791
1792#ifdef OBJ_COFF
1793 /* "set" symbols are local unless otherwise specified. */
1794 SF_SET_LOCAL (symbolP);
1795#endif /* OBJ_COFF */
1796 } /* Make a new symbol. */
1797
1798 symbol_table_insert (symbolP);
1799
1800 * end_name = delim;
1801
1802 if (equiv
1803 && S_IS_DEFINED (symbolP)
1804 && S_GET_SEGMENT (symbolP) != reg_section)
1805 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
1806
1807 pseudo_set (symbolP);
1808
1809 demand_empty_rest_of_line ();
1810
1811 /* XXX Now we come to the Thumb specific bit of code. */
1812
1813 THUMB_SET_FUNC (symbolP, 1);
1814 ARM_SET_THUMB (symbolP, 1);
1815#if defined OBJ_ELF || defined OBJ_COFF
1816 ARM_SET_INTERWORK (symbolP, support_interwork);
1817#endif
1818}
1819
b99bd4ef 1820static void
a737bd4d 1821s_arm (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1822{
1823 opcode_select (32);
1824 demand_empty_rest_of_line ();
1825}
1826
1827static void
a737bd4d 1828s_thumb (int ignore ATTRIBUTE_UNUSED)
b99bd4ef
NC
1829{
1830 opcode_select (16);
1831 demand_empty_rest_of_line ();
1832}
1833
1834static void
a737bd4d 1835s_code (int unused ATTRIBUTE_UNUSED)
b99bd4ef 1836{
a737bd4d 1837 int temp;
b99bd4ef
NC
1838
1839 temp = get_absolute_expression ();
1840 switch (temp)
1841 {
1842 case 16:
1843 case 32:
1844 opcode_select (temp);
1845 break;
1846
1847 default:
1848 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
1849 }
1850}
1851
1852static void
a737bd4d 1853end_of_line (char * str)
b99bd4ef
NC
1854{
1855 skip_whitespace (str);
1856
f03698e6
RE
1857 if (*str != '\0' && !inst.error)
1858 inst.error = _("garbage following instruction");
b99bd4ef
NC
1859}
1860
1861static int
a737bd4d 1862skip_past_comma (char ** str)
b99bd4ef
NC
1863{
1864 char * p = * str, c;
1865 int comma = 0;
1866
1867 while ((c = *p) == ' ' || c == ',')
1868 {
1869 p++;
1870 if (c == ',' && comma++)
1871 return FAIL;
1872 }
1873
1874 if (c == '\0')
1875 return FAIL;
1876
1877 *str = p;
1878 return comma ? SUCCESS : FAIL;
1879}
1880
a737bd4d
NC
1881/* Return TRUE if anything in the expression is a bignum. */
1882
1883static int
1884walk_no_bignums (symbolS * sp)
1885{
1886 if (symbol_get_value_expression (sp)->X_op == O_big)
1887 return 1;
1888
1889 if (symbol_get_value_expression (sp)->X_add_symbol)
1890 {
1891 return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
1892 || (symbol_get_value_expression (sp)->X_op_symbol
1893 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
1894 }
1895
1896 return 0;
1897}
1898
1899static int in_my_get_expression = 0;
1900
1901static int
1902my_get_expression (expressionS * ep, char ** str)
1903{
1904 char * save_in;
1905 segT seg;
1906
1907 save_in = input_line_pointer;
1908 input_line_pointer = *str;
1909 in_my_get_expression = 1;
1910 seg = expression (ep);
1911 in_my_get_expression = 0;
1912
1913 if (ep->X_op == O_illegal)
1914 {
1915 /* We found a bad expression in md_operand(). */
1916 *str = input_line_pointer;
1917 input_line_pointer = save_in;
1918 return 1;
1919 }
1920
1921#ifdef OBJ_AOUT
1922 if (seg != absolute_section
1923 && seg != text_section
1924 && seg != data_section
1925 && seg != bss_section
1926 && seg != undefined_section)
1927 {
1928 inst.error = _("bad_segment");
1929 *str = input_line_pointer;
1930 input_line_pointer = save_in;
1931 return 1;
1932 }
1933#endif
1934
1935 /* Get rid of any bignums now, so that we don't generate an error for which
1936 we can't establish a line number later on. Big numbers are never valid
1937 in instructions, which is where this routine is always called. */
1938 if (ep->X_op == O_big
1939 || (ep->X_add_symbol
1940 && (walk_no_bignums (ep->X_add_symbol)
1941 || (ep->X_op_symbol
1942 && walk_no_bignums (ep->X_op_symbol)))))
1943 {
1944 inst.error = _("invalid constant");
1945 *str = input_line_pointer;
1946 input_line_pointer = save_in;
1947 return 1;
1948 }
1949
1950 *str = input_line_pointer;
1951 input_line_pointer = save_in;
1952 return 0;
1953}
1954
b99bd4ef
NC
1955/* A standard register must be given at this point.
1956 SHIFT is the place to put it in inst.instruction.
1957 Restores input start point on error.
1958 Returns the reg#, or FAIL. */
1959
1960static int
a737bd4d 1961reg_required_here (char ** str, int shift)
b99bd4ef
NC
1962{
1963 static char buff [128]; /* XXX */
1964 int reg;
1965 char * start = * str;
1966
6c43fab6 1967 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
b99bd4ef
NC
1968 {
1969 if (shift >= 0)
1970 inst.instruction |= reg << shift;
1971 return reg;
1972 }
1973
1974 /* Restore the start point, we may have got a reg of the wrong class. */
1975 *str = start;
1976
1977 /* In the few cases where we might be able to accept something else
1978 this error can be overridden. */
f03698e6 1979 sprintf (buff, _("register expected, not '%.100s'"), start);
b99bd4ef
NC
1980 inst.error = buff;
1981
1982 return FAIL;
1983}
1984
5a6c6817 1985/* A Intel Wireless MMX technology register
e16bb312
NC
1986 must be given at this point.
1987 Shift is the place to put it in inst.instruction.
1988 Restores input start point on err.
1989 Returns the reg#, or FAIL. */
1990
1991static int
a737bd4d
NC
1992wreg_required_here (char ** str,
1993 int shift,
1994 enum wreg_type reg_type)
e16bb312
NC
1995{
1996 static char buff [128];
1997 int reg;
1998 char * start = *str;
1999
2000 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
2001 {
2002 if (wr_register (reg)
2003 && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
2004 {
2005 if (shift >= 0)
2006 inst.instruction |= (reg ^ WR_PREFIX) << shift;
2007 return reg;
2008 }
2009 else if (wc_register (reg)
2010 && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
2011 {
2012 if (shift >= 0)
2013 inst.instruction |= (reg ^ WC_PREFIX) << shift;
2014 return reg;
2015 }
2016 else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
2017 {
2018 if (shift >= 0)
2019 inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
2020 return reg;
2021 }
2022 }
2023
2024 /* Restore the start point, we may have got a reg of the wrong class. */
2025 *str = start;
2026
2027 /* In the few cases where we might be able to accept
2028 something else this error can be overridden. */
5a6c6817 2029 sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
e16bb312
NC
2030 inst.error = buff;
2031
2032 return FAIL;
2033}
2034
05d2d07e 2035static const struct asm_psr *
a737bd4d 2036arm_psr_parse (char ** ccp)
b99bd4ef
NC
2037{
2038 char * start = * ccp;
2039 char c;
2040 char * p;
05d2d07e 2041 const struct asm_psr * psr;
b99bd4ef
NC
2042
2043 p = start;
2044
2045 /* Skip to the end of the next word in the input stream. */
2046 do
2047 {
2048 c = *p++;
2049 }
3882b010 2050 while (ISALPHA (c) || c == '_');
b99bd4ef
NC
2051
2052 /* Terminate the word. */
2053 *--p = 0;
2054
2055 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2056 feature for ease of use and backwards compatibility. */
2057 if (!strncmp (start, "cpsr", 4))
2058 strncpy (start, "CPSR", 4);
2059 else if (!strncmp (start, "spsr", 4))
2060 strncpy (start, "SPSR", 4);
2061
2062 /* Now locate the word in the psr hash table. */
05d2d07e 2063 psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
b99bd4ef
NC
2064
2065 /* Restore the input stream. */
2066 *p = c;
2067
2068 /* If we found a valid match, advance the
2069 stream pointer past the end of the word. */
2070 *ccp = p;
2071
2072 return psr;
2073}
2074
2075/* Parse the input looking for a PSR flag. */
2076
2077static int
a737bd4d 2078psr_required_here (char ** str)
b99bd4ef
NC
2079{
2080 char * start = * str;
05d2d07e 2081 const struct asm_psr * psr;
b99bd4ef
NC
2082
2083 psr = arm_psr_parse (str);
2084
2085 if (psr)
2086 {
2087 /* If this is the SPSR that is being modified, set the R bit. */
2088 if (! psr->cpsr)
2089 inst.instruction |= SPSR_BIT;
2090
2091 /* Set the psr flags in the MSR instruction. */
2092 inst.instruction |= psr->field << PSR_SHIFT;
2093
2094 return SUCCESS;
2095 }
2096
2097 /* In the few cases where we might be able to accept
2098 something else this error can be overridden. */
2099 inst.error = _("flag for {c}psr instruction expected");
2100
2101 /* Restore the start point. */
2102 *str = start;
2103 return FAIL;
2104}
2105
2106static int
a737bd4d 2107co_proc_number (char ** str)
b99bd4ef
NC
2108{
2109 int processor, pchar;
6c43fab6 2110 char *start;
b99bd4ef 2111
6c43fab6
RE
2112 skip_whitespace (*str);
2113 start = *str;
b99bd4ef
NC
2114
2115 /* The data sheet seems to imply that just a number on its own is valid
2116 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2117 accept either. */
6c43fab6
RE
2118 if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
2119 == FAIL)
b99bd4ef 2120 {
6c43fab6
RE
2121 *str = start;
2122
2123 pchar = *(*str)++;
2124 if (pchar >= '0' && pchar <= '9')
b99bd4ef 2125 {
6c43fab6
RE
2126 processor = pchar - '0';
2127 if (**str >= '0' && **str <= '9')
b99bd4ef 2128 {
6c43fab6
RE
2129 processor = processor * 10 + *(*str)++ - '0';
2130 if (processor > 15)
2131 {
f03698e6 2132 inst.error = _("illegal co-processor number");
6c43fab6
RE
2133 return FAIL;
2134 }
b99bd4ef
NC
2135 }
2136 }
6c43fab6
RE
2137 else
2138 {
376eb240 2139 inst.error = all_reg_maps[REG_TYPE_CP].expected;
6c43fab6
RE
2140 return FAIL;
2141 }
b99bd4ef
NC
2142 }
2143
2144 inst.instruction |= processor << 8;
2145 return SUCCESS;
2146}
2147
2148static int
a737bd4d 2149cp_opc_expr (char ** str, int where, int length)
b99bd4ef
NC
2150{
2151 expressionS expr;
2152
2153 skip_whitespace (* str);
2154
2155 memset (&expr, '\0', sizeof (expr));
2156
2157 if (my_get_expression (&expr, str))
2158 return FAIL;
2159 if (expr.X_op != O_constant)
2160 {
2161 inst.error = _("bad or missing expression");
2162 return FAIL;
2163 }
2164
2165 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
2166 {
2167 inst.error = _("immediate co-processor expression too large");
2168 return FAIL;
2169 }
2170
2171 inst.instruction |= expr.X_add_number << where;
2172 return SUCCESS;
2173}
2174
2175static int
a737bd4d 2176cp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2177{
2178 int reg;
2179 char * start = *str;
2180
6c43fab6 2181 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
b99bd4ef 2182 {
b99bd4ef
NC
2183 inst.instruction |= reg << where;
2184 return reg;
2185 }
2186
2187 /* In the few cases where we might be able to accept something else
2188 this error can be overridden. */
376eb240 2189 inst.error = all_reg_maps[REG_TYPE_CN].expected;
b99bd4ef
NC
2190
2191 /* Restore the start point. */
2192 *str = start;
2193 return FAIL;
2194}
2195
2196static int
a737bd4d 2197fp_reg_required_here (char ** str, int where)
b99bd4ef
NC
2198{
2199 int reg;
2200 char * start = * str;
2201
6c43fab6 2202 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
b99bd4ef 2203 {
b99bd4ef
NC
2204 inst.instruction |= reg << where;
2205 return reg;
2206 }
2207
2208 /* In the few cases where we might be able to accept something else
2209 this error can be overridden. */
376eb240 2210 inst.error = all_reg_maps[REG_TYPE_FN].expected;
b99bd4ef
NC
2211
2212 /* Restore the start point. */
2213 *str = start;
2214 return FAIL;
2215}
2216
2217static int
a737bd4d 2218cp_address_offset (char ** str)
b99bd4ef
NC
2219{
2220 int offset;
2221
2222 skip_whitespace (* str);
2223
2224 if (! is_immediate_prefix (**str))
2225 {
2226 inst.error = _("immediate expression expected");
2227 return FAIL;
2228 }
2229
2230 (*str)++;
2231
2232 if (my_get_expression (& inst.reloc.exp, str))
2233 return FAIL;
2234
2235 if (inst.reloc.exp.X_op == O_constant)
2236 {
2237 offset = inst.reloc.exp.X_add_number;
2238
2239 if (offset & 3)
2240 {
2241 inst.error = _("co-processor address must be word aligned");
2242 return FAIL;
2243 }
2244
2245 if (offset > 1023 || offset < -1023)
2246 {
2247 inst.error = _("offset too large");
2248 return FAIL;
2249 }
2250
2251 if (offset >= 0)
2252 inst.instruction |= INDEX_UP;
2253 else
2254 offset = -offset;
2255
2256 inst.instruction |= offset >> 2;
2257 }
2258 else
2259 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2260
2261 return SUCCESS;
2262}
2263
2264static int
a737bd4d 2265cp_address_required_here (char ** str, int wb_ok)
b99bd4ef
NC
2266{
2267 char * p = * str;
2268 int pre_inc = 0;
2269 int write_back = 0;
2270
2271 if (*p == '[')
2272 {
2273 int reg;
2274
2275 p++;
2276 skip_whitespace (p);
2277
2278 if ((reg = reg_required_here (& p, 16)) == FAIL)
2279 return FAIL;
2280
2281 skip_whitespace (p);
2282
2283 if (*p == ']')
2284 {
2285 p++;
2286
f02232aa
NC
2287 skip_whitespace (p);
2288
2289 if (*p == '\0')
b99bd4ef 2290 {
f02232aa 2291 /* As an extension to the official ARM syntax we allow:
f02232aa 2292 [Rn]
f02232aa 2293 as a short hand for:
f02232aa
NC
2294 [Rn,#0] */
2295 inst.instruction |= PRE_INDEX | INDEX_UP;
2296 *str = p;
2297 return SUCCESS;
2298 }
a737bd4d 2299
f02232aa
NC
2300 if (skip_past_comma (& p) == FAIL)
2301 {
2302 inst.error = _("comma expected after closing square bracket");
2303 return FAIL;
2304 }
b99bd4ef 2305
f02232aa
NC
2306 skip_whitespace (p);
2307
2308 if (*p == '#')
2309 {
2310 if (wb_ok)
b99bd4ef 2311 {
f02232aa
NC
2312 /* [Rn], #expr */
2313 write_back = WRITE_BACK;
2314
2315 if (reg == REG_PC)
2316 {
2317 inst.error = _("pc may not be used in post-increment");
2318 return FAIL;
2319 }
2320
2321 if (cp_address_offset (& p) == FAIL)
2322 return FAIL;
b99bd4ef 2323 }
f02232aa
NC
2324 else
2325 pre_inc = PRE_INDEX | INDEX_UP;
2326 }
2327 else if (*p == '{')
2328 {
2329 int option;
b99bd4ef 2330
f02232aa
NC
2331 /* [Rn], {<expr>} */
2332 p++;
2333
2334 skip_whitespace (p);
2335
2336 if (my_get_expression (& inst.reloc.exp, & p))
b99bd4ef 2337 return FAIL;
f02232aa
NC
2338
2339 if (inst.reloc.exp.X_op == O_constant)
2340 {
2341 option = inst.reloc.exp.X_add_number;
2342
2343 if (option > 255 || option < 0)
2344 {
2345 inst.error = _("'option' field too large");
2346 return FAIL;
2347 }
2348
2349 skip_whitespace (p);
2350
2351 if (*p != '}')
2352 {
2353 inst.error = _("'}' expected at end of 'option' field");
2354 return FAIL;
2355 }
2356 else
2357 {
2358 p++;
2359 inst.instruction |= option;
2360 inst.instruction |= INDEX_UP;
2361 }
2362 }
2363 else
2364 {
2365 inst.error = _("non-constant expressions for 'option' field not supported");
2366 return FAIL;
2367 }
b99bd4ef
NC
2368 }
2369 else
f02232aa
NC
2370 {
2371 inst.error = _("# or { expected after comma");
a737bd4d 2372 return FAIL;
f02232aa 2373 }
b99bd4ef
NC
2374 }
2375 else
2376 {
2377 /* '['Rn, #expr']'[!] */
2378
2379 if (skip_past_comma (& p) == FAIL)
2380 {
2381 inst.error = _("pre-indexed expression expected");
2382 return FAIL;
2383 }
2384
2385 pre_inc = PRE_INDEX;
2386
2387 if (cp_address_offset (& p) == FAIL)
2388 return FAIL;
2389
2390 skip_whitespace (p);
2391
2392 if (*p++ != ']')
2393 {
2394 inst.error = _("missing ]");
2395 return FAIL;
2396 }
2397
2398 skip_whitespace (p);
2399
bfae80f2 2400 if (wb_ok && *p == '!')
b99bd4ef
NC
2401 {
2402 if (reg == REG_PC)
2403 {
2404 inst.error = _("pc may not be used with write-back");
2405 return FAIL;
2406 }
2407
2408 p++;
2409 write_back = WRITE_BACK;
2410 }
2411 }
2412 }
2413 else
2414 {
2415 if (my_get_expression (&inst.reloc.exp, &p))
2416 return FAIL;
2417
2418 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
2419 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2420 inst.reloc.pc_rel = 1;
2421 inst.instruction |= (REG_PC << 16);
2422 pre_inc = PRE_INDEX;
2423 }
2424
2425 inst.instruction |= write_back | pre_inc;
2426 *str = p;
2427 return SUCCESS;
2428}
2429
e16bb312 2430static int
a737bd4d 2431cp_byte_address_offset (char ** str)
e16bb312
NC
2432{
2433 int offset;
2434
2435 skip_whitespace (* str);
2436
2437 if (! is_immediate_prefix (**str))
2438 {
2439 inst.error = _("immediate expression expected");
2440 return FAIL;
2441 }
2442
2443 (*str)++;
a737bd4d 2444
e16bb312
NC
2445 if (my_get_expression (& inst.reloc.exp, str))
2446 return FAIL;
a737bd4d 2447
e16bb312
NC
2448 if (inst.reloc.exp.X_op == O_constant)
2449 {
2450 offset = inst.reloc.exp.X_add_number;
a737bd4d 2451
e16bb312
NC
2452 if (offset > 255 || offset < -255)
2453 {
2454 inst.error = _("offset too large");
2455 return FAIL;
2456 }
2457
2458 if (offset >= 0)
2459 inst.instruction |= INDEX_UP;
2460 else
2461 offset = -offset;
2462
2463 inst.instruction |= offset;
2464 }
2465 else
2466 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2467
2468 return SUCCESS;
2469}
2470
2471static int
a737bd4d 2472cp_byte_address_required_here (char ** str)
e16bb312
NC
2473{
2474 char * p = * str;
2475 int pre_inc = 0;
2476 int write_back = 0;
2477
2478 if (*p == '[')
2479 {
2480 int reg;
2481
2482 p++;
2483 skip_whitespace (p);
2484
2485 if ((reg = reg_required_here (& p, 16)) == FAIL)
2486 return FAIL;
2487
2488 skip_whitespace (p);
2489
2490 if (*p == ']')
2491 {
2492 p++;
a737bd4d 2493
e16bb312
NC
2494 if (skip_past_comma (& p) == SUCCESS)
2495 {
2496 /* [Rn], #expr */
2497 write_back = WRITE_BACK;
a737bd4d 2498
e16bb312
NC
2499 if (reg == REG_PC)
2500 {
2501 inst.error = _("pc may not be used in post-increment");
2502 return FAIL;
2503 }
2504
2505 if (cp_byte_address_offset (& p) == FAIL)
2506 return FAIL;
2507 }
2508 else
2509 pre_inc = PRE_INDEX | INDEX_UP;
2510 }
2511 else
2512 {
2513 /* '['Rn, #expr']'[!] */
2514
2515 if (skip_past_comma (& p) == FAIL)
2516 {
2517 inst.error = _("pre-indexed expression expected");
2518 return FAIL;
2519 }
2520
2521 pre_inc = PRE_INDEX;
a737bd4d 2522
e16bb312
NC
2523 if (cp_byte_address_offset (& p) == FAIL)
2524 return FAIL;
2525
2526 skip_whitespace (p);
2527
2528 if (*p++ != ']')
2529 {
2530 inst.error = _("missing ]");
2531 return FAIL;
2532 }
2533
2534 skip_whitespace (p);
2535
2536 if (*p == '!')
2537 {
2538 if (reg == REG_PC)
2539 {
2540 inst.error = _("pc may not be used with write-back");
2541 return FAIL;
2542 }
2543
2544 p++;
2545 write_back = WRITE_BACK;
2546 }
2547 }
2548 }
2549 else
2550 {
2551 if (my_get_expression (&inst.reloc.exp, &p))
2552 return FAIL;
2553
2554 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
2555 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
2556 inst.reloc.pc_rel = 1;
2557 inst.instruction |= (REG_PC << 16);
2558 pre_inc = PRE_INDEX;
2559 }
2560
2561 inst.instruction |= write_back | pre_inc;
2562 *str = p;
2563 return SUCCESS;
2564}
2565
0dd132b6
NC
2566static void
2567do_nop (char * str)
2568{
2569 skip_whitespace (str);
2570 if (*str == '{')
2571 {
2572 str++;
2573
2574 if (my_get_expression (&inst.reloc.exp, &str))
2575 inst.reloc.exp.X_op = O_illegal;
2576 else
2577 {
2578 skip_whitespace (str);
2579 if (*str == '}')
2580 str++;
2581 else
2582 inst.reloc.exp.X_op = O_illegal;
2583 }
2584
2585 if (inst.reloc.exp.X_op != O_constant
2586 || inst.reloc.exp.X_add_number > 255
2587 || inst.reloc.exp.X_add_number < 0)
2588 {
2589 inst.error = _("Invalid NOP hint");
2590 return;
2591 }
2592
2593 /* Arcitectural NOP hints are CPSR sets with no bits selected. */
2594 inst.instruction &= 0xf0000000;
2595 inst.instruction |= 0x0320f000 + inst.reloc.exp.X_add_number;
2596 }
2597
2598 end_of_line (str);
2599}
2600
b99bd4ef 2601static void
a737bd4d 2602do_empty (char * str)
b99bd4ef
NC
2603{
2604 /* Do nothing really. */
b99bd4ef 2605 end_of_line (str);
b99bd4ef
NC
2606}
2607
2608static void
a737bd4d 2609do_mrs (char * str)
b99bd4ef
NC
2610{
2611 int skip = 0;
2612
2613 /* Only one syntax. */
2614 skip_whitespace (str);
2615
2616 if (reg_required_here (&str, 12) == FAIL)
2617 {
2618 inst.error = BAD_ARGS;
2619 return;
2620 }
2621
2622 if (skip_past_comma (&str) == FAIL)
2623 {
2624 inst.error = _("comma expected after register name");
2625 return;
2626 }
2627
2628 skip_whitespace (str);
2629
a737bd4d
NC
2630 if ( streq (str, "CPSR")
2631 || streq (str, "SPSR")
2d2255b5 2632 /* Lower case versions for backwards compatibility. */
a737bd4d
NC
2633 || streq (str, "cpsr")
2634 || streq (str, "spsr"))
b99bd4ef
NC
2635 skip = 4;
2636
2d2255b5 2637 /* This is for backwards compatibility with older toolchains. */
a737bd4d
NC
2638 else if ( streq (str, "cpsr_all")
2639 || streq (str, "spsr_all"))
b99bd4ef
NC
2640 skip = 8;
2641 else
2642 {
f03698e6 2643 inst.error = _("CPSR or SPSR expected");
b99bd4ef
NC
2644 return;
2645 }
2646
2647 if (* str == 's' || * str == 'S')
2648 inst.instruction |= SPSR_BIT;
2649 str += skip;
2650
b99bd4ef
NC
2651 end_of_line (str);
2652}
2653
2654/* Two possible forms:
2655 "{C|S}PSR_<field>, Rm",
2656 "{C|S}PSR_f, #expression". */
2657
2658static void
a737bd4d 2659do_msr (char * str)
b99bd4ef
NC
2660{
2661 skip_whitespace (str);
2662
2663 if (psr_required_here (& str) == FAIL)
2664 return;
2665
2666 if (skip_past_comma (& str) == FAIL)
2667 {
2668 inst.error = _("comma missing after psr flags");
2669 return;
2670 }
2671
2672 skip_whitespace (str);
2673
2674 if (reg_required_here (& str, 0) != FAIL)
2675 {
2676 inst.error = NULL;
b99bd4ef
NC
2677 end_of_line (str);
2678 return;
2679 }
2680
2681 if (! is_immediate_prefix (* str))
2682 {
2683 inst.error =
2684 _("only a register or immediate value can follow a psr flag");
2685 return;
2686 }
2687
2688 str ++;
2689 inst.error = NULL;
2690
2691 if (my_get_expression (& inst.reloc.exp, & str))
2692 {
2693 inst.error =
2694 _("only a register or immediate value can follow a psr flag");
2695 return;
2696 }
2697
f2b7cb0a 2698 inst.instruction |= INST_IMMEDIATE;
b99bd4ef
NC
2699
2700 if (inst.reloc.exp.X_add_symbol)
2701 {
2702 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2703 inst.reloc.pc_rel = 0;
2704 }
2705 else
2706 {
2707 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
2708
2709 if (value == (unsigned) FAIL)
2710 {
f03698e6 2711 inst.error = _("invalid constant");
b99bd4ef
NC
2712 return;
2713 }
2714
2715 inst.instruction |= value;
2716 }
2717
2718 inst.error = NULL;
b99bd4ef
NC
2719 end_of_line (str);
2720}
2721
2722/* Long Multiply Parser
2723 UMULL RdLo, RdHi, Rm, Rs
2724 SMULL RdLo, RdHi, Rm, Rs
2725 UMLAL RdLo, RdHi, Rm, Rs
2726 SMLAL RdLo, RdHi, Rm, Rs. */
2727
2728static void
a737bd4d 2729do_mull (char * str)
b99bd4ef
NC
2730{
2731 int rdlo, rdhi, rm, rs;
2732
2733 /* Only one format "rdlo, rdhi, rm, rs". */
2734 skip_whitespace (str);
2735
2736 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
2737 {
2738 inst.error = BAD_ARGS;
2739 return;
2740 }
2741
2742 if (skip_past_comma (&str) == FAIL
2743 || (rdhi = reg_required_here (&str, 16)) == FAIL)
2744 {
2745 inst.error = BAD_ARGS;
2746 return;
2747 }
2748
2749 if (skip_past_comma (&str) == FAIL
2750 || (rm = reg_required_here (&str, 0)) == FAIL)
2751 {
2752 inst.error = BAD_ARGS;
2753 return;
2754 }
2755
2756 /* rdhi, rdlo and rm must all be different. */
2757 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
2758 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
2759
2760 if (skip_past_comma (&str) == FAIL
2761 || (rs = reg_required_here (&str, 8)) == FAIL)
2762 {
2763 inst.error = BAD_ARGS;
2764 return;
2765 }
2766
2767 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
2768 {
2769 inst.error = BAD_PC;
2770 return;
2771 }
2772
b99bd4ef 2773 end_of_line (str);
b99bd4ef
NC
2774}
2775
2776static void
a737bd4d 2777do_mul (char * str)
b99bd4ef
NC
2778{
2779 int rd, rm;
2780
2781 /* Only one format "rd, rm, rs". */
2782 skip_whitespace (str);
2783
2784 if ((rd = reg_required_here (&str, 16)) == FAIL)
2785 {
2786 inst.error = BAD_ARGS;
2787 return;
2788 }
2789
2790 if (rd == REG_PC)
2791 {
2792 inst.error = BAD_PC;
2793 return;
2794 }
2795
2796 if (skip_past_comma (&str) == FAIL
2797 || (rm = reg_required_here (&str, 0)) == FAIL)
2798 {
2799 inst.error = BAD_ARGS;
2800 return;
2801 }
2802
2803 if (rm == REG_PC)
2804 {
2805 inst.error = BAD_PC;
2806 return;
2807 }
2808
2809 if (rm == rd)
2810 as_tsktsk (_("rd and rm should be different in mul"));
2811
2812 if (skip_past_comma (&str) == FAIL
2813 || (rm = reg_required_here (&str, 8)) == FAIL)
2814 {
2815 inst.error = BAD_ARGS;
2816 return;
2817 }
2818
2819 if (rm == REG_PC)
2820 {
2821 inst.error = BAD_PC;
2822 return;
2823 }
2824
b99bd4ef 2825 end_of_line (str);
b99bd4ef
NC
2826}
2827
2828static void
b05fe5cf 2829do_mlas (char * str, bfd_boolean is_mls)
b99bd4ef
NC
2830{
2831 int rd, rm;
2832
2833 /* Only one format "rd, rm, rs, rn". */
2834 skip_whitespace (str);
2835
2836 if ((rd = reg_required_here (&str, 16)) == FAIL)
2837 {
2838 inst.error = BAD_ARGS;
2839 return;
2840 }
2841
2842 if (rd == REG_PC)
2843 {
2844 inst.error = BAD_PC;
2845 return;
2846 }
2847
2848 if (skip_past_comma (&str) == FAIL
2849 || (rm = reg_required_here (&str, 0)) == FAIL)
2850 {
2851 inst.error = BAD_ARGS;
2852 return;
2853 }
2854
2855 if (rm == REG_PC)
2856 {
2857 inst.error = BAD_PC;
2858 return;
2859 }
2860
b05fe5cf
ZW
2861 /* This restriction does not apply to mls (nor to mla in v6, but
2862 that's hard to detect at present). */
2863 if (rm == rd && !is_mls)
b99bd4ef
NC
2864 as_tsktsk (_("rd and rm should be different in mla"));
2865
2866 if (skip_past_comma (&str) == FAIL
2867 || (rd = reg_required_here (&str, 8)) == FAIL
2868 || skip_past_comma (&str) == FAIL
2869 || (rm = reg_required_here (&str, 12)) == FAIL)
2870 {
2871 inst.error = BAD_ARGS;
2872 return;
2873 }
2874
2875 if (rd == REG_PC || rm == REG_PC)
2876 {
2877 inst.error = BAD_PC;
2878 return;
2879 }
2880
b99bd4ef 2881 end_of_line (str);
b99bd4ef
NC
2882}
2883
b05fe5cf
ZW
2884static void
2885do_mla (char *str)
2886{
2887 do_mlas (str, FALSE);
2888}
2889
2890static void
2891do_mls (char *str)
2892{
2893 do_mlas (str, TRUE);
2894}
2895
b99bd4ef
NC
2896/* Expects *str -> the characters "acc0", possibly with leading blanks.
2897 Advances *str to the next non-alphanumeric.
2898 Returns 0, or else FAIL (in which case sets inst.error).
2899
2900 (In a future XScale, there may be accumulators other than zero.
2901 At that time this routine and its callers can be upgraded to suit.) */
2902
2903static int
a737bd4d 2904accum0_required_here (char ** str)
b99bd4ef
NC
2905{
2906 static char buff [128]; /* Note the address is taken. Hence, static. */
2907 char * p = * str;
2908 char c;
2909 int result = 0; /* The accum number. */
2910
2911 skip_whitespace (p);
2912
a737bd4d
NC
2913 *str = p; /* Advance caller's string pointer too. */
2914 c = *p++;
2915 while (ISALNUM (c))
2916 c = *p++;
2917
2918 *--p = 0; /* Aap nul into input buffer at non-alnum. */
2919
2920 if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
2921 {
2922 sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
2923 inst.error = buff;
2924 result = FAIL;
2925 }
2926
2927 *p = c; /* Unzap. */
2928 *str = p; /* Caller's string pointer to after match. */
2929 return result;
2930}
2931
2932static int
2933ldst_extend_v4 (char ** str)
2934{
2935 int add = INDEX_UP;
2936
2937 switch (**str)
2938 {
2939 case '#':
2940 case '$':
2941 (*str)++;
2942 if (my_get_expression (& inst.reloc.exp, str))
2943 return FAIL;
2944
2945 if (inst.reloc.exp.X_op == O_constant)
2946 {
2947 int value = inst.reloc.exp.X_add_number;
2948
2949 if (value < -255 || value > 255)
2950 {
2951 inst.error = _("address offset too large");
2952 return FAIL;
2953 }
2954
2955 if (value < 0)
2956 {
2957 value = -value;
2958 add = 0;
2959 }
2960
2961 /* Halfword and signextension instructions have the
2962 immediate value split across bits 11..8 and bits 3..0. */
2963 inst.instruction |= (add | HWOFFSET_IMM
2964 | ((value >> 4) << 8) | (value & 0xF));
2965 }
2966 else
2967 {
2968 inst.instruction |= HWOFFSET_IMM;
2969 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2970 inst.reloc.pc_rel = 0;
2971 }
2972 return SUCCESS;
2973
2974 case '-':
2975 add = 0;
2976 /* Fall through. */
2977
2978 case '+':
2979 (*str)++;
2980 /* Fall through. */
b99bd4ef 2981
a737bd4d
NC
2982 default:
2983 if (reg_required_here (str, 0) == FAIL)
2984 return FAIL;
b99bd4ef 2985
a737bd4d
NC
2986 inst.instruction |= add;
2987 return SUCCESS;
b99bd4ef 2988 }
b99bd4ef
NC
2989}
2990
2991/* Expects **str -> after a comma. May be leading blanks.
2992 Advances *str, recognizing a load mode, and setting inst.instruction.
2993 Returns rn, or else FAIL (in which case may set inst.error
2994 and not advance str)
2995
2996 Note: doesn't know Rd, so no err checks that require such knowledge. */
2997
2998static int
a737bd4d 2999ld_mode_required_here (char ** string)
b99bd4ef
NC
3000{
3001 char * str = * string;
3002 int rn;
3003 int pre_inc = 0;
3004
3005 skip_whitespace (str);
3006
3007 if (* str == '[')
3008 {
3009 str++;
3010
3011 skip_whitespace (str);
3012
3013 if ((rn = reg_required_here (& str, 16)) == FAIL)
3014 return FAIL;
3015
3016 skip_whitespace (str);
3017
3018 if (* str == ']')
3019 {
3020 str ++;
3021
3022 if (skip_past_comma (& str) == SUCCESS)
3023 {
3024 /* [Rn],... (post inc) */
90e4755a 3025 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3026 return FAIL;
3027 }
3028 else /* [Rn] */
3029 {
cc8a6dd0 3030 skip_whitespace (str);
b99bd4ef 3031
cc8a6dd0
KH
3032 if (* str == '!')
3033 {
3034 str ++;
3035 inst.instruction |= WRITE_BACK;
3036 }
b99bd4ef
NC
3037
3038 inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3039 pre_inc = 1;
3040 }
3041 }
3042 else /* [Rn,...] */
3043 {
3044 if (skip_past_comma (& str) == FAIL)
3045 {
3046 inst.error = _("pre-indexed expression expected");
3047 return FAIL;
3048 }
3049
3050 pre_inc = 1;
3051
90e4755a 3052 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
3053 return FAIL;
3054
3055 skip_whitespace (str);
3056
3057 if (* str ++ != ']')
3058 {
3059 inst.error = _("missing ]");
3060 return FAIL;
3061 }
3062
3063 skip_whitespace (str);
3064
3065 if (* str == '!')
3066 {
3067 str ++;
3068 inst.instruction |= WRITE_BACK;
3069 }
3070 }
3071 }
3072 else if (* str == '=') /* ldr's "r,=label" syntax */
3073 /* We should never reach here, because <text> = <expression> is
3074 caught gas/read.c read_a_source_file() as a .set operation. */
3075 return FAIL;
3076 else /* PC +- 8 bit immediate offset. */
3077 {
3078 if (my_get_expression (& inst.reloc.exp, & str))
3079 return FAIL;
3080
3081 inst.instruction |= HWOFFSET_IMM; /* The I bit. */
3082 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
3083 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */
3084 inst.reloc.pc_rel = 1;
3085 inst.instruction |= (REG_PC << 16);
3086
3087 rn = REG_PC;
3088 pre_inc = 1;
3089 }
3090
3091 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3092 * string = str;
3093
3094 return rn;
3095}
3096
3097/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3098 SMLAxy{cond} Rd,Rm,Rs,Rn
3099 SMLAWy{cond} Rd,Rm,Rs,Rn
3100 Error if any register is R15. */
3101
3102static void
a737bd4d 3103do_smla (char * str)
b99bd4ef
NC
3104{
3105 int rd, rm, rs, rn;
3106
3107 skip_whitespace (str);
3108
3109 if ((rd = reg_required_here (& str, 16)) == FAIL
3110 || skip_past_comma (& str) == FAIL
3111 || (rm = reg_required_here (& str, 0)) == FAIL
3112 || skip_past_comma (& str) == FAIL
3113 || (rs = reg_required_here (& str, 8)) == FAIL
3114 || skip_past_comma (& str) == FAIL
3115 || (rn = reg_required_here (& str, 12)) == FAIL)
3116 inst.error = BAD_ARGS;
3117
3118 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3119 inst.error = BAD_PC;
3120
b99bd4ef
NC
3121 else
3122 end_of_line (str);
3123}
3124
3125/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3126 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3127 Error if any register is R15.
3128 Warning if Rdlo == Rdhi. */
3129
3130static void
a737bd4d 3131do_smlal (char * str)
b99bd4ef
NC
3132{
3133 int rdlo, rdhi, rm, rs;
3134
3135 skip_whitespace (str);
3136
3137 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3138 || skip_past_comma (& str) == FAIL
3139 || (rdhi = reg_required_here (& str, 16)) == FAIL
3140 || skip_past_comma (& str) == FAIL
3141 || (rm = reg_required_here (& str, 0)) == FAIL
3142 || skip_past_comma (& str) == FAIL
3143 || (rs = reg_required_here (& str, 8)) == FAIL)
3144 {
3145 inst.error = BAD_ARGS;
3146 return;
3147 }
3148
3149 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3150 {
3151 inst.error = BAD_PC;
3152 return;
3153 }
3154
3155 if (rdlo == rdhi)
3156 as_tsktsk (_("rdhi and rdlo must be different"));
3157
f2b7cb0a 3158 end_of_line (str);
b99bd4ef
NC
3159}
3160
3161/* ARM V5E (El Segundo) signed-multiply (argument parse)
3162 SMULxy{cond} Rd,Rm,Rs
3163 Error if any register is R15. */
3164
3165static void
a737bd4d 3166do_smul (char * str)
b99bd4ef
NC
3167{
3168 int rd, rm, rs;
3169
3170 skip_whitespace (str);
3171
3172 if ((rd = reg_required_here (& str, 16)) == FAIL
3173 || skip_past_comma (& str) == FAIL
3174 || (rm = reg_required_here (& str, 0)) == FAIL
3175 || skip_past_comma (& str) == FAIL
3176 || (rs = reg_required_here (& str, 8)) == FAIL)
3177 inst.error = BAD_ARGS;
3178
3179 else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
3180 inst.error = BAD_PC;
3181
b99bd4ef
NC
3182 else
3183 end_of_line (str);
3184}
3185
3186/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3187 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3188 Error if any register is R15. */
3189
3190static void
a737bd4d 3191do_qadd (char * str)
b99bd4ef
NC
3192{
3193 int rd, rm, rn;
3194
3195 skip_whitespace (str);
3196
3197 if ((rd = reg_required_here (& str, 12)) == FAIL
3198 || skip_past_comma (& str) == FAIL
3199 || (rm = reg_required_here (& str, 0)) == FAIL
3200 || skip_past_comma (& str) == FAIL
3201 || (rn = reg_required_here (& str, 16)) == FAIL)
3202 inst.error = BAD_ARGS;
3203
3204 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
3205 inst.error = BAD_PC;
3206
b99bd4ef
NC
3207 else
3208 end_of_line (str);
3209}
3210
3211/* ARM V5E (el Segundo)
3212 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3213 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3214
3215 These are equivalent to the XScale instructions MAR and MRA,
3216 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3217
3218 Result unpredicatable if Rd or Rn is R15. */
3219
3220static void
a737bd4d 3221do_co_reg2c (char * str)
b99bd4ef
NC
3222{
3223 int rd, rn;
3224
3225 skip_whitespace (str);
3226
3227 if (co_proc_number (& str) == FAIL)
3228 {
3229 if (!inst.error)
3230 inst.error = BAD_ARGS;
3231 return;
3232 }
3233
3234 if (skip_past_comma (& str) == FAIL
3235 || cp_opc_expr (& str, 4, 4) == FAIL)
3236 {
3237 if (!inst.error)
3238 inst.error = BAD_ARGS;
3239 return;
3240 }
3241
3242 if (skip_past_comma (& str) == FAIL
3243 || (rd = reg_required_here (& str, 12)) == FAIL)
3244 {
3245 if (!inst.error)
3246 inst.error = BAD_ARGS;
3247 return;
3248 }
3249
3250 if (skip_past_comma (& str) == FAIL
3251 || (rn = reg_required_here (& str, 16)) == FAIL)
3252 {
3253 if (!inst.error)
3254 inst.error = BAD_ARGS;
3255 return;
3256 }
3257
09d92015
MM
3258 /* Unpredictable result if rd or rn is R15. */
3259 if (rd == REG_PC || rn == REG_PC)
3260 as_tsktsk
3261 (_("Warning: instruction unpredictable when using r15"));
3262
3263 if (skip_past_comma (& str) == FAIL
3264 || cp_reg_required_here (& str, 0) == FAIL)
3265 {
3266 if (!inst.error)
3267 inst.error = BAD_ARGS;
3268 return;
3269 }
3270
3271 end_of_line (str);
3272}
3273
3274/* ARM V5 count-leading-zeroes instruction (argument parse)
3275 CLZ{<cond>} <Rd>, <Rm>
3276 Condition defaults to COND_ALWAYS.
3277 Error if Rd or Rm are R15. */
3278
3279static void
a737bd4d 3280do_clz (char * str)
09d92015
MM
3281{
3282 int rd, rm;
3283
3284 skip_whitespace (str);
3285
3286 if (((rd = reg_required_here (& str, 12)) == FAIL)
3287 || (skip_past_comma (& str) == FAIL)
3288 || ((rm = reg_required_here (& str, 0)) == FAIL))
3289 inst.error = BAD_ARGS;
3290
3291 else if (rd == REG_PC || rm == REG_PC )
3292 inst.error = BAD_PC;
3293
3294 else
3295 end_of_line (str);
3296}
3297
3298/* ARM V5 (argument parse)
3299 LDC2{L} <coproc>, <CRd>, <addressing mode>
3300 STC2{L} <coproc>, <CRd>, <addressing mode>
3301 Instruction is not conditional, and has 0xf in the condition field.
3302 Otherwise, it's the same as LDC/STC. */
3303
3304static void
a737bd4d 3305do_lstc2 (char * str)
09d92015
MM
3306{
3307 skip_whitespace (str);
3308
3309 if (co_proc_number (& str) == FAIL)
3310 {
3311 if (!inst.error)
3312 inst.error = BAD_ARGS;
3313 }
3314 else if (skip_past_comma (& str) == FAIL
3315 || cp_reg_required_here (& str, 12) == FAIL)
3316 {
3317 if (!inst.error)
3318 inst.error = BAD_ARGS;
3319 }
3320 else if (skip_past_comma (& str) == FAIL
3321 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
3322 {
3323 if (! inst.error)
3324 inst.error = BAD_ARGS;
3325 }
3326 else
3327 end_of_line (str);
3328}
3329
3330/* ARM V5 (argument parse)
3331 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3332 Instruction is not conditional, and has 0xf in the condition field.
3333 Otherwise, it's the same as CDP. */
3334
3335static void
a737bd4d 3336do_cdp2 (char * str)
09d92015
MM
3337{
3338 skip_whitespace (str);
3339
3340 if (co_proc_number (& str) == FAIL)
3341 {
3342 if (!inst.error)
3343 inst.error = BAD_ARGS;
3344 return;
3345 }
3346
3347 if (skip_past_comma (& str) == FAIL
3348 || cp_opc_expr (& str, 20,4) == FAIL)
3349 {
3350 if (!inst.error)
3351 inst.error = BAD_ARGS;
3352 return;
3353 }
3354
3355 if (skip_past_comma (& str) == FAIL
3356 || cp_reg_required_here (& str, 12) == FAIL)
3357 {
3358 if (!inst.error)
3359 inst.error = BAD_ARGS;
3360 return;
3361 }
3362
3363 if (skip_past_comma (& str) == FAIL
3364 || cp_reg_required_here (& str, 16) == FAIL)
3365 {
3366 if (!inst.error)
3367 inst.error = BAD_ARGS;
3368 return;
3369 }
3370
3371 if (skip_past_comma (& str) == FAIL
3372 || cp_reg_required_here (& str, 0) == FAIL)
3373 {
3374 if (!inst.error)
3375 inst.error = BAD_ARGS;
3376 return;
3377 }
3378
3379 if (skip_past_comma (& str) == SUCCESS)
3380 {
3381 if (cp_opc_expr (& str, 5, 3) == FAIL)
3382 {
3383 if (!inst.error)
3384 inst.error = BAD_ARGS;
3385 return;
3386 }
3387 }
3388
3389 end_of_line (str);
3390}
3391
3392/* ARM V5 (argument parse)
3393 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3394 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3395 Instruction is not conditional, and has 0xf in the condition field.
3396 Otherwise, it's the same as MCR/MRC. */
3397
3398static void
a737bd4d 3399do_co_reg2 (char * str)
09d92015
MM
3400{
3401 skip_whitespace (str);
3402
3403 if (co_proc_number (& str) == FAIL)
3404 {
3405 if (!inst.error)
3406 inst.error = BAD_ARGS;
3407 return;
3408 }
3409
3410 if (skip_past_comma (& str) == FAIL
3411 || cp_opc_expr (& str, 21, 3) == FAIL)
3412 {
3413 if (!inst.error)
3414 inst.error = BAD_ARGS;
3415 return;
3416 }
3417
3418 if (skip_past_comma (& str) == FAIL
3419 || reg_required_here (& str, 12) == FAIL)
3420 {
3421 if (!inst.error)
3422 inst.error = BAD_ARGS;
3423 return;
3424 }
3425
3426 if (skip_past_comma (& str) == FAIL
3427 || cp_reg_required_here (& str, 16) == FAIL)
3428 {
3429 if (!inst.error)
3430 inst.error = BAD_ARGS;
3431 return;
3432 }
3433
3434 if (skip_past_comma (& str) == FAIL
3435 || cp_reg_required_here (& str, 0) == FAIL)
3436 {
3437 if (!inst.error)
3438 inst.error = BAD_ARGS;
3439 return;
3440 }
3441
3442 if (skip_past_comma (& str) == SUCCESS)
3443 {
3444 if (cp_opc_expr (& str, 5, 3) == FAIL)
3445 {
3446 if (!inst.error)
3447 inst.error = BAD_ARGS;
3448 return;
3449 }
3450 }
3451
3452 end_of_line (str);
3453}
3454
a737bd4d
NC
3455static void
3456do_bx (char * str)
3457{
3458 int reg;
3459
3460 skip_whitespace (str);
3461
3462 if ((reg = reg_required_here (&str, 0)) == FAIL)
3463 {
3464 inst.error = BAD_ARGS;
3465 return;
3466 }
3467
3468 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
3469 if (reg == REG_PC)
3470 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
3471
3472 end_of_line (str);
3473}
3474
09d92015 3475/* ARM v5TEJ. Jump to Jazelle code. */
a737bd4d 3476
09d92015 3477static void
a737bd4d 3478do_bxj (char * str)
09d92015
MM
3479{
3480 int reg;
3481
3482 skip_whitespace (str);
3483
3484 if ((reg = reg_required_here (&str, 0)) == FAIL)
3485 {
3486 inst.error = BAD_ARGS;
3487 return;
3488 }
3489
a737bd4d
NC
3490 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3491 if (reg == REG_PC)
3492 as_tsktsk (_("use of r15 in bxj is not really useful"));
3493
3494 end_of_line (str);
3495}
3496
3497/* ARM V6 umaal (argument parse). */
3498
3499static void
3500do_umaal (char * str)
3501{
3502 int rdlo, rdhi, rm, rs;
3503
3504 skip_whitespace (str);
3505 if ((rdlo = reg_required_here (& str, 12)) == FAIL
3506 || skip_past_comma (& str) == FAIL
3507 || (rdhi = reg_required_here (& str, 16)) == FAIL
3508 || skip_past_comma (& str) == FAIL
3509 || (rm = reg_required_here (& str, 0)) == FAIL
3510 || skip_past_comma (& str) == FAIL
3511 || (rs = reg_required_here (& str, 8)) == FAIL)
3512 {
3513 inst.error = BAD_ARGS;
3514 return;
3515 }
3516
3517 if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
3518 {
3519 inst.error = BAD_PC;
3520 return;
3521 }
3522
3523 end_of_line (str);
3524}
3525
3526/* ARM V6 strex (argument parse). */
3527
3528static void
3529do_strex (char * str)
3530{
3531 int rd, rm, rn;
3532
3533 /* Parse Rd, Rm,. */
3534 skip_whitespace (str);
3535 if ((rd = reg_required_here (& str, 12)) == FAIL
3536 || skip_past_comma (& str) == FAIL
3537 || (rm = reg_required_here (& str, 0)) == FAIL
3538 || skip_past_comma (& str) == FAIL)
3539 {
3540 inst.error = BAD_ARGS;
3541 return;
3542 }
3543 if (rd == REG_PC || rm == REG_PC)
3544 {
3545 inst.error = BAD_PC;
3546 return;
3547 }
3548 if (rd == rm)
3549 {
3550 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3551 return;
3552 }
3553
3554 /* Skip past '['. */
3555 if ((strlen (str) >= 1)
3556 && strncmp (str, "[", 1) == 0)
3557 str += 1;
3558
3559 skip_whitespace (str);
3560
3561 /* Parse Rn. */
3562 if ((rn = reg_required_here (& str, 16)) == FAIL)
3563 {
3564 inst.error = BAD_ARGS;
3565 return;
3566 }
3567 else if (rn == REG_PC)
3568 {
3569 inst.error = BAD_PC;
3570 return;
3571 }
3572 if (rd == rn)
3573 {
3574 inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
3575 return;
3576 }
3577 skip_whitespace (str);
3578
3579 /* Skip past ']'. */
3580 if ((strlen (str) >= 1)
3581 && strncmp (str, "]", 1) == 0)
3582 str += 1;
3583
3584 end_of_line (str);
3585}
3586
3587/* KIND indicates what kind of shifts are accepted. */
3588
3589static int
3590decode_shift (char ** str, int kind)
3591{
3592 const struct asm_shift_name * shift;
3593 char * p;
3594 char c;
3595
3596 skip_whitespace (* str);
3597
3598 for (p = * str; ISALPHA (* p); p ++)
3599 ;
3600
3601 if (p == * str)
3602 {
3603 inst.error = _("shift expression expected");
3604 return FAIL;
3605 }
3606
3607 c = * p;
3608 * p = '\0';
3609 shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
3610 * p = c;
3611
3612 if (shift == NULL)
3613 {
3614 inst.error = _("shift expression expected");
3615 return FAIL;
3616 }
3617
3618 assert (shift->properties->index == shift_properties[shift->properties->index].index);
3619
3620 if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
3621 && shift->properties->index != SHIFT_LSL
3622 && shift->properties->index != SHIFT_ASR)
3623 {
3624 inst.error = _("'LSL' or 'ASR' required");
3625 return FAIL;
3626 }
3627 else if (kind == SHIFT_LSL_IMMEDIATE
3628 && shift->properties->index != SHIFT_LSL)
3629 {
3630 inst.error = _("'LSL' required");
3631 return FAIL;
3632 }
3633 else if (kind == SHIFT_ASR_IMMEDIATE
3634 && shift->properties->index != SHIFT_ASR)
3635 {
3636 inst.error = _("'ASR' required");
3637 return FAIL;
3638 }
3639
3640 if (shift->properties->index == SHIFT_RRX)
3641 {
3642 * str = p;
3643 inst.instruction |= shift->properties->bit_field;
3644 return SUCCESS;
3645 }
3646
3647 skip_whitespace (p);
3648
3649 if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
3650 {
3651 inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
3652 * str = p;
3653 return SUCCESS;
3654 }
3655 else if (! is_immediate_prefix (* p))
3656 {
3657 inst.error = (NO_SHIFT_RESTRICT
3658 ? _("shift requires register or #expression")
3659 : _("shift requires #expression"));
3660 * str = p;
3661 return FAIL;
3662 }
3663
3664 inst.error = NULL;
3665 p ++;
3666
3667 if (my_get_expression (& inst.reloc.exp, & p))
3668 return FAIL;
3669
3670 /* Validate some simple #expressions. */
3671 if (inst.reloc.exp.X_op == O_constant)
3672 {
3673 unsigned num = inst.reloc.exp.X_add_number;
3674
3675 /* Reject operations greater than 32. */
3676 if (num > 32
3677 /* Reject a shift of 0 unless the mode allows it. */
3678 || (num == 0 && shift->properties->allows_0 == 0)
3679 /* Reject a shift of 32 unless the mode allows it. */
3680 || (num == 32 && shift->properties->allows_32 == 0)
3681 )
3682 {
3683 /* As a special case we allow a shift of zero for
3684 modes that do not support it to be recoded as an
3685 logical shift left of zero (ie nothing). We warn
3686 about this though. */
3687 if (num == 0)
3688 {
3689 as_warn (_("shift of 0 ignored."));
3690 shift = & shift_names[0];
3691 assert (shift->properties->index == SHIFT_LSL);
3692 }
3693 else
3694 {
3695 inst.error = _("invalid immediate shift");
3696 return FAIL;
3697 }
3698 }
3699
3700 /* Shifts of 32 are encoded as 0, for those shifts that
3701 support it. */
3702 if (num == 32)
3703 num = 0;
3704
3705 inst.instruction |= (num << 7) | shift->properties->bit_field;
3706 }
3707 else
3708 {
3709 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
3710 inst.reloc.pc_rel = 0;
3711 inst.instruction |= shift->properties->bit_field;
3712 }
3713
3714 * str = p;
3715 return SUCCESS;
09d92015
MM
3716}
3717
09d92015 3718static void
a737bd4d 3719do_sat (char ** str, int bias)
09d92015 3720{
a737bd4d
NC
3721 int rd, rm;
3722 expressionS expr;
09d92015 3723
a737bd4d 3724 skip_whitespace (*str);
09d92015 3725
a737bd4d
NC
3726 /* Parse <Rd>, field. */
3727 if ((rd = reg_required_here (str, 12)) == FAIL
3728 || skip_past_comma (str) == FAIL)
09d92015
MM
3729 {
3730 inst.error = BAD_ARGS;
a737bd4d 3731 return;
09d92015 3732 }
a737bd4d 3733 if (rd == REG_PC)
09d92015
MM
3734 {
3735 inst.error = BAD_PC;
3736 return;
3737 }
3738
a737bd4d
NC
3739 /* Parse #<immed>, field. */
3740 if (is_immediate_prefix (**str))
3741 (*str)++;
3742 else
09d92015 3743 {
a737bd4d 3744 inst.error = _("immediate expression expected");
09d92015
MM
3745 return;
3746 }
a737bd4d 3747 if (my_get_expression (&expr, str))
09d92015 3748 {
a737bd4d 3749 inst.error = _("bad expression");
09d92015
MM
3750 return;
3751 }
a737bd4d 3752 if (expr.X_op != O_constant)
09d92015 3753 {
a737bd4d 3754 inst.error = _("constant expression expected");
09d92015
MM
3755 return;
3756 }
a737bd4d
NC
3757 if (expr.X_add_number + bias < 0
3758 || expr.X_add_number + bias > 31)
3759 {
3760 inst.error = _("immediate value out of range");
3761 return;
3762 }
3763 inst.instruction |= (expr.X_add_number + bias) << 16;
3764 if (skip_past_comma (str) == FAIL)
09d92015
MM
3765 {
3766 inst.error = BAD_ARGS;
3767 return;
3768 }
a737bd4d
NC
3769
3770 /* Parse <Rm> field. */
3771 if ((rm = reg_required_here (str, 0)) == FAIL)
09d92015 3772 {
a737bd4d 3773 inst.error = BAD_ARGS;
09d92015
MM
3774 return;
3775 }
a737bd4d 3776 if (rm == REG_PC)
09d92015 3777 {
a737bd4d 3778 inst.error = BAD_PC;
09d92015
MM
3779 return;
3780 }
09d92015 3781
a737bd4d
NC
3782 if (skip_past_comma (str) == SUCCESS)
3783 decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
09d92015
MM
3784}
3785
a737bd4d 3786/* ARM V6 ssat (argument parse). */
09d92015
MM
3787
3788static void
a737bd4d 3789do_ssat (char * str)
09d92015
MM
3790{
3791 do_sat (&str, /*bias=*/-1);
3792 end_of_line (str);
3793}
3794
a737bd4d 3795/* ARM V6 usat (argument parse). */
09d92015
MM
3796
3797static void
a737bd4d 3798do_usat (char * str)
09d92015
MM
3799{
3800 do_sat (&str, /*bias=*/0);
3801 end_of_line (str);
3802}
3803
3804static void
a737bd4d 3805do_sat16 (char ** str, int bias)
09d92015
MM
3806{
3807 int rd, rm;
3808 expressionS expr;
3809
3810 skip_whitespace (*str);
a737bd4d
NC
3811
3812 /* Parse the <Rd> field. */
09d92015
MM
3813 if ((rd = reg_required_here (str, 12)) == FAIL
3814 || skip_past_comma (str) == FAIL)
3815 {
3816 inst.error = BAD_ARGS;
3817 return;
3818 }
3819 if (rd == REG_PC)
3820 {
3821 inst.error = BAD_PC;
3822 return;
3823 }
3824
a737bd4d 3825 /* Parse #<immed>, field. */
09d92015
MM
3826 if (is_immediate_prefix (**str))
3827 (*str)++;
3828 else
3829 {
3830 inst.error = _("immediate expression expected");
3831 return;
3832 }
3833 if (my_get_expression (&expr, str))
3834 {
3835 inst.error = _("bad expression");
3836 return;
3837 }
3838 if (expr.X_op != O_constant)
3839 {
3840 inst.error = _("constant expression expected");
3841 return;
3842 }
3843 if (expr.X_add_number + bias < 0
a737bd4d 3844 || expr.X_add_number + bias > 15)
09d92015
MM
3845 {
3846 inst.error = _("immediate value out of range");
3847 return;
3848 }
3849 inst.instruction |= (expr.X_add_number + bias) << 16;
3850 if (skip_past_comma (str) == FAIL)
3851 {
3852 inst.error = BAD_ARGS;
3853 return;
3854 }
3855
a737bd4d 3856 /* Parse <Rm> field. */
09d92015
MM
3857 if ((rm = reg_required_here (str, 0)) == FAIL)
3858 {
3859 inst.error = BAD_ARGS;
3860 return;
3861 }
3862 if (rm == REG_PC)
3863 {
3864 inst.error = BAD_PC;
3865 return;
3866 }
09d92015
MM
3867}
3868
a737bd4d 3869/* ARM V6 ssat16 (argument parse). */
09d92015
MM
3870
3871static void
a737bd4d 3872do_ssat16 (char * str)
09d92015
MM
3873{
3874 do_sat16 (&str, /*bias=*/-1);
3875 end_of_line (str);
3876}
3877
3878static void
a737bd4d 3879do_usat16 (char * str)
09d92015
MM
3880{
3881 do_sat16 (&str, /*bias=*/0);
3882 end_of_line (str);
3883}
3884
3885static void
a737bd4d 3886do_cps_mode (char ** str)
09d92015 3887{
09d92015
MM
3888 expressionS expr;
3889
3890 skip_whitespace (*str);
3891
a737bd4d 3892 if (! is_immediate_prefix (**str))
09d92015
MM
3893 {
3894 inst.error = _("immediate expression expected");
3895 return;
3896 }
a737bd4d
NC
3897
3898 (*str)++; /* Strip off the immediate signifier. */
09d92015
MM
3899 if (my_get_expression (&expr, str))
3900 {
3901 inst.error = _("bad expression");
3902 return;
3903 }
a737bd4d 3904
09d92015
MM
3905 if (expr.X_op != O_constant)
3906 {
3907 inst.error = _("constant expression expected");
3908 return;
3909 }
09d92015 3910
a737bd4d
NC
3911 /* The mode is a 5 bit field. Valid values are 0-31. */
3912 if (((unsigned) expr.X_add_number) > 31
3913 || (inst.reloc.exp.X_add_number) < 0)
09d92015 3914 {
a737bd4d 3915 inst.error = _("invalid constant");
09d92015
MM
3916 return;
3917 }
a737bd4d
NC
3918
3919 inst.instruction |= expr.X_add_number;
09d92015
MM
3920}
3921
a737bd4d 3922/* ARM V6 srs (argument parse). */
09d92015
MM
3923
3924static void
a737bd4d 3925do_srs (char * str)
09d92015
MM
3926{
3927 char *exclam;
3928 skip_whitespace (str);
3929 exclam = strchr (str, '!');
3930 if (exclam)
3931 *exclam = '\0';
3932 do_cps_mode (&str);
3933 if (exclam)
3934 *exclam = '!';
a737bd4d 3935 if (*str == '!')
09d92015
MM
3936 {
3937 inst.instruction |= WRITE_BACK;
3938 str++;
3939 }
3940 end_of_line (str);
3941}
3942
a737bd4d 3943/* ARM V6 SMMUL (argument parse). */
09d92015
MM
3944
3945static void
a737bd4d 3946do_smmul (char * str)
09d92015
MM
3947{
3948 int rd, rm, rs;
a737bd4d 3949
09d92015
MM
3950 skip_whitespace (str);
3951 if ((rd = reg_required_here (&str, 16)) == FAIL
3952 || skip_past_comma (&str) == FAIL
3953 || (rm = reg_required_here (&str, 0)) == FAIL
3954 || skip_past_comma (&str) == FAIL
3955 || (rs = reg_required_here (&str, 8)) == FAIL)
3956 {
3957 inst.error = BAD_ARGS;
3958 return;
3959 }
3960
a737bd4d 3961 if ( rd == REG_PC
09d92015
MM
3962 || rm == REG_PC
3963 || rs == REG_PC)
3964 {
3965 inst.error = BAD_PC;
3966 return;
3967 }
3968
3969 end_of_line (str);
09d92015
MM
3970}
3971
a737bd4d 3972/* ARM V6 SMLALD (argument parse). */
09d92015
MM
3973
3974static void
a737bd4d 3975do_smlald (char * str)
09d92015
MM
3976{
3977 int rdlo, rdhi, rm, rs;
a737bd4d 3978
09d92015
MM
3979 skip_whitespace (str);
3980 if ((rdlo = reg_required_here (&str, 12)) == FAIL
3981 || skip_past_comma (&str) == FAIL
3982 || (rdhi = reg_required_here (&str, 16)) == FAIL
3983 || skip_past_comma (&str) == FAIL
3984 || (rm = reg_required_here (&str, 0)) == FAIL
3985 || skip_past_comma (&str) == FAIL
3986 || (rs = reg_required_here (&str, 8)) == FAIL)
3987 {
3988 inst.error = BAD_ARGS;
3989 return;
3990 }
3991
a737bd4d
NC
3992 if ( rdlo == REG_PC
3993 || rdhi == REG_PC
09d92015
MM
3994 || rm == REG_PC
3995 || rs == REG_PC)
3996 {
3997 inst.error = BAD_PC;
3998 return;
3999 }
4000
4001 end_of_line (str);
4002}
4003
a737bd4d 4004/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
09d92015
MM
4005 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
4006
a737bd4d
NC
4007static void
4008do_smlad (char * str)
09d92015
MM
4009{
4010 int rd, rm, rs, rn;
a737bd4d 4011
09d92015
MM
4012 skip_whitespace (str);
4013 if ((rd = reg_required_here (&str, 16)) == FAIL
4014 || skip_past_comma (&str) == FAIL
4015 || (rm = reg_required_here (&str, 0)) == FAIL
4016 || skip_past_comma (&str) == FAIL
4017 || (rs = reg_required_here (&str, 8)) == FAIL
4018 || skip_past_comma (&str) == FAIL
4019 || (rn = reg_required_here (&str, 12)) == FAIL)
4020 {
4021 inst.error = BAD_ARGS;
4022 return;
4023 }
a737bd4d
NC
4024
4025 if ( rd == REG_PC
4026 || rn == REG_PC
09d92015
MM
4027 || rs == REG_PC
4028 || rm == REG_PC)
4029 {
4030 inst.error = BAD_PC;
4031 return;
4032 }
4033
4034 end_of_line (str);
09d92015
MM
4035}
4036
4037/* Returns true if the endian-specifier indicates big-endianness. */
4038
4039static int
a737bd4d 4040do_endian_specifier (char * str)
09d92015
MM
4041{
4042 int big_endian = 0;
4043
4044 skip_whitespace (str);
4045 if (strlen (str) < 2)
4046 inst.error = _("missing endian specifier");
4047 else if (strncasecmp (str, "BE", 2) == 0)
4048 {
4049 str += 2;
4050 big_endian = 1;
4051 }
4052 else if (strncasecmp (str, "LE", 2) == 0)
4053 str += 2;
4054 else
4055 inst.error = _("valid endian specifiers are be or le");
4056
4057 end_of_line (str);
4058
4059 return big_endian;
4060}
4061
a737bd4d
NC
4062/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
4063 preserving the other bits.
4064
4065 setend <endian_specifier>, where <endian_specifier> is either
4066 BE or LE. */
4067
4068static void
4069do_setend (char * str)
4070{
4071 if (do_endian_specifier (str))
4072 inst.instruction |= 0x200;
4073}
4074
09d92015
MM
4075/* ARM V6 SXTH.
4076
4077 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
4078 Condition defaults to COND_ALWAYS.
a737bd4d 4079 Error if any register uses R15. */
09d92015 4080
a737bd4d
NC
4081static void
4082do_sxth (char * str)
09d92015
MM
4083{
4084 int rd, rm;
4085 expressionS expr;
4086 int rotation_clear_mask = 0xfffff3ff;
4087 int rotation_eight_mask = 0x00000400;
4088 int rotation_sixteen_mask = 0x00000800;
4089 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4090
09d92015
MM
4091 skip_whitespace (str);
4092 if ((rd = reg_required_here (&str, 12)) == FAIL
4093 || skip_past_comma (&str) == FAIL
4094 || (rm = reg_required_here (&str, 0)) == FAIL)
4095 {
4096 inst.error = BAD_ARGS;
4097 return;
4098 }
4099
4100 else if (rd == REG_PC || rm == REG_PC)
4101 {
4102 inst.error = BAD_PC;
4103 return;
4104 }
a737bd4d
NC
4105
4106 /* Zero out the rotation field. */
09d92015 4107 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4108
4109 /* Check for lack of optional rotation field. */
09d92015
MM
4110 if (skip_past_comma (&str) == FAIL)
4111 {
4112 end_of_line (str);
4113 return;
4114 }
a737bd4d
NC
4115
4116 /* Move past 'ROR'. */
09d92015
MM
4117 skip_whitespace (str);
4118 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4119 str += 3;
09d92015
MM
4120 else
4121 {
4122 inst.error = _("missing rotation field after comma");
4123 return;
4124 }
a737bd4d
NC
4125
4126 /* Get the immediate constant. */
09d92015
MM
4127 skip_whitespace (str);
4128 if (is_immediate_prefix (* str))
4129 str++;
4130 else
4131 {
4132 inst.error = _("immediate expression expected");
4133 return;
4134 }
a737bd4d 4135
09d92015
MM
4136 if (my_get_expression (&expr, &str))
4137 {
4138 inst.error = _("bad expression");
4139 return;
4140 }
4141
4142 if (expr.X_op != O_constant)
4143 {
4144 inst.error = _("constant expression expected");
4145 return;
4146 }
a737bd4d
NC
4147
4148 switch (expr.X_add_number)
09d92015
MM
4149 {
4150 case 0:
a737bd4d 4151 /* Rotation field has already been zeroed. */
09d92015
MM
4152 break;
4153 case 8:
4154 inst.instruction |= rotation_eight_mask;
4155 break;
4156
4157 case 16:
4158 inst.instruction |= rotation_sixteen_mask;
4159 break;
a737bd4d 4160
09d92015
MM
4161 case 24:
4162 inst.instruction |= rotation_twenty_four_mask;
4163 break;
4164
4165 default:
4166 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4167 break;
4168 }
4169
4170 end_of_line (str);
09d92015
MM
4171}
4172
4173/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
4174 extends it to 32-bits, and adds the result to a value in another
4175 register. You can specify a rotation by 0, 8, 16, or 24 bits
4176 before extracting the 16-bit value.
4177 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
4178 Condition defaults to COND_ALWAYS.
a737bd4d 4179 Error if any register uses R15. */
09d92015 4180
a737bd4d
NC
4181static void
4182do_sxtah (char * str)
09d92015
MM
4183{
4184 int rd, rn, rm;
4185 expressionS expr;
4186 int rotation_clear_mask = 0xfffff3ff;
4187 int rotation_eight_mask = 0x00000400;
4188 int rotation_sixteen_mask = 0x00000800;
4189 int rotation_twenty_four_mask = 0x00000c00;
a737bd4d 4190
09d92015
MM
4191 skip_whitespace (str);
4192 if ((rd = reg_required_here (&str, 12)) == FAIL
4193 || skip_past_comma (&str) == FAIL
4194 || (rn = reg_required_here (&str, 16)) == FAIL
4195 || skip_past_comma (&str) == FAIL
4196 || (rm = reg_required_here (&str, 0)) == FAIL)
4197 {
4198 inst.error = BAD_ARGS;
4199 return;
4200 }
4201
4202 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
4203 {
4204 inst.error = BAD_PC;
4205 return;
4206 }
a737bd4d
NC
4207
4208 /* Zero out the rotation field. */
09d92015 4209 inst.instruction &= rotation_clear_mask;
a737bd4d
NC
4210
4211 /* Check for lack of optional rotation field. */
09d92015
MM
4212 if (skip_past_comma (&str) == FAIL)
4213 {
4214 end_of_line (str);
4215 return;
4216 }
a737bd4d
NC
4217
4218 /* Move past 'ROR'. */
09d92015
MM
4219 skip_whitespace (str);
4220 if (strncasecmp (str, "ROR", 3) == 0)
a737bd4d 4221 str += 3;
09d92015
MM
4222 else
4223 {
4224 inst.error = _("missing rotation field after comma");
4225 return;
4226 }
a737bd4d
NC
4227
4228 /* Get the immediate constant. */
09d92015
MM
4229 skip_whitespace (str);
4230 if (is_immediate_prefix (* str))
4231 str++;
4232 else
4233 {
4234 inst.error = _("immediate expression expected");
4235 return;
4236 }
a737bd4d 4237
09d92015
MM
4238 if (my_get_expression (&expr, &str))
4239 {
4240 inst.error = _("bad expression");
4241 return;
4242 }
4243
4244 if (expr.X_op != O_constant)
4245 {
4246 inst.error = _("constant expression expected");
4247 return;
4248 }
a737bd4d
NC
4249
4250 switch (expr.X_add_number)
09d92015
MM
4251 {
4252 case 0:
a737bd4d 4253 /* Rotation field has already been zeroed. */
09d92015
MM
4254 break;
4255
4256 case 8:
4257 inst.instruction |= rotation_eight_mask;
4258 break;
4259
4260 case 16:
4261 inst.instruction |= rotation_sixteen_mask;
4262 break;
a737bd4d 4263
09d92015
MM
4264 case 24:
4265 inst.instruction |= rotation_twenty_four_mask;
4266 break;
4267
4268 default:
4269 inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
4270 break;
4271 }
4272
4273 end_of_line (str);
09d92015 4274}
a737bd4d 4275
09d92015
MM
4276
4277/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
4278 word at the specified address and the following word
a737bd4d 4279 respectively.
09d92015 4280 Unconditionally executed.
a737bd4d 4281 Error if Rn is R15. */
09d92015
MM
4282
4283static void
a737bd4d 4284do_rfe (char * str)
09d92015
MM
4285{
4286 int rn;
4287
4288 skip_whitespace (str);
a737bd4d 4289
09d92015
MM
4290 if ((rn = reg_required_here (&str, 16)) == FAIL)
4291 return;
b99bd4ef 4292
09d92015 4293 if (rn == REG_PC)
b99bd4ef 4294 {
09d92015 4295 inst.error = BAD_PC;
b99bd4ef
NC
4296 return;
4297 }
4298
09d92015 4299 skip_whitespace (str);
a737bd4d 4300
09d92015
MM
4301 if (*str == '!')
4302 {
4303 inst.instruction |= WRITE_BACK;
4304 str++;
4305 }
b99bd4ef
NC
4306 end_of_line (str);
4307}
4308
09d92015
MM
4309/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
4310 register (argument parse).
4311 REV{<cond>} Rd, Rm.
4312 Condition defaults to COND_ALWAYS.
a737bd4d 4313 Error if Rd or Rm are R15. */
b99bd4ef
NC
4314
4315static void
a737bd4d 4316do_rev (char * str)
b99bd4ef
NC
4317{
4318 int rd, rm;
4319
b99bd4ef
NC
4320 skip_whitespace (str);
4321
09d92015
MM
4322 if ((rd = reg_required_here (&str, 12)) == FAIL
4323 || skip_past_comma (&str) == FAIL
4324 || (rm = reg_required_here (&str, 0)) == FAIL)
b99bd4ef
NC
4325 inst.error = BAD_ARGS;
4326
09d92015 4327 else if (rd == REG_PC || rm == REG_PC)
b99bd4ef
NC
4328 inst.error = BAD_PC;
4329
4330 else
4331 end_of_line (str);
4332}
4333
09d92015 4334/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
a737bd4d 4335 QADD16{<cond>} <Rd>, <Rn>, <Rm>
09d92015
MM
4336 Condition defaults to COND_ALWAYS.
4337 Error if Rd, Rn or Rm are R15. */
b99bd4ef
NC
4338
4339static void
a737bd4d 4340do_qadd16 (char * str)
b99bd4ef 4341{
09d92015
MM
4342 int rd, rm, rn;
4343
b99bd4ef
NC
4344 skip_whitespace (str);
4345
09d92015
MM
4346 if ((rd = reg_required_here (&str, 12)) == FAIL
4347 || skip_past_comma (&str) == FAIL
4348 || (rn = reg_required_here (&str, 16)) == FAIL
4349 || skip_past_comma (&str) == FAIL
4350 || (rm = reg_required_here (&str, 0)) == FAIL)
4351 inst.error = BAD_ARGS;
4352
4353 else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4354 inst.error = BAD_PC;
4355
b99bd4ef
NC
4356 else
4357 end_of_line (str);
4358}
4359
b99bd4ef 4360static void
a737bd4d 4361do_pkh_core (char * str, int shift)
b99bd4ef 4362{
09d92015 4363 int rd, rn, rm;
b99bd4ef 4364
09d92015
MM
4365 skip_whitespace (str);
4366 if (((rd = reg_required_here (&str, 12)) == FAIL)
4367 || (skip_past_comma (&str) == FAIL)
4368 || ((rn = reg_required_here (&str, 16)) == FAIL)
4369 || (skip_past_comma (&str) == FAIL)
4370 || ((rm = reg_required_here (&str, 0)) == FAIL))
b99bd4ef 4371 {
09d92015 4372 inst.error = BAD_ARGS;
b99bd4ef
NC
4373 return;
4374 }
4375
09d92015 4376 else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
b99bd4ef 4377 {
09d92015 4378 inst.error = BAD_PC;
b99bd4ef
NC
4379 return;
4380 }
4381
a737bd4d
NC
4382 /* Check for optional shift immediate constant. */
4383 if (skip_past_comma (&str) == FAIL)
b99bd4ef 4384 {
09d92015
MM
4385 if (shift == SHIFT_ASR_IMMEDIATE)
4386 {
4387 /* If the shift specifier is ommited, turn the instruction
4388 into pkhbt rd, rm, rn. First, switch the instruction
4389 code, and clear the rn and rm fields. */
4390 inst.instruction &= 0xfff0f010;
4391 /* Now, re-encode the registers. */
4392 inst.instruction |= (rm << 16) | rn;
4393 }
b99bd4ef
NC
4394 return;
4395 }
4396
09d92015
MM
4397 decode_shift (&str, shift);
4398}
4399
a737bd4d
NC
4400/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
4401 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
4402 Condition defaults to COND_ALWAYS.
4403 Error if Rd, Rn or Rm are R15. */
4404
4405static void
4406do_pkhbt (char * str)
4407{
4408 do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
4409}
4410
4411/* ARM V6 PKHTB (Argument Parse). */
4412
4413static void
4414do_pkhtb (char * str)
4415{
4416 do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
4417}
4418
09d92015 4419/* ARM V6 Load Register Exclusive instruction (argument parse).
0dd132b6 4420 LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
09d92015 4421 Condition defaults to COND_ALWAYS.
a737bd4d
NC
4422 Error if Rd or Rn are R15.
4423 See ARMARMv6 A4.1.27: LDREX. */
09d92015
MM
4424
4425static void
a737bd4d 4426do_ldrex (char * str)
09d92015
MM
4427{
4428 int rd, rn;
4429
4430 skip_whitespace (str);
4431
a737bd4d 4432 /* Parse Rd. */
09d92015
MM
4433 if (((rd = reg_required_here (&str, 12)) == FAIL)
4434 || (skip_past_comma (&str) == FAIL))
b99bd4ef 4435 {
09d92015 4436 inst.error = BAD_ARGS;
b99bd4ef
NC
4437 return;
4438 }
09d92015 4439 else if (rd == REG_PC)
b99bd4ef 4440 {
09d92015 4441 inst.error = BAD_PC;
b99bd4ef
NC
4442 return;
4443 }
a737bd4d 4444 skip_whitespace (str);
b99bd4ef 4445
a737bd4d
NC
4446 /* Skip past '['. */
4447 if ((strlen (str) >= 1)
09d92015 4448 &&strncmp (str, "[", 1) == 0)
a737bd4d
NC
4449 str += 1;
4450 skip_whitespace (str);
09d92015 4451
a737bd4d 4452 /* Parse Rn. */
09d92015 4453 if ((rn = reg_required_here (&str, 16)) == FAIL)
b99bd4ef 4454 {
09d92015
MM
4455 inst.error = BAD_ARGS;
4456 return;
b99bd4ef 4457 }
09d92015
MM
4458 else if (rn == REG_PC)
4459 {
4460 inst.error = BAD_PC;
4461 return;
4462 }
a737bd4d 4463 skip_whitespace (str);
b99bd4ef 4464
a737bd4d
NC
4465 /* Skip past ']'. */
4466 if ((strlen (str) >= 1)
09d92015 4467 && strncmp (str, "]", 1) == 0)
a737bd4d
NC
4468 str += 1;
4469
b99bd4ef
NC
4470 end_of_line (str);
4471}
4472
09d92015 4473/* ARM V6 change processor state instruction (argument parse)
a737bd4d 4474 CPS, CPSIE, CSPID . */
b99bd4ef
NC
4475
4476static void
a737bd4d 4477do_cps (char * str)
b99bd4ef 4478{
09d92015
MM
4479 do_cps_mode (&str);
4480 end_of_line (str);
4481}
b99bd4ef 4482
09d92015 4483static void
a737bd4d 4484do_cps_flags (char ** str, int thumb_p)
ea6ef066 4485{
a737bd4d
NC
4486 struct cps_flag
4487 {
09d92015
MM
4488 char character;
4489 unsigned long arm_value;
4490 unsigned long thumb_value;
4491 };
a737bd4d
NC
4492 static struct cps_flag flag_table[] =
4493 {
09d92015
MM
4494 {'a', 0x100, 0x4 },
4495 {'i', 0x080, 0x2 },
4496 {'f', 0x040, 0x1 }
4497 };
ea6ef066 4498
09d92015 4499 int saw_a_flag = 0;
ea6ef066 4500
09d92015
MM
4501 skip_whitespace (*str);
4502
a737bd4d 4503 /* Get the a, f and i flags. */
09d92015 4504 while (**str && **str != ',')
ea6ef066 4505 {
09d92015
MM
4506 struct cps_flag *p;
4507 struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
a737bd4d 4508
09d92015
MM
4509 for (p = flag_table; p < q; ++p)
4510 if (strncasecmp (*str, &p->character, 1) == 0)
4511 {
4512 inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
4513 saw_a_flag = 1;
4514 break;
4515 }
4516 if (p == q)
4517 {
4518 inst.error = _("unrecognized flag");
4519 return;
4520 }
4521 (*str)++;
ea6ef066 4522 }
a737bd4d
NC
4523
4524 if (!saw_a_flag)
4525 inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
4526}
4527
4528static void
4529do_cpsi (char * str)
4530{
4531 do_cps_flags (&str, /*thumb_p=*/0);
4532
4533 if (skip_past_comma (&str) == SUCCESS)
4534 {
4535 skip_whitespace (str);
4536 do_cps_mode (&str);
4537 }
4538 end_of_line (str);
ea6ef066
RE
4539}
4540
b05fe5cf
ZW
4541/* ARM V6T2 bitfield manipulation instructions. */
4542
4543static int
4544five_bit_unsigned_immediate (char **str)
4545{
4546 expressionS expr;
4547
4548 skip_whitespace (*str);
4549 if (!is_immediate_prefix (**str))
4550 {
4551 inst.error = _("immediate expression expected");
4552 return -1;
4553 }
4554 (*str)++;
4555 if (my_get_expression (&expr, str))
4556 {
4557 inst.error = _("bad expression");
4558 return -1;
4559 }
4560 if (expr.X_op != O_constant)
4561 {
4562 inst.error = _("constant expression expected");
4563 return -1;
4564 }
4565 if (expr.X_add_number < 0 || expr.X_add_number > 32)
4566 {
4567 inst.error = _("immediate value out of range");
4568 return -1;
4569 }
4570
4571 return expr.X_add_number;
4572}
4573
4574static void
4575bfci_lsb_and_width (char *str)
4576{
4577 int lsb, width;
4578
4579 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4580 return;
4581
4582 if (skip_past_comma (&str) == FAIL)
4583 {
4584 inst.error = BAD_ARGS;
4585 return;
4586 }
4587 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4588 return;
4589
4590 end_of_line (str);
4591
4592 if (width == 0 || lsb == 32)
4593 {
4594 inst.error = _("immediate value out of range");
4595 return;
4596 }
4597 else if (width + lsb > 32)
4598 {
4599 inst.error = _("bit-field extends past end of register");
4600 return;
4601 }
4602
4603 /* Convert to LSB/MSB and write to register. */
4604 inst.instruction |= lsb << 7;
4605 inst.instruction |= (width + lsb - 1) << 16;
4606}
4607
4608static void
4609do_bfc (char *str)
4610{
4611 int rd;
4612
4613 /* Rd. */
4614 skip_whitespace (str);
4615 if (((rd = reg_required_here (&str, 12)) == FAIL)
4616 || (skip_past_comma (&str) == FAIL))
4617 {
4618 inst.error = BAD_ARGS;
4619 return;
4620 }
4621 else if (rd == REG_PC)
4622 {
4623 inst.error = BAD_PC;
4624 return;
4625 }
4626
4627 bfci_lsb_and_width (str);
4628}
4629
4630static void
4631do_bfi (char *str)
4632{
4633 int rd, rm;
4634
4635 /* Rd. */
4636 skip_whitespace (str);
4637 if (((rd = reg_required_here (&str, 12)) == FAIL)
4638 || (skip_past_comma (&str) == FAIL))
4639 {
4640 inst.error = BAD_ARGS;
4641 return;
4642 }
4643 else if (rd == REG_PC)
4644 {
4645 inst.error = BAD_PC;
4646 return;
4647 }
4648
4649 /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
4650 skip_whitespace (str);
4651 if (is_immediate_prefix (*str))
4652 {
4653 expressionS expr;
4654 str++;
4655 if (my_get_expression (&expr, &str))
4656 {
4657 inst.error = _("bad expression");
4658 return;
4659 }
4660 if (expr.X_op != O_constant)
4661 {
4662 inst.error = _("constant expression expected");
4663 return;
4664 }
4665 if (expr.X_add_number != 0)
4666 {
4667 inst.error = _("immediate value out of range");
4668 return;
4669 }
4670 inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
4671 }
4672 else
4673 {
4674 if ((rm = reg_required_here (&str, 0)) == FAIL)
4675 {
4676 inst.error = BAD_ARGS;
4677 return;
4678 }
4679 else if (rm == REG_PC)
4680 {
4681 inst.error = BAD_PC;
4682 return;
4683 }
4684 }
4685 if (skip_past_comma (&str) == FAIL)
4686 {
4687 inst.error = BAD_ARGS;
4688 return;
4689 }
4690
4691 bfci_lsb_and_width (str);
4692}
4693
4694static void
4695do_bfx (char *str)
4696{
4697 int lsb, width;
4698
4699 /* Rd. */
4700 skip_whitespace (str);
4701 if (reg_required_here (&str, 12) == FAIL
4702 || skip_past_comma (&str) == FAIL)
4703 {
4704 inst.error = BAD_ARGS;
4705 return;
4706 }
4707
4708 /* Rm. */
4709 skip_whitespace (str);
4710 if (reg_required_here (&str, 0) == FAIL
4711 || skip_past_comma (&str) == FAIL)
4712 {
4713 inst.error = BAD_ARGS;
4714 return;
4715 }
4716
4717 if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
4718 return;
4719
4720 if (skip_past_comma (&str) == FAIL)
4721 {
4722 inst.error = BAD_ARGS;
4723 return;
4724 }
4725 if ((width = five_bit_unsigned_immediate (&str)) == -1)
4726 return;
4727
4728 end_of_line (str);
4729
4730 if (width == 0 || lsb == 32)
4731 {
4732 inst.error = _("immediate value out of range");
4733 return;
4734 }
4735 else if (width + lsb > 32)
4736 {
4737 inst.error = _("bit-field extends past end of register");
4738 return;
4739 }
4740
4741 inst.instruction |= lsb << 7;
4742 inst.instruction |= (width - 1) << 16;
4743}
4744
4745static void
4746do_rbit (char *str)
4747{
4748 /* Rd. */
4749 skip_whitespace (str);
4750 if (reg_required_here (&str, 12) == FAIL
4751 || skip_past_comma (&str) == FAIL)
4752 {
4753 inst.error = BAD_ARGS;
4754 return;
4755 }
4756
4757 /* Rm. */
4758 skip_whitespace (str);
4759 if (reg_required_here (&str, 0) == FAIL)
4760 {
4761 inst.error = BAD_ARGS;
4762 return;
4763 }
4764
4765 end_of_line (str);
4766}
4767
4768/* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
4769static void
4770do_mov16 (char *str)
4771{
4772 int rd;
4773 expressionS expr;
4774
4775 /* Rd. */
4776 skip_whitespace (str);
4777 if (((rd = reg_required_here (&str, 12)) == FAIL)
4778 || (skip_past_comma (&str) == FAIL))
4779 {
4780 inst.error = BAD_ARGS;
4781 return;
4782 }
4783 else if (rd == REG_PC)
4784 {
4785 inst.error = BAD_PC;
4786 return;
4787 }
4788
4789 /* Imm16. */
4790 skip_whitespace (str);
4791 if (!is_immediate_prefix (*str))
4792 {
4793 inst.error = _("immediate expression expected");
4794 return;
4795 }
4796 str++;
4797 if (my_get_expression (&expr, &str))
4798 {
4799 inst.error = _("bad expression");
4800 return;
4801 }
4802 if (expr.X_op != O_constant)
4803 {
4804 inst.error = _("constant expression expected");
4805 return;
4806 }
4807 if (expr.X_add_number < 0 || expr.X_add_number > 65535)
4808 {
4809 inst.error = _("immediate value out of range");
4810 return;
4811 }
4812
4813 end_of_line (str);
4814
4815 /* The value is in two pieces: 0:11, 16:19. */
4816 inst.instruction |= (expr.X_add_number & 0x00000fff);
4817 inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
4818}
4819
4820
b99bd4ef
NC
4821/* THUMB V5 breakpoint instruction (argument parse)
4822 BKPT <immed_8>. */
4823
4824static void
a737bd4d 4825do_t_bkpt (char * str)
b99bd4ef
NC
4826{
4827 expressionS expr;
4828 unsigned long number;
4829
4830 skip_whitespace (str);
4831
4832 /* Allow optional leading '#'. */
4833 if (is_immediate_prefix (*str))
4834 str ++;
4835
4836 memset (& expr, '\0', sizeof (expr));
143c8e19
NC
4837 if (my_get_expression (& expr, & str)
4838 || (expr.X_op != O_constant
4839 /* As a convenience we allow 'bkpt' without an operand. */
4840 && expr.X_op != O_absent))
b99bd4ef 4841 {
143c8e19 4842 inst.error = _("bad expression");
b99bd4ef
NC
4843 return;
4844 }
4845
4846 number = expr.X_add_number;
4847
4848 /* Check it fits an 8 bit unsigned. */
4849 if (number != (number & 0xff))
4850 {
4851 inst.error = _("immediate value out of range");
4852 return;
4853 }
4854
4855 inst.instruction |= number;
4856
4857 end_of_line (str);
4858}
4859
f17c130b 4860#ifdef OBJ_ELF
a737bd4d
NC
4861static bfd_reloc_code_real_type
4862arm_parse_reloc (void)
4863{
4864 char id [16];
4865 char * ip;
4866 unsigned int i;
4867 static struct
4868 {
4869 char * str;
4870 int len;
4871 bfd_reloc_code_real_type reloc;
4872 }
4873 reloc_map[] =
4874 {
4875#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
4876 MAP ("(got)", BFD_RELOC_ARM_GOT32),
4877 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
4878 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
4879 branch instructions generated by GCC for PLT relocs. */
4880 MAP ("(plt)", BFD_RELOC_ARM_PLT32),
4881 MAP ("(target1)", BFD_RELOC_ARM_TARGET1),
4882 MAP ("(sbrel)", BFD_RELOC_ARM_SBREL32),
4883 MAP ("(target2)", BFD_RELOC_ARM_TARGET2),
4884 { NULL, 0, BFD_RELOC_UNUSED }
4885#undef MAP
4886 };
4887
4888 for (i = 0, ip = input_line_pointer;
4889 i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
4890 i++, ip++)
4891 id[i] = TOLOWER (*ip);
4892
4893 for (i = 0; reloc_map[i].str; i++)
4894 if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
4895 break;
4896
4897 input_line_pointer += reloc_map[i].len;
4898
4899 return reloc_map[i].reloc;
4900}
f17c130b 4901#endif
a737bd4d 4902
b99bd4ef
NC
4903/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4904 Expects inst.instruction is set for BLX(1).
4905 Note: this is cloned from do_branch, and the reloc changed to be a
4906 new one that can cope with setting one extra bit (the H bit). */
4907
4908static void
a737bd4d 4909do_branch25 (char * str)
b99bd4ef
NC
4910{
4911 if (my_get_expression (& inst.reloc.exp, & str))
4912 return;
4913
4914#ifdef OBJ_ELF
4915 {
4916 char * save_in;
4917
4918 /* ScottB: February 5, 1998 */
4919 /* Check to see of PLT32 reloc required for the instruction. */
4920
4921 /* arm_parse_reloc() works on input_line_pointer.
4922 We actually want to parse the operands to the branch instruction
4923 passed in 'str'. Save the input pointer and restore it later. */
4924 save_in = input_line_pointer;
4925 input_line_pointer = str;
4926
4927 if (inst.reloc.exp.X_op == O_symbol
4928 && *str == '('
4929 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4930 {
4931 inst.reloc.type = BFD_RELOC_ARM_PLT32;
4932 inst.reloc.pc_rel = 0;
4933 /* Modify str to point to after parsed operands, otherwise
4934 end_of_line() will complain about the (PLT) left in str. */
4935 str = input_line_pointer;
4936 }
4937 else
4938 {
4939 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4940 inst.reloc.pc_rel = 1;
4941 }
4942
4943 input_line_pointer = save_in;
4944 }
4945#else
4946 inst.reloc.type = BFD_RELOC_ARM_PCREL_BLX;
4947 inst.reloc.pc_rel = 1;
4948#endif /* OBJ_ELF */
4949
4950 end_of_line (str);
4951}
4952
4953/* ARM V5 branch-link-exchange instruction (argument parse)
4954 BLX <target_addr> ie BLX(1)
4955 BLX{<condition>} <Rm> ie BLX(2)
4956 Unfortunately, there are two different opcodes for this mnemonic.
4957 So, the insns[].value is not used, and the code here zaps values
4958 into inst.instruction.
4959 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4960
4961static void
a737bd4d 4962do_blx (char * str)
b99bd4ef
NC
4963{
4964 char * mystr = str;
4965 int rm;
4966
b99bd4ef
NC
4967 skip_whitespace (mystr);
4968 rm = reg_required_here (& mystr, 0);
4969
4970 /* The above may set inst.error. Ignore his opinion. */
4971 inst.error = 0;
4972
4973 if (rm != FAIL)
4974 {
4975 /* Arg is a register.
4976 Use the condition code our caller put in inst.instruction.
4977 Pass ourselves off as a BX with a funny opcode. */
4978 inst.instruction |= 0x012fff30;
f2b7cb0a 4979 do_bx (str);
b99bd4ef
NC
4980 }
4981 else
4982 {
4983 /* This must be is BLX <target address>, no condition allowed. */
4984 if (inst.instruction != COND_ALWAYS)
cc8a6dd0
KH
4985 {
4986 inst.error = BAD_COND;
b99bd4ef 4987 return;
cc8a6dd0 4988 }
b99bd4ef
NC
4989
4990 inst.instruction = 0xfafffffe;
4991
4992 /* Process like a B/BL, but with a different reloc.
4993 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
f2b7cb0a 4994 do_branch25 (str);
b99bd4ef
NC
4995 }
4996}
4997
4998/* ARM V5 Thumb BLX (argument parse)
4999 BLX <target_addr> which is BLX(1)
5000 BLX <Rm> which is BLX(2)
5001 Unfortunately, there are two different opcodes for this mnemonic.
5002 So, the tinsns[].value is not used, and the code here zaps values
5003 into inst.instruction. */
5004
5005static void
a737bd4d 5006do_t_blx (char * str)
b99bd4ef
NC
5007{
5008 char * mystr = str;
5009 int rm;
5010
5011 skip_whitespace (mystr);
5012 inst.instruction = 0x4780;
5013
5014 /* Note that this call is to the ARM register recognizer. BLX(2)
5015 uses the ARM register space, not the Thumb one, so a call to
5016 thumb_reg() would be wrong. */
5017 rm = reg_required_here (& mystr, 3);
5018 inst.error = 0;
5019
5020 if (rm != FAIL)
5021 {
5022 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5023 inst.size = 2;
5024 }
5025 else
5026 {
5027 /* No ARM register. This must be BLX(1). Change the .instruction. */
5028 inst.instruction = 0xf7ffeffe;
5029 inst.size = 4;
5030
5031 if (my_get_expression (& inst.reloc.exp, & mystr))
5032 return;
5033
5034 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
5035 inst.reloc.pc_rel = 1;
5036 }
5037
5038 end_of_line (mystr);
5039}
5040
5041/* ARM V5 breakpoint instruction (argument parse)
5042 BKPT <16 bit unsigned immediate>
5043 Instruction is not conditional.
5044 The bit pattern given in insns[] has the COND_ALWAYS condition,
cc8a6dd0 5045 and it is an error if the caller tried to override that. */
b99bd4ef
NC
5046
5047static void
a737bd4d 5048do_bkpt (char * str)
b99bd4ef
NC
5049{
5050 expressionS expr;
5051 unsigned long number;
5052
5053 skip_whitespace (str);
5054
5055 /* Allow optional leading '#'. */
5056 if (is_immediate_prefix (* str))
5057 str++;
5058
5059 memset (& expr, '\0', sizeof (expr));
5060
143c8e19
NC
5061 if (my_get_expression (& expr, & str)
5062 || (expr.X_op != O_constant
5063 /* As a convenience we allow 'bkpt' without an operand. */
5064 && expr.X_op != O_absent))
b99bd4ef 5065 {
143c8e19 5066 inst.error = _("bad expression");
b99bd4ef
NC
5067 return;
5068 }
5069
5070 number = expr.X_add_number;
5071
5072 /* Check it fits a 16 bit unsigned. */
5073 if (number != (number & 0xffff))
5074 {
5075 inst.error = _("immediate value out of range");
5076 return;
5077 }
5078
5079 /* Top 12 of 16 bits to bits 19:8. */
5080 inst.instruction |= (number & 0xfff0) << 4;
5081
5082 /* Bottom 4 of 16 bits to bits 3:0. */
5083 inst.instruction |= number & 0xf;
5084
5085 end_of_line (str);
b99bd4ef
NC
5086}
5087
09d92015
MM
5088/* THUMB CPS instruction (argument parse). */
5089
5090static void
a737bd4d 5091do_t_cps (char * str)
09d92015
MM
5092{
5093 do_cps_flags (&str, /*thumb_p=*/1);
5094 end_of_line (str);
5095}
5096
a737bd4d
NC
5097/* Parse and validate that a register is of the right form, this saves
5098 repeated checking of this information in many similar cases.
5099 Unlike the 32-bit case we do not insert the register into the opcode
5100 here, since the position is often unknown until the full instruction
5101 has been parsed. */
5102
5103static int
5104thumb_reg (char ** strp, int hi_lo)
5105{
5106 int reg;
5107
5108 if ((reg = reg_required_here (strp, -1)) == FAIL)
5109 return FAIL;
5110
5111 switch (hi_lo)
5112 {
5113 case THUMB_REG_LO:
5114 if (reg > 7)
5115 {
5116 inst.error = _("lo register required");
5117 return FAIL;
5118 }
5119 break;
5120
5121 case THUMB_REG_HI:
5122 if (reg < 8)
5123 {
5124 inst.error = _("hi register required");
5125 return FAIL;
5126 }
5127 break;
5128
5129 default:
5130 break;
5131 }
5132
5133 return reg;
5134}
5135
5136static void
5137thumb_mov_compare (char * str, int move)
5138{
5139 int Rd, Rs = FAIL;
5140
5141 skip_whitespace (str);
5142
5143 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
5144 || skip_past_comma (&str) == FAIL)
5145 {
5146 if (! inst.error)
5147 inst.error = BAD_ARGS;
5148 return;
5149 }
5150
5151 if (move != THUMB_CPY && is_immediate_prefix (*str))
5152 {
5153 str++;
5154 if (my_get_expression (&inst.reloc.exp, &str))
5155 return;
5156 }
5157 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
5158 return;
5159
5160 if (Rs != FAIL)
5161 {
5162 if (move != THUMB_CPY && Rs < 8 && Rd < 8)
5163 {
5164 if (move == THUMB_MOVE)
5165 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
5166 since a MOV instruction produces unpredictable results. */
5167 inst.instruction = T_OPCODE_ADD_I3;
5168 else
5169 inst.instruction = T_OPCODE_CMP_LR;
5170 inst.instruction |= Rd | (Rs << 3);
5171 }
5172 else
5173 {
5174 if (move == THUMB_MOVE)
5175 inst.instruction = T_OPCODE_MOV_HR;
5176 else if (move != THUMB_CPY)
5177 inst.instruction = T_OPCODE_CMP_HR;
5178
5179 if (Rd > 7)
5180 inst.instruction |= THUMB_H1;
5181
5182 if (Rs > 7)
5183 inst.instruction |= THUMB_H2;
5184
5185 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
5186 }
5187 }
5188 else
5189 {
5190 if (Rd > 7)
5191 {
5192 inst.error = _("only lo regs allowed with immediate");
5193 return;
5194 }
5195
5196 if (move == THUMB_MOVE)
5197 inst.instruction = T_OPCODE_MOV_I8;
5198 else
5199 inst.instruction = T_OPCODE_CMP_I8;
5200
5201 inst.instruction |= Rd << 8;
5202
5203 if (inst.reloc.exp.X_op != O_constant)
5204 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
5205 else
5206 {
5207 unsigned value = inst.reloc.exp.X_add_number;
5208
5209 if (value > 255)
5210 {
5211 inst.error = _("invalid immediate");
5212 return;
5213 }
5214
5215 inst.instruction |= value;
5216 }
5217 }
5218
5219 end_of_line (str);
5220}
5221
09d92015
MM
5222/* THUMB CPY instruction (argument parse). */
5223
5224static void
a737bd4d 5225do_t_cpy (char * str)
09d92015
MM
5226{
5227 thumb_mov_compare (str, THUMB_CPY);
5228}
5229
5230/* THUMB SETEND instruction (argument parse). */
5231
5232static void
a737bd4d 5233do_t_setend (char * str)
09d92015
MM
5234{
5235 if (do_endian_specifier (str))
5236 inst.instruction |= 0x8;
5237}
5238
e16bb312
NC
5239/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
5240
5241static unsigned long
a737bd4d
NC
5242check_iwmmxt_insn (char * str,
5243 enum iwmmxt_insn_type insn_type,
5244 int immediate_size)
e16bb312
NC
5245{
5246 int reg = 0;
5247 const char * inst_error;
5248 expressionS expr;
5249 unsigned long number;
5250
5251 inst_error = inst.error;
5252 if (!inst.error)
5253 inst.error = BAD_ARGS;
5254 skip_whitespace (str);
5255
5256 switch (insn_type)
5257 {
5258 case check_rd:
5259 if ((reg = reg_required_here (&str, 12)) == FAIL)
5260 return FAIL;
5261 break;
a737bd4d 5262
e16bb312
NC
5263 case check_wr:
5264 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
5265 return FAIL;
5266 break;
a737bd4d 5267
e16bb312
NC
5268 case check_wrwr:
5269 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5270 || skip_past_comma (&str) == FAIL
5271 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5272 return FAIL;
5273 break;
a737bd4d 5274
e16bb312
NC
5275 case check_wrwrwr:
5276 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5277 || skip_past_comma (&str) == FAIL
5278 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5279 || skip_past_comma (&str) == FAIL
5280 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5281 return FAIL;
5282 break;
a737bd4d 5283
e16bb312
NC
5284 case check_wrwrwcg:
5285 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5286 || skip_past_comma (&str) == FAIL
5287 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5288 || skip_past_comma (&str) == FAIL
5289 || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
5290 return FAIL;
5291 break;
a737bd4d 5292
e16bb312
NC
5293 case check_tbcst:
5294 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5295 || skip_past_comma (&str) == FAIL
5296 || reg_required_here (&str, 12) == FAIL))
5297 return FAIL;
5298 break;
a737bd4d 5299
e16bb312
NC
5300 case check_tmovmsk:
5301 if ((reg_required_here (&str, 12) == FAIL
5302 || skip_past_comma (&str) == FAIL
5303 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
5304 return FAIL;
5305 break;
a737bd4d 5306
e16bb312
NC
5307 case check_tmia:
5308 if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
5309 || skip_past_comma (&str) == FAIL
5310 || reg_required_here (&str, 0) == FAIL
5311 || skip_past_comma (&str) == FAIL
5312 || reg_required_here (&str, 12) == FAIL))
5313 return FAIL;
5314 break;
a737bd4d 5315
e16bb312
NC
5316 case check_tmcrr:
5317 if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5318 || skip_past_comma (&str) == FAIL
5319 || reg_required_here (&str, 12) == FAIL
5320 || skip_past_comma (&str) == FAIL
5321 || reg_required_here (&str, 16) == FAIL))
5322 return FAIL;
5323 break;
a737bd4d 5324
e16bb312
NC
5325 case check_tmrrc:
5326 if ((reg_required_here (&str, 12) == FAIL
5327 || skip_past_comma (&str) == FAIL
5328 || reg_required_here (&str, 16) == FAIL
5329 || skip_past_comma (&str) == FAIL
5330 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
5331 return FAIL;
5332 break;
a737bd4d 5333
e16bb312
NC
5334 case check_tmcr:
5335 if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
5336 || skip_past_comma (&str) == FAIL
5337 || reg_required_here (&str, 12) == FAIL))
5338 return FAIL;
5339 break;
a737bd4d 5340
e16bb312
NC
5341 case check_tmrc:
5342 if ((reg_required_here (&str, 12) == FAIL
5343 || skip_past_comma (&str) == FAIL
5344 || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
5345 return FAIL;
5346 break;
a737bd4d 5347
e16bb312
NC
5348 case check_tinsr:
5349 if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5350 || skip_past_comma (&str) == FAIL
5351 || reg_required_here (&str, 12) == FAIL
5352 || skip_past_comma (&str) == FAIL))
5353 return FAIL;
5354 break;
a737bd4d 5355
e16bb312
NC
5356 case check_textrc:
5357 if ((reg_required_here (&str, 12) == FAIL
5358 || skip_past_comma (&str) == FAIL))
5359 return FAIL;
5360 break;
a737bd4d 5361
e16bb312
NC
5362 case check_waligni:
5363 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5364 || skip_past_comma (&str) == FAIL
5365 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5366 || skip_past_comma (&str) == FAIL
5367 || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
5368 || skip_past_comma (&str) == FAIL))
5369 return FAIL;
5370 break;
a737bd4d 5371
e16bb312
NC
5372 case check_textrm:
5373 if ((reg_required_here (&str, 12) == FAIL
5374 || skip_past_comma (&str) == FAIL
5375 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5376 || skip_past_comma (&str) == FAIL))
5377 return FAIL;
5378 break;
a737bd4d 5379
e16bb312
NC
5380 case check_wshufh:
5381 if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
5382 || skip_past_comma (&str) == FAIL
5383 || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
5384 || skip_past_comma (&str) == FAIL))
5385 return FAIL;
5386 break;
5387 }
a737bd4d 5388
e16bb312
NC
5389 if (immediate_size == 0)
5390 {
5391 end_of_line (str);
5392 inst.error = inst_error;
5393 return reg;
5394 }
5395 else
5396 {
a737bd4d
NC
5397 skip_whitespace (str);
5398
5399 /* Allow optional leading '#'. */
e16bb312
NC
5400 if (is_immediate_prefix (* str))
5401 str++;
5402
5403 memset (& expr, '\0', sizeof (expr));
a737bd4d 5404
e16bb312
NC
5405 if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
5406 {
5407 inst.error = _("bad or missing expression");
5408 return FAIL;
5409 }
a737bd4d 5410
e16bb312 5411 number = expr.X_add_number;
a737bd4d 5412
e16bb312
NC
5413 if (number != (number & immediate_size))
5414 {
5415 inst.error = _("immediate value out of range");
5416 return FAIL;
5417 }
5418 end_of_line (str);
5419 inst.error = inst_error;
5420 return number;
5421 }
5422}
5423
5424static void
a737bd4d 5425do_iwmmxt_byte_addr (char * str)
e16bb312
NC
5426{
5427 int op = (inst.instruction & 0x300) >> 8;
5428 int reg;
5429
5430 inst.instruction &= ~0x300;
a737bd4d 5431 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5432
5433 skip_whitespace (str);
5434
5435 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5436 || skip_past_comma (& str) == FAIL
5437 || cp_byte_address_required_here (&str) == FAIL)
5438 {
5439 if (! inst.error)
5440 inst.error = BAD_ARGS;
5441 }
5442 else
5443 end_of_line (str);
5444
5445 if (wc_register (reg))
5446 {
ece01a63 5447 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5448 inst.instruction |= 0xf0000100;
5449 inst.instruction &= ~0x00400000;
5450 }
5451}
5452
5453static void
a737bd4d 5454do_iwmmxt_tandc (char * str)
e16bb312
NC
5455{
5456 int reg;
5457
5458 reg = check_iwmmxt_insn (str, check_rd, 0);
5459
5460 if (reg != REG_PC && !inst.error)
5461 inst.error = _("only r15 allowed here");
e16bb312
NC
5462}
5463
5464static void
a737bd4d 5465do_iwmmxt_tbcst (char * str)
e16bb312
NC
5466{
5467 check_iwmmxt_insn (str, check_tbcst, 0);
e16bb312
NC
5468}
5469
5470static void
a737bd4d 5471do_iwmmxt_textrc (char * str)
e16bb312
NC
5472{
5473 unsigned long number;
5474
5475 if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
5476 return;
5477
5478 inst.instruction |= number & 0x7;
e16bb312
NC
5479}
5480
5481static void
a737bd4d 5482do_iwmmxt_textrm (char * str)
e16bb312
NC
5483{
5484 unsigned long number;
5485
5486 if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
5487 return;
5488
5489 inst.instruction |= number & 0x7;
5490}
5491
5492static void
a737bd4d 5493do_iwmmxt_tinsr (char * str)
e16bb312
NC
5494{
5495 unsigned long number;
5496
5497 if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
5498 return;
5499
5500 inst.instruction |= number & 0x7;
e16bb312
NC
5501}
5502
5503static void
a737bd4d 5504do_iwmmxt_tmcr (char * str)
e16bb312
NC
5505{
5506 check_iwmmxt_insn (str, check_tmcr, 0);
e16bb312
NC
5507}
5508
5509static void
a737bd4d 5510do_iwmmxt_tmcrr (char * str)
e16bb312
NC
5511{
5512 check_iwmmxt_insn (str, check_tmcrr, 0);
e16bb312
NC
5513}
5514
5515static void
a737bd4d 5516do_iwmmxt_tmia (char * str)
e16bb312
NC
5517{
5518 check_iwmmxt_insn (str, check_tmia, 0);
e16bb312
NC
5519}
5520
5521static void
a737bd4d 5522do_iwmmxt_tmovmsk (char * str)
e16bb312
NC
5523{
5524 check_iwmmxt_insn (str, check_tmovmsk, 0);
e16bb312
NC
5525}
5526
5527static void
a737bd4d 5528do_iwmmxt_tmrc (char * str)
e16bb312
NC
5529{
5530 check_iwmmxt_insn (str, check_tmrc, 0);
e16bb312
NC
5531}
5532
5533static void
a737bd4d 5534do_iwmmxt_tmrrc (char * str)
e16bb312
NC
5535{
5536 check_iwmmxt_insn (str, check_tmrrc, 0);
e16bb312
NC
5537}
5538
5539static void
a737bd4d 5540do_iwmmxt_torc (char * str)
e16bb312
NC
5541{
5542 check_iwmmxt_insn (str, check_rd, 0);
e16bb312
NC
5543}
5544
5545static void
a737bd4d 5546do_iwmmxt_waligni (char * str)
e16bb312
NC
5547{
5548 unsigned long number;
5549
5550 if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
5551 return;
5552
5553 inst.instruction |= ((number & 0x7) << 20);
e16bb312
NC
5554}
5555
5556static void
a737bd4d 5557do_iwmmxt_wmov (char * str)
e16bb312
NC
5558{
5559 if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
5560 return;
a737bd4d 5561
e16bb312 5562 inst.instruction |= ((inst.instruction >> 16) & 0xf);
e16bb312
NC
5563}
5564
5565static void
a737bd4d 5566do_iwmmxt_word_addr (char * str)
e16bb312
NC
5567{
5568 int op = (inst.instruction & 0x300) >> 8;
5569 int reg;
5570
5571 inst.instruction &= ~0x300;
a737bd4d 5572 inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
e16bb312
NC
5573
5574 skip_whitespace (str);
5575
5576 if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
5577 || skip_past_comma (& str) == FAIL
5578 || cp_address_required_here (& str, CP_WB_OK) == FAIL)
5579 {
5580 if (! inst.error)
5581 inst.error = BAD_ARGS;
5582 }
5583 else
5584 end_of_line (str);
5585
5586 if (wc_register (reg))
5587 {
ece01a63
ILT
5588 if ((inst.instruction & COND_MASK) != COND_ALWAYS)
5589 as_bad (_("conditional execution not supported with control register"));
5590 if (op != 2)
5591 as_bad (_("non-word size not supported with control register"));
e16bb312
NC
5592 inst.instruction |= 0xf0000100;
5593 inst.instruction &= ~0x00400000;
5594 }
5595}
5596
5597static void
a737bd4d 5598do_iwmmxt_wrwr (char * str)
e16bb312
NC
5599{
5600 check_iwmmxt_insn (str, check_wrwr, 0);
e16bb312
NC
5601}
5602
5603static void
a737bd4d 5604do_iwmmxt_wrwrwcg (char * str)
e16bb312
NC
5605{
5606 check_iwmmxt_insn (str, check_wrwrwcg, 0);
e16bb312
NC
5607}
5608
5609static void
a737bd4d 5610do_iwmmxt_wrwrwr (char * str)
e16bb312
NC
5611{
5612 check_iwmmxt_insn (str, check_wrwrwr, 0);
e16bb312
NC
5613}
5614
5615static void
a737bd4d 5616do_iwmmxt_wshufh (char * str)
e16bb312
NC
5617{
5618 unsigned long number;
5619
5620 if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5621 return;
5622
5623 inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
e16bb312
NC
5624}
5625
5626static void
a737bd4d 5627do_iwmmxt_wzero (char * str)
e16bb312
NC
5628{
5629 if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5630 return;
5631
5632 inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
e16bb312
NC
5633}
5634
b99bd4ef
NC
5635/* Xscale multiply-accumulate (argument parse)
5636 MIAcc acc0,Rm,Rs
5637 MIAPHcc acc0,Rm,Rs
5638 MIAxycc acc0,Rm,Rs. */
5639
5640static void
a737bd4d 5641do_xsc_mia (char * str)
b99bd4ef
NC
5642{
5643 int rs;
5644 int rm;
5645
f2b7cb0a 5646 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5647 inst.error = ERR_NO_ACCUM;
5648
5649 else if (skip_past_comma (& str) == FAIL
5650 || (rm = reg_required_here (& str, 0)) == FAIL)
5651 inst.error = BAD_ARGS;
5652
5653 else if (skip_past_comma (& str) == FAIL
5654 || (rs = reg_required_here (& str, 12)) == FAIL)
5655 inst.error = BAD_ARGS;
5656
5657 /* inst.instruction has now been zapped with both rm and rs. */
5658 else if (rm == REG_PC || rs == REG_PC)
5659 inst.error = BAD_PC; /* Undefined result if rm or rs is R15. */
5660
5661 else
5662 end_of_line (str);
5663}
5664
5665/* Xscale move-accumulator-register (argument parse)
5666
5667 MARcc acc0,RdLo,RdHi. */
5668
5669static void
a737bd4d 5670do_xsc_mar (char * str)
b99bd4ef
NC
5671{
5672 int rdlo, rdhi;
5673
f2b7cb0a 5674 if (accum0_required_here (& str) == FAIL)
b99bd4ef
NC
5675 inst.error = ERR_NO_ACCUM;
5676
5677 else if (skip_past_comma (& str) == FAIL
5678 || (rdlo = reg_required_here (& str, 12)) == FAIL)
5679 inst.error = BAD_ARGS;
5680
5681 else if (skip_past_comma (& str) == FAIL
5682 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5683 inst.error = BAD_ARGS;
5684
5685 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5686 else if (rdlo == REG_PC || rdhi == REG_PC)
5687 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5688
5689 else
5690 end_of_line (str);
5691}
5692
5693/* Xscale move-register-accumulator (argument parse)
5694
5695 MRAcc RdLo,RdHi,acc0. */
5696
5697static void
a737bd4d 5698do_xsc_mra (char * str)
b99bd4ef
NC
5699{
5700 int rdlo;
5701 int rdhi;
5702
b99bd4ef
NC
5703 skip_whitespace (str);
5704
5705 if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5706 inst.error = BAD_ARGS;
5707
5708 else if (skip_past_comma (& str) == FAIL
5709 || (rdhi = reg_required_here (& str, 16)) == FAIL)
5710 inst.error = BAD_ARGS;
5711
5712 else if (skip_past_comma (& str) == FAIL
5713 || accum0_required_here (& str) == FAIL)
5714 inst.error = ERR_NO_ACCUM;
5715
a737bd4d
NC
5716 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5717 else if (rdlo == rdhi)
5718 inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
5719
5720 else if (rdlo == REG_PC || rdhi == REG_PC)
5721 inst.error = BAD_PC; /* Undefined result if rdlo or rdhi is R15. */
5722 else
5723 end_of_line (str);
5724}
5725
5726static int
5727ldst_extend (char ** str)
5728{
5729 int add = INDEX_UP;
5730
5731 switch (**str)
5732 {
5733 case '#':
5734 case '$':
5735 (*str)++;
5736 if (my_get_expression (& inst.reloc.exp, str))
5737 return FAIL;
5738
5739 if (inst.reloc.exp.X_op == O_constant)
5740 {
5741 int value = inst.reloc.exp.X_add_number;
5742
5743 if (value < -4095 || value > 4095)
5744 {
5745 inst.error = _("address offset too large");
5746 return FAIL;
5747 }
5748
5749 if (value < 0)
5750 {
5751 value = -value;
5752 add = 0;
5753 }
5754
5755 inst.instruction |= add | value;
5756 }
5757 else
5758 {
5759 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5760 inst.reloc.pc_rel = 0;
5761 }
5762 return SUCCESS;
5763
5764 case '-':
5765 add = 0;
5766 /* Fall through. */
5767
5768 case '+':
5769 (*str)++;
5770 /* Fall through. */
5771
5772 default:
5773 if (reg_required_here (str, 0) == FAIL)
5774 return FAIL;
5775
5776 inst.instruction |= add | OFFSET_REG;
5777 if (skip_past_comma (str) == SUCCESS)
5778 return decode_shift (str, SHIFT_IMMEDIATE);
b99bd4ef 5779
a737bd4d
NC
5780 return SUCCESS;
5781 }
b99bd4ef
NC
5782}
5783
c9b604bd 5784/* ARMv5TE: Preload-Cache
b99bd4ef
NC
5785
5786 PLD <addr_mode>
5787
5788 Syntactically, like LDR with B=1, W=0, L=1. */
5789
5790static void
a737bd4d 5791do_pld (char * str)
b99bd4ef
NC
5792{
5793 int rd;
5794
b99bd4ef
NC
5795 skip_whitespace (str);
5796
5797 if (* str != '[')
5798 {
5799 inst.error = _("'[' expected after PLD mnemonic");
5800 return;
5801 }
5802
90e4755a 5803 ++str;
b99bd4ef
NC
5804 skip_whitespace (str);
5805
5806 if ((rd = reg_required_here (& str, 16)) == FAIL)
5807 return;
5808
5809 skip_whitespace (str);
5810
90e4755a 5811 if (*str == ']')
b99bd4ef
NC
5812 {
5813 /* [Rn], ... ? */
90e4755a 5814 ++str;
b99bd4ef
NC
5815 skip_whitespace (str);
5816
90e4755a
RE
5817 /* Post-indexed addressing is not allowed with PLD. */
5818 if (skip_past_comma (&str) == SUCCESS)
b99bd4ef 5819 {
90e4755a
RE
5820 inst.error
5821 = _("post-indexed expression used in preload instruction");
5822 return;
b99bd4ef 5823 }
90e4755a 5824 else if (*str == '!') /* [Rn]! */
b99bd4ef
NC
5825 {
5826 inst.error = _("writeback used in preload instruction");
90e4755a 5827 ++str;
b99bd4ef
NC
5828 }
5829 else /* [Rn] */
5830 inst.instruction |= INDEX_UP | PRE_INDEX;
5831 }
5832 else /* [Rn, ...] */
5833 {
5834 if (skip_past_comma (& str) == FAIL)
5835 {
5836 inst.error = _("pre-indexed expression expected");
5837 return;
5838 }
5839
90e4755a 5840 if (ldst_extend (&str) == FAIL)
b99bd4ef
NC
5841 return;
5842
5843 skip_whitespace (str);
5844
5845 if (* str != ']')
5846 {
5847 inst.error = _("missing ]");
5848 return;
5849 }
5850
5851 ++ str;
5852 skip_whitespace (str);
5853
5854 if (* str == '!') /* [Rn]! */
5855 {
5856 inst.error = _("writeback used in preload instruction");
5857 ++ str;
5858 }
5859
5860 inst.instruction |= PRE_INDEX;
5861 }
5862
5863 end_of_line (str);
5864}
5865
c9b604bd 5866/* ARMv5TE load-consecutive (argument parse)
b99bd4ef
NC
5867 Mode is like LDRH.
5868
5869 LDRccD R, mode
5870 STRccD R, mode. */
5871
5872static void
a737bd4d 5873do_ldrd (char * str)
b99bd4ef
NC
5874{
5875 int rd;
5876 int rn;
5877
b99bd4ef
NC
5878 skip_whitespace (str);
5879
5880 if ((rd = reg_required_here (& str, 12)) == FAIL)
5881 {
5882 inst.error = BAD_ARGS;
5883 return;
5884 }
5885
5886 if (skip_past_comma (& str) == FAIL
5887 || (rn = ld_mode_required_here (& str)) == FAIL)
5888 {
5889 if (!inst.error)
cc8a6dd0 5890 inst.error = BAD_ARGS;
a737bd4d 5891 return;
b99bd4ef
NC
5892 }
5893
a737bd4d
NC
5894 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5895 if (rd & 1) /* Unpredictable result if Rd is odd. */
5896 {
5897 inst.error = _("destination register must be even");
5898 return;
5899 }
b99bd4ef 5900
a737bd4d 5901 if (rd == REG_LR)
b99bd4ef 5902 {
a737bd4d
NC
5903 inst.error = _("r14 not allowed here");
5904 return;
b99bd4ef 5905 }
a737bd4d
NC
5906
5907 if (((rd == rn) || (rd + 1 == rn))
5908 && ((inst.instruction & WRITE_BACK)
5909 || (!(inst.instruction & PRE_INDEX))))
5910 as_warn (_("pre/post-indexing used when modified address register is destination"));
5911
5912 /* For an index-register load, the index register must not overlap the
5913 destination (even if not write-back). */
5914 if ((inst.instruction & V4_STR_BIT) == 0
5915 && (inst.instruction & HWOFFSET_IMM) == 0)
b99bd4ef 5916 {
a737bd4d
NC
5917 int rm = inst.instruction & 0x0000000f;
5918
5919 if (rm == rd || (rm == rd + 1))
5920 as_warn (_("ldrd destination registers must not overlap index register"));
b99bd4ef
NC
5921 }
5922
a737bd4d
NC
5923 end_of_line (str);
5924}
b99bd4ef 5925
a737bd4d
NC
5926/* Returns the index into fp_values of a floating point number,
5927 or -1 if not in the table. */
b99bd4ef 5928
a737bd4d
NC
5929static int
5930my_get_float_expression (char ** str)
5931{
5932 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5933 char * save_in;
5934 expressionS exp;
5935 int i;
5936 int j;
b99bd4ef 5937
a737bd4d
NC
5938 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5939
5940 /* Look for a raw floating point number. */
5941 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5942 && is_end_of_line[(unsigned char) *save_in])
5943 {
5944 for (i = 0; i < NUM_FLOAT_VALS; i++)
b99bd4ef 5945 {
a737bd4d 5946 for (j = 0; j < MAX_LITTLENUMS; j++)
b99bd4ef 5947 {
a737bd4d
NC
5948 if (words[j] != fp_values[i][j])
5949 break;
b99bd4ef 5950 }
a737bd4d
NC
5951
5952 if (j == MAX_LITTLENUMS)
b99bd4ef 5953 {
a737bd4d
NC
5954 *str = save_in;
5955 return i;
b99bd4ef
NC
5956 }
5957 }
a737bd4d 5958 }
b99bd4ef 5959
a737bd4d
NC
5960 /* Try and parse a more complex expression, this will probably fail
5961 unless the code uses a floating point prefix (eg "0f"). */
5962 save_in = input_line_pointer;
5963 input_line_pointer = *str;
5964 if (expression (&exp) == absolute_section
5965 && exp.X_op == O_big
5966 && exp.X_add_number < 0)
5967 {
5968 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5969 Ditto for 15. */
5970 if (gen_to_words (words, 5, (long) 15) == 0)
5971 {
5972 for (i = 0; i < NUM_FLOAT_VALS; i++)
5973 {
5974 for (j = 0; j < MAX_LITTLENUMS; j++)
5975 {
5976 if (words[j] != fp_values[i][j])
5977 break;
5978 }
b99bd4ef 5979
a737bd4d
NC
5980 if (j == MAX_LITTLENUMS)
5981 {
5982 *str = input_line_pointer;
5983 input_line_pointer = save_in;
5984 return i;
5985 }
5986 }
5987 }
b99bd4ef 5988 }
a737bd4d
NC
5989
5990 *str = input_line_pointer;
5991 input_line_pointer = save_in;
5992 return -1;
5993}
5994
5995/* We handle all bad expressions here, so that we can report the faulty
5996 instruction in the error message. */
5997void
5998md_operand (expressionS * expr)
5999{
6000 if (in_my_get_expression)
b99bd4ef 6001 {
a737bd4d
NC
6002 expr->X_op = O_illegal;
6003 if (inst.error == NULL)
6004 inst.error = _("bad expression");
b99bd4ef 6005 }
b99bd4ef
NC
6006}
6007
6008/* Do those data_ops which can take a negative immediate constant
2d2255b5 6009 by altering the instruction. A bit of a hack really.
b99bd4ef
NC
6010 MOV <-> MVN
6011 AND <-> BIC
6012 ADC <-> SBC
6013 by inverting the second operand, and
6014 ADD <-> SUB
6015 CMP <-> CMN
6016 by negating the second operand. */
6017
6018static int
a737bd4d
NC
6019negate_data_op (unsigned long * instruction,
6020 unsigned long value)
b99bd4ef
NC
6021{
6022 int op, new_inst;
6023 unsigned long negated, inverted;
6024
6025 negated = validate_immediate (-value);
6026 inverted = validate_immediate (~value);
6027
6028 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
6029 switch (op)
6030 {
6031 /* First negates. */
6032 case OPCODE_SUB: /* ADD <-> SUB */
6033 new_inst = OPCODE_ADD;
6034 value = negated;
6035 break;
6036
6037 case OPCODE_ADD:
6038 new_inst = OPCODE_SUB;
6039 value = negated;
6040 break;
6041
6042 case OPCODE_CMP: /* CMP <-> CMN */
6043 new_inst = OPCODE_CMN;
6044 value = negated;
6045 break;
6046
6047 case OPCODE_CMN:
6048 new_inst = OPCODE_CMP;
6049 value = negated;
6050 break;
6051
6052 /* Now Inverted ops. */
6053 case OPCODE_MOV: /* MOV <-> MVN */
6054 new_inst = OPCODE_MVN;
6055 value = inverted;
6056 break;
6057
6058 case OPCODE_MVN:
6059 new_inst = OPCODE_MOV;
6060 value = inverted;
6061 break;
6062
6063 case OPCODE_AND: /* AND <-> BIC */
6064 new_inst = OPCODE_BIC;
6065 value = inverted;
6066 break;
6067
6068 case OPCODE_BIC:
6069 new_inst = OPCODE_AND;
6070 value = inverted;
6071 break;
6072
6073 case OPCODE_ADC: /* ADC <-> SBC */
6074 new_inst = OPCODE_SBC;
6075 value = inverted;
6076 break;
6077
6078 case OPCODE_SBC:
6079 new_inst = OPCODE_ADC;
6080 value = inverted;
6081 break;
6082
6083 /* We cannot do anything. */
6084 default:
6085 return FAIL;
6086 }
6087
6088 if (value == (unsigned) FAIL)
6089 return FAIL;
6090
6091 *instruction &= OPCODE_MASK;
6092 *instruction |= new_inst << DATA_OP_SHIFT;
6093 return value;
6094}
6095
6096static int
a737bd4d 6097data_op2 (char ** str)
b99bd4ef
NC
6098{
6099 int value;
6100 expressionS expr;
6101
6102 skip_whitespace (* str);
6103
6104 if (reg_required_here (str, 0) != FAIL)
6105 {
6106 if (skip_past_comma (str) == SUCCESS)
6107 /* Shift operation on register. */
6108 return decode_shift (str, NO_SHIFT_RESTRICT);
6109
6110 return SUCCESS;
6111 }
6112 else
6113 {
6114 /* Immediate expression. */
6115 if (is_immediate_prefix (**str))
6116 {
6117 (*str)++;
6118 inst.error = NULL;
6119
6120 if (my_get_expression (&inst.reloc.exp, str))
6121 return FAIL;
6122
6123 if (inst.reloc.exp.X_add_symbol)
6124 {
6125 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
6126 inst.reloc.pc_rel = 0;
6127 }
6128 else
6129 {
6130 if (skip_past_comma (str) == SUCCESS)
6131 {
6132 /* #x, y -- ie explicit rotation by Y. */
6133 if (my_get_expression (&expr, str))
6134 return FAIL;
6135
6136 if (expr.X_op != O_constant)
6137 {
f03698e6 6138 inst.error = _("constant expression expected");
b99bd4ef
NC
6139 return FAIL;
6140 }
6141
6142 /* Rotate must be a multiple of 2. */
6143 if (((unsigned) expr.X_add_number) > 30
6144 || (expr.X_add_number & 1) != 0
6145 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
6146 {
f03698e6 6147 inst.error = _("invalid constant");
b99bd4ef
NC
6148 return FAIL;
6149 }
6150 inst.instruction |= INST_IMMEDIATE;
6151 inst.instruction |= inst.reloc.exp.X_add_number;
6152 inst.instruction |= expr.X_add_number << 7;
6153 return SUCCESS;
6154 }
6155
6156 /* Implicit rotation, select a suitable one. */
6157 value = validate_immediate (inst.reloc.exp.X_add_number);
6158
6159 if (value == FAIL)
6160 {
6161 /* Can't be done. Perhaps the code reads something like
6162 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
6163 if ((value = negate_data_op (&inst.instruction,
6164 inst.reloc.exp.X_add_number))
6165 == FAIL)
6166 {
f03698e6 6167 inst.error = _("invalid constant");
b99bd4ef
NC
6168 return FAIL;
6169 }
6170 }
6171
6172 inst.instruction |= value;
6173 }
6174
6175 inst.instruction |= INST_IMMEDIATE;
6176 return SUCCESS;
6177 }
6178
6179 (*str)++;
f03698e6 6180 inst.error = _("register or shift expression expected");
b99bd4ef
NC
6181 return FAIL;
6182 }
6183}
6184
6185static int
a737bd4d 6186fp_op2 (char ** str)
b99bd4ef
NC
6187{
6188 skip_whitespace (* str);
6189
6190 if (fp_reg_required_here (str, 0) != FAIL)
6191 return SUCCESS;
6192 else
6193 {
6194 /* Immediate expression. */
6195 if (*((*str)++) == '#')
6196 {
6197 int i;
6198
6199 inst.error = NULL;
6200
6201 skip_whitespace (* str);
6202
6203 /* First try and match exact strings, this is to guarantee
6204 that some formats will work even for cross assembly. */
6205
6206 for (i = 0; fp_const[i]; i++)
6207 {
6208 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
6209 {
6210 char *start = *str;
6211
6212 *str += strlen (fp_const[i]);
6213 if (is_end_of_line[(unsigned char) **str])
6214 {
6215 inst.instruction |= i + 8;
6216 return SUCCESS;
6217 }
6218 *str = start;
6219 }
6220 }
6221
6222 /* Just because we didn't get a match doesn't mean that the
6223 constant isn't valid, just that it is in a format that we
6224 don't automatically recognize. Try parsing it with
6225 the standard expression routines. */
6226 if ((i = my_get_float_expression (str)) >= 0)
6227 {
6228 inst.instruction |= i + 8;
6229 return SUCCESS;
6230 }
6231
f03698e6 6232 inst.error = _("invalid floating point immediate expression");
b99bd4ef
NC
6233 return FAIL;
6234 }
6235 inst.error =
f03698e6 6236 _("floating point register or immediate expression expected");
b99bd4ef
NC
6237 return FAIL;
6238 }
6239}
6240
6241static void
a737bd4d 6242do_arit (char * str)
b99bd4ef
NC
6243{
6244 skip_whitespace (str);
6245
6246 if (reg_required_here (&str, 12) == FAIL
6247 || skip_past_comma (&str) == FAIL
6248 || reg_required_here (&str, 16) == FAIL
6249 || skip_past_comma (&str) == FAIL
6250 || data_op2 (&str) == FAIL)
6251 {
6252 if (!inst.error)
6253 inst.error = BAD_ARGS;
6254 return;
6255 }
6256
b99bd4ef 6257 end_of_line (str);
b99bd4ef
NC
6258}
6259
6260static void
a737bd4d 6261do_adr (char * str)
b99bd4ef 6262{
90e4755a
RE
6263 /* This is a pseudo-op of the form "adr rd, label" to be converted
6264 into a relative address of the form "add rd, pc, #label-.-8". */
6265 skip_whitespace (str);
6266
6267 if (reg_required_here (&str, 12) == FAIL
6268 || skip_past_comma (&str) == FAIL
6269 || my_get_expression (&inst.reloc.exp, &str))
6270 {
6271 if (!inst.error)
6272 inst.error = BAD_ARGS;
6273 return;
6274 }
6275
6276 /* Frag hacking will turn this into a sub instruction if the offset turns
6277 out to be negative. */
6278 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
250355db 6279#ifndef TE_WINCE
90e4755a 6280 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
250355db 6281#endif
90e4755a
RE
6282 inst.reloc.pc_rel = 1;
6283
6284 end_of_line (str);
6285}
6286
6287static void
a737bd4d 6288do_adrl (char * str)
90e4755a
RE
6289{
6290 /* This is a pseudo-op of the form "adrl rd, label" to be converted
6291 into a relative address of the form:
6292 add rd, pc, #low(label-.-8)"
6293 add rd, rd, #high(label-.-8)" */
6294
6295 skip_whitespace (str);
6296
6297 if (reg_required_here (&str, 12) == FAIL
6298 || skip_past_comma (&str) == FAIL
6299 || my_get_expression (&inst.reloc.exp, &str))
6300 {
6301 if (!inst.error)
6302 inst.error = BAD_ARGS;
6303
6304 return;
6305 }
6306
6307 end_of_line (str);
6308 /* Frag hacking will turn this into a sub instruction if the offset turns
6309 out to be negative. */
6310 inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
a737bd4d 6311#ifndef TE_WINCE
90e4755a 6312 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
250355db 6313#endif
90e4755a
RE
6314 inst.reloc.pc_rel = 1;
6315 inst.size = INSN_SIZE * 2;
90e4755a
RE
6316}
6317
6318static void
a737bd4d 6319do_cmp (char * str)
90e4755a
RE
6320{
6321 skip_whitespace (str);
6322
6323 if (reg_required_here (&str, 16) == FAIL)
6324 {
6325 if (!inst.error)
6326 inst.error = BAD_ARGS;
6327 return;
6328 }
6329
6330 if (skip_past_comma (&str) == FAIL
6331 || data_op2 (&str) == FAIL)
6332 {
6333 if (!inst.error)
6334 inst.error = BAD_ARGS;
6335 return;
6336 }
6337
90e4755a 6338 end_of_line (str);
90e4755a
RE
6339}
6340
6341static void
a737bd4d 6342do_mov (char * str)
90e4755a
RE
6343{
6344 skip_whitespace (str);
6345
6346 if (reg_required_here (&str, 12) == FAIL)
6347 {
6348 if (!inst.error)
6349 inst.error = BAD_ARGS;
6350 return;
6351 }
6352
6353 if (skip_past_comma (&str) == FAIL
6354 || data_op2 (&str) == FAIL)
6355 {
6356 if (!inst.error)
6357 inst.error = BAD_ARGS;
6358 return;
6359 }
6360
90e4755a 6361 end_of_line (str);
90e4755a
RE
6362}
6363
90e4755a 6364static void
a737bd4d 6365do_ldst (char * str)
90e4755a
RE
6366{
6367 int pre_inc = 0;
6368 int conflict_reg;
6369 int value;
6370
b99bd4ef
NC
6371 skip_whitespace (str);
6372
90e4755a
RE
6373 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
6374 {
6375 if (!inst.error)
6376 inst.error = BAD_ARGS;
6377 return;
6378 }
6379
6380 if (skip_past_comma (&str) == FAIL)
6381 {
f03698e6 6382 inst.error = _("address expected");
90e4755a
RE
6383 return;
6384 }
6385
90e4755a
RE
6386 if (*str == '[')
6387 {
6388 int reg;
6389
6390 str++;
6391
6392 skip_whitespace (str);
6393
6394 if ((reg = reg_required_here (&str, 16)) == FAIL)
6395 return;
6396
6397 /* Conflicts can occur on stores as well as loads. */
6398 conflict_reg = (conflict_reg == reg);
6399
6400 skip_whitespace (str);
6401
6402 if (*str == ']')
6403 {
6404 str ++;
6405
6406 if (skip_past_comma (&str) == SUCCESS)
6407 {
6408 /* [Rn],... (post inc) */
6409 if (ldst_extend (&str) == FAIL)
6410 return;
6411 if (conflict_reg)
6412 as_warn (_("%s register same as write-back base"),
6413 ((inst.instruction & LOAD_BIT)
6414 ? _("destination") : _("source")));
6415 }
6416 else
6417 {
6418 /* [Rn] */
6419 skip_whitespace (str);
6420
6421 if (*str == '!')
6422 {
6423 if (conflict_reg)
6424 as_warn (_("%s register same as write-back base"),
6425 ((inst.instruction & LOAD_BIT)
6426 ? _("destination") : _("source")));
6427 str++;
6428 inst.instruction |= WRITE_BACK;
6429 }
6430
6431 inst.instruction |= INDEX_UP;
6432 pre_inc = 1;
6433 }
6434 }
6435 else
6436 {
6437 /* [Rn,...] */
6438 if (skip_past_comma (&str) == FAIL)
6439 {
6440 inst.error = _("pre-indexed expression expected");
6441 return;
6442 }
6443
6444 pre_inc = 1;
6445 if (ldst_extend (&str) == FAIL)
6446 return;
6447
6448 skip_whitespace (str);
6449
6450 if (*str++ != ']')
6451 {
6452 inst.error = _("missing ]");
6453 return;
6454 }
6455
6456 skip_whitespace (str);
6457
6458 if (*str == '!')
6459 {
6460 if (conflict_reg)
6461 as_warn (_("%s register same as write-back base"),
6462 ((inst.instruction & LOAD_BIT)
6463 ? _("destination") : _("source")));
6464 str++;
6465 inst.instruction |= WRITE_BACK;
6466 }
6467 }
6468 }
6469 else if (*str == '=')
6470 {
f03698e6
RE
6471 if ((inst.instruction & LOAD_BIT) == 0)
6472 {
6473 inst.error = _("invalid pseudo operation");
6474 return;
6475 }
6476
90e4755a
RE
6477 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6478 str++;
6479
6480 skip_whitespace (str);
6481
6482 if (my_get_expression (&inst.reloc.exp, &str))
6483 return;
6484
6485 if (inst.reloc.exp.X_op != O_constant
6486 && inst.reloc.exp.X_op != O_symbol)
6487 {
f03698e6 6488 inst.error = _("constant expression expected");
90e4755a
RE
6489 return;
6490 }
6491
e28cd48c 6492 if (inst.reloc.exp.X_op == O_constant)
90e4755a 6493 {
e28cd48c
RE
6494 value = validate_immediate (inst.reloc.exp.X_add_number);
6495
6496 if (value != FAIL)
90e4755a 6497 {
e28cd48c
RE
6498 /* This can be done with a mov instruction. */
6499 inst.instruction &= LITERAL_MASK;
6500 inst.instruction |= (INST_IMMEDIATE
6501 | (OPCODE_MOV << DATA_OP_SHIFT));
6502 inst.instruction |= value & 0xfff;
6503 end_of_line (str);
90e4755a
RE
6504 return;
6505 }
b99bd4ef 6506
e28cd48c
RE
6507 value = validate_immediate (~inst.reloc.exp.X_add_number);
6508
6509 if (value != FAIL)
6510 {
6511 /* This can be done with a mvn instruction. */
6512 inst.instruction &= LITERAL_MASK;
6513 inst.instruction |= (INST_IMMEDIATE
6514 | (OPCODE_MVN << DATA_OP_SHIFT));
6515 inst.instruction |= value & 0xfff;
6516 end_of_line (str);
6517 return;
6518 }
90e4755a 6519 }
e28cd48c
RE
6520
6521 /* Insert into literal pool. */
6522 if (add_to_lit_pool () == FAIL)
6523 {
6524 if (!inst.error)
6525 inst.error = _("literal pool insertion failed");
6526 return;
6527 }
6528
6529 /* Change the instruction exp to point to the pool. */
6530 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6531 inst.reloc.pc_rel = 1;
6532 inst.instruction |= (REG_PC << 16);
6533 pre_inc = 1;
1cac9012
NC
6534 }
6535 else
6536 {
90e4755a
RE
6537 if (my_get_expression (&inst.reloc.exp, &str))
6538 return;
6539
6540 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6541#ifndef TE_WINCE
6542 /* PC rel adjust. */
6543 inst.reloc.exp.X_add_number -= 8;
6544#endif
1cac9012 6545 inst.reloc.pc_rel = 1;
90e4755a
RE
6546 inst.instruction |= (REG_PC << 16);
6547 pre_inc = 1;
b99bd4ef
NC
6548 }
6549
90e4755a 6550 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6551 end_of_line (str);
b99bd4ef
NC
6552}
6553
6554static void
a737bd4d 6555do_ldstt (char * str)
b99bd4ef 6556{
90e4755a
RE
6557 int conflict_reg;
6558
b99bd4ef
NC
6559 skip_whitespace (str);
6560
90e4755a 6561 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
b99bd4ef
NC
6562 {
6563 if (!inst.error)
6564 inst.error = BAD_ARGS;
6565 return;
6566 }
6567
90e4755a 6568 if (skip_past_comma (& str) == FAIL)
b99bd4ef 6569 {
f03698e6 6570 inst.error = _("address expected");
b99bd4ef
NC
6571 return;
6572 }
6573
90e4755a
RE
6574 if (*str == '[')
6575 {
6576 int reg;
b99bd4ef 6577
90e4755a 6578 str++;
b99bd4ef 6579
90e4755a 6580 skip_whitespace (str);
b99bd4ef 6581
90e4755a
RE
6582 if ((reg = reg_required_here (&str, 16)) == FAIL)
6583 return;
b99bd4ef 6584
90e4755a
RE
6585 /* ldrt/strt always use post-indexed addressing, so if the base is
6586 the same as Rd, we warn. */
6587 if (conflict_reg == reg)
6588 as_warn (_("%s register same as write-back base"),
6589 ((inst.instruction & LOAD_BIT)
6590 ? _("destination") : _("source")));
6591
6592 skip_whitespace (str);
6593
6594 if (*str == ']')
6595 {
6596 str ++;
6597
6598 if (skip_past_comma (&str) == SUCCESS)
6599 {
6600 /* [Rn],... (post inc) */
6601 if (ldst_extend (&str) == FAIL)
6602 return;
6603 }
6604 else
6605 {
6606 /* [Rn] */
6607 skip_whitespace (str);
6608
6609 /* Skip a write-back '!'. */
6610 if (*str == '!')
6611 str++;
6612
6613 inst.instruction |= INDEX_UP;
6614 }
6615 }
6616 else
6617 {
6618 inst.error = _("post-indexed expression expected");
6619 return;
6620 }
6621 }
6622 else
b99bd4ef 6623 {
90e4755a 6624 inst.error = _("post-indexed expression expected");
b99bd4ef
NC
6625 return;
6626 }
6627
b99bd4ef 6628 end_of_line (str);
b99bd4ef
NC
6629}
6630
90e4755a 6631/* Halfword and signed-byte load/store operations. */
a737bd4d 6632
b99bd4ef 6633static void
a737bd4d 6634do_ldstv4 (char * str)
b99bd4ef 6635{
b99bd4ef
NC
6636 int pre_inc = 0;
6637 int conflict_reg;
6638 int value;
6639
b99bd4ef
NC
6640 skip_whitespace (str);
6641
6642 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6643 {
6644 if (!inst.error)
6645 inst.error = BAD_ARGS;
6646 return;
6647 }
6648
6649 if (skip_past_comma (& str) == FAIL)
6650 {
f03698e6 6651 inst.error = _("address expected");
b99bd4ef
NC
6652 return;
6653 }
6654
6655 if (*str == '[')
6656 {
6657 int reg;
6658
6659 str++;
6660
6661 skip_whitespace (str);
6662
6663 if ((reg = reg_required_here (&str, 16)) == FAIL)
6664 return;
6665
6666 /* Conflicts can occur on stores as well as loads. */
6667 conflict_reg = (conflict_reg == reg);
6668
6669 skip_whitespace (str);
6670
6671 if (*str == ']')
6672 {
6673 str ++;
6674
6675 if (skip_past_comma (&str) == SUCCESS)
6676 {
6677 /* [Rn],... (post inc) */
90e4755a 6678 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6679 return;
6680 if (conflict_reg)
90e4755a
RE
6681 as_warn (_("%s register same as write-back base"),
6682 ((inst.instruction & LOAD_BIT)
6683 ? _("destination") : _("source")));
b99bd4ef
NC
6684 }
6685 else
6686 {
6687 /* [Rn] */
90e4755a 6688 inst.instruction |= HWOFFSET_IMM;
b99bd4ef
NC
6689
6690 skip_whitespace (str);
6691
6692 if (*str == '!')
6693 {
6694 if (conflict_reg)
6695 as_warn (_("%s register same as write-back base"),
6696 ((inst.instruction & LOAD_BIT)
6697 ? _("destination") : _("source")));
6698 str++;
6699 inst.instruction |= WRITE_BACK;
6700 }
6701
90e4755a
RE
6702 inst.instruction |= INDEX_UP;
6703 pre_inc = 1;
b99bd4ef
NC
6704 }
6705 }
6706 else
6707 {
6708 /* [Rn,...] */
6709 if (skip_past_comma (&str) == FAIL)
6710 {
6711 inst.error = _("pre-indexed expression expected");
6712 return;
6713 }
6714
6715 pre_inc = 1;
90e4755a 6716 if (ldst_extend_v4 (&str) == FAIL)
b99bd4ef
NC
6717 return;
6718
6719 skip_whitespace (str);
6720
6721 if (*str++ != ']')
6722 {
6723 inst.error = _("missing ]");
6724 return;
6725 }
6726
6727 skip_whitespace (str);
6728
6729 if (*str == '!')
6730 {
6731 if (conflict_reg)
6732 as_warn (_("%s register same as write-back base"),
6733 ((inst.instruction & LOAD_BIT)
6734 ? _("destination") : _("source")));
6735 str++;
6736 inst.instruction |= WRITE_BACK;
6737 }
6738 }
6739 }
6740 else if (*str == '=')
6741 {
f03698e6
RE
6742 if ((inst.instruction & LOAD_BIT) == 0)
6743 {
6744 inst.error = _("invalid pseudo operation");
6745 return;
6746 }
6747
90e4755a 6748 /* XXX Does this work correctly for half-word/byte ops? */
b99bd4ef
NC
6749 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6750 str++;
6751
6752 skip_whitespace (str);
6753
6754 if (my_get_expression (&inst.reloc.exp, &str))
6755 return;
6756
6757 if (inst.reloc.exp.X_op != O_constant
6758 && inst.reloc.exp.X_op != O_symbol)
6759 {
f03698e6 6760 inst.error = _("constant expression expected");
b99bd4ef
NC
6761 return;
6762 }
6763
d8273442 6764 if (inst.reloc.exp.X_op == O_constant)
b99bd4ef 6765 {
d8273442
NC
6766 value = validate_immediate (inst.reloc.exp.X_add_number);
6767
6768 if (value != FAIL)
b99bd4ef 6769 {
d8273442
NC
6770 /* This can be done with a mov instruction. */
6771 inst.instruction &= LITERAL_MASK;
6772 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
90e4755a 6773 inst.instruction |= value & 0xfff;
d8273442 6774 end_of_line (str);
b99bd4ef
NC
6775 return;
6776 }
cc8a6dd0 6777
d8273442 6778 value = validate_immediate (~ inst.reloc.exp.X_add_number);
b99bd4ef 6779
d8273442 6780 if (value != FAIL)
b99bd4ef 6781 {
d8273442
NC
6782 /* This can be done with a mvn instruction. */
6783 inst.instruction &= LITERAL_MASK;
6784 inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
90e4755a 6785 inst.instruction |= value & 0xfff;
d8273442
NC
6786 end_of_line (str);
6787 return;
b99bd4ef 6788 }
b99bd4ef 6789 }
d8273442
NC
6790
6791 /* Insert into literal pool. */
6792 if (add_to_lit_pool () == FAIL)
6793 {
6794 if (!inst.error)
6795 inst.error = _("literal pool insertion failed");
6796 return;
6797 }
6798
6799 /* Change the instruction exp to point to the pool. */
90e4755a
RE
6800 inst.instruction |= HWOFFSET_IMM;
6801 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
d8273442
NC
6802 inst.reloc.pc_rel = 1;
6803 inst.instruction |= (REG_PC << 16);
6804 pre_inc = 1;
b99bd4ef
NC
6805 }
6806 else
6807 {
6808 if (my_get_expression (&inst.reloc.exp, &str))
6809 return;
6810
90e4755a
RE
6811 inst.instruction |= HWOFFSET_IMM;
6812 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
b99bd4ef
NC
6813#ifndef TE_WINCE
6814 /* PC rel adjust. */
6815 inst.reloc.exp.X_add_number -= 8;
6816#endif
6817 inst.reloc.pc_rel = 1;
6818 inst.instruction |= (REG_PC << 16);
6819 pre_inc = 1;
6820 }
6821
90e4755a 6822 inst.instruction |= (pre_inc ? PRE_INDEX : 0);
b99bd4ef 6823 end_of_line (str);
b99bd4ef
NC
6824}
6825
b05fe5cf
ZW
6826static void
6827do_ldsttv4 (char * str)
6828{
6829 int conflict_reg;
6830
6831 skip_whitespace (str);
6832
6833 if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6834 {
6835 if (!inst.error)
6836 inst.error = BAD_ARGS;
6837 return;
6838 }
6839
6840 if (skip_past_comma (& str) == FAIL)
6841 {
6842 inst.error = _("address expected");
6843 return;
6844 }
6845
6846 if (*str == '[')
6847 {
6848 int reg;
6849
6850 str++;
6851
6852 skip_whitespace (str);
6853
6854 if ((reg = reg_required_here (&str, 16)) == FAIL)
6855 return;
6856
6857 /* ldrt/strt always use post-indexed addressing, so if the base is
6858 the same as Rd, we warn. */
6859 if (conflict_reg == reg)
6860 as_warn (_("%s register same as write-back base"),
6861 ((inst.instruction & LOAD_BIT)
6862 ? _("destination") : _("source")));
6863
6864 skip_whitespace (str);
6865
6866 if (*str == ']')
6867 {
6868 str ++;
6869
6870 if (skip_past_comma (&str) == SUCCESS)
6871 {
6872 /* [Rn],... (post inc) */
6873 if (ldst_extend_v4 (&str) == FAIL)
6874 return;
6875 }
6876 else
6877 {
6878 /* [Rn] */
6879 skip_whitespace (str);
6880
6881 /* Skip a write-back '!'. */
6882 if (*str == '!')
6883 str++;
6884
6885 inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
6886 }
6887 }
6888 else
6889 {
6890 inst.error = _("post-indexed expression expected");
6891 return;
6892 }
6893 }
6894 else
6895 {
6896 inst.error = _("post-indexed expression expected");
6897 return;
6898 }
6899
6900 end_of_line (str);
6901}
6902
6903
b99bd4ef 6904static long
a737bd4d 6905reg_list (char ** strp)
b99bd4ef
NC
6906{
6907 char * str = * strp;
6908 long range = 0;
6909 int another_range;
6910
6911 /* We come back here if we get ranges concatenated by '+' or '|'. */
6912 do
6913 {
6914 another_range = 0;
6915
6916 if (*str == '{')
6917 {
6918 int in_range = 0;
6919 int cur_reg = -1;
6920
6921 str++;
6922 do
6923 {
6924 int reg;
6925
6926 skip_whitespace (str);
6927
6928 if ((reg = reg_required_here (& str, -1)) == FAIL)
6929 return FAIL;
6930
6931 if (in_range)
6932 {
6933 int i;
6934
6935 if (reg <= cur_reg)
6936 {
f03698e6 6937 inst.error = _("bad range in register list");
b99bd4ef
NC
6938 return FAIL;
6939 }
6940
6941 for (i = cur_reg + 1; i < reg; i++)
6942 {
6943 if (range & (1 << i))
6944 as_tsktsk
f03698e6 6945 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6946 i);
6947 else
6948 range |= 1 << i;
6949 }
6950 in_range = 0;
6951 }
6952
6953 if (range & (1 << reg))
f03698e6 6954 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6955 reg);
6956 else if (reg <= cur_reg)
f03698e6 6957 as_tsktsk (_("Warning: register range not in ascending order"));
b99bd4ef
NC
6958
6959 range |= 1 << reg;
6960 cur_reg = reg;
6961 }
6962 while (skip_past_comma (&str) != FAIL
6963 || (in_range = 1, *str++ == '-'));
6964 str--;
6965 skip_whitespace (str);
6966
6967 if (*str++ != '}')
6968 {
f03698e6 6969 inst.error = _("missing `}'");
b99bd4ef
NC
6970 return FAIL;
6971 }
6972 }
6973 else
6974 {
6975 expressionS expr;
6976
6977 if (my_get_expression (&expr, &str))
6978 return FAIL;
6979
6980 if (expr.X_op == O_constant)
6981 {
6982 if (expr.X_add_number
6983 != (expr.X_add_number & 0x0000ffff))
6984 {
6985 inst.error = _("invalid register mask");
6986 return FAIL;
6987 }
6988
6989 if ((range & expr.X_add_number) != 0)
6990 {
6991 int regno = range & expr.X_add_number;
6992
6993 regno &= -regno;
6994 regno = (1 << regno) - 1;
6995 as_tsktsk
f03698e6 6996 (_("Warning: duplicated register (r%d) in register list"),
b99bd4ef
NC
6997 regno);
6998 }
6999
7000 range |= expr.X_add_number;
7001 }
7002 else
7003 {
7004 if (inst.reloc.type != 0)
7005 {
7006 inst.error = _("expression too complex");
7007 return FAIL;
7008 }
7009
7010 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
7011 inst.reloc.type = BFD_RELOC_ARM_MULTI;
7012 inst.reloc.pc_rel = 0;
7013 }
7014 }
7015
7016 skip_whitespace (str);
7017
7018 if (*str == '|' || *str == '+')
7019 {
7020 str++;
7021 another_range = 1;
7022 }
7023 }
7024 while (another_range);
7025
7026 *strp = str;
7027 return range;
7028}
7029
7030static void
a737bd4d 7031do_ldmstm (char * str)
b99bd4ef
NC
7032{
7033 int base_reg;
7034 long range;
7035
7036 skip_whitespace (str);
7037
7038 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
7039 return;
7040
7041 if (base_reg == REG_PC)
7042 {
7043 inst.error = _("r15 not allowed as base register");
7044 return;
7045 }
7046
7047 skip_whitespace (str);
7048
7049 if (*str == '!')
7050 {
90e4755a 7051 inst.instruction |= WRITE_BACK;
b99bd4ef
NC
7052 str++;
7053 }
7054
7055 if (skip_past_comma (&str) == FAIL
7056 || (range = reg_list (&str)) == FAIL)
7057 {
7058 if (! inst.error)
7059 inst.error = BAD_ARGS;
7060 return;
7061 }
7062
7063 if (*str == '^')
7064 {
7065 str++;
90e4755a 7066 inst.instruction |= LDM_TYPE_2_OR_3;
b99bd4ef
NC
7067 }
7068
6189168b
NC
7069 if (inst.instruction & WRITE_BACK)
7070 {
7071 /* Check for unpredictable uses of writeback. */
7072 if (inst.instruction & LOAD_BIT)
7073 {
7074 /* Not allowed in LDM type 2. */
7075 if ((inst.instruction & LDM_TYPE_2_OR_3)
7076 && ((range & (1 << REG_PC)) == 0))
7077 as_warn (_("writeback of base register is UNPREDICTABLE"));
7078 /* Only allowed if base reg not in list for other types. */
7079 else if (range & (1 << base_reg))
7080 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
7081 }
7082 else /* STM. */
7083 {
7084 /* Not allowed for type 2. */
7085 if (inst.instruction & LDM_TYPE_2_OR_3)
7086 as_warn (_("writeback of base register is UNPREDICTABLE"));
7087 /* Only allowed if base reg not in list, or first in list. */
7088 else if ((range & (1 << base_reg))
7089 && (range & ((1 << base_reg) - 1)))
7090 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
7091 }
7092 }
61b5f74b 7093
f2b7cb0a 7094 inst.instruction |= range;
b99bd4ef 7095 end_of_line (str);
b99bd4ef
NC
7096}
7097
0dd132b6
NC
7098static void
7099do_smi (char * str)
7100{
7101 skip_whitespace (str);
7102
7103 /* Allow optional leading '#'. */
7104 if (is_immediate_prefix (*str))
7105 str++;
7106
7107 if (my_get_expression (& inst.reloc.exp, & str))
7108 return;
7109
7110 inst.reloc.type = BFD_RELOC_ARM_SMI;
7111 inst.reloc.pc_rel = 0;
7112 end_of_line (str);
7113}
7114
b99bd4ef 7115static void
a737bd4d 7116do_swi (char * str)
b99bd4ef
NC
7117{
7118 skip_whitespace (str);
7119
7120 /* Allow optional leading '#'. */
7121 if (is_immediate_prefix (*str))
7122 str++;
7123
7124 if (my_get_expression (& inst.reloc.exp, & str))
7125 return;
7126
7127 inst.reloc.type = BFD_RELOC_ARM_SWI;
7128 inst.reloc.pc_rel = 0;
b99bd4ef 7129 end_of_line (str);
b99bd4ef
NC
7130}
7131
7132static void
a737bd4d 7133do_swap (char * str)
b99bd4ef
NC
7134{
7135 int reg;
7136
7137 skip_whitespace (str);
7138
7139 if ((reg = reg_required_here (&str, 12)) == FAIL)
7140 return;
7141
7142 if (reg == REG_PC)
7143 {
7144 inst.error = _("r15 not allowed in swap");
7145 return;
7146 }
7147
7148 if (skip_past_comma (&str) == FAIL
7149 || (reg = reg_required_here (&str, 0)) == FAIL)
7150 {
7151 if (!inst.error)
7152 inst.error = BAD_ARGS;
7153 return;
7154 }
7155
7156 if (reg == REG_PC)
7157 {
7158 inst.error = _("r15 not allowed in swap");
7159 return;
7160 }
7161
7162 if (skip_past_comma (&str) == FAIL
7163 || *str++ != '[')
7164 {
7165 inst.error = BAD_ARGS;
7166 return;
7167 }
7168
7169 skip_whitespace (str);
7170
7171 if ((reg = reg_required_here (&str, 16)) == FAIL)
7172 return;
7173
7174 if (reg == REG_PC)
7175 {
7176 inst.error = BAD_PC;
7177 return;
7178 }
7179
7180 skip_whitespace (str);
7181
7182 if (*str++ != ']')
7183 {
7184 inst.error = _("missing ]");
7185 return;
7186 }
7187
b99bd4ef 7188 end_of_line (str);
b99bd4ef
NC
7189}
7190
7191static void
a737bd4d 7192do_branch (char * str)
b99bd4ef
NC
7193{
7194 if (my_get_expression (&inst.reloc.exp, &str))
7195 return;
7196
7197#ifdef OBJ_ELF
7198 {
7199 char * save_in;
7200
7201 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
7202 required for the instruction. */
7203
7204 /* arm_parse_reloc () works on input_line_pointer.
7205 We actually want to parse the operands to the branch instruction
7206 passed in 'str'. Save the input pointer and restore it later. */
7207 save_in = input_line_pointer;
7208 input_line_pointer = str;
7209 if (inst.reloc.exp.X_op == O_symbol
7210 && *str == '('
7211 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
7212 {
7213 inst.reloc.type = BFD_RELOC_ARM_PLT32;
7214 inst.reloc.pc_rel = 0;
7215 /* Modify str to point to after parsed operands, otherwise
7216 end_of_line() will complain about the (PLT) left in str. */
7217 str = input_line_pointer;
7218 }
7219 else
7220 {
7221 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7222 inst.reloc.pc_rel = 1;
7223 }
7224 input_line_pointer = save_in;
7225 }
7226#else
7227 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
7228 inst.reloc.pc_rel = 1;
7229#endif /* OBJ_ELF */
7230
7231 end_of_line (str);
b99bd4ef
NC
7232}
7233
7234static void
a737bd4d 7235do_cdp (char * str)
b99bd4ef
NC
7236{
7237 /* Co-processor data operation.
7238 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
7239 skip_whitespace (str);
7240
7241 if (co_proc_number (&str) == FAIL)
7242 {
7243 if (!inst.error)
7244 inst.error = BAD_ARGS;
7245 return;
7246 }
7247
7248 if (skip_past_comma (&str) == FAIL
7249 || cp_opc_expr (&str, 20,4) == FAIL)
7250 {
7251 if (!inst.error)
7252 inst.error = BAD_ARGS;
7253 return;
7254 }
7255
7256 if (skip_past_comma (&str) == FAIL
7257 || cp_reg_required_here (&str, 12) == FAIL)
7258 {
7259 if (!inst.error)
7260 inst.error = BAD_ARGS;
7261 return;
7262 }
7263
7264 if (skip_past_comma (&str) == FAIL
7265 || cp_reg_required_here (&str, 16) == FAIL)
7266 {
7267 if (!inst.error)
7268 inst.error = BAD_ARGS;
7269 return;
7270 }
7271
7272 if (skip_past_comma (&str) == FAIL
7273 || cp_reg_required_here (&str, 0) == FAIL)
7274 {
7275 if (!inst.error)
7276 inst.error = BAD_ARGS;
7277 return;
7278 }
7279
7280 if (skip_past_comma (&str) == SUCCESS)
7281 {
7282 if (cp_opc_expr (&str, 5, 3) == FAIL)
7283 {
7284 if (!inst.error)
7285 inst.error = BAD_ARGS;
7286 return;
7287 }
7288 }
7289
7290 end_of_line (str);
b99bd4ef
NC
7291}
7292
7293static void
a737bd4d 7294do_lstc (char * str)
b99bd4ef
NC
7295{
7296 /* Co-processor register load/store.
7297 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7298
7299 skip_whitespace (str);
7300
7301 if (co_proc_number (&str) == FAIL)
7302 {
7303 if (!inst.error)
7304 inst.error = BAD_ARGS;
7305 return;
7306 }
7307
7308 if (skip_past_comma (&str) == FAIL
7309 || cp_reg_required_here (&str, 12) == FAIL)
7310 {
7311 if (!inst.error)
7312 inst.error = BAD_ARGS;
7313 return;
7314 }
7315
7316 if (skip_past_comma (&str) == FAIL
bfae80f2 7317 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7318 {
7319 if (! inst.error)
7320 inst.error = BAD_ARGS;
7321 return;
7322 }
7323
b99bd4ef 7324 end_of_line (str);
b99bd4ef
NC
7325}
7326
7327static void
a737bd4d 7328do_co_reg (char * str)
b99bd4ef
NC
7329{
7330 /* Co-processor register transfer.
7331 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7332
7333 skip_whitespace (str);
7334
7335 if (co_proc_number (&str) == FAIL)
7336 {
7337 if (!inst.error)
7338 inst.error = BAD_ARGS;
7339 return;
7340 }
7341
7342 if (skip_past_comma (&str) == FAIL
7343 || cp_opc_expr (&str, 21, 3) == FAIL)
7344 {
7345 if (!inst.error)
7346 inst.error = BAD_ARGS;
7347 return;
7348 }
7349
7350 if (skip_past_comma (&str) == FAIL
7351 || reg_required_here (&str, 12) == FAIL)
7352 {
7353 if (!inst.error)
7354 inst.error = BAD_ARGS;
7355 return;
7356 }
7357
7358 if (skip_past_comma (&str) == FAIL
7359 || cp_reg_required_here (&str, 16) == FAIL)
7360 {
7361 if (!inst.error)
7362 inst.error = BAD_ARGS;
7363 return;
7364 }
7365
7366 if (skip_past_comma (&str) == FAIL
7367 || cp_reg_required_here (&str, 0) == FAIL)
7368 {
7369 if (!inst.error)
7370 inst.error = BAD_ARGS;
7371 return;
7372 }
7373
7374 if (skip_past_comma (&str) == SUCCESS)
7375 {
7376 if (cp_opc_expr (&str, 5, 3) == FAIL)
7377 {
7378 if (!inst.error)
7379 inst.error = BAD_ARGS;
7380 return;
7381 }
7382 }
b99bd4ef
NC
7383
7384 end_of_line (str);
b99bd4ef
NC
7385}
7386
7387static void
a737bd4d 7388do_fpa_ctrl (char * str)
b99bd4ef
NC
7389{
7390 /* FP control registers.
7391 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7392
7393 skip_whitespace (str);
7394
7395 if (reg_required_here (&str, 12) == FAIL)
7396 {
7397 if (!inst.error)
7398 inst.error = BAD_ARGS;
7399 return;
7400 }
7401
7402 end_of_line (str);
b99bd4ef
NC
7403}
7404
7405static void
a737bd4d 7406do_fpa_ldst (char * str)
b99bd4ef
NC
7407{
7408 skip_whitespace (str);
7409
b99bd4ef
NC
7410 if (fp_reg_required_here (&str, 12) == FAIL)
7411 {
7412 if (!inst.error)
7413 inst.error = BAD_ARGS;
7414 return;
7415 }
7416
7417 if (skip_past_comma (&str) == FAIL
bfae80f2 7418 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7419 {
7420 if (!inst.error)
7421 inst.error = BAD_ARGS;
7422 return;
7423 }
7424
7425 end_of_line (str);
7426}
7427
7428static void
a737bd4d 7429do_fpa_ldmstm (char * str)
b99bd4ef
NC
7430{
7431 int num_regs;
7432
7433 skip_whitespace (str);
7434
7435 if (fp_reg_required_here (&str, 12) == FAIL)
7436 {
7437 if (! inst.error)
7438 inst.error = BAD_ARGS;
7439 return;
7440 }
7441
7442 /* Get Number of registers to transfer. */
7443 if (skip_past_comma (&str) == FAIL
7444 || my_get_expression (&inst.reloc.exp, &str))
7445 {
7446 if (! inst.error)
7447 inst.error = _("constant expression expected");
7448 return;
7449 }
7450
7451 if (inst.reloc.exp.X_op != O_constant)
7452 {
f03698e6 7453 inst.error = _("constant value required for number of registers");
b99bd4ef
NC
7454 return;
7455 }
7456
7457 num_regs = inst.reloc.exp.X_add_number;
7458
7459 if (num_regs < 1 || num_regs > 4)
7460 {
7461 inst.error = _("number of registers must be in the range [1:4]");
7462 return;
7463 }
7464
7465 switch (num_regs)
7466 {
7467 case 1:
7468 inst.instruction |= CP_T_X;
7469 break;
7470 case 2:
7471 inst.instruction |= CP_T_Y;
7472 break;
7473 case 3:
7474 inst.instruction |= CP_T_Y | CP_T_X;
7475 break;
7476 case 4:
7477 break;
7478 default:
7479 abort ();
7480 }
7481
e28cd48c 7482 if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format. */
b99bd4ef
NC
7483 {
7484 int reg;
7485 int write_back;
7486 int offset;
7487
7488 /* The instruction specified "ea" or "fd", so we can only accept
7489 [Rn]{!}. The instruction does not really support stacking or
7490 unstacking, so we have to emulate these by setting appropriate
7491 bits and offsets. */
7492 if (skip_past_comma (&str) == FAIL
7493 || *str != '[')
7494 {
7495 if (! inst.error)
7496 inst.error = BAD_ARGS;
7497 return;
7498 }
7499
7500 str++;
7501 skip_whitespace (str);
7502
7503 if ((reg = reg_required_here (&str, 16)) == FAIL)
7504 return;
7505
7506 skip_whitespace (str);
7507
7508 if (*str != ']')
7509 {
7510 inst.error = BAD_ARGS;
7511 return;
7512 }
7513
7514 str++;
7515 if (*str == '!')
7516 {
7517 write_back = 1;
7518 str++;
7519 if (reg == REG_PC)
7520 {
7521 inst.error =
f03698e6 7522 _("r15 not allowed as base register with write-back");
b99bd4ef
NC
7523 return;
7524 }
7525 }
7526 else
7527 write_back = 0;
7528
90e4755a 7529 if (inst.instruction & CP_T_Pre)
b99bd4ef
NC
7530 {
7531 /* Pre-decrement. */
7532 offset = 3 * num_regs;
7533 if (write_back)
90e4755a 7534 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7535 }
7536 else
7537 {
7538 /* Post-increment. */
7539 if (write_back)
7540 {
90e4755a 7541 inst.instruction |= CP_T_WB;
b99bd4ef
NC
7542 offset = 3 * num_regs;
7543 }
7544 else
7545 {
7546 /* No write-back, so convert this into a standard pre-increment
7547 instruction -- aesthetically more pleasing. */
90e4755a 7548 inst.instruction |= CP_T_Pre | CP_T_UD;
b99bd4ef
NC
7549 offset = 0;
7550 }
7551 }
7552
f2b7cb0a 7553 inst.instruction |= offset;
b99bd4ef
NC
7554 }
7555 else if (skip_past_comma (&str) == FAIL
bfae80f2 7556 || cp_address_required_here (&str, CP_WB_OK) == FAIL)
b99bd4ef
NC
7557 {
7558 if (! inst.error)
7559 inst.error = BAD_ARGS;
7560 return;
7561 }
7562
7563 end_of_line (str);
7564}
7565
7566static void
a737bd4d 7567do_fpa_dyadic (char * str)
b99bd4ef
NC
7568{
7569 skip_whitespace (str);
7570
b99bd4ef
NC
7571 if (fp_reg_required_here (&str, 12) == FAIL)
7572 {
7573 if (! inst.error)
7574 inst.error = BAD_ARGS;
7575 return;
7576 }
7577
7578 if (skip_past_comma (&str) == FAIL
7579 || fp_reg_required_here (&str, 16) == FAIL)
7580 {
7581 if (! inst.error)
7582 inst.error = BAD_ARGS;
7583 return;
7584 }
7585
7586 if (skip_past_comma (&str) == FAIL
7587 || fp_op2 (&str) == FAIL)
7588 {
7589 if (! inst.error)
7590 inst.error = BAD_ARGS;
7591 return;
7592 }
7593
b99bd4ef 7594 end_of_line (str);
b99bd4ef
NC
7595}
7596
7597static void
a737bd4d 7598do_fpa_monadic (char * str)
b99bd4ef
NC
7599{
7600 skip_whitespace (str);
7601
b99bd4ef
NC
7602 if (fp_reg_required_here (&str, 12) == FAIL)
7603 {
7604 if (! inst.error)
7605 inst.error = BAD_ARGS;
7606 return;
7607 }
7608
7609 if (skip_past_comma (&str) == FAIL
7610 || fp_op2 (&str) == FAIL)
7611 {
7612 if (! inst.error)
7613 inst.error = BAD_ARGS;
7614 return;
7615 }
7616
b99bd4ef 7617 end_of_line (str);
b99bd4ef
NC
7618}
7619
7620static void
a737bd4d 7621do_fpa_cmp (char * str)
b99bd4ef
NC
7622{
7623 skip_whitespace (str);
7624
7625 if (fp_reg_required_here (&str, 16) == FAIL)
7626 {
7627 if (! inst.error)
7628 inst.error = BAD_ARGS;
7629 return;
7630 }
7631
7632 if (skip_past_comma (&str) == FAIL
7633 || fp_op2 (&str) == FAIL)
7634 {
7635 if (! inst.error)
7636 inst.error = BAD_ARGS;
7637 return;
7638 }
7639
b99bd4ef 7640 end_of_line (str);
b99bd4ef
NC
7641}
7642
7643static void
a737bd4d 7644do_fpa_from_reg (char * str)
b99bd4ef
NC
7645{
7646 skip_whitespace (str);
7647
b99bd4ef
NC
7648 if (fp_reg_required_here (&str, 16) == FAIL)
7649 {
7650 if (! inst.error)
7651 inst.error = BAD_ARGS;
7652 return;
7653 }
7654
7655 if (skip_past_comma (&str) == FAIL
7656 || reg_required_here (&str, 12) == FAIL)
7657 {
7658 if (! inst.error)
7659 inst.error = BAD_ARGS;
7660 return;
7661 }
7662
b99bd4ef 7663 end_of_line (str);
b99bd4ef
NC
7664}
7665
7666static void
a737bd4d 7667do_fpa_to_reg (char * str)
b99bd4ef
NC
7668{
7669 skip_whitespace (str);
7670
7671 if (reg_required_here (&str, 12) == FAIL)
7672 return;
7673
7674 if (skip_past_comma (&str) == FAIL
7675 || fp_reg_required_here (&str, 0) == FAIL)
7676 {
7677 if (! inst.error)
7678 inst.error = BAD_ARGS;
7679 return;
7680 }
7681
b99bd4ef 7682 end_of_line (str);
b99bd4ef
NC
7683}
7684
7ed4c4c5
NC
7685/* Encode a VFP SP register number. */
7686
7687static void
7688vfp_sp_encode_reg (int reg, enum vfp_sp_reg_pos pos)
7689{
7690 switch (pos)
7691 {
7692 case VFP_REG_Sd:
7693 inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7694 break;
7695
7696 case VFP_REG_Sn:
7697 inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7698 break;
7699
7700 case VFP_REG_Sm:
7701 inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7702 break;
7703
7704 default:
7705 abort ();
7706 }
7707}
7708
b99bd4ef 7709static int
a737bd4d
NC
7710vfp_sp_reg_required_here (char ** str,
7711 enum vfp_sp_reg_pos pos)
b99bd4ef 7712{
bfae80f2 7713 int reg;
7ed4c4c5 7714 char * start = *str;
b99bd4ef 7715
bfae80f2 7716 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
b99bd4ef 7717 {
7ed4c4c5 7718 vfp_sp_encode_reg (reg, pos);
bfae80f2
RE
7719 return reg;
7720 }
b99bd4ef 7721
bfae80f2
RE
7722 /* In the few cases where we might be able to accept something else
7723 this error can be overridden. */
7724 inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7725
7726 /* Restore the start point. */
7727 *str = start;
7728 return FAIL;
7729}
7730
7731static int
a737bd4d
NC
7732vfp_dp_reg_required_here (char ** str,
7733 enum vfp_dp_reg_pos pos)
bfae80f2 7734{
a737bd4d
NC
7735 int reg;
7736 char * start = *str;
bfae80f2
RE
7737
7738 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7739 {
7740 switch (pos)
b99bd4ef 7741 {
bfae80f2
RE
7742 case VFP_REG_Dd:
7743 inst.instruction |= reg << 12;
7744 break;
b99bd4ef 7745
bfae80f2
RE
7746 case VFP_REG_Dn:
7747 inst.instruction |= reg << 16;
7748 break;
7749
7750 case VFP_REG_Dm:
7751 inst.instruction |= reg << 0;
7752 break;
7753
7754 default:
7755 abort ();
7756 }
7757 return reg;
b99bd4ef
NC
7758 }
7759
bfae80f2
RE
7760 /* In the few cases where we might be able to accept something else
7761 this error can be overridden. */
7762 inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
b99bd4ef 7763
bfae80f2
RE
7764 /* Restore the start point. */
7765 *str = start;
7766 return FAIL;
7767}
b99bd4ef
NC
7768
7769static void
a737bd4d 7770do_vfp_sp_monadic (char * str)
b99bd4ef 7771{
b99bd4ef
NC
7772 skip_whitespace (str);
7773
bfae80f2
RE
7774 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7775 return;
7776
7777 if (skip_past_comma (&str) == FAIL
7778 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef
NC
7779 {
7780 if (! inst.error)
7781 inst.error = BAD_ARGS;
7782 return;
7783 }
7784
bfae80f2 7785 end_of_line (str);
bfae80f2
RE
7786}
7787
7788static void
a737bd4d 7789do_vfp_dp_monadic (char * str)
bfae80f2
RE
7790{
7791 skip_whitespace (str);
7792
7793 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7794 return;
7795
7796 if (skip_past_comma (&str) == FAIL
7797 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
b99bd4ef 7798 {
bfae80f2
RE
7799 if (! inst.error)
7800 inst.error = BAD_ARGS;
7801 return;
b99bd4ef 7802 }
b99bd4ef 7803
bfae80f2 7804 end_of_line (str);
bfae80f2 7805}
b99bd4ef 7806
bfae80f2 7807static void
a737bd4d 7808do_vfp_sp_dyadic (char * str)
bfae80f2
RE
7809{
7810 skip_whitespace (str);
b99bd4ef 7811
bfae80f2
RE
7812 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7813 return;
b99bd4ef 7814
bfae80f2
RE
7815 if (skip_past_comma (&str) == FAIL
7816 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7817 || skip_past_comma (&str) == FAIL
7818 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
b99bd4ef 7819 {
bfae80f2
RE
7820 if (! inst.error)
7821 inst.error = BAD_ARGS;
7822 return;
7823 }
b99bd4ef 7824
bfae80f2 7825 end_of_line (str);
bfae80f2 7826}
b99bd4ef 7827
bfae80f2 7828static void
a737bd4d 7829do_vfp_dp_dyadic (char * str)
bfae80f2
RE
7830{
7831 skip_whitespace (str);
b99bd4ef 7832
bfae80f2
RE
7833 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7834 return;
b99bd4ef 7835
bfae80f2
RE
7836 if (skip_past_comma (&str) == FAIL
7837 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7838 || skip_past_comma (&str) == FAIL
7839 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7840 {
7841 if (! inst.error)
7842 inst.error = BAD_ARGS;
7843 return;
7844 }
b99bd4ef 7845
bfae80f2 7846 end_of_line (str);
bfae80f2 7847}
b99bd4ef 7848
bfae80f2 7849static void
a737bd4d 7850do_vfp_reg_from_sp (char * str)
bfae80f2
RE
7851{
7852 skip_whitespace (str);
7853
7854 if (reg_required_here (&str, 12) == FAIL)
7855 return;
7856
7857 if (skip_past_comma (&str) == FAIL
7858 || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7859 {
7860 if (! inst.error)
7861 inst.error = BAD_ARGS;
7862 return;
7863 }
7864
7865 end_of_line (str);
bfae80f2
RE
7866}
7867
7ed4c4c5
NC
7868/* Parse a VFP register list. If the string is invalid return FAIL.
7869 Otherwise return the number of registers, and set PBASE to the first
7870 register. Double precision registers are matched if DP is nonzero. */
a737bd4d 7871
7ed4c4c5
NC
7872static int
7873vfp_parse_reg_list (char **str, int *pbase, int dp)
a737bd4d 7874{
7ed4c4c5 7875 int base_reg;
a737bd4d 7876 int new_base;
7ed4c4c5
NC
7877 int regtype;
7878 int max_regs;
a737bd4d 7879 int count = 0;
a737bd4d 7880 int warned = 0;
7ed4c4c5
NC
7881 unsigned long mask = 0;
7882 int i;
a737bd4d
NC
7883
7884 if (**str != '{')
7885 return FAIL;
7886
7887 (*str)++;
7888 skip_whitespace (*str);
7889
7ed4c4c5 7890 if (dp)
a737bd4d 7891 {
7ed4c4c5
NC
7892 regtype = REG_TYPE_DN;
7893 max_regs = 16;
7894 }
7895 else
7896 {
7897 regtype = REG_TYPE_SN;
7898 max_regs = 32;
7899 }
a737bd4d 7900
7ed4c4c5 7901 base_reg = max_regs;
a737bd4d 7902
7ed4c4c5
NC
7903 do
7904 {
7905 new_base = arm_reg_parse (str, all_reg_maps[regtype].htab);
7906 if (new_base == FAIL)
a737bd4d 7907 {
7ed4c4c5
NC
7908 inst.error = _(all_reg_maps[regtype].expected);
7909 return FAIL;
a737bd4d
NC
7910 }
7911
7ed4c4c5
NC
7912 if (new_base < base_reg)
7913 base_reg = new_base;
7914
a737bd4d
NC
7915 if (mask & (1 << new_base))
7916 {
7917 inst.error = _("invalid register list");
7918 return FAIL;
7919 }
7920
7921 if ((mask >> new_base) != 0 && ! warned)
7922 {
7923 as_tsktsk (_("register list not in ascending order"));
7924 warned = 1;
7925 }
7926
7927 mask |= 1 << new_base;
7928 count++;
7929
7930 skip_whitespace (*str);
7931
7932 if (**str == '-') /* We have the start of a range expression */
7933 {
7934 int high_range;
7935
7936 (*str)++;
7937
7938 if ((high_range
7ed4c4c5 7939 = arm_reg_parse (str, all_reg_maps[regtype].htab))
a737bd4d
NC
7940 == FAIL)
7941 {
7ed4c4c5 7942 inst.error = _(all_reg_maps[regtype].expected);
a737bd4d
NC
7943 return FAIL;
7944 }
7945
7946 if (high_range <= new_base)
7947 {
7948 inst.error = _("register range not in ascending order");
7949 return FAIL;
7950 }
7951
7952 for (new_base++; new_base <= high_range; new_base++)
7953 {
7954 if (mask & (1 << new_base))
7955 {
7956 inst.error = _("invalid register list");
7957 return FAIL;
7958 }
7959
7960 mask |= 1 << new_base;
7961 count++;
7962 }
7963 }
7964 }
7965 while (skip_past_comma (str) != FAIL);
7966
a737bd4d
NC
7967 (*str)++;
7968
a737bd4d 7969 /* Sanity check -- should have raised a parse error above. */
7ed4c4c5 7970 if (count == 0 || count > max_regs)
a737bd4d
NC
7971 abort ();
7972
7ed4c4c5
NC
7973 *pbase = base_reg;
7974
a737bd4d 7975 /* Final test -- the registers must be consecutive. */
7ed4c4c5
NC
7976 mask >>= base_reg;
7977 for (i = 0; i < count; i++)
a737bd4d 7978 {
7ed4c4c5 7979 if ((mask & (1u << i)) == 0)
a737bd4d
NC
7980 {
7981 inst.error = _("non-contiguous register range");
7982 return FAIL;
7983 }
7984 }
7985
7ed4c4c5 7986 return count;
a737bd4d
NC
7987}
7988
bfae80f2 7989static void
a737bd4d 7990do_vfp_reg2_from_sp2 (char * str)
bfae80f2 7991{
7ed4c4c5
NC
7992 int reg;
7993
bfae80f2
RE
7994 skip_whitespace (str);
7995
e45d0630
PB
7996 if (reg_required_here (&str, 12) == FAIL
7997 || skip_past_comma (&str) == FAIL
bfae80f2
RE
7998 || reg_required_here (&str, 16) == FAIL
7999 || skip_past_comma (&str) == FAIL)
8000 {
8001 if (! inst.error)
8002 inst.error = BAD_ARGS;
8003 return;
8004 }
8005
8006 /* We require exactly two consecutive SP registers. */
7ed4c4c5 8007 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
bfae80f2
RE
8008 {
8009 if (! inst.error)
8010 inst.error = _("only two consecutive VFP SP registers allowed here");
8011 }
7ed4c4c5 8012 vfp_sp_encode_reg (reg, VFP_REG_Sm);
bfae80f2
RE
8013
8014 end_of_line (str);
bfae80f2
RE
8015}
8016
8017static void
a737bd4d 8018do_vfp_sp_from_reg (char * str)
bfae80f2
RE
8019{
8020 skip_whitespace (str);
8021
8022 if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8023 return;
8024
8025 if (skip_past_comma (&str) == FAIL
8026 || reg_required_here (&str, 12) == FAIL)
8027 {
8028 if (! inst.error)
8029 inst.error = BAD_ARGS;
8030 return;
8031 }
8032
8033 end_of_line (str);
bfae80f2
RE
8034}
8035
e45d0630 8036static void
a737bd4d 8037do_vfp_sp2_from_reg2 (char * str)
e45d0630 8038{
7ed4c4c5
NC
8039 int reg;
8040
e45d0630
PB
8041 skip_whitespace (str);
8042
8043 /* We require exactly two consecutive SP registers. */
7ed4c4c5 8044 if (vfp_parse_reg_list (&str, &reg, 0) != 2)
e45d0630
PB
8045 {
8046 if (! inst.error)
8047 inst.error = _("only two consecutive VFP SP registers allowed here");
8048 }
7ed4c4c5 8049 vfp_sp_encode_reg (reg, VFP_REG_Sm);
e45d0630
PB
8050
8051 if (skip_past_comma (&str) == FAIL
8052 || reg_required_here (&str, 12) == FAIL
8053 || skip_past_comma (&str) == FAIL
8054 || reg_required_here (&str, 16) == FAIL)
8055 {
8056 if (! inst.error)
8057 inst.error = BAD_ARGS;
8058 return;
8059 }
8060
8061 end_of_line (str);
8062}
8063
bfae80f2 8064static void
a737bd4d 8065do_vfp_reg_from_dp (char * str)
bfae80f2
RE
8066{
8067 skip_whitespace (str);
8068
8069 if (reg_required_here (&str, 12) == FAIL)
8070 return;
8071
8072 if (skip_past_comma (&str) == FAIL
8073 || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8074 {
8075 if (! inst.error)
8076 inst.error = BAD_ARGS;
8077 return;
8078 }
8079
8080 end_of_line (str);
bfae80f2
RE
8081}
8082
8083static void
a737bd4d 8084do_vfp_reg2_from_dp (char * str)
bfae80f2
RE
8085{
8086 skip_whitespace (str);
8087
8088 if (reg_required_here (&str, 12) == FAIL)
8089 return;
8090
8091 if (skip_past_comma (&str) == FAIL
8092 || reg_required_here (&str, 16) == FAIL
8093 || skip_past_comma (&str) == FAIL
8094 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8095 {
8096 if (! inst.error)
8097 inst.error = BAD_ARGS;
8098 return;
8099 }
8100
8101 end_of_line (str);
bfae80f2
RE
8102}
8103
8104static void
a737bd4d 8105do_vfp_dp_from_reg (char * str)
bfae80f2
RE
8106{
8107 skip_whitespace (str);
8108
8109 if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
8110 return;
8111
8112 if (skip_past_comma (&str) == FAIL
8113 || reg_required_here (&str, 12) == FAIL)
8114 {
8115 if (! inst.error)
8116 inst.error = BAD_ARGS;
8117 return;
8118 }
8119
8120 end_of_line (str);
bfae80f2
RE
8121}
8122
8123static void
a737bd4d 8124do_vfp_dp_from_reg2 (char * str)
bfae80f2
RE
8125{
8126 skip_whitespace (str);
8127
8128 if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8129 return;
8130
8131 if (skip_past_comma (&str) == FAIL
8132 || reg_required_here (&str, 12) == FAIL
8133 || skip_past_comma (&str) == FAIL
e45d0630 8134 || reg_required_here (&str, 16) == FAIL)
bfae80f2
RE
8135 {
8136 if (! inst.error)
8137 inst.error = BAD_ARGS;
8138 return;
8139 }
8140
8141 end_of_line (str);
bfae80f2
RE
8142}
8143
8144static const struct vfp_reg *
a737bd4d 8145vfp_psr_parse (char ** str)
bfae80f2
RE
8146{
8147 char *start = *str;
8148 char c;
8149 char *p;
8150 const struct vfp_reg *vreg;
8151
8152 p = start;
8153
8154 /* Find the end of the current token. */
8155 do
8156 {
8157 c = *p++;
8158 }
8159 while (ISALPHA (c));
8160
8161 /* Mark it. */
8162 *--p = 0;
8163
cc8a6dd0 8164 for (vreg = vfp_regs + 0;
bfae80f2
RE
8165 vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
8166 vreg++)
8167 {
a737bd4d 8168 if (streq (start, vreg->name))
bfae80f2
RE
8169 {
8170 *p = c;
8171 *str = p;
8172 return vreg;
8173 }
8174 }
8175
8176 *p = c;
8177 return NULL;
8178}
8179
8180static int
a737bd4d 8181vfp_psr_required_here (char ** str)
bfae80f2
RE
8182{
8183 char *start = *str;
8184 const struct vfp_reg *vreg;
8185
8186 vreg = vfp_psr_parse (str);
8187
8188 if (vreg)
8189 {
8190 inst.instruction |= vreg->regno;
8191 return SUCCESS;
8192 }
8193
8194 inst.error = _("VFP system register expected");
8195
8196 *str = start;
8197 return FAIL;
8198}
8199
8200static void
a737bd4d 8201do_vfp_reg_from_ctrl (char * str)
bfae80f2
RE
8202{
8203 skip_whitespace (str);
8204
8205 if (reg_required_here (&str, 12) == FAIL)
8206 return;
8207
8208 if (skip_past_comma (&str) == FAIL
8209 || vfp_psr_required_here (&str) == FAIL)
8210 {
8211 if (! inst.error)
8212 inst.error = BAD_ARGS;
8213 return;
8214 }
8215
8216 end_of_line (str);
bfae80f2
RE
8217}
8218
8219static void
a737bd4d 8220do_vfp_ctrl_from_reg (char * str)
bfae80f2
RE
8221{
8222 skip_whitespace (str);
8223
8224 if (vfp_psr_required_here (&str) == FAIL)
8225 return;
8226
8227 if (skip_past_comma (&str) == FAIL
8228 || reg_required_here (&str, 12) == FAIL)
8229 {
8230 if (! inst.error)
8231 inst.error = BAD_ARGS;
8232 return;
8233 }
8234
8235 end_of_line (str);
bfae80f2
RE
8236}
8237
8238static void
a737bd4d 8239do_vfp_sp_ldst (char * str)
bfae80f2
RE
8240{
8241 skip_whitespace (str);
8242
8243 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8244 {
8245 if (!inst.error)
8246 inst.error = BAD_ARGS;
8247 return;
8248 }
8249
8250 if (skip_past_comma (&str) == FAIL
8251 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8252 {
8253 if (!inst.error)
8254 inst.error = BAD_ARGS;
8255 return;
8256 }
8257
8258 end_of_line (str);
bfae80f2
RE
8259}
8260
8261static void
a737bd4d 8262do_vfp_dp_ldst (char * str)
bfae80f2
RE
8263{
8264 skip_whitespace (str);
8265
8266 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8267 {
8268 if (!inst.error)
8269 inst.error = BAD_ARGS;
8270 return;
8271 }
8272
8273 if (skip_past_comma (&str) == FAIL
8274 || cp_address_required_here (&str, CP_NO_WB) == FAIL)
8275 {
8276 if (!inst.error)
a737bd4d
NC
8277 inst.error = BAD_ARGS;
8278 return;
bfae80f2
RE
8279 }
8280
a737bd4d 8281 end_of_line (str);
bfae80f2
RE
8282}
8283
bfae80f2
RE
8284
8285static void
a737bd4d 8286vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 8287{
7ed4c4c5
NC
8288 int count;
8289 int reg;
bfae80f2
RE
8290
8291 skip_whitespace (str);
8292
8293 if (reg_required_here (&str, 16) == FAIL)
8294 return;
8295
8296 skip_whitespace (str);
8297
8298 if (*str == '!')
8299 {
8300 inst.instruction |= WRITE_BACK;
8301 str++;
8302 }
8303 else if (ldstm_type != VFP_LDSTMIA)
8304 {
8305 inst.error = _("this addressing mode requires base-register writeback");
8306 return;
8307 }
8308
8309 if (skip_past_comma (&str) == FAIL
7ed4c4c5 8310 || (count = vfp_parse_reg_list (&str, &reg, 0)) == FAIL)
bfae80f2
RE
8311 {
8312 if (!inst.error)
8313 inst.error = BAD_ARGS;
8314 return;
8315 }
7ed4c4c5 8316 vfp_sp_encode_reg (reg, VFP_REG_Sd);
bfae80f2 8317
7ed4c4c5 8318 inst.instruction |= count;
bfae80f2
RE
8319 end_of_line (str);
8320}
8321
8322static void
a737bd4d 8323vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
bfae80f2 8324{
7ed4c4c5
NC
8325 int count;
8326 int reg;
bfae80f2
RE
8327
8328 skip_whitespace (str);
8329
8330 if (reg_required_here (&str, 16) == FAIL)
8331 return;
8332
8333 skip_whitespace (str);
8334
8335 if (*str == '!')
8336 {
8337 inst.instruction |= WRITE_BACK;
8338 str++;
8339 }
8340 else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8341 {
8342 inst.error = _("this addressing mode requires base-register writeback");
8343 return;
8344 }
8345
8346 if (skip_past_comma (&str) == FAIL
7ed4c4c5 8347 || (count = vfp_parse_reg_list (&str, &reg, 1)) == FAIL)
bfae80f2
RE
8348 {
8349 if (!inst.error)
8350 inst.error = BAD_ARGS;
8351 return;
8352 }
8353
7ed4c4c5 8354 count <<= 1;
bfae80f2 8355 if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
7ed4c4c5 8356 count += 1;
bfae80f2 8357
7ed4c4c5 8358 inst.instruction |= (reg << 12) | count;
bfae80f2
RE
8359 end_of_line (str);
8360}
8361
8362static void
a737bd4d 8363do_vfp_sp_ldstmia (char * str)
bfae80f2
RE
8364{
8365 vfp_sp_ldstm (str, VFP_LDSTMIA);
8366}
8367
8368static void
a737bd4d 8369do_vfp_sp_ldstmdb (char * str)
bfae80f2
RE
8370{
8371 vfp_sp_ldstm (str, VFP_LDSTMDB);
8372}
8373
8374static void
a737bd4d 8375do_vfp_dp_ldstmia (char * str)
bfae80f2
RE
8376{
8377 vfp_dp_ldstm (str, VFP_LDSTMIA);
8378}
8379
8380static void
a737bd4d 8381do_vfp_dp_ldstmdb (char * str)
bfae80f2
RE
8382{
8383 vfp_dp_ldstm (str, VFP_LDSTMDB);
8384}
8385
8386static void
a737bd4d 8387do_vfp_xp_ldstmia (char *str)
bfae80f2
RE
8388{
8389 vfp_dp_ldstm (str, VFP_LDSTMIAX);
8390}
8391
8392static void
a737bd4d 8393do_vfp_xp_ldstmdb (char * str)
bfae80f2
RE
8394{
8395 vfp_dp_ldstm (str, VFP_LDSTMDBX);
8396}
8397
8398static void
a737bd4d 8399do_vfp_sp_compare_z (char * str)
bfae80f2
RE
8400{
8401 skip_whitespace (str);
8402
8403 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8404 {
8405 if (!inst.error)
8406 inst.error = BAD_ARGS;
8407 return;
8408 }
8409
8410 end_of_line (str);
bfae80f2
RE
8411}
8412
8413static void
a737bd4d 8414do_vfp_dp_compare_z (char * str)
bfae80f2
RE
8415{
8416 skip_whitespace (str);
8417
8418 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8419 {
8420 if (!inst.error)
8421 inst.error = BAD_ARGS;
8422 return;
8423 }
8424
8425 end_of_line (str);
bfae80f2
RE
8426}
8427
8428static void
a737bd4d 8429do_vfp_dp_sp_cvt (char * str)
bfae80f2
RE
8430{
8431 skip_whitespace (str);
8432
8433 if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8434 return;
8435
8436 if (skip_past_comma (&str) == FAIL
8437 || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8438 {
8439 if (! inst.error)
8440 inst.error = BAD_ARGS;
8441 return;
8442 }
8443
8444 end_of_line (str);
bfae80f2
RE
8445}
8446
8447static void
a737bd4d 8448do_vfp_sp_dp_cvt (char * str)
bfae80f2
RE
8449{
8450 skip_whitespace (str);
8451
8452 if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8453 return;
8454
8455 if (skip_past_comma (&str) == FAIL
8456 || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8457 {
8458 if (! inst.error)
8459 inst.error = BAD_ARGS;
8460 return;
8461 }
8462
8463 end_of_line (str);
bfae80f2
RE
8464}
8465
8466/* Thumb specific routines. */
8467
bfae80f2
RE
8468/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8469 was SUB. */
8470
8471static void
a737bd4d 8472thumb_add_sub (char * str, int subtract)
bfae80f2
RE
8473{
8474 int Rd, Rs, Rn = FAIL;
8475
8476 skip_whitespace (str);
8477
8478 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8479 || skip_past_comma (&str) == FAIL)
8480 {
8481 if (! inst.error)
8482 inst.error = BAD_ARGS;
8483 return;
8484 }
8485
8486 if (is_immediate_prefix (*str))
8487 {
8488 Rs = Rd;
8489 str++;
8490 if (my_get_expression (&inst.reloc.exp, &str))
8491 return;
8492 }
8493 else
8494 {
8495 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8496 return;
8497
8498 if (skip_past_comma (&str) == FAIL)
8499 {
8500 /* Two operand format, shuffle the registers
8501 and pretend there are 3. */
8502 Rn = Rs;
8503 Rs = Rd;
8504 }
8505 else if (is_immediate_prefix (*str))
8506 {
8507 str++;
8508 if (my_get_expression (&inst.reloc.exp, &str))
8509 return;
8510 }
8511 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8512 return;
8513 }
8514
8515 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8516 for the latter case, EXPR contains the immediate that was found. */
8517 if (Rn != FAIL)
8518 {
8519 /* All register format. */
8520 if (Rd > 7 || Rs > 7 || Rn > 7)
8521 {
8522 if (Rs != Rd)
8523 {
8524 inst.error = _("dest and source1 must be the same register");
8525 return;
8526 }
8527
8528 /* Can't do this for SUB. */
8529 if (subtract)
8530 {
8531 inst.error = _("subtract valid only on lo regs");
8532 return;
8533 }
8534
8535 inst.instruction = (T_OPCODE_ADD_HI
8536 | (Rd > 7 ? THUMB_H1 : 0)
8537 | (Rn > 7 ? THUMB_H2 : 0));
8538 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8539 }
8540 else
8541 {
8542 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8543 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8544 }
8545 }
8546 else
8547 {
8548 /* Immediate expression, now things start to get nasty. */
8549
8550 /* First deal with HI regs, only very restricted cases allowed:
8551 Adjusting SP, and using PC or SP to get an address. */
8552 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8553 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8554 {
8555 inst.error = _("invalid Hi register with immediate");
8556 return;
8557 }
8558
8559 if (inst.reloc.exp.X_op != O_constant)
8560 {
8561 /* Value isn't known yet, all we can do is store all the fragments
8562 we know about in the instruction and let the reloc hacking
8563 work it all out. */
8564 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8565 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8566 }
8567 else
8568 {
8569 int offset = inst.reloc.exp.X_add_number;
8570
8571 if (subtract)
358b94bd 8572 offset = - offset;
bfae80f2
RE
8573
8574 if (offset < 0)
8575 {
358b94bd 8576 offset = - offset;
bfae80f2
RE
8577 subtract = 1;
8578
8579 /* Quick check, in case offset is MIN_INT. */
8580 if (offset < 0)
8581 {
8582 inst.error = _("immediate value out of range");
8583 return;
8584 }
8585 }
358b94bd
NC
8586 /* Note - you cannot convert a subtract of 0 into an
8587 add of 0 because the carry flag is set differently. */
8588 else if (offset > 0)
bfae80f2
RE
8589 subtract = 0;
8590
8591 if (Rd == REG_SP)
8592 {
8593 if (offset & ~0x1fc)
8594 {
8595 inst.error = _("invalid immediate value for stack adjust");
8596 return;
b99bd4ef
NC
8597 }
8598 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8599 inst.instruction |= offset >> 2;
8600 }
8601 else if (Rs == REG_PC || Rs == REG_SP)
8602 {
8603 if (subtract
8604 || (offset & ~0x3fc))
8605 {
8606 inst.error = _("invalid immediate for address calculation");
8607 return;
8608 }
8609 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8610 : T_OPCODE_ADD_SP);
8611 inst.instruction |= (Rd << 8) | (offset >> 2);
8612 }
8613 else if (Rs == Rd)
8614 {
8615 if (offset & ~0xff)
8616 {
8617 inst.error = _("immediate value out of range");
8618 return;
8619 }
8620 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8621 inst.instruction |= (Rd << 8) | offset;
8622 }
8623 else
8624 {
8625 if (offset & ~0x7)
8626 {
8627 inst.error = _("immediate value out of range");
8628 return;
8629 }
8630 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8631 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8632 }
8633 }
8634 }
8635
8636 end_of_line (str);
8637}
8638
8639static void
a737bd4d 8640thumb_shift (char * str, int shift)
b99bd4ef
NC
8641{
8642 int Rd, Rs, Rn = FAIL;
8643
8644 skip_whitespace (str);
8645
8646 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8647 || skip_past_comma (&str) == FAIL)
8648 {
8649 if (! inst.error)
8650 inst.error = BAD_ARGS;
8651 return;
8652 }
8653
8654 if (is_immediate_prefix (*str))
8655 {
8656 /* Two operand immediate format, set Rs to Rd. */
8657 Rs = Rd;
8658 str ++;
8659 if (my_get_expression (&inst.reloc.exp, &str))
8660 return;
8661 }
8662 else
8663 {
8664 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8665 return;
8666
8667 if (skip_past_comma (&str) == FAIL)
8668 {
8669 /* Two operand format, shuffle the registers
8670 and pretend there are 3. */
8671 Rn = Rs;
8672 Rs = Rd;
8673 }
8674 else if (is_immediate_prefix (*str))
8675 {
8676 str++;
8677 if (my_get_expression (&inst.reloc.exp, &str))
8678 return;
8679 }
8680 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8681 return;
8682 }
8683
8684 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8685 for the latter case, EXPR contains the immediate that was found. */
8686
8687 if (Rn != FAIL)
8688 {
8689 if (Rs != Rd)
8690 {
8691 inst.error = _("source1 and dest must be same register");
8692 return;
8693 }
8694
8695 switch (shift)
8696 {
8697 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8698 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8699 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8700 }
8701
8702 inst.instruction |= Rd | (Rn << 3);
8703 }
8704 else
8705 {
8706 switch (shift)
8707 {
8708 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8709 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8710 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8711 }
8712
8713 if (inst.reloc.exp.X_op != O_constant)
8714 {
8715 /* Value isn't known yet, create a dummy reloc and let reloc
8716 hacking fix it up. */
8717 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8718 }
8719 else
8720 {
8721 unsigned shift_value = inst.reloc.exp.X_add_number;
8722
8723 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8724 {
f03698e6 8725 inst.error = _("invalid immediate for shift");
b99bd4ef
NC
8726 return;
8727 }
8728
8729 /* Shifts of zero are handled by converting to LSL. */
8730 if (shift_value == 0)
8731 inst.instruction = T_OPCODE_LSL_I;
8732
8733 /* Shifts of 32 are encoded as a shift of zero. */
8734 if (shift_value == 32)
8735 shift_value = 0;
8736
8737 inst.instruction |= shift_value << 6;
8738 }
8739
8740 inst.instruction |= Rd | (Rs << 3);
8741 }
8742
8743 end_of_line (str);
8744}
8745
8746static void
a737bd4d 8747thumb_load_store (char * str, int load_store, int size)
b99bd4ef
NC
8748{
8749 int Rd, Rb, Ro = FAIL;
8750
8751 skip_whitespace (str);
8752
8753 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8754 || skip_past_comma (&str) == FAIL)
8755 {
8756 if (! inst.error)
8757 inst.error = BAD_ARGS;
8758 return;
8759 }
8760
8761 if (*str == '[')
8762 {
8763 str++;
8764 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8765 return;
8766
8767 if (skip_past_comma (&str) != FAIL)
8768 {
8769 if (is_immediate_prefix (*str))
8770 {
8771 str++;
8772 if (my_get_expression (&inst.reloc.exp, &str))
8773 return;
8774 }
8775 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8776 return;
8777 }
8778 else
8779 {
8780 inst.reloc.exp.X_op = O_constant;
8781 inst.reloc.exp.X_add_number = 0;
8782 }
8783
8784 if (*str != ']')
8785 {
8786 inst.error = _("expected ']'");
8787 return;
8788 }
8789 str++;
8790 }
8791 else if (*str == '=')
8792 {
f03698e6
RE
8793 if (load_store != THUMB_LOAD)
8794 {
8795 inst.error = _("invalid pseudo operation");
8796 return;
8797 }
8798
b99bd4ef
NC
8799 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8800 str++;
8801
8802 skip_whitespace (str);
8803
8804 if (my_get_expression (& inst.reloc.exp, & str))
8805 return;
8806
8807 end_of_line (str);
8808
8809 if ( inst.reloc.exp.X_op != O_constant
8810 && inst.reloc.exp.X_op != O_symbol)
8811 {
8812 inst.error = "Constant expression expected";
8813 return;
8814 }
8815
8816 if (inst.reloc.exp.X_op == O_constant
8817 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8818 {
8819 /* This can be done with a mov instruction. */
8820
8821 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
8822 inst.instruction |= inst.reloc.exp.X_add_number;
8823 return;
8824 }
8825
8826 /* Insert into literal pool. */
8827 if (add_to_lit_pool () == FAIL)
8828 {
8829 if (!inst.error)
8830 inst.error = "literal pool insertion failed";
8831 return;
8832 }
8833
8834 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8835 inst.reloc.pc_rel = 1;
8836 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8837 /* Adjust ARM pipeline offset to Thumb. */
8838 inst.reloc.exp.X_add_number += 4;
8839
8840 return;
8841 }
8842 else
8843 {
8844 if (my_get_expression (&inst.reloc.exp, &str))
8845 return;
8846
8847 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8848 inst.reloc.pc_rel = 1;
8849 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset. */
8850 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8851 end_of_line (str);
8852 return;
8853 }
8854
8855 if (Rb == REG_PC || Rb == REG_SP)
8856 {
8857 if (size != THUMB_WORD)
8858 {
8859 inst.error = _("byte or halfword not valid for base register");
8860 return;
8861 }
8862 else if (Rb == REG_PC && load_store != THUMB_LOAD)
8863 {
f03698e6 8864 inst.error = _("r15 based store not allowed");
b99bd4ef
NC
8865 return;
8866 }
8867 else if (Ro != FAIL)
8868 {
f03698e6 8869 inst.error = _("invalid base register for register offset");
b99bd4ef
NC
8870 return;
8871 }
8872
8873 if (Rb == REG_PC)
8874 inst.instruction = T_OPCODE_LDR_PC;
8875 else if (load_store == THUMB_LOAD)
8876 inst.instruction = T_OPCODE_LDR_SP;
8877 else
8878 inst.instruction = T_OPCODE_STR_SP;
8879
8880 inst.instruction |= Rd << 8;
8881 if (inst.reloc.exp.X_op == O_constant)
8882 {
8883 unsigned offset = inst.reloc.exp.X_add_number;
8884
8885 if (offset & ~0x3fc)
8886 {
8887 inst.error = _("invalid offset");
8888 return;
8889 }
8890
8891 inst.instruction |= offset >> 2;
8892 }
8893 else
8894 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8895 }
8896 else if (Rb > 7)
8897 {
8898 inst.error = _("invalid base register in load/store");
8899 return;
8900 }
8901 else if (Ro == FAIL)
8902 {
8903 /* Immediate offset. */
8904 if (size == THUMB_WORD)
8905 inst.instruction = (load_store == THUMB_LOAD
8906 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8907 else if (size == THUMB_HALFWORD)
8908 inst.instruction = (load_store == THUMB_LOAD
8909 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8910 else
8911 inst.instruction = (load_store == THUMB_LOAD
8912 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8913
8914 inst.instruction |= Rd | (Rb << 3);
8915
8916 if (inst.reloc.exp.X_op == O_constant)
8917 {
8918 unsigned offset = inst.reloc.exp.X_add_number;
8919
8920 if (offset & ~(0x1f << size))
8921 {
f03698e6 8922 inst.error = _("invalid offset");
b99bd4ef
NC
8923 return;
8924 }
8925 inst.instruction |= (offset >> size) << 6;
8926 }
8927 else
8928 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8929 }
8930 else
8931 {
8932 /* Register offset. */
8933 if (size == THUMB_WORD)
8934 inst.instruction = (load_store == THUMB_LOAD
8935 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8936 else if (size == THUMB_HALFWORD)
8937 inst.instruction = (load_store == THUMB_LOAD
8938 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8939 else
8940 inst.instruction = (load_store == THUMB_LOAD
8941 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8942
8943 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8944 }
8945
8946 end_of_line (str);
8947}
8948
404ff6b5
AH
8949/* A register must be given at this point.
8950
404ff6b5
AH
8951 Shift is the place to put it in inst.instruction.
8952
404ff6b5
AH
8953 Restores input start point on err.
8954 Returns the reg#, or FAIL. */
8955
8956static int
a737bd4d 8957mav_reg_required_here (char ** str, int shift, enum arm_reg_type regtype)
404ff6b5 8958{
6c43fab6
RE
8959 int reg;
8960 char *start = *str;
404ff6b5 8961
6c43fab6 8962 if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
404ff6b5 8963 {
404ff6b5
AH
8964 if (shift >= 0)
8965 inst.instruction |= reg << shift;
8966
6c43fab6 8967 return reg;
404ff6b5
AH
8968 }
8969
6c43fab6 8970 /* Restore the start point. */
404ff6b5 8971 *str = start;
cc8a6dd0 8972
3631a3c8
NC
8973 /* Try generic coprocessor name if applicable. */
8974 if (regtype == REG_TYPE_MVF ||
8975 regtype == REG_TYPE_MVD ||
8976 regtype == REG_TYPE_MVFX ||
8977 regtype == REG_TYPE_MVDX)
8978 {
8979 if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
8980 {
8981 if (shift >= 0)
8982 inst.instruction |= reg << shift;
8983
8984 return reg;
8985 }
8986
8987 /* Restore the start point. */
8988 *str = start;
8989 }
8990
404ff6b5
AH
8991 /* In the few cases where we might be able to accept something else
8992 this error can be overridden. */
6c43fab6 8993 inst.error = _(all_reg_maps[regtype].expected);
cc8a6dd0 8994
404ff6b5
AH
8995 return FAIL;
8996}
8997
a737bd4d
NC
8998/* Cirrus Maverick Instructions. */
8999
9000/* Isnsn like "foo X,Y". */
9001
9002static void
9003do_mav_binops (char * str,
9004 int mode,
9005 enum arm_reg_type reg0,
9006 enum arm_reg_type reg1)
9007{
9008 int shift0, shift1;
9009
9010 shift0 = mode & 0xff;
9011 shift1 = (mode >> 8) & 0xff;
9012
9013 skip_whitespace (str);
9014
9015 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9016 || skip_past_comma (&str) == FAIL
9017 || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9018 {
9019 if (!inst.error)
9020 inst.error = BAD_ARGS;
9021 }
9022 else
9023 end_of_line (str);
9024}
9025
9026/* Isnsn like "foo X,Y,Z". */
9027
9028static void
9029do_mav_triple (char * str,
9030 int mode,
9031 enum arm_reg_type reg0,
9032 enum arm_reg_type reg1,
9033 enum arm_reg_type reg2)
9034{
9035 int shift0, shift1, shift2;
9036
9037 shift0 = mode & 0xff;
9038 shift1 = (mode >> 8) & 0xff;
9039 shift2 = (mode >> 16) & 0xff;
9040
9041 skip_whitespace (str);
9042
9043 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9044 || skip_past_comma (&str) == FAIL
9045 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9046 || skip_past_comma (&str) == FAIL
9047 || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9048 {
9049 if (!inst.error)
9050 inst.error = BAD_ARGS;
9051 }
9052 else
9053 end_of_line (str);
9054}
9055
9056/* Wrapper functions. */
9057
9058static void
9059do_mav_binops_1a (char * str)
9060{
9061 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
9062}
9063
9064static void
9065do_mav_binops_1b (char * str)
9066{
9067 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
9068}
9069
9070static void
9071do_mav_binops_1c (char * str)
9072{
9073 do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
9074}
9075
9076static void
9077do_mav_binops_1d (char * str)
9078{
9079 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
9080}
9081
9082static void
9083do_mav_binops_1e (char * str)
9084{
9085 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
9086}
9087
9088static void
9089do_mav_binops_1f (char * str)
9090{
9091 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
9092}
9093
9094static void
9095do_mav_binops_1g (char * str)
9096{
9097 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
9098}
9099
9100static void
9101do_mav_binops_1h (char * str)
9102{
9103 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
9104}
9105
9106static void
9107do_mav_binops_1i (char * str)
9108{
9109 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
9110}
9111
9112static void
9113do_mav_binops_1j (char * str)
9114{
9115 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
9116}
9117
9118static void
9119do_mav_binops_1k (char * str)
9120{
9121 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
9122}
9123
9124static void
9125do_mav_binops_1l (char * str)
9126{
9127 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
9128}
9129
9130static void
9131do_mav_binops_1m (char * str)
9132{
9133 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
9134}
9135
9136static void
9137do_mav_binops_1n (char * str)
9138{
9139 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
9140}
9141
9142static void
9143do_mav_binops_1o (char * str)
9144{
9145 do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
9146}
9147
9148static void
9149do_mav_binops_2a (char * str)
9150{
9151 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
9152}
9153
9154static void
9155do_mav_binops_2b (char * str)
9156{
9157 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
9158}
404ff6b5 9159
a737bd4d
NC
9160static void
9161do_mav_binops_2c (char * str)
9162{
9163 do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9164}
404ff6b5
AH
9165
9166static void
a737bd4d 9167do_mav_binops_3a (char * str)
6c43fab6 9168{
a737bd4d 9169 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
6c43fab6
RE
9170}
9171
9172static void
a737bd4d 9173do_mav_binops_3b (char * str)
6c43fab6 9174{
a737bd4d 9175 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
6c43fab6
RE
9176}
9177
9178static void
a737bd4d 9179do_mav_binops_3c (char * str)
404ff6b5 9180{
a737bd4d 9181 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
404ff6b5
AH
9182}
9183
9184static void
a737bd4d 9185do_mav_binops_3d (char * str)
404ff6b5 9186{
a737bd4d 9187 do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
404ff6b5
AH
9188}
9189
9190static void
a737bd4d 9191do_mav_triple_4a (char * str)
404ff6b5 9192{
a737bd4d 9193 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
404ff6b5
AH
9194}
9195
9196static void
a737bd4d 9197do_mav_triple_4b (char * str)
404ff6b5 9198{
a737bd4d 9199 do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
404ff6b5
AH
9200}
9201
9202static void
a737bd4d 9203do_mav_triple_5a (char * str)
404ff6b5 9204{
a737bd4d 9205 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
404ff6b5
AH
9206}
9207
9208static void
a737bd4d 9209do_mav_triple_5b (char * str)
404ff6b5 9210{
a737bd4d 9211 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
404ff6b5
AH
9212}
9213
6c43fab6 9214static void
a737bd4d 9215do_mav_triple_5c (char * str)
6c43fab6 9216{
a737bd4d 9217 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9218}
9219
9220static void
a737bd4d 9221do_mav_triple_5d (char * str)
6c43fab6 9222{
a737bd4d 9223 do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
9224}
9225
9226static void
a737bd4d 9227do_mav_triple_5e (char * str)
6c43fab6 9228{
a737bd4d 9229 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
6c43fab6
RE
9230}
9231
9232static void
a737bd4d 9233do_mav_triple_5f (char * str)
6c43fab6 9234{
a737bd4d 9235 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
6c43fab6
RE
9236}
9237
9238static void
a737bd4d 9239do_mav_triple_5g (char * str)
6c43fab6 9240{
a737bd4d 9241 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9242}
9243
9244static void
a737bd4d 9245do_mav_triple_5h (char * str)
6c43fab6 9246{
a737bd4d 9247 do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
6c43fab6
RE
9248}
9249
a737bd4d
NC
9250/* Isnsn like "foo W,X,Y,Z".
9251 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9252
6c43fab6 9253static void
a737bd4d
NC
9254do_mav_quad (char * str,
9255 int mode,
9256 enum arm_reg_type reg0,
9257 enum arm_reg_type reg1,
9258 enum arm_reg_type reg2,
9259 enum arm_reg_type reg3)
6c43fab6 9260{
a737bd4d
NC
9261 int shift0, shift1, shift2, shift3;
9262
9263 shift0= mode & 0xff;
9264 shift1 = (mode >> 8) & 0xff;
9265 shift2 = (mode >> 16) & 0xff;
9266 shift3 = (mode >> 24) & 0xff;
9267
9268 skip_whitespace (str);
9269
9270 if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9271 || skip_past_comma (&str) == FAIL
9272 || mav_reg_required_here (&str, shift1, reg1) == FAIL
9273 || skip_past_comma (&str) == FAIL
9274 || mav_reg_required_here (&str, shift2, reg2) == FAIL
9275 || skip_past_comma (&str) == FAIL
9276 || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9277 {
9278 if (!inst.error)
9279 inst.error = BAD_ARGS;
9280 }
9281 else
9282 end_of_line (str);
6c43fab6
RE
9283}
9284
9285static void
a737bd4d 9286do_mav_quad_6a (char * str)
6c43fab6 9287{
a737bd4d
NC
9288 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9289 REG_TYPE_MVFX);
6c43fab6
RE
9290}
9291
9292static void
a737bd4d 9293do_mav_quad_6b (char * str)
6c43fab6 9294{
a737bd4d
NC
9295 do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9296 REG_TYPE_MVFX);
6c43fab6
RE
9297}
9298
a737bd4d 9299/* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
6c43fab6 9300static void
a737bd4d 9301do_mav_dspsc_1 (char * str)
6c43fab6 9302{
a737bd4d
NC
9303 skip_whitespace (str);
9304
9305 /* cfmvsc32. */
9306 if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9307 || skip_past_comma (&str) == FAIL
9308 || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
9309 {
9310 if (!inst.error)
9311 inst.error = BAD_ARGS;
9312
9313 return;
9314 }
9315
9316 end_of_line (str);
6c43fab6
RE
9317}
9318
a737bd4d 9319/* cfmv32sc<cond> MVDX[15:0],DSPSC. */
6c43fab6 9320static void
a737bd4d 9321do_mav_dspsc_2 (char * str)
6c43fab6 9322{
a737bd4d
NC
9323 skip_whitespace (str);
9324
9325 /* cfmv32sc. */
9326 if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
9327 || skip_past_comma (&str) == FAIL
9328 || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9329 {
9330 if (!inst.error)
9331 inst.error = BAD_ARGS;
9332
9333 return;
9334 }
9335
9336 end_of_line (str);
6c43fab6
RE
9337}
9338
a737bd4d
NC
9339/* Maverick shift immediate instructions.
9340 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9341 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9342
6c43fab6 9343static void
a737bd4d
NC
9344do_mav_shift (char * str,
9345 enum arm_reg_type reg0,
9346 enum arm_reg_type reg1)
6c43fab6 9347{
a737bd4d
NC
9348 int error;
9349 int imm, neg = 0;
9350
9351 skip_whitespace (str);
9352
9353 error = 0;
9354
9355 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9356 || skip_past_comma (&str) == FAIL
9357 || mav_reg_required_here (&str, 16, reg1) == FAIL
9358 || skip_past_comma (&str) == FAIL)
9359 {
9360 if (!inst.error)
9361 inst.error = BAD_ARGS;
9362 return;
9363 }
9364
9365 /* Calculate the immediate operand.
9366 The operand is a 7bit signed number. */
9367 skip_whitespace (str);
9368
9369 if (*str == '#')
9370 ++str;
9371
9372 if (!ISDIGIT (*str) && *str != '-')
9373 {
9374 inst.error = _("expecting immediate, 7bit operand");
9375 return;
9376 }
9377
9378 if (*str == '-')
9379 {
9380 neg = 1;
9381 ++str;
9382 }
9383
9384 for (imm = 0; *str && ISDIGIT (*str); ++str)
9385 imm = imm * 10 + *str - '0';
9386
9387 if (imm > 64)
9388 {
9389 inst.error = _("immediate out of range");
9390 return;
9391 }
9392
9393 /* Make negative imm's into 7bit signed numbers. */
9394 if (neg)
9395 {
9396 imm = -imm;
9397 imm &= 0x0000007f;
9398 }
9399
9400 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9401 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9402 Bit 4 should be 0. */
9403 imm = (imm & 0xf) | ((imm & 0x70) << 1);
9404
9405 inst.instruction |= imm;
9406 end_of_line (str);
6c43fab6
RE
9407}
9408
9409static void
a737bd4d 9410do_mav_shift_1 (char * str)
6c43fab6 9411{
a737bd4d 9412 do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
6c43fab6
RE
9413}
9414
9415static void
a737bd4d 9416do_mav_shift_2 (char * str)
6c43fab6 9417{
a737bd4d
NC
9418 do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9419}
9420
9421static int
9422mav_parse_offset (char ** str, int * negative)
9423{
9424 char * p = *str;
9425 int offset;
9426
9427 *negative = 0;
9428
9429 skip_whitespace (p);
9430
9431 if (*p == '#')
9432 ++p;
9433
9434 if (*p == '-')
9435 {
9436 *negative = 1;
9437 ++p;
9438 }
9439
9440 if (!ISDIGIT (*p))
9441 {
9442 inst.error = _("offset expected");
9443 return 0;
9444 }
9445
9446 for (offset = 0; *p && ISDIGIT (*p); ++p)
9447 offset = offset * 10 + *p - '0';
9448
9449 if (offset > 0x3fc)
9450 {
9451 inst.error = _("offset out of range");
9452 return 0;
9453 }
9454 if (offset & 0x3)
9455 {
9456 inst.error = _("offset not a multiple of 4");
9457 return 0;
9458 }
9459
9460 *str = p;
9461
9462 return *negative ? -offset : offset;
6c43fab6
RE
9463}
9464
a737bd4d
NC
9465/* Maverick load/store instructions.
9466 <insn><cond> CRd,[Rn,<offset>]{!}.
9467 <insn><cond> CRd,[Rn],<offset>. */
9468
9469static void
9470do_mav_ldst (char * str, enum arm_reg_type reg0)
9471{
9472 int offset, negative;
9473
9474 skip_whitespace (str);
9475
9476 if (mav_reg_required_here (&str, 12, reg0) == FAIL
9477 || skip_past_comma (&str) == FAIL
9478 || *str++ != '['
9479 || reg_required_here (&str, 16) == FAIL)
9480 goto fail_ldst;
9481
9482 if (skip_past_comma (&str) == SUCCESS)
9483 {
9484 /* You are here: "<offset>]{!}". */
9485 inst.instruction |= PRE_INDEX;
9486
9487 offset = mav_parse_offset (&str, &negative);
9488
9489 if (inst.error)
9490 return;
9491
9492 if (*str++ != ']')
9493 {
9494 inst.error = _("missing ]");
9495 return;
9496 }
9497
9498 if (*str == '!')
9499 {
9500 inst.instruction |= WRITE_BACK;
9501 ++str;
9502 }
9503 }
9504 else
9505 {
9506 /* You are here: "], <offset>". */
9507 if (*str++ != ']')
9508 {
9509 inst.error = _("missing ]");
9510 return;
9511 }
9512
9513 if (skip_past_comma (&str) == FAIL
9514 || (offset = mav_parse_offset (&str, &negative), inst.error))
9515 goto fail_ldst;
6c43fab6 9516
a737bd4d
NC
9517 inst.instruction |= CP_T_WB; /* Post indexed, set bit W. */
9518 }
6c43fab6 9519
a737bd4d
NC
9520 if (negative)
9521 offset = -offset;
9522 else
9523 inst.instruction |= CP_T_UD; /* Positive, so set bit U. */
6c43fab6 9524
a737bd4d
NC
9525 inst.instruction |= offset >> 2;
9526 end_of_line (str);
9527 return;
6c43fab6 9528
a737bd4d
NC
9529fail_ldst:
9530 if (!inst.error)
9531 inst.error = BAD_ARGS;
6c43fab6
RE
9532}
9533
9534static void
a737bd4d 9535do_mav_ldst_1 (char * str)
6c43fab6 9536{
a737bd4d 9537 do_mav_ldst (str, REG_TYPE_MVF);
6c43fab6
RE
9538}
9539
9540static void
a737bd4d 9541do_mav_ldst_2 (char * str)
6c43fab6 9542{
a737bd4d 9543 do_mav_ldst (str, REG_TYPE_MVD);
6c43fab6
RE
9544}
9545
9546static void
a737bd4d 9547do_mav_ldst_3 (char * str)
6c43fab6 9548{
a737bd4d 9549 do_mav_ldst (str, REG_TYPE_MVFX);
6c43fab6
RE
9550}
9551
9552static void
a737bd4d 9553do_mav_ldst_4 (char * str)
6c43fab6 9554{
a737bd4d 9555 do_mav_ldst (str, REG_TYPE_MVDX);
6c43fab6
RE
9556}
9557
9558static void
a737bd4d 9559do_t_nop (char * str)
6c43fab6 9560{
a737bd4d
NC
9561 /* Do nothing. */
9562 end_of_line (str);
6c43fab6
RE
9563}
9564
a737bd4d
NC
9565/* Handle the Format 4 instructions that do not have equivalents in other
9566 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9567 BIC and MVN. */
6c43fab6
RE
9568
9569static void
a737bd4d 9570do_t_arit (char * str)
6c43fab6 9571{
a737bd4d 9572 int Rd, Rs, Rn;
6c43fab6 9573
6c43fab6
RE
9574 skip_whitespace (str);
9575
a737bd4d 9576 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
6c43fab6 9577 || skip_past_comma (&str) == FAIL
a737bd4d 9578 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
6c43fab6 9579 {
a737bd4d 9580 inst.error = BAD_ARGS;
6c43fab6
RE
9581 return;
9582 }
9583
a737bd4d 9584 if (skip_past_comma (&str) != FAIL)
6c43fab6 9585 {
a737bd4d
NC
9586 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9587 (It isn't allowed for CMP either, but that isn't handled by this
9588 function.) */
9589 if (inst.instruction == T_OPCODE_TST
9590 || inst.instruction == T_OPCODE_CMN
9591 || inst.instruction == T_OPCODE_NEG
9592 || inst.instruction == T_OPCODE_MVN)
9593 {
9594 inst.error = BAD_ARGS;
9595 return;
9596 }
6c43fab6 9597
a737bd4d
NC
9598 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9599 return;
9600
9601 if (Rs != Rd)
9602 {
9603 inst.error = _("dest and source1 must be the same register");
9604 return;
9605 }
9606 Rs = Rn;
6c43fab6
RE
9607 }
9608
a737bd4d
NC
9609 if (inst.instruction == T_OPCODE_MUL
9610 && Rs == Rd)
9611 as_tsktsk (_("Rs and Rd must be different in MUL"));
9612
9613 inst.instruction |= Rd | (Rs << 3);
6c43fab6 9614 end_of_line (str);
404ff6b5
AH
9615}
9616
9617static void
a737bd4d 9618do_t_add (char * str)
404ff6b5 9619{
a737bd4d 9620 thumb_add_sub (str, 0);
404ff6b5
AH
9621}
9622
9623static void
a737bd4d 9624do_t_asr (char * str)
404ff6b5 9625{
a737bd4d 9626 thumb_shift (str, THUMB_ASR);
404ff6b5
AH
9627}
9628
9629static void
a737bd4d 9630do_t_branch9 (char * str)
404ff6b5 9631{
a737bd4d
NC
9632 if (my_get_expression (&inst.reloc.exp, &str))
9633 return;
9634 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9635 inst.reloc.pc_rel = 1;
9636 end_of_line (str);
404ff6b5
AH
9637}
9638
9639static void
a737bd4d 9640do_t_branch12 (char * str)
404ff6b5 9641{
a737bd4d
NC
9642 if (my_get_expression (&inst.reloc.exp, &str))
9643 return;
9644 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9645 inst.reloc.pc_rel = 1;
9646 end_of_line (str);
404ff6b5
AH
9647}
9648
a737bd4d 9649/* Find the real, Thumb encoded start of a Thumb function. */
404ff6b5 9650
a737bd4d
NC
9651static symbolS *
9652find_real_start (symbolS * symbolP)
404ff6b5 9653{
a737bd4d
NC
9654 char * real_start;
9655 const char * name = S_GET_NAME (symbolP);
9656 symbolS * new_target;
404ff6b5 9657
a737bd4d
NC
9658 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
9659#define STUB_NAME ".real_start_of"
404ff6b5 9660
a737bd4d
NC
9661 if (name == NULL)
9662 abort ();
404ff6b5 9663
a737bd4d
NC
9664 /* Names that start with '.' are local labels, not function entry points.
9665 The compiler may generate BL instructions to these labels because it
9666 needs to perform a branch to a far away location. */
9667 if (name[0] == '.')
9668 return symbolP;
404ff6b5 9669
a737bd4d
NC
9670 real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9671 sprintf (real_start, "%s%s", STUB_NAME, name);
404ff6b5 9672
a737bd4d
NC
9673 new_target = symbol_find (real_start);
9674
9675 if (new_target == NULL)
404ff6b5 9676 {
a737bd4d
NC
9677 as_warn ("Failed to find real start of function: %s\n", name);
9678 new_target = symbolP;
404ff6b5 9679 }
404ff6b5 9680
a737bd4d
NC
9681 free (real_start);
9682
9683 return new_target;
9684}
404ff6b5
AH
9685
9686static void
a737bd4d 9687do_t_branch23 (char * str)
404ff6b5 9688{
a737bd4d
NC
9689 if (my_get_expression (& inst.reloc.exp, & str))
9690 return;
404ff6b5 9691
a737bd4d
NC
9692 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
9693 inst.reloc.pc_rel = 1;
9694 end_of_line (str);
404ff6b5 9695
a737bd4d
NC
9696 /* If the destination of the branch is a defined symbol which does not have
9697 the THUMB_FUNC attribute, then we must be calling a function which has
9698 the (interfacearm) attribute. We look for the Thumb entry point to that
9699 function and change the branch to refer to that function instead. */
9700 if ( inst.reloc.exp.X_op == O_symbol
9701 && inst.reloc.exp.X_add_symbol != NULL
9702 && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9703 && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9704 inst.reloc.exp.X_add_symbol =
9705 find_real_start (inst.reloc.exp.X_add_symbol);
404ff6b5
AH
9706}
9707
404ff6b5 9708static void
a737bd4d 9709do_t_bx (char * str)
404ff6b5 9710{
a737bd4d 9711 int reg;
404ff6b5
AH
9712
9713 skip_whitespace (str);
9714
a737bd4d
NC
9715 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9716 return;
9717
9718 /* This sets THUMB_H2 from the top bit of reg. */
9719 inst.instruction |= reg << 3;
9720
9721 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9722 should cause the alignment to be checked once it is known. This is
9723 because BX PC only works if the instruction is word aligned. */
9724
9725 end_of_line (str);
404ff6b5
AH
9726}
9727
a737bd4d
NC
9728static void
9729do_t_compare (char * str)
9730{
9731 thumb_mov_compare (str, THUMB_COMPARE);
9732}
404ff6b5
AH
9733
9734static void
a737bd4d 9735do_t_ldmstm (char * str)
404ff6b5 9736{
a737bd4d
NC
9737 int Rb;
9738 long range;
404ff6b5
AH
9739
9740 skip_whitespace (str);
9741
a737bd4d
NC
9742 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9743 return;
404ff6b5 9744
a737bd4d
NC
9745 if (*str != '!')
9746 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9747 else
9748 str++;
9749
9750 if (skip_past_comma (&str) == FAIL
9751 || (range = reg_list (&str)) == FAIL)
404ff6b5 9752 {
a737bd4d 9753 if (! inst.error)
404ff6b5
AH
9754 inst.error = BAD_ARGS;
9755 return;
9756 }
9757
620b81c1 9758 if (inst.reloc.type != BFD_RELOC_UNUSED)
404ff6b5 9759 {
a737bd4d 9760 /* This really doesn't seem worth it. */
620b81c1 9761 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d 9762 inst.error = _("expression too complex");
404ff6b5
AH
9763 return;
9764 }
9765
a737bd4d 9766 if (range & ~0xff)
404ff6b5 9767 {
a737bd4d 9768 inst.error = _("only lo-regs valid in load/store multiple");
404ff6b5
AH
9769 return;
9770 }
9771
a737bd4d 9772 inst.instruction |= (Rb << 8) | range;
404ff6b5 9773 end_of_line (str);
404ff6b5
AH
9774}
9775
a737bd4d
NC
9776static void
9777do_t_ldr (char * str)
404ff6b5 9778{
a737bd4d
NC
9779 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9780}
404ff6b5 9781
a737bd4d
NC
9782static void
9783do_t_ldrb (char * str)
9784{
9785 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9786}
404ff6b5 9787
a737bd4d
NC
9788static void
9789do_t_ldrh (char * str)
9790{
9791 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9792}
404ff6b5 9793
a737bd4d
NC
9794static void
9795do_t_lds (char * str)
9796{
9797 int Rd, Rb, Ro;
404ff6b5 9798
a737bd4d 9799 skip_whitespace (str);
404ff6b5 9800
a737bd4d
NC
9801 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9802 || skip_past_comma (&str) == FAIL
9803 || *str++ != '['
9804 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9805 || skip_past_comma (&str) == FAIL
9806 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9807 || *str++ != ']')
404ff6b5 9808 {
a737bd4d
NC
9809 if (! inst.error)
9810 inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9811 return;
404ff6b5
AH
9812 }
9813
a737bd4d
NC
9814 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9815 end_of_line (str);
9816}
404ff6b5 9817
a737bd4d
NC
9818static void
9819do_t_lsl (char * str)
9820{
9821 thumb_shift (str, THUMB_LSL);
9822}
404ff6b5 9823
a737bd4d
NC
9824static void
9825do_t_lsr (char * str)
9826{
9827 thumb_shift (str, THUMB_LSR);
404ff6b5
AH
9828}
9829
a737bd4d
NC
9830static void
9831do_t_mov (char * str)
9832{
9833 thumb_mov_compare (str, THUMB_MOVE);
9834}
404ff6b5
AH
9835
9836static void
a737bd4d 9837do_t_push_pop (char * str)
404ff6b5 9838{
a737bd4d 9839 long range;
404ff6b5
AH
9840
9841 skip_whitespace (str);
9842
a737bd4d 9843 if ((range = reg_list (&str)) == FAIL)
404ff6b5 9844 {
a737bd4d
NC
9845 if (! inst.error)
9846 inst.error = BAD_ARGS;
9847 return;
9848 }
404ff6b5 9849
620b81c1 9850 if (inst.reloc.type != BFD_RELOC_UNUSED)
a737bd4d
NC
9851 {
9852 /* This really doesn't seem worth it. */
620b81c1 9853 inst.reloc.type = BFD_RELOC_UNUSED;
a737bd4d
NC
9854 inst.error = _("expression too complex");
9855 return;
9856 }
404ff6b5 9857
a737bd4d
NC
9858 if (range & ~0xff)
9859 {
9860 if ((inst.instruction == T_OPCODE_PUSH
9861 && (range & ~0xff) == 1 << REG_LR)
9862 || (inst.instruction == T_OPCODE_POP
9863 && (range & ~0xff) == 1 << REG_PC))
404ff6b5 9864 {
a737bd4d
NC
9865 inst.instruction |= THUMB_PP_PC_LR;
9866 range &= 0xff;
404ff6b5 9867 }
a737bd4d 9868 else
404ff6b5 9869 {
a737bd4d 9870 inst.error = _("invalid register list to push/pop instruction");
404ff6b5
AH
9871 return;
9872 }
404ff6b5
AH
9873 }
9874
a737bd4d 9875 inst.instruction |= range;
404ff6b5 9876 end_of_line (str);
a737bd4d 9877}
404ff6b5 9878
a737bd4d
NC
9879static void
9880do_t_str (char * str)
9881{
9882 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
404ff6b5
AH
9883}
9884
b99bd4ef 9885static void
a737bd4d 9886do_t_strb (char * str)
b99bd4ef 9887{
a737bd4d 9888 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
b99bd4ef
NC
9889}
9890
a737bd4d
NC
9891static void
9892do_t_strh (char * str)
9893{
9894 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9895}
b99bd4ef
NC
9896
9897static void
a737bd4d 9898do_t_sub (char * str)
b99bd4ef 9899{
a737bd4d
NC
9900 thumb_add_sub (str, 1);
9901}
b99bd4ef 9902
a737bd4d
NC
9903static void
9904do_t_swi (char * str)
9905{
b99bd4ef
NC
9906 skip_whitespace (str);
9907
a737bd4d
NC
9908 if (my_get_expression (&inst.reloc.exp, &str))
9909 return;
b99bd4ef 9910
a737bd4d
NC
9911 inst.reloc.type = BFD_RELOC_ARM_SWI;
9912 end_of_line (str);
9913}
b99bd4ef 9914
a737bd4d
NC
9915static void
9916do_t_adr (char * str)
9917{
9918 int reg;
b99bd4ef 9919
a737bd4d
NC
9920 /* This is a pseudo-op of the form "adr rd, label" to be converted
9921 into a relative address of the form "add rd, pc, #label-.-4". */
9922 skip_whitespace (str);
9923
9924 /* Store Rd in temporary location inside instruction. */
9925 if ((reg = reg_required_here (&str, 4)) == FAIL
9926 || (reg > 7) /* For Thumb reg must be r0..r7. */
9927 || skip_past_comma (&str) == FAIL
9928 || my_get_expression (&inst.reloc.exp, &str))
9929 {
9930 if (!inst.error)
9931 inst.error = BAD_ARGS;
9932 return;
b99bd4ef
NC
9933 }
9934
a737bd4d
NC
9935 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9936 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
9937 inst.reloc.pc_rel = 1;
9938 inst.instruction |= REG_PC; /* Rd is already placed into the instruction. */
b99bd4ef 9939
b99bd4ef
NC
9940 end_of_line (str);
9941}
9942
9943static void
a737bd4d
NC
9944insert_reg (const struct reg_entry * r,
9945 struct hash_control * htab)
b99bd4ef 9946{
a737bd4d
NC
9947 int len = strlen (r->name) + 2;
9948 char * buf = xmalloc (len);
9949 char * buf2 = xmalloc (len);
9950 int i = 0;
b99bd4ef 9951
a737bd4d
NC
9952#ifdef REGISTER_PREFIX
9953 buf[i++] = REGISTER_PREFIX;
9954#endif
9955
9956 strcpy (buf + i, r->name);
9957
9958 for (i = 0; buf[i]; i++)
9959 buf2[i] = TOUPPER (buf[i]);
9960
9961 buf2[i] = '\0';
9962
9963 hash_insert (htab, buf, (PTR) r);
9964 hash_insert (htab, buf2, (PTR) r);
b99bd4ef
NC
9965}
9966
9967static void
a737bd4d 9968build_reg_hsh (struct reg_map * map)
b99bd4ef 9969{
a737bd4d
NC
9970 const struct reg_entry *r;
9971
9972 if ((map->htab = hash_new ()) == NULL)
9973 as_fatal (_("virtual memory exhausted"));
9974
9975 for (r = map->names; r->name != NULL; r++)
9976 insert_reg (r, map->htab);
b99bd4ef
NC
9977}
9978
9979static void
a737bd4d
NC
9980insert_reg_alias (char * str,
9981 int regnum,
9982 struct hash_control *htab)
b99bd4ef 9983{
a737bd4d
NC
9984 const char * error;
9985 struct reg_entry * new = xmalloc (sizeof (struct reg_entry));
9986 const char * name = xmalloc (strlen (str) + 1);
9987
9988 strcpy ((char *) name, str);
9989
9990 new->name = name;
9991 new->number = regnum;
9992 new->builtin = FALSE;
9993
9994 error = hash_insert (htab, name, (PTR) new);
9995 if (error)
9996 {
9997 as_bad (_("failed to create an alias for %s, reason: %s"),
9998 str, error);
9999 free ((char *) name);
10000 free (new);
10001 }
b99bd4ef
NC
10002}
10003
a737bd4d 10004/* Look for the .req directive. This is of the form:
b99bd4ef 10005
a737bd4d
NC
10006 new_register_name .req existing_register_name
10007
10008 If we find one, or if it looks sufficiently like one that we want to
10009 handle any error here, return non-zero. Otherwise return zero. */
10010
10011static int
10012create_register_alias (char * newname, char * p)
b99bd4ef 10013{
a737bd4d
NC
10014 char * q;
10015 char c;
b99bd4ef 10016
a737bd4d
NC
10017 q = p;
10018 skip_whitespace (q);
b99bd4ef 10019
a737bd4d
NC
10020 c = *p;
10021 *p = '\0';
b99bd4ef 10022
a737bd4d
NC
10023 if (*q && !strncmp (q, ".req ", 5))
10024 {
10025 char *copy_of_str;
10026 char *r;
b99bd4ef 10027
a737bd4d
NC
10028#ifndef IGNORE_OPCODE_CASE
10029 newname = original_case_string;
10030#endif
10031 copy_of_str = newname;
b99bd4ef 10032
a737bd4d
NC
10033 q += 4;
10034 skip_whitespace (q);
b99bd4ef 10035
a737bd4d
NC
10036 for (r = q; *r != '\0'; r++)
10037 if (*r == ' ')
10038 break;
b99bd4ef 10039
a737bd4d
NC
10040 if (r != q)
10041 {
10042 enum arm_reg_type new_type, old_type;
10043 int old_regno;
10044 char d = *r;
b99bd4ef 10045
a737bd4d
NC
10046 *r = '\0';
10047 old_type = arm_reg_parse_any (q);
10048 *r = d;
10049
10050 new_type = arm_reg_parse_any (newname);
10051
10052 if (new_type == REG_TYPE_MAX)
10053 {
10054 if (old_type != REG_TYPE_MAX)
10055 {
10056 old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
10057 insert_reg_alias (newname, old_regno,
10058 all_reg_maps[old_type].htab);
10059 }
10060 else
10061 as_warn (_("register '%s' does not exist\n"), q);
10062 }
10063 else if (old_type == REG_TYPE_MAX)
10064 {
10065 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10066 copy_of_str, q);
10067 }
10068 else
10069 {
10070 /* Do not warn about redefinitions to the same alias. */
10071 if (new_type != old_type
10072 || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10073 != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10074 as_warn (_("ignoring redefinition of register alias '%s'"),
10075 copy_of_str);
10076
10077 }
10078 }
10079 else
10080 as_warn (_("ignoring incomplete .req pseuso op"));
10081
10082 *p = c;
10083 return 1;
10084 }
10085
10086 *p = c;
10087 return 0;
b99bd4ef
NC
10088}
10089
10090static void
a737bd4d 10091set_constant_flonums (void)
b99bd4ef 10092{
a737bd4d 10093 int i;
b99bd4ef 10094
a737bd4d
NC
10095 for (i = 0; i < NUM_FLOAT_VALS; i++)
10096 if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10097 abort ();
b99bd4ef
NC
10098}
10099
a737bd4d
NC
10100\f
10101static const struct asm_opcode insns[] =
b99bd4ef 10102{
a737bd4d
NC
10103 /* Core ARM Instructions. */
10104 {"and", 0xe0000000, 3, ARM_EXT_V1, do_arit},
10105 {"ands", 0xe0100000, 3, ARM_EXT_V1, do_arit},
10106 {"eor", 0xe0200000, 3, ARM_EXT_V1, do_arit},
10107 {"eors", 0xe0300000, 3, ARM_EXT_V1, do_arit},
10108 {"sub", 0xe0400000, 3, ARM_EXT_V1, do_arit},
10109 {"subs", 0xe0500000, 3, ARM_EXT_V1, do_arit},
10110 {"rsb", 0xe0600000, 3, ARM_EXT_V1, do_arit},
10111 {"rsbs", 0xe0700000, 3, ARM_EXT_V1, do_arit},
10112 {"add", 0xe0800000, 3, ARM_EXT_V1, do_arit},
10113 {"adds", 0xe0900000, 3, ARM_EXT_V1, do_arit},
10114 {"adc", 0xe0a00000, 3, ARM_EXT_V1, do_arit},
10115 {"adcs", 0xe0b00000, 3, ARM_EXT_V1, do_arit},
10116 {"sbc", 0xe0c00000, 3, ARM_EXT_V1, do_arit},
10117 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1, do_arit},
10118 {"rsc", 0xe0e00000, 3, ARM_EXT_V1, do_arit},
10119 {"rscs", 0xe0f00000, 3, ARM_EXT_V1, do_arit},
10120 {"orr", 0xe1800000, 3, ARM_EXT_V1, do_arit},
10121 {"orrs", 0xe1900000, 3, ARM_EXT_V1, do_arit},
10122 {"bic", 0xe1c00000, 3, ARM_EXT_V1, do_arit},
10123 {"bics", 0xe1d00000, 3, ARM_EXT_V1, do_arit},
10124
10125 {"tst", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10126 {"tsts", 0xe1100000, 3, ARM_EXT_V1, do_cmp},
10127 {"tstp", 0xe110f000, 3, ARM_EXT_V1, do_cmp},
10128 {"teq", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10129 {"teqs", 0xe1300000, 3, ARM_EXT_V1, do_cmp},
10130 {"teqp", 0xe130f000, 3, ARM_EXT_V1, do_cmp},
10131 {"cmp", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10132 {"cmps", 0xe1500000, 3, ARM_EXT_V1, do_cmp},
10133 {"cmpp", 0xe150f000, 3, ARM_EXT_V1, do_cmp},
10134 {"cmn", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10135 {"cmns", 0xe1700000, 3, ARM_EXT_V1, do_cmp},
10136 {"cmnp", 0xe170f000, 3, ARM_EXT_V1, do_cmp},
10137
10138 {"mov", 0xe1a00000, 3, ARM_EXT_V1, do_mov},
10139 {"movs", 0xe1b00000, 3, ARM_EXT_V1, do_mov},
10140 {"mvn", 0xe1e00000, 3, ARM_EXT_V1, do_mov},
10141 {"mvns", 0xe1f00000, 3, ARM_EXT_V1, do_mov},
10142
10143 {"ldr", 0xe4100000, 3, ARM_EXT_V1, do_ldst},
10144 {"ldrb", 0xe4500000, 3, ARM_EXT_V1, do_ldst},
10145 {"ldrt", 0xe4300000, 3, ARM_EXT_V1, do_ldstt},
10146 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1, do_ldstt},
10147 {"str", 0xe4000000, 3, ARM_EXT_V1, do_ldst},
10148 {"strb", 0xe4400000, 3, ARM_EXT_V1, do_ldst},
10149 {"strt", 0xe4200000, 3, ARM_EXT_V1, do_ldstt},
10150 {"strbt", 0xe4600000, 3, ARM_EXT_V1, do_ldstt},
10151
10152 {"stmia", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10153 {"stmib", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10154 {"stmda", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10155 {"stmdb", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10156 {"stmfd", 0xe9000000, 3, ARM_EXT_V1, do_ldmstm},
10157 {"stmfa", 0xe9800000, 3, ARM_EXT_V1, do_ldmstm},
10158 {"stmea", 0xe8800000, 3, ARM_EXT_V1, do_ldmstm},
10159 {"stmed", 0xe8000000, 3, ARM_EXT_V1, do_ldmstm},
10160
10161 {"ldmia", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10162 {"ldmib", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
10163 {"ldmda", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10164 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10165 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1, do_ldmstm},
10166 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1, do_ldmstm},
10167 {"ldmea", 0xe9100000, 3, ARM_EXT_V1, do_ldmstm},
10168 {"ldmed", 0xe9900000, 3, ARM_EXT_V1, do_ldmstm},
b99bd4ef 10169
a737bd4d
NC
10170 {"swi", 0xef000000, 3, ARM_EXT_V1, do_swi},
10171#ifdef TE_WINCE
10172 /* XXX This is the wrong place to do this. Think multi-arch. */
10173 {"bl", 0xeb000000, 2, ARM_EXT_V1, do_branch},
10174 {"b", 0xea000000, 1, ARM_EXT_V1, do_branch},
10175#else
10176 {"bl", 0xebfffffe, 2, ARM_EXT_V1, do_branch},
10177 {"b", 0xeafffffe, 1, ARM_EXT_V1, do_branch},
10178#endif
b99bd4ef 10179
a737bd4d
NC
10180 /* Pseudo ops. */
10181 {"adr", 0xe28f0000, 3, ARM_EXT_V1, do_adr},
10182 {"adrl", 0xe28f0000, 3, ARM_EXT_V1, do_adrl},
0dd132b6 10183 {"nop", 0xe1a00000, 3, ARM_EXT_V1, do_nop},
b99bd4ef 10184
a737bd4d
NC
10185 /* ARM 2 multiplies. */
10186 {"mul", 0xe0000090, 3, ARM_EXT_V2, do_mul},
10187 {"muls", 0xe0100090, 3, ARM_EXT_V2, do_mul},
10188 {"mla", 0xe0200090, 3, ARM_EXT_V2, do_mla},
10189 {"mlas", 0xe0300090, 3, ARM_EXT_V2, do_mla},
b99bd4ef 10190
a737bd4d
NC
10191 /* Generic coprocessor instructions. */
10192 {"cdp", 0xee000000, 3, ARM_EXT_V2, do_cdp},
10193 {"ldc", 0xec100000, 3, ARM_EXT_V2, do_lstc},
10194 {"ldcl", 0xec500000, 3, ARM_EXT_V2, do_lstc},
10195 {"stc", 0xec000000, 3, ARM_EXT_V2, do_lstc},
10196 {"stcl", 0xec400000, 3, ARM_EXT_V2, do_lstc},
10197 {"mcr", 0xee000010, 3, ARM_EXT_V2, do_co_reg},
10198 {"mrc", 0xee100010, 3, ARM_EXT_V2, do_co_reg},
b99bd4ef 10199
a737bd4d
NC
10200 /* ARM 3 - swp instructions. */
10201 {"swp", 0xe1000090, 3, ARM_EXT_V2S, do_swap},
10202 {"swpb", 0xe1400090, 3, ARM_EXT_V2S, do_swap},
b99bd4ef 10203
a737bd4d
NC
10204 /* ARM 6 Status register instructions. */
10205 {"mrs", 0xe10f0000, 3, ARM_EXT_V3, do_mrs},
10206 {"msr", 0xe120f000, 3, ARM_EXT_V3, do_msr},
10207 /* ScottB: our code uses 0xe128f000 for msr.
10208 NickC: but this is wrong because the bits 16 through 19 are
10209 handled by the PSR_xxx defines above. */
b99bd4ef 10210
a737bd4d
NC
10211 /* ARM 7M long multiplies. */
10212 {"smull", 0xe0c00090, 5, ARM_EXT_V3M, do_mull},
10213 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M, do_mull},
10214 {"umull", 0xe0800090, 5, ARM_EXT_V3M, do_mull},
10215 {"umulls", 0xe0900090, 5, ARM_EXT_V3M, do_mull},
10216 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M, do_mull},
10217 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M, do_mull},
10218 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M, do_mull},
10219 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M, do_mull},
b99bd4ef 10220
a737bd4d
NC
10221 /* ARM Architecture 4. */
10222 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4, do_ldstv4},
10223 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4, do_ldstv4},
10224 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4, do_ldstv4},
10225 {"strh", 0xe00000b0, 3, ARM_EXT_V4, do_ldstv4},
b99bd4ef 10226
a737bd4d
NC
10227 /* ARM Architecture 4T. */
10228 /* Note: bx (and blx) are required on V5, even if the processor does
10229 not support Thumb. */
10230 {"bx", 0xe12fff10, 2, ARM_EXT_V4T | ARM_EXT_V5, do_bx},
b99bd4ef 10231
a737bd4d
NC
10232 /* ARM Architecture 5T. */
10233 /* Note: blx has 2 variants, so the .value is set dynamically.
10234 Only one of the variants has conditional execution. */
10235 {"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
10236 {"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
10237 {"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
10238 {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
10239 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
10240 {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
10241 {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
10242 {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
10243 {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
10244 {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
b99bd4ef 10245
a737bd4d
NC
10246 /* ARM Architecture 5TExP. */
10247 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},
10248 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP, do_smla},
10249 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP, do_smla},
10250 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 10251
a737bd4d
NC
10252 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP, do_smla},
10253 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP, do_smla},
b99bd4ef 10254
a737bd4d
NC
10255 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP, do_smlal},
10256 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP, do_smlal},
10257 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP, do_smlal},
10258 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP, do_smlal},
b99bd4ef 10259
a737bd4d
NC
10260 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP, do_smul},
10261 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP, do_smul},
10262 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP, do_smul},
10263 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 10264
a737bd4d
NC
10265 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP, do_smul},
10266 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP, do_smul},
b99bd4ef 10267
a737bd4d
NC
10268 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP, do_qadd},
10269 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP, do_qadd},
10270 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP, do_qadd},
10271 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP, do_qadd},
b99bd4ef 10272
a737bd4d
NC
10273 /* ARM Architecture 5TE. */
10274 {"pld", 0xf450f000, 0, ARM_EXT_V5E, do_pld},
10275 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E, do_ldrd},
10276 {"strd", 0xe00000f0, 3, ARM_EXT_V5E, do_ldrd},
b99bd4ef 10277
a737bd4d
NC
10278 {"mcrr", 0xec400000, 4, ARM_EXT_V5E, do_co_reg2c},
10279 {"mrrc", 0xec500000, 4, ARM_EXT_V5E, do_co_reg2c},
b99bd4ef 10280
a737bd4d
NC
10281 /* ARM Architecture 5TEJ. */
10282 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
b99bd4ef 10283
a737bd4d
NC
10284 /* ARM V6. */
10285 { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
10286 { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
10287 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
10288 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
10289 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
10290 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
10291 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
10292 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
10293 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
10294 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
10295 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
10296 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
10297 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
10298 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
10299 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
10300 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
10301 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
10302 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
10303 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
10304 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
10305 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
10306 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
10307 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
10308 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
10309 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
10310 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
10311 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
10312 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
10313 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
10314 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
10315 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
10316 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
10317 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
10318 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
10319 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
10320 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
10321 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
10322 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
10323 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
10324 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
10325 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
10326 { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
10327 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
10328 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
10329 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
10330 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
10331 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
10332 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10333 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10334 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10335 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10336 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
10337 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
10338 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
10339 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
10340 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
10341 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
10342 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
10343 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
10344 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
10345 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
10346 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
10347 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
10348 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
10349 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
10350 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
10351 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
10352 { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
10353 { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
10354 { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
10355 { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
10356 { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
10357 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
10358 { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
10359 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
10360 { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
10361 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
10362 { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
10363 { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
10364 { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
10365 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
10366 { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
10367 { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
10368 { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
10369 { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
10370 { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
10371 { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
10372 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
10373 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
10374 { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
10375 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
10376 { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
10377 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
10378 { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
10379 { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
10380 { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
10381 { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
10382 { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
10383 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
b99bd4ef 10384
0dd132b6
NC
10385 /* ARM V6K. */
10386 { "clrex", 0xf57ff01f, 0, ARM_EXT_V6K, do_empty},
10387 { "ldrexb", 0xe1d00f9f, 6, ARM_EXT_V6K, do_ldrex},
10388 { "ldrexd", 0xe1b00f9f, 6, ARM_EXT_V6K, do_ldrex},
10389 { "ldrexh", 0xe1f00f9f, 6, ARM_EXT_V6K, do_ldrex},
10390 { "sev", 0xe320f004, 3, ARM_EXT_V6K, do_empty},
10391 { "strexb", 0xe1c00f90, 6, ARM_EXT_V6K, do_strex},
10392 { "strexd", 0xe1a00f90, 6, ARM_EXT_V6K, do_strex},
10393 { "strexh", 0xe1e00f90, 6, ARM_EXT_V6K, do_strex},
10394 { "wfe", 0xe320f002, 3, ARM_EXT_V6K, do_empty},
10395 { "wfi", 0xe320f003, 3, ARM_EXT_V6K, do_empty},
10396 { "yield", 0xe320f001, 5, ARM_EXT_V6K, do_empty},
7ed4c4c5 10397
0dd132b6
NC
10398 /* ARM V6Z. */
10399 { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
10400
b05fe5cf
ZW
10401 /* ARM V6T2. */
10402 { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
10403 { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
10404 { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
10405 { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
10406 { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
10407 { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
10408 { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
10409 { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
10410
10411 { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10412 { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
10413 { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
10414 { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
10415
a737bd4d
NC
10416 /* Core FPA instruction set (V1). */
10417 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10418 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10419 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
10420 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
b99bd4ef 10421
a737bd4d
NC
10422 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10423 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10424 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10425 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10426
a737bd4d
NC
10427 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10428 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10429 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
10430 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1, do_fpa_ldst},
b99bd4ef 10431
a737bd4d
NC
10432 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10433 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10434 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10435 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10436 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10437 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10438 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10439 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10440 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10441 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10442 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10443 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10444
a737bd4d
NC
10445 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10446 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10447 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10448 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10449 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10450 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10451 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10452 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10453 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10454 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10455 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10456 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10457
a737bd4d
NC
10458 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10459 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10460 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10461 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10462 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10463 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10464 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10465 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10466 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10467 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10468 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10469 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10470
a737bd4d
NC
10471 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10472 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10473 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10474 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10475 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10476 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10477 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10478 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10479 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10480 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10481 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10482 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10483
a737bd4d
NC
10484 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10485 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10486 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10487 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10488 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10489 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10490 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10491 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10492 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10493 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10494 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10495 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10496
a737bd4d
NC
10497 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10498 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10499 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10500 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10501 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10502 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10503 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10504 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10505 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10506 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10507 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10508 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10509
a737bd4d
NC
10510 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10511 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10512 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10513 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10514 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10515 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10516 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10517 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10518 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10519 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10520 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10521 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10522
a737bd4d
NC
10523 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10524 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10525 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10526 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10527 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10528 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10529 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10530 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10531 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10532 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10533 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10534 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10535
a737bd4d
NC
10536 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10537 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10538 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10539 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10540 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10541 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10542 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10543 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10544 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10545 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10546 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10547 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10548
a737bd4d
NC
10549 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10550 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10551 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10552 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10553 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10554 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10555 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10556 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10557 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10558 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10559 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10560 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10561
a737bd4d
NC
10562 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10563 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10564 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10565 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10566 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10567 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10568 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10569 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10570 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10571 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10572 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10573 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10574
a737bd4d
NC
10575 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10576 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10577 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10578 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10579 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10580 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10581 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10582 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10583 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10584 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10585 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10586 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10587
a737bd4d
NC
10588 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10589 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10590 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10591 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10592 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10593 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10594 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10595 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10596 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10597 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10598 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10599 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10600
a737bd4d
NC
10601 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10602 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10603 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10604 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10605 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10606 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10607 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10608 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10609 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10610 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10611 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10612 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10613
a737bd4d
NC
10614 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10615 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10616 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10617 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10618 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10619 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10620 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10621 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10622 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10623 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10624 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10625 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10626
a737bd4d
NC
10627 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10628 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10629 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10630 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10631 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10632 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10633 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10634 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10635 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10636 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10637 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
10638 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1, do_fpa_monadic},
b99bd4ef 10639
a737bd4d
NC
10640 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10641 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10642 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10643 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10644 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10645 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10646 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10647 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10648 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10649 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10650 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10651 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10652
a737bd4d
NC
10653 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10654 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10655 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10656 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10657 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10658 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10659 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10660 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10661 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10662 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10663 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10664 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10665
a737bd4d
NC
10666 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10667 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10668 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10669 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10670 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10671 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10672 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10673 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10674 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10675 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10676 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10677 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10678
a737bd4d
NC
10679 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10680 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10681 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10682 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10683 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10684 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10685 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10686 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10687 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10688 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10689 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10690 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10691
a737bd4d
NC
10692 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10693 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10694 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10695 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10696 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10697 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10698 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10699 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10700 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10701 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10702 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10703 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10704
a737bd4d
NC
10705 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10706 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10707 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10708 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10709 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10710 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10711 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10712 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10713 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10714 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10715 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10716 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10717
a737bd4d
NC
10718 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10719 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10720 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10721 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10722 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10723 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10724 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10725 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10726 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10727 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10728 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10729 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10730
a737bd4d
NC
10731 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10732 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10733 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10734 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10735 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10736 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10737 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10738 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10739 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10740 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10741 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10742 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10743
a737bd4d
NC
10744 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10745 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10746 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10747 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10748 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10749 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10750 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10751 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10752 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10753 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10754 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10755 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10756
a737bd4d
NC
10757 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10758 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10759 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10760 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10761 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10762 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10763 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10764 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10765 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10766 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10767 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10768 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10769
a737bd4d
NC
10770 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10771 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10772 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10773 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10774 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10775 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10776 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10777 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10778 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10779 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10780 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10781 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10782
a737bd4d
NC
10783 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10784 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10785 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10786 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10787 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10788 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10789 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10790 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10791 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10792 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10793 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10794 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
6c43fab6 10795
a737bd4d
NC
10796 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10797 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10798 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10799 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10800 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10801 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10802 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10803 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10804 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10805 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10806 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
10807 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1, do_fpa_dyadic},
b99bd4ef 10808
a737bd4d
NC
10809 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10810 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10811 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10812 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1, do_fpa_cmp},
10813 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
10814 not be an optional suffix, but part of the instruction. To be
10815 compatible, we accept either. */
10816 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
10817 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1, do_fpa_cmp},
b99bd4ef 10818
a737bd4d
NC
10819 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10820 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10821 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10822 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10823 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10824 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10825 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10826 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10827 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10828 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10829 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
10830 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1, do_fpa_from_reg},
6c43fab6 10831
a737bd4d
NC
10832 /* The implementation of the FIX instruction is broken on some
10833 assemblers, in that it accepts a precision specifier as well as a
10834 rounding specifier, despite the fact that this is meaningless.
10835 To be more compatible, we accept it as well, though of course it
10836 does not set any bits. */
10837 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10838 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10839 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10840 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10841 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10842 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10843 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10844 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10845 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10846 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10847 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10848 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
10849 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1, do_fpa_to_reg},
6c43fab6 10850
a737bd4d
NC
10851 /* Instructions that were new with the real FPA, call them V2. */
10852 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10853 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10854 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10855 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10856 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
10857 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2, do_fpa_ldmstm},
6c43fab6 10858
a737bd4d
NC
10859 /* VFP V1xD (single precision). */
10860 /* Moves and type conversions. */
10861 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10862 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
10863 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
10864 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
10865 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10866 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10867 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10868 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10869 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10870 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10871 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
10872 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
6c43fab6 10873
a737bd4d
NC
10874 /* Memory operations. */
10875 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10876 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
10877 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10878 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10879 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10880 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10881 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10882 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10883 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10884 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10885 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10886 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
10887 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10888 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
10889 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10890 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
10891 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
10892 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
6c43fab6 10893
a737bd4d
NC
10894 /* Monadic operations. */
10895 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10896 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10897 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
6c43fab6 10898
a737bd4d
NC
10899 /* Dyadic operations. */
10900 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10901 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10902 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10903 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10904 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10905 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10906 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10907 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
10908 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
6c43fab6 10909
a737bd4d
NC
10910 /* Comparisons. */
10911 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10912 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
10913 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
10914 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
6c43fab6 10915
a737bd4d
NC
10916 /* VFP V1 (Double precision). */
10917 /* Moves and type conversions. */
10918 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10919 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10920 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10921 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10922 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1, do_vfp_dp_from_reg},
10923 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10924 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1, do_vfp_reg_from_dp},
10925 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10926 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_sp_cvt},
10927 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10928 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10929 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
10930 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1, do_vfp_sp_dp_cvt},
6c43fab6 10931
a737bd4d
NC
10932 /* Memory operations. */
10933 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10934 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1, do_vfp_dp_ldst},
10935 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10936 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10937 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10938 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10939 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10940 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmia},
10941 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
10942 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1, do_vfp_dp_ldstmdb},
6c43fab6 10943
a737bd4d
NC
10944 /* Monadic operations. */
10945 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10946 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10947 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
6c43fab6 10948
a737bd4d
NC
10949 /* Dyadic operations. */
10950 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10951 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10952 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10953 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10954 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10955 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10956 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10957 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
10958 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_dyadic},
6c43fab6 10959
a737bd4d
NC
10960 /* Comparisons. */
10961 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10962 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
10963 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1, do_vfp_dp_monadic},
10964 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z},
6c43fab6 10965
a737bd4d
NC
10966 /* VFP V2. */
10967 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2},
10968 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2},
10969 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2},
10970 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp},
6c43fab6 10971
a737bd4d
NC
10972 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
10973 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE, do_xsc_mia},
10974 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10975 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10976 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10977 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10978 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE, do_xsc_mia},
10979 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE, do_xsc_mar},
10980 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE, do_xsc_mra},
cc8a6dd0 10981
a737bd4d
NC
10982 /* Intel Wireless MMX technology instructions. */
10983 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10984 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10985 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
10986 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10987 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10988 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
10989 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10990 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10991 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
10992 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10993 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10994 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10995 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10996 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10997 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
10998 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
10999 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
11000 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
11001 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
11002 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
11003 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11004 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11005 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11006 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11007 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11008 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
11009 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11010 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11011 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
11012 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
11013 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
11014 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11015 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11016 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
11017 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11018 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11019 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11020 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11021 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11022 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11023 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11024 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11025 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11026 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11027 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11028 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11029 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
11030 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11031 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11032 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11033 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11034 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11035 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11036 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11037 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11038 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11039 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11040 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11041 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11042 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11043 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11044 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11045 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11046 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11047 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11048 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11049 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11050 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11051 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11052 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11053 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11054 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11055 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11056 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11057 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11058 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11059 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11060 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11061 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11062 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11063 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11064 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11065 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11066 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11067 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11068 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11069 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11070 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11071 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
11072 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11073 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11074 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11075 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11076 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11077 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11078 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11079 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11080 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11081 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11082 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11083 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11084 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11085 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11086 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11087 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11088 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11089 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11090 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11091 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11092 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11093 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
11094 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11095 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11096 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11097 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11098 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11099 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11100 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11101 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11102 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11103 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11104 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11105 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11106 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11107 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11108 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11109 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11110 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11111 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
11112 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11113 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
11114 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11115 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
11116 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11117 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11118 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11119 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11120 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11121 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11122 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11123 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11124 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11125 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11126 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11127 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11128 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11129 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11130 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11131 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11132 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11133 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11134 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11135 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11136 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11137 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11138 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11139 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
11140 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11141 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11142 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11143 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
11144 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
b99bd4ef 11145
a737bd4d
NC
11146 /* Cirrus Maverick instructions. */
11147 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11148 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11149 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11150 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11151 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_1},
11152 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK, do_mav_ldst_2},
11153 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_3},
11154 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK, do_mav_ldst_4},
11155 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK, do_mav_binops_2a},
11156 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK, do_mav_binops_1a},
11157 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11158 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11159 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK, do_mav_binops_2b},
11160 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK, do_mav_binops_1b},
11161 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11162 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11163 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c},
11164 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c},
11165 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11166 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11167 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11168 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11169 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11170 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11171 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a},
11172 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b},
11173 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c},
11174 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d},
11175 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1},
11176 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2},
11177 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11178 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11179 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f},
11180 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK, do_mav_binops_1g},
11181 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK, do_mav_binops_1h},
11182 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1i},
11183 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1j},
11184 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1k},
11185 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11186 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11187 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
11188 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
11189 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK, do_mav_triple_4a},
11190 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK, do_mav_triple_4b},
11191 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK, do_mav_shift_1},
11192 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK, do_mav_shift_2},
11193 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK, do_mav_triple_5a},
11194 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5b},
11195 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK, do_mav_triple_5c},
11196 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5d},
11197 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11198 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11199 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d},
11200 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e},
11201 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11202 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11203 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11204 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11205 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK, do_mav_triple_5e},
11206 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK, do_mav_triple_5f},
11207 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11208 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11209 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK, do_mav_binops_1n},
11210 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK, do_mav_binops_1o},
11211 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11212 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11213 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11214 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11215 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11216 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK, do_mav_triple_5h},
11217 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11218 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK, do_mav_triple_5g},
11219 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11220 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK, do_mav_quad_6a},
11221 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11222 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK, do_mav_quad_6b},
11223};
b99bd4ef 11224
90e4755a 11225/* Iterate over the base tables to create the instruction patterns. */
a737bd4d 11226
90e4755a 11227static void
a737bd4d 11228build_arm_ops_hsh (void)
90e4755a
RE
11229{
11230 unsigned int i;
11231 unsigned int j;
11232 static struct obstack insn_obstack;
11233
11234 obstack_begin (&insn_obstack, 4000);
11235
11236 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11237 {
6c43fab6 11238 const struct asm_opcode *insn = insns + i;
90e4755a
RE
11239
11240 if (insn->cond_offset != 0)
11241 {
11242 /* Insn supports conditional execution. Build the varaints
11243 and insert them in the hash table. */
11244 for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11245 {
11246 unsigned len = strlen (insn->template);
11247 struct asm_opcode *new;
11248 char *template;
11249
11250 new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11251 /* All condition codes are two characters. */
11252 template = obstack_alloc (&insn_obstack, len + 3);
11253
11254 strncpy (template, insn->template, insn->cond_offset);
11255 strcpy (template + insn->cond_offset, conds[j].template);
11256 if (len > insn->cond_offset)
11257 strcpy (template + insn->cond_offset + 2,
11258 insn->template + insn->cond_offset);
11259 new->template = template;
11260 new->cond_offset = 0;
11261 new->variant = insn->variant;
11262 new->parms = insn->parms;
11263 new->value = (insn->value & ~COND_MASK) | conds[j].value;
11264
11265 hash_insert (arm_ops_hsh, new->template, (PTR) new);
11266 }
11267 }
11268 /* Finally, insert the unconditional insn in the table directly;
11269 no need to build a copy. */
11270 hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11271 }
11272}
11273
a737bd4d
NC
11274\f
11275static const struct thumb_opcode tinsns[] =
11276{
11277 /* Thumb v1 (ARMv4T). */
11278 {"adc", 0x4140, 2, ARM_EXT_V4T, do_t_arit},
11279 {"add", 0x0000, 2, ARM_EXT_V4T, do_t_add},
11280 {"and", 0x4000, 2, ARM_EXT_V4T, do_t_arit},
11281 {"asr", 0x0000, 2, ARM_EXT_V4T, do_t_asr},
11282 {"b", T_OPCODE_BRANCH, 2, ARM_EXT_V4T, do_t_branch12},
11283 {"beq", 0xd0fe, 2, ARM_EXT_V4T, do_t_branch9},
11284 {"bne", 0xd1fe, 2, ARM_EXT_V4T, do_t_branch9},
11285 {"bcs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11286 {"bhs", 0xd2fe, 2, ARM_EXT_V4T, do_t_branch9},
11287 {"bcc", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11288 {"bul", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11289 {"blo", 0xd3fe, 2, ARM_EXT_V4T, do_t_branch9},
11290 {"bmi", 0xd4fe, 2, ARM_EXT_V4T, do_t_branch9},
11291 {"bpl", 0xd5fe, 2, ARM_EXT_V4T, do_t_branch9},
11292 {"bvs", 0xd6fe, 2, ARM_EXT_V4T, do_t_branch9},
11293 {"bvc", 0xd7fe, 2, ARM_EXT_V4T, do_t_branch9},
11294 {"bhi", 0xd8fe, 2, ARM_EXT_V4T, do_t_branch9},
11295 {"bls", 0xd9fe, 2, ARM_EXT_V4T, do_t_branch9},
11296 {"bge", 0xdafe, 2, ARM_EXT_V4T, do_t_branch9},
11297 {"blt", 0xdbfe, 2, ARM_EXT_V4T, do_t_branch9},
11298 {"bgt", 0xdcfe, 2, ARM_EXT_V4T, do_t_branch9},
11299 {"ble", 0xddfe, 2, ARM_EXT_V4T, do_t_branch9},
11300 {"bal", 0xdefe, 2, ARM_EXT_V4T, do_t_branch9},
11301 {"bic", 0x4380, 2, ARM_EXT_V4T, do_t_arit},
11302 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
11303 {"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
11304 {"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
11305 {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
11306 {"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
11307 {"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
11308 {"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
11309 {"ldrb", 0x0000, 2, ARM_EXT_V4T, do_t_ldrb},
11310 {"ldrh", 0x0000, 2, ARM_EXT_V4T, do_t_ldrh},
11311 {"ldrsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11312 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11313 {"ldsb", 0x5600, 2, ARM_EXT_V4T, do_t_lds},
11314 {"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
11315 {"lsl", 0x0000, 2, ARM_EXT_V4T, do_t_lsl},
11316 {"lsr", 0x0000, 2, ARM_EXT_V4T, do_t_lsr},
11317 {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
11318 {"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
11319 {"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
11320 {"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
11321 {"orr", 0x4300, 2, ARM_EXT_V4T, do_t_arit},
11322 {"pop", 0xbc00, 2, ARM_EXT_V4T, do_t_push_pop},
11323 {"push", 0xb400, 2, ARM_EXT_V4T, do_t_push_pop},
11324 {"ror", 0x41c0, 2, ARM_EXT_V4T, do_t_arit},
11325 {"sbc", 0x4180, 2, ARM_EXT_V4T, do_t_arit},
11326 {"stmia", 0xc000, 2, ARM_EXT_V4T, do_t_ldmstm},
11327 {"str", 0x0000, 2, ARM_EXT_V4T, do_t_str},
11328 {"strb", 0x0000, 2, ARM_EXT_V4T, do_t_strb},
11329 {"strh", 0x0000, 2, ARM_EXT_V4T, do_t_strh},
11330 {"swi", 0xdf00, 2, ARM_EXT_V4T, do_t_swi},
11331 {"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
11332 {"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
11333 /* Pseudo ops: */
11334 {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
11335 {"nop", 0x46C0, 2, ARM_EXT_V4T, do_t_nop}, /* mov r8,r8 */
11336 /* Thumb v2 (ARMv5T). */
11337 {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
11338 {"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
11339
11340 /* ARM V6. */
11341 {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
11342 {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
11343 {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
11344 {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
11345 {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
11346 {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
11347 {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
11348 {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
11349 {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
11350 {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
11351 {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
885fc257
ZW
11352
11353 /* ARM V6K. */
11354 {"sev", 0xbf40, 2, ARM_EXT_V6K, do_empty},
11355 {"wfe", 0xbf20, 2, ARM_EXT_V6K, do_empty},
11356 {"wfi", 0xbf30, 2, ARM_EXT_V6K, do_empty},
11357 {"yield", 0xbf10, 2, ARM_EXT_V6K, do_empty},
a737bd4d 11358};
5a6c6817 11359
b99bd4ef 11360void
a737bd4d 11361md_begin (void)
b99bd4ef
NC
11362{
11363 unsigned mach;
11364 unsigned int i;
11365
11366 if ( (arm_ops_hsh = hash_new ()) == NULL
11367 || (arm_tops_hsh = hash_new ()) == NULL
11368 || (arm_cond_hsh = hash_new ()) == NULL
11369 || (arm_shift_hsh = hash_new ()) == NULL
b99bd4ef 11370 || (arm_psr_hsh = hash_new ()) == NULL)
f03698e6 11371 as_fatal (_("virtual memory exhausted"));
b99bd4ef 11372
90e4755a 11373 build_arm_ops_hsh ();
b99bd4ef
NC
11374 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11375 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11376 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11377 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11378 for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11379 hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11380 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11381 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11382
6c43fab6
RE
11383 for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11384 build_reg_hsh (all_reg_maps + i);
b99bd4ef
NC
11385
11386 set_constant_flonums ();
11387
03b1477f
RE
11388 /* Set the cpu variant based on the command-line options. We prefer
11389 -mcpu= over -march= if both are set (as for GCC); and we prefer
11390 -mfpu= over any other way of setting the floating point unit.
11391 Use of legacy options with new options are faulted. */
11392 if (legacy_cpu != -1)
11393 {
11394 if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11395 as_bad (_("use of old and new-style options to set CPU type"));
11396
11397 mcpu_cpu_opt = legacy_cpu;
11398 }
11399 else if (mcpu_cpu_opt == -1)
11400 mcpu_cpu_opt = march_cpu_opt;
11401
11402 if (legacy_fpu != -1)
11403 {
11404 if (mfpu_opt != -1)
11405 as_bad (_("use of old and new-style options to set FPU type"));
11406
11407 mfpu_opt = legacy_fpu;
11408 }
11409 else if (mfpu_opt == -1)
11410 {
4e7fd91e 11411#if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined (TE_VXWORKS))
39c2da32
RE
11412 /* Some environments specify a default FPU. If they don't, infer it
11413 from the processor. */
03b1477f
RE
11414 if (mcpu_fpu_opt != -1)
11415 mfpu_opt = mcpu_fpu_opt;
11416 else
11417 mfpu_opt = march_fpu_opt;
39c2da32
RE
11418#else
11419 mfpu_opt = FPU_DEFAULT;
11420#endif
03b1477f
RE
11421 }
11422
11423 if (mfpu_opt == -1)
11424 {
11425 if (mcpu_cpu_opt == -1)
11426 mfpu_opt = FPU_DEFAULT;
11427 else if (mcpu_cpu_opt & ARM_EXT_V5)
11428 mfpu_opt = FPU_ARCH_VFP_V2;
11429 else
11430 mfpu_opt = FPU_ARCH_FPA;
11431 }
11432
11433 if (mcpu_cpu_opt == -1)
11434 mcpu_cpu_opt = CPU_DEFAULT;
11435
11436 cpu_variant = mcpu_cpu_opt | mfpu_opt;
11437
f17c130b 11438#if defined OBJ_COFF || defined OBJ_ELF
b99bd4ef 11439 {
7cc69913
NC
11440 unsigned int flags = 0;
11441
11442#if defined OBJ_ELF
11443 flags = meabi_flags;
d507cf36
PB
11444
11445 switch (meabi_flags)
33a392fb 11446 {
d507cf36 11447 case EF_ARM_EABI_UNKNOWN:
7cc69913 11448#endif
d507cf36
PB
11449 /* Set the flags in the private structure. */
11450 if (uses_apcs_26) flags |= F_APCS26;
11451 if (support_interwork) flags |= F_INTERWORK;
11452 if (uses_apcs_float) flags |= F_APCS_FLOAT;
11453 if (pic_code) flags |= F_PIC;
11454 if ((cpu_variant & FPU_ANY) == FPU_NONE
11455 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */
7cc69913
NC
11456 flags |= F_SOFT_FLOAT;
11457
d507cf36
PB
11458 switch (mfloat_abi_opt)
11459 {
11460 case ARM_FLOAT_ABI_SOFT:
11461 case ARM_FLOAT_ABI_SOFTFP:
11462 flags |= F_SOFT_FLOAT;
11463 break;
33a392fb 11464
d507cf36
PB
11465 case ARM_FLOAT_ABI_HARD:
11466 if (flags & F_SOFT_FLOAT)
11467 as_bad (_("hard-float conflicts with specified fpu"));
11468 break;
11469 }
03b1477f 11470
7cc69913
NC
11471 /* Using VFP conventions (even if soft-float). */
11472 if (cpu_variant & FPU_VFP_EXT_NONE)
11473 flags |= F_VFP_FLOAT;
f17c130b 11474
fde78edd 11475#if defined OBJ_ELF
d507cf36
PB
11476 if (cpu_variant & FPU_ARCH_MAVERICK)
11477 flags |= EF_ARM_MAVERICK_FLOAT;
d507cf36
PB
11478 break;
11479
8cb51566 11480 case EF_ARM_EABI_VER4:
d507cf36
PB
11481 /* No additional flags to set. */
11482 break;
11483
11484 default:
11485 abort ();
11486 }
7cc69913 11487#endif
b99bd4ef
NC
11488 bfd_set_private_flags (stdoutput, flags);
11489
11490 /* We have run out flags in the COFF header to encode the
11491 status of ATPCS support, so instead we create a dummy,
11492 empty, debug section called .arm.atpcs. */
11493 if (atpcs)
11494 {
11495 asection * sec;
11496
11497 sec = bfd_make_section (stdoutput, ".arm.atpcs");
11498
11499 if (sec != NULL)
11500 {
11501 bfd_set_section_flags
11502 (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11503 bfd_set_section_size (stdoutput, sec, 0);
11504 bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11505 }
11506 }
7cc69913 11507 }
f17c130b 11508#endif
b99bd4ef
NC
11509
11510 /* Record the CPU type as well. */
11511 switch (cpu_variant & ARM_CPU_MASK)
11512 {
11513 case ARM_2:
11514 mach = bfd_mach_arm_2;
11515 break;
11516
11517 case ARM_3: /* Also ARM_250. */
11518 mach = bfd_mach_arm_2a;
11519 break;
11520
b89dddec
RE
11521 case ARM_6: /* Also ARM_7. */
11522 mach = bfd_mach_arm_3;
11523 break;
11524
b99bd4ef 11525 default:
5a6c6817 11526 mach = bfd_mach_arm_unknown;
b99bd4ef 11527 break;
b99bd4ef
NC
11528 }
11529
11530 /* Catch special cases. */
e16bb312
NC
11531 if (cpu_variant & ARM_CEXT_IWMMXT)
11532 mach = bfd_mach_arm_iWMMXt;
11533 else if (cpu_variant & ARM_CEXT_XSCALE)
b99bd4ef 11534 mach = bfd_mach_arm_XScale;
fde78edd
NC
11535 else if (cpu_variant & ARM_CEXT_MAVERICK)
11536 mach = bfd_mach_arm_ep9312;
b99bd4ef
NC
11537 else if (cpu_variant & ARM_EXT_V5E)
11538 mach = bfd_mach_arm_5TE;
11539 else if (cpu_variant & ARM_EXT_V5)
11540 {
b89dddec 11541 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11542 mach = bfd_mach_arm_5T;
11543 else
11544 mach = bfd_mach_arm_5;
11545 }
b89dddec 11546 else if (cpu_variant & ARM_EXT_V4)
b99bd4ef 11547 {
b89dddec 11548 if (cpu_variant & ARM_EXT_V4T)
b99bd4ef
NC
11549 mach = bfd_mach_arm_4T;
11550 else
11551 mach = bfd_mach_arm_4;
11552 }
b89dddec 11553 else if (cpu_variant & ARM_EXT_V3M)
b99bd4ef
NC
11554 mach = bfd_mach_arm_3M;
11555
11556 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11557}
11558
11559/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11560 for use in the a.out file, and stores them in the array pointed to by buf.
11561 This knows about the endian-ness of the target machine and does
11562 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11563 2 (short) and 4 (long) Floating numbers are put out as a series of
11564 LITTLENUMS (shorts, here at least). */
11565
11566void
a737bd4d 11567md_number_to_chars (char * buf, valueT val, int n)
b99bd4ef
NC
11568{
11569 if (target_big_endian)
11570 number_to_chars_bigendian (buf, val, n);
11571 else
11572 number_to_chars_littleendian (buf, val, n);
11573}
11574
11575static valueT
a737bd4d 11576md_chars_to_number (char * buf, int n)
b99bd4ef
NC
11577{
11578 valueT result = 0;
11579 unsigned char * where = (unsigned char *) buf;
11580
11581 if (target_big_endian)
11582 {
11583 while (n--)
11584 {
11585 result <<= 8;
11586 result |= (*where++ & 255);
11587 }
11588 }
11589 else
11590 {
11591 while (n--)
11592 {
11593 result <<= 8;
11594 result |= (where[n] & 255);
11595 }
11596 }
11597
11598 return result;
11599}
11600
11601/* Turn a string in input_line_pointer into a floating point constant
11602 of type TYPE, and store the appropriate bytes in *LITP. The number
11603 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11604 returned, or NULL on OK.
11605
11606 Note that fp constants aren't represent in the normal way on the ARM.
11607 In big endian mode, things are as expected. However, in little endian
11608 mode fp constants are big-endian word-wise, and little-endian byte-wise
11609 within the words. For example, (double) 1.1 in big endian mode is
11610 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11611 the byte sequence 99 99 f1 3f 9a 99 99 99.
11612
11613 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11614
11615char *
a737bd4d 11616md_atof (int type, char * litP, int * sizeP)
b99bd4ef
NC
11617{
11618 int prec;
11619 LITTLENUM_TYPE words[MAX_LITTLENUMS];
11620 char *t;
11621 int i;
11622
11623 switch (type)
11624 {
11625 case 'f':
11626 case 'F':
11627 case 's':
11628 case 'S':
11629 prec = 2;
11630 break;
11631
11632 case 'd':
11633 case 'D':
11634 case 'r':
11635 case 'R':
11636 prec = 4;
11637 break;
11638
11639 case 'x':
11640 case 'X':
11641 prec = 6;
11642 break;
11643
11644 case 'p':
11645 case 'P':
11646 prec = 6;
11647 break;
11648
11649 default:
11650 *sizeP = 0;
f03698e6 11651 return _("bad call to MD_ATOF()");
b99bd4ef
NC
11652 }
11653
11654 t = atof_ieee (input_line_pointer, type, words);
11655 if (t)
11656 input_line_pointer = t;
11657 *sizeP = prec * 2;
11658
11659 if (target_big_endian)
11660 {
11661 for (i = 0; i < prec; i++)
11662 {
11663 md_number_to_chars (litP, (valueT) words[i], 2);
11664 litP += 2;
11665 }
11666 }
11667 else
11668 {
bfae80f2
RE
11669 if (cpu_variant & FPU_ARCH_VFP)
11670 for (i = prec - 1; i >= 0; i--)
11671 {
11672 md_number_to_chars (litP, (valueT) words[i], 2);
11673 litP += 2;
11674 }
11675 else
11676 /* For a 4 byte float the order of elements in `words' is 1 0.
11677 For an 8 byte float the order is 1 0 3 2. */
11678 for (i = 0; i < prec; i += 2)
11679 {
11680 md_number_to_chars (litP, (valueT) words[i + 1], 2);
11681 md_number_to_chars (litP + 2, (valueT) words[i], 2);
11682 litP += 4;
11683 }
b99bd4ef
NC
11684 }
11685
11686 return 0;
11687}
11688
11689/* The knowledge of the PC's pipeline offset is built into the insns
11690 themselves. */
11691
11692long
a737bd4d 11693md_pcrel_from (fixS * fixP)
b99bd4ef
NC
11694{
11695 if (fixP->fx_addsy
11696 && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11697 && fixP->fx_subsy == NULL)
11698 return 0;
11699
11700 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11701 {
11702 /* PC relative addressing on the Thumb is slightly odd
11703 as the bottom two bits of the PC are forced to zero
11704 for the calculation. */
11705 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11706 }
11707
11708#ifdef TE_WINCE
2d2255b5
KH
11709 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11710 so we un-adjust here to compensate for the accommodation. */
b99bd4ef
NC
11711 return fixP->fx_where + fixP->fx_frag->fr_address + 8;
11712#else
11713 return fixP->fx_where + fixP->fx_frag->fr_address;
11714#endif
11715}
11716
11717/* Round up a section size to the appropriate boundary. */
11718
11719valueT
a737bd4d
NC
11720md_section_align (segT segment ATTRIBUTE_UNUSED,
11721 valueT size)
b99bd4ef
NC
11722{
11723#ifdef OBJ_ELF
11724 return size;
11725#else
11726 /* Round all sects to multiple of 4. */
11727 return (size + 3) & ~3;
11728#endif
11729}
11730
11731/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11732 Otherwise we have no need to default values of symbols. */
11733
11734symbolS *
a737bd4d 11735md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
b99bd4ef
NC
11736{
11737#ifdef OBJ_ELF
11738 if (name[0] == '_' && name[1] == 'G'
11739 && streq (name, GLOBAL_OFFSET_TABLE_NAME))
11740 {
11741 if (!GOT_symbol)
11742 {
11743 if (symbol_find (name))
11744 as_bad ("GOT already in the symbol table");
11745
11746 GOT_symbol = symbol_new (name, undefined_section,
11747 (valueT) 0, & zero_address_frag);
11748 }
11749
11750 return GOT_symbol;
11751 }
11752#endif
11753
11754 return 0;
11755}
11756
94f592af 11757void
a737bd4d
NC
11758md_apply_fix3 (fixS * fixP,
11759 valueT * valP,
11760 segT seg)
b99bd4ef 11761{
94f592af 11762 offsetT value = * valP;
b99bd4ef
NC
11763 offsetT newval;
11764 unsigned int newimm;
11765 unsigned long temp;
11766 int sign;
11767 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
11768 arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
11769
620b81c1 11770 assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
b99bd4ef
NC
11771
11772 /* Note whether this will delete the relocation. */
b99bd4ef 11773 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
b99bd4ef
NC
11774 fixP->fx_done = 1;
11775
11776 /* If this symbol is in a different section then we need to leave it for
11777 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
11778 so we have to undo it's effects here. */
11779 if (fixP->fx_pcrel)
11780 {
11781 if (fixP->fx_addsy != NULL
11782 && S_IS_DEFINED (fixP->fx_addsy)
11783 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
7f266840 11784 value += md_pcrel_from (fixP);
b99bd4ef
NC
11785 }
11786
11787 /* Remember value for emit_reloc. */
11788 fixP->fx_addnumber = value;
11789
11790 switch (fixP->fx_r_type)
11791 {
620b81c1
JB
11792 case BFD_RELOC_NONE:
11793 /* This will need to go in the object file. */
11794 fixP->fx_done = 0;
11795 break;
11796
b99bd4ef 11797 case BFD_RELOC_ARM_IMMEDIATE:
310ea308
NC
11798 /* We claim that this fixup has been processed here,
11799 even if in fact we generate an error because we do
11800 not have a reloc for it, so tc_gen_reloc will reject it. */
11801 fixP->fx_done = 1;
11802
11803 if (fixP->fx_addsy
11804 && ! S_IS_DEFINED (fixP->fx_addsy))
11805 {
11806 as_bad_where (fixP->fx_file, fixP->fx_line,
11807 _("undefined symbol %s used as an immediate value"),
11808 S_GET_NAME (fixP->fx_addsy));
11809 break;
11810 }
11811
b99bd4ef
NC
11812 newimm = validate_immediate (value);
11813 temp = md_chars_to_number (buf, INSN_SIZE);
11814
11815 /* If the instruction will fail, see if we can fix things up by
11816 changing the opcode. */
11817 if (newimm == (unsigned int) FAIL
11818 && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
11819 {
11820 as_bad_where (fixP->fx_file, fixP->fx_line,
11821 _("invalid constant (%lx) after fixup"),
11822 (unsigned long) value);
11823 break;
11824 }
11825
11826 newimm |= (temp & 0xfffff000);
11827 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11828 break;
11829
11830 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11831 {
11832 unsigned int highpart = 0;
11833 unsigned int newinsn = 0xe1a00000; /* nop. */
6189168b 11834
b99bd4ef
NC
11835 newimm = validate_immediate (value);
11836 temp = md_chars_to_number (buf, INSN_SIZE);
11837
11838 /* If the instruction will fail, see if we can fix things up by
11839 changing the opcode. */
11840 if (newimm == (unsigned int) FAIL
11841 && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
11842 {
11843 /* No ? OK - try using two ADD instructions to generate
11844 the value. */
11845 newimm = validate_immediate_twopart (value, & highpart);
11846
11847 /* Yes - then make sure that the second instruction is
11848 also an add. */
11849 if (newimm != (unsigned int) FAIL)
11850 newinsn = temp;
11851 /* Still No ? Try using a negated value. */
11852 else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
11853 temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
11854 /* Otherwise - give up. */
11855 else
11856 {
11857 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11858 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
08df2379 11859 (long) value);
b99bd4ef
NC
11860 break;
11861 }
11862
11863 /* Replace the first operand in the 2nd instruction (which
11864 is the PC) with the destination register. We have
11865 already added in the PC in the first instruction and we
11866 do not want to do it again. */
11867 newinsn &= ~ 0xf0000;
11868 newinsn |= ((newinsn & 0x0f000) << 4);
11869 }
11870
11871 newimm |= (temp & 0xfffff000);
11872 md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
11873
11874 highpart |= (newinsn & 0xfffff000);
11875 md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
11876 }
11877 break;
11878
11879 case BFD_RELOC_ARM_OFFSET_IMM:
11880 sign = value >= 0;
11881
11882 if (value < 0)
11883 value = - value;
11884
11885 if (validate_offset_imm (value, 0) == FAIL)
11886 {
11887 as_bad_where (fixP->fx_file, fixP->fx_line,
11888 _("bad immediate value for offset (%ld)"),
11889 (long) value);
11890 break;
11891 }
11892
11893 newval = md_chars_to_number (buf, INSN_SIZE);
11894 newval &= 0xff7ff000;
11895 newval |= value | (sign ? INDEX_UP : 0);
11896 md_number_to_chars (buf, newval, INSN_SIZE);
11897 break;
11898
11899 case BFD_RELOC_ARM_OFFSET_IMM8:
11900 case BFD_RELOC_ARM_HWLITERAL:
11901 sign = value >= 0;
11902
11903 if (value < 0)
11904 value = - value;
11905
11906 if (validate_offset_imm (value, 1) == FAIL)
11907 {
11908 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
11909 as_bad_where (fixP->fx_file, fixP->fx_line,
11910 _("invalid literal constant: pool needs to be closer"));
11911 else
11912 as_bad (_("bad immediate value for half-word offset (%ld)"),
11913 (long) value);
11914 break;
11915 }
11916
11917 newval = md_chars_to_number (buf, INSN_SIZE);
11918 newval &= 0xff7ff0f0;
11919 newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
11920 md_number_to_chars (buf, newval, INSN_SIZE);
11921 break;
11922
11923 case BFD_RELOC_ARM_LITERAL:
11924 sign = value >= 0;
11925
11926 if (value < 0)
11927 value = - value;
11928
11929 if (validate_offset_imm (value, 0) == FAIL)
11930 {
11931 as_bad_where (fixP->fx_file, fixP->fx_line,
11932 _("invalid literal constant: pool needs to be closer"));
11933 break;
11934 }
11935
11936 newval = md_chars_to_number (buf, INSN_SIZE);
11937 newval &= 0xff7ff000;
11938 newval |= value | (sign ? INDEX_UP : 0);
11939 md_number_to_chars (buf, newval, INSN_SIZE);
11940 break;
11941
11942 case BFD_RELOC_ARM_SHIFT_IMM:
11943 newval = md_chars_to_number (buf, INSN_SIZE);
11944 if (((unsigned long) value) > 32
11945 || (value == 32
11946 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
11947 {
11948 as_bad_where (fixP->fx_file, fixP->fx_line,
11949 _("shift expression is too large"));
11950 break;
11951 }
11952
11953 if (value == 0)
11954 /* Shifts of zero must be done as lsl. */
11955 newval &= ~0x60;
11956 else if (value == 32)
11957 value = 0;
11958 newval &= 0xfffff07f;
11959 newval |= (value & 0x1f) << 7;
11960 md_number_to_chars (buf, newval, INSN_SIZE);
11961 break;
11962
0dd132b6
NC
11963 case BFD_RELOC_ARM_SMI:
11964 if (((unsigned long) value) > 0xffff)
11965 as_bad_where (fixP->fx_file, fixP->fx_line,
11966 _("invalid smi expression"));
11967 newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
11968 newval |= (value & 0xf) | ((value & 0xfff0) << 4);
11969 md_number_to_chars (buf, newval, INSN_SIZE);
11970 break;
11971
b99bd4ef
NC
11972 case BFD_RELOC_ARM_SWI:
11973 if (arm_data->thumb_mode)
11974 {
11975 if (((unsigned long) value) > 0xff)
11976 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11977 _("invalid swi expression"));
b99bd4ef
NC
11978 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
11979 newval |= value;
11980 md_number_to_chars (buf, newval, THUMB_SIZE);
11981 }
11982 else
11983 {
11984 if (((unsigned long) value) > 0x00ffffff)
11985 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11986 _("invalid swi expression"));
b99bd4ef
NC
11987 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
11988 newval |= value;
11989 md_number_to_chars (buf, newval, INSN_SIZE);
11990 }
11991 break;
11992
11993 case BFD_RELOC_ARM_MULTI:
11994 if (((unsigned long) value) > 0xffff)
11995 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 11996 _("invalid expression in load/store multiple"));
b99bd4ef
NC
11997 newval = value | md_chars_to_number (buf, INSN_SIZE);
11998 md_number_to_chars (buf, newval, INSN_SIZE);
11999 break;
12000
12001 case BFD_RELOC_ARM_PCREL_BRANCH:
12002 newval = md_chars_to_number (buf, INSN_SIZE);
12003
12004 /* Sign-extend a 24-bit number. */
12005#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12006
12007#ifdef OBJ_ELF
7f266840 12008 value = fixP->fx_offset;
b99bd4ef
NC
12009#endif
12010
12011 /* We are going to store value (shifted right by two) in the
12012 instruction, in a 24 bit, signed field. Thus we need to check
12013 that none of the top 8 bits of the shifted value (top 7 bits of
12014 the unshifted, unsigned value) are set, or that they are all set. */
12015 if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12016 && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12017 {
12018#ifdef OBJ_ELF
12019 /* Normally we would be stuck at this point, since we cannot store
12020 the absolute address that is the destination of the branch in the
12021 24 bits of the branch instruction. If however, we happen to know
12022 that the destination of the branch is in the same section as the
2d2255b5 12023 branch instruction itself, then we can compute the relocation for
b99bd4ef
NC
12024 ourselves and not have to bother the linker with it.
12025
7f266840
DJ
12026 FIXME: The test for OBJ_ELF is only here because I have not
12027 worked out how to do this for OBJ_COFF. */
12028 if (fixP->fx_addsy != NULL
b99bd4ef
NC
12029 && S_IS_DEFINED (fixP->fx_addsy)
12030 && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12031 {
12032 /* Get pc relative value to go into the branch. */
94f592af 12033 value = * valP;
b99bd4ef
NC
12034
12035 /* Permit a backward branch provided that enough bits
12036 are set. Allow a forwards branch, provided that
12037 enough bits are clear. */
12038 if ( (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12039 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12040 fixP->fx_done = 1;
12041 }
12042
12043 if (! fixP->fx_done)
12044#endif
12045 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12046 _("GAS can't handle same-section branch dest >= 0x04000000"));
b99bd4ef
NC
12047 }
12048
12049 value >>= 2;
12050 value += SEXT24 (newval);
12051
12052 if ( (value & ~ ((offsetT) 0xffffff)) != 0
12053 && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12054 as_bad_where (fixP->fx_file, fixP->fx_line,
12055 _("out of range branch"));
12056
4e7fd91e
PB
12057 if (seg->use_rela_p && !fixP->fx_done)
12058 {
12059 /* Must unshift the value before storing it in the addend. */
12060 value <<= 2;
12061#ifdef OBJ_ELF
12062 fixP->fx_offset = value;
12063#endif
12064 fixP->fx_addnumber = value;
12065 newval = newval & 0xff000000;
12066 }
12067 else
12068 newval = (value & 0x00ffffff) | (newval & 0xff000000);
b99bd4ef
NC
12069 md_number_to_chars (buf, newval, INSN_SIZE);
12070 break;
12071
12072 case BFD_RELOC_ARM_PCREL_BLX:
12073 {
12074 offsetT hbit;
12075 newval = md_chars_to_number (buf, INSN_SIZE);
12076
12077#ifdef OBJ_ELF
7f266840 12078 value = fixP->fx_offset;
b99bd4ef
NC
12079#endif
12080 hbit = (value >> 1) & 1;
12081 value = (value >> 2) & 0x00ffffff;
12082 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
4e7fd91e
PB
12083
12084 if (seg->use_rela_p && !fixP->fx_done)
12085 {
12086 /* Must sign-extend and unshift the value before storing
12087 it in the addend. */
12088 value = SEXT24 (value);
12089 value = (value << 2) | hbit;
12090#ifdef OBJ_ELF
12091 fixP->fx_offset = value;
12092#endif
12093 fixP->fx_addnumber = value;
12094 newval = newval & 0xfe000000;
12095 }
12096 else
12097 newval = value | (newval & 0xfe000000) | (hbit << 24);
b99bd4ef
NC
12098 md_number_to_chars (buf, newval, INSN_SIZE);
12099 }
12100 break;
12101
12102 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
12103 newval = md_chars_to_number (buf, THUMB_SIZE);
12104 {
12105 addressT diff = (newval & 0xff) << 1;
12106 if (diff & 0x100)
12107 diff |= ~0xff;
12108
12109 value += diff;
12110 if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12111 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12112 _("branch out of range"));
4e7fd91e
PB
12113 if (seg->use_rela_p && !fixP->fx_done)
12114 {
12115#ifdef OBJ_ELF
12116 fixP->fx_offset = value;
12117#endif
12118 fixP->fx_addnumber = value;
12119 newval = newval & 0xff00;
12120 }
12121 else
12122 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
b99bd4ef
NC
12123 }
12124 md_number_to_chars (buf, newval, THUMB_SIZE);
12125 break;
12126
12127 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
12128 newval = md_chars_to_number (buf, THUMB_SIZE);
12129 {
12130 addressT diff = (newval & 0x7ff) << 1;
12131 if (diff & 0x800)
12132 diff |= ~0x7ff;
12133
12134 value += diff;
12135 if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12136 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12137 _("branch out of range"));
4e7fd91e
PB
12138 if (seg->use_rela_p && !fixP->fx_done)
12139 {
12140#ifdef OBJ_ELF
12141 fixP->fx_offset = value;
12142#endif
12143 fixP->fx_addnumber = value;
12144 newval = newval & 0xf800;
12145 }
12146 else
12147 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
b99bd4ef
NC
12148 }
12149 md_number_to_chars (buf, newval, THUMB_SIZE);
12150 break;
12151
12152 case BFD_RELOC_THUMB_PCREL_BLX:
12153 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12154 {
12155 offsetT newval2;
12156 addressT diff;
12157
12158 newval = md_chars_to_number (buf, THUMB_SIZE);
12159 newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12160 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12161 if (diff & 0x400000)
12162 diff |= ~0x3fffff;
12163#ifdef OBJ_ELF
12164 value = fixP->fx_offset;
12165#endif
12166 value += diff;
c62e1cc3 12167
b99bd4ef
NC
12168 if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12169 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12170 _("branch with link out of range"));
b99bd4ef 12171
b99bd4ef 12172 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
c62e1cc3
NC
12173 /* For a BLX instruction, make sure that the relocation is rounded up
12174 to a word boundary. This follows the semantics of the instruction
12175 which specifies that bit 1 of the target address will come from bit
12176 1 of the base address. */
4e7fd91e
PB
12177 value = (value + 1) & ~ 1;
12178
12179 if (seg->use_rela_p && !fixP->fx_done)
12180 {
12181#ifdef OBJ_ELF
12182 fixP->fx_offset = value;
12183#endif
12184 fixP->fx_addnumber = value;
12185 newval = newval & 0xf800;
12186 newval2 = newval2 & 0xf800;
12187 }
12188 else
12189 {
12190 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
12191 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12192 }
b99bd4ef
NC
12193 md_number_to_chars (buf, newval, THUMB_SIZE);
12194 md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12195 }
12196 break;
12197
12198 case BFD_RELOC_8:
4e7fd91e
PB
12199 if (seg->use_rela_p && !fixP->fx_done)
12200 break;
b99bd4ef
NC
12201 if (fixP->fx_done || fixP->fx_pcrel)
12202 md_number_to_chars (buf, value, 1);
12203#ifdef OBJ_ELF
7f266840 12204 else
b99bd4ef
NC
12205 {
12206 value = fixP->fx_offset;
12207 md_number_to_chars (buf, value, 1);
12208 }
12209#endif
12210 break;
12211
12212 case BFD_RELOC_16:
4e7fd91e
PB
12213 if (seg->use_rela_p && !fixP->fx_done)
12214 break;
b99bd4ef
NC
12215 if (fixP->fx_done || fixP->fx_pcrel)
12216 md_number_to_chars (buf, value, 2);
12217#ifdef OBJ_ELF
7f266840 12218 else
b99bd4ef
NC
12219 {
12220 value = fixP->fx_offset;
12221 md_number_to_chars (buf, value, 2);
12222 }
12223#endif
12224 break;
12225
12226#ifdef OBJ_ELF
12227 case BFD_RELOC_ARM_GOT32:
12228 case BFD_RELOC_ARM_GOTOFF:
eb043451 12229 case BFD_RELOC_ARM_TARGET2:
4e7fd91e
PB
12230 if (seg->use_rela_p && !fixP->fx_done)
12231 break;
b99bd4ef
NC
12232 md_number_to_chars (buf, 0, 4);
12233 break;
12234#endif
12235
12236 case BFD_RELOC_RVA:
12237 case BFD_RELOC_32:
9c504268 12238 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12239 case BFD_RELOC_ARM_ROSEGREL32:
12240 case BFD_RELOC_ARM_SBREL32:
eb043451 12241 case BFD_RELOC_32_PCREL:
4e7fd91e
PB
12242 if (seg->use_rela_p && !fixP->fx_done)
12243 break;
b99bd4ef
NC
12244 if (fixP->fx_done || fixP->fx_pcrel)
12245 md_number_to_chars (buf, value, 4);
12246#ifdef OBJ_ELF
7f266840 12247 else
b99bd4ef
NC
12248 {
12249 value = fixP->fx_offset;
12250 md_number_to_chars (buf, value, 4);
12251 }
12252#endif
12253 break;
12254
12255#ifdef OBJ_ELF
eb043451
PB
12256 case BFD_RELOC_ARM_PREL31:
12257 if (fixP->fx_done || fixP->fx_pcrel)
12258 {
12259 newval = md_chars_to_number (buf, 4) & 0x80000000;
12260 if ((value ^ (value >> 1)) & 0x40000000)
12261 {
12262 as_bad_where (fixP->fx_file, fixP->fx_line,
12263 _("rel31 relocation overflow"));
12264 }
12265 newval |= value & 0x7fffffff;
12266 md_number_to_chars (buf, newval, 4);
12267 }
12268 break;
12269
b99bd4ef
NC
12270 case BFD_RELOC_ARM_PLT32:
12271 /* It appears the instruction is fully prepared at this point. */
12272 break;
12273#endif
12274
b99bd4ef
NC
12275 case BFD_RELOC_ARM_CP_OFF_IMM:
12276 sign = value >= 0;
12277 if (value < -1023 || value > 1023 || (value & 3))
12278 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12279 _("illegal value for co-processor offset"));
b99bd4ef
NC
12280 if (value < 0)
12281 value = -value;
12282 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12283 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12284 md_number_to_chars (buf, newval, INSN_SIZE);
12285 break;
12286
e16bb312
NC
12287 case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12288 sign = value >= 0;
12289 if (value < -255 || value > 255)
12290 as_bad_where (fixP->fx_file, fixP->fx_line,
12291 _("Illegal value for co-processor offset"));
12292 if (value < 0)
12293 value = -value;
12294 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12295 newval |= value | (sign ? INDEX_UP : 0);
12296 md_number_to_chars (buf, newval , INSN_SIZE);
12297 break;
12298
b99bd4ef
NC
12299 case BFD_RELOC_ARM_THUMB_OFFSET:
12300 newval = md_chars_to_number (buf, THUMB_SIZE);
12301 /* Exactly what ranges, and where the offset is inserted depends
12302 on the type of instruction, we can establish this from the
12303 top 4 bits. */
12304 switch (newval >> 12)
12305 {
12306 case 4: /* PC load. */
12307 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12308 forced to zero for these loads, so we will need to round
12309 up the offset if the instruction address is not word
12310 aligned (since the final address produced must be, and
12311 we can only describe word-aligned immediate offsets). */
12312
12313 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12314 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12315 _("invalid offset, target not word aligned (0x%08X)"),
b99bd4ef
NC
12316 (unsigned int) (fixP->fx_frag->fr_address
12317 + fixP->fx_where + value));
12318
12319 if ((value + 2) & ~0x3fe)
12320 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12321 _("invalid offset, value too big (0x%08lX)"),
12322 (long) value);
b99bd4ef
NC
12323
12324 /* Round up, since pc will be rounded down. */
12325 newval |= (value + 2) >> 2;
12326 break;
12327
12328 case 9: /* SP load/store. */
12329 if (value & ~0x3fc)
12330 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12331 _("invalid offset, value too big (0x%08lX)"),
12332 (long) value);
b99bd4ef
NC
12333 newval |= value >> 2;
12334 break;
12335
12336 case 6: /* Word load/store. */
12337 if (value & ~0x7c)
12338 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12339 _("invalid offset, value too big (0x%08lX)"),
12340 (long) value);
b99bd4ef
NC
12341 newval |= value << 4; /* 6 - 2. */
12342 break;
12343
12344 case 7: /* Byte load/store. */
12345 if (value & ~0x1f)
12346 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12347 _("invalid offset, value too big (0x%08lX)"),
12348 (long) value);
b99bd4ef
NC
12349 newval |= value << 6;
12350 break;
12351
12352 case 8: /* Halfword load/store. */
12353 if (value & ~0x3e)
12354 as_bad_where (fixP->fx_file, fixP->fx_line,
08df2379
NC
12355 _("invalid offset, value too big (0x%08lX)"),
12356 (long) value);
b99bd4ef
NC
12357 newval |= value << 5; /* 6 - 1. */
12358 break;
12359
12360 default:
12361 as_bad_where (fixP->fx_file, fixP->fx_line,
12362 "Unable to process relocation for thumb opcode: %lx",
12363 (unsigned long) newval);
12364 break;
12365 }
12366 md_number_to_chars (buf, newval, THUMB_SIZE);
12367 break;
12368
12369 case BFD_RELOC_ARM_THUMB_ADD:
12370 /* This is a complicated relocation, since we use it for all of
12371 the following immediate relocations:
12372
12373 3bit ADD/SUB
12374 8bit ADD/SUB
12375 9bit ADD/SUB SP word-aligned
12376 10bit ADD PC/SP word-aligned
12377
12378 The type of instruction being processed is encoded in the
12379 instruction field:
12380
12381 0x8000 SUB
12382 0x00F0 Rd
12383 0x000F Rs
12384 */
12385 newval = md_chars_to_number (buf, THUMB_SIZE);
12386 {
12387 int rd = (newval >> 4) & 0xf;
12388 int rs = newval & 0xf;
12389 int subtract = newval & 0x8000;
12390
12391 if (rd == REG_SP)
12392 {
12393 if (value & ~0x1fc)
12394 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12395 _("invalid immediate for stack address calculation"));
b99bd4ef
NC
12396 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12397 newval |= value >> 2;
12398 }
12399 else if (rs == REG_PC || rs == REG_SP)
12400 {
12401 if (subtract ||
12402 value & ~0x3fc)
12403 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12404 _("invalid immediate for address calculation (value = 0x%08lX)"),
b99bd4ef
NC
12405 (unsigned long) value);
12406 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12407 newval |= rd << 8;
12408 newval |= value >> 2;
12409 }
12410 else if (rs == rd)
12411 {
12412 if (value & ~0xff)
12413 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12414 _("invalid 8bit immediate"));
b99bd4ef
NC
12415 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12416 newval |= (rd << 8) | value;
12417 }
12418 else
12419 {
12420 if (value & ~0x7)
12421 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12422 _("invalid 3bit immediate"));
b99bd4ef
NC
12423 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12424 newval |= rd | (rs << 3) | (value << 6);
12425 }
12426 }
12427 md_number_to_chars (buf, newval, THUMB_SIZE);
12428 break;
12429
12430 case BFD_RELOC_ARM_THUMB_IMM:
12431 newval = md_chars_to_number (buf, THUMB_SIZE);
12432 switch (newval >> 11)
12433 {
12434 case 0x04: /* 8bit immediate MOV. */
12435 case 0x05: /* 8bit immediate CMP. */
12436 if (value < 0 || value > 255)
12437 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12438 _("invalid immediate: %ld is too large"),
b99bd4ef
NC
12439 (long) value);
12440 newval |= value;
12441 break;
12442
12443 default:
12444 abort ();
12445 }
12446 md_number_to_chars (buf, newval, THUMB_SIZE);
12447 break;
12448
12449 case BFD_RELOC_ARM_THUMB_SHIFT:
12450 /* 5bit shift value (0..31). */
12451 if (value < 0 || value > 31)
12452 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12453 _("illegal Thumb shift value: %ld"), (long) value);
b99bd4ef
NC
12454 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12455 newval |= value << 6;
12456 md_number_to_chars (buf, newval, THUMB_SIZE);
12457 break;
12458
12459 case BFD_RELOC_VTABLE_INHERIT:
12460 case BFD_RELOC_VTABLE_ENTRY:
12461 fixP->fx_done = 0;
94f592af 12462 return;
b99bd4ef 12463
620b81c1 12464 case BFD_RELOC_UNUSED:
b99bd4ef
NC
12465 default:
12466 as_bad_where (fixP->fx_file, fixP->fx_line,
f03698e6 12467 _("bad relocation fixup type (%d)"), fixP->fx_r_type);
b99bd4ef 12468 }
b99bd4ef
NC
12469}
12470
12471/* Translate internal representation of relocation info to BFD target
12472 format. */
12473
12474arelent *
a737bd4d
NC
12475tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
12476 fixS * fixp)
b99bd4ef
NC
12477{
12478 arelent * reloc;
12479 bfd_reloc_code_real_type code;
12480
a737bd4d 12481 reloc = xmalloc (sizeof (arelent));
b99bd4ef 12482
a737bd4d 12483 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
b99bd4ef
NC
12484 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12485 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12486
12487 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12488#ifndef OBJ_ELF
12489 if (fixp->fx_pcrel == 0)
12490 reloc->addend = fixp->fx_offset;
12491 else
12492 reloc->addend = fixp->fx_offset = reloc->address;
12493#else /* OBJ_ELF */
12494 reloc->addend = fixp->fx_offset;
12495#endif
12496
12497 switch (fixp->fx_r_type)
12498 {
12499 case BFD_RELOC_8:
12500 if (fixp->fx_pcrel)
12501 {
12502 code = BFD_RELOC_8_PCREL;
12503 break;
12504 }
12505
12506 case BFD_RELOC_16:
12507 if (fixp->fx_pcrel)
12508 {
12509 code = BFD_RELOC_16_PCREL;
12510 break;
12511 }
12512
12513 case BFD_RELOC_32:
12514 if (fixp->fx_pcrel)
12515 {
12516 code = BFD_RELOC_32_PCREL;
12517 break;
12518 }
12519
620b81c1 12520 case BFD_RELOC_NONE:
b99bd4ef
NC
12521 case BFD_RELOC_ARM_PCREL_BRANCH:
12522 case BFD_RELOC_ARM_PCREL_BLX:
12523 case BFD_RELOC_RVA:
12524 case BFD_RELOC_THUMB_PCREL_BRANCH9:
12525 case BFD_RELOC_THUMB_PCREL_BRANCH12:
12526 case BFD_RELOC_THUMB_PCREL_BRANCH23:
12527 case BFD_RELOC_THUMB_PCREL_BLX:
12528 case BFD_RELOC_VTABLE_ENTRY:
12529 case BFD_RELOC_VTABLE_INHERIT:
12530 code = fixp->fx_r_type;
12531 break;
12532
12533 case BFD_RELOC_ARM_LITERAL:
12534 case BFD_RELOC_ARM_HWLITERAL:
3d0c9500
NC
12535 /* If this is called then the a literal has
12536 been referenced across a section boundary. */
b99bd4ef 12537 as_bad_where (fixp->fx_file, fixp->fx_line,
61b5f74b 12538 _("literal referenced across section boundary"));
b99bd4ef
NC
12539 return NULL;
12540
12541#ifdef OBJ_ELF
12542 case BFD_RELOC_ARM_GOT32:
12543 case BFD_RELOC_ARM_GOTOFF:
12544 case BFD_RELOC_ARM_PLT32:
9c504268 12545 case BFD_RELOC_ARM_TARGET1:
db6579d4
PB
12546 case BFD_RELOC_ARM_ROSEGREL32:
12547 case BFD_RELOC_ARM_SBREL32:
eb043451
PB
12548 case BFD_RELOC_ARM_PREL31:
12549 case BFD_RELOC_ARM_TARGET2:
b99bd4ef
NC
12550 code = fixp->fx_r_type;
12551 break;
12552#endif
12553
12554 case BFD_RELOC_ARM_IMMEDIATE:
12555 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12556 _("internal relocation (type: IMMEDIATE) not fixed up"));
b99bd4ef
NC
12557 return NULL;
12558
12559 case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12560 as_bad_where (fixp->fx_file, fixp->fx_line,
12561 _("ADRL used for a symbol not defined in the same file"));
12562 return NULL;
12563
12564 case BFD_RELOC_ARM_OFFSET_IMM:
c3ba240c
DJ
12565 if (fixp->fx_addsy != NULL
12566 && !S_IS_DEFINED (fixp->fx_addsy)
12567 && S_IS_LOCAL (fixp->fx_addsy))
12568 {
12569 as_bad_where (fixp->fx_file, fixp->fx_line,
12570 _("undefined local label `%s'"),
12571 S_GET_NAME (fixp->fx_addsy));
12572 return NULL;
12573 }
12574
b99bd4ef 12575 as_bad_where (fixp->fx_file, fixp->fx_line,
6189168b 12576 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
b99bd4ef
NC
12577 return NULL;
12578
12579 default:
12580 {
12581 char * type;
12582
12583 switch (fixp->fx_r_type)
12584 {
620b81c1 12585 case BFD_RELOC_NONE: type = "NONE"; break;
b99bd4ef
NC
12586 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
12587 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
0dd132b6 12588 case BFD_RELOC_ARM_SMI: type = "SMI"; break;
b99bd4ef
NC
12589 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
12590 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
12591 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
12592 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
12593 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
12594 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
12595 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12596 default: type = _("<unknown>"); break;
12597 }
12598 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12599 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12600 type);
12601 return NULL;
12602 }
12603 }
12604
12605#ifdef OBJ_ELF
8df7094c 12606 if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
b99bd4ef
NC
12607 && GOT_symbol
12608 && fixp->fx_addsy == GOT_symbol)
12609 {
12610 code = BFD_RELOC_ARM_GOTPC;
12611 reloc->addend = fixp->fx_offset = reloc->address;
12612 }
12613#endif
12614
12615 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12616
12617 if (reloc->howto == NULL)
12618 {
12619 as_bad_where (fixp->fx_file, fixp->fx_line,
f03698e6 12620 _("cannot represent %s relocation in this object file format"),
b99bd4ef
NC
12621 bfd_get_reloc_code_name (code));
12622 return NULL;
12623 }
12624
12625 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12626 vtable entry to be used in the relocation's section offset. */
12627 if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12628 reloc->address = fixp->fx_offset;
12629
12630 return reloc;
12631}
12632
12633int
a737bd4d
NC
12634md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
12635 segT segtype ATTRIBUTE_UNUSED)
b99bd4ef
NC
12636{
12637 as_fatal (_("md_estimate_size_before_relax\n"));
12638 return 1;
12639}
12640
a737bd4d
NC
12641/* We need to be able to fix up arbitrary expressions in some statements.
12642 This is so that we can handle symbols that are an arbitrary distance from
12643 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12644 which returns part of an address in a form which will be valid for
12645 a data instruction. We do this by pushing the expression into a symbol
12646 in the expr_section, and creating a fix for that. */
12647
12648static void
12649fix_new_arm (fragS * frag,
12650 int where,
12651 short int size,
12652 expressionS * exp,
12653 int pc_rel,
12654 int reloc)
12655{
12656 fixS * new_fix;
12657 arm_fix_data * arm_data;
12658
12659 switch (exp->X_op)
12660 {
12661 case O_constant:
12662 case O_symbol:
12663 case O_add:
12664 case O_subtract:
12665 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12666 break;
12667
12668 default:
12669 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12670 pc_rel, reloc);
12671 break;
12672 }
12673
12674 /* Mark whether the fix is to a THUMB instruction, or an ARM
12675 instruction. */
12676 arm_data = obstack_alloc (& notes, sizeof (arm_fix_data));
12677 new_fix->tc_fix_data = (PTR) arm_data;
12678 arm_data->thumb_mode = thumb_mode;
12679}
12680
b99bd4ef 12681static void
a737bd4d 12682output_inst (const char * str)
b99bd4ef
NC
12683{
12684 char * to = NULL;
12685
12686 if (inst.error)
12687 {
f03698e6 12688 as_bad ("%s -- `%s'", inst.error, str);
b99bd4ef
NC
12689 return;
12690 }
12691
12692 to = frag_more (inst.size);
12693
12694 if (thumb_mode && (inst.size > THUMB_SIZE))
12695 {
12696 assert (inst.size == (2 * THUMB_SIZE));
12697 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12698 md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12699 }
12700 else if (inst.size > INSN_SIZE)
12701 {
12702 assert (inst.size == (2 * INSN_SIZE));
12703 md_number_to_chars (to, inst.instruction, INSN_SIZE);
12704 md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12705 }
12706 else
12707 md_number_to_chars (to, inst.instruction, inst.size);
12708
620b81c1 12709 if (inst.reloc.type != BFD_RELOC_UNUSED)
b99bd4ef
NC
12710 fix_new_arm (frag_now, to - frag_now->fr_literal,
12711 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12712 inst.reloc.type);
12713
12714#ifdef OBJ_ELF
12715 dwarf2_emit_insn (inst.size);
12716#endif
12717}
12718
12719void
a737bd4d 12720md_assemble (char * str)
b99bd4ef 12721{
6c43fab6
RE
12722 char c;
12723 char *p;
12724 char *start;
b99bd4ef 12725
b99bd4ef
NC
12726 /* Align the previous label if needed. */
12727 if (last_label_seen != NULL)
12728 {
12729 symbol_set_frag (last_label_seen, frag_now);
12730 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12731 S_SET_SEGMENT (last_label_seen, now_seg);
12732 }
12733
12734 memset (&inst, '\0', sizeof (inst));
620b81c1 12735 inst.reloc.type = BFD_RELOC_UNUSED;
b99bd4ef
NC
12736
12737 skip_whitespace (str);
12738
12739 /* Scan up to the end of the op-code, which must end in white space or
12740 end of string. */
12741 for (start = p = str; *p != '\0'; p++)
12742 if (*p == ' ')
12743 break;
12744
12745 if (p == str)
12746 {
f03698e6 12747 as_bad (_("no operator -- statement `%s'\n"), str);
b99bd4ef
NC
12748 return;
12749 }
12750
12751 if (thumb_mode)
12752 {
05d2d07e 12753 const struct thumb_opcode * opcode;
b99bd4ef
NC
12754
12755 c = *p;
12756 *p = '\0';
05d2d07e 12757 opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
b99bd4ef
NC
12758 *p = c;
12759
12760 if (opcode)
12761 {
12762 /* Check that this instruction is supported for this CPU. */
90e4755a 12763 if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
b99bd4ef 12764 {
f03698e6 12765 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12766 return;
12767 }
12768
6057a28f 12769 mapping_state (MAP_THUMB);
b99bd4ef
NC
12770 inst.instruction = opcode->value;
12771 inst.size = opcode->size;
a737bd4d 12772 opcode->parms (p);
f03698e6 12773 output_inst (str);
b99bd4ef
NC
12774 return;
12775 }
12776 }
12777 else
12778 {
05d2d07e 12779 const struct asm_opcode * opcode;
b99bd4ef 12780
90e4755a
RE
12781 c = *p;
12782 *p = '\0';
6c43fab6 12783 opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
90e4755a 12784 *p = c;
b99bd4ef 12785
90e4755a 12786 if (opcode)
b99bd4ef 12787 {
90e4755a
RE
12788 /* Check that this instruction is supported for this CPU. */
12789 if ((opcode->variant & cpu_variant) == 0)
b99bd4ef 12790 {
f03698e6 12791 as_bad (_("selected processor does not support `%s'"), str);
b99bd4ef
NC
12792 return;
12793 }
12794
6057a28f 12795 mapping_state (MAP_ARM);
90e4755a
RE
12796 inst.instruction = opcode->value;
12797 inst.size = INSN_SIZE;
a737bd4d 12798 opcode->parms (p);
f03698e6 12799 output_inst (str);
90e4755a 12800 return;
b99bd4ef
NC
12801 }
12802 }
12803
12804 /* It wasn't an instruction, but it might be a register alias of the form
12805 alias .req reg. */
6c43fab6
RE
12806 if (create_register_alias (str, p))
12807 return;
b99bd4ef 12808
b99bd4ef
NC
12809 as_bad (_("bad instruction `%s'"), start);
12810}
12811
12812/* md_parse_option
12813 Invocation line includes a switch not recognized by the base assembler.
cc8a6dd0 12814 See if it's a processor-specific option.
03b1477f
RE
12815
12816 This routine is somewhat complicated by the need for backwards
12817 compatibility (since older releases of gcc can't be changed).
12818 The new options try to make the interface as compatible as
12819 possible with GCC.
12820
12821 New options (supported) are:
12822
12823 -mcpu=<cpu name> Assemble for selected processor
12824 -march=<architecture name> Assemble for selected architecture
12825 -mfpu=<fpu architecture> Assemble for selected FPU.
12826 -EB/-mbig-endian Big-endian
12827 -EL/-mlittle-endian Little-endian
12828 -k Generate PIC code
12829 -mthumb Start in Thumb mode
12830 -mthumb-interwork Code supports ARM/Thumb interworking
12831
3d0c9500 12832 For now we will also provide support for:
03b1477f
RE
12833
12834 -mapcs-32 32-bit Program counter
12835 -mapcs-26 26-bit Program counter
12836 -macps-float Floats passed in FP registers
12837 -mapcs-reentrant Reentrant code
12838 -matpcs
12839 (sometime these will probably be replaced with -mapcs=<list of options>
12840 and -matpcs=<list of options>)
12841
12842 The remaining options are only supported for back-wards compatibility.
b99bd4ef
NC
12843 Cpu variants, the arm part is optional:
12844 -m[arm]1 Currently not supported.
12845 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
12846 -m[arm]3 Arm 3 processor
12847 -m[arm]6[xx], Arm 6 processors
12848 -m[arm]7[xx][t][[d]m] Arm 7 processors
12849 -m[arm]8[10] Arm 8 processors
12850 -m[arm]9[20][tdmi] Arm 9 processors
12851 -mstrongarm[110[0]] StrongARM processors
12852 -mxscale XScale processors
12853 -m[arm]v[2345[t[e]]] Arm architectures
12854 -mall All (except the ARM1)
12855 FP variants:
12856 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
12857 -mfpe-old (No float load/store multiples)
bfae80f2
RE
12858 -mvfpxd VFP Single precision
12859 -mvfp All VFP
b99bd4ef 12860 -mno-fpu Disable all floating point instructions
b99bd4ef 12861
03b1477f
RE
12862 The following CPU names are recognized:
12863 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
12864 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
12865 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
12866 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
12867 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
12868 arm10t arm10e, arm1020t, arm1020e, arm10200e,
12869 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
12870
12871 */
12872
5a38dc70 12873const char * md_shortopts = "m:k";
03b1477f 12874
b99bd4ef
NC
12875#ifdef ARM_BI_ENDIAN
12876#define OPTION_EB (OPTION_MD_BASE + 0)
b99bd4ef 12877#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12878#else
21f0f23a
RE
12879#if TARGET_BYTES_BIG_ENDIAN
12880#define OPTION_EB (OPTION_MD_BASE + 0)
21f0f23a
RE
12881#else
12882#define OPTION_EL (OPTION_MD_BASE + 1)
21f0f23a 12883#endif
ce058b6c 12884#endif
03b1477f
RE
12885
12886struct option md_longopts[] =
12887{
12888#ifdef OPTION_EB
12889 {"EB", no_argument, NULL, OPTION_EB},
12890#endif
12891#ifdef OPTION_EL
12892 {"EL", no_argument, NULL, OPTION_EL},
b99bd4ef
NC
12893#endif
12894 {NULL, no_argument, NULL, 0}
12895};
12896
12897size_t md_longopts_size = sizeof (md_longopts);
12898
03b1477f 12899struct arm_option_table
b99bd4ef 12900{
03b1477f
RE
12901 char *option; /* Option name to match. */
12902 char *help; /* Help information. */
12903 int *var; /* Variable to change. */
12904 int value; /* What to change it to. */
12905 char *deprecated; /* If non-null, print this message. */
12906};
b99bd4ef 12907
cc8a6dd0 12908struct arm_option_table arm_opts[] =
03b1477f
RE
12909{
12910 {"k", N_("generate PIC code"), &pic_code, 1, NULL},
12911 {"mthumb", N_("assemble Thumb code"), &thumb_mode, 1, NULL},
12912 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
12913 &support_interwork, 1, NULL},
03b1477f
RE
12914 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
12915 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
12916 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
12917 1, NULL},
12918 {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
12919 {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
12920 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
12921 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
12922 NULL},
12923
12924 /* These are recognized by the assembler, but have no affect on code. */
12925 {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
12926 {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
12927
12928 /* DON'T add any new processors to this list -- we want the whole list
12929 to go away... Add them to the processors table instead. */
12930 {"marm1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12931 {"m1", NULL, &legacy_cpu, ARM_ARCH_V1, N_("use -mcpu=arm1")},
12932 {"marm2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12933 {"m2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -mcpu=arm2")},
12934 {"marm250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12935 {"m250", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
12936 {"marm3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12937 {"m3", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
12938 {"marm6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12939 {"m6", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm6")},
12940 {"marm600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12941 {"m600", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm600")},
12942 {"marm610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12943 {"m610", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm610")},
12944 {"marm620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12945 {"m620", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm620")},
12946 {"marm7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12947 {"m7", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7")},
12948 {"marm70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12949 {"m70", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm70")},
12950 {"marm700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12951 {"m700", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700")},
12952 {"marm700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12953 {"m700i", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm700i")},
12954 {"marm710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12955 {"m710", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710")},
12956 {"marm710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12957 {"m710c", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm710c")},
12958 {"marm720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12959 {"m720", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm720")},
12960 {"marm7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12961 {"m7d", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7d")},
12962 {"marm7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12963 {"m7di", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7di")},
12964 {"marm7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12965 {"m7m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
12966 {"marm7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12967 {"m7dm", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
12968 {"marm7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12969 {"m7dmi", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
12970 {"marm7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12971 {"m7100", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7100")},
12972 {"marm7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12973 {"m7500", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500")},
12974 {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12975 {"m7500fe", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -mcpu=arm7500fe")},
12976 {"marm7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12977 {"m7t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12978 {"marm7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12979 {"m7tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
12980 {"marm710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12981 {"m710t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
12982 {"marm720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12983 {"m720t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
12984 {"marm740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12985 {"m740t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
12986 {"marm8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12987 {"m8", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm8")},
12988 {"marm810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12989 {"m810", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=arm810")},
12990 {"marm9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12991 {"m9", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
12992 {"marm9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12993 {"m9tdmi", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
12994 {"marm920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12995 {"m920", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
12996 {"marm940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12997 {"m940", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
12998 {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -mcpu=strongarm")},
12999 {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13000 N_("use -mcpu=strongarm110")},
13001 {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13002 N_("use -mcpu=strongarm1100")},
13003 {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13004 N_("use -mcpu=strongarm1110")},
13005 {"mxscale", NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
e16bb312 13006 {"miwmmxt", NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
03b1477f
RE
13007 {"mall", NULL, &legacy_cpu, ARM_ANY, N_("use -mcpu=all")},
13008
13009 /* Architecture variants -- don't add any more to this list either. */
13010 {"mv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13011 {"marmv2", NULL, &legacy_cpu, ARM_ARCH_V2, N_("use -march=armv2")},
13012 {"mv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13013 {"marmv2a", NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13014 {"mv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13015 {"marmv3", NULL, &legacy_cpu, ARM_ARCH_V3, N_("use -march=armv3")},
13016 {"mv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13017 {"marmv3m", NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13018 {"mv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13019 {"marmv4", NULL, &legacy_cpu, ARM_ARCH_V4, N_("use -march=armv4")},
13020 {"mv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13021 {"marmv4t", NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13022 {"mv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13023 {"marmv5", NULL, &legacy_cpu, ARM_ARCH_V5, N_("use -march=armv5")},
13024 {"mv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13025 {"marmv5t", NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13026 {"mv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13027 {"marmv5e", NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13028
13029 /* Floating point variants -- don't add any more to this list either. */
13030 {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13031 {"mfpa10", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13032 {"mfpa11", NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13033 {"mno-fpu", NULL, &legacy_fpu, 0,
13034 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13035
13036 {NULL, NULL, NULL, 0, NULL}
13037};
21f0f23a 13038
03b1477f
RE
13039struct arm_cpu_option_table
13040{
13041 char *name;
13042 int value;
13043 /* For some CPUs we assume an FPU unless the user explicitly sets
13044 -mfpu=... */
13045 int default_fpu;
13046};
13047
13048/* This list should, at a minimum, contain all the cpu names
13049 recognized by GCC. */
13050static struct arm_cpu_option_table arm_cpus[] =
13051{
13052 {"all", ARM_ANY, FPU_ARCH_FPA},
13053 {"arm1", ARM_ARCH_V1, FPU_ARCH_FPA},
13054 {"arm2", ARM_ARCH_V2, FPU_ARCH_FPA},
13055 {"arm250", ARM_ARCH_V2S, FPU_ARCH_FPA},
13056 {"arm3", ARM_ARCH_V2S, FPU_ARCH_FPA},
13057 {"arm6", ARM_ARCH_V3, FPU_ARCH_FPA},
13058 {"arm60", ARM_ARCH_V3, FPU_ARCH_FPA},
13059 {"arm600", ARM_ARCH_V3, FPU_ARCH_FPA},
13060 {"arm610", ARM_ARCH_V3, FPU_ARCH_FPA},
13061 {"arm620", ARM_ARCH_V3, FPU_ARCH_FPA},
13062 {"arm7", ARM_ARCH_V3, FPU_ARCH_FPA},
13063 {"arm7m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13064 {"arm7d", ARM_ARCH_V3, FPU_ARCH_FPA},
13065 {"arm7dm", ARM_ARCH_V3M, FPU_ARCH_FPA},
13066 {"arm7di", ARM_ARCH_V3, FPU_ARCH_FPA},
13067 {"arm7dmi", ARM_ARCH_V3M, FPU_ARCH_FPA},
13068 {"arm70", ARM_ARCH_V3, FPU_ARCH_FPA},
13069 {"arm700", ARM_ARCH_V3, FPU_ARCH_FPA},
13070 {"arm700i", ARM_ARCH_V3, FPU_ARCH_FPA},
13071 {"arm710", ARM_ARCH_V3, FPU_ARCH_FPA},
13072 {"arm710t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13073 {"arm720", ARM_ARCH_V3, FPU_ARCH_FPA},
13074 {"arm720t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13075 {"arm740t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13076 {"arm710c", ARM_ARCH_V3, FPU_ARCH_FPA},
13077 {"arm7100", ARM_ARCH_V3, FPU_ARCH_FPA},
13078 {"arm7500", ARM_ARCH_V3, FPU_ARCH_FPA},
13079 {"arm7500fe", ARM_ARCH_V3, FPU_ARCH_FPA},
13080 {"arm7t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13081 {"arm7tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
8783612f 13082 {"arm7tdmi-s", ARM_ARCH_V4T, FPU_ARCH_FPA},
03b1477f
RE
13083 {"arm8", ARM_ARCH_V4, FPU_ARCH_FPA},
13084 {"arm810", ARM_ARCH_V4, FPU_ARCH_FPA},
13085 {"strongarm", ARM_ARCH_V4, FPU_ARCH_FPA},
13086 {"strongarm1", ARM_ARCH_V4, FPU_ARCH_FPA},
13087 {"strongarm110", ARM_ARCH_V4, FPU_ARCH_FPA},
13088 {"strongarm1100", ARM_ARCH_V4, FPU_ARCH_FPA},
13089 {"strongarm1110", ARM_ARCH_V4, FPU_ARCH_FPA},
13090 {"arm9", ARM_ARCH_V4T, FPU_ARCH_FPA},
13091 {"arm920", ARM_ARCH_V4T, FPU_ARCH_FPA},
13092 {"arm920t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13093 {"arm922t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13094 {"arm940t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13095 {"arm9tdmi", ARM_ARCH_V4T, FPU_ARCH_FPA},
13096 /* For V5 or later processors we default to using VFP; but the user
13097 should really set the FPU type explicitly. */
13098 {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13099 {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
ea6ef066 13100 {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
7de9afa2 13101 {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
8783612f 13102 {"arm926ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
03b1477f
RE
13103 {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13104 {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13105 {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13106 {"arm966e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13107 {"arm10t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13108 {"arm10e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13109 {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
13110 {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1},
13111 {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2},
5dc1606f
PB
13112 {"arm1026ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
13113 {"arm1026ej-s", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2},
09d92015 13114 {"arm1136js", ARM_ARCH_V6, FPU_NONE},
9166bcd7 13115 {"arm1136j-s", ARM_ARCH_V6, FPU_NONE},
09d92015 13116 {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
8783612f 13117 {"arm1136jf-s", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
0dd132b6
NC
13118 {"mpcore", ARM_ARCH_V6K, FPU_ARCH_VFP_V2},
13119 {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE},
13120 {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE},
13121 {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2},
03b1477f
RE
13122 /* ??? XSCALE is really an architecture. */
13123 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
5a6c6817 13124 /* ??? iwmmxt is not a processor. */
e16bb312 13125 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
03b1477f
RE
13126 {"i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13127 /* Maverick */
33a392fb 13128 {"ep9312", ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
03b1477f
RE
13129 {NULL, 0, 0}
13130};
cc8a6dd0 13131
03b1477f
RE
13132struct arm_arch_option_table
13133{
13134 char *name;
13135 int value;
13136 int default_fpu;
13137};
13138
13139/* This list should, at a minimum, contain all the architecture names
13140 recognized by GCC. */
13141static struct arm_arch_option_table arm_archs[] =
13142{
13143 {"all", ARM_ANY, FPU_ARCH_FPA},
13144 {"armv1", ARM_ARCH_V1, FPU_ARCH_FPA},
13145 {"armv2", ARM_ARCH_V2, FPU_ARCH_FPA},
13146 {"armv2a", ARM_ARCH_V2S, FPU_ARCH_FPA},
13147 {"armv2s", ARM_ARCH_V2S, FPU_ARCH_FPA},
13148 {"armv3", ARM_ARCH_V3, FPU_ARCH_FPA},
13149 {"armv3m", ARM_ARCH_V3M, FPU_ARCH_FPA},
13150 {"armv4", ARM_ARCH_V4, FPU_ARCH_FPA},
13151 {"armv4xm", ARM_ARCH_V4xM, FPU_ARCH_FPA},
13152 {"armv4t", ARM_ARCH_V4T, FPU_ARCH_FPA},
13153 {"armv4txm", ARM_ARCH_V4TxM, FPU_ARCH_FPA},
13154 {"armv5", ARM_ARCH_V5, FPU_ARCH_VFP},
13155 {"armv5t", ARM_ARCH_V5T, FPU_ARCH_VFP},
13156 {"armv5txm", ARM_ARCH_V5TxM, FPU_ARCH_VFP},
13157 {"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
13158 {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
ea6ef066 13159 {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
84255574 13160 {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
1ddd7f43 13161 {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP},
0dd132b6
NC
13162 {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
13163 {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
13164 {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
b05fe5cf
ZW
13165 {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
13166 {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
13167 {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
13168 {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
03b1477f 13169 {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
8266886e 13170 {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
03b1477f
RE
13171 {NULL, 0, 0}
13172};
13173
13174/* ISA extensions in the co-processor space. */
13175struct arm_arch_extension_table
13176{
13177 char *name;
13178 int value;
13179};
13180
13181static struct arm_arch_extension_table arm_extensions[] =
13182{
13183 {"maverick", ARM_CEXT_MAVERICK},
13184 {"xscale", ARM_CEXT_XSCALE},
e16bb312 13185 {"iwmmxt", ARM_CEXT_IWMMXT},
03b1477f
RE
13186 {NULL, 0}
13187};
b99bd4ef 13188
03b1477f
RE
13189struct arm_fpu_option_table
13190{
13191 char *name;
13192 int value;
13193};
13194
13195/* This list should, at a minimum, contain all the fpu names
13196 recognized by GCC. */
13197static struct arm_fpu_option_table arm_fpus[] =
13198{
13199 {"softfpa", FPU_NONE},
13200 {"fpe", FPU_ARCH_FPE},
d193a22a
RE
13201 {"fpe2", FPU_ARCH_FPE},
13202 {"fpe3", FPU_ARCH_FPA}, /* Third release supports LFM/SFM. */
03b1477f
RE
13203 {"fpa", FPU_ARCH_FPA},
13204 {"fpa10", FPU_ARCH_FPA},
13205 {"fpa11", FPU_ARCH_FPA},
13206 {"arm7500fe", FPU_ARCH_FPA},
13207 {"softvfp", FPU_ARCH_VFP},
13208 {"softvfp+vfp", FPU_ARCH_VFP_V2},
13209 {"vfp", FPU_ARCH_VFP_V2},
13210 {"vfp9", FPU_ARCH_VFP_V2},
13211 {"vfp10", FPU_ARCH_VFP_V2},
13212 {"vfp10-r0", FPU_ARCH_VFP_V1},
13213 {"vfpxd", FPU_ARCH_VFP_V1xD},
13214 {"arm1020t", FPU_ARCH_VFP_V1},
13215 {"arm1020e", FPU_ARCH_VFP_V2},
09d92015 13216 {"arm1136jfs", FPU_ARCH_VFP_V2},
8783612f 13217 {"arm1136jf-s", FPU_ARCH_VFP_V2},
33a392fb
PB
13218 {"maverick", FPU_ARCH_MAVERICK},
13219 {NULL, 0}
13220};
13221
13222struct arm_float_abi_option_table
13223{
13224 char *name;
13225 int value;
13226};
13227
13228static struct arm_float_abi_option_table arm_float_abis[] =
13229{
13230 {"hard", ARM_FLOAT_ABI_HARD},
13231 {"softfp", ARM_FLOAT_ABI_SOFTFP},
13232 {"soft", ARM_FLOAT_ABI_SOFT},
03b1477f
RE
13233 {NULL, 0}
13234};
13235
d507cf36
PB
13236struct arm_eabi_option_table
13237{
13238 char *name;
13239 unsigned int value;
13240};
13241
7cc69913 13242#ifdef OBJ_ELF
8cb51566 13243/* We only know how to output GNU and ver 4 (AAELF) formats. */
d507cf36
PB
13244static struct arm_eabi_option_table arm_eabis[] =
13245{
13246 {"gnu", EF_ARM_EABI_UNKNOWN},
8cb51566 13247 {"4", EF_ARM_EABI_VER4},
d507cf36
PB
13248 {NULL, 0}
13249};
7cc69913 13250#endif
d507cf36 13251
03b1477f
RE
13252struct arm_long_option_table
13253{
a737bd4d
NC
13254 char * option; /* Substring to match. */
13255 char * help; /* Help information. */
13256 int (* func) (char * subopt); /* Function to decode sub-option. */
13257 char * deprecated; /* If non-null, print this message. */
03b1477f
RE
13258};
13259
13260static int
a737bd4d 13261arm_parse_extension (char * str, int * opt_p)
03b1477f
RE
13262{
13263 while (str != NULL && *str != 0)
13264 {
a737bd4d
NC
13265 struct arm_arch_extension_table * opt;
13266 char * ext;
03b1477f
RE
13267 int optlen;
13268
13269 if (*str != '+')
b99bd4ef 13270 {
03b1477f
RE
13271 as_bad (_("invalid architectural extension"));
13272 return 0;
13273 }
b99bd4ef 13274
03b1477f
RE
13275 str++;
13276 ext = strchr (str, '+');
b99bd4ef 13277
03b1477f
RE
13278 if (ext != NULL)
13279 optlen = ext - str;
13280 else
13281 optlen = strlen (str);
b99bd4ef 13282
03b1477f
RE
13283 if (optlen == 0)
13284 {
13285 as_bad (_("missing architectural extension"));
13286 return 0;
13287 }
b99bd4ef 13288
03b1477f
RE
13289 for (opt = arm_extensions; opt->name != NULL; opt++)
13290 if (strncmp (opt->name, str, optlen) == 0)
13291 {
13292 *opt_p |= opt->value;
13293 break;
13294 }
bfae80f2 13295
03b1477f
RE
13296 if (opt->name == NULL)
13297 {
13298 as_bad (_("unknown architectural extnsion `%s'"), str);
13299 return 0;
13300 }
b99bd4ef 13301
03b1477f
RE
13302 str = ext;
13303 };
b99bd4ef 13304
03b1477f
RE
13305 return 1;
13306}
b99bd4ef 13307
03b1477f 13308static int
a737bd4d 13309arm_parse_cpu (char * str)
03b1477f 13310{
a737bd4d
NC
13311 struct arm_cpu_option_table * opt;
13312 char * ext = strchr (str, '+');
03b1477f 13313 int optlen;
b99bd4ef 13314
03b1477f
RE
13315 if (ext != NULL)
13316 optlen = ext - str;
13317 else
13318 optlen = strlen (str);
b99bd4ef 13319
03b1477f
RE
13320 if (optlen == 0)
13321 {
13322 as_bad (_("missing cpu name `%s'"), str);
13323 return 0;
13324 }
b99bd4ef 13325
03b1477f
RE
13326 for (opt = arm_cpus; opt->name != NULL; opt++)
13327 if (strncmp (opt->name, str, optlen) == 0)
13328 {
13329 mcpu_cpu_opt = opt->value;
13330 mcpu_fpu_opt = opt->default_fpu;
b99bd4ef 13331
03b1477f
RE
13332 if (ext != NULL)
13333 return arm_parse_extension (ext, &mcpu_cpu_opt);
b99bd4ef 13334
03b1477f
RE
13335 return 1;
13336 }
b99bd4ef 13337
03b1477f
RE
13338 as_bad (_("unknown cpu `%s'"), str);
13339 return 0;
13340}
b99bd4ef 13341
03b1477f 13342static int
a737bd4d 13343arm_parse_arch (char * str)
03b1477f
RE
13344{
13345 struct arm_arch_option_table *opt;
13346 char *ext = strchr (str, '+');
13347 int optlen;
b99bd4ef 13348
03b1477f
RE
13349 if (ext != NULL)
13350 optlen = ext - str;
13351 else
13352 optlen = strlen (str);
b99bd4ef 13353
03b1477f
RE
13354 if (optlen == 0)
13355 {
13356 as_bad (_("missing architecture name `%s'"), str);
13357 return 0;
13358 }
b99bd4ef 13359
b99bd4ef 13360
03b1477f 13361 for (opt = arm_archs; opt->name != NULL; opt++)
a737bd4d 13362 if (streq (opt->name, str))
03b1477f
RE
13363 {
13364 march_cpu_opt = opt->value;
13365 march_fpu_opt = opt->default_fpu;
b99bd4ef 13366
03b1477f
RE
13367 if (ext != NULL)
13368 return arm_parse_extension (ext, &march_cpu_opt);
b99bd4ef 13369
03b1477f
RE
13370 return 1;
13371 }
b99bd4ef 13372
03b1477f
RE
13373 as_bad (_("unknown architecture `%s'\n"), str);
13374 return 0;
13375}
13376
13377static int
a737bd4d 13378arm_parse_fpu (char * str)
03b1477f 13379{
a737bd4d 13380 struct arm_fpu_option_table * opt;
b99bd4ef 13381
03b1477f 13382 for (opt = arm_fpus; opt->name != NULL; opt++)
a737bd4d 13383 if (streq (opt->name, str))
03b1477f
RE
13384 {
13385 mfpu_opt = opt->value;
13386 return 1;
13387 }
b99bd4ef 13388
03b1477f
RE
13389 as_bad (_("unknown floating point format `%s'\n"), str);
13390 return 0;
13391}
b99bd4ef 13392
33a392fb 13393static int
a737bd4d 13394arm_parse_float_abi (char * str)
33a392fb 13395{
a737bd4d 13396 struct arm_float_abi_option_table * opt;
33a392fb
PB
13397
13398 for (opt = arm_float_abis; opt->name != NULL; opt++)
a737bd4d 13399 if (streq (opt->name, str))
33a392fb
PB
13400 {
13401 mfloat_abi_opt = opt->value;
13402 return 1;
13403 }
13404
13405 as_bad (_("unknown floating point abi `%s'\n"), str);
13406 return 0;
13407}
13408
7cc69913 13409#ifdef OBJ_ELF
d507cf36 13410static int
a737bd4d 13411arm_parse_eabi (char * str)
d507cf36
PB
13412{
13413 struct arm_eabi_option_table *opt;
13414
13415 for (opt = arm_eabis; opt->name != NULL; opt++)
a737bd4d 13416 if (streq (opt->name, str))
d507cf36
PB
13417 {
13418 meabi_flags = opt->value;
13419 return 1;
13420 }
13421 as_bad (_("unknown EABI `%s'\n"), str);
13422 return 0;
13423}
7cc69913 13424#endif
d507cf36 13425
03b1477f
RE
13426struct arm_long_option_table arm_long_opts[] =
13427{
13428 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13429 arm_parse_cpu, NULL},
13430 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13431 arm_parse_arch, NULL},
13432 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13433 arm_parse_fpu, NULL},
33a392fb
PB
13434 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13435 arm_parse_float_abi, NULL},
7cc69913 13436#ifdef OBJ_ELF
d507cf36
PB
13437 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13438 arm_parse_eabi, NULL},
7cc69913 13439#endif
03b1477f
RE
13440 {NULL, NULL, 0, NULL}
13441};
b99bd4ef 13442
03b1477f 13443int
a737bd4d 13444md_parse_option (int c, char * arg)
03b1477f
RE
13445{
13446 struct arm_option_table *opt;
13447 struct arm_long_option_table *lopt;
b99bd4ef 13448
03b1477f
RE
13449 switch (c)
13450 {
13451#ifdef OPTION_EB
13452 case OPTION_EB:
13453 target_big_endian = 1;
b99bd4ef 13454 break;
03b1477f 13455#endif
b99bd4ef 13456
03b1477f
RE
13457#ifdef OPTION_EL
13458 case OPTION_EL:
13459 target_big_endian = 0;
b99bd4ef
NC
13460 break;
13461#endif
13462
03b1477f 13463 case 'a':
cc8a6dd0 13464 /* Listing option. Just ignore these, we don't support additional
03b1477f
RE
13465 ones. */
13466 return 0;
13467
b99bd4ef 13468 default:
03b1477f
RE
13469 for (opt = arm_opts; opt->option != NULL; opt++)
13470 {
13471 if (c == opt->option[0]
13472 && ((arg == NULL && opt->option[1] == 0)
a737bd4d 13473 || streq (arg, opt->option + 1)))
03b1477f
RE
13474 {
13475#if WARN_DEPRECATED
13476 /* If the option is deprecated, tell the user. */
13477 if (opt->deprecated != NULL)
13478 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13479 arg ? arg : "", _(opt->deprecated));
13480#endif
13481
13482 if (opt->var != NULL)
13483 *opt->var = opt->value;
13484
13485 return 1;
13486 }
13487 }
13488
13489 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13490 {
cc8a6dd0 13491 /* These options are expected to have an argument. */
03b1477f
RE
13492 if (c == lopt->option[0]
13493 && arg != NULL
cc8a6dd0 13494 && strncmp (arg, lopt->option + 1,
03b1477f
RE
13495 strlen (lopt->option + 1)) == 0)
13496 {
13497#if WARN_DEPRECATED
13498 /* If the option is deprecated, tell the user. */
13499 if (lopt->deprecated != NULL)
13500 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13501 _(lopt->deprecated));
13502#endif
13503
13504 /* Call the sup-option parser. */
a737bd4d 13505 return lopt->func (arg + strlen (lopt->option) - 1);
03b1477f
RE
13506 }
13507 }
13508
b99bd4ef
NC
13509 return 0;
13510 }
13511
13512 return 1;
13513}
13514
13515void
a737bd4d 13516md_show_usage (FILE * fp)
b99bd4ef 13517{
03b1477f
RE
13518 struct arm_option_table *opt;
13519 struct arm_long_option_table *lopt;
13520
13521 fprintf (fp, _(" ARM-specific assembler options:\n"));
13522
13523 for (opt = arm_opts; opt->option != NULL; opt++)
13524 if (opt->help != NULL)
13525 fprintf (fp, " -%-23s%s\n", opt->option, _(opt->help));
13526
13527 for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13528 if (lopt->help != NULL)
13529 fprintf (fp, " -%s%s\n", lopt->option, _(lopt->help));
13530
13531#ifdef OPTION_EB
b99bd4ef 13532 fprintf (fp, _("\
03b1477f 13533 -EB assemble code for a big-endian cpu\n"));
b99bd4ef 13534#endif
03b1477f
RE
13535
13536#ifdef OPTION_EL
b99bd4ef 13537 fprintf (fp, _("\
03b1477f 13538 -EL assemble code for a little-endian cpu\n"));
b99bd4ef
NC
13539#endif
13540}
13541
b99bd4ef
NC
13542/* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13543
13544void
a737bd4d
NC
13545cons_fix_new_arm (fragS * frag,
13546 int where,
13547 int size,
13548 expressionS * exp)
b99bd4ef
NC
13549{
13550 bfd_reloc_code_real_type type;
13551 int pcrel = 0;
13552
13553 /* Pick a reloc.
13554 FIXME: @@ Should look at CPU word size. */
13555 switch (size)
13556 {
13557 case 1:
13558 type = BFD_RELOC_8;
13559 break;
13560 case 2:
13561 type = BFD_RELOC_16;
13562 break;
13563 case 4:
13564 default:
13565 type = BFD_RELOC_32;
13566 break;
13567 case 8:
13568 type = BFD_RELOC_64;
13569 break;
13570 }
13571
13572 fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13573}
13574
13575/* A good place to do this, although this was probably not intended
13576 for this kind of use. We need to dump the literal pool before
13577 references are made to a null symbol pointer. */
13578
13579void
a737bd4d 13580arm_cleanup (void)
b99bd4ef 13581{
3d0c9500 13582 literal_pool * pool;
b99bd4ef 13583
3d0c9500
NC
13584 for (pool = list_of_pools; pool; pool = pool->next)
13585 {
13586 /* Put it at the end of the relevent section. */
13587 subseg_set (pool->section, pool->sub_section);
69b97547
NC
13588#ifdef OBJ_ELF
13589 arm_elf_change_section ();
13590#endif
3d0c9500
NC
13591 s_ltorg (0);
13592 }
b99bd4ef
NC
13593}
13594
13595void
a737bd4d 13596arm_start_line_hook (void)
b99bd4ef
NC
13597{
13598 last_label_seen = NULL;
13599}
13600
13601void
a737bd4d 13602arm_frob_label (symbolS * sym)
b99bd4ef
NC
13603{
13604 last_label_seen = sym;
13605
13606 ARM_SET_THUMB (sym, thumb_mode);
13607
13608#if defined OBJ_COFF || defined OBJ_ELF
13609 ARM_SET_INTERWORK (sym, support_interwork);
13610#endif
13611
13612 /* Note - do not allow local symbols (.Lxxx) to be labeled
13613 as Thumb functions. This is because these labels, whilst
13614 they exist inside Thumb code, are not the entry points for
13615 possible ARM->Thumb calls. Also, these labels can be used
13616 as part of a computed goto or switch statement. eg gcc
13617 can generate code that looks like this:
13618
13619 ldr r2, [pc, .Laaa]
13620 lsl r3, r3, #2
13621 ldr r2, [r3, r2]
13622 mov pc, r2
cc8a6dd0 13623
b99bd4ef
NC
13624 .Lbbb: .word .Lxxx
13625 .Lccc: .word .Lyyy
13626 ..etc...
13627 .Laaa: .word Lbbb
13628
13629 The first instruction loads the address of the jump table.
13630 The second instruction converts a table index into a byte offset.
13631 The third instruction gets the jump address out of the table.
13632 The fourth instruction performs the jump.
cc8a6dd0 13633
b99bd4ef
NC
13634 If the address stored at .Laaa is that of a symbol which has the
13635 Thumb_Func bit set, then the linker will arrange for this address
13636 to have the bottom bit set, which in turn would mean that the
13637 address computation performed by the third instruction would end
13638 up with the bottom bit set. Since the ARM is capable of unaligned
13639 word loads, the instruction would then load the incorrect address
13640 out of the jump table, and chaos would ensue. */
13641 if (label_is_thumb_function_name
13642 && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13643 && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13644 {
13645 /* When the address of a Thumb function is taken the bottom
13646 bit of that address should be set. This will allow
13647 interworking between Arm and Thumb functions to work
13648 correctly. */
13649
13650 THUMB_SET_FUNC (sym, 1);
13651
b34976b6 13652 label_is_thumb_function_name = FALSE;
b99bd4ef
NC
13653 }
13654}
13655
13656/* Adjust the symbol table. This marks Thumb symbols as distinct from
13657 ARM ones. */
13658
13659void
a737bd4d 13660arm_adjust_symtab (void)
b99bd4ef
NC
13661{
13662#ifdef OBJ_COFF
13663 symbolS * sym;
13664
13665 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13666 {
13667 if (ARM_IS_THUMB (sym))
13668 {
13669 if (THUMB_IS_FUNC (sym))
13670 {
13671 /* Mark the symbol as a Thumb function. */
13672 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
13673 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
13674 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13675
13676 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13677 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13678 else
13679 as_bad (_("%s: unexpected function type: %d"),
13680 S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13681 }
cc8a6dd0 13682 else switch (S_GET_STORAGE_CLASS (sym))
b99bd4ef
NC
13683 {
13684 case C_EXT:
13685 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13686 break;
13687 case C_STAT:
13688 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13689 break;
13690 case C_LABEL:
13691 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13692 break;
13693 default:
13694 /* Do nothing. */
13695 break;
13696 }
13697 }
13698
13699 if (ARM_IS_INTERWORK (sym))
13700 coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13701 }
13702#endif
13703#ifdef OBJ_ELF
13704 symbolS * sym;
13705 char bind;
13706
13707 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13708 {
13709 if (ARM_IS_THUMB (sym))
13710 {
13711 elf_symbol_type * elf_sym;
13712
13713 elf_sym = elf_symbol (symbol_get_bfdsym (sym));
d110d6a2 13714 bind = ELF_ST_BIND (elf_sym->internal_elf_sym.st_info);
b99bd4ef
NC
13715
13716 /* If it's a .thumb_func, declare it as so,
13717 otherwise tag label as .code 16. */
13718 if (THUMB_IS_FUNC (sym))
13719 elf_sym->internal_elf_sym.st_info =
13720 ELF_ST_INFO (bind, STT_ARM_TFUNC);
13721 else
13722 elf_sym->internal_elf_sym.st_info =
13723 ELF_ST_INFO (bind, STT_ARM_16BIT);
13724 }
13725 }
13726#endif
13727}
13728
13729int
a737bd4d 13730arm_data_in_code (void)
b99bd4ef
NC
13731{
13732 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13733 {
13734 *input_line_pointer = '/';
13735 input_line_pointer += 5;
13736 *input_line_pointer = 0;
13737 return 1;
13738 }
13739
13740 return 0;
13741}
13742
13743char *
a737bd4d 13744arm_canonicalize_symbol_name (char * name)
b99bd4ef
NC
13745{
13746 int len;
13747
13748 if (thumb_mode && (len = strlen (name)) > 5
13749 && streq (name + len - 5, "/data"))
13750 *(name + len - 5) = 0;
13751
13752 return name;
13753}
13754
bfc866a6 13755#if defined OBJ_COFF || defined OBJ_ELF
a161fe53 13756void
a737bd4d 13757arm_validate_fix (fixS * fixP)
b99bd4ef
NC
13758{
13759 /* If the destination of the branch is a defined symbol which does not have
13760 the THUMB_FUNC attribute, then we must be calling a function which has
13761 the (interfacearm) attribute. We look for the Thumb entry point to that
13762 function and change the branch to refer to that function instead. */
13763 if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13764 && fixP->fx_addsy != NULL
13765 && S_IS_DEFINED (fixP->fx_addsy)
13766 && ! THUMB_IS_FUNC (fixP->fx_addsy))
13767 {
13768 fixP->fx_addsy = find_real_start (fixP->fx_addsy);
b99bd4ef 13769 }
b99bd4ef 13770}
bfc866a6 13771#endif
b99bd4ef 13772
114424c6 13773int
a737bd4d 13774arm_force_relocation (struct fix * fixp)
114424c6
AM
13775{
13776#if defined (OBJ_COFF) && defined (TE_PE)
13777 if (fixp->fx_r_type == BFD_RELOC_RVA)
13778 return 1;
13779#endif
13780#ifdef OBJ_ELF
ae6063d4 13781 if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
114424c6
AM
13782 || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
13783 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
13784 || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
13785 return 1;
13786#endif
13787
13788 /* Resolve these relocations even if the symbol is extern or weak. */
13789 if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
47281638 13790 || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
114424c6
AM
13791 || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13792 return 0;
13793
ae6063d4 13794 return generic_force_reloc (fixp);
114424c6
AM
13795}
13796
b99bd4ef
NC
13797#ifdef OBJ_COFF
13798/* This is a little hack to help the gas/arm/adrl.s test. It prevents
13799 local labels from being added to the output symbol table when they
13800 are used with the ADRL pseudo op. The ADRL relocation should always
13801 be resolved before the binbary is emitted, so it is safe to say that
13802 it is adjustable. */
13803
b34976b6 13804bfd_boolean
a737bd4d 13805arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13806{
13807 if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
13808 return 1;
13809 return 0;
13810}
13811#endif
114424c6 13812
b99bd4ef
NC
13813#ifdef OBJ_ELF
13814/* Relocations against Thumb function names must be left unadjusted,
13815 so that the linker can use this information to correctly set the
13816 bottom bit of their addresses. The MIPS version of this function
13817 also prevents relocations that are mips-16 specific, but I do not
13818 know why it does this.
13819
13820 FIXME:
13821 There is one other problem that ought to be addressed here, but
13822 which currently is not: Taking the address of a label (rather
13823 than a function) and then later jumping to that address. Such
13824 addresses also ought to have their bottom bit set (assuming that
13825 they reside in Thumb code), but at the moment they will not. */
13826
b34976b6 13827bfd_boolean
a737bd4d 13828arm_fix_adjustable (fixS * fixP)
b99bd4ef
NC
13829{
13830 if (fixP->fx_addsy == NULL)
13831 return 1;
13832
b99bd4ef
NC
13833 if (THUMB_IS_FUNC (fixP->fx_addsy)
13834 && fixP->fx_subsy == NULL)
13835 return 0;
13836
13837 /* We need the symbol name for the VTABLE entries. */
13838 if ( fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
13839 || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
13840 return 0;
13841
a161fe53
AM
13842 /* Don't allow symbols to be discarded on GOT related relocs. */
13843 if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
13844 || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
eb043451
PB
13845 || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF
13846 || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
a161fe53
AM
13847 return 0;
13848
b99bd4ef
NC
13849 return 1;
13850}
13851
13852const char *
a737bd4d 13853elf32_arm_target_format (void)
b99bd4ef 13854{
e5a52504
MM
13855#ifdef TE_SYMBIAN
13856 return (target_big_endian
13857 ? "elf32-bigarm-symbian"
13858 : "elf32-littlearm-symbian");
4e7fd91e
PB
13859#elif defined (TE_VXWORKS)
13860 return (target_big_endian
13861 ? "elf32-bigarm-vxworks"
13862 : "elf32-littlearm-vxworks");
a737bd4d 13863#else
b99bd4ef 13864 if (target_big_endian)
7f266840 13865 return "elf32-bigarm";
b99bd4ef 13866 else
7f266840 13867 return "elf32-littlearm";
e5a52504 13868#endif
b99bd4ef
NC
13869}
13870
13871void
a737bd4d
NC
13872armelf_frob_symbol (symbolS * symp,
13873 int * puntp)
b99bd4ef
NC
13874{
13875 elf_frob_symbol (symp, puntp);
13876}
13877
b99bd4ef 13878static void
a737bd4d 13879s_arm_elf_cons (int nbytes)
b99bd4ef
NC
13880{
13881 expressionS exp;
13882
13883#ifdef md_flush_pending_output
13884 md_flush_pending_output ();
13885#endif
13886
13887 if (is_it_end_of_statement ())
13888 {
13889 demand_empty_rest_of_line ();
13890 return;
13891 }
13892
13893#ifdef md_cons_align
13894 md_cons_align (nbytes);
13895#endif
13896
6057a28f 13897 mapping_state (MAP_DATA);
b99bd4ef
NC
13898 do
13899 {
13900 bfd_reloc_code_real_type reloc;
13901
13902 expression (& exp);
13903
13904 if (exp.X_op == O_symbol
13905 && * input_line_pointer == '('
13906 && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
13907 {
13908 reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
13909 int size = bfd_get_reloc_size (howto);
13910
13911 if (size > nbytes)
13912 as_bad ("%s relocations do not fit in %d bytes",
13913 howto->name, nbytes);
13914 else
13915 {
a737bd4d 13916 char *p = frag_more ((int) nbytes);
b99bd4ef
NC
13917 int offset = nbytes - size;
13918
13919 fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
13920 &exp, 0, reloc);
13921 }
13922 }
13923 else
13924 emit_expr (&exp, (unsigned int) nbytes);
13925 }
13926 while (*input_line_pointer++ == ',');
13927
13928 /* Put terminator back into stream. */
13929 input_line_pointer --;
13930 demand_empty_rest_of_line ();
13931}
13932
eb043451
PB
13933
13934/* Parse a .rel31 directive. */
13935
13936static void
13937s_arm_rel31 (int ignored ATTRIBUTE_UNUSED)
13938{
13939 expressionS exp;
13940 char *p;
13941 valueT highbit;
a737bd4d 13942
eb043451
PB
13943 SKIP_WHITESPACE ();
13944
13945 highbit = 0;
13946 if (*input_line_pointer == '1')
13947 highbit = 0x80000000;
13948 else if (*input_line_pointer != '0')
13949 as_bad (_("expected 0 or 1"));
13950
13951 input_line_pointer++;
13952 SKIP_WHITESPACE ();
13953 if (*input_line_pointer != ',')
13954 as_bad (_("missing comma"));
13955 input_line_pointer++;
13956
13957#ifdef md_flush_pending_output
13958 md_flush_pending_output ();
13959#endif
13960
13961#ifdef md_cons_align
13962 md_cons_align (4);
13963#endif
13964
13965 mapping_state (MAP_DATA);
13966
13967 expression (&exp);
13968
13969 p = frag_more (4);
13970 md_number_to_chars (p, highbit, 4);
13971 fix_new_arm (frag_now, p - frag_now->fr_literal, 4, &exp, 1,
13972 BFD_RELOC_ARM_PREL31);
13973
13974 demand_empty_rest_of_line ();
13975}
7ed4c4c5
NC
13976\f
13977/* Code to deal with unwinding tables. */
13978
13979static void add_unwind_adjustsp (offsetT);
13980
13981/* Switch to section NAME and create section if necessary. It's
13982 rather ugly that we have to manipulate input_line_pointer but I
13983 don't see any other way to accomplish the same thing without
13984 changing obj-elf.c (which may be the Right Thing, in the end).
13985 Copied from tc-ia64.c. */
13986
13987static void
13988set_section (char *name)
13989{
13990 char *saved_input_line_pointer;
13991
13992 saved_input_line_pointer = input_line_pointer;
13993 input_line_pointer = name;
13994 obj_elf_section (0);
13995 input_line_pointer = saved_input_line_pointer;
13996}
13997
13998/* Cenerate and deferred unwind frame offset. */
13999
14000static void
14001flush_pending_unwind (void)
14002{
14003 offsetT offset;
14004
14005 offset = unwind.pending_offset;
14006 unwind.pending_offset = 0;
14007 if (offset != 0)
14008 add_unwind_adjustsp (offset);
14009}
14010
14011/* Add an opcode to this list for this function. Two-byte opcodes should
14012 be passed as op[0] << 8 | op[1]. The list of opcodes is built in reverse
14013 order. */
14014
14015static void
14016add_unwind_opcode (valueT op, int length)
14017{
14018 /* Add any deferred stack adjustment. */
14019 if (unwind.pending_offset)
14020 flush_pending_unwind ();
14021
14022 unwind.sp_restored = 0;
14023
14024 if (unwind.opcode_count + length > unwind.opcode_alloc)
14025 {
14026 unwind.opcode_alloc += ARM_OPCODE_CHUNK_SIZE;
14027 if (unwind.opcodes)
14028 unwind.opcodes = xrealloc (unwind.opcodes,
14029 unwind.opcode_alloc);
14030 else
14031 unwind.opcodes = xmalloc (unwind.opcode_alloc);
14032 }
14033 while (length > 0)
14034 {
14035 length--;
14036 unwind.opcodes[unwind.opcode_count] = op & 0xff;
14037 op >>= 8;
14038 unwind.opcode_count++;
14039 }
14040}
14041
14042/* Add unwind opcodes to adjust the stack pointer. */
14043
14044static void
14045add_unwind_adjustsp (offsetT offset)
14046{
14047 valueT op;
14048
14049 if (offset > 0x200)
14050 {
14051 /* We need at most 5 bytes to hold a 32-bit value in a uleb128. */
14052 char bytes[5];
14053 int n;
14054 valueT o;
14055
14056 /* Long form: 0xb2, uleb128. */
14057 /* This might not fit in a word so add the individual bytes,
14058 remembering the list is built in reverse order. */
14059 o = (valueT) ((offset - 0x204) >> 2);
14060 if (o == 0)
14061 add_unwind_opcode (0, 1);
14062
14063 /* Calculate the uleb128 encoding of the offset. */
14064 n = 0;
14065 while (o)
14066 {
14067 bytes[n] = o & 0x7f;
14068 o >>= 7;
14069 if (o)
14070 bytes[n] |= 0x80;
14071 n++;
14072 }
14073 /* Add the insn. */
14074 for (; n; n--)
14075 add_unwind_opcode (bytes[n - 1], 1);
14076 add_unwind_opcode (0xb2, 1);
14077 }
14078 else if (offset > 0x100)
14079 {
14080 /* Two short opcodes. */
14081 add_unwind_opcode (0x3f, 1);
14082 op = (offset - 0x104) >> 2;
14083 add_unwind_opcode (op, 1);
14084 }
14085 else if (offset > 0)
14086 {
14087 /* Short opcode. */
14088 op = (offset - 4) >> 2;
14089 add_unwind_opcode (op, 1);
14090 }
14091 else if (offset < 0)
14092 {
14093 offset = -offset;
14094 while (offset > 0x100)
14095 {
14096 add_unwind_opcode (0x7f, 1);
14097 offset -= 0x100;
14098 }
14099 op = ((offset - 4) >> 2) | 0x40;
14100 add_unwind_opcode (op, 1);
14101 }
14102}
14103
14104/* Finish the list of unwind opcodes for this function. */
14105static void
14106finish_unwind_opcodes (void)
14107{
14108 valueT op;
14109
14110 if (unwind.fp_used)
14111 {
14112 /* Adjust sp as neccessary. */
14113 unwind.pending_offset += unwind.fp_offset - unwind.frame_size;
14114 flush_pending_unwind ();
14115
14116 /* After restoring sp from the frame pointer. */
14117 op = 0x90 | unwind.fp_reg;
14118 add_unwind_opcode (op, 1);
14119 }
14120 else
14121 flush_pending_unwind ();
14122}
14123
14124
14125/* Start an exception table entry. If idx is nonzero this is an index table
14126 entry. */
14127
14128static void
14129start_unwind_section (const segT text_seg, int idx)
14130{
14131 const char * text_name;
14132 const char * prefix;
14133 const char * prefix_once;
14134 size_t prefix_len;
14135 size_t text_len;
14136 char * sec_name;
14137 size_t sec_name_len;
14138
14139 if (idx)
14140 {
14141 prefix = ELF_STRING_ARM_unwind;
14142 prefix_once = ELF_STRING_ARM_unwind_once;
14143 }
14144 else
14145 {
14146 prefix = ELF_STRING_ARM_unwind_info;
14147 prefix_once = ELF_STRING_ARM_unwind_info_once;
14148 }
14149
14150 text_name = segment_name (text_seg);
14151 if (streq (text_name, ".text"))
14152 text_name = "";
14153
14154 if (strncmp (text_name, ".gnu.linkonce.t.",
14155 strlen (".gnu.linkonce.t.")) == 0)
14156 {
14157 prefix = prefix_once;
14158 text_name += strlen (".gnu.linkonce.t.");
14159 }
14160
14161 prefix_len = strlen (prefix);
14162 text_len = strlen (text_name);
14163 sec_name_len = prefix_len + text_len;
14164 sec_name = alloca (sec_name_len + 1);
14165 memcpy (sec_name, prefix, prefix_len);
14166 memcpy (sec_name + prefix_len, text_name, text_len);
14167 sec_name[prefix_len + text_len] = '\0';
14168
14169 /* Handle COMDAT group. */
14170 if (prefix != prefix_once && (text_seg->flags & SEC_LINK_ONCE) != 0)
14171 {
14172 char *section;
14173 size_t len, group_name_len;
14174 const char *group_name = elf_group_name (text_seg);
14175
14176 if (group_name == NULL)
14177 {
14178 as_bad ("Group section `%s' has no group signature",
14179 segment_name (text_seg));
14180 ignore_rest_of_line ();
14181 return;
14182 }
14183 /* We have to construct a fake section directive. */
14184 group_name_len = strlen (group_name);
14185 if (idx)
14186 prefix_len = 13;
14187 else
14188 prefix_len = 16;
14189
14190 len = (sec_name_len
14191 + prefix_len /* ,"aG",%sectiontype, */
14192 + group_name_len /* ,group_name */
14193 + 7); /* ,comdat */
14194
14195 section = alloca (len + 1);
14196 memcpy (section, sec_name, sec_name_len);
14197 if (idx)
14198 memcpy (section + sec_name_len, ",\"aG\",%exidx,", 13);
14199 else
14200 memcpy (section + sec_name_len, ",\"aG\",%progbits,", 16);
14201 memcpy (section + sec_name_len + prefix_len, group_name, group_name_len);
14202 memcpy (section + len - 7, ",comdat", 7);
14203 section [len] = '\0';
14204 set_section (section);
14205 }
14206 else
14207 {
14208 set_section (sec_name);
14209 bfd_set_section_flags (stdoutput, now_seg,
14210 SEC_LOAD | SEC_ALLOC | SEC_READONLY);
14211 }
14212
14213 /* Set the setion link for index tables. */
14214 if (idx)
14215 elf_linked_to_section (now_seg) = text_seg;
14216}
14217
14218
14219/* Start an unwind table entry. HAVE_DATA is nonzero if we have additional
14220 personality routine data. Returns zero, or the index table value for
14221 and inline entry. */
14222
14223static valueT
14224create_unwind_entry (int have_data)
14225{
14226 int size;
14227 addressT where;
2132e3a3 14228 char *ptr;
7ed4c4c5
NC
14229 /* The current word of data. */
14230 valueT data;
14231 /* The number of bytes left in this word. */
14232 int n;
14233
14234 finish_unwind_opcodes ();
14235
14236 /* Remember the current text section. */
14237 unwind.saved_seg = now_seg;
14238 unwind.saved_subseg = now_subseg;
14239
14240 start_unwind_section (now_seg, 0);
14241
14242 if (unwind.personality_routine == NULL)
14243 {
14244 if (unwind.personality_index == -2)
14245 {
14246 if (have_data)
14247 as_bad (_("handerdata in cantunwind frame"));
14248 return 1; /* EXIDX_CANTUNWIND. */
14249 }
14250
14251 /* Use a default personality routine if none is specified. */
14252 if (unwind.personality_index == -1)
14253 {
14254 if (unwind.opcode_count > 3)
14255 unwind.personality_index = 1;
14256 else
14257 unwind.personality_index = 0;
14258 }
14259
14260 /* Space for the personality routine entry. */
14261 if (unwind.personality_index == 0)
14262 {
14263 if (unwind.opcode_count > 3)
14264 as_bad (_("too many unwind opcodes for personality routine 0"));
14265
14266 if (!have_data)
14267 {
14268 /* All the data is inline in the index table. */
14269 data = 0x80;
14270 n = 3;
14271 while (unwind.opcode_count > 0)
14272 {
14273 unwind.opcode_count--;
14274 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14275 n--;
14276 }
14277
14278 /* Pad with "finish" opcodes. */
14279 while (n--)
14280 data = (data << 8) | 0xb0;
14281
14282 return data;
14283 }
14284 size = 0;
14285 }
14286 else
14287 /* We get two opcodes "free" in the first word. */
14288 size = unwind.opcode_count - 2;
14289 }
14290 else
14291 /* An extra byte is required for the opcode count. */
14292 size = unwind.opcode_count + 1;
14293
14294 size = (size + 3) >> 2;
14295 if (size > 0xff)
14296 as_bad (_("too many unwind opcodes"));
14297
14298 frag_align (2, 0, 0);
14299 record_alignment (now_seg, 2);
14300 unwind.table_entry = expr_build_dot ();
14301
14302 /* Allocate the table entry. */
14303 ptr = frag_more ((size << 2) + 4);
14304 where = frag_now_fix () - ((size << 2) + 4);
14305
14306 switch (unwind.personality_index)
14307 {
14308 case -1:
14309 /* ??? Should this be a PLT generating relocation? */
14310 /* Custom personality routine. */
14311 fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
14312 BFD_RELOC_ARM_PREL31);
620b81c1 14313
7ed4c4c5
NC
14314 where += 4;
14315 ptr += 4;
14316
14317 /* Set the first byte to the number of additional words. */
14318 data = size - 1;
14319 n = 3;
14320 break;
14321
14322 /* ABI defined personality routines. */
7ed4c4c5
NC
14323 case 0:
14324 /* Three opcodes bytes are packed into the first word. */
14325 data = 0x80;
14326 n = 3;
84798bd6 14327 break;
7ed4c4c5
NC
14328
14329 case 1:
14330 case 2:
14331 /* The size and first two opcode bytes go in the first word. */
14332 data = ((0x80 + unwind.personality_index) << 8) | size;
14333 n = 2;
14334 break;
14335
14336 default:
14337 /* Should never happen. */
14338 abort ();
14339 }
14340
14341 /* Pack the opcodes into words (MSB first), reversing the list at the same
14342 time. */
14343 while (unwind.opcode_count > 0)
14344 {
14345 if (n == 0)
14346 {
14347 md_number_to_chars (ptr, data, 4);
14348 ptr += 4;
14349 n = 4;
14350 data = 0;
14351 }
14352 unwind.opcode_count--;
14353 n--;
14354 data = (data << 8) | unwind.opcodes[unwind.opcode_count];
14355 }
14356
14357 /* Finish off the last word. */
14358 if (n < 4)
14359 {
14360 /* Pad with "finish" opcodes. */
14361 while (n--)
14362 data = (data << 8) | 0xb0;
14363
14364 md_number_to_chars (ptr, data, 4);
14365 }
14366
14367 if (!have_data)
14368 {
14369 /* Add an empty descriptor if there is no user-specified data. */
14370 ptr = frag_more (4);
14371 md_number_to_chars (ptr, 0, 4);
14372 }
14373
14374 return 0;
14375}
14376
14377
14378/* Parse an unwind_fnstart directive. Simply records the current location. */
14379
14380static void
14381s_arm_unwind_fnstart (int ignored ATTRIBUTE_UNUSED)
14382{
14383 demand_empty_rest_of_line ();
14384 /* Mark the start of the function. */
14385 unwind.proc_start = expr_build_dot ();
14386
14387 /* Reset the rest of the unwind info. */
14388 unwind.opcode_count = 0;
14389 unwind.table_entry = NULL;
14390 unwind.personality_routine = NULL;
14391 unwind.personality_index = -1;
14392 unwind.frame_size = 0;
14393 unwind.fp_offset = 0;
14394 unwind.fp_reg = 13;
14395 unwind.fp_used = 0;
14396 unwind.sp_restored = 0;
14397}
14398
14399
14400/* Parse a handlerdata directive. Creates the exception handling table entry
14401 for the function. */
14402
14403static void
14404s_arm_unwind_handlerdata (int ignored ATTRIBUTE_UNUSED)
14405{
14406 demand_empty_rest_of_line ();
14407 if (unwind.table_entry)
14408 as_bad (_("dupicate .handlerdata directive"));
14409
14410 create_unwind_entry (1);
14411}
14412
14413/* Parse an unwind_fnend directive. Generates the index table entry. */
14414
14415static void
14416s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
14417{
14418 long where;
2132e3a3 14419 char *ptr;
7ed4c4c5
NC
14420 valueT val;
14421
14422 demand_empty_rest_of_line ();
14423
14424 /* Add eh table entry. */
14425 if (unwind.table_entry == NULL)
14426 val = create_unwind_entry (0);
14427 else
14428 val = 0;
14429
14430 /* Add index table entry. This is two words. */
14431 start_unwind_section (unwind.saved_seg, 1);
14432 frag_align (2, 0, 0);
14433 record_alignment (now_seg, 2);
14434
14435 ptr = frag_more (8);
14436 where = frag_now_fix () - 8;
14437
14438 /* Self relative offset of the function start. */
14439 fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
be1b2b4b 14440 BFD_RELOC_ARM_PREL31);
7ed4c4c5 14441
84798bd6
JB
14442 /* Indicate dependency on EHABI-defined personality routines to the
14443 linker, if it hasn't been done already. */
14444 if (unwind.personality_index >= 0 && unwind.personality_index < 3)
14445 {
14446 char *name[] = { "__aeabi_unwind_cpp_pr0",
14447 "__aeabi_unwind_cpp_pr1",
14448 "__aeabi_unwind_cpp_pr2" };
14449 if (!(marked_pr_dependency & (1 << unwind.personality_index)))
14450 {
14451 symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
14452 fix_new (frag_now, where, 0, pr, 0, 1, BFD_RELOC_NONE);
14453 marked_pr_dependency |= 1 << unwind.personality_index;
14454 seg_info (now_seg)->tc_segment_info_data.marked_pr_dependency
14455 = marked_pr_dependency;
14456 }
14457 }
14458
7ed4c4c5
NC
14459 if (val)
14460 /* Inline exception table entry. */
14461 md_number_to_chars (ptr + 4, val, 4);
14462 else
14463 /* Self relative offset of the table entry. */
14464 fix_new (frag_now, where + 4, 4, unwind.table_entry, 0, 1,
14465 BFD_RELOC_ARM_PREL31);
14466
14467 /* Restore the original section. */
14468 subseg_set (unwind.saved_seg, unwind.saved_subseg);
14469}
14470
14471
14472/* Parse an unwind_cantunwind directive. */
14473
14474static void
14475s_arm_unwind_cantunwind (int ignored ATTRIBUTE_UNUSED)
14476{
14477 demand_empty_rest_of_line ();
14478 if (unwind.personality_routine || unwind.personality_index != -1)
14479 as_bad (_("personality routine specified for cantunwind frame"));
14480
14481 unwind.personality_index = -2;
14482}
14483
14484
14485/* Parse a personalityindex directive. */
14486
14487static void
14488s_arm_unwind_personalityindex (int ignored ATTRIBUTE_UNUSED)
14489{
14490 expressionS exp;
14491
14492 if (unwind.personality_routine || unwind.personality_index != -1)
14493 as_bad (_("duplicate .personalityindex directive"));
14494
14495 SKIP_WHITESPACE ();
14496
14497 expression (&exp);
14498
14499 if (exp.X_op != O_constant
14500 || exp.X_add_number < 0 || exp.X_add_number > 15)
14501 {
14502 as_bad (_("bad personality routine number"));
14503 ignore_rest_of_line ();
14504 return;
14505 }
14506
14507 unwind.personality_index = exp.X_add_number;
14508
14509 demand_empty_rest_of_line ();
14510}
14511
14512
14513/* Parse a personality directive. */
14514
14515static void
14516s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
14517{
14518 char *name, *p, c;
14519
14520 if (unwind.personality_routine || unwind.personality_index != -1)
14521 as_bad (_("duplicate .personality directive"));
14522
14523 SKIP_WHITESPACE ();
14524 name = input_line_pointer;
14525 c = get_symbol_end ();
14526 p = input_line_pointer;
14527 unwind.personality_routine = symbol_find_or_make (name);
14528 *p = c;
14529 SKIP_WHITESPACE ();
14530 demand_empty_rest_of_line ();
14531}
14532
14533
14534/* Parse a directive saving core registers. */
14535
14536static void
14537s_arm_unwind_save_core (void)
14538{
14539 valueT op;
14540 long range;
14541 int n;
14542
14543 SKIP_WHITESPACE ();
14544 range = reg_list (&input_line_pointer);
14545 if (range == FAIL)
14546 {
14547 as_bad (_("expected register list"));
14548 ignore_rest_of_line ();
14549 return;
14550 }
14551
14552 demand_empty_rest_of_line ();
14553
14554 /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
14555 into .unwind_save {..., sp...}. We aren't bothered about the value of
14556 ip because it is clobbered by calls. */
14557 if (unwind.sp_restored && unwind.fp_reg == 12
14558 && (range & 0x3000) == 0x1000)
14559 {
14560 unwind.opcode_count--;
14561 unwind.sp_restored = 0;
14562 range = (range | 0x2000) & ~0x1000;
14563 unwind.pending_offset = 0;
14564 }
14565
14566 /* See if we can use the short opcodes. These pop a block of upto 8
14567 registers starting with r4, plus maybe r14. */
14568 for (n = 0; n < 8; n++)
14569 {
14570 /* Break at the first non-saved register. */
14571 if ((range & (1 << (n + 4))) == 0)
14572 break;
14573 }
14574 /* See if there are any other bits set. */
14575 if (n == 0 || (range & (0xfff0 << n) & 0xbff0) != 0)
14576 {
14577 /* Use the long form. */
14578 op = 0x8000 | ((range >> 4) & 0xfff);
14579 add_unwind_opcode (op, 2);
14580 }
14581 else
14582 {
14583 /* Use the short form. */
14584 if (range & 0x4000)
14585 op = 0xa8; /* Pop r14. */
14586 else
14587 op = 0xa0; /* Do not pop r14. */
14588 op |= (n - 1);
14589 add_unwind_opcode (op, 1);
14590 }
14591
14592 /* Pop r0-r3. */
14593 if (range & 0xf)
14594 {
14595 op = 0xb100 | (range & 0xf);
14596 add_unwind_opcode (op, 2);
14597 }
14598
14599 /* Record the number of bytes pushed. */
14600 for (n = 0; n < 16; n++)
14601 {
14602 if (range & (1 << n))
14603 unwind.frame_size += 4;
14604 }
14605}
14606
14607
14608/* Parse a directive saving FPA registers. */
14609
14610static void
14611s_arm_unwind_save_fpa (int reg)
14612{
14613 expressionS exp;
14614 int num_regs;
14615 valueT op;
14616
14617 /* Get Number of registers to transfer. */
14618 if (skip_past_comma (&input_line_pointer) != FAIL)
14619 expression (&exp);
14620 else
14621 exp.X_op = O_illegal;
14622
14623 if (exp.X_op != O_constant)
14624 {
14625 as_bad (_("expected , <constant>"));
14626 ignore_rest_of_line ();
14627 return;
14628 }
14629
14630 num_regs = exp.X_add_number;
14631
14632 if (num_regs < 1 || num_regs > 4)
14633 {
14634 as_bad (_("number of registers must be in the range [1:4]"));
14635 ignore_rest_of_line ();
14636 return;
14637 }
14638
14639 demand_empty_rest_of_line ();
14640
14641 if (reg == 4)
14642 {
14643 /* Short form. */
14644 op = 0xb4 | (num_regs - 1);
14645 add_unwind_opcode (op, 1);
14646 }
14647 else
14648 {
14649 /* Long form. */
14650 op = 0xc800 | (reg << 4) | (num_regs - 1);
14651 add_unwind_opcode (op, 2);
14652 }
14653 unwind.frame_size += num_regs * 12;
14654}
14655
14656
14657/* Parse a directive saving VFP registers. */
14658
14659static void
14660s_arm_unwind_save_vfp (void)
14661{
14662 int count;
14663 int reg;
14664 valueT op;
14665
14666 count = vfp_parse_reg_list (&input_line_pointer, &reg, 1);
14667 if (count == FAIL)
14668 {
14669 as_bad (_("expected register list"));
14670 ignore_rest_of_line ();
14671 return;
14672 }
14673
14674 demand_empty_rest_of_line ();
14675
14676 if (reg == 8)
14677 {
14678 /* Short form. */
14679 op = 0xb8 | (count - 1);
14680 add_unwind_opcode (op, 1);
14681 }
14682 else
14683 {
14684 /* Long form. */
14685 op = 0xb300 | (reg << 4) | (count - 1);
14686 add_unwind_opcode (op, 2);
14687 }
14688 unwind.frame_size += count * 8 + 4;
14689}
14690
14691
14692/* Parse a directive saving iWMMXt registers. */
14693
14694static void
14695s_arm_unwind_save_wmmx (void)
14696{
14697 int reg;
14698 int hi_reg;
14699 int i;
14700 unsigned wcg_mask;
14701 unsigned wr_mask;
14702 valueT op;
14703
14704 if (*input_line_pointer == '{')
14705 input_line_pointer++;
14706
14707 wcg_mask = 0;
14708 wr_mask = 0;
14709 do
14710 {
14711 reg = arm_reg_parse (&input_line_pointer,
14712 all_reg_maps[REG_TYPE_IWMMXT].htab);
14713
14714 if (wr_register (reg))
14715 {
14716 i = reg & ~WR_PREFIX;
14717 if (wr_mask >> i)
14718 as_tsktsk (_("register list not in ascending order"));
14719 wr_mask |= 1 << i;
14720 }
14721 else if (wcg_register (reg))
14722 {
14723 i = (reg & ~WC_PREFIX) - 8;
14724 if (wcg_mask >> i)
14725 as_tsktsk (_("register list not in ascending order"));
14726 wcg_mask |= 1 << i;
14727 }
14728 else
14729 {
14730 as_bad (_("expected wr or wcgr"));
14731 goto error;
14732 }
14733
14734 SKIP_WHITESPACE ();
14735 if (*input_line_pointer == '-')
14736 {
14737 hi_reg = arm_reg_parse (&input_line_pointer,
14738 all_reg_maps[REG_TYPE_IWMMXT].htab);
14739 if (wr_register (reg) && wr_register (hi_reg))
14740 {
14741 for (; reg < hi_reg; reg++)
14742 wr_mask |= 1 << (reg & ~WR_PREFIX);
14743 }
14744 else if (wcg_register (reg) && wcg_register (hi_reg))
14745 {
14746 for (; reg < hi_reg; reg++)
14747 wcg_mask |= 1 << ((reg & ~WC_PREFIX) - 8);
14748 }
14749 else
14750 {
14751 as_bad (_("bad register range"));
14752 goto error;
14753 }
14754 }
14755 }
14756 while (skip_past_comma (&input_line_pointer) != FAIL);
14757
14758 SKIP_WHITESPACE ();
14759 if (*input_line_pointer == '}')
14760 input_line_pointer++;
14761
14762 demand_empty_rest_of_line ();
14763
14764 if (wr_mask && wcg_mask)
14765 {
14766 as_bad (_("inconsistent register types"));
14767 goto error;
14768 }
14769
14770 /* Generate any deferred opcodes becuuse we're going to be looking at
14771 the list. */
14772 flush_pending_unwind ();
14773
14774 if (wcg_mask)
14775 {
14776 for (i = 0; i < 16; i++)
14777 {
14778 if (wcg_mask & (1 << i))
14779 unwind.frame_size += 4;
14780 }
14781 op = 0xc700 | wcg_mask;
14782 add_unwind_opcode (op, 2);
14783 }
14784 else
14785 {
14786 for (i = 0; i < 16; i++)
14787 {
14788 if (wr_mask & (1 << i))
14789 unwind.frame_size += 8;
14790 }
14791 /* Attempt to combine with a previous opcode. We do this because gcc
14792 likes to output separate unwind directives for a single block of
14793 registers. */
14794 if (unwind.opcode_count > 0)
14795 {
14796 i = unwind.opcodes[unwind.opcode_count - 1];
14797 if ((i & 0xf8) == 0xc0)
14798 {
14799 i &= 7;
14800 /* Only merge if the blocks are contiguous. */
14801 if (i < 6)
14802 {
14803 if ((wr_mask & 0xfe00) == (1 << 9))
14804 {
14805 wr_mask |= ((1 << (i + 11)) - 1) & 0xfc00;
14806 unwind.opcode_count--;
14807 }
14808 }
14809 else if (i == 6 && unwind.opcode_count >= 2)
14810 {
14811 i = unwind.opcodes[unwind.opcode_count - 2];
14812 reg = i >> 4;
14813 i &= 0xf;
14814
14815 op = 0xffff << (reg - 1);
14816 if (reg > 0
14817 || ((wr_mask & op) == (1u << (reg - 1))))
14818 {
14819 op = (1 << (reg + i + 1)) - 1;
14820 op &= ~((1 << reg) - 1);
14821 wr_mask |= op;
14822 unwind.opcode_count -= 2;
14823 }
14824 }
14825 }
14826 }
14827
14828 hi_reg = 15;
14829 /* We want to generate opcodes in the order the registers have been
14830 saved, ie. descending order. */
14831 for (reg = 15; reg >= -1; reg--)
14832 {
14833 /* Save registers in blocks. */
14834 if (reg < 0
14835 || !(wr_mask & (1 << reg)))
14836 {
14837 /* We found an unsaved reg. Generate opcodes to save the
14838 preceeding block. */
14839 if (reg != hi_reg)
14840 {
14841 if (reg == 9)
14842 {
14843 /* Short form. */
14844 op = 0xc0 | (hi_reg - 10);
14845 add_unwind_opcode (op, 1);
14846 }
14847 else
14848 {
14849 /* Long form. */
14850 op = 0xc600 | ((reg + 1) << 4) | ((hi_reg - reg) - 1);
14851 add_unwind_opcode (op, 2);
14852 }
14853 }
14854 hi_reg = reg - 1;
14855 }
14856 }
14857 }
14858 return;
14859error:
14860 ignore_rest_of_line ();
14861}
14862
14863
14864/* Parse an unwind_save directive. */
14865
14866static void
14867s_arm_unwind_save (int ignored ATTRIBUTE_UNUSED)
14868{
14869 char *saved_ptr;
14870 int reg;
14871
14872 /* Figure out what sort of save we have. */
14873 SKIP_WHITESPACE ();
14874 saved_ptr = input_line_pointer;
14875
14876 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_FN].htab);
14877 if (reg != FAIL)
14878 {
14879 s_arm_unwind_save_fpa (reg);
14880 return;
14881 }
14882
14883 if (*input_line_pointer == '{')
14884 input_line_pointer++;
14885
14886 SKIP_WHITESPACE ();
14887
14888 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_RN].htab);
14889 if (reg != FAIL)
14890 {
14891 input_line_pointer = saved_ptr;
14892 s_arm_unwind_save_core ();
14893 return;
14894 }
14895
14896 reg = arm_reg_parse (&input_line_pointer, all_reg_maps[REG_TYPE_DN].htab);
14897 if (reg != FAIL)
14898 {
14899 input_line_pointer = saved_ptr;
14900 s_arm_unwind_save_vfp ();
14901 return;
14902 }
14903
14904 reg = arm_reg_parse (&input_line_pointer,
14905 all_reg_maps[REG_TYPE_IWMMXT].htab);
14906 if (reg != FAIL)
14907 {
14908 input_line_pointer = saved_ptr;
14909 s_arm_unwind_save_wmmx ();
14910 return;
14911 }
14912
14913 /* TODO: Maverick registers. */
14914 as_bad (_("unrecognised register"));
14915}
14916
14917
14918/* Parse an unwind_movsp directive. */
14919
14920static void
14921s_arm_unwind_movsp (int ignored ATTRIBUTE_UNUSED)
14922{
14923 int reg;
14924 valueT op;
14925
14926 SKIP_WHITESPACE ();
14927 reg = reg_required_here (&input_line_pointer, -1);
14928 if (reg == FAIL)
14929 {
14930 as_bad (_("ARM register expected"));
14931 ignore_rest_of_line ();
14932 return;
14933 }
14934
14935 if (reg == 13 || reg == 15)
14936 {
14937 as_bad (_("r%d not permitted in .unwind_movsp directive"), reg);
14938 ignore_rest_of_line ();
14939 return;
14940 }
14941
14942 if (unwind.fp_reg != 13)
14943 as_bad (_("unexpected .unwind_movsp directive"));
14944
14945 /* Generate opcode to restore the value. */
14946 op = 0x90 | reg;
14947 add_unwind_opcode (op, 1);
14948
14949 /* Record the information for later. */
14950 unwind.fp_reg = reg;
14951 unwind.fp_offset = unwind.frame_size;
14952 unwind.sp_restored = 1;
14953 demand_empty_rest_of_line ();
14954}
14955
14956
14957/* Parse #<number>. */
14958
14959static int
14960require_hashconst (int * val)
14961{
14962 expressionS exp;
14963
14964 SKIP_WHITESPACE ();
14965 if (*input_line_pointer == '#')
14966 {
14967 input_line_pointer++;
14968 expression (&exp);
14969 }
14970 else
14971 exp.X_op = O_illegal;
14972
14973 if (exp.X_op != O_constant)
14974 {
14975 as_bad (_("expected #constant"));
14976 ignore_rest_of_line ();
14977 return FAIL;
14978 }
14979 *val = exp.X_add_number;
14980 return SUCCESS;
14981}
14982
14983/* Parse an unwind_pad directive. */
14984
14985static void
14986s_arm_unwind_pad (int ignored ATTRIBUTE_UNUSED)
14987{
14988 int offset;
14989
14990 if (require_hashconst (&offset) == FAIL)
14991 return;
14992
14993 if (offset & 3)
14994 {
14995 as_bad (_("stack increment must be multiple of 4"));
14996 ignore_rest_of_line ();
14997 return;
14998 }
14999
15000 /* Don't generate any opcodes, just record the details for later. */
15001 unwind.frame_size += offset;
15002 unwind.pending_offset += offset;
15003
15004 demand_empty_rest_of_line ();
15005}
15006
15007/* Parse an unwind_setfp directive. */
15008
15009static void
15010s_arm_unwind_setfp (int ignored ATTRIBUTE_UNUSED)
15011{
15012 int sp_reg;
15013 int fp_reg;
15014 int offset;
15015
15016 fp_reg = reg_required_here (&input_line_pointer, -1);
15017 if (skip_past_comma (&input_line_pointer) == FAIL)
15018 sp_reg = FAIL;
15019 else
15020 sp_reg = reg_required_here (&input_line_pointer, -1);
15021
15022 if (fp_reg == FAIL || sp_reg == FAIL)
15023 {
15024 as_bad (_("expected <reg>, <reg>"));
15025 ignore_rest_of_line ();
15026 return;
15027 }
15028
15029 /* Optonal constant. */
15030 if (skip_past_comma (&input_line_pointer) != FAIL)
15031 {
15032 if (require_hashconst (&offset) == FAIL)
15033 return;
15034 }
15035 else
15036 offset = 0;
15037
15038 demand_empty_rest_of_line ();
15039
15040 if (sp_reg != 13 && sp_reg != unwind.fp_reg)
15041 {
15042 as_bad (_("register must be either sp or set by a previous"
15043 "unwind_movsp directive"));
15044 return;
15045 }
15046
15047 /* Don't generate any opcodes, just record the information for later. */
15048 unwind.fp_reg = fp_reg;
15049 unwind.fp_used = 1;
15050 if (sp_reg == 13)
15051 unwind.fp_offset = unwind.frame_size - offset;
15052 else
15053 unwind.fp_offset -= offset;
15054}
15055
15056/* Parse an unwind_raw directive. */
15057
15058static void
15059s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED)
15060{
15061 expressionS exp;
15062 /* This is an arbitary limit. */
15063 unsigned char op[16];
15064 int count;
15065
15066 SKIP_WHITESPACE ();
15067 expression (&exp);
15068 if (exp.X_op == O_constant
15069 && skip_past_comma (&input_line_pointer) != FAIL)
15070 {
15071 unwind.frame_size += exp.X_add_number;
15072 expression (&exp);
15073 }
15074 else
15075 exp.X_op = O_illegal;
15076
15077 if (exp.X_op != O_constant)
15078 {
15079 as_bad (_("expected <offset>, <opcode>"));
15080 ignore_rest_of_line ();
15081 return;
15082 }
15083
15084 count = 0;
15085
15086 /* Parse the opcode. */
15087 for (;;)
15088 {
15089 if (count >= 16)
15090 {
15091 as_bad (_("unwind opcode too long"));
15092 ignore_rest_of_line ();
15093 }
15094 if (exp.X_op != O_constant || exp.X_add_number & ~0xff)
15095 {
15096 as_bad (_("invalid unwind opcode"));
15097 ignore_rest_of_line ();
15098 return;
15099 }
15100 op[count++] = exp.X_add_number;
15101
15102 /* Parse the next byte. */
15103 if (skip_past_comma (&input_line_pointer) == FAIL)
15104 break;
15105
15106 expression (&exp);
15107 }
15108
15109 /* Add the opcode bytes in reverse order. */
15110 while (count--)
15111 add_unwind_opcode (op[count], 1);
15112
15113 demand_empty_rest_of_line ();
15114}
eb043451 15115
b99bd4ef
NC
15116#endif /* OBJ_ELF */
15117
15118/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
15119 of an rs_align_code fragment. */
15120
15121void
a737bd4d 15122arm_handle_align (fragS * fragP)
b99bd4ef
NC
15123{
15124 static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
15125 static char const thumb_noop[2] = { 0xc0, 0x46 };
15126 static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
15127 static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
15128
15129 int bytes, fix, noop_size;
15130 char * p;
15131 const char * noop;
cc8a6dd0 15132
b99bd4ef
NC
15133 if (fragP->fr_type != rs_align_code)
15134 return;
15135
15136 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
15137 p = fragP->fr_literal + fragP->fr_fix;
15138 fix = 0;
cc8a6dd0 15139
b99bd4ef
NC
15140 if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
15141 bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
cc8a6dd0 15142
b99bd4ef
NC
15143 if (fragP->tc_frag_data)
15144 {
15145 if (target_big_endian)
15146 noop = thumb_bigend_noop;
15147 else
15148 noop = thumb_noop;
15149 noop_size = sizeof (thumb_noop);
15150 }
15151 else
15152 {
15153 if (target_big_endian)
15154 noop = arm_bigend_noop;
15155 else
15156 noop = arm_noop;
15157 noop_size = sizeof (arm_noop);
15158 }
cc8a6dd0 15159
b99bd4ef
NC
15160 if (bytes & (noop_size - 1))
15161 {
15162 fix = bytes & (noop_size - 1);
15163 memset (p, 0, fix);
15164 p += fix;
15165 bytes -= fix;
15166 }
15167
15168 while (bytes >= noop_size)
15169 {
15170 memcpy (p, noop, noop_size);
15171 p += noop_size;
15172 bytes -= noop_size;
15173 fix += noop_size;
15174 }
cc8a6dd0 15175
b99bd4ef
NC
15176 fragP->fr_fix += fix;
15177 fragP->fr_var = noop_size;
15178}
15179
15180/* Called from md_do_align. Used to create an alignment
15181 frag in a code section. */
15182
15183void
a737bd4d 15184arm_frag_align_code (int n, int max)
b99bd4ef
NC
15185{
15186 char * p;
15187
2d2255b5 15188 /* We assume that there will never be a requirement
b99bd4ef
NC
15189 to support alignments greater than 32 bytes. */
15190 if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
15191 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
cc8a6dd0 15192
b99bd4ef
NC
15193 p = frag_var (rs_align_code,
15194 MAX_MEM_FOR_RS_ALIGN_CODE,
15195 1,
15196 (relax_substateT) max,
15197 (symbolS *) NULL,
15198 (offsetT) n,
15199 (char *) NULL);
15200 *p = 0;
b99bd4ef
NC
15201}
15202
15203/* Perform target specific initialisation of a frag. */
15204
15205void
a737bd4d 15206arm_init_frag (fragS * fragP)
b99bd4ef
NC
15207{
15208 /* Record whether this frag is in an ARM or a THUMB area. */
15209 fragP->tc_frag_data = thumb_mode;
15210}
a737bd4d 15211
a394c00f
NC
15212#ifdef OBJ_ELF
15213
15214/* Convert REGNAME to a DWARF-2 register number. */
15215
15216int
15217tc_arm_regname_to_dw2regnum (const char *regname)
15218{
15219 unsigned int i;
15220
15221 for (i = 0; rn_table[i].name; i++)
15222 if (streq (regname, rn_table[i].name))
15223 return rn_table[i].number;
15224
15225 return -1;
15226}
15227
15228/* Initialize the DWARF-2 unwind information for this procedure. */
15229
15230void
15231tc_arm_frame_initial_instructions (void)
15232{
15233 cfi_add_CFA_def_cfa (REG_SP, 0);
15234}
15235#endif
15236
a737bd4d
NC
15237/* This table describes all the machine specific pseudo-ops the assembler
15238 has to support. The fields are:
15239 pseudo-op name without dot
15240 function to call to execute this pseudo-op
15241 Integer arg to pass to the function. */
15242
15243const pseudo_typeS md_pseudo_table[] =
15244{
15245 /* Never called because '.req' does not start a line. */
15246 { "req", s_req, 0 },
15247 { "unreq", s_unreq, 0 },
15248 { "bss", s_bss, 0 },
15249 { "align", s_align, 0 },
15250 { "arm", s_arm, 0 },
15251 { "thumb", s_thumb, 0 },
15252 { "code", s_code, 0 },
15253 { "force_thumb", s_force_thumb, 0 },
15254 { "thumb_func", s_thumb_func, 0 },
15255 { "thumb_set", s_thumb_set, 0 },
15256 { "even", s_even, 0 },
15257 { "ltorg", s_ltorg, 0 },
15258 { "pool", s_ltorg, 0 },
15259#ifdef OBJ_ELF
15260 { "word", s_arm_elf_cons, 4 },
15261 { "long", s_arm_elf_cons, 4 },
15262 { "rel31", s_arm_rel31, 0 },
7ed4c4c5
NC
15263 { "fnstart", s_arm_unwind_fnstart, 0 },
15264 { "fnend", s_arm_unwind_fnend, 0 },
15265 { "cantunwind", s_arm_unwind_cantunwind, 0 },
15266 { "personality", s_arm_unwind_personality, 0 },
15267 { "personalityindex", s_arm_unwind_personalityindex, 0 },
15268 { "handlerdata", s_arm_unwind_handlerdata, 0 },
15269 { "save", s_arm_unwind_save, 0 },
15270 { "movsp", s_arm_unwind_movsp, 0 },
15271 { "pad", s_arm_unwind_pad, 0 },
15272 { "setfp", s_arm_unwind_setfp, 0 },
15273 { "unwind_raw", s_arm_unwind_raw, 0 },
a737bd4d
NC
15274#else
15275 { "word", cons, 4},
15276#endif
15277 { "extend", float_cons, 'x' },
15278 { "ldouble", float_cons, 'x' },
15279 { "packed", float_cons, 'p' },
15280 { 0, 0, 0 }
15281};
This page took 1.482081 seconds and 4 git commands to generate.