1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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 /* This array holds the chars that always start a comment. If the
196 pre-processor is disabled, these aren't very useful. */
197 const char comment_chars
[] = "@";
199 /* This array holds the chars that only start a comment at the beginning of
200 a line. If the line seems to have the form '# 123 filename'
201 .line and .file directives will appear in the pre-processed output. */
202 /* Note that input_file.c hand checks for '#' at the beginning of the
203 first line of the input file. This is because the compiler outputs
204 #NO_APP at the beginning of its output. */
205 /* Also note that comments like this one will always work. */
206 const char line_comment_chars
[] = "#";
208 const char line_separator_chars
[] = ";";
210 /* Chars that can be used to separate mant
211 from exp in floating point numbers. */
212 const char EXP_CHARS
[] = "eE";
214 /* Chars that mean this number is a floating point constant. */
218 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
220 /* Prefix characters that indicate the start of an immediate
222 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
225 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
226 symbolS
* GOT_symbol
;
229 /* Size of relocation record. */
230 const int md_reloc_size
= 8;
232 /* 0: assemble for ARM,
233 1: assemble for Thumb,
234 2: assemble for Thumb even though target CPU does not support thumb
236 static int thumb_mode
= 0;
238 typedef struct arm_fix
246 unsigned long instruction
;
250 bfd_reloc_code_real_type type
;
267 struct asm_shift_properties
269 enum asm_shift_index index
;
270 unsigned long bit_field
;
271 unsigned int allows_0
: 1;
272 unsigned int allows_32
: 1;
275 static const struct asm_shift_properties shift_properties
[] =
277 { SHIFT_LSL
, 0, 1, 0},
278 { SHIFT_LSR
, 0x20, 0, 1},
279 { SHIFT_ASR
, 0x40, 0, 1},
280 { SHIFT_ROR
, 0x60, 0, 0},
281 { SHIFT_RRX
, 0x60, 0, 0}
284 struct asm_shift_name
287 const struct asm_shift_properties
* properties
;
290 static const struct asm_shift_name shift_names
[] =
292 { "asl", shift_properties
+ SHIFT_LSL
},
293 { "lsl", shift_properties
+ SHIFT_LSL
},
294 { "lsr", shift_properties
+ SHIFT_LSR
},
295 { "asr", shift_properties
+ SHIFT_ASR
},
296 { "ror", shift_properties
+ SHIFT_ROR
},
297 { "rrx", shift_properties
+ SHIFT_RRX
},
298 { "ASL", shift_properties
+ SHIFT_LSL
},
299 { "LSL", shift_properties
+ SHIFT_LSL
},
300 { "LSR", shift_properties
+ SHIFT_LSR
},
301 { "ASR", shift_properties
+ SHIFT_ASR
},
302 { "ROR", shift_properties
+ SHIFT_ROR
},
303 { "RRX", shift_properties
+ SHIFT_RRX
}
306 /* Any kind of shift is accepted. */
307 #define NO_SHIFT_RESTRICT 1
308 /* The shift operand must be an immediate value, not a register. */
309 #define SHIFT_IMMEDIATE 0
310 /* The shift must be LSL or ASR and the operand must be an immediate. */
311 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
312 /* The shift must be ASR and the operand must be an immediate. */
313 #define SHIFT_ASR_IMMEDIATE 3
314 /* The shift must be LSL and the operand must be an immediate. */
315 #define SHIFT_LSL_IMMEDIATE 4
317 #define NUM_FLOAT_VALS 8
319 const char * fp_const
[] =
321 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
324 /* Number of littlenums required to hold an extended precision number. */
325 #define MAX_LITTLENUMS 6
327 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
332 /* Whether a Co-processor load/store operation accepts write-back forms. */
341 #define CP_T_X 0x00008000
342 #define CP_T_Y 0x00400000
343 #define CP_T_Pre 0x01000000
344 #define CP_T_UD 0x00800000
345 #define CP_T_WB 0x00200000
347 #define CONDS_BIT 0x00100000
348 #define LOAD_BIT 0x00100000
350 #define DOUBLE_LOAD_FLAG 0x00000001
354 const char * template;
358 #define COND_ALWAYS 0xe0000000
359 #define COND_MASK 0xf0000000
361 static const struct asm_cond conds
[] =
365 {"cs", 0x20000000}, {"hs", 0x20000000},
366 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
383 const char *template;
388 /* The bit that distinguishes CPSR and SPSR. */
389 #define SPSR_BIT (1 << 22)
391 /* How many bits to shift the PSR_xxx bits up by. */
394 #define PSR_c (1 << 0)
395 #define PSR_x (1 << 1)
396 #define PSR_s (1 << 2)
397 #define PSR_f (1 << 3)
399 static const struct asm_psr psrs
[] =
401 {"CPSR", TRUE
, PSR_c
| PSR_f
},
402 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
403 {"SPSR", FALSE
, PSR_c
| PSR_f
},
404 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
405 {"CPSR_flg", TRUE
, PSR_f
},
406 {"CPSR_f", TRUE
, PSR_f
},
407 {"SPSR_flg", FALSE
, PSR_f
},
408 {"SPSR_f", FALSE
, PSR_f
},
409 {"CPSR_c", TRUE
, PSR_c
},
410 {"CPSR_ctl", TRUE
, PSR_c
},
411 {"SPSR_c", FALSE
, PSR_c
},
412 {"SPSR_ctl", FALSE
, PSR_c
},
413 {"CPSR_x", TRUE
, PSR_x
},
414 {"CPSR_s", TRUE
, PSR_s
},
415 {"SPSR_x", FALSE
, PSR_x
},
416 {"SPSR_s", FALSE
, PSR_s
},
417 /* Combinations of flags. */
418 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
419 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
420 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
421 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
422 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
423 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
424 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
425 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
426 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
427 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
428 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
429 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
430 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
431 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
432 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
433 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
434 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
435 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
436 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
437 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
438 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
439 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
440 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
441 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
442 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
443 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
444 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
445 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
446 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
447 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
448 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
449 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
450 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
451 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
452 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
453 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
454 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
455 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
456 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
457 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
458 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
459 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
460 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
461 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
462 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
463 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
464 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
465 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
466 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
467 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
468 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
469 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
470 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
471 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
472 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
473 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
474 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
475 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
476 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
477 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
478 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
479 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
480 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
481 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
482 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
483 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
484 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
485 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
486 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
487 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
488 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
489 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
490 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
491 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
492 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
493 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
494 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
495 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
496 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
497 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
498 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
499 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
500 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
501 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
502 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
503 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
504 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
505 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
506 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
507 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
508 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
509 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
510 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
511 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
512 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
513 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
514 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
515 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
516 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
517 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
518 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
519 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
520 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
521 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
522 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
523 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
524 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
525 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
526 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
527 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
528 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
529 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
530 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
531 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
532 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
533 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
534 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
535 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
536 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
537 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
544 IWMMXT_REG_WR_OR_WC
= 2,
548 enum iwmmxt_insn_type
571 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
576 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
581 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
584 /* VFP system registers. */
591 static const struct vfp_reg vfp_regs
[] =
593 {"fpsid", 0x00000000},
594 {"FPSID", 0x00000000},
595 {"fpscr", 0x00010000},
596 {"FPSCR", 0x00010000},
597 {"fpexc", 0x00080000},
598 {"FPEXC", 0x00080000}
601 /* Structure for a hash table entry for a register. */
609 /* Some well known registers that we refer to directly elsewhere. */
614 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
615 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
616 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
618 /* These are the standard names. Users can add aliases with .req.
619 and delete them with .unreq. */
621 /* Integer Register Numbers. */
622 static const struct reg_entry rn_table
[] =
624 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
625 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
626 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
627 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
628 /* ATPCS Synonyms. */
629 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
630 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
631 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
632 /* Well-known aliases. */
633 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
634 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
638 #define WR_PREFIX 0x200
639 #define WC_PREFIX 0x400
641 static const struct reg_entry iwmmxt_table
[] =
643 /* Intel Wireless MMX technology register names. */
644 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
645 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
646 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
647 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
648 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
649 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
650 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
651 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
652 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
653 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
654 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
655 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
657 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
658 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
659 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
660 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
661 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
662 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
663 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
664 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
665 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
666 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
667 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
668 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
672 /* Co-processor Numbers. */
673 static const struct reg_entry cp_table
[] =
675 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
676 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
677 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
678 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
682 /* Co-processor Register Numbers. */
683 static const struct reg_entry cn_table
[] =
685 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
686 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
687 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
688 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
689 /* Not really valid, but kept for back-wards compatibility. */
690 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
691 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
692 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
693 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
698 static const struct reg_entry fn_table
[] =
700 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
701 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
705 /* VFP SP Registers. */
706 static const struct reg_entry sn_table
[] =
708 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
709 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
710 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
711 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
712 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
713 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
714 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
715 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
719 /* VFP DP Registers. */
720 static const struct reg_entry dn_table
[] =
722 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
723 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
724 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
725 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
729 /* Maverick DSP coprocessor registers. */
730 static const struct reg_entry mav_mvf_table
[] =
732 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
733 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
734 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
735 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
739 static const struct reg_entry mav_mvd_table
[] =
741 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
742 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
743 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
744 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
748 static const struct reg_entry mav_mvfx_table
[] =
750 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
751 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
752 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
753 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
757 static const struct reg_entry mav_mvdx_table
[] =
759 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
760 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
761 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
762 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
766 static const struct reg_entry mav_mvax_table
[] =
768 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
772 static const struct reg_entry mav_dspsc_table
[] =
780 const struct reg_entry
*names
;
782 struct hash_control
*htab
;
783 const char *expected
;
786 struct reg_map all_reg_maps
[] =
788 {rn_table
, 15, NULL
, N_("ARM register expected")},
789 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
790 {cn_table
, 15, NULL
, N_("co-processor register expected")},
791 {fn_table
, 7, NULL
, N_("FPA register expected")},
792 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
793 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
794 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
795 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
796 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
797 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
798 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
799 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
800 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
803 /* Enumeration matching entries in table above. */
807 #define REG_TYPE_FIRST REG_TYPE_RN
819 REG_TYPE_IWMMXT
= 12,
824 /* Functions called by parser. */
825 /* ARM instructions. */
826 static void do_arit
PARAMS ((char *));
827 static void do_cmp
PARAMS ((char *));
828 static void do_mov
PARAMS ((char *));
829 static void do_ldst
PARAMS ((char *));
830 static void do_ldstt
PARAMS ((char *));
831 static void do_ldmstm
PARAMS ((char *));
832 static void do_branch
PARAMS ((char *));
833 static void do_swi
PARAMS ((char *));
835 /* Pseudo Op codes. */
836 static void do_adr
PARAMS ((char *));
837 static void do_adrl
PARAMS ((char *));
838 static void do_empty
PARAMS ((char *));
841 static void do_mul
PARAMS ((char *));
842 static void do_mla
PARAMS ((char *));
845 static void do_swap
PARAMS ((char *));
848 static void do_msr
PARAMS ((char *));
849 static void do_mrs
PARAMS ((char *));
852 static void do_mull
PARAMS ((char *));
855 static void do_ldstv4
PARAMS ((char *));
858 static void do_bx
PARAMS ((char *));
861 static void do_blx
PARAMS ((char *));
862 static void do_bkpt
PARAMS ((char *));
863 static void do_clz
PARAMS ((char *));
864 static void do_lstc2
PARAMS ((char *));
865 static void do_cdp2
PARAMS ((char *));
866 static void do_co_reg2
PARAMS ((char *));
869 static void do_smla
PARAMS ((char *));
870 static void do_smlal
PARAMS ((char *));
871 static void do_smul
PARAMS ((char *));
872 static void do_qadd
PARAMS ((char *));
875 static void do_pld
PARAMS ((char *));
876 static void do_ldrd
PARAMS ((char *));
877 static void do_co_reg2c
PARAMS ((char *));
880 static void do_bxj
PARAMS ((char *));
883 static void do_cps
PARAMS ((char *));
884 static void do_cpsi
PARAMS ((char *));
885 static void do_ldrex
PARAMS ((char *));
886 static void do_pkhbt
PARAMS ((char *));
887 static void do_pkhtb
PARAMS ((char *));
888 static void do_qadd16
PARAMS ((char *));
889 static void do_rev
PARAMS ((char *));
890 static void do_rfe
PARAMS ((char *));
891 static void do_sxtah
PARAMS ((char *));
892 static void do_sxth
PARAMS ((char *));
893 static void do_setend
PARAMS ((char *));
894 static void do_smlad
PARAMS ((char *));
895 static void do_smlald
PARAMS ((char *));
896 static void do_smmul
PARAMS ((char *));
897 static void do_ssat
PARAMS ((char *));
898 static void do_usat
PARAMS ((char *));
899 static void do_srs
PARAMS ((char *));
900 static void do_ssat16
PARAMS ((char *));
901 static void do_usat16
PARAMS ((char *));
902 static void do_strex
PARAMS ((char *));
903 static void do_umaal
PARAMS ((char *));
905 static void do_cps_mode
PARAMS ((char **));
906 static void do_cps_flags
PARAMS ((char **, int));
907 static int do_endian_specifier
PARAMS ((char *));
908 static void do_pkh_core
PARAMS ((char *, int));
909 static void do_sat
PARAMS ((char **, int));
910 static void do_sat16
PARAMS ((char **, int));
912 /* Coprocessor Instructions. */
913 static void do_cdp
PARAMS ((char *));
914 static void do_lstc
PARAMS ((char *));
915 static void do_co_reg
PARAMS ((char *));
917 /* FPA instructions. */
918 static void do_fpa_ctrl
PARAMS ((char *));
919 static void do_fpa_ldst
PARAMS ((char *));
920 static void do_fpa_ldmstm
PARAMS ((char *));
921 static void do_fpa_dyadic
PARAMS ((char *));
922 static void do_fpa_monadic
PARAMS ((char *));
923 static void do_fpa_cmp
PARAMS ((char *));
924 static void do_fpa_from_reg
PARAMS ((char *));
925 static void do_fpa_to_reg
PARAMS ((char *));
927 /* VFP instructions. */
928 static void do_vfp_sp_monadic
PARAMS ((char *));
929 static void do_vfp_dp_monadic
PARAMS ((char *));
930 static void do_vfp_sp_dyadic
PARAMS ((char *));
931 static void do_vfp_dp_dyadic
PARAMS ((char *));
932 static void do_vfp_reg_from_sp
PARAMS ((char *));
933 static void do_vfp_sp_from_reg
PARAMS ((char *));
934 static void do_vfp_reg2_from_sp2
PARAMS ((char *));
935 static void do_vfp_sp2_from_reg2
PARAMS ((char *));
936 static void do_vfp_reg_from_dp
PARAMS ((char *));
937 static void do_vfp_reg2_from_dp
PARAMS ((char *));
938 static void do_vfp_dp_from_reg
PARAMS ((char *));
939 static void do_vfp_dp_from_reg2
PARAMS ((char *));
940 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
941 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
942 static void do_vfp_sp_ldst
PARAMS ((char *));
943 static void do_vfp_dp_ldst
PARAMS ((char *));
944 static void do_vfp_sp_ldstmia
PARAMS ((char *));
945 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
946 static void do_vfp_dp_ldstmia
PARAMS ((char *));
947 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
948 static void do_vfp_xp_ldstmia
PARAMS ((char *));
949 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
950 static void do_vfp_sp_compare_z
PARAMS ((char *));
951 static void do_vfp_dp_compare_z
PARAMS ((char *));
952 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
953 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
956 static void do_xsc_mia
PARAMS ((char *));
957 static void do_xsc_mar
PARAMS ((char *));
958 static void do_xsc_mra
PARAMS ((char *));
961 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
963 static void do_mav_binops_1a
PARAMS ((char *));
964 static void do_mav_binops_1b
PARAMS ((char *));
965 static void do_mav_binops_1c
PARAMS ((char *));
966 static void do_mav_binops_1d
PARAMS ((char *));
967 static void do_mav_binops_1e
PARAMS ((char *));
968 static void do_mav_binops_1f
PARAMS ((char *));
969 static void do_mav_binops_1g
PARAMS ((char *));
970 static void do_mav_binops_1h
PARAMS ((char *));
971 static void do_mav_binops_1i
PARAMS ((char *));
972 static void do_mav_binops_1j
PARAMS ((char *));
973 static void do_mav_binops_1k
PARAMS ((char *));
974 static void do_mav_binops_1l
PARAMS ((char *));
975 static void do_mav_binops_1m
PARAMS ((char *));
976 static void do_mav_binops_1n
PARAMS ((char *));
977 static void do_mav_binops_1o
PARAMS ((char *));
978 static void do_mav_binops_2a
PARAMS ((char *));
979 static void do_mav_binops_2b
PARAMS ((char *));
980 static void do_mav_binops_2c
PARAMS ((char *));
981 static void do_mav_binops_3a
PARAMS ((char *));
982 static void do_mav_binops_3b
PARAMS ((char *));
983 static void do_mav_binops_3c
PARAMS ((char *));
984 static void do_mav_binops_3d
PARAMS ((char *));
985 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
988 static void do_mav_triple_4a
PARAMS ((char *));
989 static void do_mav_triple_4b
PARAMS ((char *));
990 static void do_mav_triple_5a
PARAMS ((char *));
991 static void do_mav_triple_5b
PARAMS ((char *));
992 static void do_mav_triple_5c
PARAMS ((char *));
993 static void do_mav_triple_5d
PARAMS ((char *));
994 static void do_mav_triple_5e
PARAMS ((char *));
995 static void do_mav_triple_5f
PARAMS ((char *));
996 static void do_mav_triple_5g
PARAMS ((char *));
997 static void do_mav_triple_5h
PARAMS ((char *));
998 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
1001 enum arm_reg_type
));
1002 static void do_mav_quad_6a
PARAMS ((char *));
1003 static void do_mav_quad_6b
PARAMS ((char *));
1004 static void do_mav_dspsc_1
PARAMS ((char *));
1005 static void do_mav_dspsc_2
PARAMS ((char *));
1006 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
1007 enum arm_reg_type
));
1008 static void do_mav_shift_1
PARAMS ((char *));
1009 static void do_mav_shift_2
PARAMS ((char *));
1010 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
1011 static void do_mav_ldst_1
PARAMS ((char *));
1012 static void do_mav_ldst_2
PARAMS ((char *));
1013 static void do_mav_ldst_3
PARAMS ((char *));
1014 static void do_mav_ldst_4
PARAMS ((char *));
1016 static int mav_reg_required_here
PARAMS ((char **, int,
1017 enum arm_reg_type
));
1018 static int mav_parse_offset
PARAMS ((char **, int *));
1020 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
1022 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
1023 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
1024 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
1025 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
1027 static int add_to_lit_pool
PARAMS ((void));
1028 static unsigned validate_immediate
PARAMS ((unsigned));
1029 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
1031 static int validate_offset_imm
PARAMS ((unsigned int, int));
1032 static void opcode_select
PARAMS ((int));
1033 static void end_of_line
PARAMS ((char *));
1034 static int reg_required_here
PARAMS ((char **, int));
1035 static int psr_required_here
PARAMS ((char **));
1036 static int co_proc_number
PARAMS ((char **));
1037 static int cp_opc_expr
PARAMS ((char **, int, int));
1038 static int cp_reg_required_here
PARAMS ((char **, int));
1039 static int fp_reg_required_here
PARAMS ((char **, int));
1040 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
1041 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
1042 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1043 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1044 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
1045 static long vfp_dp_reg_list
PARAMS ((char **));
1046 static int vfp_psr_required_here
PARAMS ((char **str
));
1047 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
1048 static int cp_address_offset
PARAMS ((char **));
1049 static int cp_address_required_here
PARAMS ((char **, int));
1050 static int my_get_float_expression
PARAMS ((char **));
1051 static int skip_past_comma
PARAMS ((char **));
1052 static int walk_no_bignums
PARAMS ((symbolS
*));
1053 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1054 static int data_op2
PARAMS ((char **));
1055 static int fp_op2
PARAMS ((char **));
1056 static long reg_list
PARAMS ((char **));
1057 static void thumb_load_store
PARAMS ((char *, int, int));
1058 static int decode_shift
PARAMS ((char **, int));
1059 static int ldst_extend
PARAMS ((char **));
1060 static int ldst_extend_v4
PARAMS ((char **));
1061 static void thumb_add_sub
PARAMS ((char *, int));
1062 static void insert_reg
PARAMS ((const struct reg_entry
*,
1063 struct hash_control
*));
1064 static void thumb_shift
PARAMS ((char *, int));
1065 static void thumb_mov_compare
PARAMS ((char *, int));
1066 static void build_arm_ops_hsh
PARAMS ((void));
1067 static void set_constant_flonums
PARAMS ((void));
1068 static valueT md_chars_to_number
PARAMS ((char *, int));
1069 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1070 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1071 static int create_register_alias
PARAMS ((char *, char *));
1072 static void output_inst
PARAMS ((const char *));
1073 static int accum0_required_here
PARAMS ((char **));
1074 static int ld_mode_required_here
PARAMS ((char **));
1075 static void do_branch25
PARAMS ((char *));
1076 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1078 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1081 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1082 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1083 static void do_iwmmxt_tandc
PARAMS ((char *));
1084 static void do_iwmmxt_tbcst
PARAMS ((char *));
1085 static void do_iwmmxt_textrc
PARAMS ((char *));
1086 static void do_iwmmxt_textrm
PARAMS ((char *));
1087 static void do_iwmmxt_tinsr
PARAMS ((char *));
1088 static void do_iwmmxt_tmcr
PARAMS ((char *));
1089 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1090 static void do_iwmmxt_tmia
PARAMS ((char *));
1091 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1092 static void do_iwmmxt_tmrc
PARAMS ((char *));
1093 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1094 static void do_iwmmxt_torc
PARAMS ((char *));
1095 static void do_iwmmxt_waligni
PARAMS ((char *));
1096 static void do_iwmmxt_wmov
PARAMS ((char *));
1097 static void do_iwmmxt_word_addr
PARAMS ((char *));
1098 static void do_iwmmxt_wrwr
PARAMS ((char *));
1099 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1100 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1101 static void do_iwmmxt_wshufh
PARAMS ((char *));
1102 static void do_iwmmxt_wzero
PARAMS ((char *));
1103 static int cp_byte_address_offset
PARAMS ((char **));
1104 static int cp_byte_address_required_here
PARAMS ((char **));
1106 /* ARM instructions take 4bytes in the object file, Thumb instructions
1110 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1111 #define MAV_MODE1 0x100c
1113 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1114 #define MAV_MODE2 0x0c10
1116 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1117 #define MAV_MODE3 0x100c
1119 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1120 #define MAV_MODE4 0x0c0010
1122 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1123 #define MAV_MODE5 0x00100c
1125 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1126 #define MAV_MODE6 0x00100c05
1130 /* Basic string to match. */
1131 const char * template;
1133 /* Basic instruction code. */
1134 unsigned long value
;
1136 /* Offset into the template where the condition code (if any) will be.
1137 If zero, then the instruction is never conditional. */
1138 unsigned cond_offset
;
1140 /* Which architecture variant provides this instruction. */
1141 unsigned long variant
;
1143 /* Function to call to parse args. */
1144 void (* parms
) PARAMS ((char *));
1147 static const struct asm_opcode insns
[] =
1149 /* Core ARM Instructions. */
1150 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1151 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1152 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1153 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1154 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1155 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1156 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1157 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1158 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1159 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1160 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1161 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1162 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1163 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1164 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1165 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1166 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1167 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1168 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1169 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1171 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1172 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1173 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1174 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1175 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1176 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1177 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1178 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1179 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1180 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1181 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1182 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1184 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1185 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1186 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1187 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1189 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1190 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1191 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1192 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1193 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1194 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1195 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1196 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1198 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1199 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1200 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1201 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1202 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1203 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1204 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1205 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1207 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1208 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1209 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1210 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1211 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1212 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1213 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1214 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1216 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1218 /* XXX This is the wrong place to do this. Think multi-arch. */
1219 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1220 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1222 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1223 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1227 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1228 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1229 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1231 /* ARM 2 multiplies. */
1232 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1233 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1234 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1235 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1237 /* Generic coprocessor instructions. */
1238 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1239 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1240 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1241 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1242 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1243 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1244 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1246 /* ARM 3 - swp instructions. */
1247 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1248 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1250 /* ARM 6 Status register instructions. */
1251 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1252 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1253 /* ScottB: our code uses 0xe128f000 for msr.
1254 NickC: but this is wrong because the bits 16 through 19 are
1255 handled by the PSR_xxx defines above. */
1257 /* ARM 7M long multiplies. */
1258 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1259 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1260 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1261 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1262 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1263 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1264 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1265 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1267 /* ARM Architecture 4. */
1268 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1269 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1270 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1271 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1273 /* ARM Architecture 4T. */
1274 /* Note: bx (and blx) are required on V5, even if the processor does
1275 not support Thumb. */
1276 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1278 /* ARM Architecture 5T. */
1279 /* Note: blx has 2 variants, so the .value is set dynamically.
1280 Only one of the variants has conditional execution. */
1281 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1282 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1283 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1284 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1285 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1286 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1287 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1288 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1289 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1290 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1292 /* ARM Architecture 5TExP. */
1293 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1294 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1295 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1296 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1298 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1299 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1301 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1302 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1303 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1304 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1306 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1307 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1308 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1309 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1311 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1312 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1314 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1315 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1316 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1317 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1319 /* ARM Architecture 5TE. */
1320 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1321 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1322 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1324 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1325 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1327 /* ARM Architecture 5TEJ. */
1328 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1331 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
1332 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
1333 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
1334 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
1335 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
1336 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
1337 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
1338 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
1339 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
1340 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
1341 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
1342 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
1343 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
1344 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
1345 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
1346 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
1347 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
1348 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
1349 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
1350 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
1351 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
1352 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
1353 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
1354 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
1355 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
1356 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
1357 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
1358 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
1359 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
1360 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
1361 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
1362 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
1363 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
1364 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
1365 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
1366 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
1367 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
1368 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
1369 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
1370 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
1371 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
1372 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
1373 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
1374 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
1375 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
1376 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
1377 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
1378 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1379 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1380 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1381 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1382 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1383 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1384 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1385 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1386 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
1387 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
1388 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
1389 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
1390 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
1391 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
1392 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
1393 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
1394 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
1395 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
1396 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
1397 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
1398 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
1399 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
1400 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
1401 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
1402 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
1403 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
1404 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
1405 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
1406 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
1407 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
1408 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
1409 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
1410 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
1411 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
1412 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
1413 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
1414 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
1415 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
1416 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
1417 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
1418 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
1419 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
1420 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
1421 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
1422 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
1423 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
1424 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
1425 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
1426 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
1427 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
1428 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
1429 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
1431 /* Core FPA instruction set (V1). */
1432 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1433 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1434 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1435 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1437 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1438 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1439 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1440 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1442 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1443 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1444 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1445 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1447 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1499 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1501 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1502 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1503 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1504 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1505 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1506 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1507 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1508 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1509 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1510 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1512 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1513 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1514 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1515 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1516 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1517 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1518 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1519 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1520 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1521 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1522 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1523 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1525 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1526 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1527 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1528 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1529 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1530 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1531 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1532 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1533 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1534 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1535 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1536 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1538 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1539 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1540 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1541 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1542 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1543 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1544 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1545 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1546 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1547 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1548 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1549 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1551 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1552 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1553 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1554 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1555 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1556 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1557 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1558 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1559 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1560 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1561 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1562 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1564 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1565 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1566 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1567 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1568 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1569 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1570 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1571 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1572 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1573 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1574 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1575 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1577 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1578 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1579 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1580 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1581 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1582 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1583 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1584 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1585 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1586 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1587 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1588 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1590 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1591 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1592 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1593 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1594 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1595 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1596 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1597 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1598 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1599 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1600 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1601 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1603 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1604 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1605 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1606 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1607 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1608 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1609 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1610 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1611 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1612 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1613 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1614 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1616 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1617 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1618 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1619 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1620 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1621 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1622 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1623 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1624 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1625 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1626 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1627 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1629 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1630 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1631 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1632 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1633 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1634 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1635 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1636 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1637 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1638 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1639 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1640 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1642 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1643 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1644 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1645 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1646 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1647 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1648 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1649 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1650 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1651 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1652 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1653 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1655 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1668 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1670 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1671 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1672 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1673 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1674 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1675 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1676 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1677 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1678 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1679 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1681 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1682 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1683 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1684 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1685 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1686 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1687 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1688 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1689 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1690 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1691 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1692 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1694 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1695 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1696 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1697 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1698 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1699 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1700 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1701 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1702 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1703 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1704 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1705 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1707 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1708 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1709 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1710 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1711 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1712 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1713 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1714 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1715 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1716 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1717 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1718 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1720 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1721 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1722 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1723 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1724 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1725 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1726 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1727 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1728 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1729 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1730 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1731 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1733 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1734 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1735 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1736 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1737 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1738 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1739 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1740 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1741 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1742 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1743 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1744 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1746 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1747 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1748 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1749 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1750 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1751 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1752 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1753 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1754 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1755 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1756 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1757 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1759 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1760 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1761 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1762 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1763 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1764 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1765 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1766 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1767 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1768 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1769 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1770 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1772 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1773 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1774 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1775 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1776 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1777 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1778 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1779 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1780 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1781 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1782 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1783 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1785 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1786 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1787 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1788 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1789 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1790 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1791 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1792 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1793 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1794 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1795 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1796 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1798 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1799 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1800 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1801 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1802 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1803 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1804 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1805 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1806 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1807 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1808 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1809 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1811 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1812 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1813 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1814 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1815 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1816 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1817 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1818 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1819 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1820 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1821 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1822 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1824 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1825 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1826 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1827 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1828 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1829 not be an optional suffix, but part of the instruction. To be
1830 compatible, we accept either. */
1831 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1832 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1834 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1835 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1836 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1837 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1838 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1839 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1840 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1841 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1842 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1843 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1844 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1845 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1847 /* The implementation of the FIX instruction is broken on some
1848 assemblers, in that it accepts a precision specifier as well as a
1849 rounding specifier, despite the fact that this is meaningless.
1850 To be more compatible, we accept it as well, though of course it
1851 does not set any bits. */
1852 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1853 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1854 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1855 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1856 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1857 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1858 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1859 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1860 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1861 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1862 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1863 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1864 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1866 /* Instructions that were new with the real FPA, call them V2. */
1867 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1868 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1869 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1870 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1871 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1872 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1874 /* VFP V1xD (single precision). */
1875 /* Moves and type conversions. */
1876 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1877 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1878 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1879 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1880 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1881 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1882 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1883 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1884 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1885 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1886 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1887 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1889 /* Memory operations. */
1890 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1891 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1892 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1893 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1894 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1895 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1896 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1897 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1898 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1899 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1900 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1901 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1902 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1903 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1904 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1905 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1906 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1907 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1909 /* Monadic operations. */
1910 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1911 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1912 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1914 /* Dyadic operations. */
1915 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1916 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1917 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1918 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1919 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1920 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1921 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1922 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1923 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1926 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1927 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1928 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1929 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1931 /* VFP V1 (Double precision). */
1932 /* Moves and type conversions. */
1933 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1934 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1935 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1936 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1937 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1938 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1939 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1940 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1941 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1942 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1943 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1944 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1945 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1947 /* Memory operations. */
1948 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1949 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1950 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1951 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1952 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1953 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1954 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1955 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1956 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1957 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1959 /* Monadic operations. */
1960 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1961 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1962 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1964 /* Dyadic operations. */
1965 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1966 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1967 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1968 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1969 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1970 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1971 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1972 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1973 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1976 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1977 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1978 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1979 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1982 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
1983 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
1984 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1985 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1987 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1988 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1989 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1990 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1991 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1992 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1993 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1994 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1995 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1997 /* Intel Wireless MMX technology instructions. */
1998 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1999 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
2000 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
2001 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2002 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2003 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2004 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2005 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2006 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2007 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2008 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2009 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2010 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2011 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2012 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2013 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2014 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2015 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2016 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
2017 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
2018 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2019 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2020 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2021 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2022 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2023 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2024 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2025 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2026 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2027 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
2028 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
2029 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2030 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2031 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2032 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2033 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2034 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2035 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2036 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2037 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2038 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2039 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2040 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2041 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2042 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2043 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2044 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
2045 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2046 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2047 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2048 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2049 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2050 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2051 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2052 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2053 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2054 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2055 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2056 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2057 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2058 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2059 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2060 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2061 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2062 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2063 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2064 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2065 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2066 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2067 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2068 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2069 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2070 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2071 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2072 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2073 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2074 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2075 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2076 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2077 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2078 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2079 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2080 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2081 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2082 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2083 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2084 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2085 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2086 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
2087 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2088 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2089 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2090 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2091 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2092 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2093 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2094 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2095 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2096 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2097 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2098 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2099 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2100 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2101 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2102 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2103 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2104 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2105 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2106 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2107 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2108 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
2109 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2110 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2111 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2112 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2113 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2114 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2115 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2116 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2117 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2118 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2119 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2120 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2121 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2122 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2123 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2124 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2125 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2126 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2127 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2128 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2129 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2130 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2131 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2132 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2133 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2134 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2135 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2136 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2137 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2138 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2139 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2140 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2141 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2142 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2143 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2144 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2145 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2146 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2147 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2148 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2149 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2150 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2151 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2152 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2153 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2154 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2155 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2156 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2157 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2158 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2159 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2161 /* Cirrus Maverick instructions. */
2162 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2163 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2164 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2165 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2166 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2167 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2168 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2169 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2170 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2171 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2172 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2173 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2174 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2175 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2176 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2177 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2178 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2179 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2180 {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2181 {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2182 {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2183 {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2184 {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2185 {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2186 {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2187 {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2188 {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2189 {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2190 {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2191 {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2192 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2193 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2194 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2195 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2196 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2197 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2198 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2199 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2200 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2201 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2202 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2203 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2204 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2205 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2206 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2207 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2208 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2209 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2210 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2211 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2212 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2213 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2214 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2215 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2216 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2217 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2218 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2219 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2220 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2221 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2222 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2223 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2224 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2225 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2226 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2227 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2228 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2229 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2230 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2231 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2232 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2233 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2234 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2235 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2236 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2237 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2240 /* Defines for various bits that we will want to toggle. */
2241 #define INST_IMMEDIATE 0x02000000
2242 #define OFFSET_REG 0x02000000
2243 #define HWOFFSET_IMM 0x00400000
2244 #define SHIFT_BY_REG 0x00000010
2245 #define PRE_INDEX 0x01000000
2246 #define INDEX_UP 0x00800000
2247 #define WRITE_BACK 0x00200000
2248 #define LDM_TYPE_2_OR_3 0x00400000
2250 #define LITERAL_MASK 0xf000f000
2251 #define OPCODE_MASK 0xfe1fffff
2252 #define V4_STR_BIT 0x00000020
2254 #define DATA_OP_SHIFT 21
2256 /* Codes to distinguish the arithmetic instructions. */
2257 #define OPCODE_AND 0
2258 #define OPCODE_EOR 1
2259 #define OPCODE_SUB 2
2260 #define OPCODE_RSB 3
2261 #define OPCODE_ADD 4
2262 #define OPCODE_ADC 5
2263 #define OPCODE_SBC 6
2264 #define OPCODE_RSC 7
2265 #define OPCODE_TST 8
2266 #define OPCODE_TEQ 9
2267 #define OPCODE_CMP 10
2268 #define OPCODE_CMN 11
2269 #define OPCODE_ORR 12
2270 #define OPCODE_MOV 13
2271 #define OPCODE_BIC 14
2272 #define OPCODE_MVN 15
2274 /* Thumb v1 (ARMv4T). */
2275 static void do_t_nop
PARAMS ((char *));
2276 static void do_t_arit
PARAMS ((char *));
2277 static void do_t_add
PARAMS ((char *));
2278 static void do_t_asr
PARAMS ((char *));
2279 static void do_t_branch9
PARAMS ((char *));
2280 static void do_t_branch12
PARAMS ((char *));
2281 static void do_t_branch23
PARAMS ((char *));
2282 static void do_t_bx
PARAMS ((char *));
2283 static void do_t_compare
PARAMS ((char *));
2284 static void do_t_ldmstm
PARAMS ((char *));
2285 static void do_t_ldr
PARAMS ((char *));
2286 static void do_t_ldrb
PARAMS ((char *));
2287 static void do_t_ldrh
PARAMS ((char *));
2288 static void do_t_lds
PARAMS ((char *));
2289 static void do_t_lsl
PARAMS ((char *));
2290 static void do_t_lsr
PARAMS ((char *));
2291 static void do_t_mov
PARAMS ((char *));
2292 static void do_t_push_pop
PARAMS ((char *));
2293 static void do_t_str
PARAMS ((char *));
2294 static void do_t_strb
PARAMS ((char *));
2295 static void do_t_strh
PARAMS ((char *));
2296 static void do_t_sub
PARAMS ((char *));
2297 static void do_t_swi
PARAMS ((char *));
2298 static void do_t_adr
PARAMS ((char *));
2300 /* Thumb v2 (ARMv5T). */
2301 static void do_t_blx
PARAMS ((char *));
2302 static void do_t_bkpt
PARAMS ((char *));
2305 static void do_t_cps
PARAMS ((char *));
2306 static void do_t_cpy
PARAMS ((char *));
2307 static void do_t_setend
PARAMS ((char *));;
2309 #define T_OPCODE_MUL 0x4340
2310 #define T_OPCODE_TST 0x4200
2311 #define T_OPCODE_CMN 0x42c0
2312 #define T_OPCODE_NEG 0x4240
2313 #define T_OPCODE_MVN 0x43c0
2315 #define T_OPCODE_ADD_R3 0x1800
2316 #define T_OPCODE_SUB_R3 0x1a00
2317 #define T_OPCODE_ADD_HI 0x4400
2318 #define T_OPCODE_ADD_ST 0xb000
2319 #define T_OPCODE_SUB_ST 0xb080
2320 #define T_OPCODE_ADD_SP 0xa800
2321 #define T_OPCODE_ADD_PC 0xa000
2322 #define T_OPCODE_ADD_I8 0x3000
2323 #define T_OPCODE_SUB_I8 0x3800
2324 #define T_OPCODE_ADD_I3 0x1c00
2325 #define T_OPCODE_SUB_I3 0x1e00
2327 #define T_OPCODE_ASR_R 0x4100
2328 #define T_OPCODE_LSL_R 0x4080
2329 #define T_OPCODE_LSR_R 0x40c0
2330 #define T_OPCODE_ASR_I 0x1000
2331 #define T_OPCODE_LSL_I 0x0000
2332 #define T_OPCODE_LSR_I 0x0800
2334 #define T_OPCODE_MOV_I8 0x2000
2335 #define T_OPCODE_CMP_I8 0x2800
2336 #define T_OPCODE_CMP_LR 0x4280
2337 #define T_OPCODE_MOV_HR 0x4600
2338 #define T_OPCODE_CMP_HR 0x4500
2340 #define T_OPCODE_LDR_PC 0x4800
2341 #define T_OPCODE_LDR_SP 0x9800
2342 #define T_OPCODE_STR_SP 0x9000
2343 #define T_OPCODE_LDR_IW 0x6800
2344 #define T_OPCODE_STR_IW 0x6000
2345 #define T_OPCODE_LDR_IH 0x8800
2346 #define T_OPCODE_STR_IH 0x8000
2347 #define T_OPCODE_LDR_IB 0x7800
2348 #define T_OPCODE_STR_IB 0x7000
2349 #define T_OPCODE_LDR_RW 0x5800
2350 #define T_OPCODE_STR_RW 0x5000
2351 #define T_OPCODE_LDR_RH 0x5a00
2352 #define T_OPCODE_STR_RH 0x5200
2353 #define T_OPCODE_LDR_RB 0x5c00
2354 #define T_OPCODE_STR_RB 0x5400
2356 #define T_OPCODE_PUSH 0xb400
2357 #define T_OPCODE_POP 0xbc00
2359 #define T_OPCODE_BRANCH 0xe7fe
2361 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2363 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2364 #define THUMB_REG_LO 0x1
2365 #define THUMB_REG_HI 0x2
2366 #define THUMB_REG_ANY 0x3
2368 #define THUMB_H1 0x0080
2369 #define THUMB_H2 0x0040
2375 #define THUMB_MOVE 0
2376 #define THUMB_COMPARE 1
2379 #define THUMB_LOAD 0
2380 #define THUMB_STORE 1
2382 #define THUMB_PP_PC_LR 0x0100
2384 /* These three are used for immediate shifts, do not alter. */
2385 #define THUMB_WORD 2
2386 #define THUMB_HALFWORD 1
2387 #define THUMB_BYTE 0
2391 /* Basic string to match. */
2392 const char * template;
2394 /* Basic instruction code. */
2395 unsigned long value
;
2399 /* Which CPU variants this exists for. */
2400 unsigned long variant
;
2402 /* Function to call to parse args. */
2403 void (* parms
) PARAMS ((char *));
2406 static const struct thumb_opcode tinsns
[] =
2408 /* Thumb v1 (ARMv4T). */
2409 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2410 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2411 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2412 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2413 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2414 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2415 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2416 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2417 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2418 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2419 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2420 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2421 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2422 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2423 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2424 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2425 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2426 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2427 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2428 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2429 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2430 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2431 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2432 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2433 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2434 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2435 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2436 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2437 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2438 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2439 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2440 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2441 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2442 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2443 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2444 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2445 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2446 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2447 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2448 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2449 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2450 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2451 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2452 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2453 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2454 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2455 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2456 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2457 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2458 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2459 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2460 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2461 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2462 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2463 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2465 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2466 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2467 /* Thumb v2 (ARMv5T). */
2468 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2469 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2472 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
2473 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
2474 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
2475 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
2476 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
2477 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
2478 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
2479 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
2480 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
2481 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
2482 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
2485 #define BAD_ARGS _("bad arguments to instruction")
2486 #define BAD_PC _("r15 not allowed here")
2487 #define BAD_COND _("instruction is not conditional")
2488 #define ERR_NO_ACCUM _("acc0 expected")
2490 static struct hash_control
* arm_ops_hsh
= NULL
;
2491 static struct hash_control
* arm_tops_hsh
= NULL
;
2492 static struct hash_control
* arm_cond_hsh
= NULL
;
2493 static struct hash_control
* arm_shift_hsh
= NULL
;
2494 static struct hash_control
* arm_psr_hsh
= NULL
;
2496 /* This table describes all the machine specific pseudo-ops the assembler
2497 has to support. The fields are:
2498 pseudo-op name without dot
2499 function to call to execute this pseudo-op
2500 Integer arg to pass to the function. */
2502 static void s_req
PARAMS ((int));
2503 static void s_unreq
PARAMS ((int));
2504 static void s_align
PARAMS ((int));
2505 static void s_bss
PARAMS ((int));
2506 static void s_even
PARAMS ((int));
2507 static void s_ltorg
PARAMS ((int));
2508 static void s_arm
PARAMS ((int));
2509 static void s_thumb
PARAMS ((int));
2510 static void s_code
PARAMS ((int));
2511 static void s_force_thumb
PARAMS ((int));
2512 static void s_thumb_func
PARAMS ((int));
2513 static void s_thumb_set
PARAMS ((int));
2515 static void s_arm_elf_cons
PARAMS ((int));
2518 static int my_get_expression
PARAMS ((expressionS
*, char **));
2520 const pseudo_typeS md_pseudo_table
[] =
2522 /* Never called because '.req' does not start a line. */
2523 { "req", s_req
, 0 },
2524 { "unreq", s_unreq
, 0 },
2525 { "bss", s_bss
, 0 },
2526 { "align", s_align
, 0 },
2527 { "arm", s_arm
, 0 },
2528 { "thumb", s_thumb
, 0 },
2529 { "code", s_code
, 0 },
2530 { "force_thumb", s_force_thumb
, 0 },
2531 { "thumb_func", s_thumb_func
, 0 },
2532 { "thumb_set", s_thumb_set
, 0 },
2533 { "even", s_even
, 0 },
2534 { "ltorg", s_ltorg
, 0 },
2535 { "pool", s_ltorg
, 0 },
2537 { "word", s_arm_elf_cons
, 4 },
2538 { "long", s_arm_elf_cons
, 4 },
2542 { "extend", float_cons
, 'x' },
2543 { "ldouble", float_cons
, 'x' },
2544 { "packed", float_cons
, 'p' },
2548 /* Other internal functions. */
2549 static int arm_parse_extension
PARAMS ((char *, int *));
2550 static int arm_parse_cpu
PARAMS ((char *));
2551 static int arm_parse_arch
PARAMS ((char *));
2552 static int arm_parse_fpu
PARAMS ((char *));
2553 static int arm_parse_float_abi
PARAMS ((char *));
2554 #if 0 /* Suppressed - for now. */
2555 #if defined OBJ_COFF || defined OBJ_ELF
2556 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2560 /* Stuff needed to resolve the label ambiguity
2570 symbolS
* last_label_seen
;
2571 static int label_is_thumb_function_name
= FALSE
;
2573 /* Literal Pool stuff. */
2575 #define MAX_LITERAL_POOL_SIZE 1024
2577 /* Literal pool structure. Held on a per-section
2578 and per-sub-section basis. */
2579 typedef struct literal_pool
2581 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2582 unsigned int next_free_entry
;
2586 subsegT sub_section
;
2587 struct literal_pool
* next
;
2590 /* Pointer to a linked list of literal pools. */
2591 literal_pool
* list_of_pools
= NULL
;
2593 static literal_pool
* find_literal_pool
PARAMS ((void));
2594 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2596 static literal_pool
*
2597 find_literal_pool ()
2599 literal_pool
* pool
;
2601 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2603 if (pool
->section
== now_seg
2604 && pool
->sub_section
== now_subseg
)
2611 static literal_pool
*
2612 find_or_make_literal_pool ()
2614 /* Next literal pool ID number. */
2615 static unsigned int latest_pool_num
= 1;
2616 literal_pool
* pool
;
2618 pool
= find_literal_pool ();
2622 /* Create a new pool. */
2623 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2627 pool
->next_free_entry
= 0;
2628 pool
->section
= now_seg
;
2629 pool
->sub_section
= now_subseg
;
2630 pool
->next
= list_of_pools
;
2631 pool
->symbol
= NULL
;
2633 /* Add it to the list. */
2634 list_of_pools
= pool
;
2637 /* New pools, and emptied pools, will have a NULL symbol. */
2638 if (pool
->symbol
== NULL
)
2640 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2641 (valueT
) 0, &zero_address_frag
);
2642 pool
->id
= latest_pool_num
++;
2649 /* Add the literal in the global 'inst'
2650 structure to the relevent literal pool. */
2654 literal_pool
* pool
;
2657 pool
= find_or_make_literal_pool ();
2659 /* Check if this literal value is already in the pool. */
2660 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2662 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2663 && (inst
.reloc
.exp
.X_op
== O_constant
)
2664 && (pool
->literals
[entry
].X_add_number
2665 == inst
.reloc
.exp
.X_add_number
)
2666 && (pool
->literals
[entry
].X_unsigned
2667 == inst
.reloc
.exp
.X_unsigned
))
2670 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2671 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2672 && (pool
->literals
[entry
].X_add_number
2673 == inst
.reloc
.exp
.X_add_number
)
2674 && (pool
->literals
[entry
].X_add_symbol
2675 == inst
.reloc
.exp
.X_add_symbol
)
2676 && (pool
->literals
[entry
].X_op_symbol
2677 == inst
.reloc
.exp
.X_op_symbol
))
2681 /* Do we need to create a new entry? */
2682 if (entry
== pool
->next_free_entry
)
2684 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2686 inst
.error
= _("literal pool overflow");
2690 pool
->literals
[entry
] = inst
.reloc
.exp
;
2691 pool
->next_free_entry
+= 1;
2694 inst
.reloc
.exp
.X_op
= O_symbol
;
2695 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2696 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2701 /* Can't use symbol_new here, so have to create a symbol and then at
2702 a later date assign it a value. Thats what these functions do. */
2705 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2707 const char * name
; /* It is copied, the caller can modify. */
2708 segT segment
; /* Segment identifier (SEG_<something>). */
2709 valueT valu
; /* Symbol value. */
2710 fragS
* frag
; /* Associated fragment. */
2712 unsigned int name_length
;
2713 char * preserved_copy_of_name
;
2715 name_length
= strlen (name
) + 1; /* +1 for \0. */
2716 obstack_grow (¬es
, name
, name_length
);
2717 preserved_copy_of_name
= obstack_finish (¬es
);
2718 #ifdef STRIP_UNDERSCORE
2719 if (preserved_copy_of_name
[0] == '_')
2720 preserved_copy_of_name
++;
2723 #ifdef tc_canonicalize_symbol_name
2724 preserved_copy_of_name
=
2725 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2728 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2730 S_SET_SEGMENT (symbolP
, segment
);
2731 S_SET_VALUE (symbolP
, valu
);
2732 symbol_clear_list_pointers (symbolP
);
2734 symbol_set_frag (symbolP
, frag
);
2736 /* Link to end of symbol chain. */
2738 extern int symbol_table_frozen
;
2739 if (symbol_table_frozen
)
2743 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2745 obj_symbol_new_hook (symbolP
);
2747 #ifdef tc_symbol_new_hook
2748 tc_symbol_new_hook (symbolP
);
2752 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2753 #endif /* DEBUG_SYMS */
2756 /* Check that an immediate is valid.
2757 If so, convert it to the right format. */
2760 validate_immediate (val
)
2766 #define rotate_left(v, n) (v << n | v >> (32 - n))
2768 for (i
= 0; i
< 32; i
+= 2)
2769 if ((a
= rotate_left (val
, i
)) <= 0xff)
2770 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2775 /* Check to see if an immediate can be computed as two separate immediate
2776 values, added together. We already know that this value cannot be
2777 computed by just one ARM instruction. */
2780 validate_immediate_twopart (val
, highpart
)
2782 unsigned int * highpart
;
2787 for (i
= 0; i
< 32; i
+= 2)
2788 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2794 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2796 else if (a
& 0xff0000)
2800 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2804 assert (a
& 0xff000000);
2805 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2808 return (a
& 0xff) | (i
<< 7);
2815 validate_offset_imm (val
, hwse
)
2819 if ((hwse
&& val
> 255) || val
> 4095)
2826 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2827 (This text is taken from version B-02 of the spec):
2829 4.4.7 Mapping and tagging symbols
2831 A section of an ARM ELF file can contain a mixture of ARM code,
2832 Thumb code, and data. There are inline transitions between code
2833 and data at literal pool boundaries. There can also be inline
2834 transitions between ARM code and Thumb code, for example in
2835 ARM-Thumb inter-working veneers. Linkers, machine-level
2836 debuggers, profiling tools, and disassembly tools need to map
2837 images accurately. For example, setting an ARM breakpoint on a
2838 Thumb location, or in a literal pool, can crash the program
2839 being debugged, ruining the debugging session.
2841 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2842 tagged (see section 4.4.7.2 below) using local symbols (with
2843 binding STB_LOCAL). To assist consumers, mapping and tagging
2844 symbols should be collated first in the symbol table, before
2845 other symbols with binding STB_LOCAL.
2847 To allow properly collated mapping and tagging symbols to be
2848 skipped by consumers that have no interest in them, the first
2849 such symbol should have the name $m and its st_value field equal
2850 to the total number of mapping and tagging symbols (including
2851 the $m) in the symbol table.
2853 4.4.7.1 Mapping symbols
2855 $a Labels the first byte of a sequence of ARM instructions.
2856 Its type is STT_FUNC.
2858 $d Labels the first byte of a sequence of data items.
2859 Its type is STT_OBJECT.
2861 $t Labels the first byte of a sequence of Thumb instructions.
2862 Its type is STT_FUNC.
2864 This list of mapping symbols may be extended in the future.
2866 Section-relative mapping symbols
2868 Mapping symbols defined in a section define a sequence of
2869 half-open address intervals that cover the address range of the
2870 section. Each interval starts at the address defined by a
2871 mapping symbol, and continues up to, but not including, the
2872 address defined by the next (in address order) mapping symbol or
2873 the end of the section. A corollary is that there must be a
2874 mapping symbol defined at the beginning of each section.
2875 Consumers can ignore the size of a section-relative mapping
2876 symbol. Producers can set it to 0.
2878 Absolute mapping symbols
2880 Because of the need to crystallize a Thumb address with the
2881 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2882 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2885 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2886 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2887 where [x, y) denotes the half-open address range from x,
2888 inclusive, to y, exclusive.
2890 In the absence of a mapping symbol, a consumer can interpret a
2891 function symbol with an odd value as the Thumb code address
2892 obtained by clearing the least significant bit of the
2893 value. This interpretation is deprecated, and it may not work in
2896 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2897 the EABI (which is still under development), so they are not
2898 implemented here. */
2900 static enum mstate mapstate
= MAP_UNDEFINED
;
2903 mapping_state (enum mstate state
)
2906 const char * symname
;
2909 if (mapstate
== state
)
2910 /* The mapping symbol has already been emitted.
2911 There is nothing else to do. */
2924 type
= BSF_FUNCTION
;
2928 type
= BSF_FUNCTION
;
2936 seg_info (now_seg
)->tc_segment_info_data
= state
;
2938 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2939 symbol_table_insert (symbolP
);
2940 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2945 THUMB_SET_FUNC (symbolP
, 0);
2946 ARM_SET_THUMB (symbolP
, 0);
2947 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2951 THUMB_SET_FUNC (symbolP
, 1);
2952 ARM_SET_THUMB (symbolP
, 1);
2953 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2962 /* When we change sections we need to issue a new mapping symbol. */
2965 arm_elf_change_section (void)
2969 if (!SEG_NORMAL (now_seg
))
2972 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2974 /* We can ignore sections that only contain debug info. */
2975 if ((flags
& SEC_ALLOC
) == 0)
2978 mapstate
= seg_info (now_seg
)->tc_segment_info_data
;
2981 #define mapping_state(a)
2982 #endif /* OBJ_ELF */
2987 int a ATTRIBUTE_UNUSED
;
2989 as_bad (_("invalid syntax for .req directive"));
2992 /* The .unreq directive deletes an alias which was previously defined
2993 by .req. For example:
2999 s_unreq (int a ATTRIBUTE_UNUSED
)
3004 skip_whitespace (input_line_pointer
);
3005 name
= input_line_pointer
;
3007 while (*input_line_pointer
!= 0
3008 && *input_line_pointer
!= ' '
3009 && *input_line_pointer
!= '\n')
3010 ++input_line_pointer
;
3012 saved_char
= *input_line_pointer
;
3013 *input_line_pointer
= 0;
3017 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
3019 if (req_type
!= REG_TYPE_MAX
)
3021 char *temp_name
= name
;
3022 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
3026 struct reg_entry
*req_entry
;
3028 /* Check to see if this alias is a builtin one. */
3029 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
3032 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
3033 else if (req_entry
->builtin
)
3034 /* FIXME: We are deleting a built in register alias which
3035 points to a const data structure, so we only need to
3036 free up the memory used by the key in the hash table.
3037 Unfortunately we have not recorded this value, so this
3038 is a memory leak. */
3039 /* FIXME: Should we issue a warning message ? */
3043 /* Deleting a user defined alias. We need to free the
3044 key and the value, but fortunately the key is the same
3045 as the value->name field. */
3046 free ((char *) req_entry
->name
);
3051 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3054 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3057 as_bad (_("invalid syntax for .unreq directive"));
3059 *input_line_pointer
= saved_char
;
3060 demand_empty_rest_of_line ();
3065 int ignore ATTRIBUTE_UNUSED
;
3067 /* We don't support putting frags in the BSS segment, we fake it by
3068 marking in_bss, then looking at s_skip for clues. */
3069 subseg_set (bss_section
, 0);
3070 demand_empty_rest_of_line ();
3071 mapping_state (MAP_DATA
);
3076 int ignore ATTRIBUTE_UNUSED
;
3078 /* Never make frag if expect extra pass. */
3080 frag_align (1, 0, 0);
3082 record_alignment (now_seg
, 1);
3084 demand_empty_rest_of_line ();
3089 int ignored ATTRIBUTE_UNUSED
;
3092 literal_pool
* pool
;
3095 pool
= find_literal_pool ();
3097 || pool
->symbol
== NULL
3098 || pool
->next_free_entry
== 0)
3101 mapping_state (MAP_DATA
);
3103 /* Align pool as you have word accesses.
3104 Only make a frag if we have to. */
3106 frag_align (2, 0, 0);
3108 record_alignment (now_seg
, 2);
3110 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3112 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3113 (valueT
) frag_now_fix (), frag_now
);
3114 symbol_table_insert (pool
->symbol
);
3116 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3118 #if defined OBJ_COFF || defined OBJ_ELF
3119 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3122 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3123 /* First output the expression in the instruction to the pool. */
3124 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3126 /* Mark the pool as empty. */
3127 pool
->next_free_entry
= 0;
3128 pool
->symbol
= NULL
;
3131 /* Same as s_align_ptwo but align 0 => align 2. */
3135 int unused ATTRIBUTE_UNUSED
;
3138 register long temp_fill
;
3139 long max_alignment
= 15;
3141 temp
= get_absolute_expression ();
3142 if (temp
> max_alignment
)
3143 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3146 as_bad (_("alignment negative. 0 assumed."));
3150 if (*input_line_pointer
== ',')
3152 input_line_pointer
++;
3153 temp_fill
= get_absolute_expression ();
3161 /* Only make a frag if we HAVE to. */
3162 if (temp
&& !need_pass_2
)
3163 frag_align (temp
, (int) temp_fill
, 0);
3164 demand_empty_rest_of_line ();
3166 record_alignment (now_seg
, temp
);
3170 s_force_thumb (ignore
)
3171 int ignore ATTRIBUTE_UNUSED
;
3173 /* If we are not already in thumb mode go into it, EVEN if
3174 the target processor does not support thumb instructions.
3175 This is used by gcc/config/arm/lib1funcs.asm for example
3176 to compile interworking support functions even if the
3177 target processor should not support interworking. */
3182 record_alignment (now_seg
, 1);
3185 demand_empty_rest_of_line ();
3189 s_thumb_func (ignore
)
3190 int ignore ATTRIBUTE_UNUSED
;
3195 /* The following label is the name/address of the start of a Thumb function.
3196 We need to know this for the interworking support. */
3197 label_is_thumb_function_name
= TRUE
;
3199 demand_empty_rest_of_line ();
3202 /* Perform a .set directive, but also mark the alias as
3203 being a thumb function. */
3209 /* XXX the following is a duplicate of the code for s_set() in read.c
3210 We cannot just call that code as we need to get at the symbol that
3212 register char * name
;
3213 register char delim
;
3214 register char * end_name
;
3215 register symbolS
* symbolP
;
3217 /* Especial apologies for the random logic:
3218 This just grew, and could be parsed much more simply!
3220 name
= input_line_pointer
;
3221 delim
= get_symbol_end ();
3222 end_name
= input_line_pointer
;
3227 if (*input_line_pointer
!= ',')
3230 as_bad (_("expected comma after name \"%s\""), name
);
3232 ignore_rest_of_line ();
3236 input_line_pointer
++;
3239 if (name
[0] == '.' && name
[1] == '\0')
3241 /* XXX - this should not happen to .thumb_set. */
3245 if ((symbolP
= symbol_find (name
)) == NULL
3246 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3249 /* When doing symbol listings, play games with dummy fragments living
3250 outside the normal fragment chain to record the file and line info
3252 if (listing
& LISTING_SYMBOLS
)
3254 extern struct list_info_struct
* listing_tail
;
3255 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3257 memset (dummy_frag
, 0, sizeof (fragS
));
3258 dummy_frag
->fr_type
= rs_fill
;
3259 dummy_frag
->line
= listing_tail
;
3260 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3261 dummy_frag
->fr_symbol
= symbolP
;
3265 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3268 /* "set" symbols are local unless otherwise specified. */
3269 SF_SET_LOCAL (symbolP
);
3270 #endif /* OBJ_COFF */
3271 } /* Make a new symbol. */
3273 symbol_table_insert (symbolP
);
3278 && S_IS_DEFINED (symbolP
)
3279 && S_GET_SEGMENT (symbolP
) != reg_section
)
3280 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3282 pseudo_set (symbolP
);
3284 demand_empty_rest_of_line ();
3286 /* XXX Now we come to the Thumb specific bit of code. */
3288 THUMB_SET_FUNC (symbolP
, 1);
3289 ARM_SET_THUMB (symbolP
, 1);
3290 #if defined OBJ_ELF || defined OBJ_COFF
3291 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3296 opcode_select (width
)
3304 if (! (cpu_variant
& ARM_EXT_V4T
))
3305 as_bad (_("selected processor does not support THUMB opcodes"));
3308 /* No need to force the alignment, since we will have been
3309 coming from ARM mode, which is word-aligned. */
3310 record_alignment (now_seg
, 1);
3312 mapping_state (MAP_THUMB
);
3318 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3319 as_bad (_("selected processor does not support ARM opcodes"));
3324 frag_align (2, 0, 0);
3326 record_alignment (now_seg
, 1);
3328 mapping_state (MAP_ARM
);
3332 as_bad (_("invalid instruction size selected (%d)"), width
);
3338 int ignore ATTRIBUTE_UNUSED
;
3341 demand_empty_rest_of_line ();
3346 int ignore ATTRIBUTE_UNUSED
;
3349 demand_empty_rest_of_line ();
3354 int unused ATTRIBUTE_UNUSED
;
3358 temp
= get_absolute_expression ();
3363 opcode_select (temp
);
3367 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3375 skip_whitespace (str
);
3377 if (*str
!= '\0' && !inst
.error
)
3378 inst
.error
= _("garbage following instruction");
3382 skip_past_comma (str
)
3385 char * p
= * str
, c
;
3388 while ((c
= *p
) == ' ' || c
== ',')
3391 if (c
== ',' && comma
++)
3399 return comma
? SUCCESS
: FAIL
;
3402 /* A standard register must be given at this point.
3403 SHIFT is the place to put it in inst.instruction.
3404 Restores input start point on error.
3405 Returns the reg#, or FAIL. */
3408 reg_required_here (str
, shift
)
3412 static char buff
[128]; /* XXX */
3414 char * start
= * str
;
3416 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3419 inst
.instruction
|= reg
<< shift
;
3423 /* Restore the start point, we may have got a reg of the wrong class. */
3426 /* In the few cases where we might be able to accept something else
3427 this error can be overridden. */
3428 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3434 /* A Intel Wireless MMX technology register
3435 must be given at this point.
3436 Shift is the place to put it in inst.instruction.
3437 Restores input start point on err.
3438 Returns the reg#, or FAIL. */
3441 wreg_required_here (str
, shift
, reg_type
)
3444 enum wreg_type reg_type
;
3446 static char buff
[128];
3448 char * start
= *str
;
3450 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3452 if (wr_register (reg
)
3453 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3456 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3459 else if (wc_register (reg
)
3460 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3463 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3466 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3469 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3474 /* Restore the start point, we may have got a reg of the wrong class. */
3477 /* In the few cases where we might be able to accept
3478 something else this error can be overridden. */
3479 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3485 static const struct asm_psr
*
3487 register char ** ccp
;
3489 char * start
= * ccp
;
3492 const struct asm_psr
* psr
;
3496 /* Skip to the end of the next word in the input stream. */
3501 while (ISALPHA (c
) || c
== '_');
3503 /* Terminate the word. */
3506 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3507 feature for ease of use and backwards compatibility. */
3508 if (!strncmp (start
, "cpsr", 4))
3509 strncpy (start
, "CPSR", 4);
3510 else if (!strncmp (start
, "spsr", 4))
3511 strncpy (start
, "SPSR", 4);
3513 /* Now locate the word in the psr hash table. */
3514 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3516 /* Restore the input stream. */
3519 /* If we found a valid match, advance the
3520 stream pointer past the end of the word. */
3526 /* Parse the input looking for a PSR flag. */
3529 psr_required_here (str
)
3532 char * start
= * str
;
3533 const struct asm_psr
* psr
;
3535 psr
= arm_psr_parse (str
);
3539 /* If this is the SPSR that is being modified, set the R bit. */
3541 inst
.instruction
|= SPSR_BIT
;
3543 /* Set the psr flags in the MSR instruction. */
3544 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3549 /* In the few cases where we might be able to accept
3550 something else this error can be overridden. */
3551 inst
.error
= _("flag for {c}psr instruction expected");
3553 /* Restore the start point. */
3559 co_proc_number (str
)
3562 int processor
, pchar
;
3565 skip_whitespace (*str
);
3568 /* The data sheet seems to imply that just a number on its own is valid
3569 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3571 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3577 if (pchar
>= '0' && pchar
<= '9')
3579 processor
= pchar
- '0';
3580 if (**str
>= '0' && **str
<= '9')
3582 processor
= processor
* 10 + *(*str
)++ - '0';
3585 inst
.error
= _("illegal co-processor number");
3592 inst
.error
= _("bad or missing co-processor number");
3597 inst
.instruction
|= processor
<< 8;
3602 cp_opc_expr (str
, where
, length
)
3609 skip_whitespace (* str
);
3611 memset (&expr
, '\0', sizeof (expr
));
3613 if (my_get_expression (&expr
, str
))
3615 if (expr
.X_op
!= O_constant
)
3617 inst
.error
= _("bad or missing expression");
3621 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3623 inst
.error
= _("immediate co-processor expression too large");
3627 inst
.instruction
|= expr
.X_add_number
<< where
;
3632 cp_reg_required_here (str
, where
)
3637 char * start
= *str
;
3639 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3641 inst
.instruction
|= reg
<< where
;
3645 /* In the few cases where we might be able to accept something else
3646 this error can be overridden. */
3647 inst
.error
= _("co-processor register expected");
3649 /* Restore the start point. */
3655 fp_reg_required_here (str
, where
)
3660 char * start
= * str
;
3662 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3664 inst
.instruction
|= reg
<< where
;
3668 /* In the few cases where we might be able to accept something else
3669 this error can be overridden. */
3670 inst
.error
= _("floating point register expected");
3672 /* Restore the start point. */
3678 cp_address_offset (str
)
3683 skip_whitespace (* str
);
3685 if (! is_immediate_prefix (**str
))
3687 inst
.error
= _("immediate expression expected");
3693 if (my_get_expression (& inst
.reloc
.exp
, str
))
3696 if (inst
.reloc
.exp
.X_op
== O_constant
)
3698 offset
= inst
.reloc
.exp
.X_add_number
;
3702 inst
.error
= _("co-processor address must be word aligned");
3706 if (offset
> 1023 || offset
< -1023)
3708 inst
.error
= _("offset too large");
3713 inst
.instruction
|= INDEX_UP
;
3717 inst
.instruction
|= offset
>> 2;
3720 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3726 cp_address_required_here (str
, wb_ok
)
3739 skip_whitespace (p
);
3741 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3744 skip_whitespace (p
);
3750 skip_whitespace (p
);
3754 /* As an extension to the official ARM syntax we allow:
3758 as a short hand for:
3761 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3766 if (skip_past_comma (& p
) == FAIL
)
3768 inst
.error
= _("comma expected after closing square bracket");
3772 skip_whitespace (p
);
3779 write_back
= WRITE_BACK
;
3783 inst
.error
= _("pc may not be used in post-increment");
3787 if (cp_address_offset (& p
) == FAIL
)
3791 pre_inc
= PRE_INDEX
| INDEX_UP
;
3797 /* [Rn], {<expr>} */
3800 skip_whitespace (p
);
3802 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3805 if (inst
.reloc
.exp
.X_op
== O_constant
)
3807 option
= inst
.reloc
.exp
.X_add_number
;
3809 if (option
> 255 || option
< 0)
3811 inst
.error
= _("'option' field too large");
3815 skip_whitespace (p
);
3819 inst
.error
= _("'}' expected at end of 'option' field");
3825 inst
.instruction
|= option
;
3826 inst
.instruction
|= INDEX_UP
;
3831 inst
.error
= _("non-constant expressions for 'option' field not supported");
3837 inst
.error
= _("# or { expected after comma");
3843 /* '['Rn, #expr']'[!] */
3845 if (skip_past_comma (& p
) == FAIL
)
3847 inst
.error
= _("pre-indexed expression expected");
3851 pre_inc
= PRE_INDEX
;
3853 if (cp_address_offset (& p
) == FAIL
)
3856 skip_whitespace (p
);
3860 inst
.error
= _("missing ]");
3864 skip_whitespace (p
);
3866 if (wb_ok
&& *p
== '!')
3870 inst
.error
= _("pc may not be used with write-back");
3875 write_back
= WRITE_BACK
;
3881 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3884 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3885 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3886 inst
.reloc
.pc_rel
= 1;
3887 inst
.instruction
|= (REG_PC
<< 16);
3888 pre_inc
= PRE_INDEX
;
3891 inst
.instruction
|= write_back
| pre_inc
;
3897 cp_byte_address_offset (str
)
3902 skip_whitespace (* str
);
3904 if (! is_immediate_prefix (**str
))
3906 inst
.error
= _("immediate expression expected");
3912 if (my_get_expression (& inst
.reloc
.exp
, str
))
3915 if (inst
.reloc
.exp
.X_op
== O_constant
)
3917 offset
= inst
.reloc
.exp
.X_add_number
;
3919 if (offset
> 255 || offset
< -255)
3921 inst
.error
= _("offset too large");
3926 inst
.instruction
|= INDEX_UP
;
3930 inst
.instruction
|= offset
;
3933 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3939 cp_byte_address_required_here (str
)
3951 skip_whitespace (p
);
3953 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3956 skip_whitespace (p
);
3962 if (skip_past_comma (& p
) == SUCCESS
)
3965 write_back
= WRITE_BACK
;
3969 inst
.error
= _("pc may not be used in post-increment");
3973 if (cp_byte_address_offset (& p
) == FAIL
)
3977 pre_inc
= PRE_INDEX
| INDEX_UP
;
3981 /* '['Rn, #expr']'[!] */
3983 if (skip_past_comma (& p
) == FAIL
)
3985 inst
.error
= _("pre-indexed expression expected");
3989 pre_inc
= PRE_INDEX
;
3991 if (cp_byte_address_offset (& p
) == FAIL
)
3994 skip_whitespace (p
);
3998 inst
.error
= _("missing ]");
4002 skip_whitespace (p
);
4008 inst
.error
= _("pc may not be used with write-back");
4013 write_back
= WRITE_BACK
;
4019 if (my_get_expression (&inst
.reloc
.exp
, &p
))
4022 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
4023 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4024 inst
.reloc
.pc_rel
= 1;
4025 inst
.instruction
|= (REG_PC
<< 16);
4026 pre_inc
= PRE_INDEX
;
4029 inst
.instruction
|= write_back
| pre_inc
;
4038 /* Do nothing really. */
4048 /* Only one syntax. */
4049 skip_whitespace (str
);
4051 if (reg_required_here (&str
, 12) == FAIL
)
4053 inst
.error
= BAD_ARGS
;
4057 if (skip_past_comma (&str
) == FAIL
)
4059 inst
.error
= _("comma expected after register name");
4063 skip_whitespace (str
);
4065 if ( strcmp (str
, "CPSR") == 0
4066 || strcmp (str
, "SPSR") == 0
4067 /* Lower case versions for backwards compatibility. */
4068 || strcmp (str
, "cpsr") == 0
4069 || strcmp (str
, "spsr") == 0)
4072 /* This is for backwards compatibility with older toolchains. */
4073 else if ( strcmp (str
, "cpsr_all") == 0
4074 || strcmp (str
, "spsr_all") == 0)
4078 inst
.error
= _("CPSR or SPSR expected");
4082 if (* str
== 's' || * str
== 'S')
4083 inst
.instruction
|= SPSR_BIT
;
4089 /* Two possible forms:
4090 "{C|S}PSR_<field>, Rm",
4091 "{C|S}PSR_f, #expression". */
4097 skip_whitespace (str
);
4099 if (psr_required_here (& str
) == FAIL
)
4102 if (skip_past_comma (& str
) == FAIL
)
4104 inst
.error
= _("comma missing after psr flags");
4108 skip_whitespace (str
);
4110 if (reg_required_here (& str
, 0) != FAIL
)
4117 if (! is_immediate_prefix (* str
))
4120 _("only a register or immediate value can follow a psr flag");
4127 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4130 _("only a register or immediate value can follow a psr flag");
4134 #if 0 /* The first edition of the ARM architecture manual stated that
4135 writing anything other than the flags with an immediate operation
4136 had UNPREDICTABLE effects. This constraint was removed in the
4137 second edition of the specification. */
4138 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4139 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4141 inst
.error
= _("immediate value cannot be used to set this field");
4146 inst
.instruction
|= INST_IMMEDIATE
;
4148 if (inst
.reloc
.exp
.X_add_symbol
)
4150 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4151 inst
.reloc
.pc_rel
= 0;
4155 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4157 if (value
== (unsigned) FAIL
)
4159 inst
.error
= _("invalid constant");
4163 inst
.instruction
|= value
;
4170 /* Long Multiply Parser
4171 UMULL RdLo, RdHi, Rm, Rs
4172 SMULL RdLo, RdHi, Rm, Rs
4173 UMLAL RdLo, RdHi, Rm, Rs
4174 SMLAL RdLo, RdHi, Rm, Rs. */
4180 int rdlo
, rdhi
, rm
, rs
;
4182 /* Only one format "rdlo, rdhi, rm, rs". */
4183 skip_whitespace (str
);
4185 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4187 inst
.error
= BAD_ARGS
;
4191 if (skip_past_comma (&str
) == FAIL
4192 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4194 inst
.error
= BAD_ARGS
;
4198 if (skip_past_comma (&str
) == FAIL
4199 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4201 inst
.error
= BAD_ARGS
;
4205 /* rdhi, rdlo and rm must all be different. */
4206 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4207 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4209 if (skip_past_comma (&str
) == FAIL
4210 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4212 inst
.error
= BAD_ARGS
;
4216 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4218 inst
.error
= BAD_PC
;
4231 /* Only one format "rd, rm, rs". */
4232 skip_whitespace (str
);
4234 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4236 inst
.error
= BAD_ARGS
;
4242 inst
.error
= BAD_PC
;
4246 if (skip_past_comma (&str
) == FAIL
4247 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4249 inst
.error
= BAD_ARGS
;
4255 inst
.error
= BAD_PC
;
4260 as_tsktsk (_("rd and rm should be different in mul"));
4262 if (skip_past_comma (&str
) == FAIL
4263 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4265 inst
.error
= BAD_ARGS
;
4271 inst
.error
= BAD_PC
;
4284 /* Only one format "rd, rm, rs, rn". */
4285 skip_whitespace (str
);
4287 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4289 inst
.error
= BAD_ARGS
;
4295 inst
.error
= BAD_PC
;
4299 if (skip_past_comma (&str
) == FAIL
4300 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4302 inst
.error
= BAD_ARGS
;
4308 inst
.error
= BAD_PC
;
4313 as_tsktsk (_("rd and rm should be different in mla"));
4315 if (skip_past_comma (&str
) == FAIL
4316 || (rd
= reg_required_here (&str
, 8)) == FAIL
4317 || skip_past_comma (&str
) == FAIL
4318 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4320 inst
.error
= BAD_ARGS
;
4324 if (rd
== REG_PC
|| rm
== REG_PC
)
4326 inst
.error
= BAD_PC
;
4333 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4334 Advances *str to the next non-alphanumeric.
4335 Returns 0, or else FAIL (in which case sets inst.error).
4337 (In a future XScale, there may be accumulators other than zero.
4338 At that time this routine and its callers can be upgraded to suit.) */
4341 accum0_required_here (str
)
4344 static char buff
[128]; /* Note the address is taken. Hence, static. */
4347 int result
= 0; /* The accum number. */
4349 skip_whitespace (p
);
4351 *str
= p
; /* Advance caller's string pointer too. */
4356 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4358 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4360 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4365 *p
= c
; /* Unzap. */
4366 *str
= p
; /* Caller's string pointer to after match. */
4370 /* Expects **str -> after a comma. May be leading blanks.
4371 Advances *str, recognizing a load mode, and setting inst.instruction.
4372 Returns rn, or else FAIL (in which case may set inst.error
4373 and not advance str)
4375 Note: doesn't know Rd, so no err checks that require such knowledge. */
4378 ld_mode_required_here (string
)
4381 char * str
= * string
;
4385 skip_whitespace (str
);
4391 skip_whitespace (str
);
4393 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4396 skip_whitespace (str
);
4402 if (skip_past_comma (& str
) == SUCCESS
)
4404 /* [Rn],... (post inc) */
4405 if (ldst_extend_v4 (&str
) == FAIL
)
4410 skip_whitespace (str
);
4415 inst
.instruction
|= WRITE_BACK
;
4418 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4424 if (skip_past_comma (& str
) == FAIL
)
4426 inst
.error
= _("pre-indexed expression expected");
4432 if (ldst_extend_v4 (&str
) == FAIL
)
4435 skip_whitespace (str
);
4437 if (* str
++ != ']')
4439 inst
.error
= _("missing ]");
4443 skip_whitespace (str
);
4448 inst
.instruction
|= WRITE_BACK
;
4452 else if (* str
== '=') /* ldr's "r,=label" syntax */
4453 /* We should never reach here, because <text> = <expression> is
4454 caught gas/read.c read_a_source_file() as a .set operation. */
4456 else /* PC +- 8 bit immediate offset. */
4458 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4461 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4462 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4463 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4464 inst
.reloc
.pc_rel
= 1;
4465 inst
.instruction
|= (REG_PC
<< 16);
4471 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4477 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4478 SMLAxy{cond} Rd,Rm,Rs,Rn
4479 SMLAWy{cond} Rd,Rm,Rs,Rn
4480 Error if any register is R15. */
4488 skip_whitespace (str
);
4490 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4491 || skip_past_comma (& str
) == FAIL
4492 || (rm
= reg_required_here (& str
, 0)) == FAIL
4493 || skip_past_comma (& str
) == FAIL
4494 || (rs
= reg_required_here (& str
, 8)) == FAIL
4495 || skip_past_comma (& str
) == FAIL
4496 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4497 inst
.error
= BAD_ARGS
;
4499 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4500 inst
.error
= BAD_PC
;
4506 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4507 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4508 Error if any register is R15.
4509 Warning if Rdlo == Rdhi. */
4515 int rdlo
, rdhi
, rm
, rs
;
4517 skip_whitespace (str
);
4519 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4520 || skip_past_comma (& str
) == FAIL
4521 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4522 || skip_past_comma (& str
) == FAIL
4523 || (rm
= reg_required_here (& str
, 0)) == FAIL
4524 || skip_past_comma (& str
) == FAIL
4525 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4527 inst
.error
= BAD_ARGS
;
4531 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4533 inst
.error
= BAD_PC
;
4538 as_tsktsk (_("rdhi and rdlo must be different"));
4543 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4544 SMULxy{cond} Rd,Rm,Rs
4545 Error if any register is R15. */
4553 skip_whitespace (str
);
4555 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4556 || skip_past_comma (& str
) == FAIL
4557 || (rm
= reg_required_here (& str
, 0)) == FAIL
4558 || skip_past_comma (& str
) == FAIL
4559 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4560 inst
.error
= BAD_ARGS
;
4562 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4563 inst
.error
= BAD_PC
;
4569 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4570 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4571 Error if any register is R15. */
4579 skip_whitespace (str
);
4581 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4582 || skip_past_comma (& str
) == FAIL
4583 || (rm
= reg_required_here (& str
, 0)) == FAIL
4584 || skip_past_comma (& str
) == FAIL
4585 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4586 inst
.error
= BAD_ARGS
;
4588 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4589 inst
.error
= BAD_PC
;
4595 /* ARM V5E (el Segundo)
4596 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4597 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4599 These are equivalent to the XScale instructions MAR and MRA,
4600 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4602 Result unpredicatable if Rd or Rn is R15. */
4610 skip_whitespace (str
);
4612 if (co_proc_number (& str
) == FAIL
)
4615 inst
.error
= BAD_ARGS
;
4619 if (skip_past_comma (& str
) == FAIL
4620 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4623 inst
.error
= BAD_ARGS
;
4627 if (skip_past_comma (& str
) == FAIL
4628 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4631 inst
.error
= BAD_ARGS
;
4635 if (skip_past_comma (& str
) == FAIL
4636 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4639 inst
.error
= BAD_ARGS
;
4643 /* Unpredictable result if rd or rn is R15. */
4644 if (rd
== REG_PC
|| rn
== REG_PC
)
4646 (_("Warning: instruction unpredictable when using r15"));
4648 if (skip_past_comma (& str
) == FAIL
4649 || cp_reg_required_here (& str
, 0) == FAIL
)
4652 inst
.error
= BAD_ARGS
;
4659 /* ARM V5 count-leading-zeroes instruction (argument parse)
4660 CLZ{<cond>} <Rd>, <Rm>
4661 Condition defaults to COND_ALWAYS.
4662 Error if Rd or Rm are R15. */
4670 skip_whitespace (str
);
4672 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4673 || (skip_past_comma (& str
) == FAIL
)
4674 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4675 inst
.error
= BAD_ARGS
;
4677 else if (rd
== REG_PC
|| rm
== REG_PC
)
4678 inst
.error
= BAD_PC
;
4684 /* ARM V5 (argument parse)
4685 LDC2{L} <coproc>, <CRd>, <addressing mode>
4686 STC2{L} <coproc>, <CRd>, <addressing mode>
4687 Instruction is not conditional, and has 0xf in the condition field.
4688 Otherwise, it's the same as LDC/STC. */
4694 skip_whitespace (str
);
4696 if (co_proc_number (& str
) == FAIL
)
4699 inst
.error
= BAD_ARGS
;
4701 else if (skip_past_comma (& str
) == FAIL
4702 || cp_reg_required_here (& str
, 12) == FAIL
)
4705 inst
.error
= BAD_ARGS
;
4707 else if (skip_past_comma (& str
) == FAIL
4708 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4711 inst
.error
= BAD_ARGS
;
4717 /* ARM V5 (argument parse)
4718 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4719 Instruction is not conditional, and has 0xf in the condition field.
4720 Otherwise, it's the same as CDP. */
4726 skip_whitespace (str
);
4728 if (co_proc_number (& str
) == FAIL
)
4731 inst
.error
= BAD_ARGS
;
4735 if (skip_past_comma (& str
) == FAIL
4736 || cp_opc_expr (& str
, 20,4) == FAIL
)
4739 inst
.error
= BAD_ARGS
;
4743 if (skip_past_comma (& str
) == FAIL
4744 || cp_reg_required_here (& str
, 12) == FAIL
)
4747 inst
.error
= BAD_ARGS
;
4751 if (skip_past_comma (& str
) == FAIL
4752 || cp_reg_required_here (& str
, 16) == FAIL
)
4755 inst
.error
= BAD_ARGS
;
4759 if (skip_past_comma (& str
) == FAIL
4760 || cp_reg_required_here (& str
, 0) == FAIL
)
4763 inst
.error
= BAD_ARGS
;
4767 if (skip_past_comma (& str
) == SUCCESS
)
4769 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4772 inst
.error
= BAD_ARGS
;
4780 /* ARM V5 (argument parse)
4781 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4782 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4783 Instruction is not conditional, and has 0xf in the condition field.
4784 Otherwise, it's the same as MCR/MRC. */
4790 skip_whitespace (str
);
4792 if (co_proc_number (& str
) == FAIL
)
4795 inst
.error
= BAD_ARGS
;
4799 if (skip_past_comma (& str
) == FAIL
4800 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4803 inst
.error
= BAD_ARGS
;
4807 if (skip_past_comma (& str
) == FAIL
4808 || reg_required_here (& str
, 12) == FAIL
)
4811 inst
.error
= BAD_ARGS
;
4815 if (skip_past_comma (& str
) == FAIL
4816 || cp_reg_required_here (& str
, 16) == FAIL
)
4819 inst
.error
= BAD_ARGS
;
4823 if (skip_past_comma (& str
) == FAIL
4824 || cp_reg_required_here (& str
, 0) == FAIL
)
4827 inst
.error
= BAD_ARGS
;
4831 if (skip_past_comma (& str
) == SUCCESS
)
4833 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4836 inst
.error
= BAD_ARGS
;
4844 /* ARM v5TEJ. Jump to Jazelle code. */
4851 skip_whitespace (str
);
4853 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4855 inst
.error
= BAD_ARGS
;
4859 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4861 as_tsktsk (_("use of r15 in bxj is not really useful"));
4866 /* ARM V6 umaal (argument parse). */
4873 int rdlo
, rdhi
, rm
, rs
;
4875 skip_whitespace (str
);
4876 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4877 || skip_past_comma (& str
) == FAIL
4878 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4879 || skip_past_comma (& str
) == FAIL
4880 || (rm
= reg_required_here (& str
, 0)) == FAIL
4881 || skip_past_comma (& str
) == FAIL
4882 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4884 inst
.error
= BAD_ARGS
;
4888 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4890 inst
.error
= BAD_PC
;
4897 /* ARM V6 strex (argument parse). */
4905 /* Parse Rd, Rm,. */
4906 skip_whitespace (str
);
4907 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4908 || skip_past_comma (& str
) == FAIL
4909 || (rm
= reg_required_here (& str
, 0)) == FAIL
4910 || skip_past_comma (& str
) == FAIL
)
4912 inst
.error
= BAD_ARGS
;
4915 if (rd
== REG_PC
|| rm
== REG_PC
)
4917 inst
.error
= BAD_PC
;
4922 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4926 /* Skip past '['. */
4927 if ((strlen (str
) >= 1)
4928 && strncmp (str
, "[", 1) == 0)
4930 skip_whitespace (str
);
4933 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4935 inst
.error
= BAD_ARGS
;
4938 else if (rn
== REG_PC
)
4940 inst
.error
= BAD_PC
;
4945 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4948 skip_whitespace (str
);
4950 /* Skip past ']'. */
4951 if ((strlen (str
) >= 1)
4952 && strncmp (str
, "]", 1) == 0)
4958 /* ARM V6 ssat (argument parse). */
4964 do_sat (&str
, /*bias=*/-1);
4968 /* ARM V6 usat (argument parse). */
4974 do_sat (&str
, /*bias=*/0);
4986 skip_whitespace (*str
);
4988 /* Parse <Rd>, field. */
4989 if ((rd
= reg_required_here (str
, 12)) == FAIL
4990 || skip_past_comma (str
) == FAIL
)
4992 inst
.error
= BAD_ARGS
;
4997 inst
.error
= BAD_PC
;
5001 /* Parse #<immed>, field. */
5002 if (is_immediate_prefix (**str
))
5006 inst
.error
= _("immediate expression expected");
5009 if (my_get_expression (&expr
, str
))
5011 inst
.error
= _("bad expression");
5014 if (expr
.X_op
!= O_constant
)
5016 inst
.error
= _("constant expression expected");
5019 if (expr
.X_add_number
+ bias
< 0
5020 || expr
.X_add_number
+ bias
> 31)
5022 inst
.error
= _("immediate value out of range");
5025 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5026 if (skip_past_comma (str
) == FAIL
)
5028 inst
.error
= BAD_ARGS
;
5032 /* Parse <Rm> field. */
5033 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5035 inst
.error
= BAD_ARGS
;
5040 inst
.error
= BAD_PC
;
5044 if (skip_past_comma (str
) == SUCCESS
)
5045 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
5048 /* ARM V6 ssat16 (argument parse). */
5054 do_sat16 (&str
, /*bias=*/-1);
5062 do_sat16 (&str
, /*bias=*/0);
5067 do_sat16 (str
, bias
)
5074 skip_whitespace (*str
);
5076 /* Parse the <Rd> field. */
5077 if ((rd
= reg_required_here (str
, 12)) == FAIL
5078 || skip_past_comma (str
) == FAIL
)
5080 inst
.error
= BAD_ARGS
;
5085 inst
.error
= BAD_PC
;
5089 /* Parse #<immed>, field. */
5090 if (is_immediate_prefix (**str
))
5094 inst
.error
= _("immediate expression expected");
5097 if (my_get_expression (&expr
, str
))
5099 inst
.error
= _("bad expression");
5102 if (expr
.X_op
!= O_constant
)
5104 inst
.error
= _("constant expression expected");
5107 if (expr
.X_add_number
+ bias
< 0
5108 || expr
.X_add_number
+ bias
> 15)
5110 inst
.error
= _("immediate value out of range");
5113 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5114 if (skip_past_comma (str
) == FAIL
)
5116 inst
.error
= BAD_ARGS
;
5120 /* Parse <Rm> field. */
5121 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5123 inst
.error
= BAD_ARGS
;
5128 inst
.error
= BAD_PC
;
5133 /* ARM V6 srs (argument parse). */
5140 skip_whitespace (str
);
5141 exclam
= strchr (str
, '!');
5149 inst
.instruction
|= WRITE_BACK
;
5155 /* ARM V6 SMMUL (argument parse). */
5163 skip_whitespace (str
);
5164 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5165 || skip_past_comma (&str
) == FAIL
5166 || (rm
= reg_required_here (&str
, 0)) == FAIL
5167 || skip_past_comma (&str
) == FAIL
5168 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5170 inst
.error
= BAD_ARGS
;
5178 inst
.error
= BAD_PC
;
5186 /* ARM V6 SMLALD (argument parse). */
5192 int rdlo
, rdhi
, rm
, rs
;
5193 skip_whitespace (str
);
5194 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5195 || skip_past_comma (&str
) == FAIL
5196 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5197 || skip_past_comma (&str
) == FAIL
5198 || (rm
= reg_required_here (&str
, 0)) == FAIL
5199 || skip_past_comma (&str
) == FAIL
5200 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5202 inst
.error
= BAD_ARGS
;
5211 inst
.error
= BAD_PC
;
5218 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5219 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5227 skip_whitespace (str
);
5228 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5229 || skip_past_comma (&str
) == FAIL
5230 || (rm
= reg_required_here (&str
, 0)) == FAIL
5231 || skip_past_comma (&str
) == FAIL
5232 || (rs
= reg_required_here (&str
, 8)) == FAIL
5233 || skip_past_comma (&str
) == FAIL
5234 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5236 inst
.error
= BAD_ARGS
;
5245 inst
.error
= BAD_PC
;
5252 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5253 preserving the other bits.
5255 setend <endian_specifier>, where <endian_specifier> is either
5262 if (do_endian_specifier (str
))
5263 inst
.instruction
|= 0x200;
5266 /* Returns true if the endian-specifier indicates big-endianness. */
5269 do_endian_specifier (str
)
5274 skip_whitespace (str
);
5275 if (strlen (str
) < 2)
5276 inst
.error
= _("missing endian specifier");
5277 else if (strncasecmp (str
, "BE", 2) == 0)
5282 else if (strncasecmp (str
, "LE", 2) == 0)
5285 inst
.error
= _("valid endian specifiers are be or le");
5294 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5295 Condition defaults to COND_ALWAYS.
5296 Error if any register uses R15. */
5304 int rotation_clear_mask
= 0xfffff3ff;
5305 int rotation_eight_mask
= 0x00000400;
5306 int rotation_sixteen_mask
= 0x00000800;
5307 int rotation_twenty_four_mask
= 0x00000c00;
5309 skip_whitespace (str
);
5310 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5311 || skip_past_comma (&str
) == FAIL
5312 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5314 inst
.error
= BAD_ARGS
;
5318 else if (rd
== REG_PC
|| rm
== REG_PC
)
5320 inst
.error
= BAD_PC
;
5324 /* Zero out the rotation field. */
5325 inst
.instruction
&= rotation_clear_mask
;
5327 /* Check for lack of optional rotation field. */
5328 if (skip_past_comma (&str
) == FAIL
)
5334 /* Move past 'ROR'. */
5335 skip_whitespace (str
);
5336 if (strncasecmp (str
, "ROR", 3) == 0)
5340 inst
.error
= _("missing rotation field after comma");
5344 /* Get the immediate constant. */
5345 skip_whitespace (str
);
5346 if (is_immediate_prefix (* str
))
5350 inst
.error
= _("immediate expression expected");
5354 if (my_get_expression (&expr
, &str
))
5356 inst
.error
= _("bad expression");
5360 if (expr
.X_op
!= O_constant
)
5362 inst
.error
= _("constant expression expected");
5366 switch (expr
.X_add_number
)
5369 /* Rotation field has already been zeroed. */
5372 inst
.instruction
|= rotation_eight_mask
;
5376 inst
.instruction
|= rotation_sixteen_mask
;
5380 inst
.instruction
|= rotation_twenty_four_mask
;
5384 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5392 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5393 extends it to 32-bits, and adds the result to a value in another
5394 register. You can specify a rotation by 0, 8, 16, or 24 bits
5395 before extracting the 16-bit value.
5396 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5397 Condition defaults to COND_ALWAYS.
5398 Error if any register uses R15. */
5406 int rotation_clear_mask
= 0xfffff3ff;
5407 int rotation_eight_mask
= 0x00000400;
5408 int rotation_sixteen_mask
= 0x00000800;
5409 int rotation_twenty_four_mask
= 0x00000c00;
5411 skip_whitespace (str
);
5412 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5413 || skip_past_comma (&str
) == FAIL
5414 || (rn
= reg_required_here (&str
, 16)) == FAIL
5415 || skip_past_comma (&str
) == FAIL
5416 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5418 inst
.error
= BAD_ARGS
;
5422 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5424 inst
.error
= BAD_PC
;
5428 /* Zero out the rotation field. */
5429 inst
.instruction
&= rotation_clear_mask
;
5431 /* Check for lack of optional rotation field. */
5432 if (skip_past_comma (&str
) == FAIL
)
5438 /* Move past 'ROR'. */
5439 skip_whitespace (str
);
5440 if (strncasecmp (str
, "ROR", 3) == 0)
5444 inst
.error
= _("missing rotation field after comma");
5448 /* Get the immediate constant. */
5449 skip_whitespace (str
);
5450 if (is_immediate_prefix (* str
))
5454 inst
.error
= _("immediate expression expected");
5458 if (my_get_expression (&expr
, &str
))
5460 inst
.error
= _("bad expression");
5464 if (expr
.X_op
!= O_constant
)
5466 inst
.error
= _("constant expression expected");
5470 switch (expr
.X_add_number
)
5473 /* Rotation field has already been zeroed. */
5477 inst
.instruction
|= rotation_eight_mask
;
5481 inst
.instruction
|= rotation_sixteen_mask
;
5485 inst
.instruction
|= rotation_twenty_four_mask
;
5489 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5498 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5499 word at the specified address and the following word
5501 Unconditionally executed.
5511 skip_whitespace (str
);
5513 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5518 inst
.error
= BAD_PC
;
5522 skip_whitespace (str
);
5526 inst
.instruction
|= WRITE_BACK
;
5532 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5533 register (argument parse).
5535 Condition defaults to COND_ALWAYS.
5536 Error if Rd or Rm are R15. */
5544 skip_whitespace (str
);
5546 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5547 || skip_past_comma (&str
) == FAIL
5548 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5549 inst
.error
= BAD_ARGS
;
5551 else if (rd
== REG_PC
|| rm
== REG_PC
)
5552 inst
.error
= BAD_PC
;
5558 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5559 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5560 Condition defaults to COND_ALWAYS.
5561 Error if Rd, Rn or Rm are R15. */
5569 skip_whitespace (str
);
5571 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5572 || skip_past_comma (&str
) == FAIL
5573 || (rn
= reg_required_here (&str
, 16)) == FAIL
5574 || skip_past_comma (&str
) == FAIL
5575 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5576 inst
.error
= BAD_ARGS
;
5578 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5579 inst
.error
= BAD_PC
;
5585 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5586 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5587 Condition defaults to COND_ALWAYS.
5588 Error if Rd, Rn or Rm are R15. */
5594 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5597 /* ARM V6 PKHTB (Argument Parse). */
5603 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5607 do_pkh_core (str
, shift
)
5613 skip_whitespace (str
);
5614 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5615 || (skip_past_comma (&str
) == FAIL
)
5616 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5617 || (skip_past_comma (&str
) == FAIL
)
5618 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5620 inst
.error
= BAD_ARGS
;
5624 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5626 inst
.error
= BAD_PC
;
5630 /* Check for optional shift immediate constant. */
5631 if (skip_past_comma (&str
) == FAIL
)
5633 if (shift
== SHIFT_ASR_IMMEDIATE
)
5635 /* If the shift specifier is ommited, turn the instruction
5636 into pkhbt rd, rm, rn. First, switch the instruction
5637 code, and clear the rn and rm fields. */
5638 inst
.instruction
&= 0xfff0f010;
5639 /* Now, re-encode the registers. */
5640 inst
.instruction
|= (rm
<< 16) | rn
;
5645 decode_shift (&str
, shift
);
5648 /* ARM V6 Load Register Exclusive instruction (argument parse).
5649 LDREX{<cond>} <Rd, [<Rn>]
5650 Condition defaults to COND_ALWAYS.
5651 Error if Rd or Rn are R15.
5652 See ARMARMv6 A4.1.27: LDREX. */
5661 skip_whitespace (str
);
5664 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5665 || (skip_past_comma (&str
) == FAIL
))
5667 inst
.error
= BAD_ARGS
;
5670 else if (rd
== REG_PC
)
5672 inst
.error
= BAD_PC
;
5675 skip_whitespace (str
);
5677 /* Skip past '['. */
5678 if ((strlen (str
) >= 1)
5679 &&strncmp (str
, "[", 1) == 0)
5681 skip_whitespace (str
);
5684 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5686 inst
.error
= BAD_ARGS
;
5689 else if (rn
== REG_PC
)
5691 inst
.error
= BAD_PC
;
5694 skip_whitespace (str
);
5696 /* Skip past ']'. */
5697 if ((strlen (str
) >= 1)
5698 && strncmp (str
, "]", 1) == 0)
5704 /* ARM V6 change processor state instruction (argument parse)
5705 CPS, CPSIE, CSPID . */
5719 do_cps_flags (&str
, /*thumb_p=*/0);
5721 if (skip_past_comma (&str
) == SUCCESS
)
5723 skip_whitespace (str
);
5735 skip_whitespace (*str
);
5737 if (! is_immediate_prefix (**str
))
5739 inst
.error
= _("immediate expression expected");
5743 (*str
)++; /* Strip off the immediate signifier. */
5744 if (my_get_expression (&expr
, str
))
5746 inst
.error
= _("bad expression");
5750 if (expr
.X_op
!= O_constant
)
5752 inst
.error
= _("constant expression expected");
5756 /* The mode is a 5 bit field. Valid values are 0-31. */
5757 if (((unsigned) expr
.X_add_number
) > 31
5758 || (inst
.reloc
.exp
.X_add_number
) < 0)
5760 inst
.error
= _("invalid constant");
5764 inst
.instruction
|= expr
.X_add_number
;
5768 do_cps_flags (str
, thumb_p
)
5774 unsigned long arm_value
;
5775 unsigned long thumb_value
;
5777 static struct cps_flag flag_table
[] = {
5785 skip_whitespace (*str
);
5787 /* Get the a, f and i flags. */
5788 while (**str
&& **str
!= ',')
5791 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5792 for (p
= flag_table
; p
< q
; ++p
)
5793 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5795 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5801 inst
.error
= _("unrecognized flag");
5807 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5810 /* THUMB V5 breakpoint instruction (argument parse)
5818 unsigned long number
;
5820 skip_whitespace (str
);
5822 /* Allow optional leading '#'. */
5823 if (is_immediate_prefix (*str
))
5826 memset (& expr
, '\0', sizeof (expr
));
5827 if (my_get_expression (& expr
, & str
)
5828 || (expr
.X_op
!= O_constant
5829 /* As a convenience we allow 'bkpt' without an operand. */
5830 && expr
.X_op
!= O_absent
))
5832 inst
.error
= _("bad expression");
5836 number
= expr
.X_add_number
;
5838 /* Check it fits an 8 bit unsigned. */
5839 if (number
!= (number
& 0xff))
5841 inst
.error
= _("immediate value out of range");
5845 inst
.instruction
|= number
;
5850 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5851 Expects inst.instruction is set for BLX(1).
5852 Note: this is cloned from do_branch, and the reloc changed to be a
5853 new one that can cope with setting one extra bit (the H bit). */
5859 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5866 /* ScottB: February 5, 1998 */
5867 /* Check to see of PLT32 reloc required for the instruction. */
5869 /* arm_parse_reloc() works on input_line_pointer.
5870 We actually want to parse the operands to the branch instruction
5871 passed in 'str'. Save the input pointer and restore it later. */
5872 save_in
= input_line_pointer
;
5873 input_line_pointer
= str
;
5875 if (inst
.reloc
.exp
.X_op
== O_symbol
5877 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5879 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5880 inst
.reloc
.pc_rel
= 0;
5881 /* Modify str to point to after parsed operands, otherwise
5882 end_of_line() will complain about the (PLT) left in str. */
5883 str
= input_line_pointer
;
5887 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5888 inst
.reloc
.pc_rel
= 1;
5891 input_line_pointer
= save_in
;
5894 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5895 inst
.reloc
.pc_rel
= 1;
5896 #endif /* OBJ_ELF */
5901 /* ARM V5 branch-link-exchange instruction (argument parse)
5902 BLX <target_addr> ie BLX(1)
5903 BLX{<condition>} <Rm> ie BLX(2)
5904 Unfortunately, there are two different opcodes for this mnemonic.
5905 So, the insns[].value is not used, and the code here zaps values
5906 into inst.instruction.
5907 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5916 skip_whitespace (mystr
);
5917 rm
= reg_required_here (& mystr
, 0);
5919 /* The above may set inst.error. Ignore his opinion. */
5924 /* Arg is a register.
5925 Use the condition code our caller put in inst.instruction.
5926 Pass ourselves off as a BX with a funny opcode. */
5927 inst
.instruction
|= 0x012fff30;
5932 /* This must be is BLX <target address>, no condition allowed. */
5933 if (inst
.instruction
!= COND_ALWAYS
)
5935 inst
.error
= BAD_COND
;
5939 inst
.instruction
= 0xfafffffe;
5941 /* Process like a B/BL, but with a different reloc.
5942 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5947 /* ARM V5 Thumb BLX (argument parse)
5948 BLX <target_addr> which is BLX(1)
5949 BLX <Rm> which is BLX(2)
5950 Unfortunately, there are two different opcodes for this mnemonic.
5951 So, the tinsns[].value is not used, and the code here zaps values
5952 into inst.instruction. */
5961 skip_whitespace (mystr
);
5962 inst
.instruction
= 0x4780;
5964 /* Note that this call is to the ARM register recognizer. BLX(2)
5965 uses the ARM register space, not the Thumb one, so a call to
5966 thumb_reg() would be wrong. */
5967 rm
= reg_required_here (& mystr
, 3);
5972 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5977 /* No ARM register. This must be BLX(1). Change the .instruction. */
5978 inst
.instruction
= 0xf7ffeffe;
5981 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5984 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5985 inst
.reloc
.pc_rel
= 1;
5988 end_of_line (mystr
);
5991 /* ARM V5 breakpoint instruction (argument parse)
5992 BKPT <16 bit unsigned immediate>
5993 Instruction is not conditional.
5994 The bit pattern given in insns[] has the COND_ALWAYS condition,
5995 and it is an error if the caller tried to override that. */
6002 unsigned long number
;
6004 skip_whitespace (str
);
6006 /* Allow optional leading '#'. */
6007 if (is_immediate_prefix (* str
))
6010 memset (& expr
, '\0', sizeof (expr
));
6012 if (my_get_expression (& expr
, & str
)
6013 || (expr
.X_op
!= O_constant
6014 /* As a convenience we allow 'bkpt' without an operand. */
6015 && expr
.X_op
!= O_absent
))
6017 inst
.error
= _("bad expression");
6021 number
= expr
.X_add_number
;
6023 /* Check it fits a 16 bit unsigned. */
6024 if (number
!= (number
& 0xffff))
6026 inst
.error
= _("immediate value out of range");
6030 /* Top 12 of 16 bits to bits 19:8. */
6031 inst
.instruction
|= (number
& 0xfff0) << 4;
6033 /* Bottom 4 of 16 bits to bits 3:0. */
6034 inst
.instruction
|= number
& 0xf;
6039 /* THUMB CPS instruction (argument parse). */
6045 do_cps_flags (&str
, /*thumb_p=*/1);
6049 /* THUMB CPY instruction (argument parse). */
6055 thumb_mov_compare (str
, THUMB_CPY
);
6058 /* THUMB SETEND instruction (argument parse). */
6064 if (do_endian_specifier (str
))
6065 inst
.instruction
|= 0x8;
6068 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6070 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6072 static unsigned long
6073 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6075 enum iwmmxt_insn_type insn_type
;
6079 const char * inst_error
;
6081 unsigned long number
;
6083 inst_error
= inst
.error
;
6085 inst
.error
= BAD_ARGS
;
6086 skip_whitespace (str
);
6091 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6096 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6101 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6102 || skip_past_comma (&str
) == FAIL
6103 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6108 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6109 || skip_past_comma (&str
) == FAIL
6110 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6111 || skip_past_comma (&str
) == FAIL
6112 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6117 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6118 || skip_past_comma (&str
) == FAIL
6119 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6120 || skip_past_comma (&str
) == FAIL
6121 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6126 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6127 || skip_past_comma (&str
) == FAIL
6128 || reg_required_here (&str
, 12) == FAIL
))
6133 if ((reg_required_here (&str
, 12) == FAIL
6134 || skip_past_comma (&str
) == FAIL
6135 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6140 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6141 || skip_past_comma (&str
) == FAIL
6142 || reg_required_here (&str
, 0) == FAIL
6143 || skip_past_comma (&str
) == FAIL
6144 || reg_required_here (&str
, 12) == FAIL
))
6149 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6150 || skip_past_comma (&str
) == FAIL
6151 || reg_required_here (&str
, 12) == FAIL
6152 || skip_past_comma (&str
) == FAIL
6153 || reg_required_here (&str
, 16) == FAIL
))
6158 if ((reg_required_here (&str
, 12) == FAIL
6159 || skip_past_comma (&str
) == FAIL
6160 || reg_required_here (&str
, 16) == FAIL
6161 || skip_past_comma (&str
) == FAIL
6162 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6167 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6168 || skip_past_comma (&str
) == FAIL
6169 || reg_required_here (&str
, 12) == FAIL
))
6174 if ((reg_required_here (&str
, 12) == FAIL
6175 || skip_past_comma (&str
) == FAIL
6176 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6181 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6182 || skip_past_comma (&str
) == FAIL
6183 || reg_required_here (&str
, 12) == FAIL
6184 || skip_past_comma (&str
) == FAIL
))
6189 if ((reg_required_here (&str
, 12) == FAIL
6190 || skip_past_comma (&str
) == FAIL
))
6195 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6196 || skip_past_comma (&str
) == FAIL
6197 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6198 || skip_past_comma (&str
) == FAIL
6199 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6200 || skip_past_comma (&str
) == FAIL
))
6205 if ((reg_required_here (&str
, 12) == FAIL
6206 || skip_past_comma (&str
) == FAIL
6207 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6208 || skip_past_comma (&str
) == FAIL
))
6213 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6214 || skip_past_comma (&str
) == FAIL
6215 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6216 || skip_past_comma (&str
) == FAIL
))
6221 if (immediate_size
== 0)
6224 inst
.error
= inst_error
;
6229 skip_whitespace (str
);
6231 /* Allow optional leading '#'. */
6232 if (is_immediate_prefix (* str
))
6235 memset (& expr
, '\0', sizeof (expr
));
6237 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6239 inst
.error
= _("bad or missing expression");
6243 number
= expr
.X_add_number
;
6245 if (number
!= (number
& immediate_size
))
6247 inst
.error
= _("immediate value out of range");
6251 inst
.error
= inst_error
;
6257 do_iwmmxt_byte_addr (str
)
6260 int op
= (inst
.instruction
& 0x300) >> 8;
6263 inst
.instruction
&= ~0x300;
6264 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6266 skip_whitespace (str
);
6268 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6269 || skip_past_comma (& str
) == FAIL
6270 || cp_byte_address_required_here (&str
) == FAIL
)
6273 inst
.error
= BAD_ARGS
;
6278 if (wc_register (reg
))
6280 as_bad (_("non-word size not supported with control register"));
6281 inst
.instruction
|= 0xf0000100;
6282 inst
.instruction
&= ~0x00400000;
6287 do_iwmmxt_tandc (str
)
6292 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6294 if (reg
!= REG_PC
&& !inst
.error
)
6295 inst
.error
= _("only r15 allowed here");
6299 do_iwmmxt_tbcst (str
)
6302 check_iwmmxt_insn (str
, check_tbcst
, 0);
6306 do_iwmmxt_textrc (str
)
6309 unsigned long number
;
6311 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6314 inst
.instruction
|= number
& 0x7;
6318 do_iwmmxt_textrm (str
)
6321 unsigned long number
;
6323 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6326 inst
.instruction
|= number
& 0x7;
6330 do_iwmmxt_tinsr (str
)
6333 unsigned long number
;
6335 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6338 inst
.instruction
|= number
& 0x7;
6342 do_iwmmxt_tmcr (str
)
6345 check_iwmmxt_insn (str
, check_tmcr
, 0);
6349 do_iwmmxt_tmcrr (str
)
6352 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6356 do_iwmmxt_tmia (str
)
6359 check_iwmmxt_insn (str
, check_tmia
, 0);
6363 do_iwmmxt_tmovmsk (str
)
6366 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6370 do_iwmmxt_tmrc (str
)
6373 check_iwmmxt_insn (str
, check_tmrc
, 0);
6377 do_iwmmxt_tmrrc (str
)
6380 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6384 do_iwmmxt_torc (str
)
6387 check_iwmmxt_insn (str
, check_rd
, 0);
6391 do_iwmmxt_waligni (str
)
6394 unsigned long number
;
6396 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6399 inst
.instruction
|= ((number
& 0x7) << 20);
6403 do_iwmmxt_wmov (str
)
6406 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6409 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6413 do_iwmmxt_word_addr (str
)
6416 int op
= (inst
.instruction
& 0x300) >> 8;
6419 inst
.instruction
&= ~0x300;
6420 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6422 skip_whitespace (str
);
6424 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6425 || skip_past_comma (& str
) == FAIL
6426 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6429 inst
.error
= BAD_ARGS
;
6434 if (wc_register (reg
))
6436 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6437 as_bad (_("conditional execution not supported with control register"));
6439 as_bad (_("non-word size not supported with control register"));
6440 inst
.instruction
|= 0xf0000100;
6441 inst
.instruction
&= ~0x00400000;
6446 do_iwmmxt_wrwr (str
)
6449 check_iwmmxt_insn (str
, check_wrwr
, 0);
6453 do_iwmmxt_wrwrwcg (str
)
6456 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6460 do_iwmmxt_wrwrwr (str
)
6463 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6467 do_iwmmxt_wshufh (str
)
6470 unsigned long number
;
6472 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6475 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6479 do_iwmmxt_wzero (str
)
6482 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6485 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6488 /* Xscale multiply-accumulate (argument parse)
6491 MIAxycc acc0,Rm,Rs. */
6500 if (accum0_required_here (& str
) == FAIL
)
6501 inst
.error
= ERR_NO_ACCUM
;
6503 else if (skip_past_comma (& str
) == FAIL
6504 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6505 inst
.error
= BAD_ARGS
;
6507 else if (skip_past_comma (& str
) == FAIL
6508 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6509 inst
.error
= BAD_ARGS
;
6511 /* inst.instruction has now been zapped with both rm and rs. */
6512 else if (rm
== REG_PC
|| rs
== REG_PC
)
6513 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6519 /* Xscale move-accumulator-register (argument parse)
6521 MARcc acc0,RdLo,RdHi. */
6529 if (accum0_required_here (& str
) == FAIL
)
6530 inst
.error
= ERR_NO_ACCUM
;
6532 else if (skip_past_comma (& str
) == FAIL
6533 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6534 inst
.error
= BAD_ARGS
;
6536 else if (skip_past_comma (& str
) == FAIL
6537 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6538 inst
.error
= BAD_ARGS
;
6540 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6541 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6542 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6548 /* Xscale move-register-accumulator (argument parse)
6550 MRAcc RdLo,RdHi,acc0. */
6559 skip_whitespace (str
);
6561 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6562 inst
.error
= BAD_ARGS
;
6564 else if (skip_past_comma (& str
) == FAIL
6565 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6566 inst
.error
= BAD_ARGS
;
6568 else if (skip_past_comma (& str
) == FAIL
6569 || accum0_required_here (& str
) == FAIL
)
6570 inst
.error
= ERR_NO_ACCUM
;
6572 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6573 else if (rdlo
== rdhi
)
6574 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6576 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6577 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6582 /* ARMv5TE: Preload-Cache
6586 Syntactically, like LDR with B=1, W=0, L=1. */
6594 skip_whitespace (str
);
6598 inst
.error
= _("'[' expected after PLD mnemonic");
6603 skip_whitespace (str
);
6605 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6608 skip_whitespace (str
);
6614 skip_whitespace (str
);
6616 /* Post-indexed addressing is not allowed with PLD. */
6617 if (skip_past_comma (&str
) == SUCCESS
)
6620 = _("post-indexed expression used in preload instruction");
6623 else if (*str
== '!') /* [Rn]! */
6625 inst
.error
= _("writeback used in preload instruction");
6629 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6631 else /* [Rn, ...] */
6633 if (skip_past_comma (& str
) == FAIL
)
6635 inst
.error
= _("pre-indexed expression expected");
6639 if (ldst_extend (&str
) == FAIL
)
6642 skip_whitespace (str
);
6646 inst
.error
= _("missing ]");
6651 skip_whitespace (str
);
6653 if (* str
== '!') /* [Rn]! */
6655 inst
.error
= _("writeback used in preload instruction");
6659 inst
.instruction
|= PRE_INDEX
;
6665 /* ARMv5TE load-consecutive (argument parse)
6678 skip_whitespace (str
);
6680 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6682 inst
.error
= BAD_ARGS
;
6686 if (skip_past_comma (& str
) == FAIL
6687 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6690 inst
.error
= BAD_ARGS
;
6694 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6695 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6697 inst
.error
= _("destination register must be even");
6703 inst
.error
= _("r14 not allowed here");
6707 if (((rd
== rn
) || (rd
+ 1 == rn
))
6708 && ((inst
.instruction
& WRITE_BACK
)
6709 || (!(inst
.instruction
& PRE_INDEX
))))
6710 as_warn (_("pre/post-indexing used when modified address register is destination"));
6712 /* For an index-register load, the index register must not overlap the
6713 destination (even if not write-back). */
6714 if ((inst
.instruction
& V4_STR_BIT
) == 0
6715 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6717 int rm
= inst
.instruction
& 0x0000000f;
6719 if (rm
== rd
|| (rm
== rd
+ 1))
6720 as_warn (_("ldrd destination registers must not overlap index register"));
6726 /* Returns the index into fp_values of a floating point number,
6727 or -1 if not in the table. */
6730 my_get_float_expression (str
)
6733 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6739 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6741 /* Look for a raw floating point number. */
6742 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6743 && is_end_of_line
[(unsigned char) *save_in
])
6745 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6747 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6749 if (words
[j
] != fp_values
[i
][j
])
6753 if (j
== MAX_LITTLENUMS
)
6761 /* Try and parse a more complex expression, this will probably fail
6762 unless the code uses a floating point prefix (eg "0f"). */
6763 save_in
= input_line_pointer
;
6764 input_line_pointer
= *str
;
6765 if (expression (&exp
) == absolute_section
6766 && exp
.X_op
== O_big
6767 && exp
.X_add_number
< 0)
6769 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6771 if (gen_to_words (words
, 5, (long) 15) == 0)
6773 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6775 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6777 if (words
[j
] != fp_values
[i
][j
])
6781 if (j
== MAX_LITTLENUMS
)
6783 *str
= input_line_pointer
;
6784 input_line_pointer
= save_in
;
6791 *str
= input_line_pointer
;
6792 input_line_pointer
= save_in
;
6796 /* Return TRUE if anything in the expression is a bignum. */
6799 walk_no_bignums (sp
)
6802 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6805 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6807 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6808 || (symbol_get_value_expression (sp
)->X_op_symbol
6809 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6815 static int in_my_get_expression
= 0;
6818 my_get_expression (ep
, str
)
6825 save_in
= input_line_pointer
;
6826 input_line_pointer
= *str
;
6827 in_my_get_expression
= 1;
6828 seg
= expression (ep
);
6829 in_my_get_expression
= 0;
6831 if (ep
->X_op
== O_illegal
)
6833 /* We found a bad expression in md_operand(). */
6834 *str
= input_line_pointer
;
6835 input_line_pointer
= save_in
;
6840 if (seg
!= absolute_section
6841 && seg
!= text_section
6842 && seg
!= data_section
6843 && seg
!= bss_section
6844 && seg
!= undefined_section
)
6846 inst
.error
= _("bad_segment");
6847 *str
= input_line_pointer
;
6848 input_line_pointer
= save_in
;
6853 /* Get rid of any bignums now, so that we don't generate an error for which
6854 we can't establish a line number later on. Big numbers are never valid
6855 in instructions, which is where this routine is always called. */
6856 if (ep
->X_op
== O_big
6857 || (ep
->X_add_symbol
6858 && (walk_no_bignums (ep
->X_add_symbol
)
6860 && walk_no_bignums (ep
->X_op_symbol
)))))
6862 inst
.error
= _("invalid constant");
6863 *str
= input_line_pointer
;
6864 input_line_pointer
= save_in
;
6868 *str
= input_line_pointer
;
6869 input_line_pointer
= save_in
;
6873 /* We handle all bad expressions here, so that we can report the faulty
6874 instruction in the error message. */
6879 if (in_my_get_expression
)
6881 expr
->X_op
= O_illegal
;
6882 if (inst
.error
== NULL
)
6883 inst
.error
= _("bad expression");
6887 /* KIND indicates what kind of shifts are accepted. */
6890 decode_shift (str
, kind
)
6894 const struct asm_shift_name
* shift
;
6898 skip_whitespace (* str
);
6900 for (p
= * str
; ISALPHA (* p
); p
++)
6905 inst
.error
= _("shift expression expected");
6911 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6916 inst
.error
= _("shift expression expected");
6920 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6922 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6923 && shift
->properties
->index
!= SHIFT_LSL
6924 && shift
->properties
->index
!= SHIFT_ASR
)
6926 inst
.error
= _("'LSL' or 'ASR' required");
6929 else if (kind
== SHIFT_LSL_IMMEDIATE
6930 && shift
->properties
->index
!= SHIFT_LSL
)
6932 inst
.error
= _("'LSL' required");
6935 else if (kind
== SHIFT_ASR_IMMEDIATE
6936 && shift
->properties
->index
!= SHIFT_ASR
)
6938 inst
.error
= _("'ASR' required");
6942 if (shift
->properties
->index
== SHIFT_RRX
)
6945 inst
.instruction
|= shift
->properties
->bit_field
;
6949 skip_whitespace (p
);
6951 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6953 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6957 else if (! is_immediate_prefix (* p
))
6959 inst
.error
= (NO_SHIFT_RESTRICT
6960 ? _("shift requires register or #expression")
6961 : _("shift requires #expression"));
6969 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6972 /* Validate some simple #expressions. */
6973 if (inst
.reloc
.exp
.X_op
== O_constant
)
6975 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6977 /* Reject operations greater than 32. */
6979 /* Reject a shift of 0 unless the mode allows it. */
6980 || (num
== 0 && shift
->properties
->allows_0
== 0)
6981 /* Reject a shift of 32 unless the mode allows it. */
6982 || (num
== 32 && shift
->properties
->allows_32
== 0)
6985 /* As a special case we allow a shift of zero for
6986 modes that do not support it to be recoded as an
6987 logical shift left of zero (ie nothing). We warn
6988 about this though. */
6991 as_warn (_("shift of 0 ignored."));
6992 shift
= & shift_names
[0];
6993 assert (shift
->properties
->index
== SHIFT_LSL
);
6997 inst
.error
= _("invalid immediate shift");
7002 /* Shifts of 32 are encoded as 0, for those shifts that
7007 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
7011 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
7012 inst
.reloc
.pc_rel
= 0;
7013 inst
.instruction
|= shift
->properties
->bit_field
;
7020 /* Do those data_ops which can take a negative immediate constant
7021 by altering the instruction. A bit of a hack really.
7025 by inverting the second operand, and
7028 by negating the second operand. */
7031 negate_data_op (instruction
, value
)
7032 unsigned long * instruction
;
7033 unsigned long value
;
7036 unsigned long negated
, inverted
;
7038 negated
= validate_immediate (-value
);
7039 inverted
= validate_immediate (~value
);
7041 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
7044 /* First negates. */
7045 case OPCODE_SUB
: /* ADD <-> SUB */
7046 new_inst
= OPCODE_ADD
;
7051 new_inst
= OPCODE_SUB
;
7055 case OPCODE_CMP
: /* CMP <-> CMN */
7056 new_inst
= OPCODE_CMN
;
7061 new_inst
= OPCODE_CMP
;
7065 /* Now Inverted ops. */
7066 case OPCODE_MOV
: /* MOV <-> MVN */
7067 new_inst
= OPCODE_MVN
;
7072 new_inst
= OPCODE_MOV
;
7076 case OPCODE_AND
: /* AND <-> BIC */
7077 new_inst
= OPCODE_BIC
;
7082 new_inst
= OPCODE_AND
;
7086 case OPCODE_ADC
: /* ADC <-> SBC */
7087 new_inst
= OPCODE_SBC
;
7092 new_inst
= OPCODE_ADC
;
7096 /* We cannot do anything. */
7101 if (value
== (unsigned) FAIL
)
7104 *instruction
&= OPCODE_MASK
;
7105 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7116 skip_whitespace (* str
);
7118 if (reg_required_here (str
, 0) != FAIL
)
7120 if (skip_past_comma (str
) == SUCCESS
)
7121 /* Shift operation on register. */
7122 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7128 /* Immediate expression. */
7129 if (is_immediate_prefix (**str
))
7134 if (my_get_expression (&inst
.reloc
.exp
, str
))
7137 if (inst
.reloc
.exp
.X_add_symbol
)
7139 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7140 inst
.reloc
.pc_rel
= 0;
7144 if (skip_past_comma (str
) == SUCCESS
)
7146 /* #x, y -- ie explicit rotation by Y. */
7147 if (my_get_expression (&expr
, str
))
7150 if (expr
.X_op
!= O_constant
)
7152 inst
.error
= _("constant expression expected");
7156 /* Rotate must be a multiple of 2. */
7157 if (((unsigned) expr
.X_add_number
) > 30
7158 || (expr
.X_add_number
& 1) != 0
7159 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7161 inst
.error
= _("invalid constant");
7164 inst
.instruction
|= INST_IMMEDIATE
;
7165 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7166 inst
.instruction
|= expr
.X_add_number
<< 7;
7170 /* Implicit rotation, select a suitable one. */
7171 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7175 /* Can't be done. Perhaps the code reads something like
7176 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7177 if ((value
= negate_data_op (&inst
.instruction
,
7178 inst
.reloc
.exp
.X_add_number
))
7181 inst
.error
= _("invalid constant");
7186 inst
.instruction
|= value
;
7189 inst
.instruction
|= INST_IMMEDIATE
;
7194 inst
.error
= _("register or shift expression expected");
7203 skip_whitespace (* str
);
7205 if (fp_reg_required_here (str
, 0) != FAIL
)
7209 /* Immediate expression. */
7210 if (*((*str
)++) == '#')
7216 skip_whitespace (* str
);
7218 /* First try and match exact strings, this is to guarantee
7219 that some formats will work even for cross assembly. */
7221 for (i
= 0; fp_const
[i
]; i
++)
7223 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7227 *str
+= strlen (fp_const
[i
]);
7228 if (is_end_of_line
[(unsigned char) **str
])
7230 inst
.instruction
|= i
+ 8;
7237 /* Just because we didn't get a match doesn't mean that the
7238 constant isn't valid, just that it is in a format that we
7239 don't automatically recognize. Try parsing it with
7240 the standard expression routines. */
7241 if ((i
= my_get_float_expression (str
)) >= 0)
7243 inst
.instruction
|= i
+ 8;
7247 inst
.error
= _("invalid floating point immediate expression");
7251 _("floating point register or immediate expression expected");
7260 skip_whitespace (str
);
7262 if (reg_required_here (&str
, 12) == FAIL
7263 || skip_past_comma (&str
) == FAIL
7264 || reg_required_here (&str
, 16) == FAIL
7265 || skip_past_comma (&str
) == FAIL
7266 || data_op2 (&str
) == FAIL
)
7269 inst
.error
= BAD_ARGS
;
7280 /* This is a pseudo-op of the form "adr rd, label" to be converted
7281 into a relative address of the form "add rd, pc, #label-.-8". */
7282 skip_whitespace (str
);
7284 if (reg_required_here (&str
, 12) == FAIL
7285 || skip_past_comma (&str
) == FAIL
7286 || my_get_expression (&inst
.reloc
.exp
, &str
))
7289 inst
.error
= BAD_ARGS
;
7293 /* Frag hacking will turn this into a sub instruction if the offset turns
7294 out to be negative. */
7295 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7297 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7299 inst
.reloc
.pc_rel
= 1;
7308 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7309 into a relative address of the form:
7310 add rd, pc, #low(label-.-8)"
7311 add rd, rd, #high(label-.-8)" */
7313 skip_whitespace (str
);
7315 if (reg_required_here (&str
, 12) == FAIL
7316 || skip_past_comma (&str
) == FAIL
7317 || my_get_expression (&inst
.reloc
.exp
, &str
))
7320 inst
.error
= BAD_ARGS
;
7326 /* Frag hacking will turn this into a sub instruction if the offset turns
7327 out to be negative. */
7328 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7330 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7332 inst
.reloc
.pc_rel
= 1;
7333 inst
.size
= INSN_SIZE
* 2;
7340 skip_whitespace (str
);
7342 if (reg_required_here (&str
, 16) == FAIL
)
7345 inst
.error
= BAD_ARGS
;
7349 if (skip_past_comma (&str
) == FAIL
7350 || data_op2 (&str
) == FAIL
)
7353 inst
.error
= BAD_ARGS
;
7364 skip_whitespace (str
);
7366 if (reg_required_here (&str
, 12) == FAIL
)
7369 inst
.error
= BAD_ARGS
;
7373 if (skip_past_comma (&str
) == FAIL
7374 || data_op2 (&str
) == FAIL
)
7377 inst
.error
= BAD_ARGS
;
7395 if (my_get_expression (& inst
.reloc
.exp
, str
))
7398 if (inst
.reloc
.exp
.X_op
== O_constant
)
7400 int value
= inst
.reloc
.exp
.X_add_number
;
7402 if (value
< -4095 || value
> 4095)
7404 inst
.error
= _("address offset too large");
7414 inst
.instruction
|= add
| value
;
7418 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7419 inst
.reloc
.pc_rel
= 0;
7432 if (reg_required_here (str
, 0) == FAIL
)
7435 inst
.instruction
|= add
| OFFSET_REG
;
7436 if (skip_past_comma (str
) == SUCCESS
)
7437 return decode_shift (str
, SHIFT_IMMEDIATE
);
7451 skip_whitespace (str
);
7453 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7456 inst
.error
= BAD_ARGS
;
7460 if (skip_past_comma (&str
) == FAIL
)
7462 inst
.error
= _("address expected");
7472 skip_whitespace (str
);
7474 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7477 /* Conflicts can occur on stores as well as loads. */
7478 conflict_reg
= (conflict_reg
== reg
);
7480 skip_whitespace (str
);
7486 if (skip_past_comma (&str
) == SUCCESS
)
7488 /* [Rn],... (post inc) */
7489 if (ldst_extend (&str
) == FAIL
)
7492 as_warn (_("%s register same as write-back base"),
7493 ((inst
.instruction
& LOAD_BIT
)
7494 ? _("destination") : _("source")));
7499 skip_whitespace (str
);
7504 as_warn (_("%s register same as write-back base"),
7505 ((inst
.instruction
& LOAD_BIT
)
7506 ? _("destination") : _("source")));
7508 inst
.instruction
|= WRITE_BACK
;
7511 inst
.instruction
|= INDEX_UP
;
7518 if (skip_past_comma (&str
) == FAIL
)
7520 inst
.error
= _("pre-indexed expression expected");
7525 if (ldst_extend (&str
) == FAIL
)
7528 skip_whitespace (str
);
7532 inst
.error
= _("missing ]");
7536 skip_whitespace (str
);
7541 as_warn (_("%s register same as write-back base"),
7542 ((inst
.instruction
& LOAD_BIT
)
7543 ? _("destination") : _("source")));
7545 inst
.instruction
|= WRITE_BACK
;
7549 else if (*str
== '=')
7551 if ((inst
.instruction
& LOAD_BIT
) == 0)
7553 inst
.error
= _("invalid pseudo operation");
7557 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7560 skip_whitespace (str
);
7562 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7565 if (inst
.reloc
.exp
.X_op
!= O_constant
7566 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7568 inst
.error
= _("constant expression expected");
7572 if (inst
.reloc
.exp
.X_op
== O_constant
)
7574 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7578 /* This can be done with a mov instruction. */
7579 inst
.instruction
&= LITERAL_MASK
;
7580 inst
.instruction
|= (INST_IMMEDIATE
7581 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7582 inst
.instruction
|= value
& 0xfff;
7587 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7591 /* This can be done with a mvn instruction. */
7592 inst
.instruction
&= LITERAL_MASK
;
7593 inst
.instruction
|= (INST_IMMEDIATE
7594 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7595 inst
.instruction
|= value
& 0xfff;
7601 /* Insert into literal pool. */
7602 if (add_to_lit_pool () == FAIL
)
7605 inst
.error
= _("literal pool insertion failed");
7609 /* Change the instruction exp to point to the pool. */
7610 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7611 inst
.reloc
.pc_rel
= 1;
7612 inst
.instruction
|= (REG_PC
<< 16);
7617 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7620 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7622 /* PC rel adjust. */
7623 inst
.reloc
.exp
.X_add_number
-= 8;
7625 inst
.reloc
.pc_rel
= 1;
7626 inst
.instruction
|= (REG_PC
<< 16);
7630 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7640 skip_whitespace (str
);
7642 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7645 inst
.error
= BAD_ARGS
;
7649 if (skip_past_comma (& str
) == FAIL
)
7651 inst
.error
= _("address expected");
7661 skip_whitespace (str
);
7663 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7666 /* ldrt/strt always use post-indexed addressing, so if the base is
7667 the same as Rd, we warn. */
7668 if (conflict_reg
== reg
)
7669 as_warn (_("%s register same as write-back base"),
7670 ((inst
.instruction
& LOAD_BIT
)
7671 ? _("destination") : _("source")));
7673 skip_whitespace (str
);
7679 if (skip_past_comma (&str
) == SUCCESS
)
7681 /* [Rn],... (post inc) */
7682 if (ldst_extend (&str
) == FAIL
)
7688 skip_whitespace (str
);
7690 /* Skip a write-back '!'. */
7694 inst
.instruction
|= INDEX_UP
;
7699 inst
.error
= _("post-indexed expression expected");
7705 inst
.error
= _("post-indexed expression expected");
7713 ldst_extend_v4 (str
)
7723 if (my_get_expression (& inst
.reloc
.exp
, str
))
7726 if (inst
.reloc
.exp
.X_op
== O_constant
)
7728 int value
= inst
.reloc
.exp
.X_add_number
;
7730 if (value
< -255 || value
> 255)
7732 inst
.error
= _("address offset too large");
7742 /* Halfword and signextension instructions have the
7743 immediate value split across bits 11..8 and bits 3..0. */
7744 inst
.instruction
|= (add
| HWOFFSET_IMM
7745 | ((value
>> 4) << 8) | (value
& 0xF));
7749 inst
.instruction
|= HWOFFSET_IMM
;
7750 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7751 inst
.reloc
.pc_rel
= 0;
7764 if (reg_required_here (str
, 0) == FAIL
)
7767 inst
.instruction
|= add
;
7772 /* Halfword and signed-byte load/store operations. */
7781 skip_whitespace (str
);
7783 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7786 inst
.error
= BAD_ARGS
;
7790 if (skip_past_comma (& str
) == FAIL
)
7792 inst
.error
= _("address expected");
7802 skip_whitespace (str
);
7804 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7807 /* Conflicts can occur on stores as well as loads. */
7808 conflict_reg
= (conflict_reg
== reg
);
7810 skip_whitespace (str
);
7816 if (skip_past_comma (&str
) == SUCCESS
)
7818 /* [Rn],... (post inc) */
7819 if (ldst_extend_v4 (&str
) == FAIL
)
7822 as_warn (_("%s register same as write-back base"),
7823 ((inst
.instruction
& LOAD_BIT
)
7824 ? _("destination") : _("source")));
7829 inst
.instruction
|= HWOFFSET_IMM
;
7831 skip_whitespace (str
);
7836 as_warn (_("%s register same as write-back base"),
7837 ((inst
.instruction
& LOAD_BIT
)
7838 ? _("destination") : _("source")));
7840 inst
.instruction
|= WRITE_BACK
;
7843 inst
.instruction
|= INDEX_UP
;
7850 if (skip_past_comma (&str
) == FAIL
)
7852 inst
.error
= _("pre-indexed expression expected");
7857 if (ldst_extend_v4 (&str
) == FAIL
)
7860 skip_whitespace (str
);
7864 inst
.error
= _("missing ]");
7868 skip_whitespace (str
);
7873 as_warn (_("%s register same as write-back base"),
7874 ((inst
.instruction
& LOAD_BIT
)
7875 ? _("destination") : _("source")));
7877 inst
.instruction
|= WRITE_BACK
;
7881 else if (*str
== '=')
7883 if ((inst
.instruction
& LOAD_BIT
) == 0)
7885 inst
.error
= _("invalid pseudo operation");
7889 /* XXX Does this work correctly for half-word/byte ops? */
7890 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7893 skip_whitespace (str
);
7895 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7898 if (inst
.reloc
.exp
.X_op
!= O_constant
7899 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7901 inst
.error
= _("constant expression expected");
7905 if (inst
.reloc
.exp
.X_op
== O_constant
)
7907 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7911 /* This can be done with a mov instruction. */
7912 inst
.instruction
&= LITERAL_MASK
;
7913 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7914 inst
.instruction
|= value
& 0xfff;
7919 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7923 /* This can be done with a mvn instruction. */
7924 inst
.instruction
&= LITERAL_MASK
;
7925 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7926 inst
.instruction
|= value
& 0xfff;
7932 /* Insert into literal pool. */
7933 if (add_to_lit_pool () == FAIL
)
7936 inst
.error
= _("literal pool insertion failed");
7940 /* Change the instruction exp to point to the pool. */
7941 inst
.instruction
|= HWOFFSET_IMM
;
7942 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7943 inst
.reloc
.pc_rel
= 1;
7944 inst
.instruction
|= (REG_PC
<< 16);
7949 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7952 inst
.instruction
|= HWOFFSET_IMM
;
7953 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7955 /* PC rel adjust. */
7956 inst
.reloc
.exp
.X_add_number
-= 8;
7958 inst
.reloc
.pc_rel
= 1;
7959 inst
.instruction
|= (REG_PC
<< 16);
7963 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7971 char * str
= * strp
;
7975 /* We come back here if we get ranges concatenated by '+' or '|'. */
7990 skip_whitespace (str
);
7992 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
8001 inst
.error
= _("bad range in register list");
8005 for (i
= cur_reg
+ 1; i
< reg
; i
++)
8007 if (range
& (1 << i
))
8009 (_("Warning: duplicated register (r%d) in register list"),
8017 if (range
& (1 << reg
))
8018 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8020 else if (reg
<= cur_reg
)
8021 as_tsktsk (_("Warning: register range not in ascending order"));
8026 while (skip_past_comma (&str
) != FAIL
8027 || (in_range
= 1, *str
++ == '-'));
8029 skip_whitespace (str
);
8033 inst
.error
= _("missing `}'");
8041 if (my_get_expression (&expr
, &str
))
8044 if (expr
.X_op
== O_constant
)
8046 if (expr
.X_add_number
8047 != (expr
.X_add_number
& 0x0000ffff))
8049 inst
.error
= _("invalid register mask");
8053 if ((range
& expr
.X_add_number
) != 0)
8055 int regno
= range
& expr
.X_add_number
;
8058 regno
= (1 << regno
) - 1;
8060 (_("Warning: duplicated register (r%d) in register list"),
8064 range
|= expr
.X_add_number
;
8068 if (inst
.reloc
.type
!= 0)
8070 inst
.error
= _("expression too complex");
8074 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8075 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8076 inst
.reloc
.pc_rel
= 0;
8080 skip_whitespace (str
);
8082 if (*str
== '|' || *str
== '+')
8088 while (another_range
);
8101 skip_whitespace (str
);
8103 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8106 if (base_reg
== REG_PC
)
8108 inst
.error
= _("r15 not allowed as base register");
8112 skip_whitespace (str
);
8116 inst
.instruction
|= WRITE_BACK
;
8120 if (skip_past_comma (&str
) == FAIL
8121 || (range
= reg_list (&str
)) == FAIL
)
8124 inst
.error
= BAD_ARGS
;
8131 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8134 if (inst
.instruction
& WRITE_BACK
)
8136 /* Check for unpredictable uses of writeback. */
8137 if (inst
.instruction
& LOAD_BIT
)
8139 /* Not allowed in LDM type 2. */
8140 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8141 && ((range
& (1 << REG_PC
)) == 0))
8142 as_warn (_("writeback of base register is UNPREDICTABLE"));
8143 /* Only allowed if base reg not in list for other types. */
8144 else if (range
& (1 << base_reg
))
8145 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8149 /* Not allowed for type 2. */
8150 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8151 as_warn (_("writeback of base register is UNPREDICTABLE"));
8152 /* Only allowed if base reg not in list, or first in list. */
8153 else if ((range
& (1 << base_reg
))
8154 && (range
& ((1 << base_reg
) - 1)))
8155 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8159 inst
.instruction
|= range
;
8167 skip_whitespace (str
);
8169 /* Allow optional leading '#'. */
8170 if (is_immediate_prefix (*str
))
8173 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8176 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8177 inst
.reloc
.pc_rel
= 0;
8187 skip_whitespace (str
);
8189 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8194 inst
.error
= _("r15 not allowed in swap");
8198 if (skip_past_comma (&str
) == FAIL
8199 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8202 inst
.error
= BAD_ARGS
;
8208 inst
.error
= _("r15 not allowed in swap");
8212 if (skip_past_comma (&str
) == FAIL
8215 inst
.error
= BAD_ARGS
;
8219 skip_whitespace (str
);
8221 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8226 inst
.error
= BAD_PC
;
8230 skip_whitespace (str
);
8234 inst
.error
= _("missing ]");
8245 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8252 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8253 required for the instruction. */
8255 /* arm_parse_reloc () works on input_line_pointer.
8256 We actually want to parse the operands to the branch instruction
8257 passed in 'str'. Save the input pointer and restore it later. */
8258 save_in
= input_line_pointer
;
8259 input_line_pointer
= str
;
8260 if (inst
.reloc
.exp
.X_op
== O_symbol
8262 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8264 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8265 inst
.reloc
.pc_rel
= 0;
8266 /* Modify str to point to after parsed operands, otherwise
8267 end_of_line() will complain about the (PLT) left in str. */
8268 str
= input_line_pointer
;
8272 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8273 inst
.reloc
.pc_rel
= 1;
8275 input_line_pointer
= save_in
;
8278 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8279 inst
.reloc
.pc_rel
= 1;
8280 #endif /* OBJ_ELF */
8291 skip_whitespace (str
);
8293 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8295 inst
.error
= BAD_ARGS
;
8299 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8301 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8310 /* Co-processor data operation.
8311 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8312 skip_whitespace (str
);
8314 if (co_proc_number (&str
) == FAIL
)
8317 inst
.error
= BAD_ARGS
;
8321 if (skip_past_comma (&str
) == FAIL
8322 || cp_opc_expr (&str
, 20,4) == FAIL
)
8325 inst
.error
= BAD_ARGS
;
8329 if (skip_past_comma (&str
) == FAIL
8330 || cp_reg_required_here (&str
, 12) == FAIL
)
8333 inst
.error
= BAD_ARGS
;
8337 if (skip_past_comma (&str
) == FAIL
8338 || cp_reg_required_here (&str
, 16) == FAIL
)
8341 inst
.error
= BAD_ARGS
;
8345 if (skip_past_comma (&str
) == FAIL
8346 || cp_reg_required_here (&str
, 0) == FAIL
)
8349 inst
.error
= BAD_ARGS
;
8353 if (skip_past_comma (&str
) == SUCCESS
)
8355 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8358 inst
.error
= BAD_ARGS
;
8370 /* Co-processor register load/store.
8371 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8373 skip_whitespace (str
);
8375 if (co_proc_number (&str
) == FAIL
)
8378 inst
.error
= BAD_ARGS
;
8382 if (skip_past_comma (&str
) == FAIL
8383 || cp_reg_required_here (&str
, 12) == FAIL
)
8386 inst
.error
= BAD_ARGS
;
8390 if (skip_past_comma (&str
) == FAIL
8391 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8394 inst
.error
= BAD_ARGS
;
8405 /* Co-processor register transfer.
8406 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8408 skip_whitespace (str
);
8410 if (co_proc_number (&str
) == FAIL
)
8413 inst
.error
= BAD_ARGS
;
8417 if (skip_past_comma (&str
) == FAIL
8418 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8421 inst
.error
= BAD_ARGS
;
8425 if (skip_past_comma (&str
) == FAIL
8426 || reg_required_here (&str
, 12) == FAIL
)
8429 inst
.error
= BAD_ARGS
;
8433 if (skip_past_comma (&str
) == FAIL
8434 || cp_reg_required_here (&str
, 16) == FAIL
)
8437 inst
.error
= BAD_ARGS
;
8441 if (skip_past_comma (&str
) == FAIL
8442 || cp_reg_required_here (&str
, 0) == FAIL
)
8445 inst
.error
= BAD_ARGS
;
8449 if (skip_past_comma (&str
) == SUCCESS
)
8451 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8454 inst
.error
= BAD_ARGS
;
8466 /* FP control registers.
8467 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8469 skip_whitespace (str
);
8471 if (reg_required_here (&str
, 12) == FAIL
)
8474 inst
.error
= BAD_ARGS
;
8485 skip_whitespace (str
);
8487 if (fp_reg_required_here (&str
, 12) == FAIL
)
8490 inst
.error
= BAD_ARGS
;
8494 if (skip_past_comma (&str
) == FAIL
8495 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8498 inst
.error
= BAD_ARGS
;
8511 skip_whitespace (str
);
8513 if (fp_reg_required_here (&str
, 12) == FAIL
)
8516 inst
.error
= BAD_ARGS
;
8520 /* Get Number of registers to transfer. */
8521 if (skip_past_comma (&str
) == FAIL
8522 || my_get_expression (&inst
.reloc
.exp
, &str
))
8525 inst
.error
= _("constant expression expected");
8529 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8531 inst
.error
= _("constant value required for number of registers");
8535 num_regs
= inst
.reloc
.exp
.X_add_number
;
8537 if (num_regs
< 1 || num_regs
> 4)
8539 inst
.error
= _("number of registers must be in the range [1:4]");
8546 inst
.instruction
|= CP_T_X
;
8549 inst
.instruction
|= CP_T_Y
;
8552 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8560 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8566 /* The instruction specified "ea" or "fd", so we can only accept
8567 [Rn]{!}. The instruction does not really support stacking or
8568 unstacking, so we have to emulate these by setting appropriate
8569 bits and offsets. */
8570 if (skip_past_comma (&str
) == FAIL
8574 inst
.error
= BAD_ARGS
;
8579 skip_whitespace (str
);
8581 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8584 skip_whitespace (str
);
8588 inst
.error
= BAD_ARGS
;
8600 _("r15 not allowed as base register with write-back");
8607 if (inst
.instruction
& CP_T_Pre
)
8609 /* Pre-decrement. */
8610 offset
= 3 * num_regs
;
8612 inst
.instruction
|= CP_T_WB
;
8616 /* Post-increment. */
8619 inst
.instruction
|= CP_T_WB
;
8620 offset
= 3 * num_regs
;
8624 /* No write-back, so convert this into a standard pre-increment
8625 instruction -- aesthetically more pleasing. */
8626 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8631 inst
.instruction
|= offset
;
8633 else if (skip_past_comma (&str
) == FAIL
8634 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8637 inst
.error
= BAD_ARGS
;
8648 skip_whitespace (str
);
8650 if (fp_reg_required_here (&str
, 12) == FAIL
)
8653 inst
.error
= BAD_ARGS
;
8657 if (skip_past_comma (&str
) == FAIL
8658 || fp_reg_required_here (&str
, 16) == FAIL
)
8661 inst
.error
= BAD_ARGS
;
8665 if (skip_past_comma (&str
) == FAIL
8666 || fp_op2 (&str
) == FAIL
)
8669 inst
.error
= BAD_ARGS
;
8677 do_fpa_monadic (str
)
8680 skip_whitespace (str
);
8682 if (fp_reg_required_here (&str
, 12) == FAIL
)
8685 inst
.error
= BAD_ARGS
;
8689 if (skip_past_comma (&str
) == FAIL
8690 || fp_op2 (&str
) == FAIL
)
8693 inst
.error
= BAD_ARGS
;
8704 skip_whitespace (str
);
8706 if (fp_reg_required_here (&str
, 16) == FAIL
)
8709 inst
.error
= BAD_ARGS
;
8713 if (skip_past_comma (&str
) == FAIL
8714 || fp_op2 (&str
) == FAIL
)
8717 inst
.error
= BAD_ARGS
;
8725 do_fpa_from_reg (str
)
8728 skip_whitespace (str
);
8730 if (fp_reg_required_here (&str
, 16) == FAIL
)
8733 inst
.error
= BAD_ARGS
;
8737 if (skip_past_comma (&str
) == FAIL
8738 || reg_required_here (&str
, 12) == FAIL
)
8741 inst
.error
= BAD_ARGS
;
8752 skip_whitespace (str
);
8754 if (reg_required_here (&str
, 12) == FAIL
)
8757 if (skip_past_comma (&str
) == FAIL
8758 || fp_reg_required_here (&str
, 0) == FAIL
)
8761 inst
.error
= BAD_ARGS
;
8769 vfp_sp_reg_required_here (str
, pos
)
8771 enum vfp_sp_reg_pos pos
;
8776 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8781 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8785 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8789 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8798 /* In the few cases where we might be able to accept something else
8799 this error can be overridden. */
8800 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8802 /* Restore the start point. */
8808 vfp_dp_reg_required_here (str
, pos
)
8810 enum vfp_dp_reg_pos pos
;
8815 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8820 inst
.instruction
|= reg
<< 12;
8824 inst
.instruction
|= reg
<< 16;
8828 inst
.instruction
|= reg
<< 0;
8837 /* In the few cases where we might be able to accept something else
8838 this error can be overridden. */
8839 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8841 /* Restore the start point. */
8847 do_vfp_sp_monadic (str
)
8850 skip_whitespace (str
);
8852 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8855 if (skip_past_comma (&str
) == FAIL
8856 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8859 inst
.error
= BAD_ARGS
;
8867 do_vfp_dp_monadic (str
)
8870 skip_whitespace (str
);
8872 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8875 if (skip_past_comma (&str
) == FAIL
8876 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8879 inst
.error
= BAD_ARGS
;
8887 do_vfp_sp_dyadic (str
)
8890 skip_whitespace (str
);
8892 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8895 if (skip_past_comma (&str
) == FAIL
8896 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8897 || skip_past_comma (&str
) == FAIL
8898 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8901 inst
.error
= BAD_ARGS
;
8909 do_vfp_dp_dyadic (str
)
8912 skip_whitespace (str
);
8914 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8917 if (skip_past_comma (&str
) == FAIL
8918 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8919 || skip_past_comma (&str
) == FAIL
8920 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8923 inst
.error
= BAD_ARGS
;
8931 do_vfp_reg_from_sp (str
)
8934 skip_whitespace (str
);
8936 if (reg_required_here (&str
, 12) == FAIL
)
8939 if (skip_past_comma (&str
) == FAIL
8940 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8943 inst
.error
= BAD_ARGS
;
8951 do_vfp_reg2_from_sp2 (str
)
8954 skip_whitespace (str
);
8956 if (reg_required_here (&str
, 12) == FAIL
8957 || skip_past_comma (&str
) == FAIL
8958 || reg_required_here (&str
, 16) == FAIL
8959 || skip_past_comma (&str
) == FAIL
)
8962 inst
.error
= BAD_ARGS
;
8966 /* We require exactly two consecutive SP registers. */
8967 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8970 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8977 do_vfp_sp_from_reg (str
)
8980 skip_whitespace (str
);
8982 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8985 if (skip_past_comma (&str
) == FAIL
8986 || reg_required_here (&str
, 12) == FAIL
)
8989 inst
.error
= BAD_ARGS
;
8997 do_vfp_sp2_from_reg2 (str
)
9000 skip_whitespace (str
);
9002 /* We require exactly two consecutive SP registers. */
9003 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
9006 inst
.error
= _("only two consecutive VFP SP registers allowed here");
9009 if (skip_past_comma (&str
) == FAIL
9010 || reg_required_here (&str
, 12) == FAIL
9011 || skip_past_comma (&str
) == FAIL
9012 || reg_required_here (&str
, 16) == FAIL
)
9015 inst
.error
= BAD_ARGS
;
9023 do_vfp_reg_from_dp (str
)
9026 skip_whitespace (str
);
9028 if (reg_required_here (&str
, 12) == FAIL
)
9031 if (skip_past_comma (&str
) == FAIL
9032 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9035 inst
.error
= BAD_ARGS
;
9043 do_vfp_reg2_from_dp (str
)
9046 skip_whitespace (str
);
9048 if (reg_required_here (&str
, 12) == FAIL
)
9051 if (skip_past_comma (&str
) == FAIL
9052 || reg_required_here (&str
, 16) == FAIL
9053 || skip_past_comma (&str
) == FAIL
9054 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9057 inst
.error
= BAD_ARGS
;
9065 do_vfp_dp_from_reg (str
)
9068 skip_whitespace (str
);
9070 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9073 if (skip_past_comma (&str
) == FAIL
9074 || reg_required_here (&str
, 12) == FAIL
)
9077 inst
.error
= BAD_ARGS
;
9085 do_vfp_dp_from_reg2 (str
)
9088 skip_whitespace (str
);
9090 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9093 if (skip_past_comma (&str
) == FAIL
9094 || reg_required_here (&str
, 12) == FAIL
9095 || skip_past_comma (&str
) == FAIL
9096 || reg_required_here (&str
, 16) == FAIL
)
9099 inst
.error
= BAD_ARGS
;
9106 static const struct vfp_reg
*
9113 const struct vfp_reg
*vreg
;
9117 /* Find the end of the current token. */
9122 while (ISALPHA (c
));
9127 for (vreg
= vfp_regs
+ 0;
9128 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9131 if (strcmp (start
, vreg
->name
) == 0)
9144 vfp_psr_required_here (str
)
9148 const struct vfp_reg
*vreg
;
9150 vreg
= vfp_psr_parse (str
);
9154 inst
.instruction
|= vreg
->regno
;
9158 inst
.error
= _("VFP system register expected");
9165 do_vfp_reg_from_ctrl (str
)
9168 skip_whitespace (str
);
9170 if (reg_required_here (&str
, 12) == FAIL
)
9173 if (skip_past_comma (&str
) == FAIL
9174 || vfp_psr_required_here (&str
) == FAIL
)
9177 inst
.error
= BAD_ARGS
;
9185 do_vfp_ctrl_from_reg (str
)
9188 skip_whitespace (str
);
9190 if (vfp_psr_required_here (&str
) == FAIL
)
9193 if (skip_past_comma (&str
) == FAIL
9194 || reg_required_here (&str
, 12) == FAIL
)
9197 inst
.error
= BAD_ARGS
;
9205 do_vfp_sp_ldst (str
)
9208 skip_whitespace (str
);
9210 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9213 inst
.error
= BAD_ARGS
;
9217 if (skip_past_comma (&str
) == FAIL
9218 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9221 inst
.error
= BAD_ARGS
;
9229 do_vfp_dp_ldst (str
)
9232 skip_whitespace (str
);
9234 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9237 inst
.error
= BAD_ARGS
;
9241 if (skip_past_comma (&str
) == FAIL
9242 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9245 inst
.error
= BAD_ARGS
;
9252 /* Parse and encode a VFP SP register list, storing the initial
9253 register in position POS and returning the range as the result. If
9254 the string is invalid return FAIL (an invalid range). */
9256 vfp_sp_reg_list (str
, pos
)
9258 enum vfp_sp_reg_pos pos
;
9266 unsigned long mask
= 0;
9273 skip_whitespace (*str
);
9275 tempinst
= inst
.instruction
;
9279 inst
.instruction
= 0;
9281 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9284 if (count
== 0 || base_reg
> new_base
)
9286 base_reg
= new_base
;
9287 base_bits
= inst
.instruction
;
9290 if (mask
& (1 << new_base
))
9292 inst
.error
= _("invalid register list");
9296 if ((mask
>> new_base
) != 0 && ! warned
)
9298 as_tsktsk (_("register list not in ascending order"));
9302 mask
|= 1 << new_base
;
9305 skip_whitespace (*str
);
9307 if (**str
== '-') /* We have the start of a range expression */
9314 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9317 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9321 if (high_range
<= new_base
)
9323 inst
.error
= _("register range not in ascending order");
9327 for (new_base
++; new_base
<= high_range
; new_base
++)
9329 if (mask
& (1 << new_base
))
9331 inst
.error
= _("invalid register list");
9335 mask
|= 1 << new_base
;
9340 while (skip_past_comma (str
) != FAIL
);
9344 inst
.error
= _("invalid register list");
9352 /* Sanity check -- should have raised a parse error above. */
9353 if (count
== 0 || count
> 32)
9356 /* Final test -- the registers must be consecutive. */
9359 if ((mask
& (1 << base_reg
++)) == 0)
9361 inst
.error
= _("non-contiguous register range");
9366 inst
.instruction
= tempinst
| base_bits
;
9371 vfp_dp_reg_list (str
)
9379 unsigned long mask
= 0;
9386 skip_whitespace (*str
);
9388 tempinst
= inst
.instruction
;
9392 inst
.instruction
= 0;
9394 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9397 if (count
== 0 || base_reg
> new_base
)
9399 base_reg
= new_base
;
9400 range
= inst
.instruction
;
9403 if (mask
& (1 << new_base
))
9405 inst
.error
= _("invalid register list");
9409 if ((mask
>> new_base
) != 0 && ! warned
)
9411 as_tsktsk (_("register list not in ascending order"));
9415 mask
|= 1 << new_base
;
9418 skip_whitespace (*str
);
9420 if (**str
== '-') /* We have the start of a range expression */
9427 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9430 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9434 if (high_range
<= new_base
)
9436 inst
.error
= _("register range not in ascending order");
9440 for (new_base
++; new_base
<= high_range
; new_base
++)
9442 if (mask
& (1 << new_base
))
9444 inst
.error
= _("invalid register list");
9448 mask
|= 1 << new_base
;
9453 while (skip_past_comma (str
) != FAIL
);
9457 inst
.error
= _("invalid register list");
9465 /* Sanity check -- should have raised a parse error above. */
9466 if (count
== 0 || count
> 16)
9469 /* Final test -- the registers must be consecutive. */
9472 if ((mask
& (1 << base_reg
++)) == 0)
9474 inst
.error
= _("non-contiguous register range");
9479 inst
.instruction
= tempinst
;
9484 vfp_sp_ldstm (str
, ldstm_type
)
9486 enum vfp_ldstm_type ldstm_type
;
9490 skip_whitespace (str
);
9492 if (reg_required_here (&str
, 16) == FAIL
)
9495 skip_whitespace (str
);
9499 inst
.instruction
|= WRITE_BACK
;
9502 else if (ldstm_type
!= VFP_LDSTMIA
)
9504 inst
.error
= _("this addressing mode requires base-register writeback");
9508 if (skip_past_comma (&str
) == FAIL
9509 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9512 inst
.error
= BAD_ARGS
;
9516 inst
.instruction
|= range
;
9521 vfp_dp_ldstm (str
, ldstm_type
)
9523 enum vfp_ldstm_type ldstm_type
;
9527 skip_whitespace (str
);
9529 if (reg_required_here (&str
, 16) == FAIL
)
9532 skip_whitespace (str
);
9536 inst
.instruction
|= WRITE_BACK
;
9539 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9541 inst
.error
= _("this addressing mode requires base-register writeback");
9545 if (skip_past_comma (&str
) == FAIL
9546 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9549 inst
.error
= BAD_ARGS
;
9553 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9556 inst
.instruction
|= range
;
9561 do_vfp_sp_ldstmia (str
)
9564 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9568 do_vfp_sp_ldstmdb (str
)
9571 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9575 do_vfp_dp_ldstmia (str
)
9578 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9582 do_vfp_dp_ldstmdb (str
)
9585 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9589 do_vfp_xp_ldstmia (str
)
9592 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9596 do_vfp_xp_ldstmdb (str
)
9599 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9603 do_vfp_sp_compare_z (str
)
9606 skip_whitespace (str
);
9608 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9611 inst
.error
= BAD_ARGS
;
9619 do_vfp_dp_compare_z (str
)
9622 skip_whitespace (str
);
9624 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9627 inst
.error
= BAD_ARGS
;
9635 do_vfp_dp_sp_cvt (str
)
9638 skip_whitespace (str
);
9640 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9643 if (skip_past_comma (&str
) == FAIL
9644 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9647 inst
.error
= BAD_ARGS
;
9655 do_vfp_sp_dp_cvt (str
)
9658 skip_whitespace (str
);
9660 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9663 if (skip_past_comma (&str
) == FAIL
9664 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9667 inst
.error
= BAD_ARGS
;
9674 /* Thumb specific routines. */
9676 /* Parse and validate that a register is of the right form, this saves
9677 repeated checking of this information in many similar cases.
9678 Unlike the 32-bit case we do not insert the register into the opcode
9679 here, since the position is often unknown until the full instruction
9683 thumb_reg (strp
, hi_lo
)
9689 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9697 inst
.error
= _("lo register required");
9705 inst
.error
= _("hi register required");
9717 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9721 thumb_add_sub (str
, subtract
)
9725 int Rd
, Rs
, Rn
= FAIL
;
9727 skip_whitespace (str
);
9729 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9730 || skip_past_comma (&str
) == FAIL
)
9733 inst
.error
= BAD_ARGS
;
9737 if (is_immediate_prefix (*str
))
9741 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9746 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9749 if (skip_past_comma (&str
) == FAIL
)
9751 /* Two operand format, shuffle the registers
9752 and pretend there are 3. */
9756 else if (is_immediate_prefix (*str
))
9759 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9762 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9766 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9767 for the latter case, EXPR contains the immediate that was found. */
9770 /* All register format. */
9771 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9775 inst
.error
= _("dest and source1 must be the same register");
9779 /* Can't do this for SUB. */
9782 inst
.error
= _("subtract valid only on lo regs");
9786 inst
.instruction
= (T_OPCODE_ADD_HI
9787 | (Rd
> 7 ? THUMB_H1
: 0)
9788 | (Rn
> 7 ? THUMB_H2
: 0));
9789 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9793 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9794 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9799 /* Immediate expression, now things start to get nasty. */
9801 /* First deal with HI regs, only very restricted cases allowed:
9802 Adjusting SP, and using PC or SP to get an address. */
9803 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9804 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9806 inst
.error
= _("invalid Hi register with immediate");
9810 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9812 /* Value isn't known yet, all we can do is store all the fragments
9813 we know about in the instruction and let the reloc hacking
9815 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9816 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9820 int offset
= inst
.reloc
.exp
.X_add_number
;
9830 /* Quick check, in case offset is MIN_INT. */
9833 inst
.error
= _("immediate value out of range");
9837 /* Note - you cannot convert a subtract of 0 into an
9838 add of 0 because the carry flag is set differently. */
9839 else if (offset
> 0)
9844 if (offset
& ~0x1fc)
9846 inst
.error
= _("invalid immediate value for stack adjust");
9849 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9850 inst
.instruction
|= offset
>> 2;
9852 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9855 || (offset
& ~0x3fc))
9857 inst
.error
= _("invalid immediate for address calculation");
9860 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9862 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9868 inst
.error
= _("immediate value out of range");
9871 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9872 inst
.instruction
|= (Rd
<< 8) | offset
;
9878 inst
.error
= _("immediate value out of range");
9881 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9882 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9891 thumb_shift (str
, shift
)
9895 int Rd
, Rs
, Rn
= FAIL
;
9897 skip_whitespace (str
);
9899 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9900 || skip_past_comma (&str
) == FAIL
)
9903 inst
.error
= BAD_ARGS
;
9907 if (is_immediate_prefix (*str
))
9909 /* Two operand immediate format, set Rs to Rd. */
9912 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9917 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9920 if (skip_past_comma (&str
) == FAIL
)
9922 /* Two operand format, shuffle the registers
9923 and pretend there are 3. */
9927 else if (is_immediate_prefix (*str
))
9930 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9933 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9937 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9938 for the latter case, EXPR contains the immediate that was found. */
9944 inst
.error
= _("source1 and dest must be same register");
9950 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9951 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9952 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9955 inst
.instruction
|= Rd
| (Rn
<< 3);
9961 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9962 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9963 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9966 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9968 /* Value isn't known yet, create a dummy reloc and let reloc
9969 hacking fix it up. */
9970 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9974 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9976 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9978 inst
.error
= _("invalid immediate for shift");
9982 /* Shifts of zero are handled by converting to LSL. */
9983 if (shift_value
== 0)
9984 inst
.instruction
= T_OPCODE_LSL_I
;
9986 /* Shifts of 32 are encoded as a shift of zero. */
9987 if (shift_value
== 32)
9990 inst
.instruction
|= shift_value
<< 6;
9993 inst
.instruction
|= Rd
| (Rs
<< 3);
10000 thumb_mov_compare (str
, move
)
10006 skip_whitespace (str
);
10008 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
10009 || skip_past_comma (&str
) == FAIL
)
10012 inst
.error
= BAD_ARGS
;
10016 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
10019 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10022 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10027 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
10029 if (move
== THUMB_MOVE
)
10030 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10031 since a MOV instruction produces unpredictable results. */
10032 inst
.instruction
= T_OPCODE_ADD_I3
;
10034 inst
.instruction
= T_OPCODE_CMP_LR
;
10035 inst
.instruction
|= Rd
| (Rs
<< 3);
10039 if (move
== THUMB_MOVE
)
10040 inst
.instruction
= T_OPCODE_MOV_HR
;
10041 else if (move
!= THUMB_CPY
)
10042 inst
.instruction
= T_OPCODE_CMP_HR
;
10045 inst
.instruction
|= THUMB_H1
;
10048 inst
.instruction
|= THUMB_H2
;
10050 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
10057 inst
.error
= _("only lo regs allowed with immediate");
10061 if (move
== THUMB_MOVE
)
10062 inst
.instruction
= T_OPCODE_MOV_I8
;
10064 inst
.instruction
= T_OPCODE_CMP_I8
;
10066 inst
.instruction
|= Rd
<< 8;
10068 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10069 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10072 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10076 inst
.error
= _("invalid immediate");
10080 inst
.instruction
|= value
;
10088 thumb_load_store (str
, load_store
, size
)
10093 int Rd
, Rb
, Ro
= FAIL
;
10095 skip_whitespace (str
);
10097 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10098 || skip_past_comma (&str
) == FAIL
)
10101 inst
.error
= BAD_ARGS
;
10108 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10111 if (skip_past_comma (&str
) != FAIL
)
10113 if (is_immediate_prefix (*str
))
10116 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10119 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10124 inst
.reloc
.exp
.X_op
= O_constant
;
10125 inst
.reloc
.exp
.X_add_number
= 0;
10130 inst
.error
= _("expected ']'");
10135 else if (*str
== '=')
10137 if (load_store
!= THUMB_LOAD
)
10139 inst
.error
= _("invalid pseudo operation");
10143 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10146 skip_whitespace (str
);
10148 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10153 if ( inst
.reloc
.exp
.X_op
!= O_constant
10154 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10156 inst
.error
= "Constant expression expected";
10160 if (inst
.reloc
.exp
.X_op
== O_constant
10161 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10163 /* This can be done with a mov instruction. */
10165 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10166 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10170 /* Insert into literal pool. */
10171 if (add_to_lit_pool () == FAIL
)
10174 inst
.error
= "literal pool insertion failed";
10178 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10179 inst
.reloc
.pc_rel
= 1;
10180 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10181 /* Adjust ARM pipeline offset to Thumb. */
10182 inst
.reloc
.exp
.X_add_number
+= 4;
10188 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10191 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10192 inst
.reloc
.pc_rel
= 1;
10193 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10194 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10199 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10201 if (size
!= THUMB_WORD
)
10203 inst
.error
= _("byte or halfword not valid for base register");
10206 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10208 inst
.error
= _("r15 based store not allowed");
10211 else if (Ro
!= FAIL
)
10213 inst
.error
= _("invalid base register for register offset");
10218 inst
.instruction
= T_OPCODE_LDR_PC
;
10219 else if (load_store
== THUMB_LOAD
)
10220 inst
.instruction
= T_OPCODE_LDR_SP
;
10222 inst
.instruction
= T_OPCODE_STR_SP
;
10224 inst
.instruction
|= Rd
<< 8;
10225 if (inst
.reloc
.exp
.X_op
== O_constant
)
10227 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10229 if (offset
& ~0x3fc)
10231 inst
.error
= _("invalid offset");
10235 inst
.instruction
|= offset
>> 2;
10238 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10242 inst
.error
= _("invalid base register in load/store");
10245 else if (Ro
== FAIL
)
10247 /* Immediate offset. */
10248 if (size
== THUMB_WORD
)
10249 inst
.instruction
= (load_store
== THUMB_LOAD
10250 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10251 else if (size
== THUMB_HALFWORD
)
10252 inst
.instruction
= (load_store
== THUMB_LOAD
10253 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10255 inst
.instruction
= (load_store
== THUMB_LOAD
10256 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10258 inst
.instruction
|= Rd
| (Rb
<< 3);
10260 if (inst
.reloc
.exp
.X_op
== O_constant
)
10262 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10264 if (offset
& ~(0x1f << size
))
10266 inst
.error
= _("invalid offset");
10269 inst
.instruction
|= (offset
>> size
) << 6;
10272 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10276 /* Register offset. */
10277 if (size
== THUMB_WORD
)
10278 inst
.instruction
= (load_store
== THUMB_LOAD
10279 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10280 else if (size
== THUMB_HALFWORD
)
10281 inst
.instruction
= (load_store
== THUMB_LOAD
10282 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10284 inst
.instruction
= (load_store
== THUMB_LOAD
10285 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10287 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10293 /* A register must be given at this point.
10295 Shift is the place to put it in inst.instruction.
10297 Restores input start point on err.
10298 Returns the reg#, or FAIL. */
10301 mav_reg_required_here (str
, shift
, regtype
)
10304 enum arm_reg_type regtype
;
10307 char *start
= *str
;
10309 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10312 inst
.instruction
|= reg
<< shift
;
10317 /* Restore the start point. */
10320 /* In the few cases where we might be able to accept something else
10321 this error can be overridden. */
10322 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10327 /* Cirrus Maverick Instructions. */
10329 /* Wrapper functions. */
10332 do_mav_binops_1a (str
)
10335 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10339 do_mav_binops_1b (str
)
10342 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10346 do_mav_binops_1c (str
)
10349 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10353 do_mav_binops_1d (str
)
10356 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10360 do_mav_binops_1e (str
)
10363 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10367 do_mav_binops_1f (str
)
10370 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10374 do_mav_binops_1g (str
)
10377 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10381 do_mav_binops_1h (str
)
10384 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10388 do_mav_binops_1i (str
)
10391 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10395 do_mav_binops_1j (str
)
10398 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10402 do_mav_binops_1k (str
)
10405 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10409 do_mav_binops_1l (str
)
10412 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10416 do_mav_binops_1m (str
)
10419 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10423 do_mav_binops_1n (str
)
10426 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10430 do_mav_binops_1o (str
)
10433 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10437 do_mav_binops_2a (str
)
10440 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10444 do_mav_binops_2b (str
)
10447 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10451 do_mav_binops_2c (str
)
10454 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10458 do_mav_binops_3a (str
)
10461 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10465 do_mav_binops_3b (str
)
10468 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10472 do_mav_binops_3c (str
)
10475 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10479 do_mav_binops_3d (str
)
10482 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10486 do_mav_triple_4a (str
)
10489 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10493 do_mav_triple_4b (str
)
10496 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10500 do_mav_triple_5a (str
)
10503 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10507 do_mav_triple_5b (str
)
10510 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10514 do_mav_triple_5c (str
)
10517 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10521 do_mav_triple_5d (str
)
10524 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10528 do_mav_triple_5e (str
)
10531 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10535 do_mav_triple_5f (str
)
10538 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10542 do_mav_triple_5g (str
)
10545 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10549 do_mav_triple_5h (str
)
10552 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10556 do_mav_quad_6a (str
)
10559 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10564 do_mav_quad_6b (str
)
10567 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10571 /* cfmvsc32<cond> DSPSC,MVDX[15:0]. */
10573 do_mav_dspsc_1 (str
)
10576 skip_whitespace (str
);
10579 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10580 || skip_past_comma (&str
) == FAIL
10581 || mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
)
10584 inst
.error
= BAD_ARGS
;
10592 /* cfmv32sc<cond> MVDX[15:0],DSPSC. */
10594 do_mav_dspsc_2 (str
)
10597 skip_whitespace (str
);
10600 if (mav_reg_required_here (&str
, 12, REG_TYPE_MVDX
) == FAIL
10601 || skip_past_comma (&str
) == FAIL
10602 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10605 inst
.error
= BAD_ARGS
;
10614 do_mav_shift_1 (str
)
10617 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10621 do_mav_shift_2 (str
)
10624 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10628 do_mav_ldst_1 (str
)
10631 do_mav_ldst (str
, REG_TYPE_MVF
);
10635 do_mav_ldst_2 (str
)
10638 do_mav_ldst (str
, REG_TYPE_MVD
);
10642 do_mav_ldst_3 (str
)
10645 do_mav_ldst (str
, REG_TYPE_MVFX
);
10649 do_mav_ldst_4 (str
)
10652 do_mav_ldst (str
, REG_TYPE_MVDX
);
10655 /* Isnsn like "foo X,Y". */
10658 do_mav_binops (str
, mode
, reg0
, reg1
)
10661 enum arm_reg_type reg0
;
10662 enum arm_reg_type reg1
;
10664 int shift0
, shift1
;
10666 shift0
= mode
& 0xff;
10667 shift1
= (mode
>> 8) & 0xff;
10669 skip_whitespace (str
);
10671 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10672 || skip_past_comma (&str
) == FAIL
10673 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10676 inst
.error
= BAD_ARGS
;
10682 /* Isnsn like "foo X,Y,Z". */
10685 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10688 enum arm_reg_type reg0
;
10689 enum arm_reg_type reg1
;
10690 enum arm_reg_type reg2
;
10692 int shift0
, shift1
, shift2
;
10694 shift0
= mode
& 0xff;
10695 shift1
= (mode
>> 8) & 0xff;
10696 shift2
= (mode
>> 16) & 0xff;
10698 skip_whitespace (str
);
10700 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10701 || skip_past_comma (&str
) == FAIL
10702 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10703 || skip_past_comma (&str
) == FAIL
10704 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10707 inst
.error
= BAD_ARGS
;
10713 /* Isnsn like "foo W,X,Y,Z".
10714 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10717 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10720 enum arm_reg_type reg0
;
10721 enum arm_reg_type reg1
;
10722 enum arm_reg_type reg2
;
10723 enum arm_reg_type reg3
;
10725 int shift0
, shift1
, shift2
, shift3
;
10727 shift0
= mode
& 0xff;
10728 shift1
= (mode
>> 8) & 0xff;
10729 shift2
= (mode
>> 16) & 0xff;
10730 shift3
= (mode
>> 24) & 0xff;
10732 skip_whitespace (str
);
10734 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10735 || skip_past_comma (&str
) == FAIL
10736 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10737 || skip_past_comma (&str
) == FAIL
10738 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10739 || skip_past_comma (&str
) == FAIL
10740 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10743 inst
.error
= BAD_ARGS
;
10749 /* Maverick shift immediate instructions.
10750 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10751 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10754 do_mav_shift (str
, reg0
, reg1
)
10756 enum arm_reg_type reg0
;
10757 enum arm_reg_type reg1
;
10762 skip_whitespace (str
);
10766 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10767 || skip_past_comma (&str
) == FAIL
10768 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10769 || skip_past_comma (&str
) == FAIL
)
10772 inst
.error
= BAD_ARGS
;
10776 /* Calculate the immediate operand.
10777 The operand is a 7bit signed number. */
10778 skip_whitespace (str
);
10783 if (!ISDIGIT (*str
) && *str
!= '-')
10785 inst
.error
= _("expecting immediate, 7bit operand");
10795 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10796 imm
= imm
* 10 + *str
- '0';
10800 inst
.error
= _("immediate out of range");
10804 /* Make negative imm's into 7bit signed numbers. */
10811 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10812 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10813 Bit 4 should be 0. */
10814 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10816 inst
.instruction
|= imm
;
10821 mav_parse_offset (str
, negative
)
10830 skip_whitespace (p
);
10843 inst
.error
= _("offset expected");
10847 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10848 offset
= offset
* 10 + *p
- '0';
10852 inst
.error
= _("offset out of range");
10858 return *negative
? -offset
: offset
;
10861 /* Maverick load/store instructions.
10862 <insn><cond> CRd,[Rn,<offset>]{!}.
10863 <insn><cond> CRd,[Rn],<offset>. */
10866 do_mav_ldst (str
, reg0
)
10868 enum arm_reg_type reg0
;
10870 int offset
, negative
;
10872 skip_whitespace (str
);
10874 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10875 || skip_past_comma (&str
) == FAIL
10877 || reg_required_here (&str
, 16) == FAIL
)
10880 if (skip_past_comma (&str
) == SUCCESS
)
10882 /* You are here: "<offset>]{!}". */
10883 inst
.instruction
|= PRE_INDEX
;
10885 offset
= mav_parse_offset (&str
, &negative
);
10892 inst
.error
= _("missing ]");
10898 inst
.instruction
|= WRITE_BACK
;
10904 /* You are here: "], <offset>". */
10907 inst
.error
= _("missing ]");
10911 if (skip_past_comma (&str
) == FAIL
10912 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10915 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10921 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10923 inst
.instruction
|= offset
>> 2;
10929 inst
.error
= BAD_ARGS
;
10940 /* Handle the Format 4 instructions that do not have equivalents in other
10941 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10950 skip_whitespace (str
);
10952 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10953 || skip_past_comma (&str
) == FAIL
10954 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10956 inst
.error
= BAD_ARGS
;
10960 if (skip_past_comma (&str
) != FAIL
)
10962 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10963 (It isn't allowed for CMP either, but that isn't handled by this
10965 if (inst
.instruction
== T_OPCODE_TST
10966 || inst
.instruction
== T_OPCODE_CMN
10967 || inst
.instruction
== T_OPCODE_NEG
10968 || inst
.instruction
== T_OPCODE_MVN
)
10970 inst
.error
= BAD_ARGS
;
10974 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10979 inst
.error
= _("dest and source1 must be the same register");
10985 if (inst
.instruction
== T_OPCODE_MUL
10987 as_tsktsk (_("Rs and Rd must be different in MUL"));
10989 inst
.instruction
|= Rd
| (Rs
<< 3);
10997 thumb_add_sub (str
, 0);
11004 thumb_shift (str
, THUMB_ASR
);
11011 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11013 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
11014 inst
.reloc
.pc_rel
= 1;
11019 do_t_branch12 (str
)
11022 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11024 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
11025 inst
.reloc
.pc_rel
= 1;
11029 /* Find the real, Thumb encoded start of a Thumb function. */
11032 find_real_start (symbolP
)
11036 const char * name
= S_GET_NAME (symbolP
);
11037 symbolS
* new_target
;
11039 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11040 #define STUB_NAME ".real_start_of"
11045 /* Names that start with '.' are local labels, not function entry points.
11046 The compiler may generate BL instructions to these labels because it
11047 needs to perform a branch to a far away location. */
11048 if (name
[0] == '.')
11051 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
11052 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
11054 new_target
= symbol_find (real_start
);
11056 if (new_target
== NULL
)
11058 as_warn ("Failed to find real start of function: %s\n", name
);
11059 new_target
= symbolP
;
11068 do_t_branch23 (str
)
11071 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11074 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11075 inst
.reloc
.pc_rel
= 1;
11078 /* If the destination of the branch is a defined symbol which does not have
11079 the THUMB_FUNC attribute, then we must be calling a function which has
11080 the (interfacearm) attribute. We look for the Thumb entry point to that
11081 function and change the branch to refer to that function instead. */
11082 if ( inst
.reloc
.exp
.X_op
== O_symbol
11083 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11084 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11085 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11086 inst
.reloc
.exp
.X_add_symbol
=
11087 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11096 skip_whitespace (str
);
11098 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11101 /* This sets THUMB_H2 from the top bit of reg. */
11102 inst
.instruction
|= reg
<< 3;
11104 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11105 should cause the alignment to be checked once it is known. This is
11106 because BX PC only works if the instruction is word aligned. */
11115 thumb_mov_compare (str
, THUMB_COMPARE
);
11125 skip_whitespace (str
);
11127 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11131 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11135 if (skip_past_comma (&str
) == FAIL
11136 || (range
= reg_list (&str
)) == FAIL
)
11139 inst
.error
= BAD_ARGS
;
11143 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11145 /* This really doesn't seem worth it. */
11146 inst
.reloc
.type
= BFD_RELOC_NONE
;
11147 inst
.error
= _("expression too complex");
11153 inst
.error
= _("only lo-regs valid in load/store multiple");
11157 inst
.instruction
|= (Rb
<< 8) | range
;
11165 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11172 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11179 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11188 skip_whitespace (str
);
11190 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11191 || skip_past_comma (&str
) == FAIL
11193 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11194 || skip_past_comma (&str
) == FAIL
11195 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11199 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11203 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11211 thumb_shift (str
, THUMB_LSL
);
11218 thumb_shift (str
, THUMB_LSR
);
11225 thumb_mov_compare (str
, THUMB_MOVE
);
11229 do_t_push_pop (str
)
11234 skip_whitespace (str
);
11236 if ((range
= reg_list (&str
)) == FAIL
)
11239 inst
.error
= BAD_ARGS
;
11243 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11245 /* This really doesn't seem worth it. */
11246 inst
.reloc
.type
= BFD_RELOC_NONE
;
11247 inst
.error
= _("expression too complex");
11253 if ((inst
.instruction
== T_OPCODE_PUSH
11254 && (range
& ~0xff) == 1 << REG_LR
)
11255 || (inst
.instruction
== T_OPCODE_POP
11256 && (range
& ~0xff) == 1 << REG_PC
))
11258 inst
.instruction
|= THUMB_PP_PC_LR
;
11263 inst
.error
= _("invalid register list to push/pop instruction");
11268 inst
.instruction
|= range
;
11276 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11283 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11290 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11297 thumb_add_sub (str
, 1);
11304 skip_whitespace (str
);
11306 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11309 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11319 /* This is a pseudo-op of the form "adr rd, label" to be converted
11320 into a relative address of the form "add rd, pc, #label-.-4". */
11321 skip_whitespace (str
);
11323 /* Store Rd in temporary location inside instruction. */
11324 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11325 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11326 || skip_past_comma (&str
) == FAIL
11327 || my_get_expression (&inst
.reloc
.exp
, &str
))
11330 inst
.error
= BAD_ARGS
;
11334 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11335 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11336 inst
.reloc
.pc_rel
= 1;
11337 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11343 insert_reg (r
, htab
)
11344 const struct reg_entry
*r
;
11345 struct hash_control
*htab
;
11347 int len
= strlen (r
->name
) + 2;
11348 char * buf
= (char *) xmalloc (len
);
11349 char * buf2
= (char *) xmalloc (len
);
11352 #ifdef REGISTER_PREFIX
11353 buf
[i
++] = REGISTER_PREFIX
;
11356 strcpy (buf
+ i
, r
->name
);
11358 for (i
= 0; buf
[i
]; i
++)
11359 buf2
[i
] = TOUPPER (buf
[i
]);
11363 hash_insert (htab
, buf
, (PTR
) r
);
11364 hash_insert (htab
, buf2
, (PTR
) r
);
11368 build_reg_hsh (map
)
11369 struct reg_map
*map
;
11371 const struct reg_entry
*r
;
11373 if ((map
->htab
= hash_new ()) == NULL
)
11374 as_fatal (_("virtual memory exhausted"));
11376 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11377 insert_reg (r
, map
->htab
);
11381 insert_reg_alias (str
, regnum
, htab
)
11384 struct hash_control
*htab
;
11387 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11388 const char *name
= xmalloc (strlen (str
) + 1);
11390 strcpy ((char *) name
, str
);
11393 new->number
= regnum
;
11394 new->builtin
= FALSE
;
11396 error
= hash_insert (htab
, name
, (PTR
) new);
11399 as_bad (_("failed to create an alias for %s, reason: %s"),
11401 free ((char *) name
);
11406 /* Look for the .req directive. This is of the form:
11408 new_register_name .req existing_register_name
11410 If we find one, or if it looks sufficiently like one that we want to
11411 handle any error here, return non-zero. Otherwise return zero. */
11413 create_register_alias (newname
, p
)
11421 skip_whitespace (q
);
11426 if (*q
&& !strncmp (q
, ".req ", 5))
11431 #ifdef IGNORE_OPCODE_CASE
11432 newname
= original_case_string
;
11434 copy_of_str
= newname
;
11437 skip_whitespace (q
);
11439 for (r
= q
; *r
!= '\0'; r
++)
11445 enum arm_reg_type new_type
, old_type
;
11450 old_type
= arm_reg_parse_any (q
);
11453 new_type
= arm_reg_parse_any (newname
);
11455 if (new_type
== REG_TYPE_MAX
)
11457 if (old_type
!= REG_TYPE_MAX
)
11459 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11460 insert_reg_alias (newname
, old_regno
,
11461 all_reg_maps
[old_type
].htab
);
11464 as_warn (_("register '%s' does not exist\n"), q
);
11466 else if (old_type
== REG_TYPE_MAX
)
11468 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11473 /* Do not warn about redefinitions to the same alias. */
11474 if (new_type
!= old_type
11475 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11476 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11477 as_warn (_("ignoring redefinition of register alias '%s'"),
11483 as_warn (_("ignoring incomplete .req pseuso op"));
11494 set_constant_flonums ()
11498 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11499 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11503 /* Iterate over the base tables to create the instruction patterns. */
11505 build_arm_ops_hsh ()
11509 static struct obstack insn_obstack
;
11511 obstack_begin (&insn_obstack
, 4000);
11513 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11515 const struct asm_opcode
*insn
= insns
+ i
;
11517 if (insn
->cond_offset
!= 0)
11519 /* Insn supports conditional execution. Build the varaints
11520 and insert them in the hash table. */
11521 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11523 unsigned len
= strlen (insn
->template);
11524 struct asm_opcode
*new;
11527 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11528 /* All condition codes are two characters. */
11529 template = obstack_alloc (&insn_obstack
, len
+ 3);
11531 strncpy (template, insn
->template, insn
->cond_offset
);
11532 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11533 if (len
> insn
->cond_offset
)
11534 strcpy (template + insn
->cond_offset
+ 2,
11535 insn
->template + insn
->cond_offset
);
11536 new->template = template;
11537 new->cond_offset
= 0;
11538 new->variant
= insn
->variant
;
11539 new->parms
= insn
->parms
;
11540 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11542 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11545 /* Finally, insert the unconditional insn in the table directly;
11546 no need to build a copy. */
11547 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11551 #if 0 /* Suppressed - for now. */
11552 #if defined OBJ_ELF || defined OBJ_COFF
11555 #define arm_Note Elf_External_Note
11559 unsigned char namesz
[4]; /* Size of entry's owner string. */
11560 unsigned char descsz
[4]; /* Size of the note descriptor. */
11561 unsigned char type
[4]; /* Interpretation of the descriptor. */
11562 char name
[1]; /* Start of the name+desc data. */
11566 /* The description is kept to a fix sized in order to make updating
11567 it and merging it easier. */
11568 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11571 arm_add_note (name
, description
, type
)
11573 const char * description
;
11576 arm_Note note ATTRIBUTE_UNUSED
;
11578 unsigned int name_len
;
11580 name_len
= (strlen (name
) + 1 + 3) & ~3;
11582 p
= frag_more (sizeof (note
.namesz
));
11583 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11585 p
= frag_more (sizeof (note
.descsz
));
11586 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11588 p
= frag_more (sizeof (note
.type
));
11589 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11591 p
= frag_more (name_len
);
11594 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11595 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11596 frag_align (2, 0, 0);
11607 if ( (arm_ops_hsh
= hash_new ()) == NULL
11608 || (arm_tops_hsh
= hash_new ()) == NULL
11609 || (arm_cond_hsh
= hash_new ()) == NULL
11610 || (arm_shift_hsh
= hash_new ()) == NULL
11611 || (arm_psr_hsh
= hash_new ()) == NULL
)
11612 as_fatal (_("virtual memory exhausted"));
11614 build_arm_ops_hsh ();
11615 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11616 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11617 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11618 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11619 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11620 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11621 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11622 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11624 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11625 build_reg_hsh (all_reg_maps
+ i
);
11627 set_constant_flonums ();
11629 /* Set the cpu variant based on the command-line options. We prefer
11630 -mcpu= over -march= if both are set (as for GCC); and we prefer
11631 -mfpu= over any other way of setting the floating point unit.
11632 Use of legacy options with new options are faulted. */
11633 if (legacy_cpu
!= -1)
11635 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11636 as_bad (_("use of old and new-style options to set CPU type"));
11638 mcpu_cpu_opt
= legacy_cpu
;
11640 else if (mcpu_cpu_opt
== -1)
11641 mcpu_cpu_opt
= march_cpu_opt
;
11643 if (legacy_fpu
!= -1)
11645 if (mfpu_opt
!= -1)
11646 as_bad (_("use of old and new-style options to set FPU type"));
11648 mfpu_opt
= legacy_fpu
;
11650 else if (mfpu_opt
== -1)
11652 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11653 /* Some environments specify a default FPU. If they don't, infer it
11654 from the processor. */
11655 if (mcpu_fpu_opt
!= -1)
11656 mfpu_opt
= mcpu_fpu_opt
;
11658 mfpu_opt
= march_fpu_opt
;
11660 mfpu_opt
= FPU_DEFAULT
;
11664 if (mfpu_opt
== -1)
11666 if (mcpu_cpu_opt
== -1)
11667 mfpu_opt
= FPU_DEFAULT
;
11668 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11669 mfpu_opt
= FPU_ARCH_VFP_V2
;
11671 mfpu_opt
= FPU_ARCH_FPA
;
11674 if (mcpu_cpu_opt
== -1)
11675 mcpu_cpu_opt
= CPU_DEFAULT
;
11677 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11679 #if defined OBJ_COFF || defined OBJ_ELF
11681 unsigned int flags
= 0;
11683 /* Set the flags in the private structure. */
11684 if (uses_apcs_26
) flags
|= F_APCS26
;
11685 if (support_interwork
) flags
|= F_INTERWORK
;
11686 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11687 if (pic_code
) flags
|= F_PIC
;
11688 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11689 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11691 flags
|= F_SOFT_FLOAT
;
11693 switch (mfloat_abi_opt
)
11695 case ARM_FLOAT_ABI_SOFT
:
11696 case ARM_FLOAT_ABI_SOFTFP
:
11697 flags
|= F_SOFT_FLOAT
;
11700 case ARM_FLOAT_ABI_HARD
:
11701 if (flags
& F_SOFT_FLOAT
)
11702 as_bad (_("hard-float conflicts with specified fpu"));
11705 /* Using VFP conventions (even if soft-float). */
11706 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
11708 #if defined OBJ_ELF
11709 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11710 flags
|= EF_ARM_MAVERICK_FLOAT
;
11713 bfd_set_private_flags (stdoutput
, flags
);
11715 /* We have run out flags in the COFF header to encode the
11716 status of ATPCS support, so instead we create a dummy,
11717 empty, debug section called .arm.atpcs. */
11722 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11726 bfd_set_section_flags
11727 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11728 bfd_set_section_size (stdoutput
, sec
, 0);
11729 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11735 /* Record the CPU type as well. */
11736 switch (cpu_variant
& ARM_CPU_MASK
)
11739 mach
= bfd_mach_arm_2
;
11742 case ARM_3
: /* Also ARM_250. */
11743 mach
= bfd_mach_arm_2a
;
11746 case ARM_6
: /* Also ARM_7. */
11747 mach
= bfd_mach_arm_3
;
11751 mach
= bfd_mach_arm_unknown
;
11755 /* Catch special cases. */
11756 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11757 mach
= bfd_mach_arm_iWMMXt
;
11758 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11759 mach
= bfd_mach_arm_XScale
;
11760 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11761 mach
= bfd_mach_arm_ep9312
;
11762 else if (cpu_variant
& ARM_EXT_V5E
)
11763 mach
= bfd_mach_arm_5TE
;
11764 else if (cpu_variant
& ARM_EXT_V5
)
11766 if (cpu_variant
& ARM_EXT_V4T
)
11767 mach
= bfd_mach_arm_5T
;
11769 mach
= bfd_mach_arm_5
;
11771 else if (cpu_variant
& ARM_EXT_V4
)
11773 if (cpu_variant
& ARM_EXT_V4T
)
11774 mach
= bfd_mach_arm_4T
;
11776 mach
= bfd_mach_arm_4
;
11778 else if (cpu_variant
& ARM_EXT_V3M
)
11779 mach
= bfd_mach_arm_3M
;
11781 #if 0 /* Suppressed - for now. */
11782 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11784 /* Create a .note section to fully identify this arm binary. */
11786 #define NOTE_ARCH_STRING "arch: "
11788 #if defined OBJ_COFF && ! defined NT_VERSION
11789 #define NT_VERSION 1
11794 segT current_seg
= now_seg
;
11795 subsegT current_subseg
= now_subseg
;
11796 asection
* arm_arch
;
11797 const char * arch_string
;
11799 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11802 bfd_set_section_flags (stdoutput
, arm_arch
,
11803 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11804 | SEC_HAS_CONTENTS
);
11806 bfd_set_section_flags (stdoutput
, arm_arch
,
11807 SEC_READONLY
| SEC_HAS_CONTENTS
);
11809 arm_arch
->output_section
= arm_arch
;
11810 subseg_set (arm_arch
, 0);
11815 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11816 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11817 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11818 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11819 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11820 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11821 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11822 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11823 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11824 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11825 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11826 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11827 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11830 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11832 subseg_set (current_seg
, current_subseg
);
11835 #endif /* Suppressed code. */
11837 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11840 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11841 for use in the a.out file, and stores them in the array pointed to by buf.
11842 This knows about the endian-ness of the target machine and does
11843 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11844 2 (short) and 4 (long) Floating numbers are put out as a series of
11845 LITTLENUMS (shorts, here at least). */
11848 md_number_to_chars (buf
, val
, n
)
11853 if (target_big_endian
)
11854 number_to_chars_bigendian (buf
, val
, n
);
11856 number_to_chars_littleendian (buf
, val
, n
);
11860 md_chars_to_number (buf
, n
)
11865 unsigned char * where
= (unsigned char *) buf
;
11867 if (target_big_endian
)
11872 result
|= (*where
++ & 255);
11880 result
|= (where
[n
] & 255);
11887 /* Turn a string in input_line_pointer into a floating point constant
11888 of type TYPE, and store the appropriate bytes in *LITP. The number
11889 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11890 returned, or NULL on OK.
11892 Note that fp constants aren't represent in the normal way on the ARM.
11893 In big endian mode, things are as expected. However, in little endian
11894 mode fp constants are big-endian word-wise, and little-endian byte-wise
11895 within the words. For example, (double) 1.1 in big endian mode is
11896 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11897 the byte sequence 99 99 f1 3f 9a 99 99 99.
11899 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11902 md_atof (type
, litP
, sizeP
)
11908 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11940 return _("bad call to MD_ATOF()");
11943 t
= atof_ieee (input_line_pointer
, type
, words
);
11945 input_line_pointer
= t
;
11948 if (target_big_endian
)
11950 for (i
= 0; i
< prec
; i
++)
11952 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11958 if (cpu_variant
& FPU_ARCH_VFP
)
11959 for (i
= prec
- 1; i
>= 0; i
--)
11961 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11965 /* For a 4 byte float the order of elements in `words' is 1 0.
11966 For an 8 byte float the order is 1 0 3 2. */
11967 for (i
= 0; i
< prec
; i
+= 2)
11969 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11970 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11978 /* The knowledge of the PC's pipeline offset is built into the insns
11982 md_pcrel_from (fixP
)
11986 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11987 && fixP
->fx_subsy
== NULL
)
11990 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11992 /* PC relative addressing on the Thumb is slightly odd
11993 as the bottom two bits of the PC are forced to zero
11994 for the calculation. */
11995 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11999 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12000 so we un-adjust here to compensate for the accommodation. */
12001 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
12003 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
12007 /* Round up a section size to the appropriate boundary. */
12010 md_section_align (segment
, size
)
12011 segT segment ATTRIBUTE_UNUSED
;
12017 /* Round all sects to multiple of 4. */
12018 return (size
+ 3) & ~3;
12022 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12023 Otherwise we have no need to default values of symbols. */
12026 md_undefined_symbol (name
)
12027 char * name ATTRIBUTE_UNUSED
;
12030 if (name
[0] == '_' && name
[1] == 'G'
12031 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
12035 if (symbol_find (name
))
12036 as_bad ("GOT already in the symbol table");
12038 GOT_symbol
= symbol_new (name
, undefined_section
,
12039 (valueT
) 0, & zero_address_frag
);
12049 /* arm_reg_parse () := if it looks like a register, return its token and
12050 advance the pointer. */
12053 arm_reg_parse (ccp
, htab
)
12054 register char ** ccp
;
12055 struct hash_control
*htab
;
12057 char * start
= * ccp
;
12060 struct reg_entry
* reg
;
12062 #ifdef REGISTER_PREFIX
12063 if (*start
!= REGISTER_PREFIX
)
12068 #ifdef OPTIONAL_REGISTER_PREFIX
12069 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12073 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12077 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12081 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12087 return reg
->number
;
12093 /* Search for the following register name in each of the possible reg name
12094 tables. Return the classification if found, or REG_TYPE_MAX if not
12096 static enum arm_reg_type
12097 arm_reg_parse_any (cp
)
12102 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12103 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12104 return (enum arm_reg_type
) i
;
12106 return REG_TYPE_MAX
;
12110 md_apply_fix3 (fixP
, valP
, seg
)
12115 offsetT value
= * valP
;
12117 unsigned int newimm
;
12118 unsigned long temp
;
12120 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12121 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12123 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12125 /* Note whether this will delete the relocation. */
12127 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12128 doesn't work fully.) */
12129 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12130 && !fixP
->fx_pcrel
)
12132 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12136 /* If this symbol is in a different section then we need to leave it for
12137 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12138 so we have to undo it's effects here. */
12139 if (fixP
->fx_pcrel
)
12141 if (fixP
->fx_addsy
!= NULL
12142 && S_IS_DEFINED (fixP
->fx_addsy
)
12143 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12146 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12147 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12151 value
+= md_pcrel_from (fixP
);
12155 /* Remember value for emit_reloc. */
12156 fixP
->fx_addnumber
= value
;
12158 switch (fixP
->fx_r_type
)
12160 case BFD_RELOC_ARM_IMMEDIATE
:
12161 newimm
= validate_immediate (value
);
12162 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12164 /* If the instruction will fail, see if we can fix things up by
12165 changing the opcode. */
12166 if (newimm
== (unsigned int) FAIL
12167 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12169 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12170 _("invalid constant (%lx) after fixup"),
12171 (unsigned long) value
);
12175 newimm
|= (temp
& 0xfffff000);
12176 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12180 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12182 unsigned int highpart
= 0;
12183 unsigned int newinsn
= 0xe1a00000; /* nop. */
12185 newimm
= validate_immediate (value
);
12186 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12188 /* If the instruction will fail, see if we can fix things up by
12189 changing the opcode. */
12190 if (newimm
== (unsigned int) FAIL
12191 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12193 /* No ? OK - try using two ADD instructions to generate
12195 newimm
= validate_immediate_twopart (value
, & highpart
);
12197 /* Yes - then make sure that the second instruction is
12199 if (newimm
!= (unsigned int) FAIL
)
12201 /* Still No ? Try using a negated value. */
12202 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12203 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12204 /* Otherwise - give up. */
12207 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12208 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12213 /* Replace the first operand in the 2nd instruction (which
12214 is the PC) with the destination register. We have
12215 already added in the PC in the first instruction and we
12216 do not want to do it again. */
12217 newinsn
&= ~ 0xf0000;
12218 newinsn
|= ((newinsn
& 0x0f000) << 4);
12221 newimm
|= (temp
& 0xfffff000);
12222 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12224 highpart
|= (newinsn
& 0xfffff000);
12225 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12229 case BFD_RELOC_ARM_OFFSET_IMM
:
12235 if (validate_offset_imm (value
, 0) == FAIL
)
12237 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12238 _("bad immediate value for offset (%ld)"),
12243 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12244 newval
&= 0xff7ff000;
12245 newval
|= value
| (sign
? INDEX_UP
: 0);
12246 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12249 case BFD_RELOC_ARM_OFFSET_IMM8
:
12250 case BFD_RELOC_ARM_HWLITERAL
:
12256 if (validate_offset_imm (value
, 1) == FAIL
)
12258 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12259 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12260 _("invalid literal constant: pool needs to be closer"));
12262 as_bad (_("bad immediate value for half-word offset (%ld)"),
12267 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12268 newval
&= 0xff7ff0f0;
12269 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12270 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12273 case BFD_RELOC_ARM_LITERAL
:
12279 if (validate_offset_imm (value
, 0) == FAIL
)
12281 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12282 _("invalid literal constant: pool needs to be closer"));
12286 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12287 newval
&= 0xff7ff000;
12288 newval
|= value
| (sign
? INDEX_UP
: 0);
12289 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12292 case BFD_RELOC_ARM_SHIFT_IMM
:
12293 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12294 if (((unsigned long) value
) > 32
12296 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12298 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12299 _("shift expression is too large"));
12304 /* Shifts of zero must be done as lsl. */
12306 else if (value
== 32)
12308 newval
&= 0xfffff07f;
12309 newval
|= (value
& 0x1f) << 7;
12310 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12313 case BFD_RELOC_ARM_SWI
:
12314 if (arm_data
->thumb_mode
)
12316 if (((unsigned long) value
) > 0xff)
12317 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12318 _("invalid swi expression"));
12319 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12321 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12325 if (((unsigned long) value
) > 0x00ffffff)
12326 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12327 _("invalid swi expression"));
12328 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12330 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12334 case BFD_RELOC_ARM_MULTI
:
12335 if (((unsigned long) value
) > 0xffff)
12336 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12337 _("invalid expression in load/store multiple"));
12338 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12339 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12342 case BFD_RELOC_ARM_PCREL_BRANCH
:
12343 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12345 /* Sign-extend a 24-bit number. */
12346 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12350 value
= fixP
->fx_offset
;
12353 /* We are going to store value (shifted right by two) in the
12354 instruction, in a 24 bit, signed field. Thus we need to check
12355 that none of the top 8 bits of the shifted value (top 7 bits of
12356 the unshifted, unsigned value) are set, or that they are all set. */
12357 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12358 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12361 /* Normally we would be stuck at this point, since we cannot store
12362 the absolute address that is the destination of the branch in the
12363 24 bits of the branch instruction. If however, we happen to know
12364 that the destination of the branch is in the same section as the
12365 branch instruction itself, then we can compute the relocation for
12366 ourselves and not have to bother the linker with it.
12368 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12369 because I have not worked out how to do this for OBJ_COFF or
12372 && fixP
->fx_addsy
!= NULL
12373 && S_IS_DEFINED (fixP
->fx_addsy
)
12374 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12376 /* Get pc relative value to go into the branch. */
12379 /* Permit a backward branch provided that enough bits
12380 are set. Allow a forwards branch, provided that
12381 enough bits are clear. */
12382 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12383 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12387 if (! fixP
->fx_done
)
12389 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12390 _("GAS can't handle same-section branch dest >= 0x04000000"));
12394 value
+= SEXT24 (newval
);
12396 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12397 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12398 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12399 _("out of range branch"));
12401 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12402 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12405 case BFD_RELOC_ARM_PCREL_BLX
:
12408 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12412 value
= fixP
->fx_offset
;
12414 hbit
= (value
>> 1) & 1;
12415 value
= (value
>> 2) & 0x00ffffff;
12416 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12417 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12418 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12422 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12423 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12425 addressT diff
= (newval
& 0xff) << 1;
12430 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12431 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12432 _("branch out of range"));
12433 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12435 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12438 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12439 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12441 addressT diff
= (newval
& 0x7ff) << 1;
12446 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12447 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12448 _("branch out of range"));
12449 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12451 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12454 case BFD_RELOC_THUMB_PCREL_BLX
:
12455 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12460 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12461 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12462 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12463 if (diff
& 0x400000)
12466 value
= fixP
->fx_offset
;
12470 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12471 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12472 _("branch with link out of range"));
12474 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12475 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12476 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12477 /* For a BLX instruction, make sure that the relocation is rounded up
12478 to a word boundary. This follows the semantics of the instruction
12479 which specifies that bit 1 of the target address will come from bit
12480 1 of the base address. */
12481 newval2
= (newval2
+ 1) & ~ 1;
12482 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12483 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12488 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12489 md_number_to_chars (buf
, value
, 1);
12491 else if (!target_oabi
)
12493 value
= fixP
->fx_offset
;
12494 md_number_to_chars (buf
, value
, 1);
12500 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12501 md_number_to_chars (buf
, value
, 2);
12503 else if (!target_oabi
)
12505 value
= fixP
->fx_offset
;
12506 md_number_to_chars (buf
, value
, 2);
12512 case BFD_RELOC_ARM_GOT32
:
12513 case BFD_RELOC_ARM_GOTOFF
:
12514 md_number_to_chars (buf
, 0, 4);
12518 case BFD_RELOC_RVA
:
12520 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12521 md_number_to_chars (buf
, value
, 4);
12523 else if (!target_oabi
)
12525 value
= fixP
->fx_offset
;
12526 md_number_to_chars (buf
, value
, 4);
12532 case BFD_RELOC_ARM_PLT32
:
12533 /* It appears the instruction is fully prepared at this point. */
12537 case BFD_RELOC_ARM_CP_OFF_IMM
:
12539 if (value
< -1023 || value
> 1023 || (value
& 3))
12540 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12541 _("illegal value for co-processor offset"));
12544 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12545 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12546 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12549 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12551 if (value
< -255 || value
> 255)
12552 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12553 _("Illegal value for co-processor offset"));
12556 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12557 newval
|= value
| (sign
? INDEX_UP
: 0);
12558 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12561 case BFD_RELOC_ARM_THUMB_OFFSET
:
12562 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12563 /* Exactly what ranges, and where the offset is inserted depends
12564 on the type of instruction, we can establish this from the
12566 switch (newval
>> 12)
12568 case 4: /* PC load. */
12569 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12570 forced to zero for these loads, so we will need to round
12571 up the offset if the instruction address is not word
12572 aligned (since the final address produced must be, and
12573 we can only describe word-aligned immediate offsets). */
12575 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12576 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12577 _("invalid offset, target not word aligned (0x%08X)"),
12578 (unsigned int) (fixP
->fx_frag
->fr_address
12579 + fixP
->fx_where
+ value
));
12581 if ((value
+ 2) & ~0x3fe)
12582 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12583 _("invalid offset, value too big (0x%08lX)"),
12586 /* Round up, since pc will be rounded down. */
12587 newval
|= (value
+ 2) >> 2;
12590 case 9: /* SP load/store. */
12591 if (value
& ~0x3fc)
12592 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12593 _("invalid offset, value too big (0x%08lX)"),
12595 newval
|= value
>> 2;
12598 case 6: /* Word load/store. */
12600 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12601 _("invalid offset, value too big (0x%08lX)"),
12603 newval
|= value
<< 4; /* 6 - 2. */
12606 case 7: /* Byte load/store. */
12608 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12609 _("invalid offset, value too big (0x%08lX)"),
12611 newval
|= value
<< 6;
12614 case 8: /* Halfword load/store. */
12616 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12617 _("invalid offset, value too big (0x%08lX)"),
12619 newval
|= value
<< 5; /* 6 - 1. */
12623 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12624 "Unable to process relocation for thumb opcode: %lx",
12625 (unsigned long) newval
);
12628 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12631 case BFD_RELOC_ARM_THUMB_ADD
:
12632 /* This is a complicated relocation, since we use it for all of
12633 the following immediate relocations:
12637 9bit ADD/SUB SP word-aligned
12638 10bit ADD PC/SP word-aligned
12640 The type of instruction being processed is encoded in the
12647 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12649 int rd
= (newval
>> 4) & 0xf;
12650 int rs
= newval
& 0xf;
12651 int subtract
= newval
& 0x8000;
12655 if (value
& ~0x1fc)
12656 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12657 _("invalid immediate for stack address calculation"));
12658 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12659 newval
|= value
>> 2;
12661 else if (rs
== REG_PC
|| rs
== REG_SP
)
12665 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12666 _("invalid immediate for address calculation (value = 0x%08lX)"),
12667 (unsigned long) value
);
12668 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12670 newval
|= value
>> 2;
12675 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12676 _("invalid 8bit immediate"));
12677 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12678 newval
|= (rd
<< 8) | value
;
12683 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12684 _("invalid 3bit immediate"));
12685 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12686 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12689 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12692 case BFD_RELOC_ARM_THUMB_IMM
:
12693 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12694 switch (newval
>> 11)
12696 case 0x04: /* 8bit immediate MOV. */
12697 case 0x05: /* 8bit immediate CMP. */
12698 if (value
< 0 || value
> 255)
12699 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12700 _("invalid immediate: %ld is too large"),
12708 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12711 case BFD_RELOC_ARM_THUMB_SHIFT
:
12712 /* 5bit shift value (0..31). */
12713 if (value
< 0 || value
> 31)
12714 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12715 _("illegal Thumb shift value: %ld"), (long) value
);
12716 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12717 newval
|= value
<< 6;
12718 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12721 case BFD_RELOC_VTABLE_INHERIT
:
12722 case BFD_RELOC_VTABLE_ENTRY
:
12726 case BFD_RELOC_NONE
:
12728 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12729 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12733 /* Translate internal representation of relocation info to BFD target
12737 tc_gen_reloc (section
, fixp
)
12738 asection
* section ATTRIBUTE_UNUSED
;
12742 bfd_reloc_code_real_type code
;
12744 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12746 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12747 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12748 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12750 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12752 if (fixp
->fx_pcrel
== 0)
12753 reloc
->addend
= fixp
->fx_offset
;
12755 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12756 #else /* OBJ_ELF */
12757 reloc
->addend
= fixp
->fx_offset
;
12760 switch (fixp
->fx_r_type
)
12763 if (fixp
->fx_pcrel
)
12765 code
= BFD_RELOC_8_PCREL
;
12770 if (fixp
->fx_pcrel
)
12772 code
= BFD_RELOC_16_PCREL
;
12777 if (fixp
->fx_pcrel
)
12779 code
= BFD_RELOC_32_PCREL
;
12783 case BFD_RELOC_ARM_PCREL_BRANCH
:
12784 case BFD_RELOC_ARM_PCREL_BLX
:
12785 case BFD_RELOC_RVA
:
12786 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12787 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12788 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12789 case BFD_RELOC_THUMB_PCREL_BLX
:
12790 case BFD_RELOC_VTABLE_ENTRY
:
12791 case BFD_RELOC_VTABLE_INHERIT
:
12792 code
= fixp
->fx_r_type
;
12795 case BFD_RELOC_ARM_LITERAL
:
12796 case BFD_RELOC_ARM_HWLITERAL
:
12797 /* If this is called then the a literal has
12798 been referenced across a section boundary. */
12799 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12800 _("literal referenced across section boundary"));
12804 case BFD_RELOC_ARM_GOT32
:
12805 case BFD_RELOC_ARM_GOTOFF
:
12806 case BFD_RELOC_ARM_PLT32
:
12807 code
= fixp
->fx_r_type
;
12811 case BFD_RELOC_ARM_IMMEDIATE
:
12812 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12813 _("internal relocation (type: IMMEDIATE) not fixed up"));
12816 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12817 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12818 _("ADRL used for a symbol not defined in the same file"));
12821 case BFD_RELOC_ARM_OFFSET_IMM
:
12822 if (fixp
->fx_addsy
!= NULL
12823 && !S_IS_DEFINED (fixp
->fx_addsy
)
12824 && S_IS_LOCAL (fixp
->fx_addsy
))
12826 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12827 _("undefined local label `%s'"),
12828 S_GET_NAME (fixp
->fx_addsy
));
12832 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12833 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12840 switch (fixp
->fx_r_type
)
12842 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12843 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12844 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12845 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12846 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12847 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12848 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12849 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12850 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12851 default: type
= _("<unknown>"); break;
12853 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12854 _("cannot represent %s relocation in this object file format"),
12861 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12863 && fixp
->fx_addsy
== GOT_symbol
)
12865 code
= BFD_RELOC_ARM_GOTPC
;
12866 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12870 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12872 if (reloc
->howto
== NULL
)
12874 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12875 _("cannot represent %s relocation in this object file format"),
12876 bfd_get_reloc_code_name (code
));
12880 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12881 vtable entry to be used in the relocation's section offset. */
12882 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12883 reloc
->address
= fixp
->fx_offset
;
12889 md_estimate_size_before_relax (fragP
, segtype
)
12890 fragS
* fragP ATTRIBUTE_UNUSED
;
12891 segT segtype ATTRIBUTE_UNUSED
;
12893 as_fatal (_("md_estimate_size_before_relax\n"));
12905 as_bad ("%s -- `%s'", inst
.error
, str
);
12909 to
= frag_more (inst
.size
);
12911 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12913 assert (inst
.size
== (2 * THUMB_SIZE
));
12914 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12915 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12917 else if (inst
.size
> INSN_SIZE
)
12919 assert (inst
.size
== (2 * INSN_SIZE
));
12920 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12921 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12924 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12926 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12927 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12928 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12932 dwarf2_emit_insn (inst
.size
);
12944 /* Align the instruction.
12945 This may not be the right thing to do but ... */
12950 /* Align the previous label if needed. */
12951 if (last_label_seen
!= NULL
)
12953 symbol_set_frag (last_label_seen
, frag_now
);
12954 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12955 S_SET_SEGMENT (last_label_seen
, now_seg
);
12958 memset (&inst
, '\0', sizeof (inst
));
12959 inst
.reloc
.type
= BFD_RELOC_NONE
;
12961 skip_whitespace (str
);
12963 /* Scan up to the end of the op-code, which must end in white space or
12965 for (start
= p
= str
; *p
!= '\0'; p
++)
12971 as_bad (_("no operator -- statement `%s'\n"), str
);
12977 const struct thumb_opcode
* opcode
;
12981 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12986 /* Check that this instruction is supported for this CPU. */
12987 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12989 as_bad (_("selected processor does not support `%s'"), str
);
12993 mapping_state (MAP_THUMB
);
12994 inst
.instruction
= opcode
->value
;
12995 inst
.size
= opcode
->size
;
12996 (*opcode
->parms
) (p
);
13003 const struct asm_opcode
* opcode
;
13007 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
13012 /* Check that this instruction is supported for this CPU. */
13013 if ((opcode
->variant
& cpu_variant
) == 0)
13015 as_bad (_("selected processor does not support `%s'"), str
);
13019 mapping_state (MAP_ARM
);
13020 inst
.instruction
= opcode
->value
;
13021 inst
.size
= INSN_SIZE
;
13022 (*opcode
->parms
) (p
);
13028 /* It wasn't an instruction, but it might be a register alias of the form
13030 if (create_register_alias (str
, p
))
13033 as_bad (_("bad instruction `%s'"), start
);
13037 Invocation line includes a switch not recognized by the base assembler.
13038 See if it's a processor-specific option.
13040 This routine is somewhat complicated by the need for backwards
13041 compatibility (since older releases of gcc can't be changed).
13042 The new options try to make the interface as compatible as
13045 New options (supported) are:
13047 -mcpu=<cpu name> Assemble for selected processor
13048 -march=<architecture name> Assemble for selected architecture
13049 -mfpu=<fpu architecture> Assemble for selected FPU.
13050 -EB/-mbig-endian Big-endian
13051 -EL/-mlittle-endian Little-endian
13052 -k Generate PIC code
13053 -mthumb Start in Thumb mode
13054 -mthumb-interwork Code supports ARM/Thumb interworking
13056 For now we will also provide support for:
13058 -mapcs-32 32-bit Program counter
13059 -mapcs-26 26-bit Program counter
13060 -macps-float Floats passed in FP registers
13061 -mapcs-reentrant Reentrant code
13063 (sometime these will probably be replaced with -mapcs=<list of options>
13064 and -matpcs=<list of options>)
13066 The remaining options are only supported for back-wards compatibility.
13067 Cpu variants, the arm part is optional:
13068 -m[arm]1 Currently not supported.
13069 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13070 -m[arm]3 Arm 3 processor
13071 -m[arm]6[xx], Arm 6 processors
13072 -m[arm]7[xx][t][[d]m] Arm 7 processors
13073 -m[arm]8[10] Arm 8 processors
13074 -m[arm]9[20][tdmi] Arm 9 processors
13075 -mstrongarm[110[0]] StrongARM processors
13076 -mxscale XScale processors
13077 -m[arm]v[2345[t[e]]] Arm architectures
13078 -mall All (except the ARM1)
13080 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13081 -mfpe-old (No float load/store multiples)
13082 -mvfpxd VFP Single precision
13084 -mno-fpu Disable all floating point instructions
13086 The following CPU names are recognized:
13087 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13088 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13089 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13090 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13091 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13092 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13093 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13097 const char * md_shortopts
= "m:k";
13099 #ifdef ARM_BI_ENDIAN
13100 #define OPTION_EB (OPTION_MD_BASE + 0)
13101 #define OPTION_EL (OPTION_MD_BASE + 1)
13103 #if TARGET_BYTES_BIG_ENDIAN
13104 #define OPTION_EB (OPTION_MD_BASE + 0)
13106 #define OPTION_EL (OPTION_MD_BASE + 1)
13110 struct option md_longopts
[] =
13113 {"EB", no_argument
, NULL
, OPTION_EB
},
13116 {"EL", no_argument
, NULL
, OPTION_EL
},
13118 {NULL
, no_argument
, NULL
, 0}
13121 size_t md_longopts_size
= sizeof (md_longopts
);
13123 struct arm_option_table
13125 char *option
; /* Option name to match. */
13126 char *help
; /* Help information. */
13127 int *var
; /* Variable to change. */
13128 int value
; /* What to change it to. */
13129 char *deprecated
; /* If non-null, print this message. */
13132 struct arm_option_table arm_opts
[] =
13134 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13135 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13136 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13137 &support_interwork
, 1, NULL
},
13138 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13139 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13140 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13141 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13143 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13144 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13145 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13146 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13149 /* These are recognized by the assembler, but have no affect on code. */
13150 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13151 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13153 /* DON'T add any new processors to this list -- we want the whole list
13154 to go away... Add them to the processors table instead. */
13155 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13156 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13157 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13158 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13159 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13160 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13161 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13162 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13163 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13164 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13165 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13166 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13167 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13168 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13169 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13170 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13171 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13172 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13173 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13174 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13175 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13176 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13177 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13178 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13179 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13180 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13181 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13182 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13183 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13184 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13185 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13186 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13187 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13188 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13189 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13190 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13191 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13192 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13193 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13194 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13195 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13196 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13197 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13198 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13199 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13200 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13201 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13202 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13203 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13204 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13205 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13206 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13207 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13208 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13209 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13210 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13211 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13212 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13213 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13214 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13215 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13216 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13217 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13218 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13219 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13220 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13221 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13222 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13223 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13224 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13225 N_("use -mcpu=strongarm110")},
13226 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13227 N_("use -mcpu=strongarm1100")},
13228 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13229 N_("use -mcpu=strongarm1110")},
13230 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13231 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13232 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13234 /* Architecture variants -- don't add any more to this list either. */
13235 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13236 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13237 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13238 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13239 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13240 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13241 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13242 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13243 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13244 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13245 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13246 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13247 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13248 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13249 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13250 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13251 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13252 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13254 /* Floating point variants -- don't add any more to this list either. */
13255 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13256 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13257 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13258 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13259 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13261 {NULL
, NULL
, NULL
, 0, NULL
}
13264 struct arm_cpu_option_table
13268 /* For some CPUs we assume an FPU unless the user explicitly sets
13273 /* This list should, at a minimum, contain all the cpu names
13274 recognized by GCC. */
13275 static struct arm_cpu_option_table arm_cpus
[] =
13277 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13278 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13279 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13280 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13281 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13282 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13283 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13284 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13285 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13286 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13287 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13288 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13289 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13290 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13291 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13292 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13293 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13294 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13295 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13296 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13297 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13298 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13299 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13300 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13301 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13302 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13303 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13304 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13305 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13306 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13307 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13308 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13309 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13310 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13311 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13312 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13313 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13314 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13315 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13316 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13317 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13318 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13319 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13320 /* For V5 or later processors we default to using VFP; but the user
13321 should really set the FPU type explicitly. */
13322 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13323 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13324 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13325 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13326 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13327 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13328 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13329 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13330 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13331 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13332 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13333 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13334 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13335 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13336 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13337 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13338 /* ??? XSCALE is really an architecture. */
13339 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13340 /* ??? iwmmxt is not a processor. */
13341 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13342 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13344 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13348 struct arm_arch_option_table
13355 /* This list should, at a minimum, contain all the architecture names
13356 recognized by GCC. */
13357 static struct arm_arch_option_table arm_archs
[] =
13359 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13360 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13361 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13362 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13363 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13364 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13365 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13366 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13367 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13368 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13369 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13370 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13371 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13372 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13373 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13374 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13375 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13376 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13377 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13378 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13379 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13383 /* ISA extensions in the co-processor space. */
13384 struct arm_arch_extension_table
13390 static struct arm_arch_extension_table arm_extensions
[] =
13392 {"maverick", ARM_CEXT_MAVERICK
},
13393 {"xscale", ARM_CEXT_XSCALE
},
13394 {"iwmmxt", ARM_CEXT_IWMMXT
},
13398 struct arm_fpu_option_table
13404 /* This list should, at a minimum, contain all the fpu names
13405 recognized by GCC. */
13406 static struct arm_fpu_option_table arm_fpus
[] =
13408 {"softfpa", FPU_NONE
},
13409 {"fpe", FPU_ARCH_FPE
},
13410 {"fpe2", FPU_ARCH_FPE
},
13411 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13412 {"fpa", FPU_ARCH_FPA
},
13413 {"fpa10", FPU_ARCH_FPA
},
13414 {"fpa11", FPU_ARCH_FPA
},
13415 {"arm7500fe", FPU_ARCH_FPA
},
13416 {"softvfp", FPU_ARCH_VFP
},
13417 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13418 {"vfp", FPU_ARCH_VFP_V2
},
13419 {"vfp9", FPU_ARCH_VFP_V2
},
13420 {"vfp10", FPU_ARCH_VFP_V2
},
13421 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13422 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13423 {"arm1020t", FPU_ARCH_VFP_V1
},
13424 {"arm1020e", FPU_ARCH_VFP_V2
},
13425 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13426 {"maverick", FPU_ARCH_MAVERICK
},
13430 struct arm_float_abi_option_table
13436 static struct arm_float_abi_option_table arm_float_abis
[] =
13438 {"hard", ARM_FLOAT_ABI_HARD
},
13439 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13440 {"soft", ARM_FLOAT_ABI_SOFT
},
13444 struct arm_long_option_table
13446 char *option
; /* Substring to match. */
13447 char *help
; /* Help information. */
13448 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13449 char *deprecated
; /* If non-null, print this message. */
13453 arm_parse_extension (str
, opt_p
)
13457 while (str
!= NULL
&& *str
!= 0)
13459 struct arm_arch_extension_table
*opt
;
13465 as_bad (_("invalid architectural extension"));
13470 ext
= strchr (str
, '+');
13473 optlen
= ext
- str
;
13475 optlen
= strlen (str
);
13479 as_bad (_("missing architectural extension"));
13483 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13484 if (strncmp (opt
->name
, str
, optlen
) == 0)
13486 *opt_p
|= opt
->value
;
13490 if (opt
->name
== NULL
)
13492 as_bad (_("unknown architectural extnsion `%s'"), str
);
13503 arm_parse_cpu (str
)
13506 struct arm_cpu_option_table
*opt
;
13507 char *ext
= strchr (str
, '+');
13511 optlen
= ext
- str
;
13513 optlen
= strlen (str
);
13517 as_bad (_("missing cpu name `%s'"), str
);
13521 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13522 if (strncmp (opt
->name
, str
, optlen
) == 0)
13524 mcpu_cpu_opt
= opt
->value
;
13525 mcpu_fpu_opt
= opt
->default_fpu
;
13528 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13533 as_bad (_("unknown cpu `%s'"), str
);
13538 arm_parse_arch (str
)
13541 struct arm_arch_option_table
*opt
;
13542 char *ext
= strchr (str
, '+');
13546 optlen
= ext
- str
;
13548 optlen
= strlen (str
);
13552 as_bad (_("missing architecture name `%s'"), str
);
13557 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13558 if (strcmp (opt
->name
, str
) == 0)
13560 march_cpu_opt
= opt
->value
;
13561 march_fpu_opt
= opt
->default_fpu
;
13564 return arm_parse_extension (ext
, &march_cpu_opt
);
13569 as_bad (_("unknown architecture `%s'\n"), str
);
13574 arm_parse_fpu (str
)
13577 struct arm_fpu_option_table
*opt
;
13579 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13580 if (strcmp (opt
->name
, str
) == 0)
13582 mfpu_opt
= opt
->value
;
13586 as_bad (_("unknown floating point format `%s'\n"), str
);
13591 arm_parse_float_abi (str
)
13594 struct arm_float_abi_option_table
*opt
;
13596 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13597 if (strcmp (opt
->name
, str
) == 0)
13599 mfloat_abi_opt
= opt
->value
;
13603 as_bad (_("unknown floating point abi `%s'\n"), str
);
13607 struct arm_long_option_table arm_long_opts
[] =
13609 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13610 arm_parse_cpu
, NULL
},
13611 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13612 arm_parse_arch
, NULL
},
13613 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13614 arm_parse_fpu
, NULL
},
13615 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13616 arm_parse_float_abi
, NULL
},
13617 {NULL
, NULL
, 0, NULL
}
13621 md_parse_option (c
, arg
)
13625 struct arm_option_table
*opt
;
13626 struct arm_long_option_table
*lopt
;
13632 target_big_endian
= 1;
13638 target_big_endian
= 0;
13643 /* Listing option. Just ignore these, we don't support additional
13648 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13650 if (c
== opt
->option
[0]
13651 && ((arg
== NULL
&& opt
->option
[1] == 0)
13652 || strcmp (arg
, opt
->option
+ 1) == 0))
13654 #if WARN_DEPRECATED
13655 /* If the option is deprecated, tell the user. */
13656 if (opt
->deprecated
!= NULL
)
13657 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13658 arg
? arg
: "", _(opt
->deprecated
));
13661 if (opt
->var
!= NULL
)
13662 *opt
->var
= opt
->value
;
13668 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13670 /* These options are expected to have an argument. */
13671 if (c
== lopt
->option
[0]
13673 && strncmp (arg
, lopt
->option
+ 1,
13674 strlen (lopt
->option
+ 1)) == 0)
13676 #if WARN_DEPRECATED
13677 /* If the option is deprecated, tell the user. */
13678 if (lopt
->deprecated
!= NULL
)
13679 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13680 _(lopt
->deprecated
));
13683 /* Call the sup-option parser. */
13684 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13688 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
13699 struct arm_option_table
*opt
;
13700 struct arm_long_option_table
*lopt
;
13702 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13704 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13705 if (opt
->help
!= NULL
)
13706 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13708 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13709 if (lopt
->help
!= NULL
)
13710 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13714 -EB assemble code for a big-endian cpu\n"));
13719 -EL assemble code for a little-endian cpu\n"));
13723 /* We need to be able to fix up arbitrary expressions in some statements.
13724 This is so that we can handle symbols that are an arbitrary distance from
13725 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13726 which returns part of an address in a form which will be valid for
13727 a data instruction. We do this by pushing the expression into a symbol
13728 in the expr_section, and creating a fix for that. */
13731 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13740 arm_fix_data
* arm_data
;
13748 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13752 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13757 /* Mark whether the fix is to a THUMB instruction, or an ARM
13759 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13760 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13761 arm_data
->thumb_mode
= thumb_mode
;
13764 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13767 cons_fix_new_arm (frag
, where
, size
, exp
)
13773 bfd_reloc_code_real_type type
;
13777 FIXME: @@ Should look at CPU word size. */
13781 type
= BFD_RELOC_8
;
13784 type
= BFD_RELOC_16
;
13788 type
= BFD_RELOC_32
;
13791 type
= BFD_RELOC_64
;
13795 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13798 /* A good place to do this, although this was probably not intended
13799 for this kind of use. We need to dump the literal pool before
13800 references are made to a null symbol pointer. */
13805 literal_pool
* pool
;
13807 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13809 /* Put it at the end of the relevent section. */
13810 subseg_set (pool
->section
, pool
->sub_section
);
13812 arm_elf_change_section ();
13819 arm_start_line_hook ()
13821 last_label_seen
= NULL
;
13825 arm_frob_label (sym
)
13828 last_label_seen
= sym
;
13830 ARM_SET_THUMB (sym
, thumb_mode
);
13832 #if defined OBJ_COFF || defined OBJ_ELF
13833 ARM_SET_INTERWORK (sym
, support_interwork
);
13836 /* Note - do not allow local symbols (.Lxxx) to be labeled
13837 as Thumb functions. This is because these labels, whilst
13838 they exist inside Thumb code, are not the entry points for
13839 possible ARM->Thumb calls. Also, these labels can be used
13840 as part of a computed goto or switch statement. eg gcc
13841 can generate code that looks like this:
13843 ldr r2, [pc, .Laaa]
13853 The first instruction loads the address of the jump table.
13854 The second instruction converts a table index into a byte offset.
13855 The third instruction gets the jump address out of the table.
13856 The fourth instruction performs the jump.
13858 If the address stored at .Laaa is that of a symbol which has the
13859 Thumb_Func bit set, then the linker will arrange for this address
13860 to have the bottom bit set, which in turn would mean that the
13861 address computation performed by the third instruction would end
13862 up with the bottom bit set. Since the ARM is capable of unaligned
13863 word loads, the instruction would then load the incorrect address
13864 out of the jump table, and chaos would ensue. */
13865 if (label_is_thumb_function_name
13866 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13867 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13869 /* When the address of a Thumb function is taken the bottom
13870 bit of that address should be set. This will allow
13871 interworking between Arm and Thumb functions to work
13874 THUMB_SET_FUNC (sym
, 1);
13876 label_is_thumb_function_name
= FALSE
;
13880 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13884 arm_adjust_symtab ()
13889 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13891 if (ARM_IS_THUMB (sym
))
13893 if (THUMB_IS_FUNC (sym
))
13895 /* Mark the symbol as a Thumb function. */
13896 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13897 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13898 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13900 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13901 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13903 as_bad (_("%s: unexpected function type: %d"),
13904 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13906 else switch (S_GET_STORAGE_CLASS (sym
))
13909 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13912 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13915 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13923 if (ARM_IS_INTERWORK (sym
))
13924 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13931 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13933 if (ARM_IS_THUMB (sym
))
13935 elf_symbol_type
* elf_sym
;
13937 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13938 bind
= ELF_ST_BIND (elf_sym
);
13940 /* If it's a .thumb_func, declare it as so,
13941 otherwise tag label as .code 16. */
13942 if (THUMB_IS_FUNC (sym
))
13943 elf_sym
->internal_elf_sym
.st_info
=
13944 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13946 elf_sym
->internal_elf_sym
.st_info
=
13947 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13954 arm_data_in_code ()
13956 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13958 *input_line_pointer
= '/';
13959 input_line_pointer
+= 5;
13960 *input_line_pointer
= 0;
13968 arm_canonicalize_symbol_name (name
)
13973 if (thumb_mode
&& (len
= strlen (name
)) > 5
13974 && streq (name
+ len
- 5, "/data"))
13975 *(name
+ len
- 5) = 0;
13980 #if defined OBJ_COFF || defined OBJ_ELF
13982 arm_validate_fix (fixP
)
13985 /* If the destination of the branch is a defined symbol which does not have
13986 the THUMB_FUNC attribute, then we must be calling a function which has
13987 the (interfacearm) attribute. We look for the Thumb entry point to that
13988 function and change the branch to refer to that function instead. */
13989 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13990 && fixP
->fx_addsy
!= NULL
13991 && S_IS_DEFINED (fixP
->fx_addsy
)
13992 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13994 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
14000 arm_force_relocation (fixp
)
14003 #if defined (OBJ_COFF) && defined (TE_PE)
14004 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
14008 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
14009 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
14010 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
14011 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
14015 /* Resolve these relocations even if the symbol is extern or weak. */
14016 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
14017 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
14018 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14021 return generic_force_reloc (fixp
);
14025 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14026 local labels from being added to the output symbol table when they
14027 are used with the ADRL pseudo op. The ADRL relocation should always
14028 be resolved before the binbary is emitted, so it is safe to say that
14029 it is adjustable. */
14032 arm_fix_adjustable (fixP
)
14035 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14042 /* Relocations against Thumb function names must be left unadjusted,
14043 so that the linker can use this information to correctly set the
14044 bottom bit of their addresses. The MIPS version of this function
14045 also prevents relocations that are mips-16 specific, but I do not
14046 know why it does this.
14049 There is one other problem that ought to be addressed here, but
14050 which currently is not: Taking the address of a label (rather
14051 than a function) and then later jumping to that address. Such
14052 addresses also ought to have their bottom bit set (assuming that
14053 they reside in Thumb code), but at the moment they will not. */
14056 arm_fix_adjustable (fixP
)
14059 if (fixP
->fx_addsy
== NULL
)
14062 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14063 && fixP
->fx_subsy
== NULL
)
14066 /* We need the symbol name for the VTABLE entries. */
14067 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14068 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14071 /* Don't allow symbols to be discarded on GOT related relocs. */
14072 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14073 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14074 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
14081 elf32_arm_target_format ()
14083 if (target_big_endian
)
14086 return "elf32-bigarm-oabi";
14088 return "elf32-bigarm";
14093 return "elf32-littlearm-oabi";
14095 return "elf32-littlearm";
14100 armelf_frob_symbol (symp
, puntp
)
14104 elf_frob_symbol (symp
, puntp
);
14107 static bfd_reloc_code_real_type
14117 bfd_reloc_code_real_type reloc
;
14121 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14122 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14123 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14124 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14125 branch instructions generated by GCC for PLT relocs. */
14126 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14127 { NULL
, 0, BFD_RELOC_UNUSED
}
14131 for (i
= 0, ip
= input_line_pointer
;
14132 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14134 id
[i
] = TOLOWER (*ip
);
14136 for (i
= 0; reloc_map
[i
].str
; i
++)
14137 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14140 input_line_pointer
+= reloc_map
[i
].len
;
14142 return reloc_map
[i
].reloc
;
14146 s_arm_elf_cons (nbytes
)
14151 #ifdef md_flush_pending_output
14152 md_flush_pending_output ();
14155 if (is_it_end_of_statement ())
14157 demand_empty_rest_of_line ();
14161 #ifdef md_cons_align
14162 md_cons_align (nbytes
);
14165 mapping_state (MAP_DATA
);
14168 bfd_reloc_code_real_type reloc
;
14170 expression (& exp
);
14172 if (exp
.X_op
== O_symbol
14173 && * input_line_pointer
== '('
14174 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14176 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14177 int size
= bfd_get_reloc_size (howto
);
14180 as_bad ("%s relocations do not fit in %d bytes",
14181 howto
->name
, nbytes
);
14184 register char *p
= frag_more ((int) nbytes
);
14185 int offset
= nbytes
- size
;
14187 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14192 emit_expr (&exp
, (unsigned int) nbytes
);
14194 while (*input_line_pointer
++ == ',');
14196 /* Put terminator back into stream. */
14197 input_line_pointer
--;
14198 demand_empty_rest_of_line ();
14201 #endif /* OBJ_ELF */
14203 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14204 of an rs_align_code fragment. */
14207 arm_handle_align (fragP
)
14210 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14211 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14212 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14213 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14215 int bytes
, fix
, noop_size
;
14219 if (fragP
->fr_type
!= rs_align_code
)
14222 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14223 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14226 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14227 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14229 if (fragP
->tc_frag_data
)
14231 if (target_big_endian
)
14232 noop
= thumb_bigend_noop
;
14235 noop_size
= sizeof (thumb_noop
);
14239 if (target_big_endian
)
14240 noop
= arm_bigend_noop
;
14243 noop_size
= sizeof (arm_noop
);
14246 if (bytes
& (noop_size
- 1))
14248 fix
= bytes
& (noop_size
- 1);
14249 memset (p
, 0, fix
);
14254 while (bytes
>= noop_size
)
14256 memcpy (p
, noop
, noop_size
);
14258 bytes
-= noop_size
;
14262 fragP
->fr_fix
+= fix
;
14263 fragP
->fr_var
= noop_size
;
14266 /* Called from md_do_align. Used to create an alignment
14267 frag in a code section. */
14270 arm_frag_align_code (n
, max
)
14276 /* We assume that there will never be a requirement
14277 to support alignments greater than 32 bytes. */
14278 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14279 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14281 p
= frag_var (rs_align_code
,
14282 MAX_MEM_FOR_RS_ALIGN_CODE
,
14284 (relax_substateT
) max
,
14292 /* Perform target specific initialisation of a frag. */
14295 arm_init_frag (fragP
)
14298 /* Record whether this frag is in an ARM or a THUMB area. */
14299 fragP
->tc_frag_data
= thumb_mode
;