1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
5 Modified by David Taylor (dtaylor@armltd.co.uk)
6 Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
8 This file is part of GAS, the GNU Assembler.
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
28 #include "safe-ctype.h"
30 /* Need TARGET_CPU. */
39 #include "dwarf2dbg.h"
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
45 /* The following bitmasks control CPU extensions: */
46 #define ARM_EXT_V1 0x00000001 /* All processors (core set). */
47 #define ARM_EXT_V2 0x00000002 /* Multiply instructions. */
48 #define ARM_EXT_V2S 0x00000004 /* SWP instructions. */
49 #define ARM_EXT_V3 0x00000008 /* MSR MRS. */
50 #define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */
51 #define ARM_EXT_V4 0x00000020 /* Allow half word loads. */
52 #define ARM_EXT_V4T 0x00000040 /* Thumb v1. */
53 #define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */
54 #define ARM_EXT_V5T 0x00000100 /* Thumb v2. */
55 #define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
56 #define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
57 #define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
58 #define ARM_EXT_V6 0x00001000 /* ARM V6. */
60 /* Co-processor space extensions. */
61 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
62 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
63 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
65 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
66 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
67 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
68 three more to cover cores prior to ARM6. Finally, there are cores which
69 implement further extensions in the co-processor space. */
70 #define ARM_ARCH_V1 ARM_EXT_V1
71 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
72 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
73 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
74 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
75 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
76 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
77 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
78 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
79 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
80 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
81 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
83 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
84 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
85 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 #define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
88 /* Processors with specific extensions in the co-processor space. */
89 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
90 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
92 /* Some useful combinations: */
93 #define ARM_ANY 0x0000ffff /* Any basic core. */
94 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
95 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
96 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
99 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
100 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
101 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
102 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
103 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
104 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_MAVERICK 0x02000000 /* Cirrus Maverick. */
108 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
109 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
111 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
112 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
113 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
114 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
116 #define FPU_ARCH_MAVERICK FPU_MAVERICK
121 ARM_FLOAT_ABI_SOFTFP
,
125 /* Types of processor to assemble for. */
126 #define ARM_1 ARM_ARCH_V1
127 #define ARM_2 ARM_ARCH_V2
128 #define ARM_3 ARM_ARCH_V2S
129 #define ARM_250 ARM_ARCH_V2S
130 #define ARM_6 ARM_ARCH_V3
131 #define ARM_7 ARM_ARCH_V3
132 #define ARM_8 ARM_ARCH_V4
133 #define ARM_9 ARM_ARCH_V4T
134 #define ARM_STRONG ARM_ARCH_V4
135 #define ARM_CPU_MASK 0x0000000f /* XXX? */
138 #if defined __XSCALE__
139 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
141 #if defined __thumb__
142 #define CPU_DEFAULT (ARM_ARCH_V5T)
144 #define CPU_DEFAULT ARM_ANY
150 #define FPU_DEFAULT FPU_ARCH_FPA
155 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
157 /* Legacy a.out format. */
158 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
162 /* For backwards compatibility we default to the FPA. */
164 #define FPU_DEFAULT FPU_ARCH_FPA
167 #define streq(a, b) (strcmp (a, b) == 0)
168 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
170 static unsigned long cpu_variant
;
171 static int target_oabi
= 0;
173 /* Flags stored in private area of BFD structure. */
174 static int uses_apcs_26
= FALSE
;
175 static int atpcs
= FALSE
;
176 static int support_interwork
= FALSE
;
177 static int uses_apcs_float
= FALSE
;
178 static int pic_code
= FALSE
;
180 /* Variables that we set while parsing command-line options. Once all
181 options have been read we re-process these values to set the real
183 static int legacy_cpu
= -1;
184 static int legacy_fpu
= -1;
186 static int mcpu_cpu_opt
= -1;
187 static int mcpu_fpu_opt
= -1;
188 static int march_cpu_opt
= -1;
189 static int march_fpu_opt
= -1;
190 static int mfpu_opt
= -1;
191 static int mfloat_abi_opt
= -1;
193 /* This array holds the chars that always start a comment. If the
194 pre-processor is disabled, these aren't very useful. */
195 const char comment_chars
[] = "@";
197 /* This array holds the chars that only start a comment at the beginning of
198 a line. If the line seems to have the form '# 123 filename'
199 .line and .file directives will appear in the pre-processed output. */
200 /* Note that input_file.c hand checks for '#' at the beginning of the
201 first line of the input file. This is because the compiler outputs
202 #NO_APP at the beginning of its output. */
203 /* Also note that comments like this one will always work. */
204 const char line_comment_chars
[] = "#";
206 const char line_separator_chars
[] = ";";
208 /* Chars that can be used to separate mant
209 from exp in floating point numbers. */
210 const char EXP_CHARS
[] = "eE";
212 /* Chars that mean this number is a floating point constant. */
216 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
218 /* Prefix characters that indicate the start of an immediate
220 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
223 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
224 symbolS
* GOT_symbol
;
227 /* Size of relocation record. */
228 const int md_reloc_size
= 8;
230 /* 0: assemble for ARM,
231 1: assemble for Thumb,
232 2: assemble for Thumb even though target CPU does not support thumb
234 static int thumb_mode
= 0;
236 typedef struct arm_fix
244 unsigned long instruction
;
248 bfd_reloc_code_real_type type
;
265 struct asm_shift_properties
267 enum asm_shift_index index
;
268 unsigned long bit_field
;
269 unsigned int allows_0
: 1;
270 unsigned int allows_32
: 1;
273 static const struct asm_shift_properties shift_properties
[] =
275 { SHIFT_LSL
, 0, 1, 0},
276 { SHIFT_LSR
, 0x20, 0, 1},
277 { SHIFT_ASR
, 0x40, 0, 1},
278 { SHIFT_ROR
, 0x60, 0, 0},
279 { SHIFT_RRX
, 0x60, 0, 0}
282 struct asm_shift_name
285 const struct asm_shift_properties
* properties
;
288 static const struct asm_shift_name shift_names
[] =
290 { "asl", shift_properties
+ SHIFT_LSL
},
291 { "lsl", shift_properties
+ SHIFT_LSL
},
292 { "lsr", shift_properties
+ SHIFT_LSR
},
293 { "asr", shift_properties
+ SHIFT_ASR
},
294 { "ror", shift_properties
+ SHIFT_ROR
},
295 { "rrx", shift_properties
+ SHIFT_RRX
},
296 { "ASL", shift_properties
+ SHIFT_LSL
},
297 { "LSL", shift_properties
+ SHIFT_LSL
},
298 { "LSR", shift_properties
+ SHIFT_LSR
},
299 { "ASR", shift_properties
+ SHIFT_ASR
},
300 { "ROR", shift_properties
+ SHIFT_ROR
},
301 { "RRX", shift_properties
+ SHIFT_RRX
}
304 /* Any kind of shift is accepted. */
305 #define NO_SHIFT_RESTRICT 1
306 /* The shift operand must be an immediate value, not a register. */
307 #define SHIFT_IMMEDIATE 0
308 /* The shift must be LSL or ASR and the operand must be an immediate. */
309 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
310 /* The shift must be ASR and the operand must be an immediate. */
311 #define SHIFT_ASR_IMMEDIATE 3
312 /* The shift must be LSL and the operand must be an immediate. */
313 #define SHIFT_LSL_IMMEDIATE 4
315 #define NUM_FLOAT_VALS 8
317 const char * fp_const
[] =
319 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
322 /* Number of littlenums required to hold an extended precision number. */
323 #define MAX_LITTLENUMS 6
325 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
330 /* Whether a Co-processor load/store operation accepts write-back forms. */
339 #define CP_T_X 0x00008000
340 #define CP_T_Y 0x00400000
341 #define CP_T_Pre 0x01000000
342 #define CP_T_UD 0x00800000
343 #define CP_T_WB 0x00200000
345 #define CONDS_BIT 0x00100000
346 #define LOAD_BIT 0x00100000
348 #define DOUBLE_LOAD_FLAG 0x00000001
352 const char * template;
356 #define COND_ALWAYS 0xe0000000
357 #define COND_MASK 0xf0000000
359 static const struct asm_cond conds
[] =
363 {"cs", 0x20000000}, {"hs", 0x20000000},
364 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
381 const char *template;
386 /* The bit that distinguishes CPSR and SPSR. */
387 #define SPSR_BIT (1 << 22)
389 /* How many bits to shift the PSR_xxx bits up by. */
392 #define PSR_c (1 << 0)
393 #define PSR_x (1 << 1)
394 #define PSR_s (1 << 2)
395 #define PSR_f (1 << 3)
397 static const struct asm_psr psrs
[] =
399 {"CPSR", TRUE
, PSR_c
| PSR_f
},
400 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
401 {"SPSR", FALSE
, PSR_c
| PSR_f
},
402 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
403 {"CPSR_flg", TRUE
, PSR_f
},
404 {"CPSR_f", TRUE
, PSR_f
},
405 {"SPSR_flg", FALSE
, PSR_f
},
406 {"SPSR_f", FALSE
, PSR_f
},
407 {"CPSR_c", TRUE
, PSR_c
},
408 {"CPSR_ctl", TRUE
, PSR_c
},
409 {"SPSR_c", FALSE
, PSR_c
},
410 {"SPSR_ctl", FALSE
, PSR_c
},
411 {"CPSR_x", TRUE
, PSR_x
},
412 {"CPSR_s", TRUE
, PSR_s
},
413 {"SPSR_x", FALSE
, PSR_x
},
414 {"SPSR_s", FALSE
, PSR_s
},
415 /* Combinations of flags. */
416 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
417 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
418 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
419 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
420 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
421 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
422 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
423 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
424 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
425 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
426 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
427 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
428 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
429 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
430 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
431 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
432 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
433 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
434 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
435 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
436 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
437 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
438 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
439 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
440 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
441 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
442 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
443 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
444 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
445 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
446 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
447 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
448 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
449 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
450 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
451 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
452 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
453 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
454 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
455 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
456 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
457 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
458 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
459 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
460 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
461 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
462 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
463 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
464 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
465 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
466 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
467 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
468 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
469 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
470 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
471 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
472 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
473 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
474 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
475 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
476 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
477 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
478 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
479 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
480 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
481 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
482 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
483 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
484 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
485 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
486 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
487 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
488 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
489 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
490 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
491 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
492 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
493 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
494 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
495 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
496 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
497 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
498 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
499 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
500 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
501 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
502 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
503 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
504 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
505 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
506 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
507 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
508 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
509 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
510 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
511 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
512 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
513 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
514 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
515 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
516 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
517 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
518 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
519 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
520 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
521 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
522 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
523 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
524 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
525 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
526 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
527 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
528 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
529 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
530 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
531 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
532 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
533 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
534 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
535 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
542 IWMMXT_REG_WR_OR_WC
= 2,
546 enum iwmmxt_insn_type
569 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
574 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
579 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
582 /* VFP system registers. */
589 static const struct vfp_reg vfp_regs
[] =
591 {"fpsid", 0x00000000},
592 {"FPSID", 0x00000000},
593 {"fpscr", 0x00010000},
594 {"FPSCR", 0x00010000},
595 {"fpexc", 0x00080000},
596 {"FPEXC", 0x00080000}
599 /* Structure for a hash table entry for a register. */
607 /* Some well known registers that we refer to directly elsewhere. */
612 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
613 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
614 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
616 /* These are the standard names. Users can add aliases with .req.
617 and delete them with .unreq. */
619 /* Integer Register Numbers. */
620 static const struct reg_entry rn_table
[] =
622 {"r0", 0, TRUE
}, {"r1", 1, TRUE
}, {"r2", 2, TRUE
}, {"r3", 3, TRUE
},
623 {"r4", 4, TRUE
}, {"r5", 5, TRUE
}, {"r6", 6, TRUE
}, {"r7", 7, TRUE
},
624 {"r8", 8, TRUE
}, {"r9", 9, TRUE
}, {"r10", 10, TRUE
}, {"r11", 11, TRUE
},
625 {"r12", 12, TRUE
}, {"r13", REG_SP
, TRUE
}, {"r14", REG_LR
, TRUE
}, {"r15", REG_PC
, TRUE
},
626 /* ATPCS Synonyms. */
627 {"a1", 0, TRUE
}, {"a2", 1, TRUE
}, {"a3", 2, TRUE
}, {"a4", 3, TRUE
},
628 {"v1", 4, TRUE
}, {"v2", 5, TRUE
}, {"v3", 6, TRUE
}, {"v4", 7, TRUE
},
629 {"v5", 8, TRUE
}, {"v6", 9, TRUE
}, {"v7", 10, TRUE
}, {"v8", 11, TRUE
},
630 /* Well-known aliases. */
631 {"wr", 7, TRUE
}, {"sb", 9, TRUE
}, {"sl", 10, TRUE
}, {"fp", 11, TRUE
},
632 {"ip", 12, TRUE
}, {"sp", REG_SP
, TRUE
}, {"lr", REG_LR
, TRUE
}, {"pc", REG_PC
, TRUE
},
636 #define WR_PREFIX 0x200
637 #define WC_PREFIX 0x400
639 static const struct reg_entry iwmmxt_table
[] =
641 /* Intel Wireless MMX technology register names. */
642 { "wr0", 0x0 | WR_PREFIX
, TRUE
}, {"wr1", 0x1 | WR_PREFIX
, TRUE
},
643 { "wr2", 0x2 | WR_PREFIX
, TRUE
}, {"wr3", 0x3 | WR_PREFIX
, TRUE
},
644 { "wr4", 0x4 | WR_PREFIX
, TRUE
}, {"wr5", 0x5 | WR_PREFIX
, TRUE
},
645 { "wr6", 0x6 | WR_PREFIX
, TRUE
}, {"wr7", 0x7 | WR_PREFIX
, TRUE
},
646 { "wr8", 0x8 | WR_PREFIX
, TRUE
}, {"wr9", 0x9 | WR_PREFIX
, TRUE
},
647 { "wr10", 0xa | WR_PREFIX
, TRUE
}, {"wr11", 0xb | WR_PREFIX
, TRUE
},
648 { "wr12", 0xc | WR_PREFIX
, TRUE
}, {"wr13", 0xd | WR_PREFIX
, TRUE
},
649 { "wr14", 0xe | WR_PREFIX
, TRUE
}, {"wr15", 0xf | WR_PREFIX
, TRUE
},
650 { "wcid", 0x0 | WC_PREFIX
, TRUE
}, {"wcon", 0x1 | WC_PREFIX
, TRUE
},
651 {"wcssf", 0x2 | WC_PREFIX
, TRUE
}, {"wcasf", 0x3 | WC_PREFIX
, TRUE
},
652 {"wcgr0", 0x8 | WC_PREFIX
, TRUE
}, {"wcgr1", 0x9 | WC_PREFIX
, TRUE
},
653 {"wcgr2", 0xa | WC_PREFIX
, TRUE
}, {"wcgr3", 0xb | WC_PREFIX
, TRUE
},
655 { "wR0", 0x0 | WR_PREFIX
, TRUE
}, {"wR1", 0x1 | WR_PREFIX
, TRUE
},
656 { "wR2", 0x2 | WR_PREFIX
, TRUE
}, {"wR3", 0x3 | WR_PREFIX
, TRUE
},
657 { "wR4", 0x4 | WR_PREFIX
, TRUE
}, {"wR5", 0x5 | WR_PREFIX
, TRUE
},
658 { "wR6", 0x6 | WR_PREFIX
, TRUE
}, {"wR7", 0x7 | WR_PREFIX
, TRUE
},
659 { "wR8", 0x8 | WR_PREFIX
, TRUE
}, {"wR9", 0x9 | WR_PREFIX
, TRUE
},
660 { "wR10", 0xa | WR_PREFIX
, TRUE
}, {"wR11", 0xb | WR_PREFIX
, TRUE
},
661 { "wR12", 0xc | WR_PREFIX
, TRUE
}, {"wR13", 0xd | WR_PREFIX
, TRUE
},
662 { "wR14", 0xe | WR_PREFIX
, TRUE
}, {"wR15", 0xf | WR_PREFIX
, TRUE
},
663 { "wCID", 0x0 | WC_PREFIX
, TRUE
}, {"wCon", 0x1 | WC_PREFIX
, TRUE
},
664 {"wCSSF", 0x2 | WC_PREFIX
, TRUE
}, {"wCASF", 0x3 | WC_PREFIX
, TRUE
},
665 {"wCGR0", 0x8 | WC_PREFIX
, TRUE
}, {"wCGR1", 0x9 | WC_PREFIX
, TRUE
},
666 {"wCGR2", 0xa | WC_PREFIX
, TRUE
}, {"wCGR3", 0xb | WC_PREFIX
, TRUE
},
670 /* Co-processor Numbers. */
671 static const struct reg_entry cp_table
[] =
673 {"p0", 0, TRUE
}, {"p1", 1, TRUE
}, {"p2", 2, TRUE
}, {"p3", 3, TRUE
},
674 {"p4", 4, TRUE
}, {"p5", 5, TRUE
}, {"p6", 6, TRUE
}, {"p7", 7, TRUE
},
675 {"p8", 8, TRUE
}, {"p9", 9, TRUE
}, {"p10", 10, TRUE
}, {"p11", 11, TRUE
},
676 {"p12", 12, TRUE
}, {"p13", 13, TRUE
}, {"p14", 14, TRUE
}, {"p15", 15, TRUE
},
680 /* Co-processor Register Numbers. */
681 static const struct reg_entry cn_table
[] =
683 {"c0", 0, TRUE
}, {"c1", 1, TRUE
}, {"c2", 2, TRUE
}, {"c3", 3, TRUE
},
684 {"c4", 4, TRUE
}, {"c5", 5, TRUE
}, {"c6", 6, TRUE
}, {"c7", 7, TRUE
},
685 {"c8", 8, TRUE
}, {"c9", 9, TRUE
}, {"c10", 10, TRUE
}, {"c11", 11, TRUE
},
686 {"c12", 12, TRUE
}, {"c13", 13, TRUE
}, {"c14", 14, TRUE
}, {"c15", 15, TRUE
},
687 /* Not really valid, but kept for back-wards compatibility. */
688 {"cr0", 0, TRUE
}, {"cr1", 1, TRUE
}, {"cr2", 2, TRUE
}, {"cr3", 3, TRUE
},
689 {"cr4", 4, TRUE
}, {"cr5", 5, TRUE
}, {"cr6", 6, TRUE
}, {"cr7", 7, TRUE
},
690 {"cr8", 8, TRUE
}, {"cr9", 9, TRUE
}, {"cr10", 10, TRUE
}, {"cr11", 11, TRUE
},
691 {"cr12", 12, TRUE
}, {"cr13", 13, TRUE
}, {"cr14", 14, TRUE
}, {"cr15", 15, TRUE
},
696 static const struct reg_entry fn_table
[] =
698 {"f0", 0, TRUE
}, {"f1", 1, TRUE
}, {"f2", 2, TRUE
}, {"f3", 3, TRUE
},
699 {"f4", 4, TRUE
}, {"f5", 5, TRUE
}, {"f6", 6, TRUE
}, {"f7", 7, TRUE
},
703 /* VFP SP Registers. */
704 static const struct reg_entry sn_table
[] =
706 {"s0", 0, TRUE
}, {"s1", 1, TRUE
}, {"s2", 2, TRUE
}, {"s3", 3, TRUE
},
707 {"s4", 4, TRUE
}, {"s5", 5, TRUE
}, {"s6", 6, TRUE
}, {"s7", 7, TRUE
},
708 {"s8", 8, TRUE
}, {"s9", 9, TRUE
}, {"s10", 10, TRUE
}, {"s11", 11, TRUE
},
709 {"s12", 12, TRUE
}, {"s13", 13, TRUE
}, {"s14", 14, TRUE
}, {"s15", 15, TRUE
},
710 {"s16", 16, TRUE
}, {"s17", 17, TRUE
}, {"s18", 18, TRUE
}, {"s19", 19, TRUE
},
711 {"s20", 20, TRUE
}, {"s21", 21, TRUE
}, {"s22", 22, TRUE
}, {"s23", 23, TRUE
},
712 {"s24", 24, TRUE
}, {"s25", 25, TRUE
}, {"s26", 26, TRUE
}, {"s27", 27, TRUE
},
713 {"s28", 28, TRUE
}, {"s29", 29, TRUE
}, {"s30", 30, TRUE
}, {"s31", 31, TRUE
},
717 /* VFP DP Registers. */
718 static const struct reg_entry dn_table
[] =
720 {"d0", 0, TRUE
}, {"d1", 1, TRUE
}, {"d2", 2, TRUE
}, {"d3", 3, TRUE
},
721 {"d4", 4, TRUE
}, {"d5", 5, TRUE
}, {"d6", 6, TRUE
}, {"d7", 7, TRUE
},
722 {"d8", 8, TRUE
}, {"d9", 9, TRUE
}, {"d10", 10, TRUE
}, {"d11", 11, TRUE
},
723 {"d12", 12, TRUE
}, {"d13", 13, TRUE
}, {"d14", 14, TRUE
}, {"d15", 15, TRUE
},
727 /* Maverick DSP coprocessor registers. */
728 static const struct reg_entry mav_mvf_table
[] =
730 {"mvf0", 0, TRUE
}, {"mvf1", 1, TRUE
}, {"mvf2", 2, TRUE
}, {"mvf3", 3, TRUE
},
731 {"mvf4", 4, TRUE
}, {"mvf5", 5, TRUE
}, {"mvf6", 6, TRUE
}, {"mvf7", 7, TRUE
},
732 {"mvf8", 8, TRUE
}, {"mvf9", 9, TRUE
}, {"mvf10", 10, TRUE
}, {"mvf11", 11, TRUE
},
733 {"mvf12", 12, TRUE
}, {"mvf13", 13, TRUE
}, {"mvf14", 14, TRUE
}, {"mvf15", 15, TRUE
},
737 static const struct reg_entry mav_mvd_table
[] =
739 {"mvd0", 0, TRUE
}, {"mvd1", 1, TRUE
}, {"mvd2", 2, TRUE
}, {"mvd3", 3, TRUE
},
740 {"mvd4", 4, TRUE
}, {"mvd5", 5, TRUE
}, {"mvd6", 6, TRUE
}, {"mvd7", 7, TRUE
},
741 {"mvd8", 8, TRUE
}, {"mvd9", 9, TRUE
}, {"mvd10", 10, TRUE
}, {"mvd11", 11, TRUE
},
742 {"mvd12", 12, TRUE
}, {"mvd13", 13, TRUE
}, {"mvd14", 14, TRUE
}, {"mvd15", 15, TRUE
},
746 static const struct reg_entry mav_mvfx_table
[] =
748 {"mvfx0", 0, TRUE
}, {"mvfx1", 1, TRUE
}, {"mvfx2", 2, TRUE
}, {"mvfx3", 3, TRUE
},
749 {"mvfx4", 4, TRUE
}, {"mvfx5", 5, TRUE
}, {"mvfx6", 6, TRUE
}, {"mvfx7", 7, TRUE
},
750 {"mvfx8", 8, TRUE
}, {"mvfx9", 9, TRUE
}, {"mvfx10", 10, TRUE
}, {"mvfx11", 11, TRUE
},
751 {"mvfx12", 12, TRUE
}, {"mvfx13", 13, TRUE
}, {"mvfx14", 14, TRUE
}, {"mvfx15", 15, TRUE
},
755 static const struct reg_entry mav_mvdx_table
[] =
757 {"mvdx0", 0, TRUE
}, {"mvdx1", 1, TRUE
}, {"mvdx2", 2, TRUE
}, {"mvdx3", 3, TRUE
},
758 {"mvdx4", 4, TRUE
}, {"mvdx5", 5, TRUE
}, {"mvdx6", 6, TRUE
}, {"mvdx7", 7, TRUE
},
759 {"mvdx8", 8, TRUE
}, {"mvdx9", 9, TRUE
}, {"mvdx10", 10, TRUE
}, {"mvdx11", 11, TRUE
},
760 {"mvdx12", 12, TRUE
}, {"mvdx13", 13, TRUE
}, {"mvdx14", 14, TRUE
}, {"mvdx15", 15, TRUE
},
764 static const struct reg_entry mav_mvax_table
[] =
766 {"mvax0", 0, TRUE
}, {"mvax1", 1, TRUE
}, {"mvax2", 2, TRUE
}, {"mvax3", 3, TRUE
},
770 static const struct reg_entry mav_dspsc_table
[] =
778 const struct reg_entry
*names
;
780 struct hash_control
*htab
;
781 const char *expected
;
784 struct reg_map all_reg_maps
[] =
786 {rn_table
, 15, NULL
, N_("ARM register expected")},
787 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
788 {cn_table
, 15, NULL
, N_("co-processor register expected")},
789 {fn_table
, 7, NULL
, N_("FPA register expected")},
790 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
791 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
792 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
793 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
794 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
795 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
796 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
797 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
798 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
801 /* Enumeration matching entries in table above. */
805 #define REG_TYPE_FIRST REG_TYPE_RN
817 REG_TYPE_IWMMXT
= 12,
822 /* Functions called by parser. */
823 /* ARM instructions. */
824 static void do_arit
PARAMS ((char *));
825 static void do_cmp
PARAMS ((char *));
826 static void do_mov
PARAMS ((char *));
827 static void do_ldst
PARAMS ((char *));
828 static void do_ldstt
PARAMS ((char *));
829 static void do_ldmstm
PARAMS ((char *));
830 static void do_branch
PARAMS ((char *));
831 static void do_swi
PARAMS ((char *));
833 /* Pseudo Op codes. */
834 static void do_adr
PARAMS ((char *));
835 static void do_adrl
PARAMS ((char *));
836 static void do_empty
PARAMS ((char *));
839 static void do_mul
PARAMS ((char *));
840 static void do_mla
PARAMS ((char *));
843 static void do_swap
PARAMS ((char *));
846 static void do_msr
PARAMS ((char *));
847 static void do_mrs
PARAMS ((char *));
850 static void do_mull
PARAMS ((char *));
853 static void do_ldstv4
PARAMS ((char *));
856 static void do_bx
PARAMS ((char *));
859 static void do_blx
PARAMS ((char *));
860 static void do_bkpt
PARAMS ((char *));
861 static void do_clz
PARAMS ((char *));
862 static void do_lstc2
PARAMS ((char *));
863 static void do_cdp2
PARAMS ((char *));
864 static void do_co_reg2
PARAMS ((char *));
867 static void do_smla
PARAMS ((char *));
868 static void do_smlal
PARAMS ((char *));
869 static void do_smul
PARAMS ((char *));
870 static void do_qadd
PARAMS ((char *));
873 static void do_pld
PARAMS ((char *));
874 static void do_ldrd
PARAMS ((char *));
875 static void do_co_reg2c
PARAMS ((char *));
878 static void do_bxj
PARAMS ((char *));
881 static void do_cps
PARAMS ((char *));
882 static void do_cpsi
PARAMS ((char *));
883 static void do_ldrex
PARAMS ((char *));
884 static void do_pkhbt
PARAMS ((char *));
885 static void do_pkhtb
PARAMS ((char *));
886 static void do_qadd16
PARAMS ((char *));
887 static void do_rev
PARAMS ((char *));
888 static void do_rfe
PARAMS ((char *));
889 static void do_sxtah
PARAMS ((char *));
890 static void do_sxth
PARAMS ((char *));
891 static void do_setend
PARAMS ((char *));
892 static void do_smlad
PARAMS ((char *));
893 static void do_smlald
PARAMS ((char *));
894 static void do_smmul
PARAMS ((char *));
895 static void do_ssat
PARAMS ((char *));
896 static void do_usat
PARAMS ((char *));
897 static void do_srs
PARAMS ((char *));
898 static void do_ssat16
PARAMS ((char *));
899 static void do_usat16
PARAMS ((char *));
900 static void do_strex
PARAMS ((char *));
901 static void do_umaal
PARAMS ((char *));
903 static void do_cps_mode
PARAMS ((char **));
904 static void do_cps_flags
PARAMS ((char **, int));
905 static int do_endian_specifier
PARAMS ((char *));
906 static void do_pkh_core
PARAMS ((char *, int));
907 static void do_sat
PARAMS ((char **, int));
908 static void do_sat16
PARAMS ((char **, int));
910 /* Coprocessor Instructions. */
911 static void do_cdp
PARAMS ((char *));
912 static void do_lstc
PARAMS ((char *));
913 static void do_co_reg
PARAMS ((char *));
915 /* FPA instructions. */
916 static void do_fpa_ctrl
PARAMS ((char *));
917 static void do_fpa_ldst
PARAMS ((char *));
918 static void do_fpa_ldmstm
PARAMS ((char *));
919 static void do_fpa_dyadic
PARAMS ((char *));
920 static void do_fpa_monadic
PARAMS ((char *));
921 static void do_fpa_cmp
PARAMS ((char *));
922 static void do_fpa_from_reg
PARAMS ((char *));
923 static void do_fpa_to_reg
PARAMS ((char *));
925 /* VFP instructions. */
926 static void do_vfp_sp_monadic
PARAMS ((char *));
927 static void do_vfp_dp_monadic
PARAMS ((char *));
928 static void do_vfp_sp_dyadic
PARAMS ((char *));
929 static void do_vfp_dp_dyadic
PARAMS ((char *));
930 static void do_vfp_reg_from_sp
PARAMS ((char *));
931 static void do_vfp_sp_from_reg
PARAMS ((char *));
932 static void do_vfp_reg2_from_sp2
PARAMS ((char *));
933 static void do_vfp_sp2_from_reg2
PARAMS ((char *));
934 static void do_vfp_reg_from_dp
PARAMS ((char *));
935 static void do_vfp_reg2_from_dp
PARAMS ((char *));
936 static void do_vfp_dp_from_reg
PARAMS ((char *));
937 static void do_vfp_dp_from_reg2
PARAMS ((char *));
938 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
939 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
940 static void do_vfp_sp_ldst
PARAMS ((char *));
941 static void do_vfp_dp_ldst
PARAMS ((char *));
942 static void do_vfp_sp_ldstmia
PARAMS ((char *));
943 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
944 static void do_vfp_dp_ldstmia
PARAMS ((char *));
945 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
946 static void do_vfp_xp_ldstmia
PARAMS ((char *));
947 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
948 static void do_vfp_sp_compare_z
PARAMS ((char *));
949 static void do_vfp_dp_compare_z
PARAMS ((char *));
950 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
951 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
954 static void do_xsc_mia
PARAMS ((char *));
955 static void do_xsc_mar
PARAMS ((char *));
956 static void do_xsc_mra
PARAMS ((char *));
959 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
961 static void do_mav_binops_1a
PARAMS ((char *));
962 static void do_mav_binops_1b
PARAMS ((char *));
963 static void do_mav_binops_1c
PARAMS ((char *));
964 static void do_mav_binops_1d
PARAMS ((char *));
965 static void do_mav_binops_1e
PARAMS ((char *));
966 static void do_mav_binops_1f
PARAMS ((char *));
967 static void do_mav_binops_1g
PARAMS ((char *));
968 static void do_mav_binops_1h
PARAMS ((char *));
969 static void do_mav_binops_1i
PARAMS ((char *));
970 static void do_mav_binops_1j
PARAMS ((char *));
971 static void do_mav_binops_1k
PARAMS ((char *));
972 static void do_mav_binops_1l
PARAMS ((char *));
973 static void do_mav_binops_1m
PARAMS ((char *));
974 static void do_mav_binops_1n
PARAMS ((char *));
975 static void do_mav_binops_1o
PARAMS ((char *));
976 static void do_mav_binops_2a
PARAMS ((char *));
977 static void do_mav_binops_2b
PARAMS ((char *));
978 static void do_mav_binops_2c
PARAMS ((char *));
979 static void do_mav_binops_3a
PARAMS ((char *));
980 static void do_mav_binops_3b
PARAMS ((char *));
981 static void do_mav_binops_3c
PARAMS ((char *));
982 static void do_mav_binops_3d
PARAMS ((char *));
983 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
986 static void do_mav_triple_4a
PARAMS ((char *));
987 static void do_mav_triple_4b
PARAMS ((char *));
988 static void do_mav_triple_5a
PARAMS ((char *));
989 static void do_mav_triple_5b
PARAMS ((char *));
990 static void do_mav_triple_5c
PARAMS ((char *));
991 static void do_mav_triple_5d
PARAMS ((char *));
992 static void do_mav_triple_5e
PARAMS ((char *));
993 static void do_mav_triple_5f
PARAMS ((char *));
994 static void do_mav_triple_5g
PARAMS ((char *));
995 static void do_mav_triple_5h
PARAMS ((char *));
996 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
1000 static void do_mav_quad_6a
PARAMS ((char *));
1001 static void do_mav_quad_6b
PARAMS ((char *));
1002 static void do_mav_dspsc_1
PARAMS ((char *));
1003 static void do_mav_dspsc_2
PARAMS ((char *));
1004 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
1005 enum arm_reg_type
));
1006 static void do_mav_shift_1
PARAMS ((char *));
1007 static void do_mav_shift_2
PARAMS ((char *));
1008 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
1009 static void do_mav_ldst_1
PARAMS ((char *));
1010 static void do_mav_ldst_2
PARAMS ((char *));
1011 static void do_mav_ldst_3
PARAMS ((char *));
1012 static void do_mav_ldst_4
PARAMS ((char *));
1014 static int mav_reg_required_here
PARAMS ((char **, int,
1015 enum arm_reg_type
));
1016 static int mav_parse_offset
PARAMS ((char **, int *));
1018 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
1020 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
1021 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
1022 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
1023 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
1025 static int add_to_lit_pool
PARAMS ((void));
1026 static unsigned validate_immediate
PARAMS ((unsigned));
1027 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
1029 static int validate_offset_imm
PARAMS ((unsigned int, int));
1030 static void opcode_select
PARAMS ((int));
1031 static void end_of_line
PARAMS ((char *));
1032 static int reg_required_here
PARAMS ((char **, int));
1033 static int psr_required_here
PARAMS ((char **));
1034 static int co_proc_number
PARAMS ((char **));
1035 static int cp_opc_expr
PARAMS ((char **, int, int));
1036 static int cp_reg_required_here
PARAMS ((char **, int));
1037 static int fp_reg_required_here
PARAMS ((char **, int));
1038 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
1039 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
1040 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1041 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1042 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
1043 static long vfp_dp_reg_list
PARAMS ((char **));
1044 static int vfp_psr_required_here
PARAMS ((char **str
));
1045 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
1046 static int cp_address_offset
PARAMS ((char **));
1047 static int cp_address_required_here
PARAMS ((char **, int));
1048 static int my_get_float_expression
PARAMS ((char **));
1049 static int skip_past_comma
PARAMS ((char **));
1050 static int walk_no_bignums
PARAMS ((symbolS
*));
1051 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1052 static int data_op2
PARAMS ((char **));
1053 static int fp_op2
PARAMS ((char **));
1054 static long reg_list
PARAMS ((char **));
1055 static void thumb_load_store
PARAMS ((char *, int, int));
1056 static int decode_shift
PARAMS ((char **, int));
1057 static int ldst_extend
PARAMS ((char **));
1058 static int ldst_extend_v4
PARAMS ((char **));
1059 static void thumb_add_sub
PARAMS ((char *, int));
1060 static void insert_reg
PARAMS ((const struct reg_entry
*,
1061 struct hash_control
*));
1062 static void thumb_shift
PARAMS ((char *, int));
1063 static void thumb_mov_compare
PARAMS ((char *, int));
1064 static void build_arm_ops_hsh
PARAMS ((void));
1065 static void set_constant_flonums
PARAMS ((void));
1066 static valueT md_chars_to_number
PARAMS ((char *, int));
1067 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1068 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1069 static int create_register_alias
PARAMS ((char *, char *));
1070 static void output_inst
PARAMS ((const char *));
1071 static int accum0_required_here
PARAMS ((char **));
1072 static int ld_mode_required_here
PARAMS ((char **));
1073 static void do_branch25
PARAMS ((char *));
1074 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1076 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1079 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1080 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1081 static void do_iwmmxt_tandc
PARAMS ((char *));
1082 static void do_iwmmxt_tbcst
PARAMS ((char *));
1083 static void do_iwmmxt_textrc
PARAMS ((char *));
1084 static void do_iwmmxt_textrm
PARAMS ((char *));
1085 static void do_iwmmxt_tinsr
PARAMS ((char *));
1086 static void do_iwmmxt_tmcr
PARAMS ((char *));
1087 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1088 static void do_iwmmxt_tmia
PARAMS ((char *));
1089 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1090 static void do_iwmmxt_tmrc
PARAMS ((char *));
1091 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1092 static void do_iwmmxt_torc
PARAMS ((char *));
1093 static void do_iwmmxt_waligni
PARAMS ((char *));
1094 static void do_iwmmxt_wmov
PARAMS ((char *));
1095 static void do_iwmmxt_word_addr
PARAMS ((char *));
1096 static void do_iwmmxt_wrwr
PARAMS ((char *));
1097 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1098 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1099 static void do_iwmmxt_wshufh
PARAMS ((char *));
1100 static void do_iwmmxt_wzero
PARAMS ((char *));
1101 static int cp_byte_address_offset
PARAMS ((char **));
1102 static int cp_byte_address_required_here
PARAMS ((char **));
1104 /* ARM instructions take 4bytes in the object file, Thumb instructions
1108 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1109 #define MAV_MODE1 0x100c
1111 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1112 #define MAV_MODE2 0x0c10
1114 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1115 #define MAV_MODE3 0x1000
1117 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1118 #define MAV_MODE4 0x0c0010
1120 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1121 #define MAV_MODE5 0x00100c
1123 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1124 #define MAV_MODE6 0x00100c05
1128 /* Basic string to match. */
1129 const char * template;
1131 /* Basic instruction code. */
1132 unsigned long value
;
1134 /* Offset into the template where the condition code (if any) will be.
1135 If zero, then the instruction is never conditional. */
1136 unsigned cond_offset
;
1138 /* Which architecture variant provides this instruction. */
1139 unsigned long variant
;
1141 /* Function to call to parse args. */
1142 void (* parms
) PARAMS ((char *));
1145 static const struct asm_opcode insns
[] =
1147 /* Core ARM Instructions. */
1148 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1149 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1150 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1151 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1152 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1153 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1154 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1155 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1156 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1157 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1158 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1159 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1160 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1161 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1162 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1163 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1164 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1165 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1166 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1167 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1169 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1170 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1171 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1172 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1173 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1174 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1175 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1176 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1177 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1178 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1179 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1180 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1182 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1183 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1184 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1185 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1187 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1188 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1189 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1190 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1191 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1192 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1193 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1194 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1196 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1197 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1198 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1199 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1200 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1201 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1202 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1203 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1205 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1206 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1207 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1208 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1209 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1210 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1211 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1212 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1214 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1216 /* XXX This is the wrong place to do this. Think multi-arch. */
1217 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1218 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1220 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1221 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1225 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1226 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1227 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1229 /* ARM 2 multiplies. */
1230 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1231 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1232 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1233 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1235 /* Generic coprocessor instructions. */
1236 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1237 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1238 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1239 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1240 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1241 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1242 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1244 /* ARM 3 - swp instructions. */
1245 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1246 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1248 /* ARM 6 Status register instructions. */
1249 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1250 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1251 /* ScottB: our code uses 0xe128f000 for msr.
1252 NickC: but this is wrong because the bits 16 through 19 are
1253 handled by the PSR_xxx defines above. */
1255 /* ARM 7M long multiplies. */
1256 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1257 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1258 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1259 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1260 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1261 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1262 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1263 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1265 /* ARM Architecture 4. */
1266 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1267 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1268 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1269 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1271 /* ARM Architecture 4T. */
1272 /* Note: bx (and blx) are required on V5, even if the processor does
1273 not support Thumb. */
1274 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1276 /* ARM Architecture 5T. */
1277 /* Note: blx has 2 variants, so the .value is set dynamically.
1278 Only one of the variants has conditional execution. */
1279 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1280 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1281 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1282 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1283 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1284 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1285 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1286 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1287 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1288 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1290 /* ARM Architecture 5TExP. */
1291 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1292 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1293 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1294 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1296 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1297 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1299 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1300 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1301 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1302 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1304 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1305 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1306 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1307 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1309 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1310 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1312 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1313 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1314 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1315 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1317 /* ARM Architecture 5TE. */
1318 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1319 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1320 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1322 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1323 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1325 /* ARM Architecture 5TEJ. */
1326 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1329 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
1330 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
1331 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
1332 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
1333 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
1334 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
1335 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
1336 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
1337 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
1338 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
1339 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
1340 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
1341 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
1342 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
1343 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
1344 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
1345 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
1346 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
1347 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
1348 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
1349 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
1350 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
1351 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
1352 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
1353 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
1354 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
1355 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
1356 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
1357 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
1358 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
1359 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
1360 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
1361 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
1362 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
1363 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
1364 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
1365 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
1366 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
1367 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
1368 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
1369 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
1370 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
1371 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
1372 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
1373 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
1374 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
1375 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
1376 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1377 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1378 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1379 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1380 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1381 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1382 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1383 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1384 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
1385 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
1386 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
1387 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
1388 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
1389 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
1390 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
1391 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
1392 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
1393 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
1394 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
1395 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
1396 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
1397 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
1398 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
1399 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
1400 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
1401 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
1402 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
1403 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
1404 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
1405 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
1406 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
1407 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
1408 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
1409 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
1410 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
1411 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
1412 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
1413 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
1414 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
1415 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
1416 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
1417 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
1418 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
1419 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
1420 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
1421 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
1422 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
1423 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
1424 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
1425 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
1426 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
1427 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
1429 /* Core FPA instruction set (V1). */
1430 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1431 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1432 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1433 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1435 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1436 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1437 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1438 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1440 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1441 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1442 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1443 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1445 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1499 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1501 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1502 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1503 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1504 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1505 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1506 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1507 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1508 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1510 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1511 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1512 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1513 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1514 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1515 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1516 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1517 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1518 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1519 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1520 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1521 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1523 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1524 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1525 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1526 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1527 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1528 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1529 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1530 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1531 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1532 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1533 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1534 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1536 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1537 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1538 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1539 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1540 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1541 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1542 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1543 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1544 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1545 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1546 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1547 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1549 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1550 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1551 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1552 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1553 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1554 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1555 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1556 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1557 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1558 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1559 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1560 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1562 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1563 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1564 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1565 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1566 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1567 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1568 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1569 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1570 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1571 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1572 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1573 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1575 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1576 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1577 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1578 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1579 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1580 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1581 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1582 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1583 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1584 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1585 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1586 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1588 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1589 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1590 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1591 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1592 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1593 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1594 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1595 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1596 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1597 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1598 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1599 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1601 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1602 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1603 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1604 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1605 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1606 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1607 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1608 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1609 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1610 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1611 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1612 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1614 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1615 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1616 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1617 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1618 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1619 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1620 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1621 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1622 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1623 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1624 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1625 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1627 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1628 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1629 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1630 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1631 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1632 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1633 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1634 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1635 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1636 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1637 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1638 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1640 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1641 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1642 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1643 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1644 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1645 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1646 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1647 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1648 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1649 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1650 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1651 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1653 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1668 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1670 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1671 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1672 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1673 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1674 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1675 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1676 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1677 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1679 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1680 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1681 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1682 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1683 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1684 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1685 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1686 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1687 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1688 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1689 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1690 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1692 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1693 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1694 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1695 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1696 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1697 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1698 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1699 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1700 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1701 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1702 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1703 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1705 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1706 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1707 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1708 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1709 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1710 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1711 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1712 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1713 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1714 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1715 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1716 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1718 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1719 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1720 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1721 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1722 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1723 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1724 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1725 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1726 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1727 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1728 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1729 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1731 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1732 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1733 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1734 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1735 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1736 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1737 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1738 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1739 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1740 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1741 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1742 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1744 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1745 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1746 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1747 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1748 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1749 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1750 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1751 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1752 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1753 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1754 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1755 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1757 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1758 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1759 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1760 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1761 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1762 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1763 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1764 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1765 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1766 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1767 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1768 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1770 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1771 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1772 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1773 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1774 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1775 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1776 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1777 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1778 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1779 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1780 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1781 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1783 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1784 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1785 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1786 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1787 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1788 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1789 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1790 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1791 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1792 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1793 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1794 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1796 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1797 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1798 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1799 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1800 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1801 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1802 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1803 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1804 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1805 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1806 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1807 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1809 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1810 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1811 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1812 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1813 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1814 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1815 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1816 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1817 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1818 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1819 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1820 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1822 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1823 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1824 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1825 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1826 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1827 not be an optional suffix, but part of the instruction. To be
1828 compatible, we accept either. */
1829 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1830 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1832 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1833 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1834 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1835 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1836 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1837 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1838 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1839 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1840 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1841 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1842 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1843 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1845 /* The implementation of the FIX instruction is broken on some
1846 assemblers, in that it accepts a precision specifier as well as a
1847 rounding specifier, despite the fact that this is meaningless.
1848 To be more compatible, we accept it as well, though of course it
1849 does not set any bits. */
1850 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1851 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1852 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1853 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1854 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1855 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1856 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1857 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1858 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1859 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1860 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1861 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1862 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1864 /* Instructions that were new with the real FPA, call them V2. */
1865 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1866 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1867 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1868 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1869 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1870 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1872 /* VFP V1xD (single precision). */
1873 /* Moves and type conversions. */
1874 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1875 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1876 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1877 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1878 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1879 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1880 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1881 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1882 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1883 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1884 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1885 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1887 /* Memory operations. */
1888 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1889 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1890 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1891 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1892 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1893 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1894 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1895 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1896 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1897 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1898 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1899 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1900 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1901 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1902 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1903 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1904 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1905 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1907 /* Monadic operations. */
1908 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1909 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1910 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1912 /* Dyadic operations. */
1913 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1914 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1915 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1916 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1917 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1918 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1919 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1920 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1921 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1924 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1925 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1926 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1927 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1929 /* VFP V1 (Double precision). */
1930 /* Moves and type conversions. */
1931 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1932 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1933 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1934 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1935 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1936 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1937 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1938 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1939 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1940 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1941 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1942 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1943 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1945 /* Memory operations. */
1946 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1947 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1948 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1949 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1950 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1951 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1952 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1953 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1954 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1955 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1957 /* Monadic operations. */
1958 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1959 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1960 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1962 /* Dyadic operations. */
1963 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1964 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1965 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1966 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1967 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1968 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1969 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1970 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1971 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1974 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1975 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1976 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1977 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1980 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp2_from_reg2
},
1981 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_sp2
},
1982 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1983 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1985 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1986 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1987 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1988 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1989 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1990 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1991 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1992 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1993 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1995 /* Intel Wireless MMX technology instructions. */
1996 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1997 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1998 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1999 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2000 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2001 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2002 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2003 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2004 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2005 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2006 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2007 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2008 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2009 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2010 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2011 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2012 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2013 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2014 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
2015 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
2016 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2017 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2018 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2019 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2020 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2021 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2022 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2023 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2024 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2025 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
2026 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
2027 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2028 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2029 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2030 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2031 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2032 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2033 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2034 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2035 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2036 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2037 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2038 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2039 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2040 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2041 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2042 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
2043 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2044 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2045 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2046 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2047 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2048 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2049 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2050 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2051 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2052 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2053 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2054 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2055 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2056 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2057 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2058 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2059 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2060 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2061 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2062 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2063 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2064 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2065 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2066 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2067 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2068 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2069 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2070 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2071 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2072 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2073 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2074 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2075 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2076 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2077 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2078 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2079 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2080 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2081 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2082 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2083 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2084 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
2085 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2086 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2087 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2088 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2089 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2090 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2091 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2092 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2093 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2094 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2095 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2096 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2097 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2098 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2099 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2100 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2101 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2102 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2103 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2104 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2105 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2106 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
2107 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2108 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2109 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2110 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2111 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2112 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2113 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2114 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2115 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2116 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2117 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2118 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2119 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2120 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2121 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2122 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2123 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2124 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2125 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2126 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2127 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2128 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2129 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2130 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2131 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2132 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2133 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2134 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2135 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2136 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2137 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2138 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2139 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2140 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2141 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2142 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2143 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2144 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2145 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2146 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2147 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2148 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2149 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2150 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2151 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2152 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2153 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2154 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2155 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2156 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2157 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2159 /* Cirrus Maverick instructions. */
2160 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2161 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2162 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2163 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2164 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2165 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2166 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2167 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2168 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2169 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2170 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2171 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2172 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2173 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2174 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2175 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2176 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2177 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2178 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2179 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2180 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2181 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2182 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2183 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2184 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2185 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2186 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2187 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2188 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2189 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2190 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2191 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2192 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2193 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2194 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2195 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2196 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2197 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2198 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2199 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2200 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2201 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2202 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2203 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2204 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2205 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2206 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2207 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2208 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2209 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2210 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2211 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2212 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2213 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2214 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2215 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2216 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2217 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2218 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2219 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2220 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2221 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2222 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2223 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2224 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2225 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2226 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2227 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2228 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2229 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2230 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2231 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2232 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2233 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2234 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2235 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2238 /* Defines for various bits that we will want to toggle. */
2239 #define INST_IMMEDIATE 0x02000000
2240 #define OFFSET_REG 0x02000000
2241 #define HWOFFSET_IMM 0x00400000
2242 #define SHIFT_BY_REG 0x00000010
2243 #define PRE_INDEX 0x01000000
2244 #define INDEX_UP 0x00800000
2245 #define WRITE_BACK 0x00200000
2246 #define LDM_TYPE_2_OR_3 0x00400000
2248 #define LITERAL_MASK 0xf000f000
2249 #define OPCODE_MASK 0xfe1fffff
2250 #define V4_STR_BIT 0x00000020
2252 #define DATA_OP_SHIFT 21
2254 /* Codes to distinguish the arithmetic instructions. */
2255 #define OPCODE_AND 0
2256 #define OPCODE_EOR 1
2257 #define OPCODE_SUB 2
2258 #define OPCODE_RSB 3
2259 #define OPCODE_ADD 4
2260 #define OPCODE_ADC 5
2261 #define OPCODE_SBC 6
2262 #define OPCODE_RSC 7
2263 #define OPCODE_TST 8
2264 #define OPCODE_TEQ 9
2265 #define OPCODE_CMP 10
2266 #define OPCODE_CMN 11
2267 #define OPCODE_ORR 12
2268 #define OPCODE_MOV 13
2269 #define OPCODE_BIC 14
2270 #define OPCODE_MVN 15
2272 /* Thumb v1 (ARMv4T). */
2273 static void do_t_nop
PARAMS ((char *));
2274 static void do_t_arit
PARAMS ((char *));
2275 static void do_t_add
PARAMS ((char *));
2276 static void do_t_asr
PARAMS ((char *));
2277 static void do_t_branch9
PARAMS ((char *));
2278 static void do_t_branch12
PARAMS ((char *));
2279 static void do_t_branch23
PARAMS ((char *));
2280 static void do_t_bx
PARAMS ((char *));
2281 static void do_t_compare
PARAMS ((char *));
2282 static void do_t_ldmstm
PARAMS ((char *));
2283 static void do_t_ldr
PARAMS ((char *));
2284 static void do_t_ldrb
PARAMS ((char *));
2285 static void do_t_ldrh
PARAMS ((char *));
2286 static void do_t_lds
PARAMS ((char *));
2287 static void do_t_lsl
PARAMS ((char *));
2288 static void do_t_lsr
PARAMS ((char *));
2289 static void do_t_mov
PARAMS ((char *));
2290 static void do_t_push_pop
PARAMS ((char *));
2291 static void do_t_str
PARAMS ((char *));
2292 static void do_t_strb
PARAMS ((char *));
2293 static void do_t_strh
PARAMS ((char *));
2294 static void do_t_sub
PARAMS ((char *));
2295 static void do_t_swi
PARAMS ((char *));
2296 static void do_t_adr
PARAMS ((char *));
2298 /* Thumb v2 (ARMv5T). */
2299 static void do_t_blx
PARAMS ((char *));
2300 static void do_t_bkpt
PARAMS ((char *));
2303 static void do_t_cps
PARAMS ((char *));
2304 static void do_t_cpy
PARAMS ((char *));
2305 static void do_t_setend
PARAMS ((char *));;
2307 #define T_OPCODE_MUL 0x4340
2308 #define T_OPCODE_TST 0x4200
2309 #define T_OPCODE_CMN 0x42c0
2310 #define T_OPCODE_NEG 0x4240
2311 #define T_OPCODE_MVN 0x43c0
2313 #define T_OPCODE_ADD_R3 0x1800
2314 #define T_OPCODE_SUB_R3 0x1a00
2315 #define T_OPCODE_ADD_HI 0x4400
2316 #define T_OPCODE_ADD_ST 0xb000
2317 #define T_OPCODE_SUB_ST 0xb080
2318 #define T_OPCODE_ADD_SP 0xa800
2319 #define T_OPCODE_ADD_PC 0xa000
2320 #define T_OPCODE_ADD_I8 0x3000
2321 #define T_OPCODE_SUB_I8 0x3800
2322 #define T_OPCODE_ADD_I3 0x1c00
2323 #define T_OPCODE_SUB_I3 0x1e00
2325 #define T_OPCODE_ASR_R 0x4100
2326 #define T_OPCODE_LSL_R 0x4080
2327 #define T_OPCODE_LSR_R 0x40c0
2328 #define T_OPCODE_ASR_I 0x1000
2329 #define T_OPCODE_LSL_I 0x0000
2330 #define T_OPCODE_LSR_I 0x0800
2332 #define T_OPCODE_MOV_I8 0x2000
2333 #define T_OPCODE_CMP_I8 0x2800
2334 #define T_OPCODE_CMP_LR 0x4280
2335 #define T_OPCODE_MOV_HR 0x4600
2336 #define T_OPCODE_CMP_HR 0x4500
2338 #define T_OPCODE_LDR_PC 0x4800
2339 #define T_OPCODE_LDR_SP 0x9800
2340 #define T_OPCODE_STR_SP 0x9000
2341 #define T_OPCODE_LDR_IW 0x6800
2342 #define T_OPCODE_STR_IW 0x6000
2343 #define T_OPCODE_LDR_IH 0x8800
2344 #define T_OPCODE_STR_IH 0x8000
2345 #define T_OPCODE_LDR_IB 0x7800
2346 #define T_OPCODE_STR_IB 0x7000
2347 #define T_OPCODE_LDR_RW 0x5800
2348 #define T_OPCODE_STR_RW 0x5000
2349 #define T_OPCODE_LDR_RH 0x5a00
2350 #define T_OPCODE_STR_RH 0x5200
2351 #define T_OPCODE_LDR_RB 0x5c00
2352 #define T_OPCODE_STR_RB 0x5400
2354 #define T_OPCODE_PUSH 0xb400
2355 #define T_OPCODE_POP 0xbc00
2357 #define T_OPCODE_BRANCH 0xe7fe
2359 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2361 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2362 #define THUMB_REG_LO 0x1
2363 #define THUMB_REG_HI 0x2
2364 #define THUMB_REG_ANY 0x3
2366 #define THUMB_H1 0x0080
2367 #define THUMB_H2 0x0040
2373 #define THUMB_MOVE 0
2374 #define THUMB_COMPARE 1
2377 #define THUMB_LOAD 0
2378 #define THUMB_STORE 1
2380 #define THUMB_PP_PC_LR 0x0100
2382 /* These three are used for immediate shifts, do not alter. */
2383 #define THUMB_WORD 2
2384 #define THUMB_HALFWORD 1
2385 #define THUMB_BYTE 0
2389 /* Basic string to match. */
2390 const char * template;
2392 /* Basic instruction code. */
2393 unsigned long value
;
2397 /* Which CPU variants this exists for. */
2398 unsigned long variant
;
2400 /* Function to call to parse args. */
2401 void (* parms
) PARAMS ((char *));
2404 static const struct thumb_opcode tinsns
[] =
2406 /* Thumb v1 (ARMv4T). */
2407 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2408 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2409 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2410 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2411 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2412 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2413 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2414 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2415 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2416 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2417 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2418 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2419 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2420 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2421 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2422 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2423 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2424 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2425 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2426 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2427 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2428 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2429 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2430 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2431 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2432 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2433 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2434 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2435 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2436 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2437 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2438 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2439 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2440 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2441 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2442 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2443 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2444 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2445 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2446 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2447 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2448 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2449 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2450 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2451 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2452 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2453 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2454 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2455 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2456 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2457 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2458 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2459 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2460 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2461 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2463 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2464 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2465 /* Thumb v2 (ARMv5T). */
2466 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2467 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2470 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
2471 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
2472 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
2473 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
2474 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
2475 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
2476 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
2477 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
2478 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
2479 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
2480 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
2483 #define BAD_ARGS _("bad arguments to instruction")
2484 #define BAD_PC _("r15 not allowed here")
2485 #define BAD_COND _("instruction is not conditional")
2486 #define ERR_NO_ACCUM _("acc0 expected")
2488 static struct hash_control
* arm_ops_hsh
= NULL
;
2489 static struct hash_control
* arm_tops_hsh
= NULL
;
2490 static struct hash_control
* arm_cond_hsh
= NULL
;
2491 static struct hash_control
* arm_shift_hsh
= NULL
;
2492 static struct hash_control
* arm_psr_hsh
= NULL
;
2494 /* This table describes all the machine specific pseudo-ops the assembler
2495 has to support. The fields are:
2496 pseudo-op name without dot
2497 function to call to execute this pseudo-op
2498 Integer arg to pass to the function. */
2500 static void s_req
PARAMS ((int));
2501 static void s_unreq
PARAMS ((int));
2502 static void s_align
PARAMS ((int));
2503 static void s_bss
PARAMS ((int));
2504 static void s_even
PARAMS ((int));
2505 static void s_ltorg
PARAMS ((int));
2506 static void s_arm
PARAMS ((int));
2507 static void s_thumb
PARAMS ((int));
2508 static void s_code
PARAMS ((int));
2509 static void s_force_thumb
PARAMS ((int));
2510 static void s_thumb_func
PARAMS ((int));
2511 static void s_thumb_set
PARAMS ((int));
2513 static void s_arm_elf_cons
PARAMS ((int));
2516 static int my_get_expression
PARAMS ((expressionS
*, char **));
2518 const pseudo_typeS md_pseudo_table
[] =
2520 /* Never called because '.req' does not start a line. */
2521 { "req", s_req
, 0 },
2522 { "unreq", s_unreq
, 0 },
2523 { "bss", s_bss
, 0 },
2524 { "align", s_align
, 0 },
2525 { "arm", s_arm
, 0 },
2526 { "thumb", s_thumb
, 0 },
2527 { "code", s_code
, 0 },
2528 { "force_thumb", s_force_thumb
, 0 },
2529 { "thumb_func", s_thumb_func
, 0 },
2530 { "thumb_set", s_thumb_set
, 0 },
2531 { "even", s_even
, 0 },
2532 { "ltorg", s_ltorg
, 0 },
2533 { "pool", s_ltorg
, 0 },
2535 { "word", s_arm_elf_cons
, 4 },
2536 { "long", s_arm_elf_cons
, 4 },
2540 { "extend", float_cons
, 'x' },
2541 { "ldouble", float_cons
, 'x' },
2542 { "packed", float_cons
, 'p' },
2546 /* Other internal functions. */
2547 static int arm_parse_extension
PARAMS ((char *, int *));
2548 static int arm_parse_cpu
PARAMS ((char *));
2549 static int arm_parse_arch
PARAMS ((char *));
2550 static int arm_parse_fpu
PARAMS ((char *));
2551 static int arm_parse_float_abi
PARAMS ((char *));
2552 #if 0 /* Suppressed - for now. */
2553 #if defined OBJ_COFF || defined OBJ_ELF
2554 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2558 /* Stuff needed to resolve the label ambiguity
2568 symbolS
* last_label_seen
;
2569 static int label_is_thumb_function_name
= FALSE
;
2571 /* Literal Pool stuff. */
2573 #define MAX_LITERAL_POOL_SIZE 1024
2575 /* Literal pool structure. Held on a per-section
2576 and per-sub-section basis. */
2577 typedef struct literal_pool
2579 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2580 unsigned int next_free_entry
;
2584 subsegT sub_section
;
2585 struct literal_pool
* next
;
2588 /* Pointer to a linked list of literal pools. */
2589 literal_pool
* list_of_pools
= NULL
;
2591 static literal_pool
* find_literal_pool
PARAMS ((void));
2592 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2594 static literal_pool
*
2595 find_literal_pool ()
2597 literal_pool
* pool
;
2599 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2601 if (pool
->section
== now_seg
2602 && pool
->sub_section
== now_subseg
)
2609 static literal_pool
*
2610 find_or_make_literal_pool ()
2612 /* Next literal pool ID number. */
2613 static unsigned int latest_pool_num
= 1;
2614 literal_pool
* pool
;
2616 pool
= find_literal_pool ();
2620 /* Create a new pool. */
2621 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2625 pool
->next_free_entry
= 0;
2626 pool
->section
= now_seg
;
2627 pool
->sub_section
= now_subseg
;
2628 pool
->next
= list_of_pools
;
2629 pool
->symbol
= NULL
;
2631 /* Add it to the list. */
2632 list_of_pools
= pool
;
2635 /* New pools, and emptied pools, will have a NULL symbol. */
2636 if (pool
->symbol
== NULL
)
2638 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2639 (valueT
) 0, &zero_address_frag
);
2640 pool
->id
= latest_pool_num
++;
2647 /* Add the literal in the global 'inst'
2648 structure to the relevent literal pool. */
2652 literal_pool
* pool
;
2655 pool
= find_or_make_literal_pool ();
2657 /* Check if this literal value is already in the pool. */
2658 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2660 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2661 && (inst
.reloc
.exp
.X_op
== O_constant
)
2662 && (pool
->literals
[entry
].X_add_number
2663 == inst
.reloc
.exp
.X_add_number
)
2664 && (pool
->literals
[entry
].X_unsigned
2665 == inst
.reloc
.exp
.X_unsigned
))
2668 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2669 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2670 && (pool
->literals
[entry
].X_add_number
2671 == inst
.reloc
.exp
.X_add_number
)
2672 && (pool
->literals
[entry
].X_add_symbol
2673 == inst
.reloc
.exp
.X_add_symbol
)
2674 && (pool
->literals
[entry
].X_op_symbol
2675 == inst
.reloc
.exp
.X_op_symbol
))
2679 /* Do we need to create a new entry? */
2680 if (entry
== pool
->next_free_entry
)
2682 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2684 inst
.error
= _("literal pool overflow");
2688 pool
->literals
[entry
] = inst
.reloc
.exp
;
2689 pool
->next_free_entry
+= 1;
2692 inst
.reloc
.exp
.X_op
= O_symbol
;
2693 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2694 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2699 /* Can't use symbol_new here, so have to create a symbol and then at
2700 a later date assign it a value. Thats what these functions do. */
2703 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2705 const char * name
; /* It is copied, the caller can modify. */
2706 segT segment
; /* Segment identifier (SEG_<something>). */
2707 valueT valu
; /* Symbol value. */
2708 fragS
* frag
; /* Associated fragment. */
2710 unsigned int name_length
;
2711 char * preserved_copy_of_name
;
2713 name_length
= strlen (name
) + 1; /* +1 for \0. */
2714 obstack_grow (¬es
, name
, name_length
);
2715 preserved_copy_of_name
= obstack_finish (¬es
);
2716 #ifdef STRIP_UNDERSCORE
2717 if (preserved_copy_of_name
[0] == '_')
2718 preserved_copy_of_name
++;
2721 #ifdef tc_canonicalize_symbol_name
2722 preserved_copy_of_name
=
2723 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2726 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2728 S_SET_SEGMENT (symbolP
, segment
);
2729 S_SET_VALUE (symbolP
, valu
);
2730 symbol_clear_list_pointers (symbolP
);
2732 symbol_set_frag (symbolP
, frag
);
2734 /* Link to end of symbol chain. */
2736 extern int symbol_table_frozen
;
2737 if (symbol_table_frozen
)
2741 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2743 obj_symbol_new_hook (symbolP
);
2745 #ifdef tc_symbol_new_hook
2746 tc_symbol_new_hook (symbolP
);
2750 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2751 #endif /* DEBUG_SYMS */
2754 /* Check that an immediate is valid.
2755 If so, convert it to the right format. */
2758 validate_immediate (val
)
2764 #define rotate_left(v, n) (v << n | v >> (32 - n))
2766 for (i
= 0; i
< 32; i
+= 2)
2767 if ((a
= rotate_left (val
, i
)) <= 0xff)
2768 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2773 /* Check to see if an immediate can be computed as two separate immediate
2774 values, added together. We already know that this value cannot be
2775 computed by just one ARM instruction. */
2778 validate_immediate_twopart (val
, highpart
)
2780 unsigned int * highpart
;
2785 for (i
= 0; i
< 32; i
+= 2)
2786 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2792 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2794 else if (a
& 0xff0000)
2798 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2802 assert (a
& 0xff000000);
2803 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2806 return (a
& 0xff) | (i
<< 7);
2813 validate_offset_imm (val
, hwse
)
2817 if ((hwse
&& val
> 255) || val
> 4095)
2831 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2832 (This text is taken from version B-02 of the spec):
2834 4.4.7 Mapping and tagging symbols
2836 A section of an ARM ELF file can contain a mixture of ARM code,
2837 Thumb code, and data. There are inline transitions between code
2838 and data at literal pool boundaries. There can also be inline
2839 transitions between ARM code and Thumb code, for example in
2840 ARM-Thumb inter-working veneers. Linkers, machine-level
2841 debuggers, profiling tools, and disassembly tools need to map
2842 images accurately. For example, setting an ARM breakpoint on a
2843 Thumb location, or in a literal pool, can crash the program
2844 being debugged, ruining the debugging session.
2846 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2847 tagged (see section 4.4.7.2 below) using local symbols (with
2848 binding STB_LOCAL). To assist consumers, mapping and tagging
2849 symbols should be collated first in the symbol table, before
2850 other symbols with binding STB_LOCAL.
2852 To allow properly collated mapping and tagging symbols to be
2853 skipped by consumers that have no interest in them, the first
2854 such symbol should have the name $m and its st_value field equal
2855 to the total number of mapping and tagging symbols (including
2856 the $m) in the symbol table.
2858 4.4.7.1 Mapping symbols
2860 $a Labels the first byte of a sequence of ARM instructions.
2861 Its type is STT_FUNC.
2863 $d Labels the first byte of a sequence of data items.
2864 Its type is STT_OBJECT.
2866 $t Labels the first byte of a sequence of Thumb instructions.
2867 Its type is STT_FUNC.
2869 This list of mapping symbols may be extended in the future.
2871 Section-relative mapping symbols
2873 Mapping symbols defined in a section define a sequence of
2874 half-open address intervals that cover the address range of the
2875 section. Each interval starts at the address defined by a
2876 mapping symbol, and continues up to, but not including, the
2877 address defined by the next (in address order) mapping symbol or
2878 the end of the section. A corollary is that there must be a
2879 mapping symbol defined at the beginning of each section.
2880 Consumers can ignore the size of a section-relative mapping
2881 symbol. Producers can set it to 0.
2883 Absolute mapping symbols
2885 Because of the need to crystallize a Thumb address with the
2886 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2887 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2890 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2891 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2892 where [x, y) denotes the half-open address range from x,
2893 inclusive, to y, exclusive.
2895 In the absence of a mapping symbol, a consumer can interpret a
2896 function symbol with an odd value as the Thumb code address
2897 obtained by clearing the least significant bit of the
2898 value. This interpretation is deprecated, and it may not work in
2901 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2902 the EABI (which is still under development), so they are not
2903 implemented here. */
2906 mapping_state (enum mstate state
)
2908 static enum mstate mapstate
= MAP_DATA
;
2910 const char * symname
;
2913 if (mapstate
== state
)
2914 /* The mapping symbol has already been emitted.
2915 There is nothing else to do. */
2928 type
= BSF_FUNCTION
;
2932 type
= BSF_FUNCTION
;
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 if (flags
& SEC_CODE
)
2981 mapping_state (MAP_THUMB
);
2983 mapping_state (MAP_ARM
);
2986 /* This section does not contain code. Therefore it must contain data. */
2987 mapping_state (MAP_DATA
);
2990 #define mapping_state(a)
2991 #endif /* OBJ_ELF */
2996 int a ATTRIBUTE_UNUSED
;
2998 as_bad (_("invalid syntax for .req directive"));
3001 /* The .unreq directive deletes an alias which was previously defined
3002 by .req. For example:
3008 s_unreq (int a ATTRIBUTE_UNUSED
)
3013 skip_whitespace (input_line_pointer
);
3014 name
= input_line_pointer
;
3016 while (*input_line_pointer
!= 0
3017 && *input_line_pointer
!= ' '
3018 && *input_line_pointer
!= '\n')
3019 ++input_line_pointer
;
3021 saved_char
= *input_line_pointer
;
3022 *input_line_pointer
= 0;
3026 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
3028 if (req_type
!= REG_TYPE_MAX
)
3030 char *temp_name
= name
;
3031 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
3035 struct reg_entry
*req_entry
;
3037 /* Check to see if this alias is a builtin one. */
3038 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
3041 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
3042 else if (req_entry
->builtin
)
3043 /* FIXME: We are deleting a built in register alias which
3044 points to a const data structure, so we only need to
3045 free up the memory used by the key in the hash table.
3046 Unfortunately we have not recorded this value, so this
3047 is a memory leak. */
3048 /* FIXME: Should we issue a warning message ? */
3052 /* Deleting a user defined alias. We need to free the
3053 key and the value, but fortunately the key is the same
3054 as the value->name field. */
3055 free ((char *) req_entry
->name
);
3060 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3063 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3066 as_bad (_("invalid syntax for .unreq directive"));
3068 *input_line_pointer
= saved_char
;
3069 demand_empty_rest_of_line ();
3074 int ignore ATTRIBUTE_UNUSED
;
3076 /* We don't support putting frags in the BSS segment, we fake it by
3077 marking in_bss, then looking at s_skip for clues. */
3078 subseg_set (bss_section
, 0);
3079 demand_empty_rest_of_line ();
3080 mapping_state (MAP_DATA
);
3085 int ignore ATTRIBUTE_UNUSED
;
3087 /* Never make frag if expect extra pass. */
3089 frag_align (1, 0, 0);
3091 record_alignment (now_seg
, 1);
3093 demand_empty_rest_of_line ();
3098 int ignored ATTRIBUTE_UNUSED
;
3101 literal_pool
* pool
;
3104 pool
= find_literal_pool ();
3106 || pool
->symbol
== NULL
3107 || pool
->next_free_entry
== 0)
3110 /* Align pool as you have word accesses.
3111 Only make a frag if we have to. */
3113 frag_align (2, 0, 0);
3115 record_alignment (now_seg
, 2);
3117 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3119 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3120 (valueT
) frag_now_fix (), frag_now
);
3121 symbol_table_insert (pool
->symbol
);
3123 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3125 #if defined OBJ_COFF || defined OBJ_ELF
3126 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3129 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3130 /* First output the expression in the instruction to the pool. */
3131 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3133 /* Mark the pool as empty. */
3134 pool
->next_free_entry
= 0;
3135 pool
->symbol
= NULL
;
3138 /* Same as s_align_ptwo but align 0 => align 2. */
3142 int unused ATTRIBUTE_UNUSED
;
3145 register long temp_fill
;
3146 long max_alignment
= 15;
3148 temp
= get_absolute_expression ();
3149 if (temp
> max_alignment
)
3150 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3153 as_bad (_("alignment negative. 0 assumed."));
3157 if (*input_line_pointer
== ',')
3159 input_line_pointer
++;
3160 temp_fill
= get_absolute_expression ();
3168 /* Only make a frag if we HAVE to. */
3169 if (temp
&& !need_pass_2
)
3170 frag_align (temp
, (int) temp_fill
, 0);
3171 demand_empty_rest_of_line ();
3173 record_alignment (now_seg
, temp
);
3177 s_force_thumb (ignore
)
3178 int ignore ATTRIBUTE_UNUSED
;
3180 /* If we are not already in thumb mode go into it, EVEN if
3181 the target processor does not support thumb instructions.
3182 This is used by gcc/config/arm/lib1funcs.asm for example
3183 to compile interworking support functions even if the
3184 target processor should not support interworking. */
3189 record_alignment (now_seg
, 1);
3192 demand_empty_rest_of_line ();
3196 s_thumb_func (ignore
)
3197 int ignore ATTRIBUTE_UNUSED
;
3202 /* The following label is the name/address of the start of a Thumb function.
3203 We need to know this for the interworking support. */
3204 label_is_thumb_function_name
= TRUE
;
3206 demand_empty_rest_of_line ();
3209 /* Perform a .set directive, but also mark the alias as
3210 being a thumb function. */
3216 /* XXX the following is a duplicate of the code for s_set() in read.c
3217 We cannot just call that code as we need to get at the symbol that
3219 register char * name
;
3220 register char delim
;
3221 register char * end_name
;
3222 register symbolS
* symbolP
;
3224 /* Especial apologies for the random logic:
3225 This just grew, and could be parsed much more simply!
3227 name
= input_line_pointer
;
3228 delim
= get_symbol_end ();
3229 end_name
= input_line_pointer
;
3234 if (*input_line_pointer
!= ',')
3237 as_bad (_("expected comma after name \"%s\""), name
);
3239 ignore_rest_of_line ();
3243 input_line_pointer
++;
3246 if (name
[0] == '.' && name
[1] == '\0')
3248 /* XXX - this should not happen to .thumb_set. */
3252 if ((symbolP
= symbol_find (name
)) == NULL
3253 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3256 /* When doing symbol listings, play games with dummy fragments living
3257 outside the normal fragment chain to record the file and line info
3259 if (listing
& LISTING_SYMBOLS
)
3261 extern struct list_info_struct
* listing_tail
;
3262 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3264 memset (dummy_frag
, 0, sizeof (fragS
));
3265 dummy_frag
->fr_type
= rs_fill
;
3266 dummy_frag
->line
= listing_tail
;
3267 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3268 dummy_frag
->fr_symbol
= symbolP
;
3272 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3275 /* "set" symbols are local unless otherwise specified. */
3276 SF_SET_LOCAL (symbolP
);
3277 #endif /* OBJ_COFF */
3278 } /* Make a new symbol. */
3280 symbol_table_insert (symbolP
);
3285 && S_IS_DEFINED (symbolP
)
3286 && S_GET_SEGMENT (symbolP
) != reg_section
)
3287 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3289 pseudo_set (symbolP
);
3291 demand_empty_rest_of_line ();
3293 /* XXX Now we come to the Thumb specific bit of code. */
3295 THUMB_SET_FUNC (symbolP
, 1);
3296 ARM_SET_THUMB (symbolP
, 1);
3297 #if defined OBJ_ELF || defined OBJ_COFF
3298 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3303 opcode_select (width
)
3311 if (! (cpu_variant
& ARM_EXT_V4T
))
3312 as_bad (_("selected processor does not support THUMB opcodes"));
3315 /* No need to force the alignment, since we will have been
3316 coming from ARM mode, which is word-aligned. */
3317 record_alignment (now_seg
, 1);
3319 mapping_state (MAP_THUMB
);
3325 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3326 as_bad (_("selected processor does not support ARM opcodes"));
3331 frag_align (2, 0, 0);
3333 record_alignment (now_seg
, 1);
3335 mapping_state (MAP_ARM
);
3339 as_bad (_("invalid instruction size selected (%d)"), width
);
3345 int ignore ATTRIBUTE_UNUSED
;
3348 demand_empty_rest_of_line ();
3353 int ignore ATTRIBUTE_UNUSED
;
3356 demand_empty_rest_of_line ();
3361 int unused ATTRIBUTE_UNUSED
;
3365 temp
= get_absolute_expression ();
3370 opcode_select (temp
);
3374 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3382 skip_whitespace (str
);
3384 if (*str
!= '\0' && !inst
.error
)
3385 inst
.error
= _("garbage following instruction");
3389 skip_past_comma (str
)
3392 char * p
= * str
, c
;
3395 while ((c
= *p
) == ' ' || c
== ',')
3398 if (c
== ',' && comma
++)
3406 return comma
? SUCCESS
: FAIL
;
3409 /* A standard register must be given at this point.
3410 SHIFT is the place to put it in inst.instruction.
3411 Restores input start point on error.
3412 Returns the reg#, or FAIL. */
3415 reg_required_here (str
, shift
)
3419 static char buff
[128]; /* XXX */
3421 char * start
= * str
;
3423 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3426 inst
.instruction
|= reg
<< shift
;
3430 /* Restore the start point, we may have got a reg of the wrong class. */
3433 /* In the few cases where we might be able to accept something else
3434 this error can be overridden. */
3435 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3441 /* A Intel Wireless MMX technology register
3442 must be given at this point.
3443 Shift is the place to put it in inst.instruction.
3444 Restores input start point on err.
3445 Returns the reg#, or FAIL. */
3448 wreg_required_here (str
, shift
, reg_type
)
3451 enum wreg_type reg_type
;
3453 static char buff
[128];
3455 char * start
= *str
;
3457 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3459 if (wr_register (reg
)
3460 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3463 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3466 else if (wc_register (reg
)
3467 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3470 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3473 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3476 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3481 /* Restore the start point, we may have got a reg of the wrong class. */
3484 /* In the few cases where we might be able to accept
3485 something else this error can be overridden. */
3486 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3492 static const struct asm_psr
*
3494 register char ** ccp
;
3496 char * start
= * ccp
;
3499 const struct asm_psr
* psr
;
3503 /* Skip to the end of the next word in the input stream. */
3508 while (ISALPHA (c
) || c
== '_');
3510 /* Terminate the word. */
3513 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3514 feature for ease of use and backwards compatibility. */
3515 if (!strncmp (start
, "cpsr", 4))
3516 strncpy (start
, "CPSR", 4);
3517 else if (!strncmp (start
, "spsr", 4))
3518 strncpy (start
, "SPSR", 4);
3520 /* Now locate the word in the psr hash table. */
3521 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3523 /* Restore the input stream. */
3526 /* If we found a valid match, advance the
3527 stream pointer past the end of the word. */
3533 /* Parse the input looking for a PSR flag. */
3536 psr_required_here (str
)
3539 char * start
= * str
;
3540 const struct asm_psr
* psr
;
3542 psr
= arm_psr_parse (str
);
3546 /* If this is the SPSR that is being modified, set the R bit. */
3548 inst
.instruction
|= SPSR_BIT
;
3550 /* Set the psr flags in the MSR instruction. */
3551 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3556 /* In the few cases where we might be able to accept
3557 something else this error can be overridden. */
3558 inst
.error
= _("flag for {c}psr instruction expected");
3560 /* Restore the start point. */
3566 co_proc_number (str
)
3569 int processor
, pchar
;
3572 skip_whitespace (*str
);
3575 /* The data sheet seems to imply that just a number on its own is valid
3576 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3578 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3584 if (pchar
>= '0' && pchar
<= '9')
3586 processor
= pchar
- '0';
3587 if (**str
>= '0' && **str
<= '9')
3589 processor
= processor
* 10 + *(*str
)++ - '0';
3592 inst
.error
= _("illegal co-processor number");
3599 inst
.error
= _("bad or missing co-processor number");
3604 inst
.instruction
|= processor
<< 8;
3609 cp_opc_expr (str
, where
, length
)
3616 skip_whitespace (* str
);
3618 memset (&expr
, '\0', sizeof (expr
));
3620 if (my_get_expression (&expr
, str
))
3622 if (expr
.X_op
!= O_constant
)
3624 inst
.error
= _("bad or missing expression");
3628 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3630 inst
.error
= _("immediate co-processor expression too large");
3634 inst
.instruction
|= expr
.X_add_number
<< where
;
3639 cp_reg_required_here (str
, where
)
3644 char * start
= *str
;
3646 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3648 inst
.instruction
|= reg
<< where
;
3652 /* In the few cases where we might be able to accept something else
3653 this error can be overridden. */
3654 inst
.error
= _("co-processor register expected");
3656 /* Restore the start point. */
3662 fp_reg_required_here (str
, where
)
3667 char * start
= * str
;
3669 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3671 inst
.instruction
|= reg
<< where
;
3675 /* In the few cases where we might be able to accept something else
3676 this error can be overridden. */
3677 inst
.error
= _("floating point register expected");
3679 /* Restore the start point. */
3685 cp_address_offset (str
)
3690 skip_whitespace (* str
);
3692 if (! is_immediate_prefix (**str
))
3694 inst
.error
= _("immediate expression expected");
3700 if (my_get_expression (& inst
.reloc
.exp
, str
))
3703 if (inst
.reloc
.exp
.X_op
== O_constant
)
3705 offset
= inst
.reloc
.exp
.X_add_number
;
3709 inst
.error
= _("co-processor address must be word aligned");
3713 if (offset
> 1023 || offset
< -1023)
3715 inst
.error
= _("offset too large");
3720 inst
.instruction
|= INDEX_UP
;
3724 inst
.instruction
|= offset
>> 2;
3727 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3733 cp_address_required_here (str
, wb_ok
)
3746 skip_whitespace (p
);
3748 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3751 skip_whitespace (p
);
3757 skip_whitespace (p
);
3761 /* As an extension to the official ARM syntax we allow:
3765 as a short hand for:
3768 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3773 if (skip_past_comma (& p
) == FAIL
)
3775 inst
.error
= _("comma expected after closing square bracket");
3779 skip_whitespace (p
);
3786 write_back
= WRITE_BACK
;
3790 inst
.error
= _("pc may not be used in post-increment");
3794 if (cp_address_offset (& p
) == FAIL
)
3798 pre_inc
= PRE_INDEX
| INDEX_UP
;
3804 /* [Rn], {<expr>} */
3807 skip_whitespace (p
);
3809 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3812 if (inst
.reloc
.exp
.X_op
== O_constant
)
3814 option
= inst
.reloc
.exp
.X_add_number
;
3816 if (option
> 255 || option
< 0)
3818 inst
.error
= _("'option' field too large");
3822 skip_whitespace (p
);
3826 inst
.error
= _("'}' expected at end of 'option' field");
3832 inst
.instruction
|= option
;
3833 inst
.instruction
|= INDEX_UP
;
3838 inst
.error
= _("non-constant expressions for 'option' field not supported");
3844 inst
.error
= _("# or { expected after comma");
3850 /* '['Rn, #expr']'[!] */
3852 if (skip_past_comma (& p
) == FAIL
)
3854 inst
.error
= _("pre-indexed expression expected");
3858 pre_inc
= PRE_INDEX
;
3860 if (cp_address_offset (& p
) == FAIL
)
3863 skip_whitespace (p
);
3867 inst
.error
= _("missing ]");
3871 skip_whitespace (p
);
3873 if (wb_ok
&& *p
== '!')
3877 inst
.error
= _("pc may not be used with write-back");
3882 write_back
= WRITE_BACK
;
3888 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3891 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3892 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3893 inst
.reloc
.pc_rel
= 1;
3894 inst
.instruction
|= (REG_PC
<< 16);
3895 pre_inc
= PRE_INDEX
;
3898 inst
.instruction
|= write_back
| pre_inc
;
3904 cp_byte_address_offset (str
)
3909 skip_whitespace (* str
);
3911 if (! is_immediate_prefix (**str
))
3913 inst
.error
= _("immediate expression expected");
3919 if (my_get_expression (& inst
.reloc
.exp
, str
))
3922 if (inst
.reloc
.exp
.X_op
== O_constant
)
3924 offset
= inst
.reloc
.exp
.X_add_number
;
3926 if (offset
> 255 || offset
< -255)
3928 inst
.error
= _("offset too large");
3933 inst
.instruction
|= INDEX_UP
;
3937 inst
.instruction
|= offset
;
3940 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3946 cp_byte_address_required_here (str
)
3958 skip_whitespace (p
);
3960 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3963 skip_whitespace (p
);
3969 if (skip_past_comma (& p
) == SUCCESS
)
3972 write_back
= WRITE_BACK
;
3976 inst
.error
= _("pc may not be used in post-increment");
3980 if (cp_byte_address_offset (& p
) == FAIL
)
3984 pre_inc
= PRE_INDEX
| INDEX_UP
;
3988 /* '['Rn, #expr']'[!] */
3990 if (skip_past_comma (& p
) == FAIL
)
3992 inst
.error
= _("pre-indexed expression expected");
3996 pre_inc
= PRE_INDEX
;
3998 if (cp_byte_address_offset (& p
) == FAIL
)
4001 skip_whitespace (p
);
4005 inst
.error
= _("missing ]");
4009 skip_whitespace (p
);
4015 inst
.error
= _("pc may not be used with write-back");
4020 write_back
= WRITE_BACK
;
4026 if (my_get_expression (&inst
.reloc
.exp
, &p
))
4029 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
4030 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4031 inst
.reloc
.pc_rel
= 1;
4032 inst
.instruction
|= (REG_PC
<< 16);
4033 pre_inc
= PRE_INDEX
;
4036 inst
.instruction
|= write_back
| pre_inc
;
4045 /* Do nothing really. */
4055 /* Only one syntax. */
4056 skip_whitespace (str
);
4058 if (reg_required_here (&str
, 12) == FAIL
)
4060 inst
.error
= BAD_ARGS
;
4064 if (skip_past_comma (&str
) == FAIL
)
4066 inst
.error
= _("comma expected after register name");
4070 skip_whitespace (str
);
4072 if ( strcmp (str
, "CPSR") == 0
4073 || strcmp (str
, "SPSR") == 0
4074 /* Lower case versions for backwards compatibility. */
4075 || strcmp (str
, "cpsr") == 0
4076 || strcmp (str
, "spsr") == 0)
4079 /* This is for backwards compatibility with older toolchains. */
4080 else if ( strcmp (str
, "cpsr_all") == 0
4081 || strcmp (str
, "spsr_all") == 0)
4085 inst
.error
= _("CPSR or SPSR expected");
4089 if (* str
== 's' || * str
== 'S')
4090 inst
.instruction
|= SPSR_BIT
;
4096 /* Two possible forms:
4097 "{C|S}PSR_<field>, Rm",
4098 "{C|S}PSR_f, #expression". */
4104 skip_whitespace (str
);
4106 if (psr_required_here (& str
) == FAIL
)
4109 if (skip_past_comma (& str
) == FAIL
)
4111 inst
.error
= _("comma missing after psr flags");
4115 skip_whitespace (str
);
4117 if (reg_required_here (& str
, 0) != FAIL
)
4124 if (! is_immediate_prefix (* str
))
4127 _("only a register or immediate value can follow a psr flag");
4134 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4137 _("only a register or immediate value can follow a psr flag");
4141 #if 0 /* The first edition of the ARM architecture manual stated that
4142 writing anything other than the flags with an immediate operation
4143 had UNPREDICTABLE effects. This constraint was removed in the
4144 second edition of the specification. */
4145 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4146 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4148 inst
.error
= _("immediate value cannot be used to set this field");
4153 inst
.instruction
|= INST_IMMEDIATE
;
4155 if (inst
.reloc
.exp
.X_add_symbol
)
4157 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4158 inst
.reloc
.pc_rel
= 0;
4162 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4164 if (value
== (unsigned) FAIL
)
4166 inst
.error
= _("invalid constant");
4170 inst
.instruction
|= value
;
4177 /* Long Multiply Parser
4178 UMULL RdLo, RdHi, Rm, Rs
4179 SMULL RdLo, RdHi, Rm, Rs
4180 UMLAL RdLo, RdHi, Rm, Rs
4181 SMLAL RdLo, RdHi, Rm, Rs. */
4187 int rdlo
, rdhi
, rm
, rs
;
4189 /* Only one format "rdlo, rdhi, rm, rs". */
4190 skip_whitespace (str
);
4192 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4194 inst
.error
= BAD_ARGS
;
4198 if (skip_past_comma (&str
) == FAIL
4199 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4201 inst
.error
= BAD_ARGS
;
4205 if (skip_past_comma (&str
) == FAIL
4206 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4208 inst
.error
= BAD_ARGS
;
4212 /* rdhi, rdlo and rm must all be different. */
4213 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4214 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4216 if (skip_past_comma (&str
) == FAIL
4217 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4219 inst
.error
= BAD_ARGS
;
4223 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4225 inst
.error
= BAD_PC
;
4238 /* Only one format "rd, rm, rs". */
4239 skip_whitespace (str
);
4241 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4243 inst
.error
= BAD_ARGS
;
4249 inst
.error
= BAD_PC
;
4253 if (skip_past_comma (&str
) == FAIL
4254 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4256 inst
.error
= BAD_ARGS
;
4262 inst
.error
= BAD_PC
;
4267 as_tsktsk (_("rd and rm should be different in mul"));
4269 if (skip_past_comma (&str
) == FAIL
4270 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4272 inst
.error
= BAD_ARGS
;
4278 inst
.error
= BAD_PC
;
4291 /* Only one format "rd, rm, rs, rn". */
4292 skip_whitespace (str
);
4294 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4296 inst
.error
= BAD_ARGS
;
4302 inst
.error
= BAD_PC
;
4306 if (skip_past_comma (&str
) == FAIL
4307 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4309 inst
.error
= BAD_ARGS
;
4315 inst
.error
= BAD_PC
;
4320 as_tsktsk (_("rd and rm should be different in mla"));
4322 if (skip_past_comma (&str
) == FAIL
4323 || (rd
= reg_required_here (&str
, 8)) == FAIL
4324 || skip_past_comma (&str
) == FAIL
4325 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4327 inst
.error
= BAD_ARGS
;
4331 if (rd
== REG_PC
|| rm
== REG_PC
)
4333 inst
.error
= BAD_PC
;
4340 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4341 Advances *str to the next non-alphanumeric.
4342 Returns 0, or else FAIL (in which case sets inst.error).
4344 (In a future XScale, there may be accumulators other than zero.
4345 At that time this routine and its callers can be upgraded to suit.) */
4348 accum0_required_here (str
)
4351 static char buff
[128]; /* Note the address is taken. Hence, static. */
4354 int result
= 0; /* The accum number. */
4356 skip_whitespace (p
);
4358 *str
= p
; /* Advance caller's string pointer too. */
4363 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4365 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4367 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4372 *p
= c
; /* Unzap. */
4373 *str
= p
; /* Caller's string pointer to after match. */
4377 /* Expects **str -> after a comma. May be leading blanks.
4378 Advances *str, recognizing a load mode, and setting inst.instruction.
4379 Returns rn, or else FAIL (in which case may set inst.error
4380 and not advance str)
4382 Note: doesn't know Rd, so no err checks that require such knowledge. */
4385 ld_mode_required_here (string
)
4388 char * str
= * string
;
4392 skip_whitespace (str
);
4398 skip_whitespace (str
);
4400 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4403 skip_whitespace (str
);
4409 if (skip_past_comma (& str
) == SUCCESS
)
4411 /* [Rn],... (post inc) */
4412 if (ldst_extend_v4 (&str
) == FAIL
)
4417 skip_whitespace (str
);
4422 inst
.instruction
|= WRITE_BACK
;
4425 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4431 if (skip_past_comma (& str
) == FAIL
)
4433 inst
.error
= _("pre-indexed expression expected");
4439 if (ldst_extend_v4 (&str
) == FAIL
)
4442 skip_whitespace (str
);
4444 if (* str
++ != ']')
4446 inst
.error
= _("missing ]");
4450 skip_whitespace (str
);
4455 inst
.instruction
|= WRITE_BACK
;
4459 else if (* str
== '=') /* ldr's "r,=label" syntax */
4460 /* We should never reach here, because <text> = <expression> is
4461 caught gas/read.c read_a_source_file() as a .set operation. */
4463 else /* PC +- 8 bit immediate offset. */
4465 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4468 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4469 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4470 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4471 inst
.reloc
.pc_rel
= 1;
4472 inst
.instruction
|= (REG_PC
<< 16);
4478 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4484 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4485 SMLAxy{cond} Rd,Rm,Rs,Rn
4486 SMLAWy{cond} Rd,Rm,Rs,Rn
4487 Error if any register is R15. */
4495 skip_whitespace (str
);
4497 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4498 || skip_past_comma (& str
) == FAIL
4499 || (rm
= reg_required_here (& str
, 0)) == FAIL
4500 || skip_past_comma (& str
) == FAIL
4501 || (rs
= reg_required_here (& str
, 8)) == FAIL
4502 || skip_past_comma (& str
) == FAIL
4503 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4504 inst
.error
= BAD_ARGS
;
4506 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4507 inst
.error
= BAD_PC
;
4513 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4514 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4515 Error if any register is R15.
4516 Warning if Rdlo == Rdhi. */
4522 int rdlo
, rdhi
, rm
, rs
;
4524 skip_whitespace (str
);
4526 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4527 || skip_past_comma (& str
) == FAIL
4528 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4529 || skip_past_comma (& str
) == FAIL
4530 || (rm
= reg_required_here (& str
, 0)) == FAIL
4531 || skip_past_comma (& str
) == FAIL
4532 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4534 inst
.error
= BAD_ARGS
;
4538 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4540 inst
.error
= BAD_PC
;
4545 as_tsktsk (_("rdhi and rdlo must be different"));
4550 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4551 SMULxy{cond} Rd,Rm,Rs
4552 Error if any register is R15. */
4560 skip_whitespace (str
);
4562 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4563 || skip_past_comma (& str
) == FAIL
4564 || (rm
= reg_required_here (& str
, 0)) == FAIL
4565 || skip_past_comma (& str
) == FAIL
4566 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4567 inst
.error
= BAD_ARGS
;
4569 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4570 inst
.error
= BAD_PC
;
4576 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4577 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4578 Error if any register is R15. */
4586 skip_whitespace (str
);
4588 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4589 || skip_past_comma (& str
) == FAIL
4590 || (rm
= reg_required_here (& str
, 0)) == FAIL
4591 || skip_past_comma (& str
) == FAIL
4592 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4593 inst
.error
= BAD_ARGS
;
4595 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4596 inst
.error
= BAD_PC
;
4602 /* ARM V5E (el Segundo)
4603 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4604 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4606 These are equivalent to the XScale instructions MAR and MRA,
4607 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4609 Result unpredicatable if Rd or Rn is R15. */
4617 skip_whitespace (str
);
4619 if (co_proc_number (& str
) == FAIL
)
4622 inst
.error
= BAD_ARGS
;
4626 if (skip_past_comma (& str
) == FAIL
4627 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4630 inst
.error
= BAD_ARGS
;
4634 if (skip_past_comma (& str
) == FAIL
4635 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4638 inst
.error
= BAD_ARGS
;
4642 if (skip_past_comma (& str
) == FAIL
4643 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4646 inst
.error
= BAD_ARGS
;
4650 /* Unpredictable result if rd or rn is R15. */
4651 if (rd
== REG_PC
|| rn
== REG_PC
)
4653 (_("Warning: instruction unpredictable when using r15"));
4655 if (skip_past_comma (& str
) == FAIL
4656 || cp_reg_required_here (& str
, 0) == FAIL
)
4659 inst
.error
= BAD_ARGS
;
4666 /* ARM V5 count-leading-zeroes instruction (argument parse)
4667 CLZ{<cond>} <Rd>, <Rm>
4668 Condition defaults to COND_ALWAYS.
4669 Error if Rd or Rm are R15. */
4677 skip_whitespace (str
);
4679 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4680 || (skip_past_comma (& str
) == FAIL
)
4681 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4682 inst
.error
= BAD_ARGS
;
4684 else if (rd
== REG_PC
|| rm
== REG_PC
)
4685 inst
.error
= BAD_PC
;
4691 /* ARM V5 (argument parse)
4692 LDC2{L} <coproc>, <CRd>, <addressing mode>
4693 STC2{L} <coproc>, <CRd>, <addressing mode>
4694 Instruction is not conditional, and has 0xf in the condition field.
4695 Otherwise, it's the same as LDC/STC. */
4701 skip_whitespace (str
);
4703 if (co_proc_number (& str
) == FAIL
)
4706 inst
.error
= BAD_ARGS
;
4708 else if (skip_past_comma (& str
) == FAIL
4709 || cp_reg_required_here (& str
, 12) == FAIL
)
4712 inst
.error
= BAD_ARGS
;
4714 else if (skip_past_comma (& str
) == FAIL
4715 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4718 inst
.error
= BAD_ARGS
;
4724 /* ARM V5 (argument parse)
4725 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4726 Instruction is not conditional, and has 0xf in the condition field.
4727 Otherwise, it's the same as CDP. */
4733 skip_whitespace (str
);
4735 if (co_proc_number (& str
) == FAIL
)
4738 inst
.error
= BAD_ARGS
;
4742 if (skip_past_comma (& str
) == FAIL
4743 || cp_opc_expr (& str
, 20,4) == FAIL
)
4746 inst
.error
= BAD_ARGS
;
4750 if (skip_past_comma (& str
) == FAIL
4751 || cp_reg_required_here (& str
, 12) == FAIL
)
4754 inst
.error
= BAD_ARGS
;
4758 if (skip_past_comma (& str
) == FAIL
4759 || cp_reg_required_here (& str
, 16) == FAIL
)
4762 inst
.error
= BAD_ARGS
;
4766 if (skip_past_comma (& str
) == FAIL
4767 || cp_reg_required_here (& str
, 0) == FAIL
)
4770 inst
.error
= BAD_ARGS
;
4774 if (skip_past_comma (& str
) == SUCCESS
)
4776 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4779 inst
.error
= BAD_ARGS
;
4787 /* ARM V5 (argument parse)
4788 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4789 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4790 Instruction is not conditional, and has 0xf in the condition field.
4791 Otherwise, it's the same as MCR/MRC. */
4797 skip_whitespace (str
);
4799 if (co_proc_number (& str
) == FAIL
)
4802 inst
.error
= BAD_ARGS
;
4806 if (skip_past_comma (& str
) == FAIL
4807 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4810 inst
.error
= BAD_ARGS
;
4814 if (skip_past_comma (& str
) == FAIL
4815 || reg_required_here (& str
, 12) == FAIL
)
4818 inst
.error
= BAD_ARGS
;
4822 if (skip_past_comma (& str
) == FAIL
4823 || cp_reg_required_here (& str
, 16) == FAIL
)
4826 inst
.error
= BAD_ARGS
;
4830 if (skip_past_comma (& str
) == FAIL
4831 || cp_reg_required_here (& str
, 0) == FAIL
)
4834 inst
.error
= BAD_ARGS
;
4838 if (skip_past_comma (& str
) == SUCCESS
)
4840 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4843 inst
.error
= BAD_ARGS
;
4851 /* ARM v5TEJ. Jump to Jazelle code. */
4858 skip_whitespace (str
);
4860 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4862 inst
.error
= BAD_ARGS
;
4866 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4868 as_tsktsk (_("use of r15 in bxj is not really useful"));
4873 /* ARM V6 umaal (argument parse). */
4880 int rdlo
, rdhi
, rm
, rs
;
4882 skip_whitespace (str
);
4883 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4884 || skip_past_comma (& str
) == FAIL
4885 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4886 || skip_past_comma (& str
) == FAIL
4887 || (rm
= reg_required_here (& str
, 0)) == FAIL
4888 || skip_past_comma (& str
) == FAIL
4889 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4891 inst
.error
= BAD_ARGS
;
4895 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4897 inst
.error
= BAD_PC
;
4904 /* ARM V6 strex (argument parse). */
4912 /* Parse Rd, Rm,. */
4913 skip_whitespace (str
);
4914 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4915 || skip_past_comma (& str
) == FAIL
4916 || (rm
= reg_required_here (& str
, 0)) == FAIL
4917 || skip_past_comma (& str
) == FAIL
)
4919 inst
.error
= BAD_ARGS
;
4922 if (rd
== REG_PC
|| rm
== REG_PC
)
4924 inst
.error
= BAD_PC
;
4929 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4933 /* Skip past '['. */
4934 if ((strlen (str
) >= 1)
4935 && strncmp (str
, "[", 1) == 0)
4937 skip_whitespace (str
);
4940 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4942 inst
.error
= BAD_ARGS
;
4945 else if (rn
== REG_PC
)
4947 inst
.error
= BAD_PC
;
4952 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4955 skip_whitespace (str
);
4957 /* Skip past ']'. */
4958 if ((strlen (str
) >= 1)
4959 && strncmp (str
, "]", 1) == 0)
4965 /* ARM V6 ssat (argument parse). */
4971 do_sat (&str
, /*bias=*/-1);
4975 /* ARM V6 usat (argument parse). */
4981 do_sat (&str
, /*bias=*/0);
4993 skip_whitespace (*str
);
4995 /* Parse <Rd>, field. */
4996 if ((rd
= reg_required_here (str
, 12)) == FAIL
4997 || skip_past_comma (str
) == FAIL
)
4999 inst
.error
= BAD_ARGS
;
5004 inst
.error
= BAD_PC
;
5008 /* Parse #<immed>, field. */
5009 if (is_immediate_prefix (**str
))
5013 inst
.error
= _("immediate expression expected");
5016 if (my_get_expression (&expr
, str
))
5018 inst
.error
= _("bad expression");
5021 if (expr
.X_op
!= O_constant
)
5023 inst
.error
= _("constant expression expected");
5026 if (expr
.X_add_number
+ bias
< 0
5027 || expr
.X_add_number
+ bias
> 31)
5029 inst
.error
= _("immediate value out of range");
5032 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5033 if (skip_past_comma (str
) == FAIL
)
5035 inst
.error
= BAD_ARGS
;
5039 /* Parse <Rm> field. */
5040 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5042 inst
.error
= BAD_ARGS
;
5047 inst
.error
= BAD_PC
;
5051 if (skip_past_comma (str
) == SUCCESS
)
5052 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
5055 /* ARM V6 ssat16 (argument parse). */
5061 do_sat16 (&str
, /*bias=*/-1);
5069 do_sat16 (&str
, /*bias=*/0);
5074 do_sat16 (str
, bias
)
5081 skip_whitespace (*str
);
5083 /* Parse the <Rd> field. */
5084 if ((rd
= reg_required_here (str
, 12)) == FAIL
5085 || skip_past_comma (str
) == FAIL
)
5087 inst
.error
= BAD_ARGS
;
5092 inst
.error
= BAD_PC
;
5096 /* Parse #<immed>, field. */
5097 if (is_immediate_prefix (**str
))
5101 inst
.error
= _("immediate expression expected");
5104 if (my_get_expression (&expr
, str
))
5106 inst
.error
= _("bad expression");
5109 if (expr
.X_op
!= O_constant
)
5111 inst
.error
= _("constant expression expected");
5114 if (expr
.X_add_number
+ bias
< 0
5115 || expr
.X_add_number
+ bias
> 15)
5117 inst
.error
= _("immediate value out of range");
5120 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5121 if (skip_past_comma (str
) == FAIL
)
5123 inst
.error
= BAD_ARGS
;
5127 /* Parse <Rm> field. */
5128 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5130 inst
.error
= BAD_ARGS
;
5135 inst
.error
= BAD_PC
;
5140 /* ARM V6 srs (argument parse). */
5147 skip_whitespace (str
);
5148 exclam
= strchr (str
, '!');
5156 inst
.instruction
|= WRITE_BACK
;
5162 /* ARM V6 SMMUL (argument parse). */
5170 skip_whitespace (str
);
5171 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5172 || skip_past_comma (&str
) == FAIL
5173 || (rm
= reg_required_here (&str
, 0)) == FAIL
5174 || skip_past_comma (&str
) == FAIL
5175 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5177 inst
.error
= BAD_ARGS
;
5185 inst
.error
= BAD_PC
;
5193 /* ARM V6 SMLALD (argument parse). */
5199 int rdlo
, rdhi
, rm
, rs
;
5200 skip_whitespace (str
);
5201 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5202 || skip_past_comma (&str
) == FAIL
5203 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5204 || skip_past_comma (&str
) == FAIL
5205 || (rm
= reg_required_here (&str
, 0)) == FAIL
5206 || skip_past_comma (&str
) == FAIL
5207 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5209 inst
.error
= BAD_ARGS
;
5218 inst
.error
= BAD_PC
;
5225 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5226 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5234 skip_whitespace (str
);
5235 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5236 || skip_past_comma (&str
) == FAIL
5237 || (rm
= reg_required_here (&str
, 0)) == FAIL
5238 || skip_past_comma (&str
) == FAIL
5239 || (rs
= reg_required_here (&str
, 8)) == FAIL
5240 || skip_past_comma (&str
) == FAIL
5241 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5243 inst
.error
= BAD_ARGS
;
5252 inst
.error
= BAD_PC
;
5259 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5260 preserving the other bits.
5262 setend <endian_specifier>, where <endian_specifier> is either
5269 if (do_endian_specifier (str
))
5270 inst
.instruction
|= 0x200;
5273 /* Returns true if the endian-specifier indicates big-endianness. */
5276 do_endian_specifier (str
)
5281 skip_whitespace (str
);
5282 if (strlen (str
) < 2)
5283 inst
.error
= _("missing endian specifier");
5284 else if (strncasecmp (str
, "BE", 2) == 0)
5289 else if (strncasecmp (str
, "LE", 2) == 0)
5292 inst
.error
= _("valid endian specifiers are be or le");
5301 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5302 Condition defaults to COND_ALWAYS.
5303 Error if any register uses R15. */
5311 int rotation_clear_mask
= 0xfffff3ff;
5312 int rotation_eight_mask
= 0x00000400;
5313 int rotation_sixteen_mask
= 0x00000800;
5314 int rotation_twenty_four_mask
= 0x00000c00;
5316 skip_whitespace (str
);
5317 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5318 || skip_past_comma (&str
) == FAIL
5319 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5321 inst
.error
= BAD_ARGS
;
5325 else if (rd
== REG_PC
|| rm
== REG_PC
)
5327 inst
.error
= BAD_PC
;
5331 /* Zero out the rotation field. */
5332 inst
.instruction
&= rotation_clear_mask
;
5334 /* Check for lack of optional rotation field. */
5335 if (skip_past_comma (&str
) == FAIL
)
5341 /* Move past 'ROR'. */
5342 skip_whitespace (str
);
5343 if (strncasecmp (str
, "ROR", 3) == 0)
5347 inst
.error
= _("missing rotation field after comma");
5351 /* Get the immediate constant. */
5352 skip_whitespace (str
);
5353 if (is_immediate_prefix (* str
))
5357 inst
.error
= _("immediate expression expected");
5361 if (my_get_expression (&expr
, &str
))
5363 inst
.error
= _("bad expression");
5367 if (expr
.X_op
!= O_constant
)
5369 inst
.error
= _("constant expression expected");
5373 switch (expr
.X_add_number
)
5376 /* Rotation field has already been zeroed. */
5379 inst
.instruction
|= rotation_eight_mask
;
5383 inst
.instruction
|= rotation_sixteen_mask
;
5387 inst
.instruction
|= rotation_twenty_four_mask
;
5391 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5399 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5400 extends it to 32-bits, and adds the result to a value in another
5401 register. You can specify a rotation by 0, 8, 16, or 24 bits
5402 before extracting the 16-bit value.
5403 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5404 Condition defaults to COND_ALWAYS.
5405 Error if any register uses R15. */
5413 int rotation_clear_mask
= 0xfffff3ff;
5414 int rotation_eight_mask
= 0x00000400;
5415 int rotation_sixteen_mask
= 0x00000800;
5416 int rotation_twenty_four_mask
= 0x00000c00;
5418 skip_whitespace (str
);
5419 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5420 || skip_past_comma (&str
) == FAIL
5421 || (rn
= reg_required_here (&str
, 16)) == FAIL
5422 || skip_past_comma (&str
) == FAIL
5423 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5425 inst
.error
= BAD_ARGS
;
5429 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5431 inst
.error
= BAD_PC
;
5435 /* Zero out the rotation field. */
5436 inst
.instruction
&= rotation_clear_mask
;
5438 /* Check for lack of optional rotation field. */
5439 if (skip_past_comma (&str
) == FAIL
)
5445 /* Move past 'ROR'. */
5446 skip_whitespace (str
);
5447 if (strncasecmp (str
, "ROR", 3) == 0)
5451 inst
.error
= _("missing rotation field after comma");
5455 /* Get the immediate constant. */
5456 skip_whitespace (str
);
5457 if (is_immediate_prefix (* str
))
5461 inst
.error
= _("immediate expression expected");
5465 if (my_get_expression (&expr
, &str
))
5467 inst
.error
= _("bad expression");
5471 if (expr
.X_op
!= O_constant
)
5473 inst
.error
= _("constant expression expected");
5477 switch (expr
.X_add_number
)
5480 /* Rotation field has already been zeroed. */
5484 inst
.instruction
|= rotation_eight_mask
;
5488 inst
.instruction
|= rotation_sixteen_mask
;
5492 inst
.instruction
|= rotation_twenty_four_mask
;
5496 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5505 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5506 word at the specified address and the following word
5508 Unconditionally executed.
5518 skip_whitespace (str
);
5520 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5525 inst
.error
= BAD_PC
;
5529 skip_whitespace (str
);
5533 inst
.instruction
|= WRITE_BACK
;
5539 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5540 register (argument parse).
5542 Condition defaults to COND_ALWAYS.
5543 Error if Rd or Rm are R15. */
5551 skip_whitespace (str
);
5553 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5554 || skip_past_comma (&str
) == FAIL
5555 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5556 inst
.error
= BAD_ARGS
;
5558 else if (rd
== REG_PC
|| rm
== REG_PC
)
5559 inst
.error
= BAD_PC
;
5565 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5566 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5567 Condition defaults to COND_ALWAYS.
5568 Error if Rd, Rn or Rm are R15. */
5576 skip_whitespace (str
);
5578 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5579 || skip_past_comma (&str
) == FAIL
5580 || (rn
= reg_required_here (&str
, 16)) == FAIL
5581 || skip_past_comma (&str
) == FAIL
5582 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5583 inst
.error
= BAD_ARGS
;
5585 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5586 inst
.error
= BAD_PC
;
5592 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5593 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5594 Condition defaults to COND_ALWAYS.
5595 Error if Rd, Rn or Rm are R15. */
5601 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5604 /* ARM V6 PKHTB (Argument Parse). */
5610 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5614 do_pkh_core (str
, shift
)
5620 skip_whitespace (str
);
5621 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5622 || (skip_past_comma (&str
) == FAIL
)
5623 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5624 || (skip_past_comma (&str
) == FAIL
)
5625 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5627 inst
.error
= BAD_ARGS
;
5631 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5633 inst
.error
= BAD_PC
;
5637 /* Check for optional shift immediate constant. */
5638 if (skip_past_comma (&str
) == FAIL
)
5640 if (shift
== SHIFT_ASR_IMMEDIATE
)
5642 /* If the shift specifier is ommited, turn the instruction
5643 into pkhbt rd, rm, rn. First, switch the instruction
5644 code, and clear the rn and rm fields. */
5645 inst
.instruction
&= 0xfff0f010;
5646 /* Now, re-encode the registers. */
5647 inst
.instruction
|= (rm
<< 16) | rn
;
5652 decode_shift (&str
, shift
);
5655 /* ARM V6 Load Register Exclusive instruction (argument parse).
5656 LDREX{<cond>} <Rd, [<Rn>]
5657 Condition defaults to COND_ALWAYS.
5658 Error if Rd or Rn are R15.
5659 See ARMARMv6 A4.1.27: LDREX. */
5668 skip_whitespace (str
);
5671 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5672 || (skip_past_comma (&str
) == FAIL
))
5674 inst
.error
= BAD_ARGS
;
5677 else if (rd
== REG_PC
)
5679 inst
.error
= BAD_PC
;
5682 skip_whitespace (str
);
5684 /* Skip past '['. */
5685 if ((strlen (str
) >= 1)
5686 &&strncmp (str
, "[", 1) == 0)
5688 skip_whitespace (str
);
5691 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5693 inst
.error
= BAD_ARGS
;
5696 else if (rn
== REG_PC
)
5698 inst
.error
= BAD_PC
;
5701 skip_whitespace (str
);
5703 /* Skip past ']'. */
5704 if ((strlen (str
) >= 1)
5705 && strncmp (str
, "]", 1) == 0)
5711 /* ARM V6 change processor state instruction (argument parse)
5712 CPS, CPSIE, CSPID . */
5726 do_cps_flags (&str
, /*thumb_p=*/0);
5728 if (skip_past_comma (&str
) == SUCCESS
)
5730 skip_whitespace (str
);
5742 skip_whitespace (*str
);
5744 if (! is_immediate_prefix (**str
))
5746 inst
.error
= _("immediate expression expected");
5750 (*str
)++; /* Strip off the immediate signifier. */
5751 if (my_get_expression (&expr
, str
))
5753 inst
.error
= _("bad expression");
5757 if (expr
.X_op
!= O_constant
)
5759 inst
.error
= _("constant expression expected");
5763 /* The mode is a 5 bit field. Valid values are 0-31. */
5764 if (((unsigned) expr
.X_add_number
) > 31
5765 || (inst
.reloc
.exp
.X_add_number
) < 0)
5767 inst
.error
= _("invalid constant");
5771 inst
.instruction
|= expr
.X_add_number
;
5775 do_cps_flags (str
, thumb_p
)
5781 unsigned long arm_value
;
5782 unsigned long thumb_value
;
5784 static struct cps_flag flag_table
[] = {
5792 skip_whitespace (*str
);
5794 /* Get the a, f and i flags. */
5795 while (**str
&& **str
!= ',')
5798 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5799 for (p
= flag_table
; p
< q
; ++p
)
5800 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5802 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5808 inst
.error
= _("unrecognized flag");
5814 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5817 /* THUMB V5 breakpoint instruction (argument parse)
5825 unsigned long number
;
5827 skip_whitespace (str
);
5829 /* Allow optional leading '#'. */
5830 if (is_immediate_prefix (*str
))
5833 memset (& expr
, '\0', sizeof (expr
));
5834 if (my_get_expression (& expr
, & str
)
5835 || (expr
.X_op
!= O_constant
5836 /* As a convenience we allow 'bkpt' without an operand. */
5837 && expr
.X_op
!= O_absent
))
5839 inst
.error
= _("bad expression");
5843 number
= expr
.X_add_number
;
5845 /* Check it fits an 8 bit unsigned. */
5846 if (number
!= (number
& 0xff))
5848 inst
.error
= _("immediate value out of range");
5852 inst
.instruction
|= number
;
5857 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5858 Expects inst.instruction is set for BLX(1).
5859 Note: this is cloned from do_branch, and the reloc changed to be a
5860 new one that can cope with setting one extra bit (the H bit). */
5866 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5873 /* ScottB: February 5, 1998 */
5874 /* Check to see of PLT32 reloc required for the instruction. */
5876 /* arm_parse_reloc() works on input_line_pointer.
5877 We actually want to parse the operands to the branch instruction
5878 passed in 'str'. Save the input pointer and restore it later. */
5879 save_in
= input_line_pointer
;
5880 input_line_pointer
= str
;
5882 if (inst
.reloc
.exp
.X_op
== O_symbol
5884 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5886 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5887 inst
.reloc
.pc_rel
= 0;
5888 /* Modify str to point to after parsed operands, otherwise
5889 end_of_line() will complain about the (PLT) left in str. */
5890 str
= input_line_pointer
;
5894 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5895 inst
.reloc
.pc_rel
= 1;
5898 input_line_pointer
= save_in
;
5901 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5902 inst
.reloc
.pc_rel
= 1;
5903 #endif /* OBJ_ELF */
5908 /* ARM V5 branch-link-exchange instruction (argument parse)
5909 BLX <target_addr> ie BLX(1)
5910 BLX{<condition>} <Rm> ie BLX(2)
5911 Unfortunately, there are two different opcodes for this mnemonic.
5912 So, the insns[].value is not used, and the code here zaps values
5913 into inst.instruction.
5914 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5923 skip_whitespace (mystr
);
5924 rm
= reg_required_here (& mystr
, 0);
5926 /* The above may set inst.error. Ignore his opinion. */
5931 /* Arg is a register.
5932 Use the condition code our caller put in inst.instruction.
5933 Pass ourselves off as a BX with a funny opcode. */
5934 inst
.instruction
|= 0x012fff30;
5939 /* This must be is BLX <target address>, no condition allowed. */
5940 if (inst
.instruction
!= COND_ALWAYS
)
5942 inst
.error
= BAD_COND
;
5946 inst
.instruction
= 0xfafffffe;
5948 /* Process like a B/BL, but with a different reloc.
5949 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5954 /* ARM V5 Thumb BLX (argument parse)
5955 BLX <target_addr> which is BLX(1)
5956 BLX <Rm> which is BLX(2)
5957 Unfortunately, there are two different opcodes for this mnemonic.
5958 So, the tinsns[].value is not used, and the code here zaps values
5959 into inst.instruction. */
5968 skip_whitespace (mystr
);
5969 inst
.instruction
= 0x4780;
5971 /* Note that this call is to the ARM register recognizer. BLX(2)
5972 uses the ARM register space, not the Thumb one, so a call to
5973 thumb_reg() would be wrong. */
5974 rm
= reg_required_here (& mystr
, 3);
5979 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5984 /* No ARM register. This must be BLX(1). Change the .instruction. */
5985 inst
.instruction
= 0xf7ffeffe;
5988 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5991 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5992 inst
.reloc
.pc_rel
= 1;
5995 end_of_line (mystr
);
5998 /* ARM V5 breakpoint instruction (argument parse)
5999 BKPT <16 bit unsigned immediate>
6000 Instruction is not conditional.
6001 The bit pattern given in insns[] has the COND_ALWAYS condition,
6002 and it is an error if the caller tried to override that. */
6009 unsigned long number
;
6011 skip_whitespace (str
);
6013 /* Allow optional leading '#'. */
6014 if (is_immediate_prefix (* str
))
6017 memset (& expr
, '\0', sizeof (expr
));
6019 if (my_get_expression (& expr
, & str
)
6020 || (expr
.X_op
!= O_constant
6021 /* As a convenience we allow 'bkpt' without an operand. */
6022 && expr
.X_op
!= O_absent
))
6024 inst
.error
= _("bad expression");
6028 number
= expr
.X_add_number
;
6030 /* Check it fits a 16 bit unsigned. */
6031 if (number
!= (number
& 0xffff))
6033 inst
.error
= _("immediate value out of range");
6037 /* Top 12 of 16 bits to bits 19:8. */
6038 inst
.instruction
|= (number
& 0xfff0) << 4;
6040 /* Bottom 4 of 16 bits to bits 3:0. */
6041 inst
.instruction
|= number
& 0xf;
6046 /* THUMB CPS instruction (argument parse). */
6052 do_cps_flags (&str
, /*thumb_p=*/1);
6056 /* THUMB CPY instruction (argument parse). */
6062 thumb_mov_compare (str
, THUMB_CPY
);
6065 /* THUMB SETEND instruction (argument parse). */
6071 if (do_endian_specifier (str
))
6072 inst
.instruction
|= 0x8;
6075 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6077 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6079 static unsigned long
6080 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6082 enum iwmmxt_insn_type insn_type
;
6086 const char * inst_error
;
6088 unsigned long number
;
6090 inst_error
= inst
.error
;
6092 inst
.error
= BAD_ARGS
;
6093 skip_whitespace (str
);
6098 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6103 if ((wreg_required_here (&str
, 0, 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
))
6115 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6116 || skip_past_comma (&str
) == FAIL
6117 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6118 || skip_past_comma (&str
) == FAIL
6119 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6124 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6125 || skip_past_comma (&str
) == FAIL
6126 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6127 || skip_past_comma (&str
) == FAIL
6128 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6133 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6134 || skip_past_comma (&str
) == FAIL
6135 || reg_required_here (&str
, 12) == FAIL
))
6140 if ((reg_required_here (&str
, 12) == FAIL
6141 || skip_past_comma (&str
) == FAIL
6142 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6147 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6148 || skip_past_comma (&str
) == FAIL
6149 || reg_required_here (&str
, 0) == FAIL
6150 || skip_past_comma (&str
) == FAIL
6151 || reg_required_here (&str
, 12) == FAIL
))
6156 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6157 || skip_past_comma (&str
) == FAIL
6158 || reg_required_here (&str
, 12) == FAIL
6159 || skip_past_comma (&str
) == FAIL
6160 || reg_required_here (&str
, 16) == FAIL
))
6165 if ((reg_required_here (&str
, 12) == FAIL
6166 || skip_past_comma (&str
) == FAIL
6167 || reg_required_here (&str
, 16) == FAIL
6168 || skip_past_comma (&str
) == FAIL
6169 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6174 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6175 || skip_past_comma (&str
) == FAIL
6176 || reg_required_here (&str
, 12) == FAIL
))
6181 if ((reg_required_here (&str
, 12) == FAIL
6182 || skip_past_comma (&str
) == FAIL
6183 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6188 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6189 || skip_past_comma (&str
) == FAIL
6190 || reg_required_here (&str
, 12) == FAIL
6191 || skip_past_comma (&str
) == FAIL
))
6196 if ((reg_required_here (&str
, 12) == FAIL
6197 || skip_past_comma (&str
) == FAIL
))
6202 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6203 || skip_past_comma (&str
) == FAIL
6204 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6205 || skip_past_comma (&str
) == FAIL
6206 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6207 || skip_past_comma (&str
) == FAIL
))
6212 if ((reg_required_here (&str
, 12) == FAIL
6213 || skip_past_comma (&str
) == FAIL
6214 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6215 || skip_past_comma (&str
) == FAIL
))
6220 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6221 || skip_past_comma (&str
) == FAIL
6222 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6223 || skip_past_comma (&str
) == FAIL
))
6228 if (immediate_size
== 0)
6231 inst
.error
= inst_error
;
6236 skip_whitespace (str
);
6238 /* Allow optional leading '#'. */
6239 if (is_immediate_prefix (* str
))
6242 memset (& expr
, '\0', sizeof (expr
));
6244 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6246 inst
.error
= _("bad or missing expression");
6250 number
= expr
.X_add_number
;
6252 if (number
!= (number
& immediate_size
))
6254 inst
.error
= _("immediate value out of range");
6258 inst
.error
= inst_error
;
6264 do_iwmmxt_byte_addr (str
)
6267 int op
= (inst
.instruction
& 0x300) >> 8;
6270 inst
.instruction
&= ~0x300;
6271 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6273 skip_whitespace (str
);
6275 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6276 || skip_past_comma (& str
) == FAIL
6277 || cp_byte_address_required_here (&str
) == FAIL
)
6280 inst
.error
= BAD_ARGS
;
6285 if (wc_register (reg
))
6287 as_bad (_("non-word size not supported with control register"));
6288 inst
.instruction
|= 0xf0000100;
6289 inst
.instruction
&= ~0x00400000;
6294 do_iwmmxt_tandc (str
)
6299 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6301 if (reg
!= REG_PC
&& !inst
.error
)
6302 inst
.error
= _("only r15 allowed here");
6306 do_iwmmxt_tbcst (str
)
6309 check_iwmmxt_insn (str
, check_tbcst
, 0);
6313 do_iwmmxt_textrc (str
)
6316 unsigned long number
;
6318 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6321 inst
.instruction
|= number
& 0x7;
6325 do_iwmmxt_textrm (str
)
6328 unsigned long number
;
6330 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6333 inst
.instruction
|= number
& 0x7;
6337 do_iwmmxt_tinsr (str
)
6340 unsigned long number
;
6342 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6345 inst
.instruction
|= number
& 0x7;
6349 do_iwmmxt_tmcr (str
)
6352 check_iwmmxt_insn (str
, check_tmcr
, 0);
6356 do_iwmmxt_tmcrr (str
)
6359 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6363 do_iwmmxt_tmia (str
)
6366 check_iwmmxt_insn (str
, check_tmia
, 0);
6370 do_iwmmxt_tmovmsk (str
)
6373 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6377 do_iwmmxt_tmrc (str
)
6380 check_iwmmxt_insn (str
, check_tmrc
, 0);
6384 do_iwmmxt_tmrrc (str
)
6387 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6391 do_iwmmxt_torc (str
)
6394 check_iwmmxt_insn (str
, check_rd
, 0);
6398 do_iwmmxt_waligni (str
)
6401 unsigned long number
;
6403 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6406 inst
.instruction
|= ((number
& 0x7) << 20);
6410 do_iwmmxt_wmov (str
)
6413 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6416 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6420 do_iwmmxt_word_addr (str
)
6423 int op
= (inst
.instruction
& 0x300) >> 8;
6426 inst
.instruction
&= ~0x300;
6427 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6429 skip_whitespace (str
);
6431 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6432 || skip_past_comma (& str
) == FAIL
6433 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6436 inst
.error
= BAD_ARGS
;
6441 if (wc_register (reg
))
6443 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6444 as_bad (_("conditional execution not supported with control register"));
6446 as_bad (_("non-word size not supported with control register"));
6447 inst
.instruction
|= 0xf0000100;
6448 inst
.instruction
&= ~0x00400000;
6453 do_iwmmxt_wrwr (str
)
6456 check_iwmmxt_insn (str
, check_wrwr
, 0);
6460 do_iwmmxt_wrwrwcg (str
)
6463 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6467 do_iwmmxt_wrwrwr (str
)
6470 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6474 do_iwmmxt_wshufh (str
)
6477 unsigned long number
;
6479 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6482 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6486 do_iwmmxt_wzero (str
)
6489 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6492 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6495 /* Xscale multiply-accumulate (argument parse)
6498 MIAxycc acc0,Rm,Rs. */
6507 if (accum0_required_here (& str
) == FAIL
)
6508 inst
.error
= ERR_NO_ACCUM
;
6510 else if (skip_past_comma (& str
) == FAIL
6511 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6512 inst
.error
= BAD_ARGS
;
6514 else if (skip_past_comma (& str
) == FAIL
6515 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6516 inst
.error
= BAD_ARGS
;
6518 /* inst.instruction has now been zapped with both rm and rs. */
6519 else if (rm
== REG_PC
|| rs
== REG_PC
)
6520 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6526 /* Xscale move-accumulator-register (argument parse)
6528 MARcc acc0,RdLo,RdHi. */
6536 if (accum0_required_here (& str
) == FAIL
)
6537 inst
.error
= ERR_NO_ACCUM
;
6539 else if (skip_past_comma (& str
) == FAIL
6540 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6541 inst
.error
= BAD_ARGS
;
6543 else if (skip_past_comma (& str
) == FAIL
6544 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6545 inst
.error
= BAD_ARGS
;
6547 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6548 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6549 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6555 /* Xscale move-register-accumulator (argument parse)
6557 MRAcc RdLo,RdHi,acc0. */
6566 skip_whitespace (str
);
6568 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6569 inst
.error
= BAD_ARGS
;
6571 else if (skip_past_comma (& str
) == FAIL
6572 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6573 inst
.error
= BAD_ARGS
;
6575 else if (skip_past_comma (& str
) == FAIL
6576 || accum0_required_here (& str
) == FAIL
)
6577 inst
.error
= ERR_NO_ACCUM
;
6579 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6580 else if (rdlo
== rdhi
)
6581 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6583 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6584 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6589 /* ARMv5TE: Preload-Cache
6593 Syntactically, like LDR with B=1, W=0, L=1. */
6601 skip_whitespace (str
);
6605 inst
.error
= _("'[' expected after PLD mnemonic");
6610 skip_whitespace (str
);
6612 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6615 skip_whitespace (str
);
6621 skip_whitespace (str
);
6623 /* Post-indexed addressing is not allowed with PLD. */
6624 if (skip_past_comma (&str
) == SUCCESS
)
6627 = _("post-indexed expression used in preload instruction");
6630 else if (*str
== '!') /* [Rn]! */
6632 inst
.error
= _("writeback used in preload instruction");
6636 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6638 else /* [Rn, ...] */
6640 if (skip_past_comma (& str
) == FAIL
)
6642 inst
.error
= _("pre-indexed expression expected");
6646 if (ldst_extend (&str
) == FAIL
)
6649 skip_whitespace (str
);
6653 inst
.error
= _("missing ]");
6658 skip_whitespace (str
);
6660 if (* str
== '!') /* [Rn]! */
6662 inst
.error
= _("writeback used in preload instruction");
6666 inst
.instruction
|= PRE_INDEX
;
6672 /* ARMv5TE load-consecutive (argument parse)
6685 skip_whitespace (str
);
6687 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6689 inst
.error
= BAD_ARGS
;
6693 if (skip_past_comma (& str
) == FAIL
6694 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6697 inst
.error
= BAD_ARGS
;
6701 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6702 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6704 inst
.error
= _("destination register must be even");
6710 inst
.error
= _("r14 not allowed here");
6714 if (((rd
== rn
) || (rd
+ 1 == rn
))
6715 && ((inst
.instruction
& WRITE_BACK
)
6716 || (!(inst
.instruction
& PRE_INDEX
))))
6717 as_warn (_("pre/post-indexing used when modified address register is destination"));
6719 /* For an index-register load, the index register must not overlap the
6720 destination (even if not write-back). */
6721 if ((inst
.instruction
& V4_STR_BIT
) == 0
6722 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6724 int rm
= inst
.instruction
& 0x0000000f;
6726 if (rm
== rd
|| (rm
== rd
+ 1))
6727 as_warn (_("ldrd destination registers must not overlap index register"));
6733 /* Returns the index into fp_values of a floating point number,
6734 or -1 if not in the table. */
6737 my_get_float_expression (str
)
6740 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6746 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6748 /* Look for a raw floating point number. */
6749 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6750 && is_end_of_line
[(unsigned char) *save_in
])
6752 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6754 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6756 if (words
[j
] != fp_values
[i
][j
])
6760 if (j
== MAX_LITTLENUMS
)
6768 /* Try and parse a more complex expression, this will probably fail
6769 unless the code uses a floating point prefix (eg "0f"). */
6770 save_in
= input_line_pointer
;
6771 input_line_pointer
= *str
;
6772 if (expression (&exp
) == absolute_section
6773 && exp
.X_op
== O_big
6774 && exp
.X_add_number
< 0)
6776 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6778 if (gen_to_words (words
, 5, (long) 15) == 0)
6780 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6782 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6784 if (words
[j
] != fp_values
[i
][j
])
6788 if (j
== MAX_LITTLENUMS
)
6790 *str
= input_line_pointer
;
6791 input_line_pointer
= save_in
;
6798 *str
= input_line_pointer
;
6799 input_line_pointer
= save_in
;
6803 /* Return TRUE if anything in the expression is a bignum. */
6806 walk_no_bignums (sp
)
6809 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6812 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6814 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6815 || (symbol_get_value_expression (sp
)->X_op_symbol
6816 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6822 static int in_my_get_expression
= 0;
6825 my_get_expression (ep
, str
)
6832 save_in
= input_line_pointer
;
6833 input_line_pointer
= *str
;
6834 in_my_get_expression
= 1;
6835 seg
= expression (ep
);
6836 in_my_get_expression
= 0;
6838 if (ep
->X_op
== O_illegal
)
6840 /* We found a bad expression in md_operand(). */
6841 *str
= input_line_pointer
;
6842 input_line_pointer
= save_in
;
6847 if (seg
!= absolute_section
6848 && seg
!= text_section
6849 && seg
!= data_section
6850 && seg
!= bss_section
6851 && seg
!= undefined_section
)
6853 inst
.error
= _("bad_segment");
6854 *str
= input_line_pointer
;
6855 input_line_pointer
= save_in
;
6860 /* Get rid of any bignums now, so that we don't generate an error for which
6861 we can't establish a line number later on. Big numbers are never valid
6862 in instructions, which is where this routine is always called. */
6863 if (ep
->X_op
== O_big
6864 || (ep
->X_add_symbol
6865 && (walk_no_bignums (ep
->X_add_symbol
)
6867 && walk_no_bignums (ep
->X_op_symbol
)))))
6869 inst
.error
= _("invalid constant");
6870 *str
= input_line_pointer
;
6871 input_line_pointer
= save_in
;
6875 *str
= input_line_pointer
;
6876 input_line_pointer
= save_in
;
6880 /* We handle all bad expressions here, so that we can report the faulty
6881 instruction in the error message. */
6886 if (in_my_get_expression
)
6888 expr
->X_op
= O_illegal
;
6889 if (inst
.error
== NULL
)
6890 inst
.error
= _("bad expression");
6894 /* KIND indicates what kind of shifts are accepted. */
6897 decode_shift (str
, kind
)
6901 const struct asm_shift_name
* shift
;
6905 skip_whitespace (* str
);
6907 for (p
= * str
; ISALPHA (* p
); p
++)
6912 inst
.error
= _("shift expression expected");
6918 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6923 inst
.error
= _("shift expression expected");
6927 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6929 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6930 && shift
->properties
->index
!= SHIFT_LSL
6931 && shift
->properties
->index
!= SHIFT_ASR
)
6933 inst
.error
= _("'LSL' or 'ASR' required");
6936 else if (kind
== SHIFT_LSL_IMMEDIATE
6937 && shift
->properties
->index
!= SHIFT_LSL
)
6939 inst
.error
= _("'LSL' required");
6942 else if (kind
== SHIFT_ASR_IMMEDIATE
6943 && shift
->properties
->index
!= SHIFT_ASR
)
6945 inst
.error
= _("'ASR' required");
6949 if (shift
->properties
->index
== SHIFT_RRX
)
6952 inst
.instruction
|= shift
->properties
->bit_field
;
6956 skip_whitespace (p
);
6958 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6960 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6964 else if (! is_immediate_prefix (* p
))
6966 inst
.error
= (NO_SHIFT_RESTRICT
6967 ? _("shift requires register or #expression")
6968 : _("shift requires #expression"));
6976 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6979 /* Validate some simple #expressions. */
6980 if (inst
.reloc
.exp
.X_op
== O_constant
)
6982 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6984 /* Reject operations greater than 32. */
6986 /* Reject a shift of 0 unless the mode allows it. */
6987 || (num
== 0 && shift
->properties
->allows_0
== 0)
6988 /* Reject a shift of 32 unless the mode allows it. */
6989 || (num
== 32 && shift
->properties
->allows_32
== 0)
6992 /* As a special case we allow a shift of zero for
6993 modes that do not support it to be recoded as an
6994 logical shift left of zero (ie nothing). We warn
6995 about this though. */
6998 as_warn (_("shift of 0 ignored."));
6999 shift
= & shift_names
[0];
7000 assert (shift
->properties
->index
== SHIFT_LSL
);
7004 inst
.error
= _("invalid immediate shift");
7009 /* Shifts of 32 are encoded as 0, for those shifts that
7014 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
7018 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
7019 inst
.reloc
.pc_rel
= 0;
7020 inst
.instruction
|= shift
->properties
->bit_field
;
7027 /* Do those data_ops which can take a negative immediate constant
7028 by altering the instruction. A bit of a hack really.
7032 by inverting the second operand, and
7035 by negating the second operand. */
7038 negate_data_op (instruction
, value
)
7039 unsigned long * instruction
;
7040 unsigned long value
;
7043 unsigned long negated
, inverted
;
7045 negated
= validate_immediate (-value
);
7046 inverted
= validate_immediate (~value
);
7048 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
7051 /* First negates. */
7052 case OPCODE_SUB
: /* ADD <-> SUB */
7053 new_inst
= OPCODE_ADD
;
7058 new_inst
= OPCODE_SUB
;
7062 case OPCODE_CMP
: /* CMP <-> CMN */
7063 new_inst
= OPCODE_CMN
;
7068 new_inst
= OPCODE_CMP
;
7072 /* Now Inverted ops. */
7073 case OPCODE_MOV
: /* MOV <-> MVN */
7074 new_inst
= OPCODE_MVN
;
7079 new_inst
= OPCODE_MOV
;
7083 case OPCODE_AND
: /* AND <-> BIC */
7084 new_inst
= OPCODE_BIC
;
7089 new_inst
= OPCODE_AND
;
7093 case OPCODE_ADC
: /* ADC <-> SBC */
7094 new_inst
= OPCODE_SBC
;
7099 new_inst
= OPCODE_ADC
;
7103 /* We cannot do anything. */
7108 if (value
== (unsigned) FAIL
)
7111 *instruction
&= OPCODE_MASK
;
7112 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7123 skip_whitespace (* str
);
7125 if (reg_required_here (str
, 0) != FAIL
)
7127 if (skip_past_comma (str
) == SUCCESS
)
7128 /* Shift operation on register. */
7129 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7135 /* Immediate expression. */
7136 if (is_immediate_prefix (**str
))
7141 if (my_get_expression (&inst
.reloc
.exp
, str
))
7144 if (inst
.reloc
.exp
.X_add_symbol
)
7146 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7147 inst
.reloc
.pc_rel
= 0;
7151 if (skip_past_comma (str
) == SUCCESS
)
7153 /* #x, y -- ie explicit rotation by Y. */
7154 if (my_get_expression (&expr
, str
))
7157 if (expr
.X_op
!= O_constant
)
7159 inst
.error
= _("constant expression expected");
7163 /* Rotate must be a multiple of 2. */
7164 if (((unsigned) expr
.X_add_number
) > 30
7165 || (expr
.X_add_number
& 1) != 0
7166 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7168 inst
.error
= _("invalid constant");
7171 inst
.instruction
|= INST_IMMEDIATE
;
7172 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7173 inst
.instruction
|= expr
.X_add_number
<< 7;
7177 /* Implicit rotation, select a suitable one. */
7178 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7182 /* Can't be done. Perhaps the code reads something like
7183 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7184 if ((value
= negate_data_op (&inst
.instruction
,
7185 inst
.reloc
.exp
.X_add_number
))
7188 inst
.error
= _("invalid constant");
7193 inst
.instruction
|= value
;
7196 inst
.instruction
|= INST_IMMEDIATE
;
7201 inst
.error
= _("register or shift expression expected");
7210 skip_whitespace (* str
);
7212 if (fp_reg_required_here (str
, 0) != FAIL
)
7216 /* Immediate expression. */
7217 if (*((*str
)++) == '#')
7223 skip_whitespace (* str
);
7225 /* First try and match exact strings, this is to guarantee
7226 that some formats will work even for cross assembly. */
7228 for (i
= 0; fp_const
[i
]; i
++)
7230 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7234 *str
+= strlen (fp_const
[i
]);
7235 if (is_end_of_line
[(unsigned char) **str
])
7237 inst
.instruction
|= i
+ 8;
7244 /* Just because we didn't get a match doesn't mean that the
7245 constant isn't valid, just that it is in a format that we
7246 don't automatically recognize. Try parsing it with
7247 the standard expression routines. */
7248 if ((i
= my_get_float_expression (str
)) >= 0)
7250 inst
.instruction
|= i
+ 8;
7254 inst
.error
= _("invalid floating point immediate expression");
7258 _("floating point register or immediate expression expected");
7267 skip_whitespace (str
);
7269 if (reg_required_here (&str
, 12) == FAIL
7270 || skip_past_comma (&str
) == FAIL
7271 || reg_required_here (&str
, 16) == FAIL
7272 || skip_past_comma (&str
) == FAIL
7273 || data_op2 (&str
) == FAIL
)
7276 inst
.error
= BAD_ARGS
;
7287 /* This is a pseudo-op of the form "adr rd, label" to be converted
7288 into a relative address of the form "add rd, pc, #label-.-8". */
7289 skip_whitespace (str
);
7291 if (reg_required_here (&str
, 12) == FAIL
7292 || skip_past_comma (&str
) == FAIL
7293 || my_get_expression (&inst
.reloc
.exp
, &str
))
7296 inst
.error
= BAD_ARGS
;
7300 /* Frag hacking will turn this into a sub instruction if the offset turns
7301 out to be negative. */
7302 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7304 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7306 inst
.reloc
.pc_rel
= 1;
7315 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7316 into a relative address of the form:
7317 add rd, pc, #low(label-.-8)"
7318 add rd, rd, #high(label-.-8)" */
7320 skip_whitespace (str
);
7322 if (reg_required_here (&str
, 12) == FAIL
7323 || skip_past_comma (&str
) == FAIL
7324 || my_get_expression (&inst
.reloc
.exp
, &str
))
7327 inst
.error
= BAD_ARGS
;
7333 /* Frag hacking will turn this into a sub instruction if the offset turns
7334 out to be negative. */
7335 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7337 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7339 inst
.reloc
.pc_rel
= 1;
7340 inst
.size
= INSN_SIZE
* 2;
7347 skip_whitespace (str
);
7349 if (reg_required_here (&str
, 16) == FAIL
)
7352 inst
.error
= BAD_ARGS
;
7356 if (skip_past_comma (&str
) == FAIL
7357 || data_op2 (&str
) == FAIL
)
7360 inst
.error
= BAD_ARGS
;
7371 skip_whitespace (str
);
7373 if (reg_required_here (&str
, 12) == FAIL
)
7376 inst
.error
= BAD_ARGS
;
7380 if (skip_past_comma (&str
) == FAIL
7381 || data_op2 (&str
) == FAIL
)
7384 inst
.error
= BAD_ARGS
;
7402 if (my_get_expression (& inst
.reloc
.exp
, str
))
7405 if (inst
.reloc
.exp
.X_op
== O_constant
)
7407 int value
= inst
.reloc
.exp
.X_add_number
;
7409 if (value
< -4095 || value
> 4095)
7411 inst
.error
= _("address offset too large");
7421 inst
.instruction
|= add
| value
;
7425 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7426 inst
.reloc
.pc_rel
= 0;
7439 if (reg_required_here (str
, 0) == FAIL
)
7442 inst
.instruction
|= add
| OFFSET_REG
;
7443 if (skip_past_comma (str
) == SUCCESS
)
7444 return decode_shift (str
, SHIFT_IMMEDIATE
);
7458 skip_whitespace (str
);
7460 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7463 inst
.error
= BAD_ARGS
;
7467 if (skip_past_comma (&str
) == FAIL
)
7469 inst
.error
= _("address expected");
7479 skip_whitespace (str
);
7481 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7484 /* Conflicts can occur on stores as well as loads. */
7485 conflict_reg
= (conflict_reg
== reg
);
7487 skip_whitespace (str
);
7493 if (skip_past_comma (&str
) == SUCCESS
)
7495 /* [Rn],... (post inc) */
7496 if (ldst_extend (&str
) == FAIL
)
7499 as_warn (_("%s register same as write-back base"),
7500 ((inst
.instruction
& LOAD_BIT
)
7501 ? _("destination") : _("source")));
7506 skip_whitespace (str
);
7511 as_warn (_("%s register same as write-back base"),
7512 ((inst
.instruction
& LOAD_BIT
)
7513 ? _("destination") : _("source")));
7515 inst
.instruction
|= WRITE_BACK
;
7518 inst
.instruction
|= INDEX_UP
;
7525 if (skip_past_comma (&str
) == FAIL
)
7527 inst
.error
= _("pre-indexed expression expected");
7532 if (ldst_extend (&str
) == FAIL
)
7535 skip_whitespace (str
);
7539 inst
.error
= _("missing ]");
7543 skip_whitespace (str
);
7548 as_warn (_("%s register same as write-back base"),
7549 ((inst
.instruction
& LOAD_BIT
)
7550 ? _("destination") : _("source")));
7552 inst
.instruction
|= WRITE_BACK
;
7556 else if (*str
== '=')
7558 if ((inst
.instruction
& LOAD_BIT
) == 0)
7560 inst
.error
= _("invalid pseudo operation");
7564 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7567 skip_whitespace (str
);
7569 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7572 if (inst
.reloc
.exp
.X_op
!= O_constant
7573 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7575 inst
.error
= _("constant expression expected");
7579 if (inst
.reloc
.exp
.X_op
== O_constant
)
7581 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7585 /* This can be done with a mov instruction. */
7586 inst
.instruction
&= LITERAL_MASK
;
7587 inst
.instruction
|= (INST_IMMEDIATE
7588 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7589 inst
.instruction
|= value
& 0xfff;
7594 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7598 /* This can be done with a mvn instruction. */
7599 inst
.instruction
&= LITERAL_MASK
;
7600 inst
.instruction
|= (INST_IMMEDIATE
7601 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7602 inst
.instruction
|= value
& 0xfff;
7608 /* Insert into literal pool. */
7609 if (add_to_lit_pool () == FAIL
)
7612 inst
.error
= _("literal pool insertion failed");
7616 /* Change the instruction exp to point to the pool. */
7617 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7618 inst
.reloc
.pc_rel
= 1;
7619 inst
.instruction
|= (REG_PC
<< 16);
7624 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7627 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7629 /* PC rel adjust. */
7630 inst
.reloc
.exp
.X_add_number
-= 8;
7632 inst
.reloc
.pc_rel
= 1;
7633 inst
.instruction
|= (REG_PC
<< 16);
7637 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7647 skip_whitespace (str
);
7649 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7652 inst
.error
= BAD_ARGS
;
7656 if (skip_past_comma (& str
) == FAIL
)
7658 inst
.error
= _("address expected");
7668 skip_whitespace (str
);
7670 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7673 /* ldrt/strt always use post-indexed addressing, so if the base is
7674 the same as Rd, we warn. */
7675 if (conflict_reg
== reg
)
7676 as_warn (_("%s register same as write-back base"),
7677 ((inst
.instruction
& LOAD_BIT
)
7678 ? _("destination") : _("source")));
7680 skip_whitespace (str
);
7686 if (skip_past_comma (&str
) == SUCCESS
)
7688 /* [Rn],... (post inc) */
7689 if (ldst_extend (&str
) == FAIL
)
7695 skip_whitespace (str
);
7697 /* Skip a write-back '!'. */
7701 inst
.instruction
|= INDEX_UP
;
7706 inst
.error
= _("post-indexed expression expected");
7712 inst
.error
= _("post-indexed expression expected");
7720 ldst_extend_v4 (str
)
7730 if (my_get_expression (& inst
.reloc
.exp
, str
))
7733 if (inst
.reloc
.exp
.X_op
== O_constant
)
7735 int value
= inst
.reloc
.exp
.X_add_number
;
7737 if (value
< -255 || value
> 255)
7739 inst
.error
= _("address offset too large");
7749 /* Halfword and signextension instructions have the
7750 immediate value split across bits 11..8 and bits 3..0. */
7751 inst
.instruction
|= (add
| HWOFFSET_IMM
7752 | ((value
>> 4) << 8) | (value
& 0xF));
7756 inst
.instruction
|= HWOFFSET_IMM
;
7757 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7758 inst
.reloc
.pc_rel
= 0;
7771 if (reg_required_here (str
, 0) == FAIL
)
7774 inst
.instruction
|= add
;
7779 /* Halfword and signed-byte load/store operations. */
7788 skip_whitespace (str
);
7790 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7793 inst
.error
= BAD_ARGS
;
7797 if (skip_past_comma (& str
) == FAIL
)
7799 inst
.error
= _("address expected");
7809 skip_whitespace (str
);
7811 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7814 /* Conflicts can occur on stores as well as loads. */
7815 conflict_reg
= (conflict_reg
== reg
);
7817 skip_whitespace (str
);
7823 if (skip_past_comma (&str
) == SUCCESS
)
7825 /* [Rn],... (post inc) */
7826 if (ldst_extend_v4 (&str
) == FAIL
)
7829 as_warn (_("%s register same as write-back base"),
7830 ((inst
.instruction
& LOAD_BIT
)
7831 ? _("destination") : _("source")));
7836 inst
.instruction
|= HWOFFSET_IMM
;
7838 skip_whitespace (str
);
7843 as_warn (_("%s register same as write-back base"),
7844 ((inst
.instruction
& LOAD_BIT
)
7845 ? _("destination") : _("source")));
7847 inst
.instruction
|= WRITE_BACK
;
7850 inst
.instruction
|= INDEX_UP
;
7857 if (skip_past_comma (&str
) == FAIL
)
7859 inst
.error
= _("pre-indexed expression expected");
7864 if (ldst_extend_v4 (&str
) == FAIL
)
7867 skip_whitespace (str
);
7871 inst
.error
= _("missing ]");
7875 skip_whitespace (str
);
7880 as_warn (_("%s register same as write-back base"),
7881 ((inst
.instruction
& LOAD_BIT
)
7882 ? _("destination") : _("source")));
7884 inst
.instruction
|= WRITE_BACK
;
7888 else if (*str
== '=')
7890 if ((inst
.instruction
& LOAD_BIT
) == 0)
7892 inst
.error
= _("invalid pseudo operation");
7896 /* XXX Does this work correctly for half-word/byte ops? */
7897 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7900 skip_whitespace (str
);
7902 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7905 if (inst
.reloc
.exp
.X_op
!= O_constant
7906 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7908 inst
.error
= _("constant expression expected");
7912 if (inst
.reloc
.exp
.X_op
== O_constant
)
7914 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7918 /* This can be done with a mov instruction. */
7919 inst
.instruction
&= LITERAL_MASK
;
7920 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7921 inst
.instruction
|= value
& 0xfff;
7926 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7930 /* This can be done with a mvn instruction. */
7931 inst
.instruction
&= LITERAL_MASK
;
7932 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7933 inst
.instruction
|= value
& 0xfff;
7939 /* Insert into literal pool. */
7940 if (add_to_lit_pool () == FAIL
)
7943 inst
.error
= _("literal pool insertion failed");
7947 /* Change the instruction exp to point to the pool. */
7948 inst
.instruction
|= HWOFFSET_IMM
;
7949 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7950 inst
.reloc
.pc_rel
= 1;
7951 inst
.instruction
|= (REG_PC
<< 16);
7956 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7959 inst
.instruction
|= HWOFFSET_IMM
;
7960 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7962 /* PC rel adjust. */
7963 inst
.reloc
.exp
.X_add_number
-= 8;
7965 inst
.reloc
.pc_rel
= 1;
7966 inst
.instruction
|= (REG_PC
<< 16);
7970 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7978 char * str
= * strp
;
7982 /* We come back here if we get ranges concatenated by '+' or '|'. */
7997 skip_whitespace (str
);
7999 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
8008 inst
.error
= _("bad range in register list");
8012 for (i
= cur_reg
+ 1; i
< reg
; i
++)
8014 if (range
& (1 << i
))
8016 (_("Warning: duplicated register (r%d) in register list"),
8024 if (range
& (1 << reg
))
8025 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8027 else if (reg
<= cur_reg
)
8028 as_tsktsk (_("Warning: register range not in ascending order"));
8033 while (skip_past_comma (&str
) != FAIL
8034 || (in_range
= 1, *str
++ == '-'));
8036 skip_whitespace (str
);
8040 inst
.error
= _("missing `}'");
8048 if (my_get_expression (&expr
, &str
))
8051 if (expr
.X_op
== O_constant
)
8053 if (expr
.X_add_number
8054 != (expr
.X_add_number
& 0x0000ffff))
8056 inst
.error
= _("invalid register mask");
8060 if ((range
& expr
.X_add_number
) != 0)
8062 int regno
= range
& expr
.X_add_number
;
8065 regno
= (1 << regno
) - 1;
8067 (_("Warning: duplicated register (r%d) in register list"),
8071 range
|= expr
.X_add_number
;
8075 if (inst
.reloc
.type
!= 0)
8077 inst
.error
= _("expression too complex");
8081 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8082 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8083 inst
.reloc
.pc_rel
= 0;
8087 skip_whitespace (str
);
8089 if (*str
== '|' || *str
== '+')
8095 while (another_range
);
8108 skip_whitespace (str
);
8110 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8113 if (base_reg
== REG_PC
)
8115 inst
.error
= _("r15 not allowed as base register");
8119 skip_whitespace (str
);
8123 inst
.instruction
|= WRITE_BACK
;
8127 if (skip_past_comma (&str
) == FAIL
8128 || (range
= reg_list (&str
)) == FAIL
)
8131 inst
.error
= BAD_ARGS
;
8138 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8141 if (inst
.instruction
& WRITE_BACK
)
8143 /* Check for unpredictable uses of writeback. */
8144 if (inst
.instruction
& LOAD_BIT
)
8146 /* Not allowed in LDM type 2. */
8147 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8148 && ((range
& (1 << REG_PC
)) == 0))
8149 as_warn (_("writeback of base register is UNPREDICTABLE"));
8150 /* Only allowed if base reg not in list for other types. */
8151 else if (range
& (1 << base_reg
))
8152 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8156 /* Not allowed for type 2. */
8157 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8158 as_warn (_("writeback of base register is UNPREDICTABLE"));
8159 /* Only allowed if base reg not in list, or first in list. */
8160 else if ((range
& (1 << base_reg
))
8161 && (range
& ((1 << base_reg
) - 1)))
8162 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8166 inst
.instruction
|= range
;
8174 skip_whitespace (str
);
8176 /* Allow optional leading '#'. */
8177 if (is_immediate_prefix (*str
))
8180 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8183 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8184 inst
.reloc
.pc_rel
= 0;
8194 skip_whitespace (str
);
8196 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8201 inst
.error
= _("r15 not allowed in swap");
8205 if (skip_past_comma (&str
) == FAIL
8206 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8209 inst
.error
= BAD_ARGS
;
8215 inst
.error
= _("r15 not allowed in swap");
8219 if (skip_past_comma (&str
) == FAIL
8222 inst
.error
= BAD_ARGS
;
8226 skip_whitespace (str
);
8228 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8233 inst
.error
= BAD_PC
;
8237 skip_whitespace (str
);
8241 inst
.error
= _("missing ]");
8252 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8259 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8260 required for the instruction. */
8262 /* arm_parse_reloc () works on input_line_pointer.
8263 We actually want to parse the operands to the branch instruction
8264 passed in 'str'. Save the input pointer and restore it later. */
8265 save_in
= input_line_pointer
;
8266 input_line_pointer
= str
;
8267 if (inst
.reloc
.exp
.X_op
== O_symbol
8269 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8271 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8272 inst
.reloc
.pc_rel
= 0;
8273 /* Modify str to point to after parsed operands, otherwise
8274 end_of_line() will complain about the (PLT) left in str. */
8275 str
= input_line_pointer
;
8279 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8280 inst
.reloc
.pc_rel
= 1;
8282 input_line_pointer
= save_in
;
8285 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8286 inst
.reloc
.pc_rel
= 1;
8287 #endif /* OBJ_ELF */
8298 skip_whitespace (str
);
8300 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8302 inst
.error
= BAD_ARGS
;
8306 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8308 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8317 /* Co-processor data operation.
8318 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8319 skip_whitespace (str
);
8321 if (co_proc_number (&str
) == FAIL
)
8324 inst
.error
= BAD_ARGS
;
8328 if (skip_past_comma (&str
) == FAIL
8329 || cp_opc_expr (&str
, 20,4) == FAIL
)
8332 inst
.error
= BAD_ARGS
;
8336 if (skip_past_comma (&str
) == FAIL
8337 || cp_reg_required_here (&str
, 12) == FAIL
)
8340 inst
.error
= BAD_ARGS
;
8344 if (skip_past_comma (&str
) == FAIL
8345 || cp_reg_required_here (&str
, 16) == FAIL
)
8348 inst
.error
= BAD_ARGS
;
8352 if (skip_past_comma (&str
) == FAIL
8353 || cp_reg_required_here (&str
, 0) == FAIL
)
8356 inst
.error
= BAD_ARGS
;
8360 if (skip_past_comma (&str
) == SUCCESS
)
8362 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8365 inst
.error
= BAD_ARGS
;
8377 /* Co-processor register load/store.
8378 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8380 skip_whitespace (str
);
8382 if (co_proc_number (&str
) == FAIL
)
8385 inst
.error
= BAD_ARGS
;
8389 if (skip_past_comma (&str
) == FAIL
8390 || cp_reg_required_here (&str
, 12) == FAIL
)
8393 inst
.error
= BAD_ARGS
;
8397 if (skip_past_comma (&str
) == FAIL
8398 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8401 inst
.error
= BAD_ARGS
;
8412 /* Co-processor register transfer.
8413 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8415 skip_whitespace (str
);
8417 if (co_proc_number (&str
) == FAIL
)
8420 inst
.error
= BAD_ARGS
;
8424 if (skip_past_comma (&str
) == FAIL
8425 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8428 inst
.error
= BAD_ARGS
;
8432 if (skip_past_comma (&str
) == FAIL
8433 || reg_required_here (&str
, 12) == FAIL
)
8436 inst
.error
= BAD_ARGS
;
8440 if (skip_past_comma (&str
) == FAIL
8441 || cp_reg_required_here (&str
, 16) == FAIL
)
8444 inst
.error
= BAD_ARGS
;
8448 if (skip_past_comma (&str
) == FAIL
8449 || cp_reg_required_here (&str
, 0) == FAIL
)
8452 inst
.error
= BAD_ARGS
;
8456 if (skip_past_comma (&str
) == SUCCESS
)
8458 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8461 inst
.error
= BAD_ARGS
;
8473 /* FP control registers.
8474 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8476 skip_whitespace (str
);
8478 if (reg_required_here (&str
, 12) == FAIL
)
8481 inst
.error
= BAD_ARGS
;
8492 skip_whitespace (str
);
8494 if (fp_reg_required_here (&str
, 12) == FAIL
)
8497 inst
.error
= BAD_ARGS
;
8501 if (skip_past_comma (&str
) == FAIL
8502 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8505 inst
.error
= BAD_ARGS
;
8518 skip_whitespace (str
);
8520 if (fp_reg_required_here (&str
, 12) == FAIL
)
8523 inst
.error
= BAD_ARGS
;
8527 /* Get Number of registers to transfer. */
8528 if (skip_past_comma (&str
) == FAIL
8529 || my_get_expression (&inst
.reloc
.exp
, &str
))
8532 inst
.error
= _("constant expression expected");
8536 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8538 inst
.error
= _("constant value required for number of registers");
8542 num_regs
= inst
.reloc
.exp
.X_add_number
;
8544 if (num_regs
< 1 || num_regs
> 4)
8546 inst
.error
= _("number of registers must be in the range [1:4]");
8553 inst
.instruction
|= CP_T_X
;
8556 inst
.instruction
|= CP_T_Y
;
8559 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8567 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8573 /* The instruction specified "ea" or "fd", so we can only accept
8574 [Rn]{!}. The instruction does not really support stacking or
8575 unstacking, so we have to emulate these by setting appropriate
8576 bits and offsets. */
8577 if (skip_past_comma (&str
) == FAIL
8581 inst
.error
= BAD_ARGS
;
8586 skip_whitespace (str
);
8588 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8591 skip_whitespace (str
);
8595 inst
.error
= BAD_ARGS
;
8607 _("r15 not allowed as base register with write-back");
8614 if (inst
.instruction
& CP_T_Pre
)
8616 /* Pre-decrement. */
8617 offset
= 3 * num_regs
;
8619 inst
.instruction
|= CP_T_WB
;
8623 /* Post-increment. */
8626 inst
.instruction
|= CP_T_WB
;
8627 offset
= 3 * num_regs
;
8631 /* No write-back, so convert this into a standard pre-increment
8632 instruction -- aesthetically more pleasing. */
8633 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8638 inst
.instruction
|= offset
;
8640 else if (skip_past_comma (&str
) == FAIL
8641 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8644 inst
.error
= BAD_ARGS
;
8655 skip_whitespace (str
);
8657 if (fp_reg_required_here (&str
, 12) == FAIL
)
8660 inst
.error
= BAD_ARGS
;
8664 if (skip_past_comma (&str
) == FAIL
8665 || fp_reg_required_here (&str
, 16) == FAIL
)
8668 inst
.error
= BAD_ARGS
;
8672 if (skip_past_comma (&str
) == FAIL
8673 || fp_op2 (&str
) == FAIL
)
8676 inst
.error
= BAD_ARGS
;
8684 do_fpa_monadic (str
)
8687 skip_whitespace (str
);
8689 if (fp_reg_required_here (&str
, 12) == FAIL
)
8692 inst
.error
= BAD_ARGS
;
8696 if (skip_past_comma (&str
) == FAIL
8697 || fp_op2 (&str
) == FAIL
)
8700 inst
.error
= BAD_ARGS
;
8711 skip_whitespace (str
);
8713 if (fp_reg_required_here (&str
, 16) == FAIL
)
8716 inst
.error
= BAD_ARGS
;
8720 if (skip_past_comma (&str
) == FAIL
8721 || fp_op2 (&str
) == FAIL
)
8724 inst
.error
= BAD_ARGS
;
8732 do_fpa_from_reg (str
)
8735 skip_whitespace (str
);
8737 if (fp_reg_required_here (&str
, 16) == FAIL
)
8740 inst
.error
= BAD_ARGS
;
8744 if (skip_past_comma (&str
) == FAIL
8745 || reg_required_here (&str
, 12) == FAIL
)
8748 inst
.error
= BAD_ARGS
;
8759 skip_whitespace (str
);
8761 if (reg_required_here (&str
, 12) == FAIL
)
8764 if (skip_past_comma (&str
) == FAIL
8765 || fp_reg_required_here (&str
, 0) == FAIL
)
8768 inst
.error
= BAD_ARGS
;
8776 vfp_sp_reg_required_here (str
, pos
)
8778 enum vfp_sp_reg_pos pos
;
8783 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8788 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8792 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8796 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8805 /* In the few cases where we might be able to accept something else
8806 this error can be overridden. */
8807 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8809 /* Restore the start point. */
8815 vfp_dp_reg_required_here (str
, pos
)
8817 enum vfp_dp_reg_pos pos
;
8822 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8827 inst
.instruction
|= reg
<< 12;
8831 inst
.instruction
|= reg
<< 16;
8835 inst
.instruction
|= reg
<< 0;
8844 /* In the few cases where we might be able to accept something else
8845 this error can be overridden. */
8846 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8848 /* Restore the start point. */
8854 do_vfp_sp_monadic (str
)
8857 skip_whitespace (str
);
8859 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8862 if (skip_past_comma (&str
) == FAIL
8863 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8866 inst
.error
= BAD_ARGS
;
8874 do_vfp_dp_monadic (str
)
8877 skip_whitespace (str
);
8879 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8882 if (skip_past_comma (&str
) == FAIL
8883 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8886 inst
.error
= BAD_ARGS
;
8894 do_vfp_sp_dyadic (str
)
8897 skip_whitespace (str
);
8899 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8902 if (skip_past_comma (&str
) == FAIL
8903 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8904 || skip_past_comma (&str
) == FAIL
8905 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8908 inst
.error
= BAD_ARGS
;
8916 do_vfp_dp_dyadic (str
)
8919 skip_whitespace (str
);
8921 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8924 if (skip_past_comma (&str
) == FAIL
8925 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8926 || skip_past_comma (&str
) == FAIL
8927 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8930 inst
.error
= BAD_ARGS
;
8938 do_vfp_reg_from_sp (str
)
8941 skip_whitespace (str
);
8943 if (reg_required_here (&str
, 12) == FAIL
)
8946 if (skip_past_comma (&str
) == FAIL
8947 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8950 inst
.error
= BAD_ARGS
;
8958 do_vfp_reg2_from_sp2 (str
)
8961 skip_whitespace (str
);
8963 if (reg_required_here (&str
, 12) == FAIL
8964 || skip_past_comma (&str
) == FAIL
8965 || reg_required_here (&str
, 16) == FAIL
8966 || skip_past_comma (&str
) == FAIL
)
8969 inst
.error
= BAD_ARGS
;
8973 /* We require exactly two consecutive SP registers. */
8974 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8977 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8984 do_vfp_sp_from_reg (str
)
8987 skip_whitespace (str
);
8989 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8992 if (skip_past_comma (&str
) == FAIL
8993 || reg_required_here (&str
, 12) == FAIL
)
8996 inst
.error
= BAD_ARGS
;
9004 do_vfp_sp2_from_reg2 (str
)
9007 skip_whitespace (str
);
9009 /* We require exactly two consecutive SP registers. */
9010 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
9013 inst
.error
= _("only two consecutive VFP SP registers allowed here");
9016 if (skip_past_comma (&str
) == FAIL
9017 || reg_required_here (&str
, 12) == FAIL
9018 || skip_past_comma (&str
) == FAIL
9019 || reg_required_here (&str
, 16) == FAIL
)
9022 inst
.error
= BAD_ARGS
;
9030 do_vfp_reg_from_dp (str
)
9033 skip_whitespace (str
);
9035 if (reg_required_here (&str
, 12) == FAIL
)
9038 if (skip_past_comma (&str
) == FAIL
9039 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9042 inst
.error
= BAD_ARGS
;
9050 do_vfp_reg2_from_dp (str
)
9053 skip_whitespace (str
);
9055 if (reg_required_here (&str
, 12) == FAIL
)
9058 if (skip_past_comma (&str
) == FAIL
9059 || reg_required_here (&str
, 16) == FAIL
9060 || skip_past_comma (&str
) == FAIL
9061 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9064 inst
.error
= BAD_ARGS
;
9072 do_vfp_dp_from_reg (str
)
9075 skip_whitespace (str
);
9077 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9080 if (skip_past_comma (&str
) == FAIL
9081 || reg_required_here (&str
, 12) == FAIL
)
9084 inst
.error
= BAD_ARGS
;
9092 do_vfp_dp_from_reg2 (str
)
9095 skip_whitespace (str
);
9097 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9100 if (skip_past_comma (&str
) == FAIL
9101 || reg_required_here (&str
, 12) == FAIL
9102 || skip_past_comma (&str
) == FAIL
9103 || reg_required_here (&str
, 16) == FAIL
)
9106 inst
.error
= BAD_ARGS
;
9113 static const struct vfp_reg
*
9120 const struct vfp_reg
*vreg
;
9124 /* Find the end of the current token. */
9129 while (ISALPHA (c
));
9134 for (vreg
= vfp_regs
+ 0;
9135 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9138 if (strcmp (start
, vreg
->name
) == 0)
9151 vfp_psr_required_here (str
)
9155 const struct vfp_reg
*vreg
;
9157 vreg
= vfp_psr_parse (str
);
9161 inst
.instruction
|= vreg
->regno
;
9165 inst
.error
= _("VFP system register expected");
9172 do_vfp_reg_from_ctrl (str
)
9175 skip_whitespace (str
);
9177 if (reg_required_here (&str
, 12) == FAIL
)
9180 if (skip_past_comma (&str
) == FAIL
9181 || vfp_psr_required_here (&str
) == FAIL
)
9184 inst
.error
= BAD_ARGS
;
9192 do_vfp_ctrl_from_reg (str
)
9195 skip_whitespace (str
);
9197 if (vfp_psr_required_here (&str
) == FAIL
)
9200 if (skip_past_comma (&str
) == FAIL
9201 || reg_required_here (&str
, 12) == FAIL
)
9204 inst
.error
= BAD_ARGS
;
9212 do_vfp_sp_ldst (str
)
9215 skip_whitespace (str
);
9217 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9220 inst
.error
= BAD_ARGS
;
9224 if (skip_past_comma (&str
) == FAIL
9225 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9228 inst
.error
= BAD_ARGS
;
9236 do_vfp_dp_ldst (str
)
9239 skip_whitespace (str
);
9241 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9244 inst
.error
= BAD_ARGS
;
9248 if (skip_past_comma (&str
) == FAIL
9249 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9252 inst
.error
= BAD_ARGS
;
9259 /* Parse and encode a VFP SP register list, storing the initial
9260 register in position POS and returning the range as the result. If
9261 the string is invalid return FAIL (an invalid range). */
9263 vfp_sp_reg_list (str
, pos
)
9265 enum vfp_sp_reg_pos pos
;
9273 unsigned long mask
= 0;
9280 skip_whitespace (*str
);
9282 tempinst
= inst
.instruction
;
9286 inst
.instruction
= 0;
9288 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9291 if (count
== 0 || base_reg
> new_base
)
9293 base_reg
= new_base
;
9294 base_bits
= inst
.instruction
;
9297 if (mask
& (1 << new_base
))
9299 inst
.error
= _("invalid register list");
9303 if ((mask
>> new_base
) != 0 && ! warned
)
9305 as_tsktsk (_("register list not in ascending order"));
9309 mask
|= 1 << new_base
;
9312 skip_whitespace (*str
);
9314 if (**str
== '-') /* We have the start of a range expression */
9321 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9324 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9328 if (high_range
<= new_base
)
9330 inst
.error
= _("register range not in ascending order");
9334 for (new_base
++; new_base
<= high_range
; new_base
++)
9336 if (mask
& (1 << new_base
))
9338 inst
.error
= _("invalid register list");
9342 mask
|= 1 << new_base
;
9347 while (skip_past_comma (str
) != FAIL
);
9351 inst
.error
= _("invalid register list");
9359 /* Sanity check -- should have raised a parse error above. */
9360 if (count
== 0 || count
> 32)
9363 /* Final test -- the registers must be consecutive. */
9366 if ((mask
& (1 << base_reg
++)) == 0)
9368 inst
.error
= _("non-contiguous register range");
9373 inst
.instruction
= tempinst
| base_bits
;
9378 vfp_dp_reg_list (str
)
9386 unsigned long mask
= 0;
9393 skip_whitespace (*str
);
9395 tempinst
= inst
.instruction
;
9399 inst
.instruction
= 0;
9401 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9404 if (count
== 0 || base_reg
> new_base
)
9406 base_reg
= new_base
;
9407 range
= inst
.instruction
;
9410 if (mask
& (1 << new_base
))
9412 inst
.error
= _("invalid register list");
9416 if ((mask
>> new_base
) != 0 && ! warned
)
9418 as_tsktsk (_("register list not in ascending order"));
9422 mask
|= 1 << new_base
;
9425 skip_whitespace (*str
);
9427 if (**str
== '-') /* We have the start of a range expression */
9434 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9437 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9441 if (high_range
<= new_base
)
9443 inst
.error
= _("register range not in ascending order");
9447 for (new_base
++; new_base
<= high_range
; new_base
++)
9449 if (mask
& (1 << new_base
))
9451 inst
.error
= _("invalid register list");
9455 mask
|= 1 << new_base
;
9460 while (skip_past_comma (str
) != FAIL
);
9464 inst
.error
= _("invalid register list");
9472 /* Sanity check -- should have raised a parse error above. */
9473 if (count
== 0 || count
> 16)
9476 /* Final test -- the registers must be consecutive. */
9479 if ((mask
& (1 << base_reg
++)) == 0)
9481 inst
.error
= _("non-contiguous register range");
9486 inst
.instruction
= tempinst
;
9491 vfp_sp_ldstm (str
, ldstm_type
)
9493 enum vfp_ldstm_type ldstm_type
;
9497 skip_whitespace (str
);
9499 if (reg_required_here (&str
, 16) == FAIL
)
9502 skip_whitespace (str
);
9506 inst
.instruction
|= WRITE_BACK
;
9509 else if (ldstm_type
!= VFP_LDSTMIA
)
9511 inst
.error
= _("this addressing mode requires base-register writeback");
9515 if (skip_past_comma (&str
) == FAIL
9516 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9519 inst
.error
= BAD_ARGS
;
9523 inst
.instruction
|= range
;
9528 vfp_dp_ldstm (str
, ldstm_type
)
9530 enum vfp_ldstm_type ldstm_type
;
9534 skip_whitespace (str
);
9536 if (reg_required_here (&str
, 16) == FAIL
)
9539 skip_whitespace (str
);
9543 inst
.instruction
|= WRITE_BACK
;
9546 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9548 inst
.error
= _("this addressing mode requires base-register writeback");
9552 if (skip_past_comma (&str
) == FAIL
9553 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9556 inst
.error
= BAD_ARGS
;
9560 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9563 inst
.instruction
|= range
;
9568 do_vfp_sp_ldstmia (str
)
9571 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9575 do_vfp_sp_ldstmdb (str
)
9578 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9582 do_vfp_dp_ldstmia (str
)
9585 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9589 do_vfp_dp_ldstmdb (str
)
9592 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9596 do_vfp_xp_ldstmia (str
)
9599 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9603 do_vfp_xp_ldstmdb (str
)
9606 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9610 do_vfp_sp_compare_z (str
)
9613 skip_whitespace (str
);
9615 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9618 inst
.error
= BAD_ARGS
;
9626 do_vfp_dp_compare_z (str
)
9629 skip_whitespace (str
);
9631 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9634 inst
.error
= BAD_ARGS
;
9642 do_vfp_dp_sp_cvt (str
)
9645 skip_whitespace (str
);
9647 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9650 if (skip_past_comma (&str
) == FAIL
9651 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9654 inst
.error
= BAD_ARGS
;
9662 do_vfp_sp_dp_cvt (str
)
9665 skip_whitespace (str
);
9667 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9670 if (skip_past_comma (&str
) == FAIL
9671 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9674 inst
.error
= BAD_ARGS
;
9681 /* Thumb specific routines. */
9683 /* Parse and validate that a register is of the right form, this saves
9684 repeated checking of this information in many similar cases.
9685 Unlike the 32-bit case we do not insert the register into the opcode
9686 here, since the position is often unknown until the full instruction
9690 thumb_reg (strp
, hi_lo
)
9696 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9704 inst
.error
= _("lo register required");
9712 inst
.error
= _("hi register required");
9724 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9728 thumb_add_sub (str
, subtract
)
9732 int Rd
, Rs
, Rn
= FAIL
;
9734 skip_whitespace (str
);
9736 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9737 || skip_past_comma (&str
) == FAIL
)
9740 inst
.error
= BAD_ARGS
;
9744 if (is_immediate_prefix (*str
))
9748 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9753 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9756 if (skip_past_comma (&str
) == FAIL
)
9758 /* Two operand format, shuffle the registers
9759 and pretend there are 3. */
9763 else if (is_immediate_prefix (*str
))
9766 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9769 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9773 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9774 for the latter case, EXPR contains the immediate that was found. */
9777 /* All register format. */
9778 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9782 inst
.error
= _("dest and source1 must be the same register");
9786 /* Can't do this for SUB. */
9789 inst
.error
= _("subtract valid only on lo regs");
9793 inst
.instruction
= (T_OPCODE_ADD_HI
9794 | (Rd
> 7 ? THUMB_H1
: 0)
9795 | (Rn
> 7 ? THUMB_H2
: 0));
9796 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9800 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9801 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9806 /* Immediate expression, now things start to get nasty. */
9808 /* First deal with HI regs, only very restricted cases allowed:
9809 Adjusting SP, and using PC or SP to get an address. */
9810 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9811 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9813 inst
.error
= _("invalid Hi register with immediate");
9817 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9819 /* Value isn't known yet, all we can do is store all the fragments
9820 we know about in the instruction and let the reloc hacking
9822 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9823 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9827 int offset
= inst
.reloc
.exp
.X_add_number
;
9837 /* Quick check, in case offset is MIN_INT. */
9840 inst
.error
= _("immediate value out of range");
9844 /* Note - you cannot convert a subtract of 0 into an
9845 add of 0 because the carry flag is set differently. */
9846 else if (offset
> 0)
9851 if (offset
& ~0x1fc)
9853 inst
.error
= _("invalid immediate value for stack adjust");
9856 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9857 inst
.instruction
|= offset
>> 2;
9859 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9862 || (offset
& ~0x3fc))
9864 inst
.error
= _("invalid immediate for address calculation");
9867 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9869 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9875 inst
.error
= _("immediate value out of range");
9878 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9879 inst
.instruction
|= (Rd
<< 8) | offset
;
9885 inst
.error
= _("immediate value out of range");
9888 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9889 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9898 thumb_shift (str
, shift
)
9902 int Rd
, Rs
, Rn
= FAIL
;
9904 skip_whitespace (str
);
9906 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9907 || skip_past_comma (&str
) == FAIL
)
9910 inst
.error
= BAD_ARGS
;
9914 if (is_immediate_prefix (*str
))
9916 /* Two operand immediate format, set Rs to Rd. */
9919 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9924 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9927 if (skip_past_comma (&str
) == FAIL
)
9929 /* Two operand format, shuffle the registers
9930 and pretend there are 3. */
9934 else if (is_immediate_prefix (*str
))
9937 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9940 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9944 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9945 for the latter case, EXPR contains the immediate that was found. */
9951 inst
.error
= _("source1 and dest must be same register");
9957 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9958 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9959 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9962 inst
.instruction
|= Rd
| (Rn
<< 3);
9968 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9969 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9970 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9973 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9975 /* Value isn't known yet, create a dummy reloc and let reloc
9976 hacking fix it up. */
9977 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9981 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9983 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9985 inst
.error
= _("invalid immediate for shift");
9989 /* Shifts of zero are handled by converting to LSL. */
9990 if (shift_value
== 0)
9991 inst
.instruction
= T_OPCODE_LSL_I
;
9993 /* Shifts of 32 are encoded as a shift of zero. */
9994 if (shift_value
== 32)
9997 inst
.instruction
|= shift_value
<< 6;
10000 inst
.instruction
|= Rd
| (Rs
<< 3);
10007 thumb_mov_compare (str
, move
)
10013 skip_whitespace (str
);
10015 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
10016 || skip_past_comma (&str
) == FAIL
)
10019 inst
.error
= BAD_ARGS
;
10023 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
10026 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10029 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10034 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
10036 if (move
== THUMB_MOVE
)
10037 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10038 since a MOV instruction produces unpredictable results. */
10039 inst
.instruction
= T_OPCODE_ADD_I3
;
10041 inst
.instruction
= T_OPCODE_CMP_LR
;
10042 inst
.instruction
|= Rd
| (Rs
<< 3);
10046 if (move
== THUMB_MOVE
)
10047 inst
.instruction
= T_OPCODE_MOV_HR
;
10048 else if (move
!= THUMB_CPY
)
10049 inst
.instruction
= T_OPCODE_CMP_HR
;
10052 inst
.instruction
|= THUMB_H1
;
10055 inst
.instruction
|= THUMB_H2
;
10057 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
10064 inst
.error
= _("only lo regs allowed with immediate");
10068 if (move
== THUMB_MOVE
)
10069 inst
.instruction
= T_OPCODE_MOV_I8
;
10071 inst
.instruction
= T_OPCODE_CMP_I8
;
10073 inst
.instruction
|= Rd
<< 8;
10075 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10076 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10079 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10083 inst
.error
= _("invalid immediate");
10087 inst
.instruction
|= value
;
10095 thumb_load_store (str
, load_store
, size
)
10100 int Rd
, Rb
, Ro
= FAIL
;
10102 skip_whitespace (str
);
10104 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10105 || skip_past_comma (&str
) == FAIL
)
10108 inst
.error
= BAD_ARGS
;
10115 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10118 if (skip_past_comma (&str
) != FAIL
)
10120 if (is_immediate_prefix (*str
))
10123 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10126 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10131 inst
.reloc
.exp
.X_op
= O_constant
;
10132 inst
.reloc
.exp
.X_add_number
= 0;
10137 inst
.error
= _("expected ']'");
10142 else if (*str
== '=')
10144 if (load_store
!= THUMB_LOAD
)
10146 inst
.error
= _("invalid pseudo operation");
10150 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10153 skip_whitespace (str
);
10155 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10160 if ( inst
.reloc
.exp
.X_op
!= O_constant
10161 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10163 inst
.error
= "Constant expression expected";
10167 if (inst
.reloc
.exp
.X_op
== O_constant
10168 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10170 /* This can be done with a mov instruction. */
10172 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10173 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10177 /* Insert into literal pool. */
10178 if (add_to_lit_pool () == FAIL
)
10181 inst
.error
= "literal pool insertion failed";
10185 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10186 inst
.reloc
.pc_rel
= 1;
10187 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10188 /* Adjust ARM pipeline offset to Thumb. */
10189 inst
.reloc
.exp
.X_add_number
+= 4;
10195 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10198 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10199 inst
.reloc
.pc_rel
= 1;
10200 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10201 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10206 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10208 if (size
!= THUMB_WORD
)
10210 inst
.error
= _("byte or halfword not valid for base register");
10213 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10215 inst
.error
= _("r15 based store not allowed");
10218 else if (Ro
!= FAIL
)
10220 inst
.error
= _("invalid base register for register offset");
10225 inst
.instruction
= T_OPCODE_LDR_PC
;
10226 else if (load_store
== THUMB_LOAD
)
10227 inst
.instruction
= T_OPCODE_LDR_SP
;
10229 inst
.instruction
= T_OPCODE_STR_SP
;
10231 inst
.instruction
|= Rd
<< 8;
10232 if (inst
.reloc
.exp
.X_op
== O_constant
)
10234 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10236 if (offset
& ~0x3fc)
10238 inst
.error
= _("invalid offset");
10242 inst
.instruction
|= offset
>> 2;
10245 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10249 inst
.error
= _("invalid base register in load/store");
10252 else if (Ro
== FAIL
)
10254 /* Immediate offset. */
10255 if (size
== THUMB_WORD
)
10256 inst
.instruction
= (load_store
== THUMB_LOAD
10257 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10258 else if (size
== THUMB_HALFWORD
)
10259 inst
.instruction
= (load_store
== THUMB_LOAD
10260 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10262 inst
.instruction
= (load_store
== THUMB_LOAD
10263 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10265 inst
.instruction
|= Rd
| (Rb
<< 3);
10267 if (inst
.reloc
.exp
.X_op
== O_constant
)
10269 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10271 if (offset
& ~(0x1f << size
))
10273 inst
.error
= _("invalid offset");
10276 inst
.instruction
|= (offset
>> size
) << 6;
10279 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10283 /* Register offset. */
10284 if (size
== THUMB_WORD
)
10285 inst
.instruction
= (load_store
== THUMB_LOAD
10286 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10287 else if (size
== THUMB_HALFWORD
)
10288 inst
.instruction
= (load_store
== THUMB_LOAD
10289 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10291 inst
.instruction
= (load_store
== THUMB_LOAD
10292 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10294 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10300 /* A register must be given at this point.
10302 Shift is the place to put it in inst.instruction.
10304 Restores input start point on err.
10305 Returns the reg#, or FAIL. */
10308 mav_reg_required_here (str
, shift
, regtype
)
10311 enum arm_reg_type regtype
;
10314 char *start
= *str
;
10316 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10319 inst
.instruction
|= reg
<< shift
;
10324 /* Restore the start point. */
10327 /* In the few cases where we might be able to accept something else
10328 this error can be overridden. */
10329 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10334 /* Cirrus Maverick Instructions. */
10336 /* Wrapper functions. */
10339 do_mav_binops_1a (str
)
10342 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10346 do_mav_binops_1b (str
)
10349 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10353 do_mav_binops_1c (str
)
10356 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10360 do_mav_binops_1d (str
)
10363 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10367 do_mav_binops_1e (str
)
10370 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10374 do_mav_binops_1f (str
)
10377 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10381 do_mav_binops_1g (str
)
10384 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10388 do_mav_binops_1h (str
)
10391 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10395 do_mav_binops_1i (str
)
10398 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10402 do_mav_binops_1j (str
)
10405 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10409 do_mav_binops_1k (str
)
10412 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10416 do_mav_binops_1l (str
)
10419 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10423 do_mav_binops_1m (str
)
10426 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10430 do_mav_binops_1n (str
)
10433 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10437 do_mav_binops_1o (str
)
10440 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10444 do_mav_binops_2a (str
)
10447 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10451 do_mav_binops_2b (str
)
10454 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10458 do_mav_binops_2c (str
)
10461 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10465 do_mav_binops_3a (str
)
10468 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10472 do_mav_binops_3b (str
)
10475 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10479 do_mav_binops_3c (str
)
10482 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10486 do_mav_binops_3d (str
)
10489 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10493 do_mav_triple_4a (str
)
10496 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10500 do_mav_triple_4b (str
)
10503 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10507 do_mav_triple_5a (str
)
10510 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10514 do_mav_triple_5b (str
)
10517 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10521 do_mav_triple_5c (str
)
10524 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10528 do_mav_triple_5d (str
)
10531 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10535 do_mav_triple_5e (str
)
10538 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10542 do_mav_triple_5f (str
)
10545 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10549 do_mav_triple_5g (str
)
10552 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10556 do_mav_triple_5h (str
)
10559 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10563 do_mav_quad_6a (str
)
10566 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10571 do_mav_quad_6b (str
)
10574 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10578 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
10580 do_mav_dspsc_1 (str
)
10583 skip_whitespace (str
);
10586 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10587 || skip_past_comma (&str
) == FAIL
10588 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
10591 inst
.error
= BAD_ARGS
;
10599 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
10601 do_mav_dspsc_2 (str
)
10604 skip_whitespace (str
);
10607 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
10608 || skip_past_comma (&str
) == FAIL
10609 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10612 inst
.error
= BAD_ARGS
;
10621 do_mav_shift_1 (str
)
10624 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10628 do_mav_shift_2 (str
)
10631 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10635 do_mav_ldst_1 (str
)
10638 do_mav_ldst (str
, REG_TYPE_MVF
);
10642 do_mav_ldst_2 (str
)
10645 do_mav_ldst (str
, REG_TYPE_MVD
);
10649 do_mav_ldst_3 (str
)
10652 do_mav_ldst (str
, REG_TYPE_MVFX
);
10656 do_mav_ldst_4 (str
)
10659 do_mav_ldst (str
, REG_TYPE_MVDX
);
10662 /* Isnsn like "foo X,Y". */
10665 do_mav_binops (str
, mode
, reg0
, reg1
)
10668 enum arm_reg_type reg0
;
10669 enum arm_reg_type reg1
;
10671 int shift0
, shift1
;
10673 shift0
= mode
& 0xff;
10674 shift1
= (mode
>> 8) & 0xff;
10676 skip_whitespace (str
);
10678 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10679 || skip_past_comma (&str
) == FAIL
10680 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10683 inst
.error
= BAD_ARGS
;
10689 /* Isnsn like "foo X,Y,Z". */
10692 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10695 enum arm_reg_type reg0
;
10696 enum arm_reg_type reg1
;
10697 enum arm_reg_type reg2
;
10699 int shift0
, shift1
, shift2
;
10701 shift0
= mode
& 0xff;
10702 shift1
= (mode
>> 8) & 0xff;
10703 shift2
= (mode
>> 16) & 0xff;
10705 skip_whitespace (str
);
10707 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10708 || skip_past_comma (&str
) == FAIL
10709 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10710 || skip_past_comma (&str
) == FAIL
10711 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10714 inst
.error
= BAD_ARGS
;
10720 /* Isnsn like "foo W,X,Y,Z".
10721 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10724 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10727 enum arm_reg_type reg0
;
10728 enum arm_reg_type reg1
;
10729 enum arm_reg_type reg2
;
10730 enum arm_reg_type reg3
;
10732 int shift0
, shift1
, shift2
, shift3
;
10734 shift0
= mode
& 0xff;
10735 shift1
= (mode
>> 8) & 0xff;
10736 shift2
= (mode
>> 16) & 0xff;
10737 shift3
= (mode
>> 24) & 0xff;
10739 skip_whitespace (str
);
10741 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10742 || skip_past_comma (&str
) == FAIL
10743 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10744 || skip_past_comma (&str
) == FAIL
10745 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10746 || skip_past_comma (&str
) == FAIL
10747 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10750 inst
.error
= BAD_ARGS
;
10756 /* Maverick shift immediate instructions.
10757 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10758 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10761 do_mav_shift (str
, reg0
, reg1
)
10763 enum arm_reg_type reg0
;
10764 enum arm_reg_type reg1
;
10769 skip_whitespace (str
);
10773 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10774 || skip_past_comma (&str
) == FAIL
10775 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10776 || skip_past_comma (&str
) == FAIL
)
10779 inst
.error
= BAD_ARGS
;
10783 /* Calculate the immediate operand.
10784 The operand is a 7bit signed number. */
10785 skip_whitespace (str
);
10790 if (!ISDIGIT (*str
) && *str
!= '-')
10792 inst
.error
= _("expecting immediate, 7bit operand");
10802 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10803 imm
= imm
* 10 + *str
- '0';
10807 inst
.error
= _("immediate out of range");
10811 /* Make negative imm's into 7bit signed numbers. */
10818 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10819 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10820 Bit 4 should be 0. */
10821 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10823 inst
.instruction
|= imm
;
10828 mav_parse_offset (str
, negative
)
10837 skip_whitespace (p
);
10850 inst
.error
= _("offset expected");
10854 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10855 offset
= offset
* 10 + *p
- '0';
10859 inst
.error
= _("offset out of range");
10865 return *negative
? -offset
: offset
;
10868 /* Maverick load/store instructions.
10869 <insn><cond> CRd,[Rn,<offset>]{!}.
10870 <insn><cond> CRd,[Rn],<offset>. */
10873 do_mav_ldst (str
, reg0
)
10875 enum arm_reg_type reg0
;
10877 int offset
, negative
;
10879 skip_whitespace (str
);
10881 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10882 || skip_past_comma (&str
) == FAIL
10884 || reg_required_here (&str
, 16) == FAIL
)
10887 if (skip_past_comma (&str
) == SUCCESS
)
10889 /* You are here: "<offset>]{!}". */
10890 inst
.instruction
|= PRE_INDEX
;
10892 offset
= mav_parse_offset (&str
, &negative
);
10899 inst
.error
= _("missing ]");
10905 inst
.instruction
|= WRITE_BACK
;
10911 /* You are here: "], <offset>". */
10914 inst
.error
= _("missing ]");
10918 if (skip_past_comma (&str
) == FAIL
10919 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10922 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10928 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10930 inst
.instruction
|= offset
>> 2;
10936 inst
.error
= BAD_ARGS
;
10947 /* Handle the Format 4 instructions that do not have equivalents in other
10948 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10957 skip_whitespace (str
);
10959 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10960 || skip_past_comma (&str
) == FAIL
10961 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10963 inst
.error
= BAD_ARGS
;
10967 if (skip_past_comma (&str
) != FAIL
)
10969 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10970 (It isn't allowed for CMP either, but that isn't handled by this
10972 if (inst
.instruction
== T_OPCODE_TST
10973 || inst
.instruction
== T_OPCODE_CMN
10974 || inst
.instruction
== T_OPCODE_NEG
10975 || inst
.instruction
== T_OPCODE_MVN
)
10977 inst
.error
= BAD_ARGS
;
10981 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10986 inst
.error
= _("dest and source1 must be the same register");
10992 if (inst
.instruction
== T_OPCODE_MUL
10994 as_tsktsk (_("Rs and Rd must be different in MUL"));
10996 inst
.instruction
|= Rd
| (Rs
<< 3);
11004 thumb_add_sub (str
, 0);
11011 thumb_shift (str
, THUMB_ASR
);
11018 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11020 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
11021 inst
.reloc
.pc_rel
= 1;
11026 do_t_branch12 (str
)
11029 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11031 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
11032 inst
.reloc
.pc_rel
= 1;
11036 /* Find the real, Thumb encoded start of a Thumb function. */
11039 find_real_start (symbolP
)
11043 const char * name
= S_GET_NAME (symbolP
);
11044 symbolS
* new_target
;
11046 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11047 #define STUB_NAME ".real_start_of"
11052 /* Names that start with '.' are local labels, not function entry points.
11053 The compiler may generate BL instructions to these labels because it
11054 needs to perform a branch to a far away location. */
11055 if (name
[0] == '.')
11058 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
11059 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
11061 new_target
= symbol_find (real_start
);
11063 if (new_target
== NULL
)
11065 as_warn ("Failed to find real start of function: %s\n", name
);
11066 new_target
= symbolP
;
11075 do_t_branch23 (str
)
11078 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11081 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11082 inst
.reloc
.pc_rel
= 1;
11085 /* If the destination of the branch is a defined symbol which does not have
11086 the THUMB_FUNC attribute, then we must be calling a function which has
11087 the (interfacearm) attribute. We look for the Thumb entry point to that
11088 function and change the branch to refer to that function instead. */
11089 if ( inst
.reloc
.exp
.X_op
== O_symbol
11090 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11091 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11092 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11093 inst
.reloc
.exp
.X_add_symbol
=
11094 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11103 skip_whitespace (str
);
11105 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11108 /* This sets THUMB_H2 from the top bit of reg. */
11109 inst
.instruction
|= reg
<< 3;
11111 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11112 should cause the alignment to be checked once it is known. This is
11113 because BX PC only works if the instruction is word aligned. */
11122 thumb_mov_compare (str
, THUMB_COMPARE
);
11132 skip_whitespace (str
);
11134 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11138 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11142 if (skip_past_comma (&str
) == FAIL
11143 || (range
= reg_list (&str
)) == FAIL
)
11146 inst
.error
= BAD_ARGS
;
11150 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11152 /* This really doesn't seem worth it. */
11153 inst
.reloc
.type
= BFD_RELOC_NONE
;
11154 inst
.error
= _("expression too complex");
11160 inst
.error
= _("only lo-regs valid in load/store multiple");
11164 inst
.instruction
|= (Rb
<< 8) | range
;
11172 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11179 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11186 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11195 skip_whitespace (str
);
11197 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11198 || skip_past_comma (&str
) == FAIL
11200 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11201 || skip_past_comma (&str
) == FAIL
11202 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11206 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11210 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11218 thumb_shift (str
, THUMB_LSL
);
11225 thumb_shift (str
, THUMB_LSR
);
11232 thumb_mov_compare (str
, THUMB_MOVE
);
11236 do_t_push_pop (str
)
11241 skip_whitespace (str
);
11243 if ((range
= reg_list (&str
)) == FAIL
)
11246 inst
.error
= BAD_ARGS
;
11250 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11252 /* This really doesn't seem worth it. */
11253 inst
.reloc
.type
= BFD_RELOC_NONE
;
11254 inst
.error
= _("expression too complex");
11260 if ((inst
.instruction
== T_OPCODE_PUSH
11261 && (range
& ~0xff) == 1 << REG_LR
)
11262 || (inst
.instruction
== T_OPCODE_POP
11263 && (range
& ~0xff) == 1 << REG_PC
))
11265 inst
.instruction
|= THUMB_PP_PC_LR
;
11270 inst
.error
= _("invalid register list to push/pop instruction");
11275 inst
.instruction
|= range
;
11283 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11290 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11297 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11304 thumb_add_sub (str
, 1);
11311 skip_whitespace (str
);
11313 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11316 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11326 /* This is a pseudo-op of the form "adr rd, label" to be converted
11327 into a relative address of the form "add rd, pc, #label-.-4". */
11328 skip_whitespace (str
);
11330 /* Store Rd in temporary location inside instruction. */
11331 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11332 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11333 || skip_past_comma (&str
) == FAIL
11334 || my_get_expression (&inst
.reloc
.exp
, &str
))
11337 inst
.error
= BAD_ARGS
;
11341 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11342 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11343 inst
.reloc
.pc_rel
= 1;
11344 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11350 insert_reg (r
, htab
)
11351 const struct reg_entry
*r
;
11352 struct hash_control
*htab
;
11354 int len
= strlen (r
->name
) + 2;
11355 char * buf
= (char *) xmalloc (len
);
11356 char * buf2
= (char *) xmalloc (len
);
11359 #ifdef REGISTER_PREFIX
11360 buf
[i
++] = REGISTER_PREFIX
;
11363 strcpy (buf
+ i
, r
->name
);
11365 for (i
= 0; buf
[i
]; i
++)
11366 buf2
[i
] = TOUPPER (buf
[i
]);
11370 hash_insert (htab
, buf
, (PTR
) r
);
11371 hash_insert (htab
, buf2
, (PTR
) r
);
11375 build_reg_hsh (map
)
11376 struct reg_map
*map
;
11378 const struct reg_entry
*r
;
11380 if ((map
->htab
= hash_new ()) == NULL
)
11381 as_fatal (_("virtual memory exhausted"));
11383 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11384 insert_reg (r
, map
->htab
);
11388 insert_reg_alias (str
, regnum
, htab
)
11391 struct hash_control
*htab
;
11394 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11395 const char *name
= xmalloc (strlen (str
) + 1);
11397 strcpy ((char *) name
, str
);
11400 new->number
= regnum
;
11401 new->builtin
= FALSE
;
11403 error
= hash_insert (htab
, name
, (PTR
) new);
11406 as_bad (_("failed to create an alias for %s, reason: %s"),
11408 free ((char *) name
);
11413 /* Look for the .req directive. This is of the form:
11415 new_register_name .req existing_register_name
11417 If we find one, or if it looks sufficiently like one that we want to
11418 handle any error here, return non-zero. Otherwise return zero. */
11420 create_register_alias (newname
, p
)
11428 skip_whitespace (q
);
11433 if (*q
&& !strncmp (q
, ".req ", 5))
11438 #ifdef IGNORE_OPCODE_CASE
11439 newname
= original_case_string
;
11441 copy_of_str
= newname
;
11444 skip_whitespace (q
);
11446 for (r
= q
; *r
!= '\0'; r
++)
11452 enum arm_reg_type new_type
, old_type
;
11457 old_type
= arm_reg_parse_any (q
);
11460 new_type
= arm_reg_parse_any (newname
);
11462 if (new_type
== REG_TYPE_MAX
)
11464 if (old_type
!= REG_TYPE_MAX
)
11466 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11467 insert_reg_alias (newname
, old_regno
,
11468 all_reg_maps
[old_type
].htab
);
11471 as_warn (_("register '%s' does not exist\n"), q
);
11473 else if (old_type
== REG_TYPE_MAX
)
11475 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11480 /* Do not warn about redefinitions to the same alias. */
11481 if (new_type
!= old_type
11482 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11483 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11484 as_warn (_("ignoring redefinition of register alias '%s'"),
11490 as_warn (_("ignoring incomplete .req pseuso op"));
11501 set_constant_flonums ()
11505 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11506 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11510 /* Iterate over the base tables to create the instruction patterns. */
11512 build_arm_ops_hsh ()
11516 static struct obstack insn_obstack
;
11518 obstack_begin (&insn_obstack
, 4000);
11520 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11522 const struct asm_opcode
*insn
= insns
+ i
;
11524 if (insn
->cond_offset
!= 0)
11526 /* Insn supports conditional execution. Build the varaints
11527 and insert them in the hash table. */
11528 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11530 unsigned len
= strlen (insn
->template);
11531 struct asm_opcode
*new;
11534 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11535 /* All condition codes are two characters. */
11536 template = obstack_alloc (&insn_obstack
, len
+ 3);
11538 strncpy (template, insn
->template, insn
->cond_offset
);
11539 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11540 if (len
> insn
->cond_offset
)
11541 strcpy (template + insn
->cond_offset
+ 2,
11542 insn
->template + insn
->cond_offset
);
11543 new->template = template;
11544 new->cond_offset
= 0;
11545 new->variant
= insn
->variant
;
11546 new->parms
= insn
->parms
;
11547 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11549 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11552 /* Finally, insert the unconditional insn in the table directly;
11553 no need to build a copy. */
11554 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11558 #if 0 /* Suppressed - for now. */
11559 #if defined OBJ_ELF || defined OBJ_COFF
11562 #define arm_Note Elf_External_Note
11566 unsigned char namesz
[4]; /* Size of entry's owner string. */
11567 unsigned char descsz
[4]; /* Size of the note descriptor. */
11568 unsigned char type
[4]; /* Interpretation of the descriptor. */
11569 char name
[1]; /* Start of the name+desc data. */
11573 /* The description is kept to a fix sized in order to make updating
11574 it and merging it easier. */
11575 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11578 arm_add_note (name
, description
, type
)
11580 const char * description
;
11583 arm_Note note ATTRIBUTE_UNUSED
;
11585 unsigned int name_len
;
11587 name_len
= (strlen (name
) + 1 + 3) & ~3;
11589 p
= frag_more (sizeof (note
.namesz
));
11590 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11592 p
= frag_more (sizeof (note
.descsz
));
11593 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11595 p
= frag_more (sizeof (note
.type
));
11596 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11598 p
= frag_more (name_len
);
11601 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11602 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11603 frag_align (2, 0, 0);
11614 if ( (arm_ops_hsh
= hash_new ()) == NULL
11615 || (arm_tops_hsh
= hash_new ()) == NULL
11616 || (arm_cond_hsh
= hash_new ()) == NULL
11617 || (arm_shift_hsh
= hash_new ()) == NULL
11618 || (arm_psr_hsh
= hash_new ()) == NULL
)
11619 as_fatal (_("virtual memory exhausted"));
11621 build_arm_ops_hsh ();
11622 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11623 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11624 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11625 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11626 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11627 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11628 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11629 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11631 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11632 build_reg_hsh (all_reg_maps
+ i
);
11634 set_constant_flonums ();
11636 /* Set the cpu variant based on the command-line options. We prefer
11637 -mcpu= over -march= if both are set (as for GCC); and we prefer
11638 -mfpu= over any other way of setting the floating point unit.
11639 Use of legacy options with new options are faulted. */
11640 if (legacy_cpu
!= -1)
11642 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11643 as_bad (_("use of old and new-style options to set CPU type"));
11645 mcpu_cpu_opt
= legacy_cpu
;
11647 else if (mcpu_cpu_opt
== -1)
11648 mcpu_cpu_opt
= march_cpu_opt
;
11650 if (legacy_fpu
!= -1)
11652 if (mfpu_opt
!= -1)
11653 as_bad (_("use of old and new-style options to set FPU type"));
11655 mfpu_opt
= legacy_fpu
;
11657 else if (mfpu_opt
== -1)
11659 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11660 /* Some environments specify a default FPU. If they don't, infer it
11661 from the processor. */
11662 if (mcpu_fpu_opt
!= -1)
11663 mfpu_opt
= mcpu_fpu_opt
;
11665 mfpu_opt
= march_fpu_opt
;
11667 mfpu_opt
= FPU_DEFAULT
;
11671 if (mfpu_opt
== -1)
11673 if (mcpu_cpu_opt
== -1)
11674 mfpu_opt
= FPU_DEFAULT
;
11675 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11676 mfpu_opt
= FPU_ARCH_VFP_V2
;
11678 mfpu_opt
= FPU_ARCH_FPA
;
11681 if (mcpu_cpu_opt
== -1)
11682 mcpu_cpu_opt
= CPU_DEFAULT
;
11684 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11686 #if defined OBJ_COFF || defined OBJ_ELF
11688 unsigned int flags
= 0;
11690 /* Set the flags in the private structure. */
11691 if (uses_apcs_26
) flags
|= F_APCS26
;
11692 if (support_interwork
) flags
|= F_INTERWORK
;
11693 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11694 if (pic_code
) flags
|= F_PIC
;
11695 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11696 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11698 flags
|= F_SOFT_FLOAT
;
11700 switch (mfloat_abi_opt
)
11702 case ARM_FLOAT_ABI_SOFT
:
11703 case ARM_FLOAT_ABI_SOFTFP
:
11704 flags
|= F_SOFT_FLOAT
;
11707 case ARM_FLOAT_ABI_HARD
:
11708 if (flags
& F_SOFT_FLOAT
)
11709 as_bad (_("hard-float conflicts with specified fpu"));
11712 /* Using VFP conventions (even if soft-float). */
11713 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
11715 #if defined OBJ_ELF
11716 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11717 flags
|= EF_ARM_MAVERICK_FLOAT
;
11720 bfd_set_private_flags (stdoutput
, flags
);
11722 /* We have run out flags in the COFF header to encode the
11723 status of ATPCS support, so instead we create a dummy,
11724 empty, debug section called .arm.atpcs. */
11729 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11733 bfd_set_section_flags
11734 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11735 bfd_set_section_size (stdoutput
, sec
, 0);
11736 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11742 /* Record the CPU type as well. */
11743 switch (cpu_variant
& ARM_CPU_MASK
)
11746 mach
= bfd_mach_arm_2
;
11749 case ARM_3
: /* Also ARM_250. */
11750 mach
= bfd_mach_arm_2a
;
11753 case ARM_6
: /* Also ARM_7. */
11754 mach
= bfd_mach_arm_3
;
11758 mach
= bfd_mach_arm_unknown
;
11762 /* Catch special cases. */
11763 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11764 mach
= bfd_mach_arm_iWMMXt
;
11765 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11766 mach
= bfd_mach_arm_XScale
;
11767 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11768 mach
= bfd_mach_arm_ep9312
;
11769 else if (cpu_variant
& ARM_EXT_V5E
)
11770 mach
= bfd_mach_arm_5TE
;
11771 else if (cpu_variant
& ARM_EXT_V5
)
11773 if (cpu_variant
& ARM_EXT_V4T
)
11774 mach
= bfd_mach_arm_5T
;
11776 mach
= bfd_mach_arm_5
;
11778 else if (cpu_variant
& ARM_EXT_V4
)
11780 if (cpu_variant
& ARM_EXT_V4T
)
11781 mach
= bfd_mach_arm_4T
;
11783 mach
= bfd_mach_arm_4
;
11785 else if (cpu_variant
& ARM_EXT_V3M
)
11786 mach
= bfd_mach_arm_3M
;
11788 #if 0 /* Suppressed - for now. */
11789 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11791 /* Create a .note section to fully identify this arm binary. */
11793 #define NOTE_ARCH_STRING "arch: "
11795 #if defined OBJ_COFF && ! defined NT_VERSION
11796 #define NT_VERSION 1
11801 segT current_seg
= now_seg
;
11802 subsegT current_subseg
= now_subseg
;
11803 asection
* arm_arch
;
11804 const char * arch_string
;
11806 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11809 bfd_set_section_flags (stdoutput
, arm_arch
,
11810 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11811 | SEC_HAS_CONTENTS
);
11813 bfd_set_section_flags (stdoutput
, arm_arch
,
11814 SEC_READONLY
| SEC_HAS_CONTENTS
);
11816 arm_arch
->output_section
= arm_arch
;
11817 subseg_set (arm_arch
, 0);
11822 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11823 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11824 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11825 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11826 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11827 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11828 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11829 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11830 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11831 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11832 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11833 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11834 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11837 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11839 subseg_set (current_seg
, current_subseg
);
11842 #endif /* Suppressed code. */
11844 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11847 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11848 for use in the a.out file, and stores them in the array pointed to by buf.
11849 This knows about the endian-ness of the target machine and does
11850 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11851 2 (short) and 4 (long) Floating numbers are put out as a series of
11852 LITTLENUMS (shorts, here at least). */
11855 md_number_to_chars (buf
, val
, n
)
11860 if (target_big_endian
)
11861 number_to_chars_bigendian (buf
, val
, n
);
11863 number_to_chars_littleendian (buf
, val
, n
);
11867 md_chars_to_number (buf
, n
)
11872 unsigned char * where
= (unsigned char *) buf
;
11874 if (target_big_endian
)
11879 result
|= (*where
++ & 255);
11887 result
|= (where
[n
] & 255);
11894 /* Turn a string in input_line_pointer into a floating point constant
11895 of type TYPE, and store the appropriate bytes in *LITP. The number
11896 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11897 returned, or NULL on OK.
11899 Note that fp constants aren't represent in the normal way on the ARM.
11900 In big endian mode, things are as expected. However, in little endian
11901 mode fp constants are big-endian word-wise, and little-endian byte-wise
11902 within the words. For example, (double) 1.1 in big endian mode is
11903 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11904 the byte sequence 99 99 f1 3f 9a 99 99 99.
11906 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11909 md_atof (type
, litP
, sizeP
)
11915 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11947 return _("bad call to MD_ATOF()");
11950 t
= atof_ieee (input_line_pointer
, type
, words
);
11952 input_line_pointer
= t
;
11955 if (target_big_endian
)
11957 for (i
= 0; i
< prec
; i
++)
11959 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11965 if (cpu_variant
& FPU_ARCH_VFP
)
11966 for (i
= prec
- 1; i
>= 0; i
--)
11968 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11972 /* For a 4 byte float the order of elements in `words' is 1 0.
11973 For an 8 byte float the order is 1 0 3 2. */
11974 for (i
= 0; i
< prec
; i
+= 2)
11976 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11977 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11985 /* The knowledge of the PC's pipeline offset is built into the insns
11989 md_pcrel_from (fixP
)
11993 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11994 && fixP
->fx_subsy
== NULL
)
11997 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11999 /* PC relative addressing on the Thumb is slightly odd
12000 as the bottom two bits of the PC are forced to zero
12001 for the calculation. */
12002 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
12006 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12007 so we un-adjust here to compensate for the accommodation. */
12008 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
12010 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
12014 /* Round up a section size to the appropriate boundary. */
12017 md_section_align (segment
, size
)
12018 segT segment ATTRIBUTE_UNUSED
;
12024 /* Round all sects to multiple of 4. */
12025 return (size
+ 3) & ~3;
12029 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12030 Otherwise we have no need to default values of symbols. */
12033 md_undefined_symbol (name
)
12034 char * name ATTRIBUTE_UNUSED
;
12037 if (name
[0] == '_' && name
[1] == 'G'
12038 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
12042 if (symbol_find (name
))
12043 as_bad ("GOT already in the symbol table");
12045 GOT_symbol
= symbol_new (name
, undefined_section
,
12046 (valueT
) 0, & zero_address_frag
);
12056 /* arm_reg_parse () := if it looks like a register, return its token and
12057 advance the pointer. */
12060 arm_reg_parse (ccp
, htab
)
12061 register char ** ccp
;
12062 struct hash_control
*htab
;
12064 char * start
= * ccp
;
12067 struct reg_entry
* reg
;
12069 #ifdef REGISTER_PREFIX
12070 if (*start
!= REGISTER_PREFIX
)
12075 #ifdef OPTIONAL_REGISTER_PREFIX
12076 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12080 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12084 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12088 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12094 return reg
->number
;
12100 /* Search for the following register name in each of the possible reg name
12101 tables. Return the classification if found, or REG_TYPE_MAX if not
12103 static enum arm_reg_type
12104 arm_reg_parse_any (cp
)
12109 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12110 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12111 return (enum arm_reg_type
) i
;
12113 return REG_TYPE_MAX
;
12117 md_apply_fix3 (fixP
, valP
, seg
)
12122 offsetT value
= * valP
;
12124 unsigned int newimm
;
12125 unsigned long temp
;
12127 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12128 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12130 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12132 /* Note whether this will delete the relocation. */
12134 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12135 doesn't work fully.) */
12136 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12137 && !fixP
->fx_pcrel
)
12139 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12143 /* If this symbol is in a different section then we need to leave it for
12144 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12145 so we have to undo it's effects here. */
12146 if (fixP
->fx_pcrel
)
12148 if (fixP
->fx_addsy
!= NULL
12149 && S_IS_DEFINED (fixP
->fx_addsy
)
12150 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12153 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12154 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12158 value
+= md_pcrel_from (fixP
);
12162 /* Remember value for emit_reloc. */
12163 fixP
->fx_addnumber
= value
;
12165 switch (fixP
->fx_r_type
)
12167 case BFD_RELOC_ARM_IMMEDIATE
:
12168 newimm
= validate_immediate (value
);
12169 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12171 /* If the instruction will fail, see if we can fix things up by
12172 changing the opcode. */
12173 if (newimm
== (unsigned int) FAIL
12174 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12176 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12177 _("invalid constant (%lx) after fixup"),
12178 (unsigned long) value
);
12182 newimm
|= (temp
& 0xfffff000);
12183 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12187 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12189 unsigned int highpart
= 0;
12190 unsigned int newinsn
= 0xe1a00000; /* nop. */
12192 newimm
= validate_immediate (value
);
12193 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12195 /* If the instruction will fail, see if we can fix things up by
12196 changing the opcode. */
12197 if (newimm
== (unsigned int) FAIL
12198 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12200 /* No ? OK - try using two ADD instructions to generate
12202 newimm
= validate_immediate_twopart (value
, & highpart
);
12204 /* Yes - then make sure that the second instruction is
12206 if (newimm
!= (unsigned int) FAIL
)
12208 /* Still No ? Try using a negated value. */
12209 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12210 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12211 /* Otherwise - give up. */
12214 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12215 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12220 /* Replace the first operand in the 2nd instruction (which
12221 is the PC) with the destination register. We have
12222 already added in the PC in the first instruction and we
12223 do not want to do it again. */
12224 newinsn
&= ~ 0xf0000;
12225 newinsn
|= ((newinsn
& 0x0f000) << 4);
12228 newimm
|= (temp
& 0xfffff000);
12229 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12231 highpart
|= (newinsn
& 0xfffff000);
12232 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12236 case BFD_RELOC_ARM_OFFSET_IMM
:
12242 if (validate_offset_imm (value
, 0) == FAIL
)
12244 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12245 _("bad immediate value for offset (%ld)"),
12250 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12251 newval
&= 0xff7ff000;
12252 newval
|= value
| (sign
? INDEX_UP
: 0);
12253 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12256 case BFD_RELOC_ARM_OFFSET_IMM8
:
12257 case BFD_RELOC_ARM_HWLITERAL
:
12263 if (validate_offset_imm (value
, 1) == FAIL
)
12265 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12266 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12267 _("invalid literal constant: pool needs to be closer"));
12269 as_bad (_("bad immediate value for half-word offset (%ld)"),
12274 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12275 newval
&= 0xff7ff0f0;
12276 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12277 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12280 case BFD_RELOC_ARM_LITERAL
:
12286 if (validate_offset_imm (value
, 0) == FAIL
)
12288 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12289 _("invalid literal constant: pool needs to be closer"));
12293 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12294 newval
&= 0xff7ff000;
12295 newval
|= value
| (sign
? INDEX_UP
: 0);
12296 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12299 case BFD_RELOC_ARM_SHIFT_IMM
:
12300 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12301 if (((unsigned long) value
) > 32
12303 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12305 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12306 _("shift expression is too large"));
12311 /* Shifts of zero must be done as lsl. */
12313 else if (value
== 32)
12315 newval
&= 0xfffff07f;
12316 newval
|= (value
& 0x1f) << 7;
12317 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12320 case BFD_RELOC_ARM_SWI
:
12321 if (arm_data
->thumb_mode
)
12323 if (((unsigned long) value
) > 0xff)
12324 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12325 _("invalid swi expression"));
12326 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12328 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12332 if (((unsigned long) value
) > 0x00ffffff)
12333 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12334 _("invalid swi expression"));
12335 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12337 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12341 case BFD_RELOC_ARM_MULTI
:
12342 if (((unsigned long) value
) > 0xffff)
12343 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12344 _("invalid expression in load/store multiple"));
12345 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12346 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12349 case BFD_RELOC_ARM_PCREL_BRANCH
:
12350 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12352 /* Sign-extend a 24-bit number. */
12353 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12357 value
= fixP
->fx_offset
;
12360 /* We are going to store value (shifted right by two) in the
12361 instruction, in a 24 bit, signed field. Thus we need to check
12362 that none of the top 8 bits of the shifted value (top 7 bits of
12363 the unshifted, unsigned value) are set, or that they are all set. */
12364 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12365 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12368 /* Normally we would be stuck at this point, since we cannot store
12369 the absolute address that is the destination of the branch in the
12370 24 bits of the branch instruction. If however, we happen to know
12371 that the destination of the branch is in the same section as the
12372 branch instruction itself, then we can compute the relocation for
12373 ourselves and not have to bother the linker with it.
12375 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12376 because I have not worked out how to do this for OBJ_COFF or
12379 && fixP
->fx_addsy
!= NULL
12380 && S_IS_DEFINED (fixP
->fx_addsy
)
12381 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12383 /* Get pc relative value to go into the branch. */
12386 /* Permit a backward branch provided that enough bits
12387 are set. Allow a forwards branch, provided that
12388 enough bits are clear. */
12389 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12390 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12394 if (! fixP
->fx_done
)
12396 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12397 _("GAS can't handle same-section branch dest >= 0x04000000"));
12401 value
+= SEXT24 (newval
);
12403 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12404 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12405 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12406 _("out of range branch"));
12408 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12409 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12412 case BFD_RELOC_ARM_PCREL_BLX
:
12415 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12419 value
= fixP
->fx_offset
;
12421 hbit
= (value
>> 1) & 1;
12422 value
= (value
>> 2) & 0x00ffffff;
12423 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12424 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12425 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12429 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12430 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12432 addressT diff
= (newval
& 0xff) << 1;
12437 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12438 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12439 _("branch out of range"));
12440 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12442 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12445 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12446 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12448 addressT diff
= (newval
& 0x7ff) << 1;
12453 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12454 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12455 _("branch out of range"));
12456 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12458 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12461 case BFD_RELOC_THUMB_PCREL_BLX
:
12462 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12467 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12468 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12469 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12470 if (diff
& 0x400000)
12473 value
= fixP
->fx_offset
;
12477 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12478 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12479 _("branch with link out of range"));
12481 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12482 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12483 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12484 /* For a BLX instruction, make sure that the relocation is rounded up
12485 to a word boundary. This follows the semantics of the instruction
12486 which specifies that bit 1 of the target address will come from bit
12487 1 of the base address. */
12488 newval2
= (newval2
+ 1) & ~ 1;
12489 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12490 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12495 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12496 md_number_to_chars (buf
, value
, 1);
12498 else if (!target_oabi
)
12500 value
= fixP
->fx_offset
;
12501 md_number_to_chars (buf
, value
, 1);
12507 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12508 md_number_to_chars (buf
, value
, 2);
12510 else if (!target_oabi
)
12512 value
= fixP
->fx_offset
;
12513 md_number_to_chars (buf
, value
, 2);
12519 case BFD_RELOC_ARM_GOT32
:
12520 case BFD_RELOC_ARM_GOTOFF
:
12521 md_number_to_chars (buf
, 0, 4);
12525 case BFD_RELOC_RVA
:
12527 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12528 md_number_to_chars (buf
, value
, 4);
12530 else if (!target_oabi
)
12532 value
= fixP
->fx_offset
;
12533 md_number_to_chars (buf
, value
, 4);
12539 case BFD_RELOC_ARM_PLT32
:
12540 /* It appears the instruction is fully prepared at this point. */
12544 case BFD_RELOC_ARM_CP_OFF_IMM
:
12546 if (value
< -1023 || value
> 1023 || (value
& 3))
12547 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12548 _("illegal value for co-processor offset"));
12551 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12552 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12553 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12556 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12558 if (value
< -255 || value
> 255)
12559 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12560 _("Illegal value for co-processor offset"));
12563 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12564 newval
|= value
| (sign
? INDEX_UP
: 0);
12565 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12568 case BFD_RELOC_ARM_THUMB_OFFSET
:
12569 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12570 /* Exactly what ranges, and where the offset is inserted depends
12571 on the type of instruction, we can establish this from the
12573 switch (newval
>> 12)
12575 case 4: /* PC load. */
12576 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12577 forced to zero for these loads, so we will need to round
12578 up the offset if the instruction address is not word
12579 aligned (since the final address produced must be, and
12580 we can only describe word-aligned immediate offsets). */
12582 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12583 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12584 _("invalid offset, target not word aligned (0x%08X)"),
12585 (unsigned int) (fixP
->fx_frag
->fr_address
12586 + fixP
->fx_where
+ value
));
12588 if ((value
+ 2) & ~0x3fe)
12589 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12590 _("invalid offset, value too big (0x%08lX)"),
12593 /* Round up, since pc will be rounded down. */
12594 newval
|= (value
+ 2) >> 2;
12597 case 9: /* SP load/store. */
12598 if (value
& ~0x3fc)
12599 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12600 _("invalid offset, value too big (0x%08lX)"),
12602 newval
|= value
>> 2;
12605 case 6: /* Word load/store. */
12607 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12608 _("invalid offset, value too big (0x%08lX)"),
12610 newval
|= value
<< 4; /* 6 - 2. */
12613 case 7: /* Byte load/store. */
12615 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12616 _("invalid offset, value too big (0x%08lX)"),
12618 newval
|= value
<< 6;
12621 case 8: /* Halfword load/store. */
12623 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12624 _("invalid offset, value too big (0x%08lX)"),
12626 newval
|= value
<< 5; /* 6 - 1. */
12630 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12631 "Unable to process relocation for thumb opcode: %lx",
12632 (unsigned long) newval
);
12635 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12638 case BFD_RELOC_ARM_THUMB_ADD
:
12639 /* This is a complicated relocation, since we use it for all of
12640 the following immediate relocations:
12644 9bit ADD/SUB SP word-aligned
12645 10bit ADD PC/SP word-aligned
12647 The type of instruction being processed is encoded in the
12654 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12656 int rd
= (newval
>> 4) & 0xf;
12657 int rs
= newval
& 0xf;
12658 int subtract
= newval
& 0x8000;
12662 if (value
& ~0x1fc)
12663 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12664 _("invalid immediate for stack address calculation"));
12665 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12666 newval
|= value
>> 2;
12668 else if (rs
== REG_PC
|| rs
== REG_SP
)
12672 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12673 _("invalid immediate for address calculation (value = 0x%08lX)"),
12674 (unsigned long) value
);
12675 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12677 newval
|= value
>> 2;
12682 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12683 _("invalid 8bit immediate"));
12684 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12685 newval
|= (rd
<< 8) | value
;
12690 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12691 _("invalid 3bit immediate"));
12692 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12693 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12696 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12699 case BFD_RELOC_ARM_THUMB_IMM
:
12700 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12701 switch (newval
>> 11)
12703 case 0x04: /* 8bit immediate MOV. */
12704 case 0x05: /* 8bit immediate CMP. */
12705 if (value
< 0 || value
> 255)
12706 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12707 _("invalid immediate: %ld is too large"),
12715 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12718 case BFD_RELOC_ARM_THUMB_SHIFT
:
12719 /* 5bit shift value (0..31). */
12720 if (value
< 0 || value
> 31)
12721 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12722 _("illegal Thumb shift value: %ld"), (long) value
);
12723 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12724 newval
|= value
<< 6;
12725 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12728 case BFD_RELOC_VTABLE_INHERIT
:
12729 case BFD_RELOC_VTABLE_ENTRY
:
12733 case BFD_RELOC_NONE
:
12735 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12736 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12740 /* Translate internal representation of relocation info to BFD target
12744 tc_gen_reloc (section
, fixp
)
12745 asection
* section ATTRIBUTE_UNUSED
;
12749 bfd_reloc_code_real_type code
;
12751 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12753 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12754 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12755 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12757 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12759 if (fixp
->fx_pcrel
== 0)
12760 reloc
->addend
= fixp
->fx_offset
;
12762 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12763 #else /* OBJ_ELF */
12764 reloc
->addend
= fixp
->fx_offset
;
12767 switch (fixp
->fx_r_type
)
12770 if (fixp
->fx_pcrel
)
12772 code
= BFD_RELOC_8_PCREL
;
12777 if (fixp
->fx_pcrel
)
12779 code
= BFD_RELOC_16_PCREL
;
12784 if (fixp
->fx_pcrel
)
12786 code
= BFD_RELOC_32_PCREL
;
12790 case BFD_RELOC_ARM_PCREL_BRANCH
:
12791 case BFD_RELOC_ARM_PCREL_BLX
:
12792 case BFD_RELOC_RVA
:
12793 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12794 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12795 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12796 case BFD_RELOC_THUMB_PCREL_BLX
:
12797 case BFD_RELOC_VTABLE_ENTRY
:
12798 case BFD_RELOC_VTABLE_INHERIT
:
12799 code
= fixp
->fx_r_type
;
12802 case BFD_RELOC_ARM_LITERAL
:
12803 case BFD_RELOC_ARM_HWLITERAL
:
12804 /* If this is called then the a literal has
12805 been referenced across a section boundary. */
12806 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12807 _("literal referenced across section boundary"));
12811 case BFD_RELOC_ARM_GOT32
:
12812 case BFD_RELOC_ARM_GOTOFF
:
12813 case BFD_RELOC_ARM_PLT32
:
12814 code
= fixp
->fx_r_type
;
12818 case BFD_RELOC_ARM_IMMEDIATE
:
12819 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12820 _("internal relocation (type: IMMEDIATE) not fixed up"));
12823 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12824 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12825 _("ADRL used for a symbol not defined in the same file"));
12828 case BFD_RELOC_ARM_OFFSET_IMM
:
12829 if (fixp
->fx_addsy
!= NULL
12830 && !S_IS_DEFINED (fixp
->fx_addsy
)
12831 && S_IS_LOCAL (fixp
->fx_addsy
))
12833 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12834 _("undefined local label `%s'"),
12835 S_GET_NAME (fixp
->fx_addsy
));
12839 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12840 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12847 switch (fixp
->fx_r_type
)
12849 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12850 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12851 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12852 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12853 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12854 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12855 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12856 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12857 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12858 default: type
= _("<unknown>"); break;
12860 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12861 _("cannot represent %s relocation in this object file format"),
12868 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12870 && fixp
->fx_addsy
== GOT_symbol
)
12872 code
= BFD_RELOC_ARM_GOTPC
;
12873 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12877 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12879 if (reloc
->howto
== NULL
)
12881 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12882 _("cannot represent %s relocation in this object file format"),
12883 bfd_get_reloc_code_name (code
));
12887 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12888 vtable entry to be used in the relocation's section offset. */
12889 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12890 reloc
->address
= fixp
->fx_offset
;
12896 md_estimate_size_before_relax (fragP
, segtype
)
12897 fragS
* fragP ATTRIBUTE_UNUSED
;
12898 segT segtype ATTRIBUTE_UNUSED
;
12900 as_fatal (_("md_estimate_size_before_relax\n"));
12912 as_bad ("%s -- `%s'", inst
.error
, str
);
12916 to
= frag_more (inst
.size
);
12918 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12920 assert (inst
.size
== (2 * THUMB_SIZE
));
12921 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12922 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12924 else if (inst
.size
> INSN_SIZE
)
12926 assert (inst
.size
== (2 * INSN_SIZE
));
12927 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12928 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12931 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12933 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12934 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12935 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12939 dwarf2_emit_insn (inst
.size
);
12951 /* Align the instruction.
12952 This may not be the right thing to do but ... */
12957 /* Align the previous label if needed. */
12958 if (last_label_seen
!= NULL
)
12960 symbol_set_frag (last_label_seen
, frag_now
);
12961 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12962 S_SET_SEGMENT (last_label_seen
, now_seg
);
12965 memset (&inst
, '\0', sizeof (inst
));
12966 inst
.reloc
.type
= BFD_RELOC_NONE
;
12968 skip_whitespace (str
);
12970 /* Scan up to the end of the op-code, which must end in white space or
12972 for (start
= p
= str
; *p
!= '\0'; p
++)
12978 as_bad (_("no operator -- statement `%s'\n"), str
);
12984 const struct thumb_opcode
* opcode
;
12988 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12993 /* Check that this instruction is supported for this CPU. */
12994 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12996 as_bad (_("selected processor does not support `%s'"), str
);
13000 mapping_state (MAP_THUMB
);
13001 inst
.instruction
= opcode
->value
;
13002 inst
.size
= opcode
->size
;
13003 (*opcode
->parms
) (p
);
13010 const struct asm_opcode
* opcode
;
13014 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
13019 /* Check that this instruction is supported for this CPU. */
13020 if ((opcode
->variant
& cpu_variant
) == 0)
13022 as_bad (_("selected processor does not support `%s'"), str
);
13026 mapping_state (MAP_ARM
);
13027 inst
.instruction
= opcode
->value
;
13028 inst
.size
= INSN_SIZE
;
13029 (*opcode
->parms
) (p
);
13035 /* It wasn't an instruction, but it might be a register alias of the form
13037 if (create_register_alias (str
, p
))
13040 as_bad (_("bad instruction `%s'"), start
);
13044 Invocation line includes a switch not recognized by the base assembler.
13045 See if it's a processor-specific option.
13047 This routine is somewhat complicated by the need for backwards
13048 compatibility (since older releases of gcc can't be changed).
13049 The new options try to make the interface as compatible as
13052 New options (supported) are:
13054 -mcpu=<cpu name> Assemble for selected processor
13055 -march=<architecture name> Assemble for selected architecture
13056 -mfpu=<fpu architecture> Assemble for selected FPU.
13057 -EB/-mbig-endian Big-endian
13058 -EL/-mlittle-endian Little-endian
13059 -k Generate PIC code
13060 -mthumb Start in Thumb mode
13061 -mthumb-interwork Code supports ARM/Thumb interworking
13063 For now we will also provide support for:
13065 -mapcs-32 32-bit Program counter
13066 -mapcs-26 26-bit Program counter
13067 -macps-float Floats passed in FP registers
13068 -mapcs-reentrant Reentrant code
13070 (sometime these will probably be replaced with -mapcs=<list of options>
13071 and -matpcs=<list of options>)
13073 The remaining options are only supported for back-wards compatibility.
13074 Cpu variants, the arm part is optional:
13075 -m[arm]1 Currently not supported.
13076 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13077 -m[arm]3 Arm 3 processor
13078 -m[arm]6[xx], Arm 6 processors
13079 -m[arm]7[xx][t][[d]m] Arm 7 processors
13080 -m[arm]8[10] Arm 8 processors
13081 -m[arm]9[20][tdmi] Arm 9 processors
13082 -mstrongarm[110[0]] StrongARM processors
13083 -mxscale XScale processors
13084 -m[arm]v[2345[t[e]]] Arm architectures
13085 -mall All (except the ARM1)
13087 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13088 -mfpe-old (No float load/store multiples)
13089 -mvfpxd VFP Single precision
13091 -mno-fpu Disable all floating point instructions
13093 The following CPU names are recognized:
13094 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13095 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13096 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13097 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13098 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13099 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13100 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13104 const char * md_shortopts
= "m:k";
13106 #ifdef ARM_BI_ENDIAN
13107 #define OPTION_EB (OPTION_MD_BASE + 0)
13108 #define OPTION_EL (OPTION_MD_BASE + 1)
13110 #if TARGET_BYTES_BIG_ENDIAN
13111 #define OPTION_EB (OPTION_MD_BASE + 0)
13113 #define OPTION_EL (OPTION_MD_BASE + 1)
13117 struct option md_longopts
[] =
13120 {"EB", no_argument
, NULL
, OPTION_EB
},
13123 {"EL", no_argument
, NULL
, OPTION_EL
},
13125 {NULL
, no_argument
, NULL
, 0}
13128 size_t md_longopts_size
= sizeof (md_longopts
);
13130 struct arm_option_table
13132 char *option
; /* Option name to match. */
13133 char *help
; /* Help information. */
13134 int *var
; /* Variable to change. */
13135 int value
; /* What to change it to. */
13136 char *deprecated
; /* If non-null, print this message. */
13139 struct arm_option_table arm_opts
[] =
13141 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13142 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13143 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13144 &support_interwork
, 1, NULL
},
13145 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13146 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13147 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13148 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13150 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13151 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13152 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13153 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13156 /* These are recognized by the assembler, but have no affect on code. */
13157 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13158 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13160 /* DON'T add any new processors to this list -- we want the whole list
13161 to go away... Add them to the processors table instead. */
13162 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13163 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13164 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13165 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13166 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13167 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13168 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13169 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13170 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13171 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13172 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13173 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13174 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13175 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13176 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13177 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13178 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13179 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13180 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13181 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13182 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13183 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13184 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13185 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13186 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13187 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13188 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13189 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13190 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13191 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13192 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13193 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13194 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13195 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13196 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13197 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13198 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13199 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13200 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13201 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13202 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13203 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13204 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13205 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13206 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13207 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13208 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13209 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13210 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13211 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13212 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13213 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13214 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13215 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13216 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13217 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13218 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13219 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13220 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13221 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13222 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13223 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13224 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13225 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13226 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13227 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13228 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13229 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13230 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13231 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13232 N_("use -mcpu=strongarm110")},
13233 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13234 N_("use -mcpu=strongarm1100")},
13235 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13236 N_("use -mcpu=strongarm1110")},
13237 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13238 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13239 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13241 /* Architecture variants -- don't add any more to this list either. */
13242 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13243 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13244 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13245 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13246 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13247 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13248 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13249 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13250 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13251 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13252 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13253 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13254 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13255 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13256 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13257 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13258 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13259 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13261 /* Floating point variants -- don't add any more to this list either. */
13262 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13263 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13264 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13265 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13266 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13268 {NULL
, NULL
, NULL
, 0, NULL
}
13271 struct arm_cpu_option_table
13275 /* For some CPUs we assume an FPU unless the user explicitly sets
13280 /* This list should, at a minimum, contain all the cpu names
13281 recognized by GCC. */
13282 static struct arm_cpu_option_table arm_cpus
[] =
13284 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13285 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13286 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13287 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13288 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13289 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13290 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13291 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13292 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13293 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13294 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13295 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13296 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13297 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13298 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13299 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13300 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13301 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13302 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13303 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13304 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13305 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13306 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13307 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13308 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13309 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13310 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13311 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13312 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13313 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13314 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13315 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13316 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13317 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13318 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13319 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13320 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13321 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13322 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13323 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13324 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13325 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13326 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13327 /* For V5 or later processors we default to using VFP; but the user
13328 should really set the FPU type explicitly. */
13329 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13330 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13331 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13332 {"arm926ejs", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13333 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13334 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13335 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13336 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13337 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13338 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13339 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13340 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13341 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13342 {"arm1026ejs", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13343 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13344 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13345 /* ??? XSCALE is really an architecture. */
13346 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13347 /* ??? iwmmxt is not a processor. */
13348 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13349 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13351 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13355 struct arm_arch_option_table
13362 /* This list should, at a minimum, contain all the architecture names
13363 recognized by GCC. */
13364 static struct arm_arch_option_table arm_archs
[] =
13366 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13367 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13368 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13369 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13370 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13371 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13372 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13373 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13374 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13375 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13376 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13377 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13378 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13379 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13380 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13381 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13382 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13383 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13384 {"armv6j", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13385 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13386 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13390 /* ISA extensions in the co-processor space. */
13391 struct arm_arch_extension_table
13397 static struct arm_arch_extension_table arm_extensions
[] =
13399 {"maverick", ARM_CEXT_MAVERICK
},
13400 {"xscale", ARM_CEXT_XSCALE
},
13401 {"iwmmxt", ARM_CEXT_IWMMXT
},
13405 struct arm_fpu_option_table
13411 /* This list should, at a minimum, contain all the fpu names
13412 recognized by GCC. */
13413 static struct arm_fpu_option_table arm_fpus
[] =
13415 {"softfpa", FPU_NONE
},
13416 {"fpe", FPU_ARCH_FPE
},
13417 {"fpe2", FPU_ARCH_FPE
},
13418 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13419 {"fpa", FPU_ARCH_FPA
},
13420 {"fpa10", FPU_ARCH_FPA
},
13421 {"fpa11", FPU_ARCH_FPA
},
13422 {"arm7500fe", FPU_ARCH_FPA
},
13423 {"softvfp", FPU_ARCH_VFP
},
13424 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13425 {"vfp", FPU_ARCH_VFP_V2
},
13426 {"vfp9", FPU_ARCH_VFP_V2
},
13427 {"vfp10", FPU_ARCH_VFP_V2
},
13428 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13429 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13430 {"arm1020t", FPU_ARCH_VFP_V1
},
13431 {"arm1020e", FPU_ARCH_VFP_V2
},
13432 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13433 {"maverick", FPU_ARCH_MAVERICK
},
13437 struct arm_float_abi_option_table
13443 static struct arm_float_abi_option_table arm_float_abis
[] =
13445 {"hard", ARM_FLOAT_ABI_HARD
},
13446 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13447 {"soft", ARM_FLOAT_ABI_SOFT
},
13451 struct arm_long_option_table
13453 char *option
; /* Substring to match. */
13454 char *help
; /* Help information. */
13455 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13456 char *deprecated
; /* If non-null, print this message. */
13460 arm_parse_extension (str
, opt_p
)
13464 while (str
!= NULL
&& *str
!= 0)
13466 struct arm_arch_extension_table
*opt
;
13472 as_bad (_("invalid architectural extension"));
13477 ext
= strchr (str
, '+');
13480 optlen
= ext
- str
;
13482 optlen
= strlen (str
);
13486 as_bad (_("missing architectural extension"));
13490 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13491 if (strncmp (opt
->name
, str
, optlen
) == 0)
13493 *opt_p
|= opt
->value
;
13497 if (opt
->name
== NULL
)
13499 as_bad (_("unknown architectural extnsion `%s'"), str
);
13510 arm_parse_cpu (str
)
13513 struct arm_cpu_option_table
*opt
;
13514 char *ext
= strchr (str
, '+');
13518 optlen
= ext
- str
;
13520 optlen
= strlen (str
);
13524 as_bad (_("missing cpu name `%s'"), str
);
13528 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13529 if (strncmp (opt
->name
, str
, optlen
) == 0)
13531 mcpu_cpu_opt
= opt
->value
;
13532 mcpu_fpu_opt
= opt
->default_fpu
;
13535 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13540 as_bad (_("unknown cpu `%s'"), str
);
13545 arm_parse_arch (str
)
13548 struct arm_arch_option_table
*opt
;
13549 char *ext
= strchr (str
, '+');
13553 optlen
= ext
- str
;
13555 optlen
= strlen (str
);
13559 as_bad (_("missing architecture name `%s'"), str
);
13564 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13565 if (strcmp (opt
->name
, str
) == 0)
13567 march_cpu_opt
= opt
->value
;
13568 march_fpu_opt
= opt
->default_fpu
;
13571 return arm_parse_extension (ext
, &march_cpu_opt
);
13576 as_bad (_("unknown architecture `%s'\n"), str
);
13581 arm_parse_fpu (str
)
13584 struct arm_fpu_option_table
*opt
;
13586 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13587 if (strcmp (opt
->name
, str
) == 0)
13589 mfpu_opt
= opt
->value
;
13593 as_bad (_("unknown floating point format `%s'\n"), str
);
13598 arm_parse_float_abi (str
)
13601 struct arm_float_abi_option_table
*opt
;
13603 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13604 if (strcmp (opt
->name
, str
) == 0)
13606 mfloat_abi_opt
= opt
->value
;
13610 as_bad (_("unknown floating point abi `%s'\n"), str
);
13614 struct arm_long_option_table arm_long_opts
[] =
13616 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13617 arm_parse_cpu
, NULL
},
13618 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13619 arm_parse_arch
, NULL
},
13620 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13621 arm_parse_fpu
, NULL
},
13622 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13623 arm_parse_float_abi
, NULL
},
13624 {NULL
, NULL
, 0, NULL
}
13628 md_parse_option (c
, arg
)
13632 struct arm_option_table
*opt
;
13633 struct arm_long_option_table
*lopt
;
13639 target_big_endian
= 1;
13645 target_big_endian
= 0;
13650 /* Listing option. Just ignore these, we don't support additional
13655 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13657 if (c
== opt
->option
[0]
13658 && ((arg
== NULL
&& opt
->option
[1] == 0)
13659 || strcmp (arg
, opt
->option
+ 1) == 0))
13661 #if WARN_DEPRECATED
13662 /* If the option is deprecated, tell the user. */
13663 if (opt
->deprecated
!= NULL
)
13664 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13665 arg
? arg
: "", _(opt
->deprecated
));
13668 if (opt
->var
!= NULL
)
13669 *opt
->var
= opt
->value
;
13675 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13677 /* These options are expected to have an argument. */
13678 if (c
== lopt
->option
[0]
13680 && strncmp (arg
, lopt
->option
+ 1,
13681 strlen (lopt
->option
+ 1)) == 0)
13683 #if WARN_DEPRECATED
13684 /* If the option is deprecated, tell the user. */
13685 if (lopt
->deprecated
!= NULL
)
13686 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13687 _(lopt
->deprecated
));
13690 /* Call the sup-option parser. */
13691 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13695 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
13706 struct arm_option_table
*opt
;
13707 struct arm_long_option_table
*lopt
;
13709 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13711 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13712 if (opt
->help
!= NULL
)
13713 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13715 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13716 if (lopt
->help
!= NULL
)
13717 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13721 -EB assemble code for a big-endian cpu\n"));
13726 -EL assemble code for a little-endian cpu\n"));
13730 /* We need to be able to fix up arbitrary expressions in some statements.
13731 This is so that we can handle symbols that are an arbitrary distance from
13732 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13733 which returns part of an address in a form which will be valid for
13734 a data instruction. We do this by pushing the expression into a symbol
13735 in the expr_section, and creating a fix for that. */
13738 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13747 arm_fix_data
* arm_data
;
13755 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13759 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13764 /* Mark whether the fix is to a THUMB instruction, or an ARM
13766 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13767 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13768 arm_data
->thumb_mode
= thumb_mode
;
13771 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13774 cons_fix_new_arm (frag
, where
, size
, exp
)
13780 bfd_reloc_code_real_type type
;
13784 FIXME: @@ Should look at CPU word size. */
13788 type
= BFD_RELOC_8
;
13791 type
= BFD_RELOC_16
;
13795 type
= BFD_RELOC_32
;
13798 type
= BFD_RELOC_64
;
13802 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13805 /* A good place to do this, although this was probably not intended
13806 for this kind of use. We need to dump the literal pool before
13807 references are made to a null symbol pointer. */
13812 literal_pool
* pool
;
13814 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13816 /* Put it at the end of the relevent section. */
13817 subseg_set (pool
->section
, pool
->sub_section
);
13823 arm_start_line_hook ()
13825 last_label_seen
= NULL
;
13829 arm_frob_label (sym
)
13832 last_label_seen
= sym
;
13834 ARM_SET_THUMB (sym
, thumb_mode
);
13836 #if defined OBJ_COFF || defined OBJ_ELF
13837 ARM_SET_INTERWORK (sym
, support_interwork
);
13840 /* Note - do not allow local symbols (.Lxxx) to be labeled
13841 as Thumb functions. This is because these labels, whilst
13842 they exist inside Thumb code, are not the entry points for
13843 possible ARM->Thumb calls. Also, these labels can be used
13844 as part of a computed goto or switch statement. eg gcc
13845 can generate code that looks like this:
13847 ldr r2, [pc, .Laaa]
13857 The first instruction loads the address of the jump table.
13858 The second instruction converts a table index into a byte offset.
13859 The third instruction gets the jump address out of the table.
13860 The fourth instruction performs the jump.
13862 If the address stored at .Laaa is that of a symbol which has the
13863 Thumb_Func bit set, then the linker will arrange for this address
13864 to have the bottom bit set, which in turn would mean that the
13865 address computation performed by the third instruction would end
13866 up with the bottom bit set. Since the ARM is capable of unaligned
13867 word loads, the instruction would then load the incorrect address
13868 out of the jump table, and chaos would ensue. */
13869 if (label_is_thumb_function_name
13870 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13871 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13873 /* When the address of a Thumb function is taken the bottom
13874 bit of that address should be set. This will allow
13875 interworking between Arm and Thumb functions to work
13878 THUMB_SET_FUNC (sym
, 1);
13880 label_is_thumb_function_name
= FALSE
;
13884 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13888 arm_adjust_symtab ()
13893 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13895 if (ARM_IS_THUMB (sym
))
13897 if (THUMB_IS_FUNC (sym
))
13899 /* Mark the symbol as a Thumb function. */
13900 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13901 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13902 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13904 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13905 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13907 as_bad (_("%s: unexpected function type: %d"),
13908 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13910 else switch (S_GET_STORAGE_CLASS (sym
))
13913 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13916 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13919 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13927 if (ARM_IS_INTERWORK (sym
))
13928 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13935 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13937 if (ARM_IS_THUMB (sym
))
13939 elf_symbol_type
* elf_sym
;
13941 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13942 bind
= ELF_ST_BIND (elf_sym
);
13944 /* If it's a .thumb_func, declare it as so,
13945 otherwise tag label as .code 16. */
13946 if (THUMB_IS_FUNC (sym
))
13947 elf_sym
->internal_elf_sym
.st_info
=
13948 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13950 elf_sym
->internal_elf_sym
.st_info
=
13951 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13958 arm_data_in_code ()
13960 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13962 *input_line_pointer
= '/';
13963 input_line_pointer
+= 5;
13964 *input_line_pointer
= 0;
13972 arm_canonicalize_symbol_name (name
)
13977 if (thumb_mode
&& (len
= strlen (name
)) > 5
13978 && streq (name
+ len
- 5, "/data"))
13979 *(name
+ len
- 5) = 0;
13984 #if defined OBJ_COFF || defined OBJ_ELF
13986 arm_validate_fix (fixP
)
13989 /* If the destination of the branch is a defined symbol which does not have
13990 the THUMB_FUNC attribute, then we must be calling a function which has
13991 the (interfacearm) attribute. We look for the Thumb entry point to that
13992 function and change the branch to refer to that function instead. */
13993 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13994 && fixP
->fx_addsy
!= NULL
13995 && S_IS_DEFINED (fixP
->fx_addsy
)
13996 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13998 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
14004 arm_force_relocation (fixp
)
14007 #if defined (OBJ_COFF) && defined (TE_PE)
14008 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
14012 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
14013 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
14014 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
14015 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
14019 /* Resolve these relocations even if the symbol is extern or weak. */
14020 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
14021 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
14022 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14025 return generic_force_reloc (fixp
);
14029 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
14030 local labels from being added to the output symbol table when they
14031 are used with the ADRL pseudo op. The ADRL relocation should always
14032 be resolved before the binbary is emitted, so it is safe to say that
14033 it is adjustable. */
14036 arm_fix_adjustable (fixP
)
14039 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14046 /* Relocations against Thumb function names must be left unadjusted,
14047 so that the linker can use this information to correctly set the
14048 bottom bit of their addresses. The MIPS version of this function
14049 also prevents relocations that are mips-16 specific, but I do not
14050 know why it does this.
14053 There is one other problem that ought to be addressed here, but
14054 which currently is not: Taking the address of a label (rather
14055 than a function) and then later jumping to that address. Such
14056 addresses also ought to have their bottom bit set (assuming that
14057 they reside in Thumb code), but at the moment they will not. */
14060 arm_fix_adjustable (fixP
)
14063 if (fixP
->fx_addsy
== NULL
)
14066 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14067 && fixP
->fx_subsy
== NULL
)
14070 /* We need the symbol name for the VTABLE entries. */
14071 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14072 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14075 /* Don't allow symbols to be discarded on GOT related relocs. */
14076 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14077 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14078 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
14085 elf32_arm_target_format ()
14087 if (target_big_endian
)
14090 return "elf32-bigarm-oabi";
14092 return "elf32-bigarm";
14097 return "elf32-littlearm-oabi";
14099 return "elf32-littlearm";
14104 armelf_frob_symbol (symp
, puntp
)
14108 elf_frob_symbol (symp
, puntp
);
14111 static bfd_reloc_code_real_type
14121 bfd_reloc_code_real_type reloc
;
14125 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14126 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14127 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14128 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14129 branch instructions generated by GCC for PLT relocs. */
14130 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14131 { NULL
, 0, BFD_RELOC_UNUSED
}
14135 for (i
= 0, ip
= input_line_pointer
;
14136 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14138 id
[i
] = TOLOWER (*ip
);
14140 for (i
= 0; reloc_map
[i
].str
; i
++)
14141 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14144 input_line_pointer
+= reloc_map
[i
].len
;
14146 return reloc_map
[i
].reloc
;
14150 s_arm_elf_cons (nbytes
)
14155 #ifdef md_flush_pending_output
14156 md_flush_pending_output ();
14159 if (is_it_end_of_statement ())
14161 demand_empty_rest_of_line ();
14165 #ifdef md_cons_align
14166 md_cons_align (nbytes
);
14169 mapping_state (MAP_DATA
);
14172 bfd_reloc_code_real_type reloc
;
14174 expression (& exp
);
14176 if (exp
.X_op
== O_symbol
14177 && * input_line_pointer
== '('
14178 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14180 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14181 int size
= bfd_get_reloc_size (howto
);
14184 as_bad ("%s relocations do not fit in %d bytes",
14185 howto
->name
, nbytes
);
14188 register char *p
= frag_more ((int) nbytes
);
14189 int offset
= nbytes
- size
;
14191 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14196 emit_expr (&exp
, (unsigned int) nbytes
);
14198 while (*input_line_pointer
++ == ',');
14200 /* Put terminator back into stream. */
14201 input_line_pointer
--;
14202 demand_empty_rest_of_line ();
14205 #endif /* OBJ_ELF */
14207 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14208 of an rs_align_code fragment. */
14211 arm_handle_align (fragP
)
14214 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14215 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14216 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14217 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14219 int bytes
, fix
, noop_size
;
14223 if (fragP
->fr_type
!= rs_align_code
)
14226 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14227 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14230 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14231 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14233 if (fragP
->tc_frag_data
)
14235 if (target_big_endian
)
14236 noop
= thumb_bigend_noop
;
14239 noop_size
= sizeof (thumb_noop
);
14243 if (target_big_endian
)
14244 noop
= arm_bigend_noop
;
14247 noop_size
= sizeof (arm_noop
);
14250 if (bytes
& (noop_size
- 1))
14252 fix
= bytes
& (noop_size
- 1);
14253 memset (p
, 0, fix
);
14258 while (bytes
>= noop_size
)
14260 memcpy (p
, noop
, noop_size
);
14262 bytes
-= noop_size
;
14266 fragP
->fr_fix
+= fix
;
14267 fragP
->fr_var
= noop_size
;
14270 /* Called from md_do_align. Used to create an alignment
14271 frag in a code section. */
14274 arm_frag_align_code (n
, max
)
14280 /* We assume that there will never be a requirement
14281 to support alignments greater than 32 bytes. */
14282 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14283 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14285 p
= frag_var (rs_align_code
,
14286 MAX_MEM_FOR_RS_ALIGN_CODE
,
14288 (relax_substateT
) max
,
14296 /* Perform target specific initialisation of a frag. */
14299 arm_init_frag (fragP
)
14302 /* Record whether this frag is in an ARM or a THUMB area. */
14303 fragP
->tc_frag_data
= thumb_mode
;