1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
7 Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
10 This file is part of GAS, the GNU Assembler.
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 #include "safe-ctype.h"
32 /* Need TARGET_CPU. */
41 #include "dwarf2dbg.h"
44 /* XXX Set this to 1 after the next binutils release */
45 #define WARN_DEPRECATED 0
47 /* The following bitmasks control CPU extensions: */
48 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
49 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
50 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
51 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
52 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
53 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
54 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
55 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
56 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
57 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
58 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
59 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
60 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
62 /* Co-processor space extensions. */
63 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
64 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
65 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
67 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
68 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
69 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
70 three more to cover cores prior to ARM6. Finally, there are cores which
71 implement further extensions in the co-processor space. */
72 #define ARM_ARCH_V1 ARM_EXT_V1
73 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
74 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
75 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
76 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
77 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
78 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
79 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
80 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
81 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
82 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
83 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
84 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
85 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
86 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
87 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
88 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
90 /* Processors with specific extensions in the co-processor space. */
91 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
92 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
94 /* Some useful combinations: */
95 #define ARM_ANY 0x0000ffff /* Any basic core. */
96 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
97 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
98 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
101 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
102 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
103 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
104 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
105 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
106 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
107 #define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
110 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
111 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
113 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
114 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
115 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
116 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
118 #define FPU_ARCH_MAVERICK FPU_MAVERICK
123 ARM_FLOAT_ABI_SOFTFP
,
127 /* Types of processor to assemble for. */
128 #define ARM_1 ARM_ARCH_V1
129 #define ARM_2 ARM_ARCH_V2
130 #define ARM_3 ARM_ARCH_V2S
131 #define ARM_250 ARM_ARCH_V2S
132 #define ARM_6 ARM_ARCH_V3
133 #define ARM_7 ARM_ARCH_V3
134 #define ARM_8 ARM_ARCH_V4
135 #define ARM_9 ARM_ARCH_V4T
136 #define ARM_STRONG ARM_ARCH_V4
137 #define ARM_CPU_MASK 0x0000000f /* XXX? */
140 #if defined __XSCALE__
141 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
143 #if defined __thumb__
144 #define CPU_DEFAULT (ARM_ARCH_V5T)
146 #define CPU_DEFAULT ARM_ANY
152 #define FPU_DEFAULT FPU_ARCH_FPA
157 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
159 /* Legacy a.out format. */
160 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
164 /* For backwards compatibility we default to the FPA. */
166 #define FPU_DEFAULT FPU_ARCH_FPA
169 #define streq(a, b) (strcmp (a, b) == 0)
170 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
172 static unsigned long cpu_variant
;
173 static int target_oabi
= 0;
175 /* Flags stored in private area of BFD structure. */
176 static int uses_apcs_26
= FALSE
;
177 static int atpcs
= FALSE
;
178 static int support_interwork
= FALSE
;
179 static int uses_apcs_float
= FALSE
;
180 static int pic_code
= FALSE
;
182 /* Variables that we set while parsing command-line options. Once all
183 options have been read we re-process these values to set the real
185 static int legacy_cpu
= -1;
186 static int legacy_fpu
= -1;
188 static int mcpu_cpu_opt
= -1;
189 static int mcpu_fpu_opt
= -1;
190 static int march_cpu_opt
= -1;
191 static int march_fpu_opt
= -1;
192 static int mfpu_opt
= -1;
193 static int mfloat_abi_opt
= -1;
195 static int meabi_flags
= EF_ARM_EABI_UNKNOWN
;
198 /* This array holds the chars that always start a comment. If the
199 pre-processor is disabled, these aren't very useful. */
200 const char comment_chars
[] = "@";
202 /* This array holds the chars that only start a comment at the beginning of
203 a line. If the line seems to have the form '# 123 filename'
204 .line and .file directives will appear in the pre-processed output. */
205 /* Note that input_file.c hand checks for '#' at the beginning of the
206 first line of the input file. This is because the compiler outputs
207 #NO_APP at the beginning of its output. */
208 /* Also note that comments like this one will always work. */
209 const char line_comment_chars
[] = "#";
211 const char line_separator_chars
[] = ";";
213 /* Chars that can be used to separate mant
214 from exp in floating point numbers. */
215 const char EXP_CHARS
[] = "eE";
217 /* Chars that mean this number is a floating point constant. */
221 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
223 /* Prefix characters that indicate the start of an immediate
225 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
228 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
229 symbolS
* GOT_symbol
;
232 /* Size of relocation record. */
233 const int md_reloc_size
= 8;
235 /* 0: assemble for ARM,
236 1: assemble for Thumb,
237 2: assemble for Thumb even though target CPU does not support thumb
239 static int thumb_mode
= 0;
241 typedef struct arm_fix
249 unsigned long instruction
;
253 bfd_reloc_code_real_type type
;
270 struct asm_shift_properties
272 enum asm_shift_index index
;
273 unsigned long bit_field
;
274 unsigned int allows_0
: 1;
275 unsigned int allows_32
: 1;
278 static const struct asm_shift_properties shift_properties
[] =
280 { SHIFT_LSL
, 0, 1, 0},
281 { SHIFT_LSR
, 0x20, 0, 1},
282 { SHIFT_ASR
, 0x40, 0, 1},
283 { SHIFT_ROR
, 0x60, 0, 0},
284 { SHIFT_RRX
, 0x60, 0, 0}
287 struct asm_shift_name
290 const struct asm_shift_properties
* properties
;
293 static const struct asm_shift_name shift_names
[] =
295 { "asl", shift_properties
+ SHIFT_LSL
},
296 { "lsl", shift_properties
+ SHIFT_LSL
},
297 { "lsr", shift_properties
+ SHIFT_LSR
},
298 { "asr", shift_properties
+ SHIFT_ASR
},
299 { "ror", shift_properties
+ SHIFT_ROR
},
300 { "rrx", shift_properties
+ SHIFT_RRX
},
301 { "ASL", shift_properties
+ SHIFT_LSL
},
302 { "LSL", shift_properties
+ SHIFT_LSL
},
303 { "LSR", shift_properties
+ SHIFT_LSR
},
304 { "ASR", shift_properties
+ SHIFT_ASR
},
305 { "ROR", shift_properties
+ SHIFT_ROR
},
306 { "RRX", shift_properties
+ SHIFT_RRX
}
309 /* Any kind of shift is accepted. */
310 #define NO_SHIFT_RESTRICT 1
311 /* The shift operand must be an immediate value, not a register. */
312 #define SHIFT_IMMEDIATE 0
313 /* The shift must be LSL or ASR and the operand must be an immediate. */
314 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
315 /* The shift must be ASR and the operand must be an immediate. */
316 #define SHIFT_ASR_IMMEDIATE 3
317 /* The shift must be LSL and the operand must be an immediate. */
318 #define SHIFT_LSL_IMMEDIATE 4
320 #define NUM_FLOAT_VALS 8
322 const char * fp_const
[] =
324 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
327 /* Number of littlenums required to hold an extended precision number. */
328 #define MAX_LITTLENUMS 6
330 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
335 /* Whether a Co-processor load/store operation accepts write-back forms. */
344 #define CP_T_X 0x00008000
345 #define CP_T_Y 0x00400000
346 #define CP_T_Pre 0x01000000
347 #define CP_T_UD 0x00800000
348 #define CP_T_WB 0x00200000
350 #define CONDS_BIT 0x00100000
351 #define LOAD_BIT 0x00100000
353 #define DOUBLE_LOAD_FLAG 0x00000001
357 const char * template;
361 #define COND_ALWAYS 0xe0000000
362 #define COND_MASK 0xf0000000
364 static const struct asm_cond conds
[] =
368 {"cs", 0x20000000}, {"hs", 0x20000000},
369 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
386 const char *template;
391 /* The bit that distinguishes CPSR and SPSR. */
392 #define SPSR_BIT (1 << 22)
394 /* How many bits to shift the PSR_xxx bits up by. */
397 #define PSR_c (1 << 0)
398 #define PSR_x (1 << 1)
399 #define PSR_s (1 << 2)
400 #define PSR_f (1 << 3)
402 static const struct asm_psr psrs
[] =
404 {"CPSR", TRUE
, PSR_c
| PSR_f
},
405 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
406 {"SPSR", FALSE
, PSR_c
| PSR_f
},
407 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
408 {"CPSR_flg", TRUE
, PSR_f
},
409 {"CPSR_f", TRUE
, PSR_f
},
410 {"SPSR_flg", FALSE
, PSR_f
},
411 {"SPSR_f", FALSE
, PSR_f
},
412 {"CPSR_c", TRUE
, PSR_c
},
413 {"CPSR_ctl", TRUE
, PSR_c
},
414 {"SPSR_c", FALSE
, PSR_c
},
415 {"SPSR_ctl", FALSE
, PSR_c
},
416 {"CPSR_x", TRUE
, PSR_x
},
417 {"CPSR_s", TRUE
, PSR_s
},
418 {"SPSR_x", FALSE
, PSR_x
},
419 {"SPSR_s", FALSE
, PSR_s
},
420 /* Combinations of flags. */
421 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
422 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
423 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
424 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
425 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
426 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
427 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
428 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
429 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
430 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
431 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
432 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
433 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
434 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
435 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
436 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
437 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
438 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
439 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
440 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
441 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
442 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
443 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
444 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
445 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
446 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
447 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
448 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
449 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
450 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
451 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
452 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
453 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
454 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
455 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
456 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
457 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
458 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
459 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
460 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
461 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
462 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
463 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
464 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
465 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
466 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
467 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
468 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
469 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
470 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
471 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
472 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
473 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
474 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
475 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
476 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
477 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
478 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
479 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
480 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
481 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
482 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
483 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
484 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
485 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
486 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
487 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
488 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
489 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
490 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
491 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
492 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
493 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
494 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
495 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
496 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
497 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
498 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
499 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
500 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
501 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
502 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
503 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
504 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
505 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
506 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
507 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
508 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
509 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
510 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
511 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
512 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
513 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
514 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
515 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
516 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
517 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
518 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
519 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
520 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
521 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
522 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
523 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
524 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
525 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
526 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
527 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
528 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
529 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
530 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
531 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
532 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
533 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
534 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
535 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
536 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
537 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
538 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
539 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
540 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
547 IWMMXT_REG_WR_OR_WC
= 2,
551 enum iwmmxt_insn_type
574 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
579 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
584 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
587 /* VFP system registers. */
594 static const struct vfp_reg vfp_regs
[] =
596 {"fpsid", 0x00000000},
597 {"FPSID", 0x00000000},
598 {"fpscr", 0x00010000},
599 {"FPSCR", 0x00010000},
600 {"fpexc", 0x00080000},
601 {"FPEXC", 0x00080000}
604 /* Structure for a hash table entry for a register. */
612 /* Some well known registers that we refer to directly elsewhere. */
617 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
618 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
619 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
621 /* These are the standard names. Users can add aliases with .req.
622 and delete them with .unreq. */
624 /* Integer Register Numbers. */
625 static const struct reg_entry rn_table
[] =
627 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
628 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
629 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
630 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
631 /* ATPCS Synonyms. */
632 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
633 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
634 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
635 /* Well-known aliases. */
636 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
637 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
641 #define WR_PREFIX 0x200
642 #define WC_PREFIX 0x400
644 static const struct reg_entry iwmmxt_table
[] =
646 /* Intel Wireless MMX technology register names. */
647 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
648 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
649 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
650 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
651 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
652 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
653 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
654 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
655 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
656 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
657 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
658 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
660 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
661 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
662 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
663 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
664 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
665 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
666 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
667 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
668 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
669 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
670 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
671 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
675 /* Co-processor Numbers. */
676 static const struct reg_entry cp_table
[] =
678 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
679 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
680 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
681 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
685 /* Co-processor Register Numbers. */
686 static const struct reg_entry cn_table
[] =
688 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
689 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
690 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
691 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
692 /* Not really valid, but kept for back-wards compatibility. */
693 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
694 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
695 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
696 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
701 static const struct reg_entry fn_table
[] =
703 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
704 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
708 /* VFP SP Registers. */
709 static const struct reg_entry sn_table
[] =
711 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
712 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
713 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
714 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
715 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
716 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
717 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
718 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
722 /* VFP DP Registers. */
723 static const struct reg_entry dn_table
[] =
725 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
726 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
727 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
728 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
732 /* Maverick DSP coprocessor registers. */
733 static const struct reg_entry mav_mvf_table
[] =
735 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
736 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
737 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
738 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
742 static const struct reg_entry mav_mvd_table
[] =
744 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
745 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
746 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
747 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
751 static const struct reg_entry mav_mvfx_table
[] =
753 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
754 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
755 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
756 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
760 static const struct reg_entry mav_mvdx_table
[] =
762 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
763 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
764 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
765 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
769 static const struct reg_entry mav_mvax_table
[] =
771 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
775 static const struct reg_entry mav_dspsc_table
[] =
783 const struct reg_entry
*names
;
785 struct hash_control
*htab
;
786 const char *expected
;
789 struct reg_map all_reg_maps
[] =
791 {rn_table
, 15, NULL
, N_("ARM register expected")},
792 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
793 {cn_table
, 15, NULL
, N_("co-processor register expected")},
794 {fn_table
, 7, NULL
, N_("FPA register expected")},
795 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
796 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
797 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
798 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
799 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
800 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
801 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
802 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
803 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
806 /* Enumeration matching entries in table above. */
810 #define REG_TYPE_FIRST REG_TYPE_RN
822 REG_TYPE_IWMMXT
= 12,
827 /* Functions called by parser. */
828 /* ARM instructions. */
829 static void do_arit
PARAMS ((char *));
830 static void do_cmp
PARAMS ((char *));
831 static void do_mov
PARAMS ((char *));
832 static void do_ldst
PARAMS ((char *));
833 static void do_ldstt
PARAMS ((char *));
834 static void do_ldmstm
PARAMS ((char *));
835 static void do_branch
PARAMS ((char *));
836 static void do_swi
PARAMS ((char *));
838 /* Pseudo Op codes. */
839 static void do_adr
PARAMS ((char *));
840 static void do_adrl
PARAMS ((char *));
841 static void do_empty
PARAMS ((char *));
844 static void do_mul
PARAMS ((char *));
845 static void do_mla
PARAMS ((char *));
848 static void do_swap
PARAMS ((char *));
851 static void do_msr
PARAMS ((char *));
852 static void do_mrs
PARAMS ((char *));
855 static void do_mull
PARAMS ((char *));
858 static void do_ldstv4
PARAMS ((char *));
861 static void do_bx
PARAMS ((char *));
864 static void do_blx
PARAMS ((char *));
865 static void do_bkpt
PARAMS ((char *));
866 static void do_clz
PARAMS ((char *));
867 static void do_lstc2
PARAMS ((char *));
868 static void do_cdp2
PARAMS ((char *));
869 static void do_co_reg2
PARAMS ((char *));
872 static void do_smla
PARAMS ((char *));
873 static void do_smlal
PARAMS ((char *));
874 static void do_smul
PARAMS ((char *));
875 static void do_qadd
PARAMS ((char *));
878 static void do_pld
PARAMS ((char *));
879 static void do_ldrd
PARAMS ((char *));
880 static void do_co_reg2c
PARAMS ((char *));
883 static void do_bxj
PARAMS ((char *));
886 static void do_cps
PARAMS ((char *));
887 static void do_cpsi
PARAMS ((char *));
888 static void do_ldrex
PARAMS ((char *));
889 static void do_pkhbt
PARAMS ((char *));
890 static void do_pkhtb
PARAMS ((char *));
891 static void do_qadd16
PARAMS ((char *));
892 static void do_rev
PARAMS ((char *));
893 static void do_rfe
PARAMS ((char *));
894 static void do_sxtah
PARAMS ((char *));
895 static void do_sxth
PARAMS ((char *));
896 static void do_setend
PARAMS ((char *));
897 static void do_smlad
PARAMS ((char *));
898 static void do_smlald
PARAMS ((char *));
899 static void do_smmul
PARAMS ((char *));
900 static void do_ssat
PARAMS ((char *));
901 static void do_usat
PARAMS ((char *));
902 static void do_srs
PARAMS ((char *));
903 static void do_ssat16
PARAMS ((char *));
904 static void do_usat16
PARAMS ((char *));
905 static void do_strex
PARAMS ((char *));
906 static void do_umaal
PARAMS ((char *));
908 static void do_cps_mode
PARAMS ((char **));
909 static void do_cps_flags
PARAMS ((char **, int));
910 static int do_endian_specifier
PARAMS ((char *));
911 static void do_pkh_core
PARAMS ((char *, int));
912 static void do_sat
PARAMS ((char **, int));
913 static void do_sat16
PARAMS ((char **, int));
915 /* Coprocessor Instructions. */
916 static void do_cdp
PARAMS ((char *));
917 static void do_lstc
PARAMS ((char *));
918 static void do_co_reg
PARAMS ((char *));
920 /* FPA instructions. */
921 static void do_fpa_ctrl
PARAMS ((char *));
922 static void do_fpa_ldst
PARAMS ((char *));
923 static void do_fpa_ldmstm
PARAMS ((char *));
924 static void do_fpa_dyadic
PARAMS ((char *));
925 static void do_fpa_monadic
PARAMS ((char *));
926 static void do_fpa_cmp
PARAMS ((char *));
927 static void do_fpa_from_reg
PARAMS ((char *));
928 static void do_fpa_to_reg
PARAMS ((char *));
930 /* VFP instructions. */
931 static void do_vfp_sp_monadic
PARAMS ((char *));
932 static void do_vfp_dp_monadic
PARAMS ((char *));
933 static void do_vfp_sp_dyadic
PARAMS ((char *));
934 static void do_vfp_dp_dyadic
PARAMS ((char *));
935 static void do_vfp_reg_from_sp
PARAMS ((char *));
936 static void do_vfp_sp_from_reg
PARAMS ((char *));
937 static void do_vfp_reg2_from_sp2
PARAMS ((char *));
938 static void do_vfp_sp2_from_reg2
PARAMS ((char *));
939 static void do_vfp_reg_from_dp
PARAMS ((char *));
940 static void do_vfp_reg2_from_dp
PARAMS ((char *));
941 static void do_vfp_dp_from_reg
PARAMS ((char *));
942 static void do_vfp_dp_from_reg2
PARAMS ((char *));
943 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
944 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
945 static void do_vfp_sp_ldst
PARAMS ((char *));
946 static void do_vfp_dp_ldst
PARAMS ((char *));
947 static void do_vfp_sp_ldstmia
PARAMS ((char *));
948 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
949 static void do_vfp_dp_ldstmia
PARAMS ((char *));
950 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
951 static void do_vfp_xp_ldstmia
PARAMS ((char *));
952 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
953 static void do_vfp_sp_compare_z
PARAMS ((char *));
954 static void do_vfp_dp_compare_z
PARAMS ((char *));
955 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
956 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
959 static void do_xsc_mia
PARAMS ((char *));
960 static void do_xsc_mar
PARAMS ((char *));
961 static void do_xsc_mra
PARAMS ((char *));
964 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
966 static void do_mav_binops_1a
PARAMS ((char *));
967 static void do_mav_binops_1b
PARAMS ((char *));
968 static void do_mav_binops_1c
PARAMS ((char *));
969 static void do_mav_binops_1d
PARAMS ((char *));
970 static void do_mav_binops_1e
PARAMS ((char *));
971 static void do_mav_binops_1f
PARAMS ((char *));
972 static void do_mav_binops_1g
PARAMS ((char *));
973 static void do_mav_binops_1h
PARAMS ((char *));
974 static void do_mav_binops_1i
PARAMS ((char *));
975 static void do_mav_binops_1j
PARAMS ((char *));
976 static void do_mav_binops_1k
PARAMS ((char *));
977 static void do_mav_binops_1l
PARAMS ((char *));
978 static void do_mav_binops_1m
PARAMS ((char *));
979 static void do_mav_binops_1n
PARAMS ((char *));
980 static void do_mav_binops_1o
PARAMS ((char *));
981 static void do_mav_binops_2a
PARAMS ((char *));
982 static void do_mav_binops_2b
PARAMS ((char *));
983 static void do_mav_binops_2c
PARAMS ((char *));
984 static void do_mav_binops_3a
PARAMS ((char *));
985 static void do_mav_binops_3b
PARAMS ((char *));
986 static void do_mav_binops_3c
PARAMS ((char *));
987 static void do_mav_binops_3d
PARAMS ((char *));
988 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
991 static void do_mav_triple_4a
PARAMS ((char *));
992 static void do_mav_triple_4b
PARAMS ((char *));
993 static void do_mav_triple_5a
PARAMS ((char *));
994 static void do_mav_triple_5b
PARAMS ((char *));
995 static void do_mav_triple_5c
PARAMS ((char *));
996 static void do_mav_triple_5d
PARAMS ((char *));
997 static void do_mav_triple_5e
PARAMS ((char *));
998 static void do_mav_triple_5f
PARAMS ((char *));
999 static void do_mav_triple_5g
PARAMS ((char *));
1000 static void do_mav_triple_5h
PARAMS ((char *));
1001 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
1004 enum arm_reg_type
));
1005 static void do_mav_quad_6a
PARAMS ((char *));
1006 static void do_mav_quad_6b
PARAMS ((char *));
1007 static void do_mav_dspsc_1
PARAMS ((char *));
1008 static void do_mav_dspsc_2
PARAMS ((char *));
1009 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
1010 enum arm_reg_type
));
1011 static void do_mav_shift_1
PARAMS ((char *));
1012 static void do_mav_shift_2
PARAMS ((char *));
1013 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
1014 static void do_mav_ldst_1
PARAMS ((char *));
1015 static void do_mav_ldst_2
PARAMS ((char *));
1016 static void do_mav_ldst_3
PARAMS ((char *));
1017 static void do_mav_ldst_4
PARAMS ((char *));
1019 static int mav_reg_required_here
PARAMS ((char **, int,
1020 enum arm_reg_type
));
1021 static int mav_parse_offset
PARAMS ((char **, int *));
1023 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
1025 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
1026 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
1027 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
1028 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
1030 static int add_to_lit_pool
PARAMS ((void));
1031 static unsigned validate_immediate
PARAMS ((unsigned));
1032 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
1034 static int validate_offset_imm
PARAMS ((unsigned int, int));
1035 static void opcode_select
PARAMS ((int));
1036 static void end_of_line
PARAMS ((char *));
1037 static int reg_required_here
PARAMS ((char **, int));
1038 static int psr_required_here
PARAMS ((char **));
1039 static int co_proc_number
PARAMS ((char **));
1040 static int cp_opc_expr
PARAMS ((char **, int, int));
1041 static int cp_reg_required_here
PARAMS ((char **, int));
1042 static int fp_reg_required_here
PARAMS ((char **, int));
1043 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
1044 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
1045 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1046 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1047 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
1048 static long vfp_dp_reg_list
PARAMS ((char **));
1049 static int vfp_psr_required_here
PARAMS ((char **str
));
1050 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
1051 static int cp_address_offset
PARAMS ((char **));
1052 static int cp_address_required_here
PARAMS ((char **, int));
1053 static int my_get_float_expression
PARAMS ((char **));
1054 static int skip_past_comma
PARAMS ((char **));
1055 static int walk_no_bignums
PARAMS ((symbolS
*));
1056 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1057 static int data_op2
PARAMS ((char **));
1058 static int fp_op2
PARAMS ((char **));
1059 static long reg_list
PARAMS ((char **));
1060 static void thumb_load_store
PARAMS ((char *, int, int));
1061 static int decode_shift
PARAMS ((char **, int));
1062 static int ldst_extend
PARAMS ((char **));
1063 static int ldst_extend_v4
PARAMS ((char **));
1064 static void thumb_add_sub
PARAMS ((char *, int));
1065 static void insert_reg
PARAMS ((const struct reg_entry
*,
1066 struct hash_control
*));
1067 static void thumb_shift
PARAMS ((char *, int));
1068 static void thumb_mov_compare
PARAMS ((char *, int));
1069 static void build_arm_ops_hsh
PARAMS ((void));
1070 static void set_constant_flonums
PARAMS ((void));
1071 static valueT md_chars_to_number
PARAMS ((char *, int));
1072 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1073 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1074 static int create_register_alias
PARAMS ((char *, char *));
1075 static void output_inst
PARAMS ((const char *));
1076 static int accum0_required_here
PARAMS ((char **));
1077 static int ld_mode_required_here
PARAMS ((char **));
1078 static void do_branch25
PARAMS ((char *));
1079 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1081 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1084 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1085 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1086 static void do_iwmmxt_tandc
PARAMS ((char *));
1087 static void do_iwmmxt_tbcst
PARAMS ((char *));
1088 static void do_iwmmxt_textrc
PARAMS ((char *));
1089 static void do_iwmmxt_textrm
PARAMS ((char *));
1090 static void do_iwmmxt_tinsr
PARAMS ((char *));
1091 static void do_iwmmxt_tmcr
PARAMS ((char *));
1092 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1093 static void do_iwmmxt_tmia
PARAMS ((char *));
1094 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1095 static void do_iwmmxt_tmrc
PARAMS ((char *));
1096 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1097 static void do_iwmmxt_torc
PARAMS ((char *));
1098 static void do_iwmmxt_waligni
PARAMS ((char *));
1099 static void do_iwmmxt_wmov
PARAMS ((char *));
1100 static void do_iwmmxt_word_addr
PARAMS ((char *));
1101 static void do_iwmmxt_wrwr
PARAMS ((char *));
1102 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1103 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1104 static void do_iwmmxt_wshufh
PARAMS ((char *));
1105 static void do_iwmmxt_wzero
PARAMS ((char *));
1106 static int cp_byte_address_offset
PARAMS ((char **));
1107 static int cp_byte_address_required_here
PARAMS ((char **));
1109 /* ARM instructions take 4bytes in the object file, Thumb instructions
1113 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1114 #define MAV_MODE1 0x100c
1116 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1117 #define MAV_MODE2 0x0c10
1119 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1120 #define MAV_MODE3 0x100c
1122 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1123 #define MAV_MODE4 0x0c0010
1125 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1126 #define MAV_MODE5 0x00100c
1128 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1129 #define MAV_MODE6 0x00100c05
1133 /* Basic string to match. */
1134 const char * template;
1136 /* Basic instruction code. */
1137 unsigned long value
;
1139 /* Offset into the template where the condition code (if any) will be.
1140 If zero, then the instruction is never conditional. */
1141 unsigned cond_offset
;
1143 /* Which architecture variant provides this instruction. */
1144 unsigned long variant
;
1146 /* Function to call to parse args. */
1147 void (* parms
) PARAMS ((char *));
1150 static const struct asm_opcode insns
[] =
1152 /* Core ARM Instructions. */
1153 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1154 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1155 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1156 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1157 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1158 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1159 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1160 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1161 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1162 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1163 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1164 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1165 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1166 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1167 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1168 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1169 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1170 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1171 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1172 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1174 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1175 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1176 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1177 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1178 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1179 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1180 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1181 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1182 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1183 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1184 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1185 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1187 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1188 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1189 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1190 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1192 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1193 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1194 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1195 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1196 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1197 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1198 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1199 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1201 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1202 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1203 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1204 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1205 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1206 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1207 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1208 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1210 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1211 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1212 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1213 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1214 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1215 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1216 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1217 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1219 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1221 /* XXX This is the wrong place to do this. Think multi-arch. */
1222 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1223 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1225 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1226 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1230 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1231 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1232 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1234 /* ARM 2 multiplies. */
1235 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1236 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1237 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1238 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1240 /* Generic coprocessor instructions. */
1241 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1242 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1243 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1244 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1245 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1246 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1247 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1249 /* ARM 3 - swp instructions. */
1250 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1251 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1253 /* ARM 6 Status register instructions. */
1254 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1255 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1256 /* ScottB: our code uses 0xe128f000 for msr.
1257 NickC: but this is wrong because the bits 16 through 19 are
1258 handled by the PSR_xxx defines above. */
1260 /* ARM 7M long multiplies. */
1261 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1262 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1263 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1264 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1265 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1266 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1267 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1268 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1270 /* ARM Architecture 4. */
1271 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1272 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1273 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1274 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1276 /* ARM Architecture 4T. */
1277 /* Note: bx (and blx) are required on V5, even if the processor does
1278 not support Thumb. */
1279 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1281 /* ARM Architecture 5T. */
1282 /* Note: blx has 2 variants, so the .value is set dynamically.
1283 Only one of the variants has conditional execution. */
1284 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1285 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1286 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1287 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1288 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1289 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1290 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1291 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1292 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1293 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1295 /* ARM Architecture 5TExP. */
1296 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1297 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1298 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1299 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1301 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1302 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1304 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1305 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1306 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1307 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1309 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1310 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1311 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1312 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1314 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1315 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1317 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1318 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1319 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1320 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1322 /* ARM Architecture 5TE. */
1323 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1324 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1325 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1327 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1328 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1330 /* ARM Architecture 5TEJ. */
1331 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1334 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
1335 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
1336 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
1337 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
1338 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
1339 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
1340 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
1341 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
1342 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
1343 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
1344 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
1345 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
1346 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
1347 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
1348 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
1349 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
1350 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
1351 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
1352 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
1353 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
1354 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
1355 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
1356 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
1357 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
1358 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
1359 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
1360 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
1361 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
1362 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
1363 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
1364 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
1365 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
1366 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
1367 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
1368 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
1369 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
1370 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
1371 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
1372 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
1373 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
1374 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
1375 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
1376 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
1377 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
1378 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
1379 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
1380 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
1381 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1382 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1383 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1384 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1385 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1386 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1387 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1388 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1389 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
1390 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
1391 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
1392 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
1393 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
1394 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
1395 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
1396 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
1397 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
1398 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
1399 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
1400 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
1401 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
1402 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
1403 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
1404 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
1405 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
1406 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
1407 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
1408 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
1409 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
1410 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
1411 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
1412 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
1413 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
1414 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
1415 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
1416 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
1417 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
1418 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
1419 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
1420 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
1421 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
1422 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
1423 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
1424 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
1425 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
1426 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
1427 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
1428 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
1429 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
1430 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
1431 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
1432 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
1434 /* Core FPA instruction set (V1). */
1435 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1436 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1437 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1438 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1440 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1441 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1442 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1443 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1445 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1446 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1447 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1448 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1450 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1499 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1502 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1503 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1504 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1505 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1506 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1507 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1508 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1509 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1510 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1511 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1512 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1513 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1515 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1516 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1517 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1518 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1519 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1520 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1521 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1522 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1523 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1524 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1525 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1526 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1528 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1529 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1530 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1531 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1532 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1533 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1534 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1535 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1536 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1537 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1538 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1539 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1541 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1542 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1543 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1544 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1545 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1546 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1547 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1548 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1549 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1550 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1551 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1552 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1554 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1555 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1556 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1557 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1558 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1559 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1560 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1561 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1562 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1563 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1564 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1565 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1567 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1568 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1569 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1570 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1571 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1572 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1573 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1574 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1575 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1576 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1577 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1578 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1580 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1581 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1582 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1583 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1584 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1585 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1586 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1587 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1588 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1589 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1590 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1591 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1593 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1594 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1595 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1596 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1597 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1598 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1599 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1600 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1601 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1602 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1603 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1604 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1606 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1607 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1608 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1609 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1610 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1611 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1612 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1613 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1614 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1615 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1616 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1617 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1619 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1620 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1621 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1622 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1623 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1624 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1625 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1626 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1627 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1628 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1629 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1630 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1632 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1633 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1634 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1635 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1636 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1637 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1638 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1639 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1640 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1641 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1642 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1643 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1645 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1646 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1647 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1648 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1649 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1650 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1651 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1652 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1653 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1654 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1655 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1656 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1658 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1668 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1671 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1672 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1673 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1674 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1675 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1676 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1677 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1678 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1679 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1680 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1681 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1682 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1684 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1685 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1686 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1687 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1688 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1689 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1690 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1691 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1692 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1693 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1694 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1695 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1697 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1698 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1699 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1700 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1701 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1702 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1703 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1704 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1705 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1706 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1707 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1708 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1710 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1711 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1712 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1713 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1714 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1715 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1716 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1717 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1718 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1719 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1720 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1721 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1723 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1724 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1725 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1726 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1727 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1728 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1729 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1730 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1731 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1732 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1733 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1734 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1736 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1737 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1738 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1739 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1740 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1741 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1742 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1743 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1744 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1745 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1746 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1747 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1749 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1750 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1751 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1752 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1753 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1754 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1755 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1756 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1757 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1758 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1759 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1760 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1762 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1763 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1764 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1765 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1766 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1767 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1768 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1769 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1770 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1771 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1772 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1773 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1775 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1776 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1777 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1778 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1779 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1780 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1781 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1782 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1783 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1784 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1785 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1786 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1788 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1789 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1790 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1791 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1792 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1793 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1794 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1795 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1796 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1797 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1798 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1799 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1801 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1802 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1803 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1804 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1805 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1806 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1807 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1808 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1809 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1810 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1811 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1812 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1814 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1815 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1816 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1817 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1818 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1819 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1820 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1821 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1822 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1823 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1824 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1825 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1827 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1828 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1829 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1830 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1831 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1832 not be an optional suffix, but part of the instruction. To be
1833 compatible, we accept either. */
1834 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1835 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1837 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1838 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1839 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1840 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1841 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1842 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1843 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1844 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1845 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1846 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1847 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1848 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1850 /* The implementation of the FIX instruction is broken on some
1851 assemblers, in that it accepts a precision specifier as well as a
1852 rounding specifier, despite the fact that this is meaningless.
1853 To be more compatible, we accept it as well, though of course it
1854 does not set any bits. */
1855 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1856 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1857 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1858 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1859 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1860 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1861 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1862 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1863 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1864 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1865 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1866 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1867 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1869 /* Instructions that were new with the real FPA, call them V2. */
1870 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1871 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1872 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1873 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1874 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1875 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1877 /* VFP V1xD (single precision). */
1878 /* Moves and type conversions. */
1879 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1880 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1881 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1882 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1883 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1884 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1885 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1886 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1887 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1888 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1889 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1890 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1892 /* Memory operations. */
1893 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1894 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1895 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1896 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1897 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1898 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1899 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1900 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1901 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1902 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1903 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1904 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1905 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1906 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1907 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1908 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1909 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1910 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1912 /* Monadic operations. */
1913 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1914 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1915 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1917 /* Dyadic operations. */
1918 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1919 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1920 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1921 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1922 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1923 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1924 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1925 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1926 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1929 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1930 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1931 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1932 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1934 /* VFP V1 (Double precision). */
1935 /* Moves and type conversions. */
1936 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1937 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1938 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1939 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1940 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1941 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1942 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1943 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1944 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1945 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1946 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1947 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1948 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1950 /* Memory operations. */
1951 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1952 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1953 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1954 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1955 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1956 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1957 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1958 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1959 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1960 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1962 /* Monadic operations. */
1963 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1964 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1965 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1967 /* Dyadic operations. */
1968 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1969 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1970 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1971 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1972 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1973 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1974 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1975 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1976 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1979 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1980 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1981 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1982 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1985 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
1986 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
1987 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1988 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1990 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1991 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1992 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1993 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1994 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1995 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1996 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1997 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1998 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
2000 /* Intel Wireless MMX technology instructions. */
2001 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
2002 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
2003 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
2004 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2005 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2006 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2007 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2008 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2009 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2010 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2011 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2012 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2013 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2014 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2015 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2016 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2017 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2018 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2019 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
2020 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
2021 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2022 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2023 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2024 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2025 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2026 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2027 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2028 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2029 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2030 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
2031 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
2032 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2033 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2034 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2035 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2036 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2037 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2038 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2039 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2040 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2041 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2042 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2043 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2044 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2045 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2046 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2047 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
2048 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2049 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2050 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2051 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2052 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2053 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2054 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2055 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2056 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2057 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2058 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2059 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2060 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2061 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2062 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2063 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2064 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2065 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2066 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2067 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2068 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2069 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2070 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2071 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2072 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2073 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2074 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2075 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2076 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2077 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2078 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2079 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2080 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2081 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2082 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2083 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2084 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2085 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2086 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2087 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2088 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2089 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
2090 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2091 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2092 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2093 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2094 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2095 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2096 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2097 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2098 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2099 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2100 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2101 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2102 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2103 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2104 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2105 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2106 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2107 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2108 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2109 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2110 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2111 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
2112 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2113 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2114 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2115 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2116 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2117 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2118 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2119 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2120 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2121 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2122 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2123 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2124 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2125 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2126 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2127 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2128 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2129 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2130 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2131 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2132 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2133 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2134 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2135 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2136 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2137 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2138 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2139 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2140 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2141 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2142 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2143 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2144 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2145 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2146 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2147 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2148 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2149 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2150 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2151 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2152 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2153 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2154 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2155 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2156 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2157 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2158 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2159 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2160 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2161 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2162 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2164 /* Cirrus Maverick instructions. */
2165 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2166 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2167 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2168 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2169 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2170 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2171 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2172 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2173 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2174 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2175 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2176 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2177 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2178 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2179 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2180 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2181 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2182 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2183 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2184 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2185 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2186 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2187 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2188 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2189 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2190 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2191 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2192 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2193 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2194 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2195 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2196 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2197 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2198 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2199 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2200 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2201 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2202 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2203 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2204 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2205 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2206 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2207 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2208 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2209 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2210 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2211 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2212 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2213 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2214 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2215 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2216 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2217 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2218 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2219 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2220 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2221 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2222 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2223 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2224 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2225 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2226 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2227 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2228 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2229 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2230 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2231 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2232 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2233 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2234 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2235 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2236 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2237 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2238 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2239 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2240 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2243 /* Defines for various bits that we will want to toggle. */
2244 #define INST_IMMEDIATE 0x02000000
2245 #define OFFSET_REG 0x02000000
2246 #define HWOFFSET_IMM 0x00400000
2247 #define SHIFT_BY_REG 0x00000010
2248 #define PRE_INDEX 0x01000000
2249 #define INDEX_UP 0x00800000
2250 #define WRITE_BACK 0x00200000
2251 #define LDM_TYPE_2_OR_3 0x00400000
2253 #define LITERAL_MASK 0xf000f000
2254 #define OPCODE_MASK 0xfe1fffff
2255 #define V4_STR_BIT 0x00000020
2257 #define DATA_OP_SHIFT 21
2259 /* Codes to distinguish the arithmetic instructions. */
2260 #define OPCODE_AND 0
2261 #define OPCODE_EOR 1
2262 #define OPCODE_SUB 2
2263 #define OPCODE_RSB 3
2264 #define OPCODE_ADD 4
2265 #define OPCODE_ADC 5
2266 #define OPCODE_SBC 6
2267 #define OPCODE_RSC 7
2268 #define OPCODE_TST 8
2269 #define OPCODE_TEQ 9
2270 #define OPCODE_CMP 10
2271 #define OPCODE_CMN 11
2272 #define OPCODE_ORR 12
2273 #define OPCODE_MOV 13
2274 #define OPCODE_BIC 14
2275 #define OPCODE_MVN 15
2277 /* Thumb v1 (ARMv4T). */
2278 static void do_t_nop
PARAMS ((char *));
2279 static void do_t_arit
PARAMS ((char *));
2280 static void do_t_add
PARAMS ((char *));
2281 static void do_t_asr
PARAMS ((char *));
2282 static void do_t_branch9
PARAMS ((char *));
2283 static void do_t_branch12
PARAMS ((char *));
2284 static void do_t_branch23
PARAMS ((char *));
2285 static void do_t_bx
PARAMS ((char *));
2286 static void do_t_compare
PARAMS ((char *));
2287 static void do_t_ldmstm
PARAMS ((char *));
2288 static void do_t_ldr
PARAMS ((char *));
2289 static void do_t_ldrb
PARAMS ((char *));
2290 static void do_t_ldrh
PARAMS ((char *));
2291 static void do_t_lds
PARAMS ((char *));
2292 static void do_t_lsl
PARAMS ((char *));
2293 static void do_t_lsr
PARAMS ((char *));
2294 static void do_t_mov
PARAMS ((char *));
2295 static void do_t_push_pop
PARAMS ((char *));
2296 static void do_t_str
PARAMS ((char *));
2297 static void do_t_strb
PARAMS ((char *));
2298 static void do_t_strh
PARAMS ((char *));
2299 static void do_t_sub
PARAMS ((char *));
2300 static void do_t_swi
PARAMS ((char *));
2301 static void do_t_adr
PARAMS ((char *));
2303 /* Thumb v2 (ARMv5T). */
2304 static void do_t_blx
PARAMS ((char *));
2305 static void do_t_bkpt
PARAMS ((char *));
2308 static void do_t_cps
PARAMS ((char *));
2309 static void do_t_cpy
PARAMS ((char *));
2310 static void do_t_setend
PARAMS ((char *));;
2312 #define T_OPCODE_MUL 0x4340
2313 #define T_OPCODE_TST 0x4200
2314 #define T_OPCODE_CMN 0x42c0
2315 #define T_OPCODE_NEG 0x4240
2316 #define T_OPCODE_MVN 0x43c0
2318 #define T_OPCODE_ADD_R3 0x1800
2319 #define T_OPCODE_SUB_R3 0x1a00
2320 #define T_OPCODE_ADD_HI 0x4400
2321 #define T_OPCODE_ADD_ST 0xb000
2322 #define T_OPCODE_SUB_ST 0xb080
2323 #define T_OPCODE_ADD_SP 0xa800
2324 #define T_OPCODE_ADD_PC 0xa000
2325 #define T_OPCODE_ADD_I8 0x3000
2326 #define T_OPCODE_SUB_I8 0x3800
2327 #define T_OPCODE_ADD_I3 0x1c00
2328 #define T_OPCODE_SUB_I3 0x1e00
2330 #define T_OPCODE_ASR_R 0x4100
2331 #define T_OPCODE_LSL_R 0x4080
2332 #define T_OPCODE_LSR_R 0x40c0
2333 #define T_OPCODE_ASR_I 0x1000
2334 #define T_OPCODE_LSL_I 0x0000
2335 #define T_OPCODE_LSR_I 0x0800
2337 #define T_OPCODE_MOV_I8 0x2000
2338 #define T_OPCODE_CMP_I8 0x2800
2339 #define T_OPCODE_CMP_LR 0x4280
2340 #define T_OPCODE_MOV_HR 0x4600
2341 #define T_OPCODE_CMP_HR 0x4500
2343 #define T_OPCODE_LDR_PC 0x4800
2344 #define T_OPCODE_LDR_SP 0x9800
2345 #define T_OPCODE_STR_SP 0x9000
2346 #define T_OPCODE_LDR_IW 0x6800
2347 #define T_OPCODE_STR_IW 0x6000
2348 #define T_OPCODE_LDR_IH 0x8800
2349 #define T_OPCODE_STR_IH 0x8000
2350 #define T_OPCODE_LDR_IB 0x7800
2351 #define T_OPCODE_STR_IB 0x7000
2352 #define T_OPCODE_LDR_RW 0x5800
2353 #define T_OPCODE_STR_RW 0x5000
2354 #define T_OPCODE_LDR_RH 0x5a00
2355 #define T_OPCODE_STR_RH 0x5200
2356 #define T_OPCODE_LDR_RB 0x5c00
2357 #define T_OPCODE_STR_RB 0x5400
2359 #define T_OPCODE_PUSH 0xb400
2360 #define T_OPCODE_POP 0xbc00
2362 #define T_OPCODE_BRANCH 0xe7fe
2364 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2366 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2367 #define THUMB_REG_LO 0x1
2368 #define THUMB_REG_HI 0x2
2369 #define THUMB_REG_ANY 0x3
2371 #define THUMB_H1 0x0080
2372 #define THUMB_H2 0x0040
2378 #define THUMB_MOVE 0
2379 #define THUMB_COMPARE 1
2382 #define THUMB_LOAD 0
2383 #define THUMB_STORE 1
2385 #define THUMB_PP_PC_LR 0x0100
2387 /* These three are used for immediate shifts, do not alter. */
2388 #define THUMB_WORD 2
2389 #define THUMB_HALFWORD 1
2390 #define THUMB_BYTE 0
2394 /* Basic string to match. */
2395 const char * template;
2397 /* Basic instruction code. */
2398 unsigned long value
;
2402 /* Which CPU variants this exists for. */
2403 unsigned long variant
;
2405 /* Function to call to parse args. */
2406 void (* parms
) PARAMS ((char *));
2409 static const struct thumb_opcode tinsns
[] =
2411 /* Thumb v1 (ARMv4T). */
2412 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2413 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2414 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2415 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2416 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2417 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2418 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2419 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2420 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2421 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2422 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2423 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2424 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2425 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2426 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2427 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2428 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2429 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2430 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2431 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2432 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2433 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2434 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2435 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2436 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2437 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2438 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2439 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2440 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2441 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2442 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2443 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2444 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2445 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2446 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2447 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2448 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2449 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2450 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2451 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2452 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2453 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2454 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2455 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2456 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2457 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2458 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2459 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2460 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2461 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2462 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2463 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2464 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2465 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2466 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2468 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2469 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2470 /* Thumb v2 (ARMv5T). */
2471 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2472 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2475 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
2476 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
2477 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
2478 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
2479 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
2480 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
2481 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
2482 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
2483 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
2484 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
2485 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
2488 #define BAD_ARGS _("bad arguments to instruction")
2489 #define BAD_PC _("r15 not allowed here")
2490 #define BAD_COND _("instruction is not conditional")
2491 #define ERR_NO_ACCUM _("acc0 expected")
2493 static struct hash_control
* arm_ops_hsh
= NULL
;
2494 static struct hash_control
* arm_tops_hsh
= NULL
;
2495 static struct hash_control
* arm_cond_hsh
= NULL
;
2496 static struct hash_control
* arm_shift_hsh
= NULL
;
2497 static struct hash_control
* arm_psr_hsh
= NULL
;
2499 /* This table describes all the machine specific pseudo-ops the assembler
2500 has to support. The fields are:
2501 pseudo-op name without dot
2502 function to call to execute this pseudo-op
2503 Integer arg to pass to the function. */
2505 static void s_req
PARAMS ((int));
2506 static void s_unreq
PARAMS ((int));
2507 static void s_align
PARAMS ((int));
2508 static void s_bss
PARAMS ((int));
2509 static void s_even
PARAMS ((int));
2510 static void s_ltorg
PARAMS ((int));
2511 static void s_arm
PARAMS ((int));
2512 static void s_thumb
PARAMS ((int));
2513 static void s_code
PARAMS ((int));
2514 static void s_force_thumb
PARAMS ((int));
2515 static void s_thumb_func
PARAMS ((int));
2516 static void s_thumb_set
PARAMS ((int));
2518 static void s_arm_elf_cons
PARAMS ((int));
2521 static int my_get_expression
PARAMS ((expressionS
*, char **));
2523 const pseudo_typeS md_pseudo_table
[] =
2525 /* Never called because '.req' does not start a line. */
2526 { "req", s_req
, 0 },
2527 { "unreq", s_unreq
, 0 },
2528 { "bss", s_bss
, 0 },
2529 { "align", s_align
, 0 },
2530 { "arm", s_arm
, 0 },
2531 { "thumb", s_thumb
, 0 },
2532 { "code", s_code
, 0 },
2533 { "force_thumb", s_force_thumb
, 0 },
2534 { "thumb_func", s_thumb_func
, 0 },
2535 { "thumb_set", s_thumb_set
, 0 },
2536 { "even", s_even
, 0 },
2537 { "ltorg", s_ltorg
, 0 },
2538 { "pool", s_ltorg
, 0 },
2540 { "word", s_arm_elf_cons
, 4 },
2541 { "long", s_arm_elf_cons
, 4 },
2545 { "extend", float_cons
, 'x' },
2546 { "ldouble", float_cons
, 'x' },
2547 { "packed", float_cons
, 'p' },
2551 /* Other internal functions. */
2552 static int arm_parse_extension
PARAMS ((char *, int *));
2553 static int arm_parse_cpu
PARAMS ((char *));
2554 static int arm_parse_arch
PARAMS ((char *));
2555 static int arm_parse_fpu
PARAMS ((char *));
2556 static int arm_parse_float_abi
PARAMS ((char *));
2558 static int arm_parse_eabi
PARAMS ((char *));
2560 #if 0 /* Suppressed - for now. */
2561 #if defined OBJ_COFF || defined OBJ_ELF
2562 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2566 /* Stuff needed to resolve the label ambiguity
2576 symbolS
* last_label_seen
;
2577 static int label_is_thumb_function_name
= FALSE
;
2579 /* Literal Pool stuff. */
2581 #define MAX_LITERAL_POOL_SIZE 1024
2583 /* Literal pool structure. Held on a per-section
2584 and per-sub-section basis. */
2585 typedef struct literal_pool
2587 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2588 unsigned int next_free_entry
;
2592 subsegT sub_section
;
2593 struct literal_pool
* next
;
2596 /* Pointer to a linked list of literal pools. */
2597 literal_pool
* list_of_pools
= NULL
;
2599 static literal_pool
* find_literal_pool
PARAMS ((void));
2600 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2602 static literal_pool
*
2603 find_literal_pool ()
2605 literal_pool
* pool
;
2607 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2609 if (pool
->section
== now_seg
2610 && pool
->sub_section
== now_subseg
)
2617 static literal_pool
*
2618 find_or_make_literal_pool ()
2620 /* Next literal pool ID number. */
2621 static unsigned int latest_pool_num
= 1;
2622 literal_pool
* pool
;
2624 pool
= find_literal_pool ();
2628 /* Create a new pool. */
2629 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2633 pool
->next_free_entry
= 0;
2634 pool
->section
= now_seg
;
2635 pool
->sub_section
= now_subseg
;
2636 pool
->next
= list_of_pools
;
2637 pool
->symbol
= NULL
;
2639 /* Add it to the list. */
2640 list_of_pools
= pool
;
2643 /* New pools, and emptied pools, will have a NULL symbol. */
2644 if (pool
->symbol
== NULL
)
2646 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2647 (valueT
) 0, &zero_address_frag
);
2648 pool
->id
= latest_pool_num
++;
2655 /* Add the literal in the global 'inst'
2656 structure to the relevent literal pool. */
2660 literal_pool
* pool
;
2663 pool
= find_or_make_literal_pool ();
2665 /* Check if this literal value is already in the pool. */
2666 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2668 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2669 && (inst
.reloc
.exp
.X_op
== O_constant
)
2670 && (pool
->literals
[entry
].X_add_number
2671 == inst
.reloc
.exp
.X_add_number
)
2672 && (pool
->literals
[entry
].X_unsigned
2673 == inst
.reloc
.exp
.X_unsigned
))
2676 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2677 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2678 && (pool
->literals
[entry
].X_add_number
2679 == inst
.reloc
.exp
.X_add_number
)
2680 && (pool
->literals
[entry
].X_add_symbol
2681 == inst
.reloc
.exp
.X_add_symbol
)
2682 && (pool
->literals
[entry
].X_op_symbol
2683 == inst
.reloc
.exp
.X_op_symbol
))
2687 /* Do we need to create a new entry? */
2688 if (entry
== pool
->next_free_entry
)
2690 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2692 inst
.error
= _("literal pool overflow");
2696 pool
->literals
[entry
] = inst
.reloc
.exp
;
2697 pool
->next_free_entry
+= 1;
2700 inst
.reloc
.exp
.X_op
= O_symbol
;
2701 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2702 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2707 /* Can't use symbol_new here, so have to create a symbol and then at
2708 a later date assign it a value. Thats what these functions do. */
2711 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2713 const char * name
; /* It is copied, the caller can modify. */
2714 segT segment
; /* Segment identifier (SEG_<something>). */
2715 valueT valu
; /* Symbol value. */
2716 fragS
* frag
; /* Associated fragment. */
2718 unsigned int name_length
;
2719 char * preserved_copy_of_name
;
2721 name_length
= strlen (name
) + 1; /* +1 for \0. */
2722 obstack_grow (¬es
, name
, name_length
);
2723 preserved_copy_of_name
= obstack_finish (¬es
);
2724 #ifdef STRIP_UNDERSCORE
2725 if (preserved_copy_of_name
[0] == '_')
2726 preserved_copy_of_name
++;
2729 #ifdef tc_canonicalize_symbol_name
2730 preserved_copy_of_name
=
2731 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2734 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2736 S_SET_SEGMENT (symbolP
, segment
);
2737 S_SET_VALUE (symbolP
, valu
);
2738 symbol_clear_list_pointers (symbolP
);
2740 symbol_set_frag (symbolP
, frag
);
2742 /* Link to end of symbol chain. */
2744 extern int symbol_table_frozen
;
2745 if (symbol_table_frozen
)
2749 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2751 obj_symbol_new_hook (symbolP
);
2753 #ifdef tc_symbol_new_hook
2754 tc_symbol_new_hook (symbolP
);
2758 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2759 #endif /* DEBUG_SYMS */
2762 /* Check that an immediate is valid.
2763 If so, convert it to the right format. */
2766 validate_immediate (val
)
2772 #define rotate_left(v, n) (v << n | v >> (32 - n))
2774 for (i
= 0; i
< 32; i
+= 2)
2775 if ((a
= rotate_left (val
, i
)) <= 0xff)
2776 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2781 /* Check to see if an immediate can be computed as two separate immediate
2782 values, added together. We already know that this value cannot be
2783 computed by just one ARM instruction. */
2786 validate_immediate_twopart (val
, highpart
)
2788 unsigned int * highpart
;
2793 for (i
= 0; i
< 32; i
+= 2)
2794 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2800 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2802 else if (a
& 0xff0000)
2806 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2810 assert (a
& 0xff000000);
2811 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2814 return (a
& 0xff) | (i
<< 7);
2821 validate_offset_imm (val
, hwse
)
2825 if ((hwse
&& val
> 255) || val
> 4095)
2839 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2840 (This text is taken from version B-02 of the spec):
2842 4.4.7 Mapping and tagging symbols
2844 A section of an ARM ELF file can contain a mixture of ARM code,
2845 Thumb code, and data. There are inline transitions between code
2846 and data at literal pool boundaries. There can also be inline
2847 transitions between ARM code and Thumb code, for example in
2848 ARM-Thumb inter-working veneers. Linkers, machine-level
2849 debuggers, profiling tools, and disassembly tools need to map
2850 images accurately. For example, setting an ARM breakpoint on a
2851 Thumb location, or in a literal pool, can crash the program
2852 being debugged, ruining the debugging session.
2854 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2855 tagged (see section 4.4.7.2 below) using local symbols (with
2856 binding STB_LOCAL). To assist consumers, mapping and tagging
2857 symbols should be collated first in the symbol table, before
2858 other symbols with binding STB_LOCAL.
2860 To allow properly collated mapping and tagging symbols to be
2861 skipped by consumers that have no interest in them, the first
2862 such symbol should have the name $m and its st_value field equal
2863 to the total number of mapping and tagging symbols (including
2864 the $m) in the symbol table.
2866 4.4.7.1 Mapping symbols
2868 $a Labels the first byte of a sequence of ARM instructions.
2869 Its type is STT_FUNC.
2871 $d Labels the first byte of a sequence of data items.
2872 Its type is STT_OBJECT.
2874 $t Labels the first byte of a sequence of Thumb instructions.
2875 Its type is STT_FUNC.
2877 This list of mapping symbols may be extended in the future.
2879 Section-relative mapping symbols
2881 Mapping symbols defined in a section define a sequence of
2882 half-open address intervals that cover the address range of the
2883 section. Each interval starts at the address defined by a
2884 mapping symbol, and continues up to, but not including, the
2885 address defined by the next (in address order) mapping symbol or
2886 the end of the section. A corollary is that there must be a
2887 mapping symbol defined at the beginning of each section.
2888 Consumers can ignore the size of a section-relative mapping
2889 symbol. Producers can set it to 0.
2891 Absolute mapping symbols
2893 Because of the need to crystallize a Thumb address with the
2894 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2895 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2898 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2899 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2900 where [x, y) denotes the half-open address range from x,
2901 inclusive, to y, exclusive.
2903 In the absence of a mapping symbol, a consumer can interpret a
2904 function symbol with an odd value as the Thumb code address
2905 obtained by clearing the least significant bit of the
2906 value. This interpretation is deprecated, and it may not work in
2909 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2910 the EABI (which is still under development), so they are not
2911 implemented here. */
2914 mapping_state (enum mstate state
)
2916 static enum mstate mapstate
= MAP_DATA
;
2918 const char * symname
;
2921 if (mapstate
== state
)
2922 /* The mapping symbol has already been emitted.
2923 There is nothing else to do. */
2936 type
= BSF_FUNCTION
;
2940 type
= BSF_FUNCTION
;
2946 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2947 symbol_table_insert (symbolP
);
2948 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2953 THUMB_SET_FUNC (symbolP
, 0);
2954 ARM_SET_THUMB (symbolP
, 0);
2955 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2959 THUMB_SET_FUNC (symbolP
, 1);
2960 ARM_SET_THUMB (symbolP
, 1);
2961 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2970 /* When we change sections we need to issue a new mapping symbol. */
2973 arm_elf_change_section (void)
2977 if (!SEG_NORMAL (now_seg
))
2980 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2982 /* We can ignore sections that only contain debug info. */
2983 if ((flags
& SEC_ALLOC
) == 0)
2986 if (flags
& SEC_CODE
)
2989 mapping_state (MAP_THUMB
);
2991 mapping_state (MAP_ARM
);
2994 /* This section does not contain code. Therefore it must contain data. */
2995 mapping_state (MAP_DATA
);
2998 #define mapping_state(a)
2999 #endif /* OBJ_ELF */
3004 int a ATTRIBUTE_UNUSED
;
3006 as_bad (_("invalid syntax for .req directive"));
3009 /* The .unreq directive deletes an alias which was previously defined
3010 by .req. For example:
3016 s_unreq (int a ATTRIBUTE_UNUSED
)
3021 skip_whitespace (input_line_pointer
);
3022 name
= input_line_pointer
;
3024 while (*input_line_pointer
!= 0
3025 && *input_line_pointer
!= ' '
3026 && *input_line_pointer
!= '\n')
3027 ++input_line_pointer
;
3029 saved_char
= *input_line_pointer
;
3030 *input_line_pointer
= 0;
3034 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
3036 if (req_type
!= REG_TYPE_MAX
)
3038 char *temp_name
= name
;
3039 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
3043 struct reg_entry
*req_entry
;
3045 /* Check to see if this alias is a builtin one. */
3046 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
3049 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
3050 else if (req_entry
->builtin
)
3051 /* FIXME: We are deleting a built in register alias which
3052 points to a const data structure, so we only need to
3053 free up the memory used by the key in the hash table.
3054 Unfortunately we have not recorded this value, so this
3055 is a memory leak. */
3056 /* FIXME: Should we issue a warning message ? */
3060 /* Deleting a user defined alias. We need to free the
3061 key and the value, but fortunately the key is the same
3062 as the value->name field. */
3063 free ((char *) req_entry
->name
);
3068 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3071 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3074 as_bad (_("invalid syntax for .unreq directive"));
3076 *input_line_pointer
= saved_char
;
3077 demand_empty_rest_of_line ();
3082 int ignore ATTRIBUTE_UNUSED
;
3084 /* We don't support putting frags in the BSS segment, we fake it by
3085 marking in_bss, then looking at s_skip for clues. */
3086 subseg_set (bss_section
, 0);
3087 demand_empty_rest_of_line ();
3088 mapping_state (MAP_DATA
);
3093 int ignore ATTRIBUTE_UNUSED
;
3095 /* Never make frag if expect extra pass. */
3097 frag_align (1, 0, 0);
3099 record_alignment (now_seg
, 1);
3101 demand_empty_rest_of_line ();
3106 int ignored ATTRIBUTE_UNUSED
;
3109 literal_pool
* pool
;
3112 pool
= find_literal_pool ();
3114 || pool
->symbol
== NULL
3115 || pool
->next_free_entry
== 0)
3118 /* Align pool as you have word accesses.
3119 Only make a frag if we have to. */
3121 frag_align (2, 0, 0);
3123 record_alignment (now_seg
, 2);
3125 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3127 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3128 (valueT
) frag_now_fix (), frag_now
);
3129 symbol_table_insert (pool
->symbol
);
3131 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3133 #if defined OBJ_COFF || defined OBJ_ELF
3134 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3137 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3138 /* First output the expression in the instruction to the pool. */
3139 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3141 /* Mark the pool as empty. */
3142 pool
->next_free_entry
= 0;
3143 pool
->symbol
= NULL
;
3146 /* Same as s_align_ptwo but align 0 => align 2. */
3150 int unused ATTRIBUTE_UNUSED
;
3153 register long temp_fill
;
3154 long max_alignment
= 15;
3156 temp
= get_absolute_expression ();
3157 if (temp
> max_alignment
)
3158 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3161 as_bad (_("alignment negative. 0 assumed."));
3165 if (*input_line_pointer
== ',')
3167 input_line_pointer
++;
3168 temp_fill
= get_absolute_expression ();
3176 /* Only make a frag if we HAVE to. */
3177 if (temp
&& !need_pass_2
)
3178 frag_align (temp
, (int) temp_fill
, 0);
3179 demand_empty_rest_of_line ();
3181 record_alignment (now_seg
, temp
);
3185 s_force_thumb (ignore
)
3186 int ignore ATTRIBUTE_UNUSED
;
3188 /* If we are not already in thumb mode go into it, EVEN if
3189 the target processor does not support thumb instructions.
3190 This is used by gcc/config/arm/lib1funcs.asm for example
3191 to compile interworking support functions even if the
3192 target processor should not support interworking. */
3197 record_alignment (now_seg
, 1);
3200 demand_empty_rest_of_line ();
3204 s_thumb_func (ignore
)
3205 int ignore ATTRIBUTE_UNUSED
;
3210 /* The following label is the name/address of the start of a Thumb function.
3211 We need to know this for the interworking support. */
3212 label_is_thumb_function_name
= TRUE
;
3214 demand_empty_rest_of_line ();
3217 /* Perform a .set directive, but also mark the alias as
3218 being a thumb function. */
3224 /* XXX the following is a duplicate of the code for s_set() in read.c
3225 We cannot just call that code as we need to get at the symbol that
3227 register char * name
;
3228 register char delim
;
3229 register char * end_name
;
3230 register symbolS
* symbolP
;
3232 /* Especial apologies for the random logic:
3233 This just grew, and could be parsed much more simply!
3235 name
= input_line_pointer
;
3236 delim
= get_symbol_end ();
3237 end_name
= input_line_pointer
;
3242 if (*input_line_pointer
!= ',')
3245 as_bad (_("expected comma after name \"%s\""), name
);
3247 ignore_rest_of_line ();
3251 input_line_pointer
++;
3254 if (name
[0] == '.' && name
[1] == '\0')
3256 /* XXX - this should not happen to .thumb_set. */
3260 if ((symbolP
= symbol_find (name
)) == NULL
3261 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3264 /* When doing symbol listings, play games with dummy fragments living
3265 outside the normal fragment chain to record the file and line info
3267 if (listing
& LISTING_SYMBOLS
)
3269 extern struct list_info_struct
* listing_tail
;
3270 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3272 memset (dummy_frag
, 0, sizeof (fragS
));
3273 dummy_frag
->fr_type
= rs_fill
;
3274 dummy_frag
->line
= listing_tail
;
3275 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3276 dummy_frag
->fr_symbol
= symbolP
;
3280 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3283 /* "set" symbols are local unless otherwise specified. */
3284 SF_SET_LOCAL (symbolP
);
3285 #endif /* OBJ_COFF */
3286 } /* Make a new symbol. */
3288 symbol_table_insert (symbolP
);
3293 && S_IS_DEFINED (symbolP
)
3294 && S_GET_SEGMENT (symbolP
) != reg_section
)
3295 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3297 pseudo_set (symbolP
);
3299 demand_empty_rest_of_line ();
3301 /* XXX Now we come to the Thumb specific bit of code. */
3303 THUMB_SET_FUNC (symbolP
, 1);
3304 ARM_SET_THUMB (symbolP
, 1);
3305 #if defined OBJ_ELF || defined OBJ_COFF
3306 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3311 opcode_select (width
)
3319 if (! (cpu_variant
& ARM_EXT_V4T
))
3320 as_bad (_("selected processor does not support THUMB opcodes"));
3323 /* No need to force the alignment, since we will have been
3324 coming from ARM mode, which is word-aligned. */
3325 record_alignment (now_seg
, 1);
3327 mapping_state (MAP_THUMB
);
3333 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3334 as_bad (_("selected processor does not support ARM opcodes"));
3339 frag_align (2, 0, 0);
3341 record_alignment (now_seg
, 1);
3343 mapping_state (MAP_ARM
);
3347 as_bad (_("invalid instruction size selected (%d)"), width
);
3353 int ignore ATTRIBUTE_UNUSED
;
3356 demand_empty_rest_of_line ();
3361 int ignore ATTRIBUTE_UNUSED
;
3364 demand_empty_rest_of_line ();
3369 int unused ATTRIBUTE_UNUSED
;
3373 temp
= get_absolute_expression ();
3378 opcode_select (temp
);
3382 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3390 skip_whitespace (str
);
3392 if (*str
!= '\0' && !inst
.error
)
3393 inst
.error
= _("garbage following instruction");
3397 skip_past_comma (str
)
3400 char * p
= * str
, c
;
3403 while ((c
= *p
) == ' ' || c
== ',')
3406 if (c
== ',' && comma
++)
3414 return comma
? SUCCESS
: FAIL
;
3417 /* A standard register must be given at this point.
3418 SHIFT is the place to put it in inst.instruction.
3419 Restores input start point on error.
3420 Returns the reg#, or FAIL. */
3423 reg_required_here (str
, shift
)
3427 static char buff
[128]; /* XXX */
3429 char * start
= * str
;
3431 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3434 inst
.instruction
|= reg
<< shift
;
3438 /* Restore the start point, we may have got a reg of the wrong class. */
3441 /* In the few cases where we might be able to accept something else
3442 this error can be overridden. */
3443 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3449 /* A Intel Wireless MMX technology register
3450 must be given at this point.
3451 Shift is the place to put it in inst.instruction.
3452 Restores input start point on err.
3453 Returns the reg#, or FAIL. */
3456 wreg_required_here (str
, shift
, reg_type
)
3459 enum wreg_type reg_type
;
3461 static char buff
[128];
3463 char * start
= *str
;
3465 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3467 if (wr_register (reg
)
3468 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3471 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3474 else if (wc_register (reg
)
3475 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3478 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3481 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3484 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3489 /* Restore the start point, we may have got a reg of the wrong class. */
3492 /* In the few cases where we might be able to accept
3493 something else this error can be overridden. */
3494 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3500 static const struct asm_psr
*
3502 register char ** ccp
;
3504 char * start
= * ccp
;
3507 const struct asm_psr
* psr
;
3511 /* Skip to the end of the next word in the input stream. */
3516 while (ISALPHA (c
) || c
== '_');
3518 /* Terminate the word. */
3521 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3522 feature for ease of use and backwards compatibility. */
3523 if (!strncmp (start
, "cpsr", 4))
3524 strncpy (start
, "CPSR", 4);
3525 else if (!strncmp (start
, "spsr", 4))
3526 strncpy (start
, "SPSR", 4);
3528 /* Now locate the word in the psr hash table. */
3529 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3531 /* Restore the input stream. */
3534 /* If we found a valid match, advance the
3535 stream pointer past the end of the word. */
3541 /* Parse the input looking for a PSR flag. */
3544 psr_required_here (str
)
3547 char * start
= * str
;
3548 const struct asm_psr
* psr
;
3550 psr
= arm_psr_parse (str
);
3554 /* If this is the SPSR that is being modified, set the R bit. */
3556 inst
.instruction
|= SPSR_BIT
;
3558 /* Set the psr flags in the MSR instruction. */
3559 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3564 /* In the few cases where we might be able to accept
3565 something else this error can be overridden. */
3566 inst
.error
= _("flag for {c}psr instruction expected");
3568 /* Restore the start point. */
3574 co_proc_number (str
)
3577 int processor
, pchar
;
3580 skip_whitespace (*str
);
3583 /* The data sheet seems to imply that just a number on its own is valid
3584 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3586 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3592 if (pchar
>= '0' && pchar
<= '9')
3594 processor
= pchar
- '0';
3595 if (**str
>= '0' && **str
<= '9')
3597 processor
= processor
* 10 + *(*str
)++ - '0';
3600 inst
.error
= _("illegal co-processor number");
3607 inst
.error
= _("bad or missing co-processor number");
3612 inst
.instruction
|= processor
<< 8;
3617 cp_opc_expr (str
, where
, length
)
3624 skip_whitespace (* str
);
3626 memset (&expr
, '\0', sizeof (expr
));
3628 if (my_get_expression (&expr
, str
))
3630 if (expr
.X_op
!= O_constant
)
3632 inst
.error
= _("bad or missing expression");
3636 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3638 inst
.error
= _("immediate co-processor expression too large");
3642 inst
.instruction
|= expr
.X_add_number
<< where
;
3647 cp_reg_required_here (str
, where
)
3652 char * start
= *str
;
3654 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3656 inst
.instruction
|= reg
<< where
;
3660 /* In the few cases where we might be able to accept something else
3661 this error can be overridden. */
3662 inst
.error
= _("co-processor register expected");
3664 /* Restore the start point. */
3670 fp_reg_required_here (str
, where
)
3675 char * start
= * str
;
3677 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3679 inst
.instruction
|= reg
<< where
;
3683 /* In the few cases where we might be able to accept something else
3684 this error can be overridden. */
3685 inst
.error
= _("floating point register expected");
3687 /* Restore the start point. */
3693 cp_address_offset (str
)
3698 skip_whitespace (* str
);
3700 if (! is_immediate_prefix (**str
))
3702 inst
.error
= _("immediate expression expected");
3708 if (my_get_expression (& inst
.reloc
.exp
, str
))
3711 if (inst
.reloc
.exp
.X_op
== O_constant
)
3713 offset
= inst
.reloc
.exp
.X_add_number
;
3717 inst
.error
= _("co-processor address must be word aligned");
3721 if (offset
> 1023 || offset
< -1023)
3723 inst
.error
= _("offset too large");
3728 inst
.instruction
|= INDEX_UP
;
3732 inst
.instruction
|= offset
>> 2;
3735 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3741 cp_address_required_here (str
, wb_ok
)
3754 skip_whitespace (p
);
3756 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3759 skip_whitespace (p
);
3765 skip_whitespace (p
);
3769 /* As an extension to the official ARM syntax we allow:
3773 as a short hand for:
3776 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3781 if (skip_past_comma (& p
) == FAIL
)
3783 inst
.error
= _("comma expected after closing square bracket");
3787 skip_whitespace (p
);
3794 write_back
= WRITE_BACK
;
3798 inst
.error
= _("pc may not be used in post-increment");
3802 if (cp_address_offset (& p
) == FAIL
)
3806 pre_inc
= PRE_INDEX
| INDEX_UP
;
3812 /* [Rn], {<expr>} */
3815 skip_whitespace (p
);
3817 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3820 if (inst
.reloc
.exp
.X_op
== O_constant
)
3822 option
= inst
.reloc
.exp
.X_add_number
;
3824 if (option
> 255 || option
< 0)
3826 inst
.error
= _("'option' field too large");
3830 skip_whitespace (p
);
3834 inst
.error
= _("'}' expected at end of 'option' field");
3840 inst
.instruction
|= option
;
3841 inst
.instruction
|= INDEX_UP
;
3846 inst
.error
= _("non-constant expressions for 'option' field not supported");
3852 inst
.error
= _("# or { expected after comma");
3858 /* '['Rn, #expr']'[!] */
3860 if (skip_past_comma (& p
) == FAIL
)
3862 inst
.error
= _("pre-indexed expression expected");
3866 pre_inc
= PRE_INDEX
;
3868 if (cp_address_offset (& p
) == FAIL
)
3871 skip_whitespace (p
);
3875 inst
.error
= _("missing ]");
3879 skip_whitespace (p
);
3881 if (wb_ok
&& *p
== '!')
3885 inst
.error
= _("pc may not be used with write-back");
3890 write_back
= WRITE_BACK
;
3896 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3899 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3900 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3901 inst
.reloc
.pc_rel
= 1;
3902 inst
.instruction
|= (REG_PC
<< 16);
3903 pre_inc
= PRE_INDEX
;
3906 inst
.instruction
|= write_back
| pre_inc
;
3912 cp_byte_address_offset (str
)
3917 skip_whitespace (* str
);
3919 if (! is_immediate_prefix (**str
))
3921 inst
.error
= _("immediate expression expected");
3927 if (my_get_expression (& inst
.reloc
.exp
, str
))
3930 if (inst
.reloc
.exp
.X_op
== O_constant
)
3932 offset
= inst
.reloc
.exp
.X_add_number
;
3934 if (offset
> 255 || offset
< -255)
3936 inst
.error
= _("offset too large");
3941 inst
.instruction
|= INDEX_UP
;
3945 inst
.instruction
|= offset
;
3948 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3954 cp_byte_address_required_here (str
)
3966 skip_whitespace (p
);
3968 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3971 skip_whitespace (p
);
3977 if (skip_past_comma (& p
) == SUCCESS
)
3980 write_back
= WRITE_BACK
;
3984 inst
.error
= _("pc may not be used in post-increment");
3988 if (cp_byte_address_offset (& p
) == FAIL
)
3992 pre_inc
= PRE_INDEX
| INDEX_UP
;
3996 /* '['Rn, #expr']'[!] */
3998 if (skip_past_comma (& p
) == FAIL
)
4000 inst
.error
= _("pre-indexed expression expected");
4004 pre_inc
= PRE_INDEX
;
4006 if (cp_byte_address_offset (& p
) == FAIL
)
4009 skip_whitespace (p
);
4013 inst
.error
= _("missing ]");
4017 skip_whitespace (p
);
4023 inst
.error
= _("pc may not be used with write-back");
4028 write_back
= WRITE_BACK
;
4034 if (my_get_expression (&inst
.reloc
.exp
, &p
))
4037 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
4038 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4039 inst
.reloc
.pc_rel
= 1;
4040 inst
.instruction
|= (REG_PC
<< 16);
4041 pre_inc
= PRE_INDEX
;
4044 inst
.instruction
|= write_back
| pre_inc
;
4053 /* Do nothing really. */
4063 /* Only one syntax. */
4064 skip_whitespace (str
);
4066 if (reg_required_here (&str
, 12) == FAIL
)
4068 inst
.error
= BAD_ARGS
;
4072 if (skip_past_comma (&str
) == FAIL
)
4074 inst
.error
= _("comma expected after register name");
4078 skip_whitespace (str
);
4080 if ( strcmp (str
, "CPSR") == 0
4081 || strcmp (str
, "SPSR") == 0
4082 /* Lower case versions for backwards compatibility. */
4083 || strcmp (str
, "cpsr") == 0
4084 || strcmp (str
, "spsr") == 0)
4087 /* This is for backwards compatibility with older toolchains. */
4088 else if ( strcmp (str
, "cpsr_all") == 0
4089 || strcmp (str
, "spsr_all") == 0)
4093 inst
.error
= _("CPSR or SPSR expected");
4097 if (* str
== 's' || * str
== 'S')
4098 inst
.instruction
|= SPSR_BIT
;
4104 /* Two possible forms:
4105 "{C|S}PSR_<field>, Rm",
4106 "{C|S}PSR_f, #expression". */
4112 skip_whitespace (str
);
4114 if (psr_required_here (& str
) == FAIL
)
4117 if (skip_past_comma (& str
) == FAIL
)
4119 inst
.error
= _("comma missing after psr flags");
4123 skip_whitespace (str
);
4125 if (reg_required_here (& str
, 0) != FAIL
)
4132 if (! is_immediate_prefix (* str
))
4135 _("only a register or immediate value can follow a psr flag");
4142 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4145 _("only a register or immediate value can follow a psr flag");
4149 #if 0 /* The first edition of the ARM architecture manual stated that
4150 writing anything other than the flags with an immediate operation
4151 had UNPREDICTABLE effects. This constraint was removed in the
4152 second edition of the specification. */
4153 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4154 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4156 inst
.error
= _("immediate value cannot be used to set this field");
4161 inst
.instruction
|= INST_IMMEDIATE
;
4163 if (inst
.reloc
.exp
.X_add_symbol
)
4165 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4166 inst
.reloc
.pc_rel
= 0;
4170 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4172 if (value
== (unsigned) FAIL
)
4174 inst
.error
= _("invalid constant");
4178 inst
.instruction
|= value
;
4185 /* Long Multiply Parser
4186 UMULL RdLo, RdHi, Rm, Rs
4187 SMULL RdLo, RdHi, Rm, Rs
4188 UMLAL RdLo, RdHi, Rm, Rs
4189 SMLAL RdLo, RdHi, Rm, Rs. */
4195 int rdlo
, rdhi
, rm
, rs
;
4197 /* Only one format "rdlo, rdhi, rm, rs". */
4198 skip_whitespace (str
);
4200 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4202 inst
.error
= BAD_ARGS
;
4206 if (skip_past_comma (&str
) == FAIL
4207 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4209 inst
.error
= BAD_ARGS
;
4213 if (skip_past_comma (&str
) == FAIL
4214 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4216 inst
.error
= BAD_ARGS
;
4220 /* rdhi, rdlo and rm must all be different. */
4221 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4222 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4224 if (skip_past_comma (&str
) == FAIL
4225 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4227 inst
.error
= BAD_ARGS
;
4231 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4233 inst
.error
= BAD_PC
;
4246 /* Only one format "rd, rm, rs". */
4247 skip_whitespace (str
);
4249 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4251 inst
.error
= BAD_ARGS
;
4257 inst
.error
= BAD_PC
;
4261 if (skip_past_comma (&str
) == FAIL
4262 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4264 inst
.error
= BAD_ARGS
;
4270 inst
.error
= BAD_PC
;
4275 as_tsktsk (_("rd and rm should be different in mul"));
4277 if (skip_past_comma (&str
) == FAIL
4278 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4280 inst
.error
= BAD_ARGS
;
4286 inst
.error
= BAD_PC
;
4299 /* Only one format "rd, rm, rs, rn". */
4300 skip_whitespace (str
);
4302 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4304 inst
.error
= BAD_ARGS
;
4310 inst
.error
= BAD_PC
;
4314 if (skip_past_comma (&str
) == FAIL
4315 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4317 inst
.error
= BAD_ARGS
;
4323 inst
.error
= BAD_PC
;
4328 as_tsktsk (_("rd and rm should be different in mla"));
4330 if (skip_past_comma (&str
) == FAIL
4331 || (rd
= reg_required_here (&str
, 8)) == FAIL
4332 || skip_past_comma (&str
) == FAIL
4333 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4335 inst
.error
= BAD_ARGS
;
4339 if (rd
== REG_PC
|| rm
== REG_PC
)
4341 inst
.error
= BAD_PC
;
4348 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4349 Advances *str to the next non-alphanumeric.
4350 Returns 0, or else FAIL (in which case sets inst.error).
4352 (In a future XScale, there may be accumulators other than zero.
4353 At that time this routine and its callers can be upgraded to suit.) */
4356 accum0_required_here (str
)
4359 static char buff
[128]; /* Note the address is taken. Hence, static. */
4362 int result
= 0; /* The accum number. */
4364 skip_whitespace (p
);
4366 *str
= p
; /* Advance caller's string pointer too. */
4371 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4373 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4375 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4380 *p
= c
; /* Unzap. */
4381 *str
= p
; /* Caller's string pointer to after match. */
4385 /* Expects **str -> after a comma. May be leading blanks.
4386 Advances *str, recognizing a load mode, and setting inst.instruction.
4387 Returns rn, or else FAIL (in which case may set inst.error
4388 and not advance str)
4390 Note: doesn't know Rd, so no err checks that require such knowledge. */
4393 ld_mode_required_here (string
)
4396 char * str
= * string
;
4400 skip_whitespace (str
);
4406 skip_whitespace (str
);
4408 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4411 skip_whitespace (str
);
4417 if (skip_past_comma (& str
) == SUCCESS
)
4419 /* [Rn],... (post inc) */
4420 if (ldst_extend_v4 (&str
) == FAIL
)
4425 skip_whitespace (str
);
4430 inst
.instruction
|= WRITE_BACK
;
4433 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4439 if (skip_past_comma (& str
) == FAIL
)
4441 inst
.error
= _("pre-indexed expression expected");
4447 if (ldst_extend_v4 (&str
) == FAIL
)
4450 skip_whitespace (str
);
4452 if (* str
++ != ']')
4454 inst
.error
= _("missing ]");
4458 skip_whitespace (str
);
4463 inst
.instruction
|= WRITE_BACK
;
4467 else if (* str
== '=') /* ldr's "r,=label" syntax */
4468 /* We should never reach here, because <text> = <expression> is
4469 caught gas/read.c read_a_source_file() as a .set operation. */
4471 else /* PC +- 8 bit immediate offset. */
4473 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4476 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4477 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4478 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4479 inst
.reloc
.pc_rel
= 1;
4480 inst
.instruction
|= (REG_PC
<< 16);
4486 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4492 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4493 SMLAxy{cond} Rd,Rm,Rs,Rn
4494 SMLAWy{cond} Rd,Rm,Rs,Rn
4495 Error if any register is R15. */
4503 skip_whitespace (str
);
4505 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4506 || skip_past_comma (& str
) == FAIL
4507 || (rm
= reg_required_here (& str
, 0)) == FAIL
4508 || skip_past_comma (& str
) == FAIL
4509 || (rs
= reg_required_here (& str
, 8)) == FAIL
4510 || skip_past_comma (& str
) == FAIL
4511 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4512 inst
.error
= BAD_ARGS
;
4514 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4515 inst
.error
= BAD_PC
;
4521 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4522 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4523 Error if any register is R15.
4524 Warning if Rdlo == Rdhi. */
4530 int rdlo
, rdhi
, rm
, rs
;
4532 skip_whitespace (str
);
4534 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4535 || skip_past_comma (& str
) == FAIL
4536 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4537 || skip_past_comma (& str
) == FAIL
4538 || (rm
= reg_required_here (& str
, 0)) == FAIL
4539 || skip_past_comma (& str
) == FAIL
4540 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4542 inst
.error
= BAD_ARGS
;
4546 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4548 inst
.error
= BAD_PC
;
4553 as_tsktsk (_("rdhi and rdlo must be different"));
4558 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4559 SMULxy{cond} Rd,Rm,Rs
4560 Error if any register is R15. */
4568 skip_whitespace (str
);
4570 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4571 || skip_past_comma (& str
) == FAIL
4572 || (rm
= reg_required_here (& str
, 0)) == FAIL
4573 || skip_past_comma (& str
) == FAIL
4574 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4575 inst
.error
= BAD_ARGS
;
4577 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4578 inst
.error
= BAD_PC
;
4584 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4585 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4586 Error if any register is R15. */
4594 skip_whitespace (str
);
4596 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4597 || skip_past_comma (& str
) == FAIL
4598 || (rm
= reg_required_here (& str
, 0)) == FAIL
4599 || skip_past_comma (& str
) == FAIL
4600 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4601 inst
.error
= BAD_ARGS
;
4603 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4604 inst
.error
= BAD_PC
;
4610 /* ARM V5E (el Segundo)
4611 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4612 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4614 These are equivalent to the XScale instructions MAR and MRA,
4615 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4617 Result unpredicatable if Rd or Rn is R15. */
4625 skip_whitespace (str
);
4627 if (co_proc_number (& str
) == FAIL
)
4630 inst
.error
= BAD_ARGS
;
4634 if (skip_past_comma (& str
) == FAIL
4635 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4638 inst
.error
= BAD_ARGS
;
4642 if (skip_past_comma (& str
) == FAIL
4643 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4646 inst
.error
= BAD_ARGS
;
4650 if (skip_past_comma (& str
) == FAIL
4651 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4654 inst
.error
= BAD_ARGS
;
4658 /* Unpredictable result if rd or rn is R15. */
4659 if (rd
== REG_PC
|| rn
== REG_PC
)
4661 (_("Warning: instruction unpredictable when using r15"));
4663 if (skip_past_comma (& str
) == FAIL
4664 || cp_reg_required_here (& str
, 0) == FAIL
)
4667 inst
.error
= BAD_ARGS
;
4674 /* ARM V5 count-leading-zeroes instruction (argument parse)
4675 CLZ{<cond>} <Rd>, <Rm>
4676 Condition defaults to COND_ALWAYS.
4677 Error if Rd or Rm are R15. */
4685 skip_whitespace (str
);
4687 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4688 || (skip_past_comma (& str
) == FAIL
)
4689 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4690 inst
.error
= BAD_ARGS
;
4692 else if (rd
== REG_PC
|| rm
== REG_PC
)
4693 inst
.error
= BAD_PC
;
4699 /* ARM V5 (argument parse)
4700 LDC2{L} <coproc>, <CRd>, <addressing mode>
4701 STC2{L} <coproc>, <CRd>, <addressing mode>
4702 Instruction is not conditional, and has 0xf in the condition field.
4703 Otherwise, it's the same as LDC/STC. */
4709 skip_whitespace (str
);
4711 if (co_proc_number (& str
) == FAIL
)
4714 inst
.error
= BAD_ARGS
;
4716 else if (skip_past_comma (& str
) == FAIL
4717 || cp_reg_required_here (& str
, 12) == FAIL
)
4720 inst
.error
= BAD_ARGS
;
4722 else if (skip_past_comma (& str
) == FAIL
4723 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4726 inst
.error
= BAD_ARGS
;
4732 /* ARM V5 (argument parse)
4733 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4734 Instruction is not conditional, and has 0xf in the condition field.
4735 Otherwise, it's the same as CDP. */
4741 skip_whitespace (str
);
4743 if (co_proc_number (& str
) == FAIL
)
4746 inst
.error
= BAD_ARGS
;
4750 if (skip_past_comma (& str
) == FAIL
4751 || cp_opc_expr (& str
, 20,4) == FAIL
)
4754 inst
.error
= BAD_ARGS
;
4758 if (skip_past_comma (& str
) == FAIL
4759 || cp_reg_required_here (& str
, 12) == FAIL
)
4762 inst
.error
= BAD_ARGS
;
4766 if (skip_past_comma (& str
) == FAIL
4767 || cp_reg_required_here (& str
, 16) == FAIL
)
4770 inst
.error
= BAD_ARGS
;
4774 if (skip_past_comma (& str
) == FAIL
4775 || cp_reg_required_here (& str
, 0) == FAIL
)
4778 inst
.error
= BAD_ARGS
;
4782 if (skip_past_comma (& str
) == SUCCESS
)
4784 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4787 inst
.error
= BAD_ARGS
;
4795 /* ARM V5 (argument parse)
4796 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4797 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4798 Instruction is not conditional, and has 0xf in the condition field.
4799 Otherwise, it's the same as MCR/MRC. */
4805 skip_whitespace (str
);
4807 if (co_proc_number (& str
) == FAIL
)
4810 inst
.error
= BAD_ARGS
;
4814 if (skip_past_comma (& str
) == FAIL
4815 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4818 inst
.error
= BAD_ARGS
;
4822 if (skip_past_comma (& str
) == FAIL
4823 || reg_required_here (& str
, 12) == FAIL
)
4826 inst
.error
= BAD_ARGS
;
4830 if (skip_past_comma (& str
) == FAIL
4831 || cp_reg_required_here (& str
, 16) == FAIL
)
4834 inst
.error
= BAD_ARGS
;
4838 if (skip_past_comma (& str
) == FAIL
4839 || cp_reg_required_here (& str
, 0) == FAIL
)
4842 inst
.error
= BAD_ARGS
;
4846 if (skip_past_comma (& str
) == SUCCESS
)
4848 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4851 inst
.error
= BAD_ARGS
;
4859 /* ARM v5TEJ. Jump to Jazelle code. */
4866 skip_whitespace (str
);
4868 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4870 inst
.error
= BAD_ARGS
;
4874 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4876 as_tsktsk (_("use of r15 in bxj is not really useful"));
4881 /* ARM V6 umaal (argument parse). */
4888 int rdlo
, rdhi
, rm
, rs
;
4890 skip_whitespace (str
);
4891 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4892 || skip_past_comma (& str
) == FAIL
4893 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4894 || skip_past_comma (& str
) == FAIL
4895 || (rm
= reg_required_here (& str
, 0)) == FAIL
4896 || skip_past_comma (& str
) == FAIL
4897 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4899 inst
.error
= BAD_ARGS
;
4903 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4905 inst
.error
= BAD_PC
;
4912 /* ARM V6 strex (argument parse). */
4920 /* Parse Rd, Rm,. */
4921 skip_whitespace (str
);
4922 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4923 || skip_past_comma (& str
) == FAIL
4924 || (rm
= reg_required_here (& str
, 0)) == FAIL
4925 || skip_past_comma (& str
) == FAIL
)
4927 inst
.error
= BAD_ARGS
;
4930 if (rd
== REG_PC
|| rm
== REG_PC
)
4932 inst
.error
= BAD_PC
;
4937 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4941 /* Skip past '['. */
4942 if ((strlen (str
) >= 1)
4943 && strncmp (str
, "[", 1) == 0)
4945 skip_whitespace (str
);
4948 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4950 inst
.error
= BAD_ARGS
;
4953 else if (rn
== REG_PC
)
4955 inst
.error
= BAD_PC
;
4960 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4963 skip_whitespace (str
);
4965 /* Skip past ']'. */
4966 if ((strlen (str
) >= 1)
4967 && strncmp (str
, "]", 1) == 0)
4973 /* ARM V6 ssat (argument parse). */
4979 do_sat (&str
, /*bias=*/-1);
4983 /* ARM V6 usat (argument parse). */
4989 do_sat (&str
, /*bias=*/0);
5001 skip_whitespace (*str
);
5003 /* Parse <Rd>, field. */
5004 if ((rd
= reg_required_here (str
, 12)) == FAIL
5005 || skip_past_comma (str
) == FAIL
)
5007 inst
.error
= BAD_ARGS
;
5012 inst
.error
= BAD_PC
;
5016 /* Parse #<immed>, field. */
5017 if (is_immediate_prefix (**str
))
5021 inst
.error
= _("immediate expression expected");
5024 if (my_get_expression (&expr
, str
))
5026 inst
.error
= _("bad expression");
5029 if (expr
.X_op
!= O_constant
)
5031 inst
.error
= _("constant expression expected");
5034 if (expr
.X_add_number
+ bias
< 0
5035 || expr
.X_add_number
+ bias
> 31)
5037 inst
.error
= _("immediate value out of range");
5040 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5041 if (skip_past_comma (str
) == FAIL
)
5043 inst
.error
= BAD_ARGS
;
5047 /* Parse <Rm> field. */
5048 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5050 inst
.error
= BAD_ARGS
;
5055 inst
.error
= BAD_PC
;
5059 if (skip_past_comma (str
) == SUCCESS
)
5060 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
5063 /* ARM V6 ssat16 (argument parse). */
5069 do_sat16 (&str
, /*bias=*/-1);
5077 do_sat16 (&str
, /*bias=*/0);
5082 do_sat16 (str
, bias
)
5089 skip_whitespace (*str
);
5091 /* Parse the <Rd> field. */
5092 if ((rd
= reg_required_here (str
, 12)) == FAIL
5093 || skip_past_comma (str
) == FAIL
)
5095 inst
.error
= BAD_ARGS
;
5100 inst
.error
= BAD_PC
;
5104 /* Parse #<immed>, field. */
5105 if (is_immediate_prefix (**str
))
5109 inst
.error
= _("immediate expression expected");
5112 if (my_get_expression (&expr
, str
))
5114 inst
.error
= _("bad expression");
5117 if (expr
.X_op
!= O_constant
)
5119 inst
.error
= _("constant expression expected");
5122 if (expr
.X_add_number
+ bias
< 0
5123 || expr
.X_add_number
+ bias
> 15)
5125 inst
.error
= _("immediate value out of range");
5128 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5129 if (skip_past_comma (str
) == FAIL
)
5131 inst
.error
= BAD_ARGS
;
5135 /* Parse <Rm> field. */
5136 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5138 inst
.error
= BAD_ARGS
;
5143 inst
.error
= BAD_PC
;
5148 /* ARM V6 srs (argument parse). */
5155 skip_whitespace (str
);
5156 exclam
= strchr (str
, '!');
5164 inst
.instruction
|= WRITE_BACK
;
5170 /* ARM V6 SMMUL (argument parse). */
5178 skip_whitespace (str
);
5179 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5180 || skip_past_comma (&str
) == FAIL
5181 || (rm
= reg_required_here (&str
, 0)) == FAIL
5182 || skip_past_comma (&str
) == FAIL
5183 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5185 inst
.error
= BAD_ARGS
;
5193 inst
.error
= BAD_PC
;
5201 /* ARM V6 SMLALD (argument parse). */
5207 int rdlo
, rdhi
, rm
, rs
;
5208 skip_whitespace (str
);
5209 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5210 || skip_past_comma (&str
) == FAIL
5211 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5212 || skip_past_comma (&str
) == FAIL
5213 || (rm
= reg_required_here (&str
, 0)) == FAIL
5214 || skip_past_comma (&str
) == FAIL
5215 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5217 inst
.error
= BAD_ARGS
;
5226 inst
.error
= BAD_PC
;
5233 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5234 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5242 skip_whitespace (str
);
5243 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5244 || skip_past_comma (&str
) == FAIL
5245 || (rm
= reg_required_here (&str
, 0)) == FAIL
5246 || skip_past_comma (&str
) == FAIL
5247 || (rs
= reg_required_here (&str
, 8)) == FAIL
5248 || skip_past_comma (&str
) == FAIL
5249 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5251 inst
.error
= BAD_ARGS
;
5260 inst
.error
= BAD_PC
;
5267 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5268 preserving the other bits.
5270 setend <endian_specifier>, where <endian_specifier> is either
5277 if (do_endian_specifier (str
))
5278 inst
.instruction
|= 0x200;
5281 /* Returns true if the endian-specifier indicates big-endianness. */
5284 do_endian_specifier (str
)
5289 skip_whitespace (str
);
5290 if (strlen (str
) < 2)
5291 inst
.error
= _("missing endian specifier");
5292 else if (strncasecmp (str
, "BE", 2) == 0)
5297 else if (strncasecmp (str
, "LE", 2) == 0)
5300 inst
.error
= _("valid endian specifiers are be or le");
5309 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5310 Condition defaults to COND_ALWAYS.
5311 Error if any register uses R15. */
5319 int rotation_clear_mask
= 0xfffff3ff;
5320 int rotation_eight_mask
= 0x00000400;
5321 int rotation_sixteen_mask
= 0x00000800;
5322 int rotation_twenty_four_mask
= 0x00000c00;
5324 skip_whitespace (str
);
5325 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5326 || skip_past_comma (&str
) == FAIL
5327 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5329 inst
.error
= BAD_ARGS
;
5333 else if (rd
== REG_PC
|| rm
== REG_PC
)
5335 inst
.error
= BAD_PC
;
5339 /* Zero out the rotation field. */
5340 inst
.instruction
&= rotation_clear_mask
;
5342 /* Check for lack of optional rotation field. */
5343 if (skip_past_comma (&str
) == FAIL
)
5349 /* Move past 'ROR'. */
5350 skip_whitespace (str
);
5351 if (strncasecmp (str
, "ROR", 3) == 0)
5355 inst
.error
= _("missing rotation field after comma");
5359 /* Get the immediate constant. */
5360 skip_whitespace (str
);
5361 if (is_immediate_prefix (* str
))
5365 inst
.error
= _("immediate expression expected");
5369 if (my_get_expression (&expr
, &str
))
5371 inst
.error
= _("bad expression");
5375 if (expr
.X_op
!= O_constant
)
5377 inst
.error
= _("constant expression expected");
5381 switch (expr
.X_add_number
)
5384 /* Rotation field has already been zeroed. */
5387 inst
.instruction
|= rotation_eight_mask
;
5391 inst
.instruction
|= rotation_sixteen_mask
;
5395 inst
.instruction
|= rotation_twenty_four_mask
;
5399 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5407 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5408 extends it to 32-bits, and adds the result to a value in another
5409 register. You can specify a rotation by 0, 8, 16, or 24 bits
5410 before extracting the 16-bit value.
5411 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5412 Condition defaults to COND_ALWAYS.
5413 Error if any register uses R15. */
5421 int rotation_clear_mask
= 0xfffff3ff;
5422 int rotation_eight_mask
= 0x00000400;
5423 int rotation_sixteen_mask
= 0x00000800;
5424 int rotation_twenty_four_mask
= 0x00000c00;
5426 skip_whitespace (str
);
5427 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5428 || skip_past_comma (&str
) == FAIL
5429 || (rn
= reg_required_here (&str
, 16)) == FAIL
5430 || skip_past_comma (&str
) == FAIL
5431 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5433 inst
.error
= BAD_ARGS
;
5437 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5439 inst
.error
= BAD_PC
;
5443 /* Zero out the rotation field. */
5444 inst
.instruction
&= rotation_clear_mask
;
5446 /* Check for lack of optional rotation field. */
5447 if (skip_past_comma (&str
) == FAIL
)
5453 /* Move past 'ROR'. */
5454 skip_whitespace (str
);
5455 if (strncasecmp (str
, "ROR", 3) == 0)
5459 inst
.error
= _("missing rotation field after comma");
5463 /* Get the immediate constant. */
5464 skip_whitespace (str
);
5465 if (is_immediate_prefix (* str
))
5469 inst
.error
= _("immediate expression expected");
5473 if (my_get_expression (&expr
, &str
))
5475 inst
.error
= _("bad expression");
5479 if (expr
.X_op
!= O_constant
)
5481 inst
.error
= _("constant expression expected");
5485 switch (expr
.X_add_number
)
5488 /* Rotation field has already been zeroed. */
5492 inst
.instruction
|= rotation_eight_mask
;
5496 inst
.instruction
|= rotation_sixteen_mask
;
5500 inst
.instruction
|= rotation_twenty_four_mask
;
5504 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5513 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5514 word at the specified address and the following word
5516 Unconditionally executed.
5526 skip_whitespace (str
);
5528 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5533 inst
.error
= BAD_PC
;
5537 skip_whitespace (str
);
5541 inst
.instruction
|= WRITE_BACK
;
5547 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5548 register (argument parse).
5550 Condition defaults to COND_ALWAYS.
5551 Error if Rd or Rm are R15. */
5559 skip_whitespace (str
);
5561 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5562 || skip_past_comma (&str
) == FAIL
5563 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5564 inst
.error
= BAD_ARGS
;
5566 else if (rd
== REG_PC
|| rm
== REG_PC
)
5567 inst
.error
= BAD_PC
;
5573 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5574 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5575 Condition defaults to COND_ALWAYS.
5576 Error if Rd, Rn or Rm are R15. */
5584 skip_whitespace (str
);
5586 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5587 || skip_past_comma (&str
) == FAIL
5588 || (rn
= reg_required_here (&str
, 16)) == FAIL
5589 || skip_past_comma (&str
) == FAIL
5590 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5591 inst
.error
= BAD_ARGS
;
5593 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5594 inst
.error
= BAD_PC
;
5600 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5601 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5602 Condition defaults to COND_ALWAYS.
5603 Error if Rd, Rn or Rm are R15. */
5609 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5612 /* ARM V6 PKHTB (Argument Parse). */
5618 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5622 do_pkh_core (str
, shift
)
5628 skip_whitespace (str
);
5629 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5630 || (skip_past_comma (&str
) == FAIL
)
5631 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5632 || (skip_past_comma (&str
) == FAIL
)
5633 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5635 inst
.error
= BAD_ARGS
;
5639 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5641 inst
.error
= BAD_PC
;
5645 /* Check for optional shift immediate constant. */
5646 if (skip_past_comma (&str
) == FAIL
)
5648 if (shift
== SHIFT_ASR_IMMEDIATE
)
5650 /* If the shift specifier is ommited, turn the instruction
5651 into pkhbt rd, rm, rn. First, switch the instruction
5652 code, and clear the rn and rm fields. */
5653 inst
.instruction
&= 0xfff0f010;
5654 /* Now, re-encode the registers. */
5655 inst
.instruction
|= (rm
<< 16) | rn
;
5660 decode_shift (&str
, shift
);
5663 /* ARM V6 Load Register Exclusive instruction (argument parse).
5664 LDREX{<cond>} <Rd, [<Rn>]
5665 Condition defaults to COND_ALWAYS.
5666 Error if Rd or Rn are R15.
5667 See ARMARMv6 A4.1.27: LDREX. */
5676 skip_whitespace (str
);
5679 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5680 || (skip_past_comma (&str
) == FAIL
))
5682 inst
.error
= BAD_ARGS
;
5685 else if (rd
== REG_PC
)
5687 inst
.error
= BAD_PC
;
5690 skip_whitespace (str
);
5692 /* Skip past '['. */
5693 if ((strlen (str
) >= 1)
5694 &&strncmp (str
, "[", 1) == 0)
5696 skip_whitespace (str
);
5699 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5701 inst
.error
= BAD_ARGS
;
5704 else if (rn
== REG_PC
)
5706 inst
.error
= BAD_PC
;
5709 skip_whitespace (str
);
5711 /* Skip past ']'. */
5712 if ((strlen (str
) >= 1)
5713 && strncmp (str
, "]", 1) == 0)
5719 /* ARM V6 change processor state instruction (argument parse)
5720 CPS, CPSIE, CSPID . */
5734 do_cps_flags (&str
, /*thumb_p=*/0);
5736 if (skip_past_comma (&str
) == SUCCESS
)
5738 skip_whitespace (str
);
5750 skip_whitespace (*str
);
5752 if (! is_immediate_prefix (**str
))
5754 inst
.error
= _("immediate expression expected");
5758 (*str
)++; /* Strip off the immediate signifier. */
5759 if (my_get_expression (&expr
, str
))
5761 inst
.error
= _("bad expression");
5765 if (expr
.X_op
!= O_constant
)
5767 inst
.error
= _("constant expression expected");
5771 /* The mode is a 5 bit field. Valid values are 0-31. */
5772 if (((unsigned) expr
.X_add_number
) > 31
5773 || (inst
.reloc
.exp
.X_add_number
) < 0)
5775 inst
.error
= _("invalid constant");
5779 inst
.instruction
|= expr
.X_add_number
;
5783 do_cps_flags (str
, thumb_p
)
5789 unsigned long arm_value
;
5790 unsigned long thumb_value
;
5792 static struct cps_flag flag_table
[] = {
5800 skip_whitespace (*str
);
5802 /* Get the a, f and i flags. */
5803 while (**str
&& **str
!= ',')
5806 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5807 for (p
= flag_table
; p
< q
; ++p
)
5808 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5810 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5816 inst
.error
= _("unrecognized flag");
5822 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5825 /* THUMB V5 breakpoint instruction (argument parse)
5833 unsigned long number
;
5835 skip_whitespace (str
);
5837 /* Allow optional leading '#'. */
5838 if (is_immediate_prefix (*str
))
5841 memset (& expr
, '\0', sizeof (expr
));
5842 if (my_get_expression (& expr
, & str
)
5843 || (expr
.X_op
!= O_constant
5844 /* As a convenience we allow 'bkpt' without an operand. */
5845 && expr
.X_op
!= O_absent
))
5847 inst
.error
= _("bad expression");
5851 number
= expr
.X_add_number
;
5853 /* Check it fits an 8 bit unsigned. */
5854 if (number
!= (number
& 0xff))
5856 inst
.error
= _("immediate value out of range");
5860 inst
.instruction
|= number
;
5865 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5866 Expects inst.instruction is set for BLX(1).
5867 Note: this is cloned from do_branch, and the reloc changed to be a
5868 new one that can cope with setting one extra bit (the H bit). */
5874 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5881 /* ScottB: February 5, 1998 */
5882 /* Check to see of PLT32 reloc required for the instruction. */
5884 /* arm_parse_reloc() works on input_line_pointer.
5885 We actually want to parse the operands to the branch instruction
5886 passed in 'str'. Save the input pointer and restore it later. */
5887 save_in
= input_line_pointer
;
5888 input_line_pointer
= str
;
5890 if (inst
.reloc
.exp
.X_op
== O_symbol
5892 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5894 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5895 inst
.reloc
.pc_rel
= 0;
5896 /* Modify str to point to after parsed operands, otherwise
5897 end_of_line() will complain about the (PLT) left in str. */
5898 str
= input_line_pointer
;
5902 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5903 inst
.reloc
.pc_rel
= 1;
5906 input_line_pointer
= save_in
;
5909 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5910 inst
.reloc
.pc_rel
= 1;
5911 #endif /* OBJ_ELF */
5916 /* ARM V5 branch-link-exchange instruction (argument parse)
5917 BLX <target_addr> ie BLX(1)
5918 BLX{<condition>} <Rm> ie BLX(2)
5919 Unfortunately, there are two different opcodes for this mnemonic.
5920 So, the insns[].value is not used, and the code here zaps values
5921 into inst.instruction.
5922 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5931 skip_whitespace (mystr
);
5932 rm
= reg_required_here (& mystr
, 0);
5934 /* The above may set inst.error. Ignore his opinion. */
5939 /* Arg is a register.
5940 Use the condition code our caller put in inst.instruction.
5941 Pass ourselves off as a BX with a funny opcode. */
5942 inst
.instruction
|= 0x012fff30;
5947 /* This must be is BLX <target address>, no condition allowed. */
5948 if (inst
.instruction
!= COND_ALWAYS
)
5950 inst
.error
= BAD_COND
;
5954 inst
.instruction
= 0xfafffffe;
5956 /* Process like a B/BL, but with a different reloc.
5957 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5962 /* ARM V5 Thumb BLX (argument parse)
5963 BLX <target_addr> which is BLX(1)
5964 BLX <Rm> which is BLX(2)
5965 Unfortunately, there are two different opcodes for this mnemonic.
5966 So, the tinsns[].value is not used, and the code here zaps values
5967 into inst.instruction. */
5976 skip_whitespace (mystr
);
5977 inst
.instruction
= 0x4780;
5979 /* Note that this call is to the ARM register recognizer. BLX(2)
5980 uses the ARM register space, not the Thumb one, so a call to
5981 thumb_reg() would be wrong. */
5982 rm
= reg_required_here (& mystr
, 3);
5987 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5992 /* No ARM register. This must be BLX(1). Change the .instruction. */
5993 inst
.instruction
= 0xf7ffeffe;
5996 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5999 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
6000 inst
.reloc
.pc_rel
= 1;
6003 end_of_line (mystr
);
6006 /* ARM V5 breakpoint instruction (argument parse)
6007 BKPT <16 bit unsigned immediate>
6008 Instruction is not conditional.
6009 The bit pattern given in insns[] has the COND_ALWAYS condition,
6010 and it is an error if the caller tried to override that. */
6017 unsigned long number
;
6019 skip_whitespace (str
);
6021 /* Allow optional leading '#'. */
6022 if (is_immediate_prefix (* str
))
6025 memset (& expr
, '\0', sizeof (expr
));
6027 if (my_get_expression (& expr
, & str
)
6028 || (expr
.X_op
!= O_constant
6029 /* As a convenience we allow 'bkpt' without an operand. */
6030 && expr
.X_op
!= O_absent
))
6032 inst
.error
= _("bad expression");
6036 number
= expr
.X_add_number
;
6038 /* Check it fits a 16 bit unsigned. */
6039 if (number
!= (number
& 0xffff))
6041 inst
.error
= _("immediate value out of range");
6045 /* Top 12 of 16 bits to bits 19:8. */
6046 inst
.instruction
|= (number
& 0xfff0) << 4;
6048 /* Bottom 4 of 16 bits to bits 3:0. */
6049 inst
.instruction
|= number
& 0xf;
6054 /* THUMB CPS instruction (argument parse). */
6060 do_cps_flags (&str
, /*thumb_p=*/1);
6064 /* THUMB CPY instruction (argument parse). */
6070 thumb_mov_compare (str
, THUMB_CPY
);
6073 /* THUMB SETEND instruction (argument parse). */
6079 if (do_endian_specifier (str
))
6080 inst
.instruction
|= 0x8;
6083 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6085 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6087 static unsigned long
6088 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6090 enum iwmmxt_insn_type insn_type
;
6094 const char * inst_error
;
6096 unsigned long number
;
6098 inst_error
= inst
.error
;
6100 inst
.error
= BAD_ARGS
;
6101 skip_whitespace (str
);
6106 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6111 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6116 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6117 || skip_past_comma (&str
) == FAIL
6118 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6123 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6124 || skip_past_comma (&str
) == FAIL
6125 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6126 || skip_past_comma (&str
) == FAIL
6127 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6132 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6133 || skip_past_comma (&str
) == FAIL
6134 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6135 || skip_past_comma (&str
) == FAIL
6136 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6141 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6142 || skip_past_comma (&str
) == FAIL
6143 || reg_required_here (&str
, 12) == FAIL
))
6148 if ((reg_required_here (&str
, 12) == FAIL
6149 || skip_past_comma (&str
) == FAIL
6150 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6155 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6156 || skip_past_comma (&str
) == FAIL
6157 || reg_required_here (&str
, 0) == FAIL
6158 || skip_past_comma (&str
) == FAIL
6159 || reg_required_here (&str
, 12) == FAIL
))
6164 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6165 || skip_past_comma (&str
) == FAIL
6166 || reg_required_here (&str
, 12) == FAIL
6167 || skip_past_comma (&str
) == FAIL
6168 || reg_required_here (&str
, 16) == FAIL
))
6173 if ((reg_required_here (&str
, 12) == FAIL
6174 || skip_past_comma (&str
) == FAIL
6175 || reg_required_here (&str
, 16) == FAIL
6176 || skip_past_comma (&str
) == FAIL
6177 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6182 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6183 || skip_past_comma (&str
) == FAIL
6184 || reg_required_here (&str
, 12) == FAIL
))
6189 if ((reg_required_here (&str
, 12) == FAIL
6190 || skip_past_comma (&str
) == FAIL
6191 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6196 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6197 || skip_past_comma (&str
) == FAIL
6198 || reg_required_here (&str
, 12) == FAIL
6199 || skip_past_comma (&str
) == FAIL
))
6204 if ((reg_required_here (&str
, 12) == FAIL
6205 || skip_past_comma (&str
) == FAIL
))
6210 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6211 || skip_past_comma (&str
) == FAIL
6212 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6213 || skip_past_comma (&str
) == FAIL
6214 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6215 || skip_past_comma (&str
) == FAIL
))
6220 if ((reg_required_here (&str
, 12) == FAIL
6221 || skip_past_comma (&str
) == FAIL
6222 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6223 || skip_past_comma (&str
) == FAIL
))
6228 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6229 || skip_past_comma (&str
) == FAIL
6230 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6231 || skip_past_comma (&str
) == FAIL
))
6236 if (immediate_size
== 0)
6239 inst
.error
= inst_error
;
6244 skip_whitespace (str
);
6246 /* Allow optional leading '#'. */
6247 if (is_immediate_prefix (* str
))
6250 memset (& expr
, '\0', sizeof (expr
));
6252 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6254 inst
.error
= _("bad or missing expression");
6258 number
= expr
.X_add_number
;
6260 if (number
!= (number
& immediate_size
))
6262 inst
.error
= _("immediate value out of range");
6266 inst
.error
= inst_error
;
6272 do_iwmmxt_byte_addr (str
)
6275 int op
= (inst
.instruction
& 0x300) >> 8;
6278 inst
.instruction
&= ~0x300;
6279 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6281 skip_whitespace (str
);
6283 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6284 || skip_past_comma (& str
) == FAIL
6285 || cp_byte_address_required_here (&str
) == FAIL
)
6288 inst
.error
= BAD_ARGS
;
6293 if (wc_register (reg
))
6295 as_bad (_("non-word size not supported with control register"));
6296 inst
.instruction
|= 0xf0000100;
6297 inst
.instruction
&= ~0x00400000;
6302 do_iwmmxt_tandc (str
)
6307 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6309 if (reg
!= REG_PC
&& !inst
.error
)
6310 inst
.error
= _("only r15 allowed here");
6314 do_iwmmxt_tbcst (str
)
6317 check_iwmmxt_insn (str
, check_tbcst
, 0);
6321 do_iwmmxt_textrc (str
)
6324 unsigned long number
;
6326 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6329 inst
.instruction
|= number
& 0x7;
6333 do_iwmmxt_textrm (str
)
6336 unsigned long number
;
6338 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6341 inst
.instruction
|= number
& 0x7;
6345 do_iwmmxt_tinsr (str
)
6348 unsigned long number
;
6350 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6353 inst
.instruction
|= number
& 0x7;
6357 do_iwmmxt_tmcr (str
)
6360 check_iwmmxt_insn (str
, check_tmcr
, 0);
6364 do_iwmmxt_tmcrr (str
)
6367 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6371 do_iwmmxt_tmia (str
)
6374 check_iwmmxt_insn (str
, check_tmia
, 0);
6378 do_iwmmxt_tmovmsk (str
)
6381 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6385 do_iwmmxt_tmrc (str
)
6388 check_iwmmxt_insn (str
, check_tmrc
, 0);
6392 do_iwmmxt_tmrrc (str
)
6395 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6399 do_iwmmxt_torc (str
)
6402 check_iwmmxt_insn (str
, check_rd
, 0);
6406 do_iwmmxt_waligni (str
)
6409 unsigned long number
;
6411 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6414 inst
.instruction
|= ((number
& 0x7) << 20);
6418 do_iwmmxt_wmov (str
)
6421 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6424 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6428 do_iwmmxt_word_addr (str
)
6431 int op
= (inst
.instruction
& 0x300) >> 8;
6434 inst
.instruction
&= ~0x300;
6435 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6437 skip_whitespace (str
);
6439 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6440 || skip_past_comma (& str
) == FAIL
6441 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6444 inst
.error
= BAD_ARGS
;
6449 if (wc_register (reg
))
6451 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6452 as_bad (_("conditional execution not supported with control register"));
6454 as_bad (_("non-word size not supported with control register"));
6455 inst
.instruction
|= 0xf0000100;
6456 inst
.instruction
&= ~0x00400000;
6461 do_iwmmxt_wrwr (str
)
6464 check_iwmmxt_insn (str
, check_wrwr
, 0);
6468 do_iwmmxt_wrwrwcg (str
)
6471 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6475 do_iwmmxt_wrwrwr (str
)
6478 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6482 do_iwmmxt_wshufh (str
)
6485 unsigned long number
;
6487 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6490 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6494 do_iwmmxt_wzero (str
)
6497 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6500 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6503 /* Xscale multiply-accumulate (argument parse)
6506 MIAxycc acc0,Rm,Rs. */
6515 if (accum0_required_here (& str
) == FAIL
)
6516 inst
.error
= ERR_NO_ACCUM
;
6518 else if (skip_past_comma (& str
) == FAIL
6519 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6520 inst
.error
= BAD_ARGS
;
6522 else if (skip_past_comma (& str
) == FAIL
6523 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6524 inst
.error
= BAD_ARGS
;
6526 /* inst.instruction has now been zapped with both rm and rs. */
6527 else if (rm
== REG_PC
|| rs
== REG_PC
)
6528 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6534 /* Xscale move-accumulator-register (argument parse)
6536 MARcc acc0,RdLo,RdHi. */
6544 if (accum0_required_here (& str
) == FAIL
)
6545 inst
.error
= ERR_NO_ACCUM
;
6547 else if (skip_past_comma (& str
) == FAIL
6548 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6549 inst
.error
= BAD_ARGS
;
6551 else if (skip_past_comma (& str
) == FAIL
6552 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6553 inst
.error
= BAD_ARGS
;
6555 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6556 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6557 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6563 /* Xscale move-register-accumulator (argument parse)
6565 MRAcc RdLo,RdHi,acc0. */
6574 skip_whitespace (str
);
6576 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6577 inst
.error
= BAD_ARGS
;
6579 else if (skip_past_comma (& str
) == FAIL
6580 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6581 inst
.error
= BAD_ARGS
;
6583 else if (skip_past_comma (& str
) == FAIL
6584 || accum0_required_here (& str
) == FAIL
)
6585 inst
.error
= ERR_NO_ACCUM
;
6587 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6588 else if (rdlo
== rdhi
)
6589 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6591 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6592 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6597 /* ARMv5TE: Preload-Cache
6601 Syntactically, like LDR with B=1, W=0, L=1. */
6609 skip_whitespace (str
);
6613 inst
.error
= _("'[' expected after PLD mnemonic");
6618 skip_whitespace (str
);
6620 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6623 skip_whitespace (str
);
6629 skip_whitespace (str
);
6631 /* Post-indexed addressing is not allowed with PLD. */
6632 if (skip_past_comma (&str
) == SUCCESS
)
6635 = _("post-indexed expression used in preload instruction");
6638 else if (*str
== '!') /* [Rn]! */
6640 inst
.error
= _("writeback used in preload instruction");
6644 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6646 else /* [Rn, ...] */
6648 if (skip_past_comma (& str
) == FAIL
)
6650 inst
.error
= _("pre-indexed expression expected");
6654 if (ldst_extend (&str
) == FAIL
)
6657 skip_whitespace (str
);
6661 inst
.error
= _("missing ]");
6666 skip_whitespace (str
);
6668 if (* str
== '!') /* [Rn]! */
6670 inst
.error
= _("writeback used in preload instruction");
6674 inst
.instruction
|= PRE_INDEX
;
6680 /* ARMv5TE load-consecutive (argument parse)
6693 skip_whitespace (str
);
6695 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6697 inst
.error
= BAD_ARGS
;
6701 if (skip_past_comma (& str
) == FAIL
6702 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6705 inst
.error
= BAD_ARGS
;
6709 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6710 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6712 inst
.error
= _("destination register must be even");
6718 inst
.error
= _("r14 not allowed here");
6722 if (((rd
== rn
) || (rd
+ 1 == rn
))
6723 && ((inst
.instruction
& WRITE_BACK
)
6724 || (!(inst
.instruction
& PRE_INDEX
))))
6725 as_warn (_("pre/post-indexing used when modified address register is destination"));
6727 /* For an index-register load, the index register must not overlap the
6728 destination (even if not write-back). */
6729 if ((inst
.instruction
& V4_STR_BIT
) == 0
6730 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6732 int rm
= inst
.instruction
& 0x0000000f;
6734 if (rm
== rd
|| (rm
== rd
+ 1))
6735 as_warn (_("ldrd destination registers must not overlap index register"));
6741 /* Returns the index into fp_values of a floating point number,
6742 or -1 if not in the table. */
6745 my_get_float_expression (str
)
6748 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6754 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6756 /* Look for a raw floating point number. */
6757 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6758 && is_end_of_line
[(unsigned char) *save_in
])
6760 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6762 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6764 if (words
[j
] != fp_values
[i
][j
])
6768 if (j
== MAX_LITTLENUMS
)
6776 /* Try and parse a more complex expression, this will probably fail
6777 unless the code uses a floating point prefix (eg "0f"). */
6778 save_in
= input_line_pointer
;
6779 input_line_pointer
= *str
;
6780 if (expression (&exp
) == absolute_section
6781 && exp
.X_op
== O_big
6782 && exp
.X_add_number
< 0)
6784 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6786 if (gen_to_words (words
, 5, (long) 15) == 0)
6788 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6790 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6792 if (words
[j
] != fp_values
[i
][j
])
6796 if (j
== MAX_LITTLENUMS
)
6798 *str
= input_line_pointer
;
6799 input_line_pointer
= save_in
;
6806 *str
= input_line_pointer
;
6807 input_line_pointer
= save_in
;
6811 /* Return TRUE if anything in the expression is a bignum. */
6814 walk_no_bignums (sp
)
6817 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6820 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6822 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6823 || (symbol_get_value_expression (sp
)->X_op_symbol
6824 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6830 static int in_my_get_expression
= 0;
6833 my_get_expression (ep
, str
)
6840 save_in
= input_line_pointer
;
6841 input_line_pointer
= *str
;
6842 in_my_get_expression
= 1;
6843 seg
= expression (ep
);
6844 in_my_get_expression
= 0;
6846 if (ep
->X_op
== O_illegal
)
6848 /* We found a bad expression in md_operand(). */
6849 *str
= input_line_pointer
;
6850 input_line_pointer
= save_in
;
6855 if (seg
!= absolute_section
6856 && seg
!= text_section
6857 && seg
!= data_section
6858 && seg
!= bss_section
6859 && seg
!= undefined_section
)
6861 inst
.error
= _("bad_segment");
6862 *str
= input_line_pointer
;
6863 input_line_pointer
= save_in
;
6868 /* Get rid of any bignums now, so that we don't generate an error for which
6869 we can't establish a line number later on. Big numbers are never valid
6870 in instructions, which is where this routine is always called. */
6871 if (ep
->X_op
== O_big
6872 || (ep
->X_add_symbol
6873 && (walk_no_bignums (ep
->X_add_symbol
)
6875 && walk_no_bignums (ep
->X_op_symbol
)))))
6877 inst
.error
= _("invalid constant");
6878 *str
= input_line_pointer
;
6879 input_line_pointer
= save_in
;
6883 *str
= input_line_pointer
;
6884 input_line_pointer
= save_in
;
6888 /* We handle all bad expressions here, so that we can report the faulty
6889 instruction in the error message. */
6894 if (in_my_get_expression
)
6896 expr
->X_op
= O_illegal
;
6897 if (inst
.error
== NULL
)
6898 inst
.error
= _("bad expression");
6902 /* KIND indicates what kind of shifts are accepted. */
6905 decode_shift (str
, kind
)
6909 const struct asm_shift_name
* shift
;
6913 skip_whitespace (* str
);
6915 for (p
= * str
; ISALPHA (* p
); p
++)
6920 inst
.error
= _("shift expression expected");
6926 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6931 inst
.error
= _("shift expression expected");
6935 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6937 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6938 && shift
->properties
->index
!= SHIFT_LSL
6939 && shift
->properties
->index
!= SHIFT_ASR
)
6941 inst
.error
= _("'LSL' or 'ASR' required");
6944 else if (kind
== SHIFT_LSL_IMMEDIATE
6945 && shift
->properties
->index
!= SHIFT_LSL
)
6947 inst
.error
= _("'LSL' required");
6950 else if (kind
== SHIFT_ASR_IMMEDIATE
6951 && shift
->properties
->index
!= SHIFT_ASR
)
6953 inst
.error
= _("'ASR' required");
6957 if (shift
->properties
->index
== SHIFT_RRX
)
6960 inst
.instruction
|= shift
->properties
->bit_field
;
6964 skip_whitespace (p
);
6966 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6968 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6972 else if (! is_immediate_prefix (* p
))
6974 inst
.error
= (NO_SHIFT_RESTRICT
6975 ? _("shift requires register or #expression")
6976 : _("shift requires #expression"));
6984 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6987 /* Validate some simple #expressions. */
6988 if (inst
.reloc
.exp
.X_op
== O_constant
)
6990 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6992 /* Reject operations greater than 32. */
6994 /* Reject a shift of 0 unless the mode allows it. */
6995 || (num
== 0 && shift
->properties
->allows_0
== 0)
6996 /* Reject a shift of 32 unless the mode allows it. */
6997 || (num
== 32 && shift
->properties
->allows_32
== 0)
7000 /* As a special case we allow a shift of zero for
7001 modes that do not support it to be recoded as an
7002 logical shift left of zero (ie nothing). We warn
7003 about this though. */
7006 as_warn (_("shift of 0 ignored."));
7007 shift
= & shift_names
[0];
7008 assert (shift
->properties
->index
== SHIFT_LSL
);
7012 inst
.error
= _("invalid immediate shift");
7017 /* Shifts of 32 are encoded as 0, for those shifts that
7022 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
7026 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
7027 inst
.reloc
.pc_rel
= 0;
7028 inst
.instruction
|= shift
->properties
->bit_field
;
7035 /* Do those data_ops which can take a negative immediate constant
7036 by altering the instruction. A bit of a hack really.
7040 by inverting the second operand, and
7043 by negating the second operand. */
7046 negate_data_op (instruction
, value
)
7047 unsigned long * instruction
;
7048 unsigned long value
;
7051 unsigned long negated
, inverted
;
7053 negated
= validate_immediate (-value
);
7054 inverted
= validate_immediate (~value
);
7056 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
7059 /* First negates. */
7060 case OPCODE_SUB
: /* ADD <-> SUB */
7061 new_inst
= OPCODE_ADD
;
7066 new_inst
= OPCODE_SUB
;
7070 case OPCODE_CMP
: /* CMP <-> CMN */
7071 new_inst
= OPCODE_CMN
;
7076 new_inst
= OPCODE_CMP
;
7080 /* Now Inverted ops. */
7081 case OPCODE_MOV
: /* MOV <-> MVN */
7082 new_inst
= OPCODE_MVN
;
7087 new_inst
= OPCODE_MOV
;
7091 case OPCODE_AND
: /* AND <-> BIC */
7092 new_inst
= OPCODE_BIC
;
7097 new_inst
= OPCODE_AND
;
7101 case OPCODE_ADC
: /* ADC <-> SBC */
7102 new_inst
= OPCODE_SBC
;
7107 new_inst
= OPCODE_ADC
;
7111 /* We cannot do anything. */
7116 if (value
== (unsigned) FAIL
)
7119 *instruction
&= OPCODE_MASK
;
7120 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7131 skip_whitespace (* str
);
7133 if (reg_required_here (str
, 0) != FAIL
)
7135 if (skip_past_comma (str
) == SUCCESS
)
7136 /* Shift operation on register. */
7137 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7143 /* Immediate expression. */
7144 if (is_immediate_prefix (**str
))
7149 if (my_get_expression (&inst
.reloc
.exp
, str
))
7152 if (inst
.reloc
.exp
.X_add_symbol
)
7154 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7155 inst
.reloc
.pc_rel
= 0;
7159 if (skip_past_comma (str
) == SUCCESS
)
7161 /* #x, y -- ie explicit rotation by Y. */
7162 if (my_get_expression (&expr
, str
))
7165 if (expr
.X_op
!= O_constant
)
7167 inst
.error
= _("constant expression expected");
7171 /* Rotate must be a multiple of 2. */
7172 if (((unsigned) expr
.X_add_number
) > 30
7173 || (expr
.X_add_number
& 1) != 0
7174 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7176 inst
.error
= _("invalid constant");
7179 inst
.instruction
|= INST_IMMEDIATE
;
7180 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7181 inst
.instruction
|= expr
.X_add_number
<< 7;
7185 /* Implicit rotation, select a suitable one. */
7186 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7190 /* Can't be done. Perhaps the code reads something like
7191 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7192 if ((value
= negate_data_op (&inst
.instruction
,
7193 inst
.reloc
.exp
.X_add_number
))
7196 inst
.error
= _("invalid constant");
7201 inst
.instruction
|= value
;
7204 inst
.instruction
|= INST_IMMEDIATE
;
7209 inst
.error
= _("register or shift expression expected");
7218 skip_whitespace (* str
);
7220 if (fp_reg_required_here (str
, 0) != FAIL
)
7224 /* Immediate expression. */
7225 if (*((*str
)++) == '#')
7231 skip_whitespace (* str
);
7233 /* First try and match exact strings, this is to guarantee
7234 that some formats will work even for cross assembly. */
7236 for (i
= 0; fp_const
[i
]; i
++)
7238 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7242 *str
+= strlen (fp_const
[i
]);
7243 if (is_end_of_line
[(unsigned char) **str
])
7245 inst
.instruction
|= i
+ 8;
7252 /* Just because we didn't get a match doesn't mean that the
7253 constant isn't valid, just that it is in a format that we
7254 don't automatically recognize. Try parsing it with
7255 the standard expression routines. */
7256 if ((i
= my_get_float_expression (str
)) >= 0)
7258 inst
.instruction
|= i
+ 8;
7262 inst
.error
= _("invalid floating point immediate expression");
7266 _("floating point register or immediate expression expected");
7275 skip_whitespace (str
);
7277 if (reg_required_here (&str
, 12) == FAIL
7278 || skip_past_comma (&str
) == FAIL
7279 || reg_required_here (&str
, 16) == FAIL
7280 || skip_past_comma (&str
) == FAIL
7281 || data_op2 (&str
) == FAIL
)
7284 inst
.error
= BAD_ARGS
;
7295 /* This is a pseudo-op of the form "adr rd, label" to be converted
7296 into a relative address of the form "add rd, pc, #label-.-8". */
7297 skip_whitespace (str
);
7299 if (reg_required_here (&str
, 12) == FAIL
7300 || skip_past_comma (&str
) == FAIL
7301 || my_get_expression (&inst
.reloc
.exp
, &str
))
7304 inst
.error
= BAD_ARGS
;
7308 /* Frag hacking will turn this into a sub instruction if the offset turns
7309 out to be negative. */
7310 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7312 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7314 inst
.reloc
.pc_rel
= 1;
7323 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7324 into a relative address of the form:
7325 add rd, pc, #low(label-.-8)"
7326 add rd, rd, #high(label-.-8)" */
7328 skip_whitespace (str
);
7330 if (reg_required_here (&str
, 12) == FAIL
7331 || skip_past_comma (&str
) == FAIL
7332 || my_get_expression (&inst
.reloc
.exp
, &str
))
7335 inst
.error
= BAD_ARGS
;
7341 /* Frag hacking will turn this into a sub instruction if the offset turns
7342 out to be negative. */
7343 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7345 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7347 inst
.reloc
.pc_rel
= 1;
7348 inst
.size
= INSN_SIZE
* 2;
7355 skip_whitespace (str
);
7357 if (reg_required_here (&str
, 16) == FAIL
)
7360 inst
.error
= BAD_ARGS
;
7364 if (skip_past_comma (&str
) == FAIL
7365 || data_op2 (&str
) == FAIL
)
7368 inst
.error
= BAD_ARGS
;
7379 skip_whitespace (str
);
7381 if (reg_required_here (&str
, 12) == FAIL
)
7384 inst
.error
= BAD_ARGS
;
7388 if (skip_past_comma (&str
) == FAIL
7389 || data_op2 (&str
) == FAIL
)
7392 inst
.error
= BAD_ARGS
;
7410 if (my_get_expression (& inst
.reloc
.exp
, str
))
7413 if (inst
.reloc
.exp
.X_op
== O_constant
)
7415 int value
= inst
.reloc
.exp
.X_add_number
;
7417 if (value
< -4095 || value
> 4095)
7419 inst
.error
= _("address offset too large");
7429 inst
.instruction
|= add
| value
;
7433 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7434 inst
.reloc
.pc_rel
= 0;
7447 if (reg_required_here (str
, 0) == FAIL
)
7450 inst
.instruction
|= add
| OFFSET_REG
;
7451 if (skip_past_comma (str
) == SUCCESS
)
7452 return decode_shift (str
, SHIFT_IMMEDIATE
);
7466 skip_whitespace (str
);
7468 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7471 inst
.error
= BAD_ARGS
;
7475 if (skip_past_comma (&str
) == FAIL
)
7477 inst
.error
= _("address expected");
7487 skip_whitespace (str
);
7489 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7492 /* Conflicts can occur on stores as well as loads. */
7493 conflict_reg
= (conflict_reg
== reg
);
7495 skip_whitespace (str
);
7501 if (skip_past_comma (&str
) == SUCCESS
)
7503 /* [Rn],... (post inc) */
7504 if (ldst_extend (&str
) == FAIL
)
7507 as_warn (_("%s register same as write-back base"),
7508 ((inst
.instruction
& LOAD_BIT
)
7509 ? _("destination") : _("source")));
7514 skip_whitespace (str
);
7519 as_warn (_("%s register same as write-back base"),
7520 ((inst
.instruction
& LOAD_BIT
)
7521 ? _("destination") : _("source")));
7523 inst
.instruction
|= WRITE_BACK
;
7526 inst
.instruction
|= INDEX_UP
;
7533 if (skip_past_comma (&str
) == FAIL
)
7535 inst
.error
= _("pre-indexed expression expected");
7540 if (ldst_extend (&str
) == FAIL
)
7543 skip_whitespace (str
);
7547 inst
.error
= _("missing ]");
7551 skip_whitespace (str
);
7556 as_warn (_("%s register same as write-back base"),
7557 ((inst
.instruction
& LOAD_BIT
)
7558 ? _("destination") : _("source")));
7560 inst
.instruction
|= WRITE_BACK
;
7564 else if (*str
== '=')
7566 if ((inst
.instruction
& LOAD_BIT
) == 0)
7568 inst
.error
= _("invalid pseudo operation");
7572 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7575 skip_whitespace (str
);
7577 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7580 if (inst
.reloc
.exp
.X_op
!= O_constant
7581 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7583 inst
.error
= _("constant expression expected");
7587 if (inst
.reloc
.exp
.X_op
== O_constant
)
7589 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7593 /* This can be done with a mov instruction. */
7594 inst
.instruction
&= LITERAL_MASK
;
7595 inst
.instruction
|= (INST_IMMEDIATE
7596 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7597 inst
.instruction
|= value
& 0xfff;
7602 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7606 /* This can be done with a mvn instruction. */
7607 inst
.instruction
&= LITERAL_MASK
;
7608 inst
.instruction
|= (INST_IMMEDIATE
7609 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7610 inst
.instruction
|= value
& 0xfff;
7616 /* Insert into literal pool. */
7617 if (add_to_lit_pool () == FAIL
)
7620 inst
.error
= _("literal pool insertion failed");
7624 /* Change the instruction exp to point to the pool. */
7625 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7626 inst
.reloc
.pc_rel
= 1;
7627 inst
.instruction
|= (REG_PC
<< 16);
7632 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7635 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7637 /* PC rel adjust. */
7638 inst
.reloc
.exp
.X_add_number
-= 8;
7640 inst
.reloc
.pc_rel
= 1;
7641 inst
.instruction
|= (REG_PC
<< 16);
7645 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7655 skip_whitespace (str
);
7657 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7660 inst
.error
= BAD_ARGS
;
7664 if (skip_past_comma (& str
) == FAIL
)
7666 inst
.error
= _("address expected");
7676 skip_whitespace (str
);
7678 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7681 /* ldrt/strt always use post-indexed addressing, so if the base is
7682 the same as Rd, we warn. */
7683 if (conflict_reg
== reg
)
7684 as_warn (_("%s register same as write-back base"),
7685 ((inst
.instruction
& LOAD_BIT
)
7686 ? _("destination") : _("source")));
7688 skip_whitespace (str
);
7694 if (skip_past_comma (&str
) == SUCCESS
)
7696 /* [Rn],... (post inc) */
7697 if (ldst_extend (&str
) == FAIL
)
7703 skip_whitespace (str
);
7705 /* Skip a write-back '!'. */
7709 inst
.instruction
|= INDEX_UP
;
7714 inst
.error
= _("post-indexed expression expected");
7720 inst
.error
= _("post-indexed expression expected");
7728 ldst_extend_v4 (str
)
7738 if (my_get_expression (& inst
.reloc
.exp
, str
))
7741 if (inst
.reloc
.exp
.X_op
== O_constant
)
7743 int value
= inst
.reloc
.exp
.X_add_number
;
7745 if (value
< -255 || value
> 255)
7747 inst
.error
= _("address offset too large");
7757 /* Halfword and signextension instructions have the
7758 immediate value split across bits 11..8 and bits 3..0. */
7759 inst
.instruction
|= (add
| HWOFFSET_IMM
7760 | ((value
>> 4) << 8) | (value
& 0xF));
7764 inst
.instruction
|= HWOFFSET_IMM
;
7765 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7766 inst
.reloc
.pc_rel
= 0;
7779 if (reg_required_here (str
, 0) == FAIL
)
7782 inst
.instruction
|= add
;
7787 /* Halfword and signed-byte load/store operations. */
7796 skip_whitespace (str
);
7798 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7801 inst
.error
= BAD_ARGS
;
7805 if (skip_past_comma (& str
) == FAIL
)
7807 inst
.error
= _("address expected");
7817 skip_whitespace (str
);
7819 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7822 /* Conflicts can occur on stores as well as loads. */
7823 conflict_reg
= (conflict_reg
== reg
);
7825 skip_whitespace (str
);
7831 if (skip_past_comma (&str
) == SUCCESS
)
7833 /* [Rn],... (post inc) */
7834 if (ldst_extend_v4 (&str
) == FAIL
)
7837 as_warn (_("%s register same as write-back base"),
7838 ((inst
.instruction
& LOAD_BIT
)
7839 ? _("destination") : _("source")));
7844 inst
.instruction
|= HWOFFSET_IMM
;
7846 skip_whitespace (str
);
7851 as_warn (_("%s register same as write-back base"),
7852 ((inst
.instruction
& LOAD_BIT
)
7853 ? _("destination") : _("source")));
7855 inst
.instruction
|= WRITE_BACK
;
7858 inst
.instruction
|= INDEX_UP
;
7865 if (skip_past_comma (&str
) == FAIL
)
7867 inst
.error
= _("pre-indexed expression expected");
7872 if (ldst_extend_v4 (&str
) == FAIL
)
7875 skip_whitespace (str
);
7879 inst
.error
= _("missing ]");
7883 skip_whitespace (str
);
7888 as_warn (_("%s register same as write-back base"),
7889 ((inst
.instruction
& LOAD_BIT
)
7890 ? _("destination") : _("source")));
7892 inst
.instruction
|= WRITE_BACK
;
7896 else if (*str
== '=')
7898 if ((inst
.instruction
& LOAD_BIT
) == 0)
7900 inst
.error
= _("invalid pseudo operation");
7904 /* XXX Does this work correctly for half-word/byte ops? */
7905 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7908 skip_whitespace (str
);
7910 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7913 if (inst
.reloc
.exp
.X_op
!= O_constant
7914 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7916 inst
.error
= _("constant expression expected");
7920 if (inst
.reloc
.exp
.X_op
== O_constant
)
7922 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7926 /* This can be done with a mov instruction. */
7927 inst
.instruction
&= LITERAL_MASK
;
7928 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7929 inst
.instruction
|= value
& 0xfff;
7934 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7938 /* This can be done with a mvn instruction. */
7939 inst
.instruction
&= LITERAL_MASK
;
7940 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7941 inst
.instruction
|= value
& 0xfff;
7947 /* Insert into literal pool. */
7948 if (add_to_lit_pool () == FAIL
)
7951 inst
.error
= _("literal pool insertion failed");
7955 /* Change the instruction exp to point to the pool. */
7956 inst
.instruction
|= HWOFFSET_IMM
;
7957 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7958 inst
.reloc
.pc_rel
= 1;
7959 inst
.instruction
|= (REG_PC
<< 16);
7964 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7967 inst
.instruction
|= HWOFFSET_IMM
;
7968 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7970 /* PC rel adjust. */
7971 inst
.reloc
.exp
.X_add_number
-= 8;
7973 inst
.reloc
.pc_rel
= 1;
7974 inst
.instruction
|= (REG_PC
<< 16);
7978 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7986 char * str
= * strp
;
7990 /* We come back here if we get ranges concatenated by '+' or '|'. */
8005 skip_whitespace (str
);
8007 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
8016 inst
.error
= _("bad range in register list");
8020 for (i
= cur_reg
+ 1; i
< reg
; i
++)
8022 if (range
& (1 << i
))
8024 (_("Warning: duplicated register (r%d) in register list"),
8032 if (range
& (1 << reg
))
8033 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8035 else if (reg
<= cur_reg
)
8036 as_tsktsk (_("Warning: register range not in ascending order"));
8041 while (skip_past_comma (&str
) != FAIL
8042 || (in_range
= 1, *str
++ == '-'));
8044 skip_whitespace (str
);
8048 inst
.error
= _("missing `}'");
8056 if (my_get_expression (&expr
, &str
))
8059 if (expr
.X_op
== O_constant
)
8061 if (expr
.X_add_number
8062 != (expr
.X_add_number
& 0x0000ffff))
8064 inst
.error
= _("invalid register mask");
8068 if ((range
& expr
.X_add_number
) != 0)
8070 int regno
= range
& expr
.X_add_number
;
8073 regno
= (1 << regno
) - 1;
8075 (_("Warning: duplicated register (r%d) in register list"),
8079 range
|= expr
.X_add_number
;
8083 if (inst
.reloc
.type
!= 0)
8085 inst
.error
= _("expression too complex");
8089 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8090 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8091 inst
.reloc
.pc_rel
= 0;
8095 skip_whitespace (str
);
8097 if (*str
== '|' || *str
== '+')
8103 while (another_range
);
8116 skip_whitespace (str
);
8118 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8121 if (base_reg
== REG_PC
)
8123 inst
.error
= _("r15 not allowed as base register");
8127 skip_whitespace (str
);
8131 inst
.instruction
|= WRITE_BACK
;
8135 if (skip_past_comma (&str
) == FAIL
8136 || (range
= reg_list (&str
)) == FAIL
)
8139 inst
.error
= BAD_ARGS
;
8146 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8149 if (inst
.instruction
& WRITE_BACK
)
8151 /* Check for unpredictable uses of writeback. */
8152 if (inst
.instruction
& LOAD_BIT
)
8154 /* Not allowed in LDM type 2. */
8155 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8156 && ((range
& (1 << REG_PC
)) == 0))
8157 as_warn (_("writeback of base register is UNPREDICTABLE"));
8158 /* Only allowed if base reg not in list for other types. */
8159 else if (range
& (1 << base_reg
))
8160 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8164 /* Not allowed for type 2. */
8165 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8166 as_warn (_("writeback of base register is UNPREDICTABLE"));
8167 /* Only allowed if base reg not in list, or first in list. */
8168 else if ((range
& (1 << base_reg
))
8169 && (range
& ((1 << base_reg
) - 1)))
8170 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8174 inst
.instruction
|= range
;
8182 skip_whitespace (str
);
8184 /* Allow optional leading '#'. */
8185 if (is_immediate_prefix (*str
))
8188 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8191 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8192 inst
.reloc
.pc_rel
= 0;
8202 skip_whitespace (str
);
8204 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8209 inst
.error
= _("r15 not allowed in swap");
8213 if (skip_past_comma (&str
) == FAIL
8214 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8217 inst
.error
= BAD_ARGS
;
8223 inst
.error
= _("r15 not allowed in swap");
8227 if (skip_past_comma (&str
) == FAIL
8230 inst
.error
= BAD_ARGS
;
8234 skip_whitespace (str
);
8236 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8241 inst
.error
= BAD_PC
;
8245 skip_whitespace (str
);
8249 inst
.error
= _("missing ]");
8260 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8267 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8268 required for the instruction. */
8270 /* arm_parse_reloc () works on input_line_pointer.
8271 We actually want to parse the operands to the branch instruction
8272 passed in 'str'. Save the input pointer and restore it later. */
8273 save_in
= input_line_pointer
;
8274 input_line_pointer
= str
;
8275 if (inst
.reloc
.exp
.X_op
== O_symbol
8277 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8279 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8280 inst
.reloc
.pc_rel
= 0;
8281 /* Modify str to point to after parsed operands, otherwise
8282 end_of_line() will complain about the (PLT) left in str. */
8283 str
= input_line_pointer
;
8287 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8288 inst
.reloc
.pc_rel
= 1;
8290 input_line_pointer
= save_in
;
8293 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8294 inst
.reloc
.pc_rel
= 1;
8295 #endif /* OBJ_ELF */
8306 skip_whitespace (str
);
8308 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8310 inst
.error
= BAD_ARGS
;
8314 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8316 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8325 /* Co-processor data operation.
8326 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8327 skip_whitespace (str
);
8329 if (co_proc_number (&str
) == FAIL
)
8332 inst
.error
= BAD_ARGS
;
8336 if (skip_past_comma (&str
) == FAIL
8337 || cp_opc_expr (&str
, 20,4) == FAIL
)
8340 inst
.error
= BAD_ARGS
;
8344 if (skip_past_comma (&str
) == FAIL
8345 || cp_reg_required_here (&str
, 12) == FAIL
)
8348 inst
.error
= BAD_ARGS
;
8352 if (skip_past_comma (&str
) == FAIL
8353 || cp_reg_required_here (&str
, 16) == FAIL
)
8356 inst
.error
= BAD_ARGS
;
8360 if (skip_past_comma (&str
) == FAIL
8361 || cp_reg_required_here (&str
, 0) == FAIL
)
8364 inst
.error
= BAD_ARGS
;
8368 if (skip_past_comma (&str
) == SUCCESS
)
8370 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8373 inst
.error
= BAD_ARGS
;
8385 /* Co-processor register load/store.
8386 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8388 skip_whitespace (str
);
8390 if (co_proc_number (&str
) == FAIL
)
8393 inst
.error
= BAD_ARGS
;
8397 if (skip_past_comma (&str
) == FAIL
8398 || cp_reg_required_here (&str
, 12) == FAIL
)
8401 inst
.error
= BAD_ARGS
;
8405 if (skip_past_comma (&str
) == FAIL
8406 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8409 inst
.error
= BAD_ARGS
;
8420 /* Co-processor register transfer.
8421 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8423 skip_whitespace (str
);
8425 if (co_proc_number (&str
) == FAIL
)
8428 inst
.error
= BAD_ARGS
;
8432 if (skip_past_comma (&str
) == FAIL
8433 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8436 inst
.error
= BAD_ARGS
;
8440 if (skip_past_comma (&str
) == FAIL
8441 || reg_required_here (&str
, 12) == FAIL
)
8444 inst
.error
= BAD_ARGS
;
8448 if (skip_past_comma (&str
) == FAIL
8449 || cp_reg_required_here (&str
, 16) == FAIL
)
8452 inst
.error
= BAD_ARGS
;
8456 if (skip_past_comma (&str
) == FAIL
8457 || cp_reg_required_here (&str
, 0) == FAIL
)
8460 inst
.error
= BAD_ARGS
;
8464 if (skip_past_comma (&str
) == SUCCESS
)
8466 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8469 inst
.error
= BAD_ARGS
;
8481 /* FP control registers.
8482 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8484 skip_whitespace (str
);
8486 if (reg_required_here (&str
, 12) == FAIL
)
8489 inst
.error
= BAD_ARGS
;
8500 skip_whitespace (str
);
8502 if (fp_reg_required_here (&str
, 12) == FAIL
)
8505 inst
.error
= BAD_ARGS
;
8509 if (skip_past_comma (&str
) == FAIL
8510 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8513 inst
.error
= BAD_ARGS
;
8526 skip_whitespace (str
);
8528 if (fp_reg_required_here (&str
, 12) == FAIL
)
8531 inst
.error
= BAD_ARGS
;
8535 /* Get Number of registers to transfer. */
8536 if (skip_past_comma (&str
) == FAIL
8537 || my_get_expression (&inst
.reloc
.exp
, &str
))
8540 inst
.error
= _("constant expression expected");
8544 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8546 inst
.error
= _("constant value required for number of registers");
8550 num_regs
= inst
.reloc
.exp
.X_add_number
;
8552 if (num_regs
< 1 || num_regs
> 4)
8554 inst
.error
= _("number of registers must be in the range [1:4]");
8561 inst
.instruction
|= CP_T_X
;
8564 inst
.instruction
|= CP_T_Y
;
8567 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8575 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8581 /* The instruction specified "ea" or "fd", so we can only accept
8582 [Rn]{!}. The instruction does not really support stacking or
8583 unstacking, so we have to emulate these by setting appropriate
8584 bits and offsets. */
8585 if (skip_past_comma (&str
) == FAIL
8589 inst
.error
= BAD_ARGS
;
8594 skip_whitespace (str
);
8596 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8599 skip_whitespace (str
);
8603 inst
.error
= BAD_ARGS
;
8615 _("r15 not allowed as base register with write-back");
8622 if (inst
.instruction
& CP_T_Pre
)
8624 /* Pre-decrement. */
8625 offset
= 3 * num_regs
;
8627 inst
.instruction
|= CP_T_WB
;
8631 /* Post-increment. */
8634 inst
.instruction
|= CP_T_WB
;
8635 offset
= 3 * num_regs
;
8639 /* No write-back, so convert this into a standard pre-increment
8640 instruction -- aesthetically more pleasing. */
8641 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8646 inst
.instruction
|= offset
;
8648 else if (skip_past_comma (&str
) == FAIL
8649 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8652 inst
.error
= BAD_ARGS
;
8663 skip_whitespace (str
);
8665 if (fp_reg_required_here (&str
, 12) == FAIL
)
8668 inst
.error
= BAD_ARGS
;
8672 if (skip_past_comma (&str
) == FAIL
8673 || fp_reg_required_here (&str
, 16) == FAIL
)
8676 inst
.error
= BAD_ARGS
;
8680 if (skip_past_comma (&str
) == FAIL
8681 || fp_op2 (&str
) == FAIL
)
8684 inst
.error
= BAD_ARGS
;
8692 do_fpa_monadic (str
)
8695 skip_whitespace (str
);
8697 if (fp_reg_required_here (&str
, 12) == FAIL
)
8700 inst
.error
= BAD_ARGS
;
8704 if (skip_past_comma (&str
) == FAIL
8705 || fp_op2 (&str
) == FAIL
)
8708 inst
.error
= BAD_ARGS
;
8719 skip_whitespace (str
);
8721 if (fp_reg_required_here (&str
, 16) == FAIL
)
8724 inst
.error
= BAD_ARGS
;
8728 if (skip_past_comma (&str
) == FAIL
8729 || fp_op2 (&str
) == FAIL
)
8732 inst
.error
= BAD_ARGS
;
8740 do_fpa_from_reg (str
)
8743 skip_whitespace (str
);
8745 if (fp_reg_required_here (&str
, 16) == FAIL
)
8748 inst
.error
= BAD_ARGS
;
8752 if (skip_past_comma (&str
) == FAIL
8753 || reg_required_here (&str
, 12) == FAIL
)
8756 inst
.error
= BAD_ARGS
;
8767 skip_whitespace (str
);
8769 if (reg_required_here (&str
, 12) == FAIL
)
8772 if (skip_past_comma (&str
) == FAIL
8773 || fp_reg_required_here (&str
, 0) == FAIL
)
8776 inst
.error
= BAD_ARGS
;
8784 vfp_sp_reg_required_here (str
, pos
)
8786 enum vfp_sp_reg_pos pos
;
8791 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8796 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8800 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8804 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8813 /* In the few cases where we might be able to accept something else
8814 this error can be overridden. */
8815 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8817 /* Restore the start point. */
8823 vfp_dp_reg_required_here (str
, pos
)
8825 enum vfp_dp_reg_pos pos
;
8830 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8835 inst
.instruction
|= reg
<< 12;
8839 inst
.instruction
|= reg
<< 16;
8843 inst
.instruction
|= reg
<< 0;
8852 /* In the few cases where we might be able to accept something else
8853 this error can be overridden. */
8854 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8856 /* Restore the start point. */
8862 do_vfp_sp_monadic (str
)
8865 skip_whitespace (str
);
8867 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8870 if (skip_past_comma (&str
) == FAIL
8871 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8874 inst
.error
= BAD_ARGS
;
8882 do_vfp_dp_monadic (str
)
8885 skip_whitespace (str
);
8887 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8890 if (skip_past_comma (&str
) == FAIL
8891 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8894 inst
.error
= BAD_ARGS
;
8902 do_vfp_sp_dyadic (str
)
8905 skip_whitespace (str
);
8907 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8910 if (skip_past_comma (&str
) == FAIL
8911 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8912 || skip_past_comma (&str
) == FAIL
8913 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8916 inst
.error
= BAD_ARGS
;
8924 do_vfp_dp_dyadic (str
)
8927 skip_whitespace (str
);
8929 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8932 if (skip_past_comma (&str
) == FAIL
8933 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8934 || skip_past_comma (&str
) == FAIL
8935 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8938 inst
.error
= BAD_ARGS
;
8946 do_vfp_reg_from_sp (str
)
8949 skip_whitespace (str
);
8951 if (reg_required_here (&str
, 12) == FAIL
)
8954 if (skip_past_comma (&str
) == FAIL
8955 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8958 inst
.error
= BAD_ARGS
;
8966 do_vfp_reg2_from_sp2 (str
)
8969 skip_whitespace (str
);
8971 if (reg_required_here (&str
, 12) == FAIL
8972 || skip_past_comma (&str
) == FAIL
8973 || reg_required_here (&str
, 16) == FAIL
8974 || skip_past_comma (&str
) == FAIL
)
8977 inst
.error
= BAD_ARGS
;
8981 /* We require exactly two consecutive SP registers. */
8982 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8985 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8992 do_vfp_sp_from_reg (str
)
8995 skip_whitespace (str
);
8997 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
9000 if (skip_past_comma (&str
) == FAIL
9001 || reg_required_here (&str
, 12) == FAIL
)
9004 inst
.error
= BAD_ARGS
;
9012 do_vfp_sp2_from_reg2 (str
)
9015 skip_whitespace (str
);
9017 /* We require exactly two consecutive SP registers. */
9018 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
9021 inst
.error
= _("only two consecutive VFP SP registers allowed here");
9024 if (skip_past_comma (&str
) == FAIL
9025 || reg_required_here (&str
, 12) == FAIL
9026 || skip_past_comma (&str
) == FAIL
9027 || reg_required_here (&str
, 16) == FAIL
)
9030 inst
.error
= BAD_ARGS
;
9038 do_vfp_reg_from_dp (str
)
9041 skip_whitespace (str
);
9043 if (reg_required_here (&str
, 12) == FAIL
)
9046 if (skip_past_comma (&str
) == FAIL
9047 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9050 inst
.error
= BAD_ARGS
;
9058 do_vfp_reg2_from_dp (str
)
9061 skip_whitespace (str
);
9063 if (reg_required_here (&str
, 12) == FAIL
)
9066 if (skip_past_comma (&str
) == FAIL
9067 || reg_required_here (&str
, 16) == FAIL
9068 || skip_past_comma (&str
) == FAIL
9069 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9072 inst
.error
= BAD_ARGS
;
9080 do_vfp_dp_from_reg (str
)
9083 skip_whitespace (str
);
9085 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9088 if (skip_past_comma (&str
) == FAIL
9089 || reg_required_here (&str
, 12) == FAIL
)
9092 inst
.error
= BAD_ARGS
;
9100 do_vfp_dp_from_reg2 (str
)
9103 skip_whitespace (str
);
9105 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9108 if (skip_past_comma (&str
) == FAIL
9109 || reg_required_here (&str
, 12) == FAIL
9110 || skip_past_comma (&str
) == FAIL
9111 || reg_required_here (&str
, 16) == FAIL
)
9114 inst
.error
= BAD_ARGS
;
9121 static const struct vfp_reg
*
9128 const struct vfp_reg
*vreg
;
9132 /* Find the end of the current token. */
9137 while (ISALPHA (c
));
9142 for (vreg
= vfp_regs
+ 0;
9143 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9146 if (strcmp (start
, vreg
->name
) == 0)
9159 vfp_psr_required_here (str
)
9163 const struct vfp_reg
*vreg
;
9165 vreg
= vfp_psr_parse (str
);
9169 inst
.instruction
|= vreg
->regno
;
9173 inst
.error
= _("VFP system register expected");
9180 do_vfp_reg_from_ctrl (str
)
9183 skip_whitespace (str
);
9185 if (reg_required_here (&str
, 12) == FAIL
)
9188 if (skip_past_comma (&str
) == FAIL
9189 || vfp_psr_required_here (&str
) == FAIL
)
9192 inst
.error
= BAD_ARGS
;
9200 do_vfp_ctrl_from_reg (str
)
9203 skip_whitespace (str
);
9205 if (vfp_psr_required_here (&str
) == FAIL
)
9208 if (skip_past_comma (&str
) == FAIL
9209 || reg_required_here (&str
, 12) == FAIL
)
9212 inst
.error
= BAD_ARGS
;
9220 do_vfp_sp_ldst (str
)
9223 skip_whitespace (str
);
9225 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9228 inst
.error
= BAD_ARGS
;
9232 if (skip_past_comma (&str
) == FAIL
9233 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9236 inst
.error
= BAD_ARGS
;
9244 do_vfp_dp_ldst (str
)
9247 skip_whitespace (str
);
9249 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9252 inst
.error
= BAD_ARGS
;
9256 if (skip_past_comma (&str
) == FAIL
9257 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9260 inst
.error
= BAD_ARGS
;
9267 /* Parse and encode a VFP SP register list, storing the initial
9268 register in position POS and returning the range as the result. If
9269 the string is invalid return FAIL (an invalid range). */
9271 vfp_sp_reg_list (str
, pos
)
9273 enum vfp_sp_reg_pos pos
;
9281 unsigned long mask
= 0;
9288 skip_whitespace (*str
);
9290 tempinst
= inst
.instruction
;
9294 inst
.instruction
= 0;
9296 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9299 if (count
== 0 || base_reg
> new_base
)
9301 base_reg
= new_base
;
9302 base_bits
= inst
.instruction
;
9305 if (mask
& (1 << new_base
))
9307 inst
.error
= _("invalid register list");
9311 if ((mask
>> new_base
) != 0 && ! warned
)
9313 as_tsktsk (_("register list not in ascending order"));
9317 mask
|= 1 << new_base
;
9320 skip_whitespace (*str
);
9322 if (**str
== '-') /* We have the start of a range expression */
9329 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9332 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9336 if (high_range
<= new_base
)
9338 inst
.error
= _("register range not in ascending order");
9342 for (new_base
++; new_base
<= high_range
; new_base
++)
9344 if (mask
& (1 << new_base
))
9346 inst
.error
= _("invalid register list");
9350 mask
|= 1 << new_base
;
9355 while (skip_past_comma (str
) != FAIL
);
9359 inst
.error
= _("invalid register list");
9367 /* Sanity check -- should have raised a parse error above. */
9368 if (count
== 0 || count
> 32)
9371 /* Final test -- the registers must be consecutive. */
9374 if ((mask
& (1 << base_reg
++)) == 0)
9376 inst
.error
= _("non-contiguous register range");
9381 inst
.instruction
= tempinst
| base_bits
;
9386 vfp_dp_reg_list (str
)
9394 unsigned long mask
= 0;
9401 skip_whitespace (*str
);
9403 tempinst
= inst
.instruction
;
9407 inst
.instruction
= 0;
9409 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9412 if (count
== 0 || base_reg
> new_base
)
9414 base_reg
= new_base
;
9415 range
= inst
.instruction
;
9418 if (mask
& (1 << new_base
))
9420 inst
.error
= _("invalid register list");
9424 if ((mask
>> new_base
) != 0 && ! warned
)
9426 as_tsktsk (_("register list not in ascending order"));
9430 mask
|= 1 << new_base
;
9433 skip_whitespace (*str
);
9435 if (**str
== '-') /* We have the start of a range expression */
9442 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9445 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9449 if (high_range
<= new_base
)
9451 inst
.error
= _("register range not in ascending order");
9455 for (new_base
++; new_base
<= high_range
; new_base
++)
9457 if (mask
& (1 << new_base
))
9459 inst
.error
= _("invalid register list");
9463 mask
|= 1 << new_base
;
9468 while (skip_past_comma (str
) != FAIL
);
9472 inst
.error
= _("invalid register list");
9480 /* Sanity check -- should have raised a parse error above. */
9481 if (count
== 0 || count
> 16)
9484 /* Final test -- the registers must be consecutive. */
9487 if ((mask
& (1 << base_reg
++)) == 0)
9489 inst
.error
= _("non-contiguous register range");
9494 inst
.instruction
= tempinst
;
9499 vfp_sp_ldstm (str
, ldstm_type
)
9501 enum vfp_ldstm_type ldstm_type
;
9505 skip_whitespace (str
);
9507 if (reg_required_here (&str
, 16) == FAIL
)
9510 skip_whitespace (str
);
9514 inst
.instruction
|= WRITE_BACK
;
9517 else if (ldstm_type
!= VFP_LDSTMIA
)
9519 inst
.error
= _("this addressing mode requires base-register writeback");
9523 if (skip_past_comma (&str
) == FAIL
9524 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9527 inst
.error
= BAD_ARGS
;
9531 inst
.instruction
|= range
;
9536 vfp_dp_ldstm (str
, ldstm_type
)
9538 enum vfp_ldstm_type ldstm_type
;
9542 skip_whitespace (str
);
9544 if (reg_required_here (&str
, 16) == FAIL
)
9547 skip_whitespace (str
);
9551 inst
.instruction
|= WRITE_BACK
;
9554 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9556 inst
.error
= _("this addressing mode requires base-register writeback");
9560 if (skip_past_comma (&str
) == FAIL
9561 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9564 inst
.error
= BAD_ARGS
;
9568 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9571 inst
.instruction
|= range
;
9576 do_vfp_sp_ldstmia (str
)
9579 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9583 do_vfp_sp_ldstmdb (str
)
9586 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9590 do_vfp_dp_ldstmia (str
)
9593 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9597 do_vfp_dp_ldstmdb (str
)
9600 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9604 do_vfp_xp_ldstmia (str
)
9607 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9611 do_vfp_xp_ldstmdb (str
)
9614 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9618 do_vfp_sp_compare_z (str
)
9621 skip_whitespace (str
);
9623 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9626 inst
.error
= BAD_ARGS
;
9634 do_vfp_dp_compare_z (str
)
9637 skip_whitespace (str
);
9639 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9642 inst
.error
= BAD_ARGS
;
9650 do_vfp_dp_sp_cvt (str
)
9653 skip_whitespace (str
);
9655 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9658 if (skip_past_comma (&str
) == FAIL
9659 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9662 inst
.error
= BAD_ARGS
;
9670 do_vfp_sp_dp_cvt (str
)
9673 skip_whitespace (str
);
9675 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9678 if (skip_past_comma (&str
) == FAIL
9679 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9682 inst
.error
= BAD_ARGS
;
9689 /* Thumb specific routines. */
9691 /* Parse and validate that a register is of the right form, this saves
9692 repeated checking of this information in many similar cases.
9693 Unlike the 32-bit case we do not insert the register into the opcode
9694 here, since the position is often unknown until the full instruction
9698 thumb_reg (strp
, hi_lo
)
9704 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9712 inst
.error
= _("lo register required");
9720 inst
.error
= _("hi register required");
9732 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9736 thumb_add_sub (str
, subtract
)
9740 int Rd
, Rs
, Rn
= FAIL
;
9742 skip_whitespace (str
);
9744 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9745 || skip_past_comma (&str
) == FAIL
)
9748 inst
.error
= BAD_ARGS
;
9752 if (is_immediate_prefix (*str
))
9756 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9761 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9764 if (skip_past_comma (&str
) == FAIL
)
9766 /* Two operand format, shuffle the registers
9767 and pretend there are 3. */
9771 else if (is_immediate_prefix (*str
))
9774 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9777 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9781 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9782 for the latter case, EXPR contains the immediate that was found. */
9785 /* All register format. */
9786 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9790 inst
.error
= _("dest and source1 must be the same register");
9794 /* Can't do this for SUB. */
9797 inst
.error
= _("subtract valid only on lo regs");
9801 inst
.instruction
= (T_OPCODE_ADD_HI
9802 | (Rd
> 7 ? THUMB_H1
: 0)
9803 | (Rn
> 7 ? THUMB_H2
: 0));
9804 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9808 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9809 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9814 /* Immediate expression, now things start to get nasty. */
9816 /* First deal with HI regs, only very restricted cases allowed:
9817 Adjusting SP, and using PC or SP to get an address. */
9818 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9819 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9821 inst
.error
= _("invalid Hi register with immediate");
9825 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9827 /* Value isn't known yet, all we can do is store all the fragments
9828 we know about in the instruction and let the reloc hacking
9830 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9831 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9835 int offset
= inst
.reloc
.exp
.X_add_number
;
9845 /* Quick check, in case offset is MIN_INT. */
9848 inst
.error
= _("immediate value out of range");
9852 /* Note - you cannot convert a subtract of 0 into an
9853 add of 0 because the carry flag is set differently. */
9854 else if (offset
> 0)
9859 if (offset
& ~0x1fc)
9861 inst
.error
= _("invalid immediate value for stack adjust");
9864 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9865 inst
.instruction
|= offset
>> 2;
9867 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9870 || (offset
& ~0x3fc))
9872 inst
.error
= _("invalid immediate for address calculation");
9875 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9877 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9883 inst
.error
= _("immediate value out of range");
9886 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9887 inst
.instruction
|= (Rd
<< 8) | offset
;
9893 inst
.error
= _("immediate value out of range");
9896 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9897 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9906 thumb_shift (str
, shift
)
9910 int Rd
, Rs
, Rn
= FAIL
;
9912 skip_whitespace (str
);
9914 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9915 || skip_past_comma (&str
) == FAIL
)
9918 inst
.error
= BAD_ARGS
;
9922 if (is_immediate_prefix (*str
))
9924 /* Two operand immediate format, set Rs to Rd. */
9927 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9932 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9935 if (skip_past_comma (&str
) == FAIL
)
9937 /* Two operand format, shuffle the registers
9938 and pretend there are 3. */
9942 else if (is_immediate_prefix (*str
))
9945 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9948 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9952 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9953 for the latter case, EXPR contains the immediate that was found. */
9959 inst
.error
= _("source1 and dest must be same register");
9965 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9966 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9967 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9970 inst
.instruction
|= Rd
| (Rn
<< 3);
9976 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9977 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9978 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9981 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9983 /* Value isn't known yet, create a dummy reloc and let reloc
9984 hacking fix it up. */
9985 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9989 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9991 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9993 inst
.error
= _("invalid immediate for shift");
9997 /* Shifts of zero are handled by converting to LSL. */
9998 if (shift_value
== 0)
9999 inst
.instruction
= T_OPCODE_LSL_I
;
10001 /* Shifts of 32 are encoded as a shift of zero. */
10002 if (shift_value
== 32)
10005 inst
.instruction
|= shift_value
<< 6;
10008 inst
.instruction
|= Rd
| (Rs
<< 3);
10015 thumb_mov_compare (str
, move
)
10021 skip_whitespace (str
);
10023 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
10024 || skip_past_comma (&str
) == FAIL
)
10027 inst
.error
= BAD_ARGS
;
10031 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
10034 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10037 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10042 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
10044 if (move
== THUMB_MOVE
)
10045 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10046 since a MOV instruction produces unpredictable results. */
10047 inst
.instruction
= T_OPCODE_ADD_I3
;
10049 inst
.instruction
= T_OPCODE_CMP_LR
;
10050 inst
.instruction
|= Rd
| (Rs
<< 3);
10054 if (move
== THUMB_MOVE
)
10055 inst
.instruction
= T_OPCODE_MOV_HR
;
10056 else if (move
!= THUMB_CPY
)
10057 inst
.instruction
= T_OPCODE_CMP_HR
;
10060 inst
.instruction
|= THUMB_H1
;
10063 inst
.instruction
|= THUMB_H2
;
10065 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
10072 inst
.error
= _("only lo regs allowed with immediate");
10076 if (move
== THUMB_MOVE
)
10077 inst
.instruction
= T_OPCODE_MOV_I8
;
10079 inst
.instruction
= T_OPCODE_CMP_I8
;
10081 inst
.instruction
|= Rd
<< 8;
10083 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10084 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10087 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10091 inst
.error
= _("invalid immediate");
10095 inst
.instruction
|= value
;
10103 thumb_load_store (str
, load_store
, size
)
10108 int Rd
, Rb
, Ro
= FAIL
;
10110 skip_whitespace (str
);
10112 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10113 || skip_past_comma (&str
) == FAIL
)
10116 inst
.error
= BAD_ARGS
;
10123 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10126 if (skip_past_comma (&str
) != FAIL
)
10128 if (is_immediate_prefix (*str
))
10131 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10134 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10139 inst
.reloc
.exp
.X_op
= O_constant
;
10140 inst
.reloc
.exp
.X_add_number
= 0;
10145 inst
.error
= _("expected ']'");
10150 else if (*str
== '=')
10152 if (load_store
!= THUMB_LOAD
)
10154 inst
.error
= _("invalid pseudo operation");
10158 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10161 skip_whitespace (str
);
10163 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10168 if ( inst
.reloc
.exp
.X_op
!= O_constant
10169 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10171 inst
.error
= "Constant expression expected";
10175 if (inst
.reloc
.exp
.X_op
== O_constant
10176 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10178 /* This can be done with a mov instruction. */
10180 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10181 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10185 /* Insert into literal pool. */
10186 if (add_to_lit_pool () == FAIL
)
10189 inst
.error
= "literal pool insertion failed";
10193 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10194 inst
.reloc
.pc_rel
= 1;
10195 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10196 /* Adjust ARM pipeline offset to Thumb. */
10197 inst
.reloc
.exp
.X_add_number
+= 4;
10203 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10206 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10207 inst
.reloc
.pc_rel
= 1;
10208 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10209 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10214 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10216 if (size
!= THUMB_WORD
)
10218 inst
.error
= _("byte or halfword not valid for base register");
10221 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10223 inst
.error
= _("r15 based store not allowed");
10226 else if (Ro
!= FAIL
)
10228 inst
.error
= _("invalid base register for register offset");
10233 inst
.instruction
= T_OPCODE_LDR_PC
;
10234 else if (load_store
== THUMB_LOAD
)
10235 inst
.instruction
= T_OPCODE_LDR_SP
;
10237 inst
.instruction
= T_OPCODE_STR_SP
;
10239 inst
.instruction
|= Rd
<< 8;
10240 if (inst
.reloc
.exp
.X_op
== O_constant
)
10242 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10244 if (offset
& ~0x3fc)
10246 inst
.error
= _("invalid offset");
10250 inst
.instruction
|= offset
>> 2;
10253 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10257 inst
.error
= _("invalid base register in load/store");
10260 else if (Ro
== FAIL
)
10262 /* Immediate offset. */
10263 if (size
== THUMB_WORD
)
10264 inst
.instruction
= (load_store
== THUMB_LOAD
10265 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10266 else if (size
== THUMB_HALFWORD
)
10267 inst
.instruction
= (load_store
== THUMB_LOAD
10268 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10270 inst
.instruction
= (load_store
== THUMB_LOAD
10271 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10273 inst
.instruction
|= Rd
| (Rb
<< 3);
10275 if (inst
.reloc
.exp
.X_op
== O_constant
)
10277 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10279 if (offset
& ~(0x1f << size
))
10281 inst
.error
= _("invalid offset");
10284 inst
.instruction
|= (offset
>> size
) << 6;
10287 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10291 /* Register offset. */
10292 if (size
== THUMB_WORD
)
10293 inst
.instruction
= (load_store
== THUMB_LOAD
10294 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10295 else if (size
== THUMB_HALFWORD
)
10296 inst
.instruction
= (load_store
== THUMB_LOAD
10297 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10299 inst
.instruction
= (load_store
== THUMB_LOAD
10300 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10302 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10308 /* A register must be given at this point.
10310 Shift is the place to put it in inst.instruction.
10312 Restores input start point on err.
10313 Returns the reg#, or FAIL. */
10316 mav_reg_required_here (str
, shift
, regtype
)
10319 enum arm_reg_type regtype
;
10322 char *start
= *str
;
10324 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10327 inst
.instruction
|= reg
<< shift
;
10332 /* Restore the start point. */
10335 /* In the few cases where we might be able to accept something else
10336 this error can be overridden. */
10337 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10342 /* Cirrus Maverick Instructions. */
10344 /* Wrapper functions. */
10347 do_mav_binops_1a (str
)
10350 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10354 do_mav_binops_1b (str
)
10357 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10361 do_mav_binops_1c (str
)
10364 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10368 do_mav_binops_1d (str
)
10371 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10375 do_mav_binops_1e (str
)
10378 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10382 do_mav_binops_1f (str
)
10385 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10389 do_mav_binops_1g (str
)
10392 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10396 do_mav_binops_1h (str
)
10399 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10403 do_mav_binops_1i (str
)
10406 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10410 do_mav_binops_1j (str
)
10413 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10417 do_mav_binops_1k (str
)
10420 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10424 do_mav_binops_1l (str
)
10427 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10431 do_mav_binops_1m (str
)
10434 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10438 do_mav_binops_1n (str
)
10441 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10445 do_mav_binops_1o (str
)
10448 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10452 do_mav_binops_2a (str
)
10455 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10459 do_mav_binops_2b (str
)
10462 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10466 do_mav_binops_2c (str
)
10469 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10473 do_mav_binops_3a (str
)
10476 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10480 do_mav_binops_3b (str
)
10483 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10487 do_mav_binops_3c (str
)
10490 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10494 do_mav_binops_3d (str
)
10497 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10501 do_mav_triple_4a (str
)
10504 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10508 do_mav_triple_4b (str
)
10511 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10515 do_mav_triple_5a (str
)
10518 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10522 do_mav_triple_5b (str
)
10525 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10529 do_mav_triple_5c (str
)
10532 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10536 do_mav_triple_5d (str
)
10539 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10543 do_mav_triple_5e (str
)
10546 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10550 do_mav_triple_5f (str
)
10553 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10557 do_mav_triple_5g (str
)
10560 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10564 do_mav_triple_5h (str
)
10567 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10571 do_mav_quad_6a (str
)
10574 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10579 do_mav_quad_6b (str
)
10582 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10586 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10588 do_mav_dspsc_1 (str
)
10591 skip_whitespace (str
);
10594 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10595 || skip_past_comma (&str
) == FAIL
10596 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
10599 inst
.error
= BAD_ARGS
;
10607 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10609 do_mav_dspsc_2 (str
)
10612 skip_whitespace (str
);
10615 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
10616 || skip_past_comma (&str
) == FAIL
10617 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10620 inst
.error
= BAD_ARGS
;
10629 do_mav_shift_1 (str
)
10632 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10636 do_mav_shift_2 (str
)
10639 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10643 do_mav_ldst_1 (str
)
10646 do_mav_ldst (str
, REG_TYPE_MVF
);
10650 do_mav_ldst_2 (str
)
10653 do_mav_ldst (str
, REG_TYPE_MVD
);
10657 do_mav_ldst_3 (str
)
10660 do_mav_ldst (str
, REG_TYPE_MVFX
);
10664 do_mav_ldst_4 (str
)
10667 do_mav_ldst (str
, REG_TYPE_MVDX
);
10670 /* Isnsn like "foo X,Y". */
10673 do_mav_binops (str
, mode
, reg0
, reg1
)
10676 enum arm_reg_type reg0
;
10677 enum arm_reg_type reg1
;
10679 int shift0
, shift1
;
10681 shift0
= mode
& 0xff;
10682 shift1
= (mode
>> 8) & 0xff;
10684 skip_whitespace (str
);
10686 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10687 || skip_past_comma (&str
) == FAIL
10688 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10691 inst
.error
= BAD_ARGS
;
10697 /* Isnsn like "foo X,Y,Z". */
10700 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10703 enum arm_reg_type reg0
;
10704 enum arm_reg_type reg1
;
10705 enum arm_reg_type reg2
;
10707 int shift0
, shift1
, shift2
;
10709 shift0
= mode
& 0xff;
10710 shift1
= (mode
>> 8) & 0xff;
10711 shift2
= (mode
>> 16) & 0xff;
10713 skip_whitespace (str
);
10715 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10716 || skip_past_comma (&str
) == FAIL
10717 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10718 || skip_past_comma (&str
) == FAIL
10719 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10722 inst
.error
= BAD_ARGS
;
10728 /* Isnsn like "foo W,X,Y,Z".
10729 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10732 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10735 enum arm_reg_type reg0
;
10736 enum arm_reg_type reg1
;
10737 enum arm_reg_type reg2
;
10738 enum arm_reg_type reg3
;
10740 int shift0
, shift1
, shift2
, shift3
;
10742 shift0
= mode
& 0xff;
10743 shift1
= (mode
>> 8) & 0xff;
10744 shift2
= (mode
>> 16) & 0xff;
10745 shift3
= (mode
>> 24) & 0xff;
10747 skip_whitespace (str
);
10749 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10750 || skip_past_comma (&str
) == FAIL
10751 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10752 || skip_past_comma (&str
) == FAIL
10753 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10754 || skip_past_comma (&str
) == FAIL
10755 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10758 inst
.error
= BAD_ARGS
;
10764 /* Maverick shift immediate instructions.
10765 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10766 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10769 do_mav_shift (str
, reg0
, reg1
)
10771 enum arm_reg_type reg0
;
10772 enum arm_reg_type reg1
;
10777 skip_whitespace (str
);
10781 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10782 || skip_past_comma (&str
) == FAIL
10783 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10784 || skip_past_comma (&str
) == FAIL
)
10787 inst
.error
= BAD_ARGS
;
10791 /* Calculate the immediate operand.
10792 The operand is a 7bit signed number. */
10793 skip_whitespace (str
);
10798 if (!ISDIGIT (*str
) && *str
!= '-')
10800 inst
.error
= _("expecting immediate, 7bit operand");
10810 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10811 imm
= imm
* 10 + *str
- '0';
10815 inst
.error
= _("immediate out of range");
10819 /* Make negative imm's into 7bit signed numbers. */
10826 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10827 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10828 Bit 4 should be 0. */
10829 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10831 inst
.instruction
|= imm
;
10836 mav_parse_offset (str
, negative
)
10845 skip_whitespace (p
);
10858 inst
.error
= _("offset expected");
10862 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10863 offset
= offset
* 10 + *p
- '0';
10867 inst
.error
= _("offset out of range");
10873 return *negative
? -offset
: offset
;
10876 /* Maverick load/store instructions.
10877 <insn><cond> CRd,[Rn,<offset>]{!}.
10878 <insn><cond> CRd,[Rn],<offset>. */
10881 do_mav_ldst (str
, reg0
)
10883 enum arm_reg_type reg0
;
10885 int offset
, negative
;
10887 skip_whitespace (str
);
10889 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10890 || skip_past_comma (&str
) == FAIL
10892 || reg_required_here (&str
, 16) == FAIL
)
10895 if (skip_past_comma (&str
) == SUCCESS
)
10897 /* You are here: "<offset>]{!}". */
10898 inst
.instruction
|= PRE_INDEX
;
10900 offset
= mav_parse_offset (&str
, &negative
);
10907 inst
.error
= _("missing ]");
10913 inst
.instruction
|= WRITE_BACK
;
10919 /* You are here: "], <offset>". */
10922 inst
.error
= _("missing ]");
10926 if (skip_past_comma (&str
) == FAIL
10927 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10930 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10936 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10938 inst
.instruction
|= offset
>> 2;
10944 inst
.error
= BAD_ARGS
;
10955 /* Handle the Format 4 instructions that do not have equivalents in other
10956 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10965 skip_whitespace (str
);
10967 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10968 || skip_past_comma (&str
) == FAIL
10969 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10971 inst
.error
= BAD_ARGS
;
10975 if (skip_past_comma (&str
) != FAIL
)
10977 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10978 (It isn't allowed for CMP either, but that isn't handled by this
10980 if (inst
.instruction
== T_OPCODE_TST
10981 || inst
.instruction
== T_OPCODE_CMN
10982 || inst
.instruction
== T_OPCODE_NEG
10983 || inst
.instruction
== T_OPCODE_MVN
)
10985 inst
.error
= BAD_ARGS
;
10989 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10994 inst
.error
= _("dest and source1 must be the same register");
11000 if (inst
.instruction
== T_OPCODE_MUL
11002 as_tsktsk (_("Rs and Rd must be different in MUL"));
11004 inst
.instruction
|= Rd
| (Rs
<< 3);
11012 thumb_add_sub (str
, 0);
11019 thumb_shift (str
, THUMB_ASR
);
11026 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11028 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
11029 inst
.reloc
.pc_rel
= 1;
11034 do_t_branch12 (str
)
11037 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11039 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
11040 inst
.reloc
.pc_rel
= 1;
11044 /* Find the real, Thumb encoded start of a Thumb function. */
11047 find_real_start (symbolP
)
11051 const char * name
= S_GET_NAME (symbolP
);
11052 symbolS
* new_target
;
11054 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11055 #define STUB_NAME ".real_start_of"
11060 /* Names that start with '.' are local labels, not function entry points.
11061 The compiler may generate BL instructions to these labels because it
11062 needs to perform a branch to a far away location. */
11063 if (name
[0] == '.')
11066 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
11067 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
11069 new_target
= symbol_find (real_start
);
11071 if (new_target
== NULL
)
11073 as_warn ("Failed to find real start of function: %s\n", name
);
11074 new_target
= symbolP
;
11083 do_t_branch23 (str
)
11086 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11089 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11090 inst
.reloc
.pc_rel
= 1;
11093 /* If the destination of the branch is a defined symbol which does not have
11094 the THUMB_FUNC attribute, then we must be calling a function which has
11095 the (interfacearm) attribute. We look for the Thumb entry point to that
11096 function and change the branch to refer to that function instead. */
11097 if ( inst
.reloc
.exp
.X_op
== O_symbol
11098 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11099 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11100 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11101 inst
.reloc
.exp
.X_add_symbol
=
11102 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11111 skip_whitespace (str
);
11113 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11116 /* This sets THUMB_H2 from the top bit of reg. */
11117 inst
.instruction
|= reg
<< 3;
11119 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11120 should cause the alignment to be checked once it is known. This is
11121 because BX PC only works if the instruction is word aligned. */
11130 thumb_mov_compare (str
, THUMB_COMPARE
);
11140 skip_whitespace (str
);
11142 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11146 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11150 if (skip_past_comma (&str
) == FAIL
11151 || (range
= reg_list (&str
)) == FAIL
)
11154 inst
.error
= BAD_ARGS
;
11158 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11160 /* This really doesn't seem worth it. */
11161 inst
.reloc
.type
= BFD_RELOC_NONE
;
11162 inst
.error
= _("expression too complex");
11168 inst
.error
= _("only lo-regs valid in load/store multiple");
11172 inst
.instruction
|= (Rb
<< 8) | range
;
11180 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11187 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11194 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11203 skip_whitespace (str
);
11205 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11206 || skip_past_comma (&str
) == FAIL
11208 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11209 || skip_past_comma (&str
) == FAIL
11210 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11214 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11218 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11226 thumb_shift (str
, THUMB_LSL
);
11233 thumb_shift (str
, THUMB_LSR
);
11240 thumb_mov_compare (str
, THUMB_MOVE
);
11244 do_t_push_pop (str
)
11249 skip_whitespace (str
);
11251 if ((range
= reg_list (&str
)) == FAIL
)
11254 inst
.error
= BAD_ARGS
;
11258 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11260 /* This really doesn't seem worth it. */
11261 inst
.reloc
.type
= BFD_RELOC_NONE
;
11262 inst
.error
= _("expression too complex");
11268 if ((inst
.instruction
== T_OPCODE_PUSH
11269 && (range
& ~0xff) == 1 << REG_LR
)
11270 || (inst
.instruction
== T_OPCODE_POP
11271 && (range
& ~0xff) == 1 << REG_PC
))
11273 inst
.instruction
|= THUMB_PP_PC_LR
;
11278 inst
.error
= _("invalid register list to push/pop instruction");
11283 inst
.instruction
|= range
;
11291 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11298 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11305 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11312 thumb_add_sub (str
, 1);
11319 skip_whitespace (str
);
11321 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11324 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11334 /* This is a pseudo-op of the form "adr rd, label" to be converted
11335 into a relative address of the form "add rd, pc, #label-.-4". */
11336 skip_whitespace (str
);
11338 /* Store Rd in temporary location inside instruction. */
11339 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11340 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11341 || skip_past_comma (&str
) == FAIL
11342 || my_get_expression (&inst
.reloc
.exp
, &str
))
11345 inst
.error
= BAD_ARGS
;
11349 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11350 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11351 inst
.reloc
.pc_rel
= 1;
11352 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11358 insert_reg (r
, htab
)
11359 const struct reg_entry
*r
;
11360 struct hash_control
*htab
;
11362 int len
= strlen (r
->name
) + 2;
11363 char * buf
= (char *) xmalloc (len
);
11364 char * buf2
= (char *) xmalloc (len
);
11367 #ifdef REGISTER_PREFIX
11368 buf
[i
++] = REGISTER_PREFIX
;
11371 strcpy (buf
+ i
, r
->name
);
11373 for (i
= 0; buf
[i
]; i
++)
11374 buf2
[i
] = TOUPPER (buf
[i
]);
11378 hash_insert (htab
, buf
, (PTR
) r
);
11379 hash_insert (htab
, buf2
, (PTR
) r
);
11383 build_reg_hsh (map
)
11384 struct reg_map
*map
;
11386 const struct reg_entry
*r
;
11388 if ((map
->htab
= hash_new ()) == NULL
)
11389 as_fatal (_("virtual memory exhausted"));
11391 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11392 insert_reg (r
, map
->htab
);
11396 insert_reg_alias (str
, regnum
, htab
)
11399 struct hash_control
*htab
;
11402 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11403 const char *name
= xmalloc (strlen (str
) + 1);
11405 strcpy ((char *) name
, str
);
11408 new->number
= regnum
;
11409 new->builtin
= FALSE
;
11411 error
= hash_insert (htab
, name
, (PTR
) new);
11414 as_bad (_("failed to create an alias for %s, reason: %s"),
11416 free ((char *) name
);
11421 /* Look for the .req directive. This is of the form:
11423 new_register_name .req existing_register_name
11425 If we find one, or if it looks sufficiently like one that we want to
11426 handle any error here, return non-zero. Otherwise return zero. */
11428 create_register_alias (newname
, p
)
11436 skip_whitespace (q
);
11441 if (*q
&& !strncmp (q
, ".req ", 5))
11446 #ifdef IGNORE_OPCODE_CASE
11447 newname
= original_case_string
;
11449 copy_of_str
= newname
;
11452 skip_whitespace (q
);
11454 for (r
= q
; *r
!= '\0'; r
++)
11460 enum arm_reg_type new_type
, old_type
;
11465 old_type
= arm_reg_parse_any (q
);
11468 new_type
= arm_reg_parse_any (newname
);
11470 if (new_type
== REG_TYPE_MAX
)
11472 if (old_type
!= REG_TYPE_MAX
)
11474 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11475 insert_reg_alias (newname
, old_regno
,
11476 all_reg_maps
[old_type
].htab
);
11479 as_warn (_("register '%s' does not exist\n"), q
);
11481 else if (old_type
== REG_TYPE_MAX
)
11483 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11488 /* Do not warn about redefinitions to the same alias. */
11489 if (new_type
!= old_type
11490 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11491 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11492 as_warn (_("ignoring redefinition of register alias '%s'"),
11498 as_warn (_("ignoring incomplete .req pseuso op"));
11509 set_constant_flonums ()
11513 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11514 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11518 /* Iterate over the base tables to create the instruction patterns. */
11520 build_arm_ops_hsh ()
11524 static struct obstack insn_obstack
;
11526 obstack_begin (&insn_obstack
, 4000);
11528 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11530 const struct asm_opcode
*insn
= insns
+ i
;
11532 if (insn
->cond_offset
!= 0)
11534 /* Insn supports conditional execution. Build the varaints
11535 and insert them in the hash table. */
11536 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11538 unsigned len
= strlen (insn
->template);
11539 struct asm_opcode
*new;
11542 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11543 /* All condition codes are two characters. */
11544 template = obstack_alloc (&insn_obstack
, len
+ 3);
11546 strncpy (template, insn
->template, insn
->cond_offset
);
11547 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11548 if (len
> insn
->cond_offset
)
11549 strcpy (template + insn
->cond_offset
+ 2,
11550 insn
->template + insn
->cond_offset
);
11551 new->template = template;
11552 new->cond_offset
= 0;
11553 new->variant
= insn
->variant
;
11554 new->parms
= insn
->parms
;
11555 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11557 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11560 /* Finally, insert the unconditional insn in the table directly;
11561 no need to build a copy. */
11562 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11566 #if 0 /* Suppressed - for now. */
11567 #if defined OBJ_ELF || defined OBJ_COFF
11570 #define arm_Note Elf_External_Note
11574 unsigned char namesz
[4]; /* Size of entry's owner string. */
11575 unsigned char descsz
[4]; /* Size of the note descriptor. */
11576 unsigned char type
[4]; /* Interpretation of the descriptor. */
11577 char name
[1]; /* Start of the name+desc data. */
11581 /* The description is kept to a fix sized in order to make updating
11582 it and merging it easier. */
11583 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11586 arm_add_note (name
, description
, type
)
11588 const char * description
;
11591 arm_Note note ATTRIBUTE_UNUSED
;
11593 unsigned int name_len
;
11595 name_len
= (strlen (name
) + 1 + 3) & ~3;
11597 p
= frag_more (sizeof (note
.namesz
));
11598 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11600 p
= frag_more (sizeof (note
.descsz
));
11601 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11603 p
= frag_more (sizeof (note
.type
));
11604 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11606 p
= frag_more (name_len
);
11609 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11610 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11611 frag_align (2, 0, 0);
11622 if ( (arm_ops_hsh
= hash_new ()) == NULL
11623 || (arm_tops_hsh
= hash_new ()) == NULL
11624 || (arm_cond_hsh
= hash_new ()) == NULL
11625 || (arm_shift_hsh
= hash_new ()) == NULL
11626 || (arm_psr_hsh
= hash_new ()) == NULL
)
11627 as_fatal (_("virtual memory exhausted"));
11629 build_arm_ops_hsh ();
11630 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11631 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11632 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11633 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11634 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11635 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11636 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11637 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11639 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11640 build_reg_hsh (all_reg_maps
+ i
);
11642 set_constant_flonums ();
11644 /* Set the cpu variant based on the command-line options. We prefer
11645 -mcpu= over -march= if both are set (as for GCC); and we prefer
11646 -mfpu= over any other way of setting the floating point unit.
11647 Use of legacy options with new options are faulted. */
11648 if (legacy_cpu
!= -1)
11650 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11651 as_bad (_("use of old and new-style options to set CPU type"));
11653 mcpu_cpu_opt
= legacy_cpu
;
11655 else if (mcpu_cpu_opt
== -1)
11656 mcpu_cpu_opt
= march_cpu_opt
;
11658 if (legacy_fpu
!= -1)
11660 if (mfpu_opt
!= -1)
11661 as_bad (_("use of old and new-style options to set FPU type"));
11663 mfpu_opt
= legacy_fpu
;
11665 else if (mfpu_opt
== -1)
11667 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11668 /* Some environments specify a default FPU. If they don't, infer it
11669 from the processor. */
11670 if (mcpu_fpu_opt
!= -1)
11671 mfpu_opt
= mcpu_fpu_opt
;
11673 mfpu_opt
= march_fpu_opt
;
11675 mfpu_opt
= FPU_DEFAULT
;
11679 if (mfpu_opt
== -1)
11681 if (mcpu_cpu_opt
== -1)
11682 mfpu_opt
= FPU_DEFAULT
;
11683 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11684 mfpu_opt
= FPU_ARCH_VFP_V2
;
11686 mfpu_opt
= FPU_ARCH_FPA
;
11689 if (mcpu_cpu_opt
== -1)
11690 mcpu_cpu_opt
= CPU_DEFAULT
;
11692 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11695 unsigned int flags
= 0;
11697 #if defined OBJ_ELF
11698 flags
= meabi_flags
;
11700 switch (meabi_flags
)
11702 case EF_ARM_EABI_UNKNOWN
:
11704 #if defined OBJ_COFF || defined OBJ_ELF
11705 /* Set the flags in the private structure. */
11706 if (uses_apcs_26
) flags
|= F_APCS26
;
11707 if (support_interwork
) flags
|= F_INTERWORK
;
11708 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11709 if (pic_code
) flags
|= F_PIC
;
11710 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11711 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11712 flags
|= F_SOFT_FLOAT
;
11714 switch (mfloat_abi_opt
)
11716 case ARM_FLOAT_ABI_SOFT
:
11717 case ARM_FLOAT_ABI_SOFTFP
:
11718 flags
|= F_SOFT_FLOAT
;
11721 case ARM_FLOAT_ABI_HARD
:
11722 if (flags
& F_SOFT_FLOAT
)
11723 as_bad (_("hard-float conflicts with specified fpu"));
11727 /* Using VFP conventions (even if soft-float). */
11728 if (cpu_variant
& FPU_VFP_EXT_NONE
)
11729 flags
|= F_VFP_FLOAT
;
11731 #if defined OBJ_ELF
11732 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11733 flags
|= EF_ARM_MAVERICK_FLOAT
;
11736 case EF_ARM_EABI_VER3
:
11737 /* No additional flags to set. */
11744 #if defined OBJ_COFF || defined OBJ_ELF
11745 bfd_set_private_flags (stdoutput
, flags
);
11747 /* We have run out flags in the COFF header to encode the
11748 status of ATPCS support, so instead we create a dummy,
11749 empty, debug section called .arm.atpcs. */
11754 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11758 bfd_set_section_flags
11759 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11760 bfd_set_section_size (stdoutput
, sec
, 0);
11761 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11767 /* Record the CPU type as well. */
11768 switch (cpu_variant
& ARM_CPU_MASK
)
11771 mach
= bfd_mach_arm_2
;
11774 case ARM_3
: /* Also ARM_250. */
11775 mach
= bfd_mach_arm_2a
;
11778 case ARM_6
: /* Also ARM_7. */
11779 mach
= bfd_mach_arm_3
;
11783 mach
= bfd_mach_arm_unknown
;
11787 /* Catch special cases. */
11788 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11789 mach
= bfd_mach_arm_iWMMXt
;
11790 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11791 mach
= bfd_mach_arm_XScale
;
11792 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11793 mach
= bfd_mach_arm_ep9312
;
11794 else if (cpu_variant
& ARM_EXT_V5E
)
11795 mach
= bfd_mach_arm_5TE
;
11796 else if (cpu_variant
& ARM_EXT_V5
)
11798 if (cpu_variant
& ARM_EXT_V4T
)
11799 mach
= bfd_mach_arm_5T
;
11801 mach
= bfd_mach_arm_5
;
11803 else if (cpu_variant
& ARM_EXT_V4
)
11805 if (cpu_variant
& ARM_EXT_V4T
)
11806 mach
= bfd_mach_arm_4T
;
11808 mach
= bfd_mach_arm_4
;
11810 else if (cpu_variant
& ARM_EXT_V3M
)
11811 mach
= bfd_mach_arm_3M
;
11813 #if 0 /* Suppressed - for now. */
11814 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11816 /* Create a .note section to fully identify this arm binary. */
11818 #define NOTE_ARCH_STRING "arch: "
11820 #if defined OBJ_COFF && ! defined NT_VERSION
11821 #define NT_VERSION 1
11826 segT current_seg
= now_seg
;
11827 subsegT current_subseg
= now_subseg
;
11828 asection
* arm_arch
;
11829 const char * arch_string
;
11831 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11834 bfd_set_section_flags (stdoutput
, arm_arch
,
11835 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11836 | SEC_HAS_CONTENTS
);
11838 bfd_set_section_flags (stdoutput
, arm_arch
,
11839 SEC_READONLY
| SEC_HAS_CONTENTS
);
11841 arm_arch
->output_section
= arm_arch
;
11842 subseg_set (arm_arch
, 0);
11847 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11848 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11849 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11850 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11851 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11852 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11853 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11854 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11855 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11856 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11857 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11858 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11859 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11862 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11864 subseg_set (current_seg
, current_subseg
);
11867 #endif /* Suppressed code. */
11869 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11872 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11873 for use in the a.out file, and stores them in the array pointed to by buf.
11874 This knows about the endian-ness of the target machine and does
11875 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11876 2 (short) and 4 (long) Floating numbers are put out as a series of
11877 LITTLENUMS (shorts, here at least). */
11880 md_number_to_chars (buf
, val
, n
)
11885 if (target_big_endian
)
11886 number_to_chars_bigendian (buf
, val
, n
);
11888 number_to_chars_littleendian (buf
, val
, n
);
11892 md_chars_to_number (buf
, n
)
11897 unsigned char * where
= (unsigned char *) buf
;
11899 if (target_big_endian
)
11904 result
|= (*where
++ & 255);
11912 result
|= (where
[n
] & 255);
11919 /* Turn a string in input_line_pointer into a floating point constant
11920 of type TYPE, and store the appropriate bytes in *LITP. The number
11921 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11922 returned, or NULL on OK.
11924 Note that fp constants aren't represent in the normal way on the ARM.
11925 In big endian mode, things are as expected. However, in little endian
11926 mode fp constants are big-endian word-wise, and little-endian byte-wise
11927 within the words. For example, (double) 1.1 in big endian mode is
11928 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11929 the byte sequence 99 99 f1 3f 9a 99 99 99.
11931 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11934 md_atof (type
, litP
, sizeP
)
11940 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11972 return _("bad call to MD_ATOF()");
11975 t
= atof_ieee (input_line_pointer
, type
, words
);
11977 input_line_pointer
= t
;
11980 if (target_big_endian
)
11982 for (i
= 0; i
< prec
; i
++)
11984 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11990 if (cpu_variant
& FPU_ARCH_VFP
)
11991 for (i
= prec
- 1; i
>= 0; i
--)
11993 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11997 /* For a 4 byte float the order of elements in `words' is 1 0.
11998 For an 8 byte float the order is 1 0 3 2. */
11999 for (i
= 0; i
< prec
; i
+= 2)
12001 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
12002 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
12010 /* The knowledge of the PC's pipeline offset is built into the insns
12014 md_pcrel_from (fixP
)
12018 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
12019 && fixP
->fx_subsy
== NULL
)
12022 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
12024 /* PC relative addressing on the Thumb is slightly odd
12025 as the bottom two bits of the PC are forced to zero
12026 for the calculation. */
12027 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
12031 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12032 so we un-adjust here to compensate for the accommodation. */
12033 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
12035 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
12039 /* Round up a section size to the appropriate boundary. */
12042 md_section_align (segment
, size
)
12043 segT segment ATTRIBUTE_UNUSED
;
12049 /* Round all sects to multiple of 4. */
12050 return (size
+ 3) & ~3;
12054 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12055 Otherwise we have no need to default values of symbols. */
12058 md_undefined_symbol (name
)
12059 char * name ATTRIBUTE_UNUSED
;
12062 if (name
[0] == '_' && name
[1] == 'G'
12063 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
12067 if (symbol_find (name
))
12068 as_bad ("GOT already in the symbol table");
12070 GOT_symbol
= symbol_new (name
, undefined_section
,
12071 (valueT
) 0, & zero_address_frag
);
12081 /* arm_reg_parse () := if it looks like a register, return its token and
12082 advance the pointer. */
12085 arm_reg_parse (ccp
, htab
)
12086 register char ** ccp
;
12087 struct hash_control
*htab
;
12089 char * start
= * ccp
;
12092 struct reg_entry
* reg
;
12094 #ifdef REGISTER_PREFIX
12095 if (*start
!= REGISTER_PREFIX
)
12100 #ifdef OPTIONAL_REGISTER_PREFIX
12101 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12105 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12109 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12113 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12119 return reg
->number
;
12125 /* Search for the following register name in each of the possible reg name
12126 tables. Return the classification if found, or REG_TYPE_MAX if not
12128 static enum arm_reg_type
12129 arm_reg_parse_any (cp
)
12134 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12135 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12136 return (enum arm_reg_type
) i
;
12138 return REG_TYPE_MAX
;
12142 md_apply_fix3 (fixP
, valP
, seg
)
12147 offsetT value
= * valP
;
12149 unsigned int newimm
;
12150 unsigned long temp
;
12152 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12153 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12155 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12157 /* Note whether this will delete the relocation. */
12159 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12160 doesn't work fully.) */
12161 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12162 && !fixP
->fx_pcrel
)
12164 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12168 /* If this symbol is in a different section then we need to leave it for
12169 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12170 so we have to undo it's effects here. */
12171 if (fixP
->fx_pcrel
)
12173 if (fixP
->fx_addsy
!= NULL
12174 && S_IS_DEFINED (fixP
->fx_addsy
)
12175 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12178 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12179 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12183 value
+= md_pcrel_from (fixP
);
12187 /* Remember value for emit_reloc. */
12188 fixP
->fx_addnumber
= value
;
12190 switch (fixP
->fx_r_type
)
12192 case BFD_RELOC_ARM_IMMEDIATE
:
12193 newimm
= validate_immediate (value
);
12194 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12196 /* If the instruction will fail, see if we can fix things up by
12197 changing the opcode. */
12198 if (newimm
== (unsigned int) FAIL
12199 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12201 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12202 _("invalid constant (%lx) after fixup"),
12203 (unsigned long) value
);
12207 newimm
|= (temp
& 0xfffff000);
12208 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12212 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12214 unsigned int highpart
= 0;
12215 unsigned int newinsn
= 0xe1a00000; /* nop. */
12217 newimm
= validate_immediate (value
);
12218 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12220 /* If the instruction will fail, see if we can fix things up by
12221 changing the opcode. */
12222 if (newimm
== (unsigned int) FAIL
12223 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12225 /* No ? OK - try using two ADD instructions to generate
12227 newimm
= validate_immediate_twopart (value
, & highpart
);
12229 /* Yes - then make sure that the second instruction is
12231 if (newimm
!= (unsigned int) FAIL
)
12233 /* Still No ? Try using a negated value. */
12234 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12235 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12236 /* Otherwise - give up. */
12239 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12240 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12245 /* Replace the first operand in the 2nd instruction (which
12246 is the PC) with the destination register. We have
12247 already added in the PC in the first instruction and we
12248 do not want to do it again. */
12249 newinsn
&= ~ 0xf0000;
12250 newinsn
|= ((newinsn
& 0x0f000) << 4);
12253 newimm
|= (temp
& 0xfffff000);
12254 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12256 highpart
|= (newinsn
& 0xfffff000);
12257 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12261 case BFD_RELOC_ARM_OFFSET_IMM
:
12267 if (validate_offset_imm (value
, 0) == FAIL
)
12269 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12270 _("bad immediate value for offset (%ld)"),
12275 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12276 newval
&= 0xff7ff000;
12277 newval
|= value
| (sign
? INDEX_UP
: 0);
12278 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12281 case BFD_RELOC_ARM_OFFSET_IMM8
:
12282 case BFD_RELOC_ARM_HWLITERAL
:
12288 if (validate_offset_imm (value
, 1) == FAIL
)
12290 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12291 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12292 _("invalid literal constant: pool needs to be closer"));
12294 as_bad (_("bad immediate value for half-word offset (%ld)"),
12299 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12300 newval
&= 0xff7ff0f0;
12301 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12302 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12305 case BFD_RELOC_ARM_LITERAL
:
12311 if (validate_offset_imm (value
, 0) == FAIL
)
12313 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12314 _("invalid literal constant: pool needs to be closer"));
12318 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12319 newval
&= 0xff7ff000;
12320 newval
|= value
| (sign
? INDEX_UP
: 0);
12321 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12324 case BFD_RELOC_ARM_SHIFT_IMM
:
12325 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12326 if (((unsigned long) value
) > 32
12328 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12330 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12331 _("shift expression is too large"));
12336 /* Shifts of zero must be done as lsl. */
12338 else if (value
== 32)
12340 newval
&= 0xfffff07f;
12341 newval
|= (value
& 0x1f) << 7;
12342 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12345 case BFD_RELOC_ARM_SWI
:
12346 if (arm_data
->thumb_mode
)
12348 if (((unsigned long) value
) > 0xff)
12349 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12350 _("invalid swi expression"));
12351 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12353 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12357 if (((unsigned long) value
) > 0x00ffffff)
12358 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12359 _("invalid swi expression"));
12360 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12362 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12366 case BFD_RELOC_ARM_MULTI
:
12367 if (((unsigned long) value
) > 0xffff)
12368 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12369 _("invalid expression in load/store multiple"));
12370 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12371 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12374 case BFD_RELOC_ARM_PCREL_BRANCH
:
12375 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12377 /* Sign-extend a 24-bit number. */
12378 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12382 value
= fixP
->fx_offset
;
12385 /* We are going to store value (shifted right by two) in the
12386 instruction, in a 24 bit, signed field. Thus we need to check
12387 that none of the top 8 bits of the shifted value (top 7 bits of
12388 the unshifted, unsigned value) are set, or that they are all set. */
12389 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12390 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12393 /* Normally we would be stuck at this point, since we cannot store
12394 the absolute address that is the destination of the branch in the
12395 24 bits of the branch instruction. If however, we happen to know
12396 that the destination of the branch is in the same section as the
12397 branch instruction itself, then we can compute the relocation for
12398 ourselves and not have to bother the linker with it.
12400 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12401 because I have not worked out how to do this for OBJ_COFF or
12404 && fixP
->fx_addsy
!= NULL
12405 && S_IS_DEFINED (fixP
->fx_addsy
)
12406 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12408 /* Get pc relative value to go into the branch. */
12411 /* Permit a backward branch provided that enough bits
12412 are set. Allow a forwards branch, provided that
12413 enough bits are clear. */
12414 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12415 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12419 if (! fixP
->fx_done
)
12421 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12422 _("GAS can't handle same-section branch dest >= 0x04000000"));
12426 value
+= SEXT24 (newval
);
12428 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12429 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12430 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12431 _("out of range branch"));
12433 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12434 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12437 case BFD_RELOC_ARM_PCREL_BLX
:
12440 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12444 value
= fixP
->fx_offset
;
12446 hbit
= (value
>> 1) & 1;
12447 value
= (value
>> 2) & 0x00ffffff;
12448 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12449 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12450 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12454 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12455 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12457 addressT diff
= (newval
& 0xff) << 1;
12462 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12463 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12464 _("branch out of range"));
12465 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12467 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12470 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12471 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12473 addressT diff
= (newval
& 0x7ff) << 1;
12478 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12479 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12480 _("branch out of range"));
12481 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12483 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12486 case BFD_RELOC_THUMB_PCREL_BLX
:
12487 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12492 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12493 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12494 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12495 if (diff
& 0x400000)
12498 value
= fixP
->fx_offset
;
12502 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12503 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12504 _("branch with link out of range"));
12506 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12507 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12508 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12509 /* For a BLX instruction, make sure that the relocation is rounded up
12510 to a word boundary. This follows the semantics of the instruction
12511 which specifies that bit 1 of the target address will come from bit
12512 1 of the base address. */
12513 newval2
= (newval2
+ 1) & ~ 1;
12514 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12515 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12520 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12521 md_number_to_chars (buf
, value
, 1);
12523 else if (!target_oabi
)
12525 value
= fixP
->fx_offset
;
12526 md_number_to_chars (buf
, value
, 1);
12532 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12533 md_number_to_chars (buf
, value
, 2);
12535 else if (!target_oabi
)
12537 value
= fixP
->fx_offset
;
12538 md_number_to_chars (buf
, value
, 2);
12544 case BFD_RELOC_ARM_GOT32
:
12545 case BFD_RELOC_ARM_GOTOFF
:
12546 md_number_to_chars (buf
, 0, 4);
12550 case BFD_RELOC_RVA
:
12552 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12553 md_number_to_chars (buf
, value
, 4);
12555 else if (!target_oabi
)
12557 value
= fixP
->fx_offset
;
12558 md_number_to_chars (buf
, value
, 4);
12564 case BFD_RELOC_ARM_PLT32
:
12565 /* It appears the instruction is fully prepared at this point. */
12569 case BFD_RELOC_ARM_CP_OFF_IMM
:
12571 if (value
< -1023 || value
> 1023 || (value
& 3))
12572 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12573 _("illegal value for co-processor offset"));
12576 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12577 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12578 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12581 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12583 if (value
< -255 || value
> 255)
12584 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12585 _("Illegal value for co-processor offset"));
12588 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12589 newval
|= value
| (sign
? INDEX_UP
: 0);
12590 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12593 case BFD_RELOC_ARM_THUMB_OFFSET
:
12594 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12595 /* Exactly what ranges, and where the offset is inserted depends
12596 on the type of instruction, we can establish this from the
12598 switch (newval
>> 12)
12600 case 4: /* PC load. */
12601 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12602 forced to zero for these loads, so we will need to round
12603 up the offset if the instruction address is not word
12604 aligned (since the final address produced must be, and
12605 we can only describe word-aligned immediate offsets). */
12607 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12608 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12609 _("invalid offset, target not word aligned (0x%08X)"),
12610 (unsigned int) (fixP
->fx_frag
->fr_address
12611 + fixP
->fx_where
+ value
));
12613 if ((value
+ 2) & ~0x3fe)
12614 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12615 _("invalid offset, value too big (0x%08lX)"),
12618 /* Round up, since pc will be rounded down. */
12619 newval
|= (value
+ 2) >> 2;
12622 case 9: /* SP load/store. */
12623 if (value
& ~0x3fc)
12624 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12625 _("invalid offset, value too big (0x%08lX)"),
12627 newval
|= value
>> 2;
12630 case 6: /* Word load/store. */
12632 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12633 _("invalid offset, value too big (0x%08lX)"),
12635 newval
|= value
<< 4; /* 6 - 2. */
12638 case 7: /* Byte load/store. */
12640 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12641 _("invalid offset, value too big (0x%08lX)"),
12643 newval
|= value
<< 6;
12646 case 8: /* Halfword load/store. */
12648 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12649 _("invalid offset, value too big (0x%08lX)"),
12651 newval
|= value
<< 5; /* 6 - 1. */
12655 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12656 "Unable to process relocation for thumb opcode: %lx",
12657 (unsigned long) newval
);
12660 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12663 case BFD_RELOC_ARM_THUMB_ADD
:
12664 /* This is a complicated relocation, since we use it for all of
12665 the following immediate relocations:
12669 9bit ADD/SUB SP word-aligned
12670 10bit ADD PC/SP word-aligned
12672 The type of instruction being processed is encoded in the
12679 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12681 int rd
= (newval
>> 4) & 0xf;
12682 int rs
= newval
& 0xf;
12683 int subtract
= newval
& 0x8000;
12687 if (value
& ~0x1fc)
12688 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12689 _("invalid immediate for stack address calculation"));
12690 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12691 newval
|= value
>> 2;
12693 else if (rs
== REG_PC
|| rs
== REG_SP
)
12697 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12698 _("invalid immediate for address calculation (value = 0x%08lX)"),
12699 (unsigned long) value
);
12700 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12702 newval
|= value
>> 2;
12707 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12708 _("invalid 8bit immediate"));
12709 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12710 newval
|= (rd
<< 8) | value
;
12715 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12716 _("invalid 3bit immediate"));
12717 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12718 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12721 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12724 case BFD_RELOC_ARM_THUMB_IMM
:
12725 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12726 switch (newval
>> 11)
12728 case 0x04: /* 8bit immediate MOV. */
12729 case 0x05: /* 8bit immediate CMP. */
12730 if (value
< 0 || value
> 255)
12731 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12732 _("invalid immediate: %ld is too large"),
12740 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12743 case BFD_RELOC_ARM_THUMB_SHIFT
:
12744 /* 5bit shift value (0..31). */
12745 if (value
< 0 || value
> 31)
12746 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12747 _("illegal Thumb shift value: %ld"), (long) value
);
12748 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12749 newval
|= value
<< 6;
12750 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12753 case BFD_RELOC_VTABLE_INHERIT
:
12754 case BFD_RELOC_VTABLE_ENTRY
:
12758 case BFD_RELOC_NONE
:
12760 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12761 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12765 /* Translate internal representation of relocation info to BFD target
12769 tc_gen_reloc (section
, fixp
)
12770 asection
* section ATTRIBUTE_UNUSED
;
12774 bfd_reloc_code_real_type code
;
12776 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12778 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12779 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12780 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12782 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12784 if (fixp
->fx_pcrel
== 0)
12785 reloc
->addend
= fixp
->fx_offset
;
12787 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12788 #else /* OBJ_ELF */
12789 reloc
->addend
= fixp
->fx_offset
;
12792 switch (fixp
->fx_r_type
)
12795 if (fixp
->fx_pcrel
)
12797 code
= BFD_RELOC_8_PCREL
;
12802 if (fixp
->fx_pcrel
)
12804 code
= BFD_RELOC_16_PCREL
;
12809 if (fixp
->fx_pcrel
)
12811 code
= BFD_RELOC_32_PCREL
;
12815 case BFD_RELOC_ARM_PCREL_BRANCH
:
12816 case BFD_RELOC_ARM_PCREL_BLX
:
12817 case BFD_RELOC_RVA
:
12818 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12819 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12820 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12821 case BFD_RELOC_THUMB_PCREL_BLX
:
12822 case BFD_RELOC_VTABLE_ENTRY
:
12823 case BFD_RELOC_VTABLE_INHERIT
:
12824 code
= fixp
->fx_r_type
;
12827 case BFD_RELOC_ARM_LITERAL
:
12828 case BFD_RELOC_ARM_HWLITERAL
:
12829 /* If this is called then the a literal has
12830 been referenced across a section boundary. */
12831 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12832 _("literal referenced across section boundary"));
12836 case BFD_RELOC_ARM_GOT32
:
12837 case BFD_RELOC_ARM_GOTOFF
:
12838 case BFD_RELOC_ARM_PLT32
:
12839 code
= fixp
->fx_r_type
;
12843 case BFD_RELOC_ARM_IMMEDIATE
:
12844 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12845 _("internal relocation (type: IMMEDIATE) not fixed up"));
12848 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12849 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12850 _("ADRL used for a symbol not defined in the same file"));
12853 case BFD_RELOC_ARM_OFFSET_IMM
:
12854 if (fixp
->fx_addsy
!= NULL
12855 && !S_IS_DEFINED (fixp
->fx_addsy
)
12856 && S_IS_LOCAL (fixp
->fx_addsy
))
12858 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12859 _("undefined local label `%s'"),
12860 S_GET_NAME (fixp
->fx_addsy
));
12864 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12865 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12872 switch (fixp
->fx_r_type
)
12874 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12875 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12876 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12877 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12878 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12879 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12880 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12881 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12882 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12883 default: type
= _("<unknown>"); break;
12885 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12886 _("cannot represent %s relocation in this object file format"),
12893 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12895 && fixp
->fx_addsy
== GOT_symbol
)
12897 code
= BFD_RELOC_ARM_GOTPC
;
12898 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12902 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12904 if (reloc
->howto
== NULL
)
12906 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12907 _("cannot represent %s relocation in this object file format"),
12908 bfd_get_reloc_code_name (code
));
12912 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12913 vtable entry to be used in the relocation's section offset. */
12914 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12915 reloc
->address
= fixp
->fx_offset
;
12921 md_estimate_size_before_relax (fragP
, segtype
)
12922 fragS
* fragP ATTRIBUTE_UNUSED
;
12923 segT segtype ATTRIBUTE_UNUSED
;
12925 as_fatal (_("md_estimate_size_before_relax\n"));
12937 as_bad ("%s -- `%s'", inst
.error
, str
);
12941 to
= frag_more (inst
.size
);
12943 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12945 assert (inst
.size
== (2 * THUMB_SIZE
));
12946 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12947 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12949 else if (inst
.size
> INSN_SIZE
)
12951 assert (inst
.size
== (2 * INSN_SIZE
));
12952 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12953 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12956 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12958 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12959 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12960 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12964 dwarf2_emit_insn (inst
.size
);
12976 /* Align the instruction.
12977 This may not be the right thing to do but ... */
12982 /* Align the previous label if needed. */
12983 if (last_label_seen
!= NULL
)
12985 symbol_set_frag (last_label_seen
, frag_now
);
12986 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12987 S_SET_SEGMENT (last_label_seen
, now_seg
);
12990 memset (&inst
, '\0', sizeof (inst
));
12991 inst
.reloc
.type
= BFD_RELOC_NONE
;
12993 skip_whitespace (str
);
12995 /* Scan up to the end of the op-code, which must end in white space or
12997 for (start
= p
= str
; *p
!= '\0'; p
++)
13003 as_bad (_("no operator -- statement `%s'\n"), str
);
13009 const struct thumb_opcode
* opcode
;
13013 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
13018 /* Check that this instruction is supported for this CPU. */
13019 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
13021 as_bad (_("selected processor does not support `%s'"), str
);
13025 mapping_state (MAP_THUMB
);
13026 inst
.instruction
= opcode
->value
;
13027 inst
.size
= opcode
->size
;
13028 (*opcode
->parms
) (p
);
13035 const struct asm_opcode
* opcode
;
13039 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
13044 /* Check that this instruction is supported for this CPU. */
13045 if ((opcode
->variant
& cpu_variant
) == 0)
13047 as_bad (_("selected processor does not support `%s'"), str
);
13051 mapping_state (MAP_ARM
);
13052 inst
.instruction
= opcode
->value
;
13053 inst
.size
= INSN_SIZE
;
13054 (*opcode
->parms
) (p
);
13060 /* It wasn't an instruction, but it might be a register alias of the form
13062 if (create_register_alias (str
, p
))
13065 as_bad (_("bad instruction `%s'"), start
);
13069 Invocation line includes a switch not recognized by the base assembler.
13070 See if it's a processor-specific option.
13072 This routine is somewhat complicated by the need for backwards
13073 compatibility (since older releases of gcc can't be changed).
13074 The new options try to make the interface as compatible as
13077 New options (supported) are:
13079 -mcpu=<cpu name> Assemble for selected processor
13080 -march=<architecture name> Assemble for selected architecture
13081 -mfpu=<fpu architecture> Assemble for selected FPU.
13082 -EB/-mbig-endian Big-endian
13083 -EL/-mlittle-endian Little-endian
13084 -k Generate PIC code
13085 -mthumb Start in Thumb mode
13086 -mthumb-interwork Code supports ARM/Thumb interworking
13088 For now we will also provide support for:
13090 -mapcs-32 32-bit Program counter
13091 -mapcs-26 26-bit Program counter
13092 -macps-float Floats passed in FP registers
13093 -mapcs-reentrant Reentrant code
13095 (sometime these will probably be replaced with -mapcs=<list of options>
13096 and -matpcs=<list of options>)
13098 The remaining options are only supported for back-wards compatibility.
13099 Cpu variants, the arm part is optional:
13100 -m[arm]1 Currently not supported.
13101 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13102 -m[arm]3 Arm 3 processor
13103 -m[arm]6[xx], Arm 6 processors
13104 -m[arm]7[xx][t][[d]m] Arm 7 processors
13105 -m[arm]8[10] Arm 8 processors
13106 -m[arm]9[20][tdmi] Arm 9 processors
13107 -mstrongarm[110[0]] StrongARM processors
13108 -mxscale XScale processors
13109 -m[arm]v[2345[t[e]]] Arm architectures
13110 -mall All (except the ARM1)
13112 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13113 -mfpe-old (No float load/store multiples)
13114 -mvfpxd VFP Single precision
13116 -mno-fpu Disable all floating point instructions
13118 The following CPU names are recognized:
13119 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13120 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13121 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13122 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13123 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13124 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13125 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13129 const char * md_shortopts
= "m:k";
13131 #ifdef ARM_BI_ENDIAN
13132 #define OPTION_EB (OPTION_MD_BASE + 0)
13133 #define OPTION_EL (OPTION_MD_BASE + 1)
13135 #if TARGET_BYTES_BIG_ENDIAN
13136 #define OPTION_EB (OPTION_MD_BASE + 0)
13138 #define OPTION_EL (OPTION_MD_BASE + 1)
13142 struct option md_longopts
[] =
13145 {"EB", no_argument
, NULL
, OPTION_EB
},
13148 {"EL", no_argument
, NULL
, OPTION_EL
},
13150 {NULL
, no_argument
, NULL
, 0}
13153 size_t md_longopts_size
= sizeof (md_longopts
);
13155 struct arm_option_table
13157 char *option
; /* Option name to match. */
13158 char *help
; /* Help information. */
13159 int *var
; /* Variable to change. */
13160 int value
; /* What to change it to. */
13161 char *deprecated
; /* If non-null, print this message. */
13164 struct arm_option_table arm_opts
[] =
13166 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13167 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13168 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13169 &support_interwork
, 1, NULL
},
13170 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13171 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13172 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13173 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13175 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13176 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13177 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13178 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13181 /* These are recognized by the assembler, but have no affect on code. */
13182 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13183 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13185 /* DON'T add any new processors to this list -- we want the whole list
13186 to go away... Add them to the processors table instead. */
13187 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13188 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13189 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13190 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13191 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13192 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13193 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13194 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13195 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13196 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13197 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13198 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13199 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13200 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13201 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13202 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13203 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13204 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13205 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13206 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13207 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13208 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13209 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13210 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13211 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13212 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13213 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13214 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13215 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13216 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13217 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13218 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13219 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13220 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13221 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13222 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13223 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13224 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13225 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13226 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13227 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13228 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13229 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13230 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13231 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13232 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13233 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13234 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13235 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13236 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13237 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13238 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13239 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13240 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13241 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13242 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13243 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13244 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13245 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13246 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13247 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13248 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13249 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13250 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13251 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13252 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13253 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13254 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13255 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13256 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13257 N_("use -mcpu=strongarm110")},
13258 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13259 N_("use -mcpu=strongarm1100")},
13260 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13261 N_("use -mcpu=strongarm1110")},
13262 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13263 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13264 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13266 /* Architecture variants -- don't add any more to this list either. */
13267 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13268 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13269 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13270 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13271 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13272 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13273 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13274 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13275 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13276 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13277 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13278 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13279 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13280 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13281 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13282 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13283 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13284 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13286 /* Floating point variants -- don't add any more to this list either. */
13287 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13288 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13289 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13290 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13291 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13293 {NULL
, NULL
, NULL
, 0, NULL
}
13296 struct arm_cpu_option_table
13300 /* For some CPUs we assume an FPU unless the user explicitly sets
13305 /* This list should, at a minimum, contain all the cpu names
13306 recognized by GCC. */
13307 static struct arm_cpu_option_table arm_cpus
[] =
13309 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13310 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13311 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13312 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13313 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13314 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13315 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13316 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13317 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13318 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13319 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13320 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13321 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13322 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13323 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13324 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13325 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13326 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13327 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13328 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13329 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13330 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13331 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13332 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13333 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13334 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13335 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13336 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13337 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13338 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13339 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13340 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13341 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13342 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13343 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13344 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13345 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13346 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13347 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13348 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13349 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13350 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13351 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13352 /* For V5 or later processors we default to using VFP; but the user
13353 should really set the FPU type explicitly. */
13354 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13355 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13356 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13357 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13358 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13359 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13360 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13361 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13362 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13363 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13364 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13365 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13366 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13367 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13368 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13369 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13370 /* ??? XSCALE is really an architecture. */
13371 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13372 /* ??? iwmmxt is not a processor. */
13373 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13374 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13376 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13380 struct arm_arch_option_table
13387 /* This list should, at a minimum, contain all the architecture names
13388 recognized by GCC. */
13389 static struct arm_arch_option_table arm_archs
[] =
13391 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13392 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13393 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13394 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13395 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13396 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13397 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13398 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13399 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13400 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13401 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13402 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13403 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13404 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13405 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13406 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13407 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13408 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13409 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13410 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13411 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13415 /* ISA extensions in the co-processor space. */
13416 struct arm_arch_extension_table
13422 static struct arm_arch_extension_table arm_extensions
[] =
13424 {"maverick", ARM_CEXT_MAVERICK
},
13425 {"xscale", ARM_CEXT_XSCALE
},
13426 {"iwmmxt", ARM_CEXT_IWMMXT
},
13430 struct arm_fpu_option_table
13436 /* This list should, at a minimum, contain all the fpu names
13437 recognized by GCC. */
13438 static struct arm_fpu_option_table arm_fpus
[] =
13440 {"softfpa", FPU_NONE
},
13441 {"fpe", FPU_ARCH_FPE
},
13442 {"fpe2", FPU_ARCH_FPE
},
13443 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13444 {"fpa", FPU_ARCH_FPA
},
13445 {"fpa10", FPU_ARCH_FPA
},
13446 {"fpa11", FPU_ARCH_FPA
},
13447 {"arm7500fe", FPU_ARCH_FPA
},
13448 {"softvfp", FPU_ARCH_VFP
},
13449 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13450 {"vfp", FPU_ARCH_VFP_V2
},
13451 {"vfp9", FPU_ARCH_VFP_V2
},
13452 {"vfp10", FPU_ARCH_VFP_V2
},
13453 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13454 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13455 {"arm1020t", FPU_ARCH_VFP_V1
},
13456 {"arm1020e", FPU_ARCH_VFP_V2
},
13457 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13458 {"maverick", FPU_ARCH_MAVERICK
},
13462 struct arm_float_abi_option_table
13468 static struct arm_float_abi_option_table arm_float_abis
[] =
13470 {"hard", ARM_FLOAT_ABI_HARD
},
13471 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13472 {"soft", ARM_FLOAT_ABI_SOFT
},
13476 struct arm_eabi_option_table
13479 unsigned int value
;
13483 /* We only know hot to output GNU and ver 3 (AAELF) formats. */
13484 static struct arm_eabi_option_table arm_eabis
[] =
13486 {"gnu", EF_ARM_EABI_UNKNOWN
},
13487 {"3", EF_ARM_EABI_VER3
},
13492 struct arm_long_option_table
13494 char *option
; /* Substring to match. */
13495 char *help
; /* Help information. */
13496 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13497 char *deprecated
; /* If non-null, print this message. */
13501 arm_parse_extension (str
, opt_p
)
13505 while (str
!= NULL
&& *str
!= 0)
13507 struct arm_arch_extension_table
*opt
;
13513 as_bad (_("invalid architectural extension"));
13518 ext
= strchr (str
, '+');
13521 optlen
= ext
- str
;
13523 optlen
= strlen (str
);
13527 as_bad (_("missing architectural extension"));
13531 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13532 if (strncmp (opt
->name
, str
, optlen
) == 0)
13534 *opt_p
|= opt
->value
;
13538 if (opt
->name
== NULL
)
13540 as_bad (_("unknown architectural extnsion `%s'"), str
);
13551 arm_parse_cpu (str
)
13554 struct arm_cpu_option_table
*opt
;
13555 char *ext
= strchr (str
, '+');
13559 optlen
= ext
- str
;
13561 optlen
= strlen (str
);
13565 as_bad (_("missing cpu name `%s'"), str
);
13569 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13570 if (strncmp (opt
->name
, str
, optlen
) == 0)
13572 mcpu_cpu_opt
= opt
->value
;
13573 mcpu_fpu_opt
= opt
->default_fpu
;
13576 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13581 as_bad (_("unknown cpu `%s'"), str
);
13586 arm_parse_arch (str
)
13589 struct arm_arch_option_table
*opt
;
13590 char *ext
= strchr (str
, '+');
13594 optlen
= ext
- str
;
13596 optlen
= strlen (str
);
13600 as_bad (_("missing architecture name `%s'"), str
);
13605 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13606 if (strcmp (opt
->name
, str
) == 0)
13608 march_cpu_opt
= opt
->value
;
13609 march_fpu_opt
= opt
->default_fpu
;
13612 return arm_parse_extension (ext
, &march_cpu_opt
);
13617 as_bad (_("unknown architecture `%s'\n"), str
);
13622 arm_parse_fpu (str
)
13625 struct arm_fpu_option_table
*opt
;
13627 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13628 if (strcmp (opt
->name
, str
) == 0)
13630 mfpu_opt
= opt
->value
;
13634 as_bad (_("unknown floating point format `%s'\n"), str
);
13639 arm_parse_float_abi (str
)
13642 struct arm_float_abi_option_table
*opt
;
13644 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13645 if (strcmp (opt
->name
, str
) == 0)
13647 mfloat_abi_opt
= opt
->value
;
13651 as_bad (_("unknown floating point abi `%s'\n"), str
);
13657 arm_parse_eabi (str
)
13660 struct arm_eabi_option_table
*opt
;
13662 for (opt
= arm_eabis
; opt
->name
!= NULL
; opt
++)
13663 if (strcmp (opt
->name
, str
) == 0)
13665 meabi_flags
= opt
->value
;
13668 as_bad (_("unknown EABI `%s'\n"), str
);
13673 struct arm_long_option_table arm_long_opts
[] =
13675 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13676 arm_parse_cpu
, NULL
},
13677 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13678 arm_parse_arch
, NULL
},
13679 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13680 arm_parse_fpu
, NULL
},
13681 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13682 arm_parse_float_abi
, NULL
},
13684 {"meabi=", N_("<ver>\t assemble for eabi version <ver>"),
13685 arm_parse_eabi
, NULL
},
13687 {NULL
, NULL
, 0, NULL
}
13691 md_parse_option (c
, arg
)
13695 struct arm_option_table
*opt
;
13696 struct arm_long_option_table
*lopt
;
13702 target_big_endian
= 1;
13708 target_big_endian
= 0;
13713 /* Listing option. Just ignore these, we don't support additional
13718 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13720 if (c
== opt
->option
[0]
13721 && ((arg
== NULL
&& opt
->option
[1] == 0)
13722 || strcmp (arg
, opt
->option
+ 1) == 0))
13724 #if WARN_DEPRECATED
13725 /* If the option is deprecated, tell the user. */
13726 if (opt
->deprecated
!= NULL
)
13727 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13728 arg
? arg
: "", _(opt
->deprecated
));
13731 if (opt
->var
!= NULL
)
13732 *opt
->var
= opt
->value
;
13738 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13740 /* These options are expected to have an argument. */
13741 if (c
== lopt
->option
[0]
13743 && strncmp (arg
, lopt
->option
+ 1,
13744 strlen (lopt
->option
+ 1)) == 0)
13746 #if WARN_DEPRECATED
13747 /* If the option is deprecated, tell the user. */
13748 if (lopt
->deprecated
!= NULL
)
13749 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13750 _(lopt
->deprecated
));
13753 /* Call the sup-option parser. */
13754 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13758 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
13769 struct arm_option_table
*opt
;
13770 struct arm_long_option_table
*lopt
;
13772 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13774 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13775 if (opt
->help
!= NULL
)
13776 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13778 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13779 if (lopt
->help
!= NULL
)
13780 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13784 -EB assemble code for a big-endian cpu\n"));
13789 -EL assemble code for a little-endian cpu\n"));
13793 /* We need to be able to fix up arbitrary expressions in some statements.
13794 This is so that we can handle symbols that are an arbitrary distance from
13795 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13796 which returns part of an address in a form which will be valid for
13797 a data instruction. We do this by pushing the expression into a symbol
13798 in the expr_section, and creating a fix for that. */
13801 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13810 arm_fix_data
* arm_data
;
13818 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13822 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13827 /* Mark whether the fix is to a THUMB instruction, or an ARM
13829 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13830 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13831 arm_data
->thumb_mode
= thumb_mode
;
13834 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13837 cons_fix_new_arm (frag
, where
, size
, exp
)
13843 bfd_reloc_code_real_type type
;
13847 FIXME: @@ Should look at CPU word size. */
13851 type
= BFD_RELOC_8
;
13854 type
= BFD_RELOC_16
;
13858 type
= BFD_RELOC_32
;
13861 type
= BFD_RELOC_64
;
13865 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13868 /* A good place to do this, although this was probably not intended
13869 for this kind of use. We need to dump the literal pool before
13870 references are made to a null symbol pointer. */
13875 literal_pool
* pool
;
13877 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13879 /* Put it at the end of the relevent section. */
13880 subseg_set (pool
->section
, pool
->sub_section
);
13886 arm_start_line_hook ()
13888 last_label_seen
= NULL
;
13892 arm_frob_label (sym
)
13895 last_label_seen
= sym
;
13897 ARM_SET_THUMB (sym
, thumb_mode
);
13899 #if defined OBJ_COFF || defined OBJ_ELF
13900 ARM_SET_INTERWORK (sym
, support_interwork
);
13903 /* Note - do not allow local symbols (.Lxxx) to be labeled
13904 as Thumb functions. This is because these labels, whilst
13905 they exist inside Thumb code, are not the entry points for
13906 possible ARM->Thumb calls. Also, these labels can be used
13907 as part of a computed goto or switch statement. eg gcc
13908 can generate code that looks like this:
13910 ldr r2, [pc, .Laaa]
13920 The first instruction loads the address of the jump table.
13921 The second instruction converts a table index into a byte offset.
13922 The third instruction gets the jump address out of the table.
13923 The fourth instruction performs the jump.
13925 If the address stored at .Laaa is that of a symbol which has the
13926 Thumb_Func bit set, then the linker will arrange for this address
13927 to have the bottom bit set, which in turn would mean that the
13928 address computation performed by the third instruction would end
13929 up with the bottom bit set. Since the ARM is capable of unaligned
13930 word loads, the instruction would then load the incorrect address
13931 out of the jump table, and chaos would ensue. */
13932 if (label_is_thumb_function_name
13933 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13934 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13936 /* When the address of a Thumb function is taken the bottom
13937 bit of that address should be set. This will allow
13938 interworking between Arm and Thumb functions to work
13941 THUMB_SET_FUNC (sym
, 1);
13943 label_is_thumb_function_name
= FALSE
;
13947 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13951 arm_adjust_symtab ()
13956 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13958 if (ARM_IS_THUMB (sym
))
13960 if (THUMB_IS_FUNC (sym
))
13962 /* Mark the symbol as a Thumb function. */
13963 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13964 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13965 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13967 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13968 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13970 as_bad (_("%s: unexpected function type: %d"),
13971 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13973 else switch (S_GET_STORAGE_CLASS (sym
))
13976 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13979 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13982 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13990 if (ARM_IS_INTERWORK (sym
))
13991 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13998 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
14000 if (ARM_IS_THUMB (sym
))
14002 elf_symbol_type
* elf_sym
;
14004 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
14005 bind
= ELF_ST_BIND (elf_sym
);
14007 /* If it's a .thumb_func, declare it as so,
14008 otherwise tag label as .code 16. */
14009 if (THUMB_IS_FUNC (sym
))
14010 elf_sym
->internal_elf_sym
.st_info
=
14011 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
14013 elf_sym
->internal_elf_sym
.st_info
=
14014 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
14021 arm_data_in_code ()
14023 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
14025 *input_line_pointer
= '/';
14026 input_line_pointer
+= 5;
14027 *input_line_pointer
= 0;
14035 arm_canonicalize_symbol_name (name
)
14040 if (thumb_mode
&& (len
= strlen (name
)) > 5
14041 && streq (name
+ len
- 5, "/data"))
14042 *(name
+ len
- 5) = 0;
14047 #if defined OBJ_COFF || defined OBJ_ELF
14049 arm_validate_fix (fixP
)
14052 /* If the destination of the branch is a defined symbol which does not have
14053 the THUMB_FUNC attribute, then we must be calling a function which has
14054 the (interfacearm) attribute. We look for the Thumb entry point to that
14055 function and change the branch to refer to that function instead. */
14056 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
14057 && fixP
->fx_addsy
!= NULL
14058 && S_IS_DEFINED (fixP
->fx_addsy
)
14059 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
14061 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
14067 arm_force_relocation (fixp
)
14070 #if defined (OBJ_COFF) && defined (TE_PE)
14071 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
14075 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
14076 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
14077 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
14078 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
14082 /* Resolve these relocations even if the symbol is extern or weak. */
14083 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
14084 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
14085 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14088 return generic_force_reloc (fixp
);
14092 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14093 local labels from being added to the output symbol table when they
14094 are used with the ADRL pseudo op. The ADRL relocation should always
14095 be resolved before the binbary is emitted, so it is safe to say that
14096 it is adjustable. */
14099 arm_fix_adjustable (fixP
)
14102 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14109 /* Relocations against Thumb function names must be left unadjusted,
14110 so that the linker can use this information to correctly set the
14111 bottom bit of their addresses. The MIPS version of this function
14112 also prevents relocations that are mips-16 specific, but I do not
14113 know why it does this.
14116 There is one other problem that ought to be addressed here, but
14117 which currently is not: Taking the address of a label (rather
14118 than a function) and then later jumping to that address. Such
14119 addresses also ought to have their bottom bit set (assuming that
14120 they reside in Thumb code), but at the moment they will not. */
14123 arm_fix_adjustable (fixP
)
14126 if (fixP
->fx_addsy
== NULL
)
14129 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14130 && fixP
->fx_subsy
== NULL
)
14133 /* We need the symbol name for the VTABLE entries. */
14134 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14135 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14138 /* Don't allow symbols to be discarded on GOT related relocs. */
14139 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14140 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14141 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
14148 elf32_arm_target_format ()
14150 if (target_big_endian
)
14153 return "elf32-bigarm-oabi";
14155 return "elf32-bigarm";
14160 return "elf32-littlearm-oabi";
14162 return "elf32-littlearm";
14167 armelf_frob_symbol (symp
, puntp
)
14171 elf_frob_symbol (symp
, puntp
);
14174 static bfd_reloc_code_real_type
14184 bfd_reloc_code_real_type reloc
;
14188 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14189 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14190 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14191 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14192 branch instructions generated by GCC for PLT relocs. */
14193 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14194 { NULL
, 0, BFD_RELOC_UNUSED
}
14198 for (i
= 0, ip
= input_line_pointer
;
14199 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14201 id
[i
] = TOLOWER (*ip
);
14203 for (i
= 0; reloc_map
[i
].str
; i
++)
14204 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14207 input_line_pointer
+= reloc_map
[i
].len
;
14209 return reloc_map
[i
].reloc
;
14213 s_arm_elf_cons (nbytes
)
14218 #ifdef md_flush_pending_output
14219 md_flush_pending_output ();
14222 if (is_it_end_of_statement ())
14224 demand_empty_rest_of_line ();
14228 #ifdef md_cons_align
14229 md_cons_align (nbytes
);
14232 mapping_state (MAP_DATA
);
14235 bfd_reloc_code_real_type reloc
;
14237 expression (& exp
);
14239 if (exp
.X_op
== O_symbol
14240 && * input_line_pointer
== '('
14241 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14243 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14244 int size
= bfd_get_reloc_size (howto
);
14247 as_bad ("%s relocations do not fit in %d bytes",
14248 howto
->name
, nbytes
);
14251 register char *p
= frag_more ((int) nbytes
);
14252 int offset
= nbytes
- size
;
14254 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14259 emit_expr (&exp
, (unsigned int) nbytes
);
14261 while (*input_line_pointer
++ == ',');
14263 /* Put terminator back into stream. */
14264 input_line_pointer
--;
14265 demand_empty_rest_of_line ();
14268 #endif /* OBJ_ELF */
14270 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14271 of an rs_align_code fragment. */
14274 arm_handle_align (fragP
)
14277 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14278 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14279 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14280 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14282 int bytes
, fix
, noop_size
;
14286 if (fragP
->fr_type
!= rs_align_code
)
14289 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14290 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14293 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14294 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14296 if (fragP
->tc_frag_data
)
14298 if (target_big_endian
)
14299 noop
= thumb_bigend_noop
;
14302 noop_size
= sizeof (thumb_noop
);
14306 if (target_big_endian
)
14307 noop
= arm_bigend_noop
;
14310 noop_size
= sizeof (arm_noop
);
14313 if (bytes
& (noop_size
- 1))
14315 fix
= bytes
& (noop_size
- 1);
14316 memset (p
, 0, fix
);
14321 while (bytes
>= noop_size
)
14323 memcpy (p
, noop
, noop_size
);
14325 bytes
-= noop_size
;
14329 fragP
->fr_fix
+= fix
;
14330 fragP
->fr_var
= noop_size
;
14333 /* Called from md_do_align. Used to create an alignment
14334 frag in a code section. */
14337 arm_frag_align_code (n
, max
)
14343 /* We assume that there will never be a requirement
14344 to support alignments greater than 32 bytes. */
14345 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14346 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14348 p
= frag_var (rs_align_code
,
14349 MAX_MEM_FOR_RS_ALIGN_CODE
,
14351 (relax_substateT
) max
,
14359 /* Perform target specific initialisation of a frag. */
14362 arm_init_frag (fragP
)
14365 /* Record whether this frag is in an ARM or a THUMB area. */
14366 fragP
->tc_frag_data
= thumb_mode
;