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_sp_reg2
PARAMS ((char *));
933 static void do_vfp_reg_from_dp
PARAMS ((char *));
934 static void do_vfp_reg2_from_dp
PARAMS ((char *));
935 static void do_vfp_dp_from_reg
PARAMS ((char *));
936 static void do_vfp_dp_from_reg2
PARAMS ((char *));
937 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
938 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
939 static void do_vfp_sp_ldst
PARAMS ((char *));
940 static void do_vfp_dp_ldst
PARAMS ((char *));
941 static void do_vfp_sp_ldstmia
PARAMS ((char *));
942 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
943 static void do_vfp_dp_ldstmia
PARAMS ((char *));
944 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
945 static void do_vfp_xp_ldstmia
PARAMS ((char *));
946 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
947 static void do_vfp_sp_compare_z
PARAMS ((char *));
948 static void do_vfp_dp_compare_z
PARAMS ((char *));
949 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
950 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
953 static void do_xsc_mia
PARAMS ((char *));
954 static void do_xsc_mar
PARAMS ((char *));
955 static void do_xsc_mra
PARAMS ((char *));
958 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
960 static void do_mav_binops_1a
PARAMS ((char *));
961 static void do_mav_binops_1b
PARAMS ((char *));
962 static void do_mav_binops_1c
PARAMS ((char *));
963 static void do_mav_binops_1d
PARAMS ((char *));
964 static void do_mav_binops_1e
PARAMS ((char *));
965 static void do_mav_binops_1f
PARAMS ((char *));
966 static void do_mav_binops_1g
PARAMS ((char *));
967 static void do_mav_binops_1h
PARAMS ((char *));
968 static void do_mav_binops_1i
PARAMS ((char *));
969 static void do_mav_binops_1j
PARAMS ((char *));
970 static void do_mav_binops_1k
PARAMS ((char *));
971 static void do_mav_binops_1l
PARAMS ((char *));
972 static void do_mav_binops_1m
PARAMS ((char *));
973 static void do_mav_binops_1n
PARAMS ((char *));
974 static void do_mav_binops_1o
PARAMS ((char *));
975 static void do_mav_binops_2a
PARAMS ((char *));
976 static void do_mav_binops_2b
PARAMS ((char *));
977 static void do_mav_binops_2c
PARAMS ((char *));
978 static void do_mav_binops_3a
PARAMS ((char *));
979 static void do_mav_binops_3b
PARAMS ((char *));
980 static void do_mav_binops_3c
PARAMS ((char *));
981 static void do_mav_binops_3d
PARAMS ((char *));
982 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
985 static void do_mav_triple_4a
PARAMS ((char *));
986 static void do_mav_triple_4b
PARAMS ((char *));
987 static void do_mav_triple_5a
PARAMS ((char *));
988 static void do_mav_triple_5b
PARAMS ((char *));
989 static void do_mav_triple_5c
PARAMS ((char *));
990 static void do_mav_triple_5d
PARAMS ((char *));
991 static void do_mav_triple_5e
PARAMS ((char *));
992 static void do_mav_triple_5f
PARAMS ((char *));
993 static void do_mav_triple_5g
PARAMS ((char *));
994 static void do_mav_triple_5h
PARAMS ((char *));
995 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
999 static void do_mav_quad_6a
PARAMS ((char *));
1000 static void do_mav_quad_6b
PARAMS ((char *));
1001 static void do_mav_dspsc_1
PARAMS ((char *));
1002 static void do_mav_dspsc_2
PARAMS ((char *));
1003 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
1004 enum arm_reg_type
));
1005 static void do_mav_shift_1
PARAMS ((char *));
1006 static void do_mav_shift_2
PARAMS ((char *));
1007 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
1008 static void do_mav_ldst_1
PARAMS ((char *));
1009 static void do_mav_ldst_2
PARAMS ((char *));
1010 static void do_mav_ldst_3
PARAMS ((char *));
1011 static void do_mav_ldst_4
PARAMS ((char *));
1013 static int mav_reg_required_here
PARAMS ((char **, int,
1014 enum arm_reg_type
));
1015 static int mav_parse_offset
PARAMS ((char **, int *));
1017 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
1019 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
1020 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
1021 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
1022 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
1024 static int add_to_lit_pool
PARAMS ((void));
1025 static unsigned validate_immediate
PARAMS ((unsigned));
1026 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
1028 static int validate_offset_imm
PARAMS ((unsigned int, int));
1029 static void opcode_select
PARAMS ((int));
1030 static void end_of_line
PARAMS ((char *));
1031 static int reg_required_here
PARAMS ((char **, int));
1032 static int psr_required_here
PARAMS ((char **));
1033 static int co_proc_number
PARAMS ((char **));
1034 static int cp_opc_expr
PARAMS ((char **, int, int));
1035 static int cp_reg_required_here
PARAMS ((char **, int));
1036 static int fp_reg_required_here
PARAMS ((char **, int));
1037 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
1038 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
1039 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1040 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
1041 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
1042 static long vfp_dp_reg_list
PARAMS ((char **));
1043 static int vfp_psr_required_here
PARAMS ((char **str
));
1044 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
1045 static int cp_address_offset
PARAMS ((char **));
1046 static int cp_address_required_here
PARAMS ((char **, int));
1047 static int my_get_float_expression
PARAMS ((char **));
1048 static int skip_past_comma
PARAMS ((char **));
1049 static int walk_no_bignums
PARAMS ((symbolS
*));
1050 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
1051 static int data_op2
PARAMS ((char **));
1052 static int fp_op2
PARAMS ((char **));
1053 static long reg_list
PARAMS ((char **));
1054 static void thumb_load_store
PARAMS ((char *, int, int));
1055 static int decode_shift
PARAMS ((char **, int));
1056 static int ldst_extend
PARAMS ((char **));
1057 static int ldst_extend_v4
PARAMS ((char **));
1058 static void thumb_add_sub
PARAMS ((char *, int));
1059 static void insert_reg
PARAMS ((const struct reg_entry
*,
1060 struct hash_control
*));
1061 static void thumb_shift
PARAMS ((char *, int));
1062 static void thumb_mov_compare
PARAMS ((char *, int));
1063 static void build_arm_ops_hsh
PARAMS ((void));
1064 static void set_constant_flonums
PARAMS ((void));
1065 static valueT md_chars_to_number
PARAMS ((char *, int));
1066 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1067 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1068 static int create_register_alias
PARAMS ((char *, char *));
1069 static void output_inst
PARAMS ((const char *));
1070 static int accum0_required_here
PARAMS ((char **));
1071 static int ld_mode_required_here
PARAMS ((char **));
1072 static void do_branch25
PARAMS ((char *));
1073 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1075 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1078 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1079 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1080 static void do_iwmmxt_tandc
PARAMS ((char *));
1081 static void do_iwmmxt_tbcst
PARAMS ((char *));
1082 static void do_iwmmxt_textrc
PARAMS ((char *));
1083 static void do_iwmmxt_textrm
PARAMS ((char *));
1084 static void do_iwmmxt_tinsr
PARAMS ((char *));
1085 static void do_iwmmxt_tmcr
PARAMS ((char *));
1086 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1087 static void do_iwmmxt_tmia
PARAMS ((char *));
1088 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1089 static void do_iwmmxt_tmrc
PARAMS ((char *));
1090 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1091 static void do_iwmmxt_torc
PARAMS ((char *));
1092 static void do_iwmmxt_waligni
PARAMS ((char *));
1093 static void do_iwmmxt_wmov
PARAMS ((char *));
1094 static void do_iwmmxt_word_addr
PARAMS ((char *));
1095 static void do_iwmmxt_wrwr
PARAMS ((char *));
1096 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1097 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1098 static void do_iwmmxt_wshufh
PARAMS ((char *));
1099 static void do_iwmmxt_wzero
PARAMS ((char *));
1100 static int cp_byte_address_offset
PARAMS ((char **));
1101 static int cp_byte_address_required_here
PARAMS ((char **));
1103 /* ARM instructions take 4bytes in the object file, Thumb instructions
1107 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1108 #define MAV_MODE1 0x100c
1110 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1111 #define MAV_MODE2 0x0c10
1113 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1114 #define MAV_MODE3 0x1000
1116 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1117 #define MAV_MODE4 0x0c0010
1119 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1120 #define MAV_MODE5 0x00100c
1122 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1123 #define MAV_MODE6 0x00100c05
1127 /* Basic string to match. */
1128 const char * template;
1130 /* Basic instruction code. */
1131 unsigned long value
;
1133 /* Offset into the template where the condition code (if any) will be.
1134 If zero, then the instruction is never conditional. */
1135 unsigned cond_offset
;
1137 /* Which architecture variant provides this instruction. */
1138 unsigned long variant
;
1140 /* Function to call to parse args. */
1141 void (* parms
) PARAMS ((char *));
1144 static const struct asm_opcode insns
[] =
1146 /* Core ARM Instructions. */
1147 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1148 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1149 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1150 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1151 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1152 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1153 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1154 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1155 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1156 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1157 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1158 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1159 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1160 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1161 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1162 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1163 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1164 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1165 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1166 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1168 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1169 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1170 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1171 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1172 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1173 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1174 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1175 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1176 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1177 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1178 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1179 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1181 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1182 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1183 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1184 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1186 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1187 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1188 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1189 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1190 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1191 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1192 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1193 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1195 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1196 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1197 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1198 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1199 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1200 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1201 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1202 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1204 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1205 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1206 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1207 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1208 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1209 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1210 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1211 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1213 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1215 /* XXX This is the wrong place to do this. Think multi-arch. */
1216 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1217 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1219 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1220 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1224 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1225 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1226 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1228 /* ARM 2 multiplies. */
1229 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1230 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1231 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1232 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1234 /* Generic coprocessor instructions. */
1235 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1236 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1237 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1238 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1239 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1240 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1241 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1243 /* ARM 3 - swp instructions. */
1244 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1245 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1247 /* ARM 6 Status register instructions. */
1248 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1249 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1250 /* ScottB: our code uses 0xe128f000 for msr.
1251 NickC: but this is wrong because the bits 16 through 19 are
1252 handled by the PSR_xxx defines above. */
1254 /* ARM 7M long multiplies. */
1255 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1256 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1257 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1258 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1259 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1260 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1261 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1262 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1264 /* ARM Architecture 4. */
1265 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1266 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1267 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1268 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1270 /* ARM Architecture 4T. */
1271 /* Note: bx (and blx) are required on V5, even if the processor does
1272 not support Thumb. */
1273 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1275 /* ARM Architecture 5T. */
1276 /* Note: blx has 2 variants, so the .value is set dynamically.
1277 Only one of the variants has conditional execution. */
1278 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1279 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1280 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1281 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1282 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1283 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1284 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1285 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1286 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1287 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1289 /* ARM Architecture 5TExP. */
1290 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1291 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1292 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1293 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1295 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1296 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1298 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1299 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1300 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1301 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1303 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1304 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1305 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1306 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1308 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1309 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1311 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1312 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1313 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1314 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1316 /* ARM Architecture 5TE. */
1317 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1318 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1319 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1321 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1322 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1324 /* ARM Architecture 5TEJ. */
1325 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1328 { "cps", 0xf1020000, 0, ARM_EXT_V6
, do_cps
},
1329 { "cpsie", 0xf1080000, 0, ARM_EXT_V6
, do_cpsi
},
1330 { "cpsid", 0xf10C0000, 0, ARM_EXT_V6
, do_cpsi
},
1331 { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6
, do_ldrex
},
1332 { "mcrr2", 0xfc400000, 0, ARM_EXT_V6
, do_co_reg2c
},
1333 { "mrrc2", 0xfc500000, 0, ARM_EXT_V6
, do_co_reg2c
},
1334 { "pkhbt", 0xe6800010, 5, ARM_EXT_V6
, do_pkhbt
},
1335 { "pkhtb", 0xe6800050, 5, ARM_EXT_V6
, do_pkhtb
},
1336 { "qadd16", 0xe6200f10, 6, ARM_EXT_V6
, do_qadd16
},
1337 { "qadd8", 0xe6200f90, 5, ARM_EXT_V6
, do_qadd16
},
1338 { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6
, do_qadd16
},
1339 { "qsub16", 0xe6200f70, 6, ARM_EXT_V6
, do_qadd16
},
1340 { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6
, do_qadd16
},
1341 { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6
, do_qadd16
},
1342 { "sadd16", 0xe6100f10, 6, ARM_EXT_V6
, do_qadd16
},
1343 { "sadd8", 0xe6100f90, 5, ARM_EXT_V6
, do_qadd16
},
1344 { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6
, do_qadd16
},
1345 { "shadd16", 0xe6300f10, 7, ARM_EXT_V6
, do_qadd16
},
1346 { "shadd8", 0xe6300f90, 6, ARM_EXT_V6
, do_qadd16
},
1347 { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6
, do_qadd16
},
1348 { "shsub16", 0xe6300f70, 7, ARM_EXT_V6
, do_qadd16
},
1349 { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6
, do_qadd16
},
1350 { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6
, do_qadd16
},
1351 { "ssub16", 0xe6100f70, 6, ARM_EXT_V6
, do_qadd16
},
1352 { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6
, do_qadd16
},
1353 { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6
, do_qadd16
},
1354 { "uadd16", 0xe6500f10, 6, ARM_EXT_V6
, do_qadd16
},
1355 { "uadd8", 0xe6500f90, 5, ARM_EXT_V6
, do_qadd16
},
1356 { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6
, do_qadd16
},
1357 { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6
, do_qadd16
},
1358 { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6
, do_qadd16
},
1359 { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6
, do_qadd16
},
1360 { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6
, do_qadd16
},
1361 { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6
, do_qadd16
},
1362 { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6
, do_qadd16
},
1363 { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6
, do_qadd16
},
1364 { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6
, do_qadd16
},
1365 { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6
, do_qadd16
},
1366 { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6
, do_qadd16
},
1367 { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6
, do_qadd16
},
1368 { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6
, do_qadd16
},
1369 { "usub16", 0xe6500f70, 6, ARM_EXT_V6
, do_qadd16
},
1370 { "usub8", 0xe6500ff0, 5, ARM_EXT_V6
, do_qadd16
},
1371 { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6
, do_qadd16
},
1372 { "rev", 0xe6bf0f30, 3, ARM_EXT_V6
, do_rev
},
1373 { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6
, do_rev
},
1374 { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6
, do_rev
},
1375 { "rfeia", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1376 { "rfeib", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1377 { "rfeda", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1378 { "rfedb", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1379 { "rfefd", 0xf8900a00, 0, ARM_EXT_V6
, do_rfe
},
1380 { "rfefa", 0xf9900a00, 0, ARM_EXT_V6
, do_rfe
},
1381 { "rfeea", 0xf8100a00, 0, ARM_EXT_V6
, do_rfe
},
1382 { "rfeed", 0xf9100a00, 0, ARM_EXT_V6
, do_rfe
},
1383 { "sxtah", 0xe6b00070, 5, ARM_EXT_V6
, do_sxtah
},
1384 { "sxtab16", 0xe6800070, 7, ARM_EXT_V6
, do_sxtah
},
1385 { "sxtab", 0xe6a00070, 5, ARM_EXT_V6
, do_sxtah
},
1386 { "sxth", 0xe6bf0070, 4, ARM_EXT_V6
, do_sxth
},
1387 { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6
, do_sxth
},
1388 { "sxtb", 0xe6af0070, 4, ARM_EXT_V6
, do_sxth
},
1389 { "uxtah", 0xe6f00070, 5, ARM_EXT_V6
, do_sxtah
},
1390 { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6
, do_sxtah
},
1391 { "uxtab", 0xe6e00070, 5, ARM_EXT_V6
, do_sxtah
},
1392 { "uxth", 0xe6ff0070, 4, ARM_EXT_V6
, do_sxth
},
1393 { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6
, do_sxth
},
1394 { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6
, do_sxth
},
1395 { "sel", 0xe68000b0, 3, ARM_EXT_V6
, do_qadd16
},
1396 { "setend", 0xf1010000, 0, ARM_EXT_V6
, do_setend
},
1397 { "smlad", 0xe7000010, 5, ARM_EXT_V6
, do_smlad
},
1398 { "smladx", 0xe7000030, 6, ARM_EXT_V6
, do_smlad
},
1399 { "smlald", 0xe7400010, 6, ARM_EXT_V6
, do_smlald
},
1400 { "smlaldx", 0xe7400030, 7, ARM_EXT_V6
, do_smlald
},
1401 { "smlsd", 0xe7000050, 5, ARM_EXT_V6
, do_smlad
},
1402 { "smlsdx", 0xe7000070, 6, ARM_EXT_V6
, do_smlad
},
1403 { "smlsld", 0xe7400050, 6, ARM_EXT_V6
, do_smlald
},
1404 { "smlsldx", 0xe7400070, 7, ARM_EXT_V6
, do_smlald
},
1405 { "smmla", 0xe7500010, 5, ARM_EXT_V6
, do_smlad
},
1406 { "smmlar", 0xe7500030, 6, ARM_EXT_V6
, do_smlad
},
1407 { "smmls", 0xe75000d0, 5, ARM_EXT_V6
, do_smlad
},
1408 { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6
, do_smlad
},
1409 { "smmul", 0xe750f010, 5, ARM_EXT_V6
, do_smmul
},
1410 { "smmulr", 0xe750f030, 6, ARM_EXT_V6
, do_smmul
},
1411 { "smuad", 0xe700f010, 5, ARM_EXT_V6
, do_smmul
},
1412 { "smuadx", 0xe700f030, 6, ARM_EXT_V6
, do_smmul
},
1413 { "smusd", 0xe700f050, 5, ARM_EXT_V6
, do_smmul
},
1414 { "smusdx", 0xe700f070, 6, ARM_EXT_V6
, do_smmul
},
1415 { "srsia", 0xf8cd0500, 0, ARM_EXT_V6
, do_srs
},
1416 { "srsib", 0xf9cd0500, 0, ARM_EXT_V6
, do_srs
},
1417 { "srsda", 0xf84d0500, 0, ARM_EXT_V6
, do_srs
},
1418 { "srsdb", 0xf94d0500, 0, ARM_EXT_V6
, do_srs
},
1419 { "ssat", 0xe6a00010, 4, ARM_EXT_V6
, do_ssat
},
1420 { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6
, do_ssat16
},
1421 { "strex", 0xe1800f90, 5, ARM_EXT_V6
, do_strex
},
1422 { "umaal", 0xe0400090, 5, ARM_EXT_V6
, do_umaal
},
1423 { "usad8", 0xe780f010, 5, ARM_EXT_V6
, do_smmul
},
1424 { "usada8", 0xe7800010, 6, ARM_EXT_V6
, do_smlad
},
1425 { "usat", 0xe6e00010, 4, ARM_EXT_V6
, do_usat
},
1426 { "usat16", 0xe6e00f30, 6, ARM_EXT_V6
, do_usat16
},
1428 /* Core FPA instruction set (V1). */
1429 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1430 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1431 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1432 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1434 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1435 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1436 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1437 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1439 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1440 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1441 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1442 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1444 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1445 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1458 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1471 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1484 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1497 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1499 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1500 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1501 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1502 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1503 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1504 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1505 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1506 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1507 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1509 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1510 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1511 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1512 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1513 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1514 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1515 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1516 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1517 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1518 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1519 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1520 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1522 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1523 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1524 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1525 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1526 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1527 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1528 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1529 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1530 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1531 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1532 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1533 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1535 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1536 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1537 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1538 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1539 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1540 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1541 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1542 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1543 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1544 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1545 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1546 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1548 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1549 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1550 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1551 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1552 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1553 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1554 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1555 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1556 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1557 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1558 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1559 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1561 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1562 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1563 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1564 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1565 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1566 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1567 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1568 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1569 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1570 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1571 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1572 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1574 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1575 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1576 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1577 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1578 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1579 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1580 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1581 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1582 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1583 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1584 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1585 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1587 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1588 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1589 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1590 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1591 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1592 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1593 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1594 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1595 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1596 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1597 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1598 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1600 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1601 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1602 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1603 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1604 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1605 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1606 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1607 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1608 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1609 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1610 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1611 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1613 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1614 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1615 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1616 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1617 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1618 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1619 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1620 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1621 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1622 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1623 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1624 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1626 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1627 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1628 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1629 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1630 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1631 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1632 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1633 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1634 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1635 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1636 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1637 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1639 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1640 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1641 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1642 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1643 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1644 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1645 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1646 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1647 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1648 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1649 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1650 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1652 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1653 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1666 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1668 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1669 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1670 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1671 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1672 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1673 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1674 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1675 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1676 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1678 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1679 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1680 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1681 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1682 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1683 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1684 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1685 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1686 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1687 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1688 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1689 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1691 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1692 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1693 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1694 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1695 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1696 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1697 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1698 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1699 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1700 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1701 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1702 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1704 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1705 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1706 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1707 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1708 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1709 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1710 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1711 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1712 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1713 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1714 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1715 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1717 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1718 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1719 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1720 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1721 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1722 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1723 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1724 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1725 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1726 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1727 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1728 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1730 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1731 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1732 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1733 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1734 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1735 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1736 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1737 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1738 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1739 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1740 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1741 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1743 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1744 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1745 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1746 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1747 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1748 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1749 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1750 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1751 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1752 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1753 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1754 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1756 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1757 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1758 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1759 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1760 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1761 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1762 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1763 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1764 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1765 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1766 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1767 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1769 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1770 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1771 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1772 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1773 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1774 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1775 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1776 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1777 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1778 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1779 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1780 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1782 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1783 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1784 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1785 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1786 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1787 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1788 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1789 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1790 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1791 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1792 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1793 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1795 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1796 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1797 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1798 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1799 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1800 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1801 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1802 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1803 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1804 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1805 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1806 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1808 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1809 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1810 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1811 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1812 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1813 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1814 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1815 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1816 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1817 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1818 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1819 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1821 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1822 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1823 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1824 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1825 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1826 not be an optional suffix, but part of the instruction. To be
1827 compatible, we accept either. */
1828 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1829 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1831 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1832 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1833 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1834 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1835 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1836 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1837 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1838 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1839 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1840 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1841 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1842 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1844 /* The implementation of the FIX instruction is broken on some
1845 assemblers, in that it accepts a precision specifier as well as a
1846 rounding specifier, despite the fact that this is meaningless.
1847 To be more compatible, we accept it as well, though of course it
1848 does not set any bits. */
1849 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1850 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1851 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1852 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1853 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1854 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1855 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1856 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1857 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1858 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1859 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1860 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1861 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1863 /* Instructions that were new with the real FPA, call them V2. */
1864 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1865 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1866 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1867 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1868 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1869 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1871 /* VFP V1xD (single precision). */
1872 /* Moves and type conversions. */
1873 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1874 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1875 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1876 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1877 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1878 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1879 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1880 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1881 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1882 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1883 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1884 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1886 /* Memory operations. */
1887 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1888 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1889 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1890 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1891 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1892 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1893 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1894 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1895 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1896 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1897 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1898 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1899 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1900 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1901 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1902 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1903 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1904 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1906 /* Monadic operations. */
1907 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1908 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1909 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1911 /* Dyadic operations. */
1912 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1913 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1914 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1915 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1916 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1917 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1918 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1919 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1920 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1923 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1924 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1925 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1926 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1928 /* VFP V1 (Double precision). */
1929 /* Moves and type conversions. */
1930 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1931 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1932 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1933 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1934 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1935 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1936 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1937 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1938 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1939 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1940 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1941 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1942 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1944 /* Memory operations. */
1945 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1946 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1947 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1948 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1949 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1950 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1951 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1952 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1953 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1954 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1956 /* Monadic operations. */
1957 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1958 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1959 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1961 /* Dyadic operations. */
1962 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1963 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1964 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1965 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1966 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1967 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1968 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1969 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1970 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1973 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1974 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1975 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1976 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1979 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1980 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1981 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1982 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1984 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1985 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1986 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1987 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1988 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1989 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1990 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1991 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1992 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1994 /* Intel Wireless MMX technology instructions. */
1995 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1996 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1997 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1998 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1999 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2000 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
2001 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2002 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2003 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
2004 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2005 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2006 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2007 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2008 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2009 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
2010 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2011 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2012 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
2013 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
2014 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
2015 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2016 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2017 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2018 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2019 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2020 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
2021 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2022 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2023 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
2024 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
2025 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
2026 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2027 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2028 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
2029 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2030 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2031 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2032 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2033 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2034 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2035 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2036 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2037 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2038 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2039 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2040 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2041 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
2042 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2043 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2044 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2045 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2046 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2047 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2048 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2049 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2050 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2051 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2052 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2053 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2054 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2055 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2056 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2057 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2058 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2059 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2060 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2061 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2062 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2063 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2064 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2065 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2066 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2067 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2068 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2069 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2070 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2071 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2072 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2073 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2074 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2075 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2076 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2077 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2078 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2079 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2080 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2081 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2082 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2083 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
2084 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2085 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2086 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2087 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2088 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2089 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2090 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2091 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2092 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2093 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2094 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2095 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2096 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2097 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2098 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2099 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2100 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2101 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2102 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2103 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2104 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2105 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
2106 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2107 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2108 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2109 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2110 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2111 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2112 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2113 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2114 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2115 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2116 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2117 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2118 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2119 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2120 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2121 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2122 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2123 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
2124 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2125 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
2126 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2127 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
2128 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2129 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2130 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2131 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2132 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2133 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2134 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2135 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2136 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2137 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2138 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2139 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2140 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2141 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2142 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2143 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2144 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2145 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2146 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2147 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2148 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2149 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2150 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2151 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
2152 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2153 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2154 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2155 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2156 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2158 /* Cirrus Maverick instructions. */
2159 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2160 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2161 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2162 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2163 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2164 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2165 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2166 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2167 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2168 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2169 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2170 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2171 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2172 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2173 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2174 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2175 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2176 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2177 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2178 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2179 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2180 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2181 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2182 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2183 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2184 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2185 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2186 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2187 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2188 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2189 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2190 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2191 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2192 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2193 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2194 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2195 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2196 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2197 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2198 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2199 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2200 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2201 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2202 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2203 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2204 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2205 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2206 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2207 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2208 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2209 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2210 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2211 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2212 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2213 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2214 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2215 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2216 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2217 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2218 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2219 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2220 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2221 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2222 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2223 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2224 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2225 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2226 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2227 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2228 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2229 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2230 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2231 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2232 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2233 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2234 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2237 /* Defines for various bits that we will want to toggle. */
2238 #define INST_IMMEDIATE 0x02000000
2239 #define OFFSET_REG 0x02000000
2240 #define HWOFFSET_IMM 0x00400000
2241 #define SHIFT_BY_REG 0x00000010
2242 #define PRE_INDEX 0x01000000
2243 #define INDEX_UP 0x00800000
2244 #define WRITE_BACK 0x00200000
2245 #define LDM_TYPE_2_OR_3 0x00400000
2247 #define LITERAL_MASK 0xf000f000
2248 #define OPCODE_MASK 0xfe1fffff
2249 #define V4_STR_BIT 0x00000020
2251 #define DATA_OP_SHIFT 21
2253 /* Codes to distinguish the arithmetic instructions. */
2254 #define OPCODE_AND 0
2255 #define OPCODE_EOR 1
2256 #define OPCODE_SUB 2
2257 #define OPCODE_RSB 3
2258 #define OPCODE_ADD 4
2259 #define OPCODE_ADC 5
2260 #define OPCODE_SBC 6
2261 #define OPCODE_RSC 7
2262 #define OPCODE_TST 8
2263 #define OPCODE_TEQ 9
2264 #define OPCODE_CMP 10
2265 #define OPCODE_CMN 11
2266 #define OPCODE_ORR 12
2267 #define OPCODE_MOV 13
2268 #define OPCODE_BIC 14
2269 #define OPCODE_MVN 15
2271 /* Thumb v1 (ARMv4T). */
2272 static void do_t_nop
PARAMS ((char *));
2273 static void do_t_arit
PARAMS ((char *));
2274 static void do_t_add
PARAMS ((char *));
2275 static void do_t_asr
PARAMS ((char *));
2276 static void do_t_branch9
PARAMS ((char *));
2277 static void do_t_branch12
PARAMS ((char *));
2278 static void do_t_branch23
PARAMS ((char *));
2279 static void do_t_bx
PARAMS ((char *));
2280 static void do_t_compare
PARAMS ((char *));
2281 static void do_t_ldmstm
PARAMS ((char *));
2282 static void do_t_ldr
PARAMS ((char *));
2283 static void do_t_ldrb
PARAMS ((char *));
2284 static void do_t_ldrh
PARAMS ((char *));
2285 static void do_t_lds
PARAMS ((char *));
2286 static void do_t_lsl
PARAMS ((char *));
2287 static void do_t_lsr
PARAMS ((char *));
2288 static void do_t_mov
PARAMS ((char *));
2289 static void do_t_push_pop
PARAMS ((char *));
2290 static void do_t_str
PARAMS ((char *));
2291 static void do_t_strb
PARAMS ((char *));
2292 static void do_t_strh
PARAMS ((char *));
2293 static void do_t_sub
PARAMS ((char *));
2294 static void do_t_swi
PARAMS ((char *));
2295 static void do_t_adr
PARAMS ((char *));
2297 /* Thumb v2 (ARMv5T). */
2298 static void do_t_blx
PARAMS ((char *));
2299 static void do_t_bkpt
PARAMS ((char *));
2302 static void do_t_cps
PARAMS ((char *));
2303 static void do_t_cpy
PARAMS ((char *));
2304 static void do_t_setend
PARAMS ((char *));;
2306 #define T_OPCODE_MUL 0x4340
2307 #define T_OPCODE_TST 0x4200
2308 #define T_OPCODE_CMN 0x42c0
2309 #define T_OPCODE_NEG 0x4240
2310 #define T_OPCODE_MVN 0x43c0
2312 #define T_OPCODE_ADD_R3 0x1800
2313 #define T_OPCODE_SUB_R3 0x1a00
2314 #define T_OPCODE_ADD_HI 0x4400
2315 #define T_OPCODE_ADD_ST 0xb000
2316 #define T_OPCODE_SUB_ST 0xb080
2317 #define T_OPCODE_ADD_SP 0xa800
2318 #define T_OPCODE_ADD_PC 0xa000
2319 #define T_OPCODE_ADD_I8 0x3000
2320 #define T_OPCODE_SUB_I8 0x3800
2321 #define T_OPCODE_ADD_I3 0x1c00
2322 #define T_OPCODE_SUB_I3 0x1e00
2324 #define T_OPCODE_ASR_R 0x4100
2325 #define T_OPCODE_LSL_R 0x4080
2326 #define T_OPCODE_LSR_R 0x40c0
2327 #define T_OPCODE_ASR_I 0x1000
2328 #define T_OPCODE_LSL_I 0x0000
2329 #define T_OPCODE_LSR_I 0x0800
2331 #define T_OPCODE_MOV_I8 0x2000
2332 #define T_OPCODE_CMP_I8 0x2800
2333 #define T_OPCODE_CMP_LR 0x4280
2334 #define T_OPCODE_MOV_HR 0x4600
2335 #define T_OPCODE_CMP_HR 0x4500
2337 #define T_OPCODE_LDR_PC 0x4800
2338 #define T_OPCODE_LDR_SP 0x9800
2339 #define T_OPCODE_STR_SP 0x9000
2340 #define T_OPCODE_LDR_IW 0x6800
2341 #define T_OPCODE_STR_IW 0x6000
2342 #define T_OPCODE_LDR_IH 0x8800
2343 #define T_OPCODE_STR_IH 0x8000
2344 #define T_OPCODE_LDR_IB 0x7800
2345 #define T_OPCODE_STR_IB 0x7000
2346 #define T_OPCODE_LDR_RW 0x5800
2347 #define T_OPCODE_STR_RW 0x5000
2348 #define T_OPCODE_LDR_RH 0x5a00
2349 #define T_OPCODE_STR_RH 0x5200
2350 #define T_OPCODE_LDR_RB 0x5c00
2351 #define T_OPCODE_STR_RB 0x5400
2353 #define T_OPCODE_PUSH 0xb400
2354 #define T_OPCODE_POP 0xbc00
2356 #define T_OPCODE_BRANCH 0xe7fe
2358 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2360 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2361 #define THUMB_REG_LO 0x1
2362 #define THUMB_REG_HI 0x2
2363 #define THUMB_REG_ANY 0x3
2365 #define THUMB_H1 0x0080
2366 #define THUMB_H2 0x0040
2372 #define THUMB_MOVE 0
2373 #define THUMB_COMPARE 1
2376 #define THUMB_LOAD 0
2377 #define THUMB_STORE 1
2379 #define THUMB_PP_PC_LR 0x0100
2381 /* These three are used for immediate shifts, do not alter. */
2382 #define THUMB_WORD 2
2383 #define THUMB_HALFWORD 1
2384 #define THUMB_BYTE 0
2388 /* Basic string to match. */
2389 const char * template;
2391 /* Basic instruction code. */
2392 unsigned long value
;
2396 /* Which CPU variants this exists for. */
2397 unsigned long variant
;
2399 /* Function to call to parse args. */
2400 void (* parms
) PARAMS ((char *));
2403 static const struct thumb_opcode tinsns
[] =
2405 /* Thumb v1 (ARMv4T). */
2406 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2407 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2408 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2409 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2410 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2411 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2412 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2413 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2414 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2415 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2416 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2417 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2418 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2419 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2420 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2421 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2422 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2423 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2424 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2425 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2426 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2427 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2428 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2429 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2430 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2431 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2432 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2433 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2434 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2435 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2436 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2437 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2438 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2439 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2440 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2441 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2442 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2443 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2444 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2445 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2446 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2447 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2448 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2449 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2450 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2451 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2452 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2453 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2454 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2455 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2456 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2457 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2458 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2459 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2460 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2462 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2463 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2464 /* Thumb v2 (ARMv5T). */
2465 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2466 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2469 {"cpsie", 0xb660, 2, ARM_EXT_V6
, do_t_cps
},
2470 {"cpsid", 0xb670, 2, ARM_EXT_V6
, do_t_cps
},
2471 {"cpy", 0x4600, 2, ARM_EXT_V6
, do_t_cpy
},
2472 {"rev", 0xba00, 2, ARM_EXT_V6
, do_t_arit
},
2473 {"rev16", 0xba40, 2, ARM_EXT_V6
, do_t_arit
},
2474 {"revsh", 0xbac0, 2, ARM_EXT_V6
, do_t_arit
},
2475 {"setend", 0xb650, 2, ARM_EXT_V6
, do_t_setend
},
2476 {"sxth", 0xb200, 2, ARM_EXT_V6
, do_t_arit
},
2477 {"sxtb", 0xb240, 2, ARM_EXT_V6
, do_t_arit
},
2478 {"uxth", 0xb280, 2, ARM_EXT_V6
, do_t_arit
},
2479 {"uxtb", 0xb2c0, 2, ARM_EXT_V6
, do_t_arit
},
2482 #define BAD_ARGS _("bad arguments to instruction")
2483 #define BAD_PC _("r15 not allowed here")
2484 #define BAD_COND _("instruction is not conditional")
2485 #define ERR_NO_ACCUM _("acc0 expected")
2487 static struct hash_control
* arm_ops_hsh
= NULL
;
2488 static struct hash_control
* arm_tops_hsh
= NULL
;
2489 static struct hash_control
* arm_cond_hsh
= NULL
;
2490 static struct hash_control
* arm_shift_hsh
= NULL
;
2491 static struct hash_control
* arm_psr_hsh
= NULL
;
2493 /* This table describes all the machine specific pseudo-ops the assembler
2494 has to support. The fields are:
2495 pseudo-op name without dot
2496 function to call to execute this pseudo-op
2497 Integer arg to pass to the function. */
2499 static void s_req
PARAMS ((int));
2500 static void s_unreq
PARAMS ((int));
2501 static void s_align
PARAMS ((int));
2502 static void s_bss
PARAMS ((int));
2503 static void s_even
PARAMS ((int));
2504 static void s_ltorg
PARAMS ((int));
2505 static void s_arm
PARAMS ((int));
2506 static void s_thumb
PARAMS ((int));
2507 static void s_code
PARAMS ((int));
2508 static void s_force_thumb
PARAMS ((int));
2509 static void s_thumb_func
PARAMS ((int));
2510 static void s_thumb_set
PARAMS ((int));
2512 static void s_arm_elf_cons
PARAMS ((int));
2515 static int my_get_expression
PARAMS ((expressionS
*, char **));
2517 const pseudo_typeS md_pseudo_table
[] =
2519 /* Never called because '.req' does not start a line. */
2520 { "req", s_req
, 0 },
2521 { "unreq", s_unreq
, 0 },
2522 { "bss", s_bss
, 0 },
2523 { "align", s_align
, 0 },
2524 { "arm", s_arm
, 0 },
2525 { "thumb", s_thumb
, 0 },
2526 { "code", s_code
, 0 },
2527 { "force_thumb", s_force_thumb
, 0 },
2528 { "thumb_func", s_thumb_func
, 0 },
2529 { "thumb_set", s_thumb_set
, 0 },
2530 { "even", s_even
, 0 },
2531 { "ltorg", s_ltorg
, 0 },
2532 { "pool", s_ltorg
, 0 },
2534 { "word", s_arm_elf_cons
, 4 },
2535 { "long", s_arm_elf_cons
, 4 },
2539 { "extend", float_cons
, 'x' },
2540 { "ldouble", float_cons
, 'x' },
2541 { "packed", float_cons
, 'p' },
2545 /* Other internal functions. */
2546 static int arm_parse_extension
PARAMS ((char *, int *));
2547 static int arm_parse_cpu
PARAMS ((char *));
2548 static int arm_parse_arch
PARAMS ((char *));
2549 static int arm_parse_fpu
PARAMS ((char *));
2550 static int arm_parse_float_abi
PARAMS ((char *));
2551 #if 0 /* Suppressed - for now. */
2552 #if defined OBJ_COFF || defined OBJ_ELF
2553 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2557 /* Stuff needed to resolve the label ambiguity
2567 symbolS
* last_label_seen
;
2568 static int label_is_thumb_function_name
= FALSE
;
2570 /* Literal Pool stuff. */
2572 #define MAX_LITERAL_POOL_SIZE 1024
2574 /* Literal pool structure. Held on a per-section
2575 and per-sub-section basis. */
2576 typedef struct literal_pool
2578 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2579 unsigned int next_free_entry
;
2583 subsegT sub_section
;
2584 struct literal_pool
* next
;
2587 /* Pointer to a linked list of literal pools. */
2588 literal_pool
* list_of_pools
= NULL
;
2590 static literal_pool
* find_literal_pool
PARAMS ((void));
2591 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2593 static literal_pool
*
2594 find_literal_pool ()
2596 literal_pool
* pool
;
2598 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2600 if (pool
->section
== now_seg
2601 && pool
->sub_section
== now_subseg
)
2608 static literal_pool
*
2609 find_or_make_literal_pool ()
2611 /* Next literal pool ID number. */
2612 static unsigned int latest_pool_num
= 1;
2613 literal_pool
* pool
;
2615 pool
= find_literal_pool ();
2619 /* Create a new pool. */
2620 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2624 pool
->next_free_entry
= 0;
2625 pool
->section
= now_seg
;
2626 pool
->sub_section
= now_subseg
;
2627 pool
->next
= list_of_pools
;
2628 pool
->symbol
= NULL
;
2630 /* Add it to the list. */
2631 list_of_pools
= pool
;
2634 /* New pools, and emptied pools, will have a NULL symbol. */
2635 if (pool
->symbol
== NULL
)
2637 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2638 (valueT
) 0, &zero_address_frag
);
2639 pool
->id
= latest_pool_num
++;
2646 /* Add the literal in the global 'inst'
2647 structure to the relevent literal pool. */
2651 literal_pool
* pool
;
2654 pool
= find_or_make_literal_pool ();
2656 /* Check if this literal value is already in the pool. */
2657 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2659 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2660 && (inst
.reloc
.exp
.X_op
== O_constant
)
2661 && (pool
->literals
[entry
].X_add_number
2662 == inst
.reloc
.exp
.X_add_number
)
2663 && (pool
->literals
[entry
].X_unsigned
2664 == inst
.reloc
.exp
.X_unsigned
))
2667 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2668 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2669 && (pool
->literals
[entry
].X_add_number
2670 == inst
.reloc
.exp
.X_add_number
)
2671 && (pool
->literals
[entry
].X_add_symbol
2672 == inst
.reloc
.exp
.X_add_symbol
)
2673 && (pool
->literals
[entry
].X_op_symbol
2674 == inst
.reloc
.exp
.X_op_symbol
))
2678 /* Do we need to create a new entry? */
2679 if (entry
== pool
->next_free_entry
)
2681 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2683 inst
.error
= _("literal pool overflow");
2687 pool
->literals
[entry
] = inst
.reloc
.exp
;
2688 pool
->next_free_entry
+= 1;
2691 inst
.reloc
.exp
.X_op
= O_symbol
;
2692 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2693 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2698 /* Can't use symbol_new here, so have to create a symbol and then at
2699 a later date assign it a value. Thats what these functions do. */
2702 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2704 const char * name
; /* It is copied, the caller can modify. */
2705 segT segment
; /* Segment identifier (SEG_<something>). */
2706 valueT valu
; /* Symbol value. */
2707 fragS
* frag
; /* Associated fragment. */
2709 unsigned int name_length
;
2710 char * preserved_copy_of_name
;
2712 name_length
= strlen (name
) + 1; /* +1 for \0. */
2713 obstack_grow (¬es
, name
, name_length
);
2714 preserved_copy_of_name
= obstack_finish (¬es
);
2715 #ifdef STRIP_UNDERSCORE
2716 if (preserved_copy_of_name
[0] == '_')
2717 preserved_copy_of_name
++;
2720 #ifdef tc_canonicalize_symbol_name
2721 preserved_copy_of_name
=
2722 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2725 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2727 S_SET_SEGMENT (symbolP
, segment
);
2728 S_SET_VALUE (symbolP
, valu
);
2729 symbol_clear_list_pointers (symbolP
);
2731 symbol_set_frag (symbolP
, frag
);
2733 /* Link to end of symbol chain. */
2735 extern int symbol_table_frozen
;
2736 if (symbol_table_frozen
)
2740 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2742 obj_symbol_new_hook (symbolP
);
2744 #ifdef tc_symbol_new_hook
2745 tc_symbol_new_hook (symbolP
);
2749 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2750 #endif /* DEBUG_SYMS */
2753 /* Check that an immediate is valid.
2754 If so, convert it to the right format. */
2757 validate_immediate (val
)
2763 #define rotate_left(v, n) (v << n | v >> (32 - n))
2765 for (i
= 0; i
< 32; i
+= 2)
2766 if ((a
= rotate_left (val
, i
)) <= 0xff)
2767 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2772 /* Check to see if an immediate can be computed as two separate immediate
2773 values, added together. We already know that this value cannot be
2774 computed by just one ARM instruction. */
2777 validate_immediate_twopart (val
, highpart
)
2779 unsigned int * highpart
;
2784 for (i
= 0; i
< 32; i
+= 2)
2785 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2791 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2793 else if (a
& 0xff0000)
2797 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2801 assert (a
& 0xff000000);
2802 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2805 return (a
& 0xff) | (i
<< 7);
2812 validate_offset_imm (val
, hwse
)
2816 if ((hwse
&& val
> 255) || val
> 4095)
2830 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2831 (This text is taken from version B-02 of the spec):
2833 4.4.7 Mapping and tagging symbols
2835 A section of an ARM ELF file can contain a mixture of ARM code,
2836 Thumb code, and data. There are inline transitions between code
2837 and data at literal pool boundaries. There can also be inline
2838 transitions between ARM code and Thumb code, for example in
2839 ARM-Thumb inter-working veneers. Linkers, machine-level
2840 debuggers, profiling tools, and disassembly tools need to map
2841 images accurately. For example, setting an ARM breakpoint on a
2842 Thumb location, or in a literal pool, can crash the program
2843 being debugged, ruining the debugging session.
2845 ARM ELF entities are mapped (see section 4.4.7.1 below) and
2846 tagged (see section 4.4.7.2 below) using local symbols (with
2847 binding STB_LOCAL). To assist consumers, mapping and tagging
2848 symbols should be collated first in the symbol table, before
2849 other symbols with binding STB_LOCAL.
2851 To allow properly collated mapping and tagging symbols to be
2852 skipped by consumers that have no interest in them, the first
2853 such symbol should have the name $m and its st_value field equal
2854 to the total number of mapping and tagging symbols (including
2855 the $m) in the symbol table.
2857 4.4.7.1 Mapping symbols
2859 $a Labels the first byte of a sequence of ARM instructions.
2860 Its type is STT_FUNC.
2862 $d Labels the first byte of a sequence of data items.
2863 Its type is STT_OBJECT.
2865 $t Labels the first byte of a sequence of Thumb instructions.
2866 Its type is STT_FUNC.
2868 This list of mapping symbols may be extended in the future.
2870 Section-relative mapping symbols
2872 Mapping symbols defined in a section define a sequence of
2873 half-open address intervals that cover the address range of the
2874 section. Each interval starts at the address defined by a
2875 mapping symbol, and continues up to, but not including, the
2876 address defined by the next (in address order) mapping symbol or
2877 the end of the section. A corollary is that there must be a
2878 mapping symbol defined at the beginning of each section.
2879 Consumers can ignore the size of a section-relative mapping
2880 symbol. Producers can set it to 0.
2882 Absolute mapping symbols
2884 Because of the need to crystallize a Thumb address with the
2885 Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2886 STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2889 The extent of a mapping symbol defined in SHN_ABS is [st_value,
2890 st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2891 where [x, y) denotes the half-open address range from x,
2892 inclusive, to y, exclusive.
2894 In the absence of a mapping symbol, a consumer can interpret a
2895 function symbol with an odd value as the Thumb code address
2896 obtained by clearing the least significant bit of the
2897 value. This interpretation is deprecated, and it may not work in
2900 Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2901 the EABI (which is still under development), so they are not
2902 implemented here. */
2905 mapping_state (enum mstate state
)
2907 static enum mstate mapstate
= MAP_DATA
;
2909 const char * symname
;
2912 if (mapstate
== state
)
2913 /* The mapping symbol has already been emitted.
2914 There is nothing else to do. */
2927 type
= BSF_FUNCTION
;
2931 type
= BSF_FUNCTION
;
2937 symbolP
= symbol_new (symname
, now_seg
, (valueT
) frag_now_fix (), frag_now
);
2938 symbol_table_insert (symbolP
);
2939 symbol_get_bfdsym (symbolP
)->flags
|= type
| BSF_LOCAL
;
2944 THUMB_SET_FUNC (symbolP
, 0);
2945 ARM_SET_THUMB (symbolP
, 0);
2946 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2950 THUMB_SET_FUNC (symbolP
, 1);
2951 ARM_SET_THUMB (symbolP
, 1);
2952 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2961 /* When we change sections we need to issue a new mapping symbol. */
2964 arm_elf_change_section (void)
2968 if (!SEG_NORMAL (now_seg
))
2971 flags
= bfd_get_section_flags (stdoutput
, now_seg
);
2973 /* We can ignore sections that only contain debug info. */
2974 if ((flags
& SEC_ALLOC
) == 0)
2977 if (flags
& SEC_CODE
)
2980 mapping_state (MAP_THUMB
);
2982 mapping_state (MAP_ARM
);
2985 /* This section does not contain code. Therefore it must contain data. */
2986 mapping_state (MAP_DATA
);
2989 #define mapping_state(a)
2990 #endif /* OBJ_ELF */
2995 int a ATTRIBUTE_UNUSED
;
2997 as_bad (_("invalid syntax for .req directive"));
3000 /* The .unreq directive deletes an alias which was previously defined
3001 by .req. For example:
3007 s_unreq (int a ATTRIBUTE_UNUSED
)
3012 skip_whitespace (input_line_pointer
);
3013 name
= input_line_pointer
;
3015 while (*input_line_pointer
!= 0
3016 && *input_line_pointer
!= ' '
3017 && *input_line_pointer
!= '\n')
3018 ++input_line_pointer
;
3020 saved_char
= *input_line_pointer
;
3021 *input_line_pointer
= 0;
3025 enum arm_reg_type req_type
= arm_reg_parse_any (name
);
3027 if (req_type
!= REG_TYPE_MAX
)
3029 char *temp_name
= name
;
3030 int req_no
= arm_reg_parse (&temp_name
, all_reg_maps
[req_type
].htab
);
3034 struct reg_entry
*req_entry
;
3036 /* Check to see if this alias is a builtin one. */
3037 req_entry
= hash_delete (all_reg_maps
[req_type
].htab
, name
);
3040 as_bad (_("unreq: missing hash entry for \"%s\""), name
);
3041 else if (req_entry
->builtin
)
3042 /* FIXME: We are deleting a built in register alias which
3043 points to a const data structure, so we only need to
3044 free up the memory used by the key in the hash table.
3045 Unfortunately we have not recorded this value, so this
3046 is a memory leak. */
3047 /* FIXME: Should we issue a warning message ? */
3051 /* Deleting a user defined alias. We need to free the
3052 key and the value, but fortunately the key is the same
3053 as the value->name field. */
3054 free ((char *) req_entry
->name
);
3059 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3062 as_bad (_(".unreq: unrecognized symbol \"%s\""), name
);
3065 as_bad (_("invalid syntax for .unreq directive"));
3067 *input_line_pointer
= saved_char
;
3068 demand_empty_rest_of_line ();
3073 int ignore ATTRIBUTE_UNUSED
;
3075 /* We don't support putting frags in the BSS segment, we fake it by
3076 marking in_bss, then looking at s_skip for clues. */
3077 subseg_set (bss_section
, 0);
3078 demand_empty_rest_of_line ();
3079 mapping_state (MAP_DATA
);
3084 int ignore ATTRIBUTE_UNUSED
;
3086 /* Never make frag if expect extra pass. */
3088 frag_align (1, 0, 0);
3090 record_alignment (now_seg
, 1);
3092 demand_empty_rest_of_line ();
3097 int ignored ATTRIBUTE_UNUSED
;
3100 literal_pool
* pool
;
3103 pool
= find_literal_pool ();
3105 || pool
->symbol
== NULL
3106 || pool
->next_free_entry
== 0)
3109 /* Align pool as you have word accesses.
3110 Only make a frag if we have to. */
3112 frag_align (2, 0, 0);
3114 record_alignment (now_seg
, 2);
3116 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
3118 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
3119 (valueT
) frag_now_fix (), frag_now
);
3120 symbol_table_insert (pool
->symbol
);
3122 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
3124 #if defined OBJ_COFF || defined OBJ_ELF
3125 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
3128 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
3129 /* First output the expression in the instruction to the pool. */
3130 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
3132 /* Mark the pool as empty. */
3133 pool
->next_free_entry
= 0;
3134 pool
->symbol
= NULL
;
3137 /* Same as s_align_ptwo but align 0 => align 2. */
3141 int unused ATTRIBUTE_UNUSED
;
3144 register long temp_fill
;
3145 long max_alignment
= 15;
3147 temp
= get_absolute_expression ();
3148 if (temp
> max_alignment
)
3149 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
3152 as_bad (_("alignment negative. 0 assumed."));
3156 if (*input_line_pointer
== ',')
3158 input_line_pointer
++;
3159 temp_fill
= get_absolute_expression ();
3167 /* Only make a frag if we HAVE to. */
3168 if (temp
&& !need_pass_2
)
3169 frag_align (temp
, (int) temp_fill
, 0);
3170 demand_empty_rest_of_line ();
3172 record_alignment (now_seg
, temp
);
3176 s_force_thumb (ignore
)
3177 int ignore ATTRIBUTE_UNUSED
;
3179 /* If we are not already in thumb mode go into it, EVEN if
3180 the target processor does not support thumb instructions.
3181 This is used by gcc/config/arm/lib1funcs.asm for example
3182 to compile interworking support functions even if the
3183 target processor should not support interworking. */
3188 record_alignment (now_seg
, 1);
3191 demand_empty_rest_of_line ();
3195 s_thumb_func (ignore
)
3196 int ignore ATTRIBUTE_UNUSED
;
3201 /* The following label is the name/address of the start of a Thumb function.
3202 We need to know this for the interworking support. */
3203 label_is_thumb_function_name
= TRUE
;
3205 demand_empty_rest_of_line ();
3208 /* Perform a .set directive, but also mark the alias as
3209 being a thumb function. */
3215 /* XXX the following is a duplicate of the code for s_set() in read.c
3216 We cannot just call that code as we need to get at the symbol that
3218 register char * name
;
3219 register char delim
;
3220 register char * end_name
;
3221 register symbolS
* symbolP
;
3223 /* Especial apologies for the random logic:
3224 This just grew, and could be parsed much more simply!
3226 name
= input_line_pointer
;
3227 delim
= get_symbol_end ();
3228 end_name
= input_line_pointer
;
3233 if (*input_line_pointer
!= ',')
3236 as_bad (_("expected comma after name \"%s\""), name
);
3238 ignore_rest_of_line ();
3242 input_line_pointer
++;
3245 if (name
[0] == '.' && name
[1] == '\0')
3247 /* XXX - this should not happen to .thumb_set. */
3251 if ((symbolP
= symbol_find (name
)) == NULL
3252 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
3255 /* When doing symbol listings, play games with dummy fragments living
3256 outside the normal fragment chain to record the file and line info
3258 if (listing
& LISTING_SYMBOLS
)
3260 extern struct list_info_struct
* listing_tail
;
3261 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
3263 memset (dummy_frag
, 0, sizeof (fragS
));
3264 dummy_frag
->fr_type
= rs_fill
;
3265 dummy_frag
->line
= listing_tail
;
3266 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
3267 dummy_frag
->fr_symbol
= symbolP
;
3271 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
3274 /* "set" symbols are local unless otherwise specified. */
3275 SF_SET_LOCAL (symbolP
);
3276 #endif /* OBJ_COFF */
3277 } /* Make a new symbol. */
3279 symbol_table_insert (symbolP
);
3284 && S_IS_DEFINED (symbolP
)
3285 && S_GET_SEGMENT (symbolP
) != reg_section
)
3286 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
3288 pseudo_set (symbolP
);
3290 demand_empty_rest_of_line ();
3292 /* XXX Now we come to the Thumb specific bit of code. */
3294 THUMB_SET_FUNC (symbolP
, 1);
3295 ARM_SET_THUMB (symbolP
, 1);
3296 #if defined OBJ_ELF || defined OBJ_COFF
3297 ARM_SET_INTERWORK (symbolP
, support_interwork
);
3302 opcode_select (width
)
3310 if (! (cpu_variant
& ARM_EXT_V4T
))
3311 as_bad (_("selected processor does not support THUMB opcodes"));
3314 /* No need to force the alignment, since we will have been
3315 coming from ARM mode, which is word-aligned. */
3316 record_alignment (now_seg
, 1);
3318 mapping_state (MAP_THUMB
);
3324 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
3325 as_bad (_("selected processor does not support ARM opcodes"));
3330 frag_align (2, 0, 0);
3332 record_alignment (now_seg
, 1);
3334 mapping_state (MAP_ARM
);
3338 as_bad (_("invalid instruction size selected (%d)"), width
);
3344 int ignore ATTRIBUTE_UNUSED
;
3347 demand_empty_rest_of_line ();
3352 int ignore ATTRIBUTE_UNUSED
;
3355 demand_empty_rest_of_line ();
3360 int unused ATTRIBUTE_UNUSED
;
3364 temp
= get_absolute_expression ();
3369 opcode_select (temp
);
3373 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
3381 skip_whitespace (str
);
3383 if (*str
!= '\0' && !inst
.error
)
3384 inst
.error
= _("garbage following instruction");
3388 skip_past_comma (str
)
3391 char * p
= * str
, c
;
3394 while ((c
= *p
) == ' ' || c
== ',')
3397 if (c
== ',' && comma
++)
3405 return comma
? SUCCESS
: FAIL
;
3408 /* A standard register must be given at this point.
3409 SHIFT is the place to put it in inst.instruction.
3410 Restores input start point on error.
3411 Returns the reg#, or FAIL. */
3414 reg_required_here (str
, shift
)
3418 static char buff
[128]; /* XXX */
3420 char * start
= * str
;
3422 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3425 inst
.instruction
|= reg
<< shift
;
3429 /* Restore the start point, we may have got a reg of the wrong class. */
3432 /* In the few cases where we might be able to accept something else
3433 this error can be overridden. */
3434 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3440 /* A Intel Wireless MMX technology register
3441 must be given at this point.
3442 Shift is the place to put it in inst.instruction.
3443 Restores input start point on err.
3444 Returns the reg#, or FAIL. */
3447 wreg_required_here (str
, shift
, reg_type
)
3450 enum wreg_type reg_type
;
3452 static char buff
[128];
3454 char * start
= *str
;
3456 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3458 if (wr_register (reg
)
3459 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3462 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3465 else if (wc_register (reg
)
3466 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3469 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3472 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3475 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3480 /* Restore the start point, we may have got a reg of the wrong class. */
3483 /* In the few cases where we might be able to accept
3484 something else this error can be overridden. */
3485 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3491 static const struct asm_psr
*
3493 register char ** ccp
;
3495 char * start
= * ccp
;
3498 const struct asm_psr
* psr
;
3502 /* Skip to the end of the next word in the input stream. */
3507 while (ISALPHA (c
) || c
== '_');
3509 /* Terminate the word. */
3512 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3513 feature for ease of use and backwards compatibility. */
3514 if (!strncmp (start
, "cpsr", 4))
3515 strncpy (start
, "CPSR", 4);
3516 else if (!strncmp (start
, "spsr", 4))
3517 strncpy (start
, "SPSR", 4);
3519 /* Now locate the word in the psr hash table. */
3520 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3522 /* Restore the input stream. */
3525 /* If we found a valid match, advance the
3526 stream pointer past the end of the word. */
3532 /* Parse the input looking for a PSR flag. */
3535 psr_required_here (str
)
3538 char * start
= * str
;
3539 const struct asm_psr
* psr
;
3541 psr
= arm_psr_parse (str
);
3545 /* If this is the SPSR that is being modified, set the R bit. */
3547 inst
.instruction
|= SPSR_BIT
;
3549 /* Set the psr flags in the MSR instruction. */
3550 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3555 /* In the few cases where we might be able to accept
3556 something else this error can be overridden. */
3557 inst
.error
= _("flag for {c}psr instruction expected");
3559 /* Restore the start point. */
3565 co_proc_number (str
)
3568 int processor
, pchar
;
3571 skip_whitespace (*str
);
3574 /* The data sheet seems to imply that just a number on its own is valid
3575 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3577 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3583 if (pchar
>= '0' && pchar
<= '9')
3585 processor
= pchar
- '0';
3586 if (**str
>= '0' && **str
<= '9')
3588 processor
= processor
* 10 + *(*str
)++ - '0';
3591 inst
.error
= _("illegal co-processor number");
3598 inst
.error
= _("bad or missing co-processor number");
3603 inst
.instruction
|= processor
<< 8;
3608 cp_opc_expr (str
, where
, length
)
3615 skip_whitespace (* str
);
3617 memset (&expr
, '\0', sizeof (expr
));
3619 if (my_get_expression (&expr
, str
))
3621 if (expr
.X_op
!= O_constant
)
3623 inst
.error
= _("bad or missing expression");
3627 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3629 inst
.error
= _("immediate co-processor expression too large");
3633 inst
.instruction
|= expr
.X_add_number
<< where
;
3638 cp_reg_required_here (str
, where
)
3643 char * start
= *str
;
3645 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3647 inst
.instruction
|= reg
<< where
;
3651 /* In the few cases where we might be able to accept something else
3652 this error can be overridden. */
3653 inst
.error
= _("co-processor register expected");
3655 /* Restore the start point. */
3661 fp_reg_required_here (str
, where
)
3666 char * start
= * str
;
3668 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3670 inst
.instruction
|= reg
<< where
;
3674 /* In the few cases where we might be able to accept something else
3675 this error can be overridden. */
3676 inst
.error
= _("floating point register expected");
3678 /* Restore the start point. */
3684 cp_address_offset (str
)
3689 skip_whitespace (* str
);
3691 if (! is_immediate_prefix (**str
))
3693 inst
.error
= _("immediate expression expected");
3699 if (my_get_expression (& inst
.reloc
.exp
, str
))
3702 if (inst
.reloc
.exp
.X_op
== O_constant
)
3704 offset
= inst
.reloc
.exp
.X_add_number
;
3708 inst
.error
= _("co-processor address must be word aligned");
3712 if (offset
> 1023 || offset
< -1023)
3714 inst
.error
= _("offset too large");
3719 inst
.instruction
|= INDEX_UP
;
3723 inst
.instruction
|= offset
>> 2;
3726 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3732 cp_address_required_here (str
, wb_ok
)
3745 skip_whitespace (p
);
3747 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3750 skip_whitespace (p
);
3756 skip_whitespace (p
);
3760 /* As an extension to the official ARM syntax we allow:
3764 as a short hand for:
3767 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3772 if (skip_past_comma (& p
) == FAIL
)
3774 inst
.error
= _("comma expected after closing square bracket");
3778 skip_whitespace (p
);
3785 write_back
= WRITE_BACK
;
3789 inst
.error
= _("pc may not be used in post-increment");
3793 if (cp_address_offset (& p
) == FAIL
)
3797 pre_inc
= PRE_INDEX
| INDEX_UP
;
3803 /* [Rn], {<expr>} */
3806 skip_whitespace (p
);
3808 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3811 if (inst
.reloc
.exp
.X_op
== O_constant
)
3813 option
= inst
.reloc
.exp
.X_add_number
;
3815 if (option
> 255 || option
< 0)
3817 inst
.error
= _("'option' field too large");
3821 skip_whitespace (p
);
3825 inst
.error
= _("'}' expected at end of 'option' field");
3831 inst
.instruction
|= option
;
3832 inst
.instruction
|= INDEX_UP
;
3837 inst
.error
= _("non-constant expressions for 'option' field not supported");
3843 inst
.error
= _("# or { expected after comma");
3849 /* '['Rn, #expr']'[!] */
3851 if (skip_past_comma (& p
) == FAIL
)
3853 inst
.error
= _("pre-indexed expression expected");
3857 pre_inc
= PRE_INDEX
;
3859 if (cp_address_offset (& p
) == FAIL
)
3862 skip_whitespace (p
);
3866 inst
.error
= _("missing ]");
3870 skip_whitespace (p
);
3872 if (wb_ok
&& *p
== '!')
3876 inst
.error
= _("pc may not be used with write-back");
3881 write_back
= WRITE_BACK
;
3887 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3890 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3891 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3892 inst
.reloc
.pc_rel
= 1;
3893 inst
.instruction
|= (REG_PC
<< 16);
3894 pre_inc
= PRE_INDEX
;
3897 inst
.instruction
|= write_back
| pre_inc
;
3903 cp_byte_address_offset (str
)
3908 skip_whitespace (* str
);
3910 if (! is_immediate_prefix (**str
))
3912 inst
.error
= _("immediate expression expected");
3918 if (my_get_expression (& inst
.reloc
.exp
, str
))
3921 if (inst
.reloc
.exp
.X_op
== O_constant
)
3923 offset
= inst
.reloc
.exp
.X_add_number
;
3925 if (offset
> 255 || offset
< -255)
3927 inst
.error
= _("offset too large");
3932 inst
.instruction
|= INDEX_UP
;
3936 inst
.instruction
|= offset
;
3939 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3945 cp_byte_address_required_here (str
)
3957 skip_whitespace (p
);
3959 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3962 skip_whitespace (p
);
3968 if (skip_past_comma (& p
) == SUCCESS
)
3971 write_back
= WRITE_BACK
;
3975 inst
.error
= _("pc may not be used in post-increment");
3979 if (cp_byte_address_offset (& p
) == FAIL
)
3983 pre_inc
= PRE_INDEX
| INDEX_UP
;
3987 /* '['Rn, #expr']'[!] */
3989 if (skip_past_comma (& p
) == FAIL
)
3991 inst
.error
= _("pre-indexed expression expected");
3995 pre_inc
= PRE_INDEX
;
3997 if (cp_byte_address_offset (& p
) == FAIL
)
4000 skip_whitespace (p
);
4004 inst
.error
= _("missing ]");
4008 skip_whitespace (p
);
4014 inst
.error
= _("pc may not be used with write-back");
4019 write_back
= WRITE_BACK
;
4025 if (my_get_expression (&inst
.reloc
.exp
, &p
))
4028 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
4029 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4030 inst
.reloc
.pc_rel
= 1;
4031 inst
.instruction
|= (REG_PC
<< 16);
4032 pre_inc
= PRE_INDEX
;
4035 inst
.instruction
|= write_back
| pre_inc
;
4044 /* Do nothing really. */
4054 /* Only one syntax. */
4055 skip_whitespace (str
);
4057 if (reg_required_here (&str
, 12) == FAIL
)
4059 inst
.error
= BAD_ARGS
;
4063 if (skip_past_comma (&str
) == FAIL
)
4065 inst
.error
= _("comma expected after register name");
4069 skip_whitespace (str
);
4071 if ( strcmp (str
, "CPSR") == 0
4072 || strcmp (str
, "SPSR") == 0
4073 /* Lower case versions for backwards compatibility. */
4074 || strcmp (str
, "cpsr") == 0
4075 || strcmp (str
, "spsr") == 0)
4078 /* This is for backwards compatibility with older toolchains. */
4079 else if ( strcmp (str
, "cpsr_all") == 0
4080 || strcmp (str
, "spsr_all") == 0)
4084 inst
.error
= _("CPSR or SPSR expected");
4088 if (* str
== 's' || * str
== 'S')
4089 inst
.instruction
|= SPSR_BIT
;
4095 /* Two possible forms:
4096 "{C|S}PSR_<field>, Rm",
4097 "{C|S}PSR_f, #expression". */
4103 skip_whitespace (str
);
4105 if (psr_required_here (& str
) == FAIL
)
4108 if (skip_past_comma (& str
) == FAIL
)
4110 inst
.error
= _("comma missing after psr flags");
4114 skip_whitespace (str
);
4116 if (reg_required_here (& str
, 0) != FAIL
)
4123 if (! is_immediate_prefix (* str
))
4126 _("only a register or immediate value can follow a psr flag");
4133 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4136 _("only a register or immediate value can follow a psr flag");
4140 #if 0 /* The first edition of the ARM architecture manual stated that
4141 writing anything other than the flags with an immediate operation
4142 had UNPREDICTABLE effects. This constraint was removed in the
4143 second edition of the specification. */
4144 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
4145 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
4147 inst
.error
= _("immediate value cannot be used to set this field");
4152 inst
.instruction
|= INST_IMMEDIATE
;
4154 if (inst
.reloc
.exp
.X_add_symbol
)
4156 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4157 inst
.reloc
.pc_rel
= 0;
4161 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4163 if (value
== (unsigned) FAIL
)
4165 inst
.error
= _("invalid constant");
4169 inst
.instruction
|= value
;
4176 /* Long Multiply Parser
4177 UMULL RdLo, RdHi, Rm, Rs
4178 SMULL RdLo, RdHi, Rm, Rs
4179 UMLAL RdLo, RdHi, Rm, Rs
4180 SMLAL RdLo, RdHi, Rm, Rs. */
4186 int rdlo
, rdhi
, rm
, rs
;
4188 /* Only one format "rdlo, rdhi, rm, rs". */
4189 skip_whitespace (str
);
4191 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
4193 inst
.error
= BAD_ARGS
;
4197 if (skip_past_comma (&str
) == FAIL
4198 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
4200 inst
.error
= BAD_ARGS
;
4204 if (skip_past_comma (&str
) == FAIL
4205 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4207 inst
.error
= BAD_ARGS
;
4211 /* rdhi, rdlo and rm must all be different. */
4212 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
4213 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4215 if (skip_past_comma (&str
) == FAIL
4216 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
4218 inst
.error
= BAD_ARGS
;
4222 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
4224 inst
.error
= BAD_PC
;
4237 /* Only one format "rd, rm, rs". */
4238 skip_whitespace (str
);
4240 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4242 inst
.error
= BAD_ARGS
;
4248 inst
.error
= BAD_PC
;
4252 if (skip_past_comma (&str
) == FAIL
4253 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4255 inst
.error
= BAD_ARGS
;
4261 inst
.error
= BAD_PC
;
4266 as_tsktsk (_("rd and rm should be different in mul"));
4268 if (skip_past_comma (&str
) == FAIL
4269 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
4271 inst
.error
= BAD_ARGS
;
4277 inst
.error
= BAD_PC
;
4290 /* Only one format "rd, rm, rs, rn". */
4291 skip_whitespace (str
);
4293 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
4295 inst
.error
= BAD_ARGS
;
4301 inst
.error
= BAD_PC
;
4305 if (skip_past_comma (&str
) == FAIL
4306 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
4308 inst
.error
= BAD_ARGS
;
4314 inst
.error
= BAD_PC
;
4319 as_tsktsk (_("rd and rm should be different in mla"));
4321 if (skip_past_comma (&str
) == FAIL
4322 || (rd
= reg_required_here (&str
, 8)) == FAIL
4323 || skip_past_comma (&str
) == FAIL
4324 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
4326 inst
.error
= BAD_ARGS
;
4330 if (rd
== REG_PC
|| rm
== REG_PC
)
4332 inst
.error
= BAD_PC
;
4339 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4340 Advances *str to the next non-alphanumeric.
4341 Returns 0, or else FAIL (in which case sets inst.error).
4343 (In a future XScale, there may be accumulators other than zero.
4344 At that time this routine and its callers can be upgraded to suit.) */
4347 accum0_required_here (str
)
4350 static char buff
[128]; /* Note the address is taken. Hence, static. */
4353 int result
= 0; /* The accum number. */
4355 skip_whitespace (p
);
4357 *str
= p
; /* Advance caller's string pointer too. */
4362 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
4364 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
4366 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
4371 *p
= c
; /* Unzap. */
4372 *str
= p
; /* Caller's string pointer to after match. */
4376 /* Expects **str -> after a comma. May be leading blanks.
4377 Advances *str, recognizing a load mode, and setting inst.instruction.
4378 Returns rn, or else FAIL (in which case may set inst.error
4379 and not advance str)
4381 Note: doesn't know Rd, so no err checks that require such knowledge. */
4384 ld_mode_required_here (string
)
4387 char * str
= * string
;
4391 skip_whitespace (str
);
4397 skip_whitespace (str
);
4399 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4402 skip_whitespace (str
);
4408 if (skip_past_comma (& str
) == SUCCESS
)
4410 /* [Rn],... (post inc) */
4411 if (ldst_extend_v4 (&str
) == FAIL
)
4416 skip_whitespace (str
);
4421 inst
.instruction
|= WRITE_BACK
;
4424 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4430 if (skip_past_comma (& str
) == FAIL
)
4432 inst
.error
= _("pre-indexed expression expected");
4438 if (ldst_extend_v4 (&str
) == FAIL
)
4441 skip_whitespace (str
);
4443 if (* str
++ != ']')
4445 inst
.error
= _("missing ]");
4449 skip_whitespace (str
);
4454 inst
.instruction
|= WRITE_BACK
;
4458 else if (* str
== '=') /* ldr's "r,=label" syntax */
4459 /* We should never reach here, because <text> = <expression> is
4460 caught gas/read.c read_a_source_file() as a .set operation. */
4462 else /* PC +- 8 bit immediate offset. */
4464 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4467 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4468 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4469 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4470 inst
.reloc
.pc_rel
= 1;
4471 inst
.instruction
|= (REG_PC
<< 16);
4477 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4483 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4484 SMLAxy{cond} Rd,Rm,Rs,Rn
4485 SMLAWy{cond} Rd,Rm,Rs,Rn
4486 Error if any register is R15. */
4494 skip_whitespace (str
);
4496 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4497 || skip_past_comma (& str
) == FAIL
4498 || (rm
= reg_required_here (& str
, 0)) == FAIL
4499 || skip_past_comma (& str
) == FAIL
4500 || (rs
= reg_required_here (& str
, 8)) == FAIL
4501 || skip_past_comma (& str
) == FAIL
4502 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4503 inst
.error
= BAD_ARGS
;
4505 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4506 inst
.error
= BAD_PC
;
4512 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4513 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4514 Error if any register is R15.
4515 Warning if Rdlo == Rdhi. */
4521 int rdlo
, rdhi
, rm
, rs
;
4523 skip_whitespace (str
);
4525 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4526 || skip_past_comma (& str
) == FAIL
4527 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4528 || skip_past_comma (& str
) == FAIL
4529 || (rm
= reg_required_here (& str
, 0)) == FAIL
4530 || skip_past_comma (& str
) == FAIL
4531 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4533 inst
.error
= BAD_ARGS
;
4537 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4539 inst
.error
= BAD_PC
;
4544 as_tsktsk (_("rdhi and rdlo must be different"));
4549 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4550 SMULxy{cond} Rd,Rm,Rs
4551 Error if any register is R15. */
4559 skip_whitespace (str
);
4561 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4562 || skip_past_comma (& str
) == FAIL
4563 || (rm
= reg_required_here (& str
, 0)) == FAIL
4564 || skip_past_comma (& str
) == FAIL
4565 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4566 inst
.error
= BAD_ARGS
;
4568 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4569 inst
.error
= BAD_PC
;
4575 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4576 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4577 Error if any register is R15. */
4585 skip_whitespace (str
);
4587 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4588 || skip_past_comma (& str
) == FAIL
4589 || (rm
= reg_required_here (& str
, 0)) == FAIL
4590 || skip_past_comma (& str
) == FAIL
4591 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4592 inst
.error
= BAD_ARGS
;
4594 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4595 inst
.error
= BAD_PC
;
4601 /* ARM V5E (el Segundo)
4602 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4603 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4605 These are equivalent to the XScale instructions MAR and MRA,
4606 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4608 Result unpredicatable if Rd or Rn is R15. */
4616 skip_whitespace (str
);
4618 if (co_proc_number (& str
) == FAIL
)
4621 inst
.error
= BAD_ARGS
;
4625 if (skip_past_comma (& str
) == FAIL
4626 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4629 inst
.error
= BAD_ARGS
;
4633 if (skip_past_comma (& str
) == FAIL
4634 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4637 inst
.error
= BAD_ARGS
;
4641 if (skip_past_comma (& str
) == FAIL
4642 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4645 inst
.error
= BAD_ARGS
;
4649 /* Unpredictable result if rd or rn is R15. */
4650 if (rd
== REG_PC
|| rn
== REG_PC
)
4652 (_("Warning: instruction unpredictable when using r15"));
4654 if (skip_past_comma (& str
) == FAIL
4655 || cp_reg_required_here (& str
, 0) == FAIL
)
4658 inst
.error
= BAD_ARGS
;
4665 /* ARM V5 count-leading-zeroes instruction (argument parse)
4666 CLZ{<cond>} <Rd>, <Rm>
4667 Condition defaults to COND_ALWAYS.
4668 Error if Rd or Rm are R15. */
4676 skip_whitespace (str
);
4678 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4679 || (skip_past_comma (& str
) == FAIL
)
4680 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4681 inst
.error
= BAD_ARGS
;
4683 else if (rd
== REG_PC
|| rm
== REG_PC
)
4684 inst
.error
= BAD_PC
;
4690 /* ARM V5 (argument parse)
4691 LDC2{L} <coproc>, <CRd>, <addressing mode>
4692 STC2{L} <coproc>, <CRd>, <addressing mode>
4693 Instruction is not conditional, and has 0xf in the condition field.
4694 Otherwise, it's the same as LDC/STC. */
4700 skip_whitespace (str
);
4702 if (co_proc_number (& str
) == FAIL
)
4705 inst
.error
= BAD_ARGS
;
4707 else if (skip_past_comma (& str
) == FAIL
4708 || cp_reg_required_here (& str
, 12) == FAIL
)
4711 inst
.error
= BAD_ARGS
;
4713 else if (skip_past_comma (& str
) == FAIL
4714 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4717 inst
.error
= BAD_ARGS
;
4723 /* ARM V5 (argument parse)
4724 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4725 Instruction is not conditional, and has 0xf in the condition field.
4726 Otherwise, it's the same as CDP. */
4732 skip_whitespace (str
);
4734 if (co_proc_number (& str
) == FAIL
)
4737 inst
.error
= BAD_ARGS
;
4741 if (skip_past_comma (& str
) == FAIL
4742 || cp_opc_expr (& str
, 20,4) == FAIL
)
4745 inst
.error
= BAD_ARGS
;
4749 if (skip_past_comma (& str
) == FAIL
4750 || cp_reg_required_here (& str
, 12) == FAIL
)
4753 inst
.error
= BAD_ARGS
;
4757 if (skip_past_comma (& str
) == FAIL
4758 || cp_reg_required_here (& str
, 16) == FAIL
)
4761 inst
.error
= BAD_ARGS
;
4765 if (skip_past_comma (& str
) == FAIL
4766 || cp_reg_required_here (& str
, 0) == FAIL
)
4769 inst
.error
= BAD_ARGS
;
4773 if (skip_past_comma (& str
) == SUCCESS
)
4775 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4778 inst
.error
= BAD_ARGS
;
4786 /* ARM V5 (argument parse)
4787 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4788 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4789 Instruction is not conditional, and has 0xf in the condition field.
4790 Otherwise, it's the same as MCR/MRC. */
4796 skip_whitespace (str
);
4798 if (co_proc_number (& str
) == FAIL
)
4801 inst
.error
= BAD_ARGS
;
4805 if (skip_past_comma (& str
) == FAIL
4806 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4809 inst
.error
= BAD_ARGS
;
4813 if (skip_past_comma (& str
) == FAIL
4814 || reg_required_here (& str
, 12) == FAIL
)
4817 inst
.error
= BAD_ARGS
;
4821 if (skip_past_comma (& str
) == FAIL
4822 || cp_reg_required_here (& str
, 16) == FAIL
)
4825 inst
.error
= BAD_ARGS
;
4829 if (skip_past_comma (& str
) == FAIL
4830 || cp_reg_required_here (& str
, 0) == FAIL
)
4833 inst
.error
= BAD_ARGS
;
4837 if (skip_past_comma (& str
) == SUCCESS
)
4839 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4842 inst
.error
= BAD_ARGS
;
4850 /* ARM v5TEJ. Jump to Jazelle code. */
4857 skip_whitespace (str
);
4859 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4861 inst
.error
= BAD_ARGS
;
4865 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4867 as_tsktsk (_("use of r15 in bxj is not really useful"));
4872 /* ARM V6 umaal (argument parse). */
4879 int rdlo
, rdhi
, rm
, rs
;
4881 skip_whitespace (str
);
4882 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4883 || skip_past_comma (& str
) == FAIL
4884 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4885 || skip_past_comma (& str
) == FAIL
4886 || (rm
= reg_required_here (& str
, 0)) == FAIL
4887 || skip_past_comma (& str
) == FAIL
4888 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4890 inst
.error
= BAD_ARGS
;
4894 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4896 inst
.error
= BAD_PC
;
4903 /* ARM V6 strex (argument parse). */
4911 /* Parse Rd, Rm,. */
4912 skip_whitespace (str
);
4913 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4914 || skip_past_comma (& str
) == FAIL
4915 || (rm
= reg_required_here (& str
, 0)) == FAIL
4916 || skip_past_comma (& str
) == FAIL
)
4918 inst
.error
= BAD_ARGS
;
4921 if (rd
== REG_PC
|| rm
== REG_PC
)
4923 inst
.error
= BAD_PC
;
4928 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4932 /* Skip past '['. */
4933 if ((strlen (str
) >= 1)
4934 && strncmp (str
, "[", 1) == 0)
4936 skip_whitespace (str
);
4939 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
4941 inst
.error
= BAD_ARGS
;
4944 else if (rn
== REG_PC
)
4946 inst
.error
= BAD_PC
;
4951 inst
.error
= _("Rd equal to Rm or Rn yields unpredictable results");
4954 skip_whitespace (str
);
4956 /* Skip past ']'. */
4957 if ((strlen (str
) >= 1)
4958 && strncmp (str
, "]", 1) == 0)
4964 /* ARM V6 ssat (argument parse). */
4970 do_sat (&str
, /*bias=*/-1);
4974 /* ARM V6 usat (argument parse). */
4980 do_sat (&str
, /*bias=*/0);
4992 skip_whitespace (*str
);
4994 /* Parse <Rd>, field. */
4995 if ((rd
= reg_required_here (str
, 12)) == FAIL
4996 || skip_past_comma (str
) == FAIL
)
4998 inst
.error
= BAD_ARGS
;
5003 inst
.error
= BAD_PC
;
5007 /* Parse #<immed>, field. */
5008 if (is_immediate_prefix (**str
))
5012 inst
.error
= _("immediate expression expected");
5015 if (my_get_expression (&expr
, str
))
5017 inst
.error
= _("bad expression");
5020 if (expr
.X_op
!= O_constant
)
5022 inst
.error
= _("constant expression expected");
5025 if (expr
.X_add_number
+ bias
< 0
5026 || expr
.X_add_number
+ bias
> 31)
5028 inst
.error
= _("immediate value out of range");
5031 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5032 if (skip_past_comma (str
) == FAIL
)
5034 inst
.error
= BAD_ARGS
;
5038 /* Parse <Rm> field. */
5039 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5041 inst
.error
= BAD_ARGS
;
5046 inst
.error
= BAD_PC
;
5050 if (skip_past_comma (str
) == SUCCESS
)
5051 decode_shift (str
, SHIFT_LSL_OR_ASR_IMMEDIATE
);
5054 /* ARM V6 ssat16 (argument parse). */
5060 do_sat16 (&str
, /*bias=*/-1);
5068 do_sat16 (&str
, /*bias=*/0);
5073 do_sat16 (str
, bias
)
5080 skip_whitespace (*str
);
5082 /* Parse the <Rd> field. */
5083 if ((rd
= reg_required_here (str
, 12)) == FAIL
5084 || skip_past_comma (str
) == FAIL
)
5086 inst
.error
= BAD_ARGS
;
5091 inst
.error
= BAD_PC
;
5095 /* Parse #<immed>, field. */
5096 if (is_immediate_prefix (**str
))
5100 inst
.error
= _("immediate expression expected");
5103 if (my_get_expression (&expr
, str
))
5105 inst
.error
= _("bad expression");
5108 if (expr
.X_op
!= O_constant
)
5110 inst
.error
= _("constant expression expected");
5113 if (expr
.X_add_number
+ bias
< 0
5114 || expr
.X_add_number
+ bias
> 15)
5116 inst
.error
= _("immediate value out of range");
5119 inst
.instruction
|= (expr
.X_add_number
+ bias
) << 16;
5120 if (skip_past_comma (str
) == FAIL
)
5122 inst
.error
= BAD_ARGS
;
5126 /* Parse <Rm> field. */
5127 if ((rm
= reg_required_here (str
, 0)) == FAIL
)
5129 inst
.error
= BAD_ARGS
;
5134 inst
.error
= BAD_PC
;
5139 /* ARM V6 srs (argument parse). */
5146 skip_whitespace (str
);
5147 exclam
= strchr (str
, '!');
5155 inst
.instruction
|= WRITE_BACK
;
5161 /* ARM V6 SMMUL (argument parse). */
5169 skip_whitespace (str
);
5170 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5171 || skip_past_comma (&str
) == FAIL
5172 || (rm
= reg_required_here (&str
, 0)) == FAIL
5173 || skip_past_comma (&str
) == FAIL
5174 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5176 inst
.error
= BAD_ARGS
;
5184 inst
.error
= BAD_PC
;
5192 /* ARM V6 SMLALD (argument parse). */
5198 int rdlo
, rdhi
, rm
, rs
;
5199 skip_whitespace (str
);
5200 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
5201 || skip_past_comma (&str
) == FAIL
5202 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
5203 || skip_past_comma (&str
) == FAIL
5204 || (rm
= reg_required_here (&str
, 0)) == FAIL
5205 || skip_past_comma (&str
) == FAIL
5206 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
5208 inst
.error
= BAD_ARGS
;
5217 inst
.error
= BAD_PC
;
5224 /* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
5225 smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5233 skip_whitespace (str
);
5234 if ((rd
= reg_required_here (&str
, 16)) == FAIL
5235 || skip_past_comma (&str
) == FAIL
5236 || (rm
= reg_required_here (&str
, 0)) == FAIL
5237 || skip_past_comma (&str
) == FAIL
5238 || (rs
= reg_required_here (&str
, 8)) == FAIL
5239 || skip_past_comma (&str
) == FAIL
5240 || (rn
= reg_required_here (&str
, 12)) == FAIL
)
5242 inst
.error
= BAD_ARGS
;
5251 inst
.error
= BAD_PC
;
5258 /* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
5259 preserving the other bits.
5261 setend <endian_specifier>, where <endian_specifier> is either
5268 if (do_endian_specifier (str
))
5269 inst
.instruction
|= 0x200;
5272 /* Returns true if the endian-specifier indicates big-endianness. */
5275 do_endian_specifier (str
)
5280 skip_whitespace (str
);
5281 if (strlen (str
) < 2)
5282 inst
.error
= _("missing endian specifier");
5283 else if (strncasecmp (str
, "BE", 2) == 0)
5288 else if (strncasecmp (str
, "LE", 2) == 0)
5291 inst
.error
= _("valid endian specifiers are be or le");
5300 SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5301 Condition defaults to COND_ALWAYS.
5302 Error if any register uses R15. */
5310 int rotation_clear_mask
= 0xfffff3ff;
5311 int rotation_eight_mask
= 0x00000400;
5312 int rotation_sixteen_mask
= 0x00000800;
5313 int rotation_twenty_four_mask
= 0x00000c00;
5315 skip_whitespace (str
);
5316 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5317 || skip_past_comma (&str
) == FAIL
5318 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5320 inst
.error
= BAD_ARGS
;
5324 else if (rd
== REG_PC
|| rm
== REG_PC
)
5326 inst
.error
= BAD_PC
;
5330 /* Zero out the rotation field. */
5331 inst
.instruction
&= rotation_clear_mask
;
5333 /* Check for lack of optional rotation field. */
5334 if (skip_past_comma (&str
) == FAIL
)
5340 /* Move past 'ROR'. */
5341 skip_whitespace (str
);
5342 if (strncasecmp (str
, "ROR", 3) == 0)
5346 inst
.error
= _("missing rotation field after comma");
5350 /* Get the immediate constant. */
5351 skip_whitespace (str
);
5352 if (is_immediate_prefix (* str
))
5356 inst
.error
= _("immediate expression expected");
5360 if (my_get_expression (&expr
, &str
))
5362 inst
.error
= _("bad expression");
5366 if (expr
.X_op
!= O_constant
)
5368 inst
.error
= _("constant expression expected");
5372 switch (expr
.X_add_number
)
5375 /* Rotation field has already been zeroed. */
5378 inst
.instruction
|= rotation_eight_mask
;
5382 inst
.instruction
|= rotation_sixteen_mask
;
5386 inst
.instruction
|= rotation_twenty_four_mask
;
5390 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5398 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5399 extends it to 32-bits, and adds the result to a value in another
5400 register. You can specify a rotation by 0, 8, 16, or 24 bits
5401 before extracting the 16-bit value.
5402 SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5403 Condition defaults to COND_ALWAYS.
5404 Error if any register uses R15. */
5412 int rotation_clear_mask
= 0xfffff3ff;
5413 int rotation_eight_mask
= 0x00000400;
5414 int rotation_sixteen_mask
= 0x00000800;
5415 int rotation_twenty_four_mask
= 0x00000c00;
5417 skip_whitespace (str
);
5418 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5419 || skip_past_comma (&str
) == FAIL
5420 || (rn
= reg_required_here (&str
, 16)) == FAIL
5421 || skip_past_comma (&str
) == FAIL
5422 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5424 inst
.error
= BAD_ARGS
;
5428 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5430 inst
.error
= BAD_PC
;
5434 /* Zero out the rotation field. */
5435 inst
.instruction
&= rotation_clear_mask
;
5437 /* Check for lack of optional rotation field. */
5438 if (skip_past_comma (&str
) == FAIL
)
5444 /* Move past 'ROR'. */
5445 skip_whitespace (str
);
5446 if (strncasecmp (str
, "ROR", 3) == 0)
5450 inst
.error
= _("missing rotation field after comma");
5454 /* Get the immediate constant. */
5455 skip_whitespace (str
);
5456 if (is_immediate_prefix (* str
))
5460 inst
.error
= _("immediate expression expected");
5464 if (my_get_expression (&expr
, &str
))
5466 inst
.error
= _("bad expression");
5470 if (expr
.X_op
!= O_constant
)
5472 inst
.error
= _("constant expression expected");
5476 switch (expr
.X_add_number
)
5479 /* Rotation field has already been zeroed. */
5483 inst
.instruction
|= rotation_eight_mask
;
5487 inst
.instruction
|= rotation_sixteen_mask
;
5491 inst
.instruction
|= rotation_twenty_four_mask
;
5495 inst
.error
= _("rotation can be 8, 16, 24 or 0 when field is ommited");
5504 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5505 word at the specified address and the following word
5507 Unconditionally executed.
5517 skip_whitespace (str
);
5519 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5524 inst
.error
= BAD_PC
;
5528 skip_whitespace (str
);
5532 inst
.instruction
|= WRITE_BACK
;
5538 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5539 register (argument parse).
5541 Condition defaults to COND_ALWAYS.
5542 Error if Rd or Rm are R15. */
5550 skip_whitespace (str
);
5552 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5553 || skip_past_comma (&str
) == FAIL
5554 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5555 inst
.error
= BAD_ARGS
;
5557 else if (rd
== REG_PC
|| rm
== REG_PC
)
5558 inst
.error
= BAD_PC
;
5564 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5565 QADD16{<cond>} <Rd>, <Rn>, <Rm>
5566 Condition defaults to COND_ALWAYS.
5567 Error if Rd, Rn or Rm are R15. */
5575 skip_whitespace (str
);
5577 if ((rd
= reg_required_here (&str
, 12)) == FAIL
5578 || skip_past_comma (&str
) == FAIL
5579 || (rn
= reg_required_here (&str
, 16)) == FAIL
5580 || skip_past_comma (&str
) == FAIL
5581 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
5582 inst
.error
= BAD_ARGS
;
5584 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
5585 inst
.error
= BAD_PC
;
5591 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5592 PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5593 Condition defaults to COND_ALWAYS.
5594 Error if Rd, Rn or Rm are R15. */
5600 do_pkh_core (str
, SHIFT_LSL_IMMEDIATE
);
5603 /* ARM V6 PKHTB (Argument Parse). */
5609 do_pkh_core (str
, SHIFT_ASR_IMMEDIATE
);
5613 do_pkh_core (str
, shift
)
5619 skip_whitespace (str
);
5620 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5621 || (skip_past_comma (&str
) == FAIL
)
5622 || ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5623 || (skip_past_comma (&str
) == FAIL
)
5624 || ((rm
= reg_required_here (&str
, 0)) == FAIL
))
5626 inst
.error
= BAD_ARGS
;
5630 else if (rd
== REG_PC
|| rn
== REG_PC
|| rm
== REG_PC
)
5632 inst
.error
= BAD_PC
;
5636 /* Check for optional shift immediate constant. */
5637 if (skip_past_comma (&str
) == FAIL
)
5639 if (shift
== SHIFT_ASR_IMMEDIATE
)
5641 /* If the shift specifier is ommited, turn the instruction
5642 into pkhbt rd, rm, rn. First, switch the instruction
5643 code, and clear the rn and rm fields. */
5644 inst
.instruction
&= 0xfff0f010;
5645 /* Now, re-encode the registers. */
5646 inst
.instruction
|= (rm
<< 16) | rn
;
5651 decode_shift (&str
, shift
);
5654 /* ARM V6 Load Register Exclusive instruction (argument parse).
5655 LDREX{<cond>} <Rd, [<Rn>]
5656 Condition defaults to COND_ALWAYS.
5657 Error if Rd or Rn are R15.
5658 See ARMARMv6 A4.1.27: LDREX. */
5667 skip_whitespace (str
);
5670 if (((rd
= reg_required_here (&str
, 12)) == FAIL
)
5671 || (skip_past_comma (&str
) == FAIL
))
5673 inst
.error
= BAD_ARGS
;
5676 else if (rd
== REG_PC
)
5678 inst
.error
= BAD_PC
;
5681 skip_whitespace (str
);
5683 /* Skip past '['. */
5684 if ((strlen (str
) >= 1)
5685 &&strncmp (str
, "[", 1) == 0)
5687 skip_whitespace (str
);
5690 if ((rn
= reg_required_here (&str
, 16)) == FAIL
)
5692 inst
.error
= BAD_ARGS
;
5695 else if (rn
== REG_PC
)
5697 inst
.error
= BAD_PC
;
5700 skip_whitespace (str
);
5702 /* Skip past ']'. */
5703 if ((strlen (str
) >= 1)
5704 && strncmp (str
, "]", 1) == 0)
5710 /* ARM V6 change processor state instruction (argument parse)
5711 CPS, CPSIE, CSPID . */
5725 do_cps_flags (&str
, /*thumb_p=*/0);
5727 if (skip_past_comma (&str
) == SUCCESS
)
5729 skip_whitespace (str
);
5741 skip_whitespace (*str
);
5743 if (! is_immediate_prefix (**str
))
5745 inst
.error
= _("immediate expression expected");
5749 (*str
)++; /* Strip off the immediate signifier. */
5750 if (my_get_expression (&expr
, str
))
5752 inst
.error
= _("bad expression");
5756 if (expr
.X_op
!= O_constant
)
5758 inst
.error
= _("constant expression expected");
5762 /* The mode is a 5 bit field. Valid values are 0-31. */
5763 if (((unsigned) expr
.X_add_number
) > 31
5764 || (inst
.reloc
.exp
.X_add_number
) < 0)
5766 inst
.error
= _("invalid constant");
5770 inst
.instruction
|= expr
.X_add_number
;
5774 do_cps_flags (str
, thumb_p
)
5780 unsigned long arm_value
;
5781 unsigned long thumb_value
;
5783 static struct cps_flag flag_table
[] = {
5791 skip_whitespace (*str
);
5793 /* Get the a, f and i flags. */
5794 while (**str
&& **str
!= ',')
5797 struct cps_flag
*q
= flag_table
+ sizeof (flag_table
)/sizeof (*p
);
5798 for (p
= flag_table
; p
< q
; ++p
)
5799 if (strncasecmp (*str
, &p
->character
, 1) == 0)
5801 inst
.instruction
|= (thumb_p
? p
->thumb_value
: p
->arm_value
);
5807 inst
.error
= _("unrecognized flag");
5813 inst
.error
= _("no 'a', 'i', or 'f' flags for 'cps'");
5816 /* THUMB V5 breakpoint instruction (argument parse)
5824 unsigned long number
;
5826 skip_whitespace (str
);
5828 /* Allow optional leading '#'. */
5829 if (is_immediate_prefix (*str
))
5832 memset (& expr
, '\0', sizeof (expr
));
5833 if (my_get_expression (& expr
, & str
)
5834 || (expr
.X_op
!= O_constant
5835 /* As a convenience we allow 'bkpt' without an operand. */
5836 && expr
.X_op
!= O_absent
))
5838 inst
.error
= _("bad expression");
5842 number
= expr
.X_add_number
;
5844 /* Check it fits an 8 bit unsigned. */
5845 if (number
!= (number
& 0xff))
5847 inst
.error
= _("immediate value out of range");
5851 inst
.instruction
|= number
;
5856 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5857 Expects inst.instruction is set for BLX(1).
5858 Note: this is cloned from do_branch, and the reloc changed to be a
5859 new one that can cope with setting one extra bit (the H bit). */
5865 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5872 /* ScottB: February 5, 1998 */
5873 /* Check to see of PLT32 reloc required for the instruction. */
5875 /* arm_parse_reloc() works on input_line_pointer.
5876 We actually want to parse the operands to the branch instruction
5877 passed in 'str'. Save the input pointer and restore it later. */
5878 save_in
= input_line_pointer
;
5879 input_line_pointer
= str
;
5881 if (inst
.reloc
.exp
.X_op
== O_symbol
5883 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5885 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5886 inst
.reloc
.pc_rel
= 0;
5887 /* Modify str to point to after parsed operands, otherwise
5888 end_of_line() will complain about the (PLT) left in str. */
5889 str
= input_line_pointer
;
5893 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5894 inst
.reloc
.pc_rel
= 1;
5897 input_line_pointer
= save_in
;
5900 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
5901 inst
.reloc
.pc_rel
= 1;
5902 #endif /* OBJ_ELF */
5907 /* ARM V5 branch-link-exchange instruction (argument parse)
5908 BLX <target_addr> ie BLX(1)
5909 BLX{<condition>} <Rm> ie BLX(2)
5910 Unfortunately, there are two different opcodes for this mnemonic.
5911 So, the insns[].value is not used, and the code here zaps values
5912 into inst.instruction.
5913 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
5922 skip_whitespace (mystr
);
5923 rm
= reg_required_here (& mystr
, 0);
5925 /* The above may set inst.error. Ignore his opinion. */
5930 /* Arg is a register.
5931 Use the condition code our caller put in inst.instruction.
5932 Pass ourselves off as a BX with a funny opcode. */
5933 inst
.instruction
|= 0x012fff30;
5938 /* This must be is BLX <target address>, no condition allowed. */
5939 if (inst
.instruction
!= COND_ALWAYS
)
5941 inst
.error
= BAD_COND
;
5945 inst
.instruction
= 0xfafffffe;
5947 /* Process like a B/BL, but with a different reloc.
5948 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
5953 /* ARM V5 Thumb BLX (argument parse)
5954 BLX <target_addr> which is BLX(1)
5955 BLX <Rm> which is BLX(2)
5956 Unfortunately, there are two different opcodes for this mnemonic.
5957 So, the tinsns[].value is not used, and the code here zaps values
5958 into inst.instruction. */
5967 skip_whitespace (mystr
);
5968 inst
.instruction
= 0x4780;
5970 /* Note that this call is to the ARM register recognizer. BLX(2)
5971 uses the ARM register space, not the Thumb one, so a call to
5972 thumb_reg() would be wrong. */
5973 rm
= reg_required_here (& mystr
, 3);
5978 /* It's BLX(2). The .instruction was zapped with rm & is final. */
5983 /* No ARM register. This must be BLX(1). Change the .instruction. */
5984 inst
.instruction
= 0xf7ffeffe;
5987 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
5990 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
5991 inst
.reloc
.pc_rel
= 1;
5994 end_of_line (mystr
);
5997 /* ARM V5 breakpoint instruction (argument parse)
5998 BKPT <16 bit unsigned immediate>
5999 Instruction is not conditional.
6000 The bit pattern given in insns[] has the COND_ALWAYS condition,
6001 and it is an error if the caller tried to override that. */
6008 unsigned long number
;
6010 skip_whitespace (str
);
6012 /* Allow optional leading '#'. */
6013 if (is_immediate_prefix (* str
))
6016 memset (& expr
, '\0', sizeof (expr
));
6018 if (my_get_expression (& expr
, & str
)
6019 || (expr
.X_op
!= O_constant
6020 /* As a convenience we allow 'bkpt' without an operand. */
6021 && expr
.X_op
!= O_absent
))
6023 inst
.error
= _("bad expression");
6027 number
= expr
.X_add_number
;
6029 /* Check it fits a 16 bit unsigned. */
6030 if (number
!= (number
& 0xffff))
6032 inst
.error
= _("immediate value out of range");
6036 /* Top 12 of 16 bits to bits 19:8. */
6037 inst
.instruction
|= (number
& 0xfff0) << 4;
6039 /* Bottom 4 of 16 bits to bits 3:0. */
6040 inst
.instruction
|= number
& 0xf;
6045 /* THUMB CPS instruction (argument parse). */
6051 do_cps_flags (&str
, /*thumb_p=*/1);
6055 /* THUMB CPY instruction (argument parse). */
6061 thumb_mov_compare (str
, THUMB_CPY
);
6064 /* THUMB SETEND instruction (argument parse). */
6070 if (do_endian_specifier (str
))
6071 inst
.instruction
|= 0x8;
6074 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
6076 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
6078 static unsigned long
6079 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
6081 enum iwmmxt_insn_type insn_type
;
6085 const char * inst_error
;
6087 unsigned long number
;
6089 inst_error
= inst
.error
;
6091 inst
.error
= BAD_ARGS
;
6092 skip_whitespace (str
);
6097 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6102 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
6107 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6108 || skip_past_comma (&str
) == FAIL
6109 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6114 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6115 || skip_past_comma (&str
) == FAIL
6116 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6117 || skip_past_comma (&str
) == FAIL
6118 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6123 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6124 || skip_past_comma (&str
) == FAIL
6125 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6126 || skip_past_comma (&str
) == FAIL
6127 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
6132 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6133 || skip_past_comma (&str
) == FAIL
6134 || reg_required_here (&str
, 12) == FAIL
))
6139 if ((reg_required_here (&str
, 12) == FAIL
6140 || skip_past_comma (&str
) == FAIL
6141 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
6146 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
6147 || skip_past_comma (&str
) == FAIL
6148 || reg_required_here (&str
, 0) == FAIL
6149 || skip_past_comma (&str
) == FAIL
6150 || reg_required_here (&str
, 12) == FAIL
))
6155 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6156 || skip_past_comma (&str
) == FAIL
6157 || reg_required_here (&str
, 12) == FAIL
6158 || skip_past_comma (&str
) == FAIL
6159 || reg_required_here (&str
, 16) == FAIL
))
6164 if ((reg_required_here (&str
, 12) == FAIL
6165 || skip_past_comma (&str
) == FAIL
6166 || reg_required_here (&str
, 16) == FAIL
6167 || skip_past_comma (&str
) == FAIL
6168 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
6173 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
6174 || skip_past_comma (&str
) == FAIL
6175 || reg_required_here (&str
, 12) == FAIL
))
6180 if ((reg_required_here (&str
, 12) == FAIL
6181 || skip_past_comma (&str
) == FAIL
6182 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
6187 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6188 || skip_past_comma (&str
) == FAIL
6189 || reg_required_here (&str
, 12) == FAIL
6190 || skip_past_comma (&str
) == FAIL
))
6195 if ((reg_required_here (&str
, 12) == FAIL
6196 || skip_past_comma (&str
) == FAIL
))
6201 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6202 || skip_past_comma (&str
) == FAIL
6203 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6204 || skip_past_comma (&str
) == FAIL
6205 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
6206 || skip_past_comma (&str
) == FAIL
))
6211 if ((reg_required_here (&str
, 12) == FAIL
6212 || skip_past_comma (&str
) == FAIL
6213 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6214 || skip_past_comma (&str
) == FAIL
))
6219 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
6220 || skip_past_comma (&str
) == FAIL
6221 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
6222 || skip_past_comma (&str
) == FAIL
))
6227 if (immediate_size
== 0)
6230 inst
.error
= inst_error
;
6235 skip_whitespace (str
);
6237 /* Allow optional leading '#'. */
6238 if (is_immediate_prefix (* str
))
6241 memset (& expr
, '\0', sizeof (expr
));
6243 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
6245 inst
.error
= _("bad or missing expression");
6249 number
= expr
.X_add_number
;
6251 if (number
!= (number
& immediate_size
))
6253 inst
.error
= _("immediate value out of range");
6257 inst
.error
= inst_error
;
6263 do_iwmmxt_byte_addr (str
)
6266 int op
= (inst
.instruction
& 0x300) >> 8;
6269 inst
.instruction
&= ~0x300;
6270 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6272 skip_whitespace (str
);
6274 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6275 || skip_past_comma (& str
) == FAIL
6276 || cp_byte_address_required_here (&str
) == FAIL
)
6279 inst
.error
= BAD_ARGS
;
6284 if (wc_register (reg
))
6286 as_bad (_("non-word size not supported with control register"));
6287 inst
.instruction
|= 0xf0000100;
6288 inst
.instruction
&= ~0x00400000;
6293 do_iwmmxt_tandc (str
)
6298 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
6300 if (reg
!= REG_PC
&& !inst
.error
)
6301 inst
.error
= _("only r15 allowed here");
6305 do_iwmmxt_tbcst (str
)
6308 check_iwmmxt_insn (str
, check_tbcst
, 0);
6312 do_iwmmxt_textrc (str
)
6315 unsigned long number
;
6317 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
6320 inst
.instruction
|= number
& 0x7;
6324 do_iwmmxt_textrm (str
)
6327 unsigned long number
;
6329 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
6332 inst
.instruction
|= number
& 0x7;
6336 do_iwmmxt_tinsr (str
)
6339 unsigned long number
;
6341 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
6344 inst
.instruction
|= number
& 0x7;
6348 do_iwmmxt_tmcr (str
)
6351 check_iwmmxt_insn (str
, check_tmcr
, 0);
6355 do_iwmmxt_tmcrr (str
)
6358 check_iwmmxt_insn (str
, check_tmcrr
, 0);
6362 do_iwmmxt_tmia (str
)
6365 check_iwmmxt_insn (str
, check_tmia
, 0);
6369 do_iwmmxt_tmovmsk (str
)
6372 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
6376 do_iwmmxt_tmrc (str
)
6379 check_iwmmxt_insn (str
, check_tmrc
, 0);
6383 do_iwmmxt_tmrrc (str
)
6386 check_iwmmxt_insn (str
, check_tmrrc
, 0);
6390 do_iwmmxt_torc (str
)
6393 check_iwmmxt_insn (str
, check_rd
, 0);
6397 do_iwmmxt_waligni (str
)
6400 unsigned long number
;
6402 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
6405 inst
.instruction
|= ((number
& 0x7) << 20);
6409 do_iwmmxt_wmov (str
)
6412 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
6415 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
6419 do_iwmmxt_word_addr (str
)
6422 int op
= (inst
.instruction
& 0x300) >> 8;
6425 inst
.instruction
&= ~0x300;
6426 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
6428 skip_whitespace (str
);
6430 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
6431 || skip_past_comma (& str
) == FAIL
6432 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
6435 inst
.error
= BAD_ARGS
;
6440 if (wc_register (reg
))
6442 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
6443 as_bad (_("conditional execution not supported with control register"));
6445 as_bad (_("non-word size not supported with control register"));
6446 inst
.instruction
|= 0xf0000100;
6447 inst
.instruction
&= ~0x00400000;
6452 do_iwmmxt_wrwr (str
)
6455 check_iwmmxt_insn (str
, check_wrwr
, 0);
6459 do_iwmmxt_wrwrwcg (str
)
6462 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
6466 do_iwmmxt_wrwrwr (str
)
6469 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
6473 do_iwmmxt_wshufh (str
)
6476 unsigned long number
;
6478 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
6481 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
6485 do_iwmmxt_wzero (str
)
6488 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
6491 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
6494 /* Xscale multiply-accumulate (argument parse)
6497 MIAxycc acc0,Rm,Rs. */
6506 if (accum0_required_here (& str
) == FAIL
)
6507 inst
.error
= ERR_NO_ACCUM
;
6509 else if (skip_past_comma (& str
) == FAIL
6510 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
6511 inst
.error
= BAD_ARGS
;
6513 else if (skip_past_comma (& str
) == FAIL
6514 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
6515 inst
.error
= BAD_ARGS
;
6517 /* inst.instruction has now been zapped with both rm and rs. */
6518 else if (rm
== REG_PC
|| rs
== REG_PC
)
6519 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
6525 /* Xscale move-accumulator-register (argument parse)
6527 MARcc acc0,RdLo,RdHi. */
6535 if (accum0_required_here (& str
) == FAIL
)
6536 inst
.error
= ERR_NO_ACCUM
;
6538 else if (skip_past_comma (& str
) == FAIL
6539 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6540 inst
.error
= BAD_ARGS
;
6542 else if (skip_past_comma (& str
) == FAIL
6543 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6544 inst
.error
= BAD_ARGS
;
6546 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6547 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6548 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6554 /* Xscale move-register-accumulator (argument parse)
6556 MRAcc RdLo,RdHi,acc0. */
6565 skip_whitespace (str
);
6567 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
6568 inst
.error
= BAD_ARGS
;
6570 else if (skip_past_comma (& str
) == FAIL
6571 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
6572 inst
.error
= BAD_ARGS
;
6574 else if (skip_past_comma (& str
) == FAIL
6575 || accum0_required_here (& str
) == FAIL
)
6576 inst
.error
= ERR_NO_ACCUM
;
6578 /* inst.instruction has now been zapped with both rdlo and rdhi. */
6579 else if (rdlo
== rdhi
)
6580 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
6582 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
6583 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
6588 /* ARMv5TE: Preload-Cache
6592 Syntactically, like LDR with B=1, W=0, L=1. */
6600 skip_whitespace (str
);
6604 inst
.error
= _("'[' expected after PLD mnemonic");
6609 skip_whitespace (str
);
6611 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
6614 skip_whitespace (str
);
6620 skip_whitespace (str
);
6622 /* Post-indexed addressing is not allowed with PLD. */
6623 if (skip_past_comma (&str
) == SUCCESS
)
6626 = _("post-indexed expression used in preload instruction");
6629 else if (*str
== '!') /* [Rn]! */
6631 inst
.error
= _("writeback used in preload instruction");
6635 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
6637 else /* [Rn, ...] */
6639 if (skip_past_comma (& str
) == FAIL
)
6641 inst
.error
= _("pre-indexed expression expected");
6645 if (ldst_extend (&str
) == FAIL
)
6648 skip_whitespace (str
);
6652 inst
.error
= _("missing ]");
6657 skip_whitespace (str
);
6659 if (* str
== '!') /* [Rn]! */
6661 inst
.error
= _("writeback used in preload instruction");
6665 inst
.instruction
|= PRE_INDEX
;
6671 /* ARMv5TE load-consecutive (argument parse)
6684 skip_whitespace (str
);
6686 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
6688 inst
.error
= BAD_ARGS
;
6692 if (skip_past_comma (& str
) == FAIL
6693 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
6696 inst
.error
= BAD_ARGS
;
6700 /* inst.instruction has now been zapped with Rd and the addressing mode. */
6701 if (rd
& 1) /* Unpredictable result if Rd is odd. */
6703 inst
.error
= _("destination register must be even");
6709 inst
.error
= _("r14 not allowed here");
6713 if (((rd
== rn
) || (rd
+ 1 == rn
))
6714 && ((inst
.instruction
& WRITE_BACK
)
6715 || (!(inst
.instruction
& PRE_INDEX
))))
6716 as_warn (_("pre/post-indexing used when modified address register is destination"));
6718 /* For an index-register load, the index register must not overlap the
6719 destination (even if not write-back). */
6720 if ((inst
.instruction
& V4_STR_BIT
) == 0
6721 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
6723 int rm
= inst
.instruction
& 0x0000000f;
6725 if (rm
== rd
|| (rm
== rd
+ 1))
6726 as_warn (_("ldrd destination registers must not overlap index register"));
6732 /* Returns the index into fp_values of a floating point number,
6733 or -1 if not in the table. */
6736 my_get_float_expression (str
)
6739 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
6745 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
6747 /* Look for a raw floating point number. */
6748 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
6749 && is_end_of_line
[(unsigned char) *save_in
])
6751 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6753 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6755 if (words
[j
] != fp_values
[i
][j
])
6759 if (j
== MAX_LITTLENUMS
)
6767 /* Try and parse a more complex expression, this will probably fail
6768 unless the code uses a floating point prefix (eg "0f"). */
6769 save_in
= input_line_pointer
;
6770 input_line_pointer
= *str
;
6771 if (expression (&exp
) == absolute_section
6772 && exp
.X_op
== O_big
6773 && exp
.X_add_number
< 0)
6775 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6777 if (gen_to_words (words
, 5, (long) 15) == 0)
6779 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
6781 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
6783 if (words
[j
] != fp_values
[i
][j
])
6787 if (j
== MAX_LITTLENUMS
)
6789 *str
= input_line_pointer
;
6790 input_line_pointer
= save_in
;
6797 *str
= input_line_pointer
;
6798 input_line_pointer
= save_in
;
6802 /* Return TRUE if anything in the expression is a bignum. */
6805 walk_no_bignums (sp
)
6808 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
6811 if (symbol_get_value_expression (sp
)->X_add_symbol
)
6813 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
6814 || (symbol_get_value_expression (sp
)->X_op_symbol
6815 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
6821 static int in_my_get_expression
= 0;
6824 my_get_expression (ep
, str
)
6831 save_in
= input_line_pointer
;
6832 input_line_pointer
= *str
;
6833 in_my_get_expression
= 1;
6834 seg
= expression (ep
);
6835 in_my_get_expression
= 0;
6837 if (ep
->X_op
== O_illegal
)
6839 /* We found a bad expression in md_operand(). */
6840 *str
= input_line_pointer
;
6841 input_line_pointer
= save_in
;
6846 if (seg
!= absolute_section
6847 && seg
!= text_section
6848 && seg
!= data_section
6849 && seg
!= bss_section
6850 && seg
!= undefined_section
)
6852 inst
.error
= _("bad_segment");
6853 *str
= input_line_pointer
;
6854 input_line_pointer
= save_in
;
6859 /* Get rid of any bignums now, so that we don't generate an error for which
6860 we can't establish a line number later on. Big numbers are never valid
6861 in instructions, which is where this routine is always called. */
6862 if (ep
->X_op
== O_big
6863 || (ep
->X_add_symbol
6864 && (walk_no_bignums (ep
->X_add_symbol
)
6866 && walk_no_bignums (ep
->X_op_symbol
)))))
6868 inst
.error
= _("invalid constant");
6869 *str
= input_line_pointer
;
6870 input_line_pointer
= save_in
;
6874 *str
= input_line_pointer
;
6875 input_line_pointer
= save_in
;
6879 /* We handle all bad expressions here, so that we can report the faulty
6880 instruction in the error message. */
6885 if (in_my_get_expression
)
6887 expr
->X_op
= O_illegal
;
6888 if (inst
.error
== NULL
)
6889 inst
.error
= _("bad expression");
6893 /* KIND indicates what kind of shifts are accepted. */
6896 decode_shift (str
, kind
)
6900 const struct asm_shift_name
* shift
;
6904 skip_whitespace (* str
);
6906 for (p
= * str
; ISALPHA (* p
); p
++)
6911 inst
.error
= _("shift expression expected");
6917 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
6922 inst
.error
= _("shift expression expected");
6926 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
6928 if (kind
== SHIFT_LSL_OR_ASR_IMMEDIATE
6929 && shift
->properties
->index
!= SHIFT_LSL
6930 && shift
->properties
->index
!= SHIFT_ASR
)
6932 inst
.error
= _("'LSL' or 'ASR' required");
6935 else if (kind
== SHIFT_LSL_IMMEDIATE
6936 && shift
->properties
->index
!= SHIFT_LSL
)
6938 inst
.error
= _("'LSL' required");
6941 else if (kind
== SHIFT_ASR_IMMEDIATE
6942 && shift
->properties
->index
!= SHIFT_ASR
)
6944 inst
.error
= _("'ASR' required");
6948 if (shift
->properties
->index
== SHIFT_RRX
)
6951 inst
.instruction
|= shift
->properties
->bit_field
;
6955 skip_whitespace (p
);
6957 if (kind
== NO_SHIFT_RESTRICT
&& reg_required_here (& p
, 8) != FAIL
)
6959 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
6963 else if (! is_immediate_prefix (* p
))
6965 inst
.error
= (NO_SHIFT_RESTRICT
6966 ? _("shift requires register or #expression")
6967 : _("shift requires #expression"));
6975 if (my_get_expression (& inst
.reloc
.exp
, & p
))
6978 /* Validate some simple #expressions. */
6979 if (inst
.reloc
.exp
.X_op
== O_constant
)
6981 unsigned num
= inst
.reloc
.exp
.X_add_number
;
6983 /* Reject operations greater than 32. */
6985 /* Reject a shift of 0 unless the mode allows it. */
6986 || (num
== 0 && shift
->properties
->allows_0
== 0)
6987 /* Reject a shift of 32 unless the mode allows it. */
6988 || (num
== 32 && shift
->properties
->allows_32
== 0)
6991 /* As a special case we allow a shift of zero for
6992 modes that do not support it to be recoded as an
6993 logical shift left of zero (ie nothing). We warn
6994 about this though. */
6997 as_warn (_("shift of 0 ignored."));
6998 shift
= & shift_names
[0];
6999 assert (shift
->properties
->index
== SHIFT_LSL
);
7003 inst
.error
= _("invalid immediate shift");
7008 /* Shifts of 32 are encoded as 0, for those shifts that
7013 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
7017 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
7018 inst
.reloc
.pc_rel
= 0;
7019 inst
.instruction
|= shift
->properties
->bit_field
;
7026 /* Do those data_ops which can take a negative immediate constant
7027 by altering the instruction. A bit of a hack really.
7031 by inverting the second operand, and
7034 by negating the second operand. */
7037 negate_data_op (instruction
, value
)
7038 unsigned long * instruction
;
7039 unsigned long value
;
7042 unsigned long negated
, inverted
;
7044 negated
= validate_immediate (-value
);
7045 inverted
= validate_immediate (~value
);
7047 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
7050 /* First negates. */
7051 case OPCODE_SUB
: /* ADD <-> SUB */
7052 new_inst
= OPCODE_ADD
;
7057 new_inst
= OPCODE_SUB
;
7061 case OPCODE_CMP
: /* CMP <-> CMN */
7062 new_inst
= OPCODE_CMN
;
7067 new_inst
= OPCODE_CMP
;
7071 /* Now Inverted ops. */
7072 case OPCODE_MOV
: /* MOV <-> MVN */
7073 new_inst
= OPCODE_MVN
;
7078 new_inst
= OPCODE_MOV
;
7082 case OPCODE_AND
: /* AND <-> BIC */
7083 new_inst
= OPCODE_BIC
;
7088 new_inst
= OPCODE_AND
;
7092 case OPCODE_ADC
: /* ADC <-> SBC */
7093 new_inst
= OPCODE_SBC
;
7098 new_inst
= OPCODE_ADC
;
7102 /* We cannot do anything. */
7107 if (value
== (unsigned) FAIL
)
7110 *instruction
&= OPCODE_MASK
;
7111 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
7122 skip_whitespace (* str
);
7124 if (reg_required_here (str
, 0) != FAIL
)
7126 if (skip_past_comma (str
) == SUCCESS
)
7127 /* Shift operation on register. */
7128 return decode_shift (str
, NO_SHIFT_RESTRICT
);
7134 /* Immediate expression. */
7135 if (is_immediate_prefix (**str
))
7140 if (my_get_expression (&inst
.reloc
.exp
, str
))
7143 if (inst
.reloc
.exp
.X_add_symbol
)
7145 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7146 inst
.reloc
.pc_rel
= 0;
7150 if (skip_past_comma (str
) == SUCCESS
)
7152 /* #x, y -- ie explicit rotation by Y. */
7153 if (my_get_expression (&expr
, str
))
7156 if (expr
.X_op
!= O_constant
)
7158 inst
.error
= _("constant expression expected");
7162 /* Rotate must be a multiple of 2. */
7163 if (((unsigned) expr
.X_add_number
) > 30
7164 || (expr
.X_add_number
& 1) != 0
7165 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
7167 inst
.error
= _("invalid constant");
7170 inst
.instruction
|= INST_IMMEDIATE
;
7171 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7172 inst
.instruction
|= expr
.X_add_number
<< 7;
7176 /* Implicit rotation, select a suitable one. */
7177 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7181 /* Can't be done. Perhaps the code reads something like
7182 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
7183 if ((value
= negate_data_op (&inst
.instruction
,
7184 inst
.reloc
.exp
.X_add_number
))
7187 inst
.error
= _("invalid constant");
7192 inst
.instruction
|= value
;
7195 inst
.instruction
|= INST_IMMEDIATE
;
7200 inst
.error
= _("register or shift expression expected");
7209 skip_whitespace (* str
);
7211 if (fp_reg_required_here (str
, 0) != FAIL
)
7215 /* Immediate expression. */
7216 if (*((*str
)++) == '#')
7222 skip_whitespace (* str
);
7224 /* First try and match exact strings, this is to guarantee
7225 that some formats will work even for cross assembly. */
7227 for (i
= 0; fp_const
[i
]; i
++)
7229 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
7233 *str
+= strlen (fp_const
[i
]);
7234 if (is_end_of_line
[(unsigned char) **str
])
7236 inst
.instruction
|= i
+ 8;
7243 /* Just because we didn't get a match doesn't mean that the
7244 constant isn't valid, just that it is in a format that we
7245 don't automatically recognize. Try parsing it with
7246 the standard expression routines. */
7247 if ((i
= my_get_float_expression (str
)) >= 0)
7249 inst
.instruction
|= i
+ 8;
7253 inst
.error
= _("invalid floating point immediate expression");
7257 _("floating point register or immediate expression expected");
7266 skip_whitespace (str
);
7268 if (reg_required_here (&str
, 12) == FAIL
7269 || skip_past_comma (&str
) == FAIL
7270 || reg_required_here (&str
, 16) == FAIL
7271 || skip_past_comma (&str
) == FAIL
7272 || data_op2 (&str
) == FAIL
)
7275 inst
.error
= BAD_ARGS
;
7286 /* This is a pseudo-op of the form "adr rd, label" to be converted
7287 into a relative address of the form "add rd, pc, #label-.-8". */
7288 skip_whitespace (str
);
7290 if (reg_required_here (&str
, 12) == FAIL
7291 || skip_past_comma (&str
) == FAIL
7292 || my_get_expression (&inst
.reloc
.exp
, &str
))
7295 inst
.error
= BAD_ARGS
;
7299 /* Frag hacking will turn this into a sub instruction if the offset turns
7300 out to be negative. */
7301 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
7302 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
7303 inst
.reloc
.pc_rel
= 1;
7312 /* This is a pseudo-op of the form "adrl rd, label" to be converted
7313 into a relative address of the form:
7314 add rd, pc, #low(label-.-8)"
7315 add rd, rd, #high(label-.-8)" */
7317 skip_whitespace (str
);
7319 if (reg_required_here (&str
, 12) == FAIL
7320 || skip_past_comma (&str
) == FAIL
7321 || my_get_expression (&inst
.reloc
.exp
, &str
))
7324 inst
.error
= BAD_ARGS
;
7330 /* Frag hacking will turn this into a sub instruction if the offset turns
7331 out to be negative. */
7332 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
7333 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
7334 inst
.reloc
.pc_rel
= 1;
7335 inst
.size
= INSN_SIZE
* 2;
7342 skip_whitespace (str
);
7344 if (reg_required_here (&str
, 16) == FAIL
)
7347 inst
.error
= BAD_ARGS
;
7351 if (skip_past_comma (&str
) == FAIL
7352 || data_op2 (&str
) == FAIL
)
7355 inst
.error
= BAD_ARGS
;
7366 skip_whitespace (str
);
7368 if (reg_required_here (&str
, 12) == FAIL
)
7371 inst
.error
= BAD_ARGS
;
7375 if (skip_past_comma (&str
) == FAIL
7376 || data_op2 (&str
) == FAIL
)
7379 inst
.error
= BAD_ARGS
;
7397 if (my_get_expression (& inst
.reloc
.exp
, str
))
7400 if (inst
.reloc
.exp
.X_op
== O_constant
)
7402 int value
= inst
.reloc
.exp
.X_add_number
;
7404 if (value
< -4095 || value
> 4095)
7406 inst
.error
= _("address offset too large");
7416 inst
.instruction
|= add
| value
;
7420 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7421 inst
.reloc
.pc_rel
= 0;
7434 if (reg_required_here (str
, 0) == FAIL
)
7437 inst
.instruction
|= add
| OFFSET_REG
;
7438 if (skip_past_comma (str
) == SUCCESS
)
7439 return decode_shift (str
, SHIFT_IMMEDIATE
);
7453 skip_whitespace (str
);
7455 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
7458 inst
.error
= BAD_ARGS
;
7462 if (skip_past_comma (&str
) == FAIL
)
7464 inst
.error
= _("address expected");
7474 skip_whitespace (str
);
7476 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7479 /* Conflicts can occur on stores as well as loads. */
7480 conflict_reg
= (conflict_reg
== reg
);
7482 skip_whitespace (str
);
7488 if (skip_past_comma (&str
) == SUCCESS
)
7490 /* [Rn],... (post inc) */
7491 if (ldst_extend (&str
) == FAIL
)
7494 as_warn (_("%s register same as write-back base"),
7495 ((inst
.instruction
& LOAD_BIT
)
7496 ? _("destination") : _("source")));
7501 skip_whitespace (str
);
7506 as_warn (_("%s register same as write-back base"),
7507 ((inst
.instruction
& LOAD_BIT
)
7508 ? _("destination") : _("source")));
7510 inst
.instruction
|= WRITE_BACK
;
7513 inst
.instruction
|= INDEX_UP
;
7520 if (skip_past_comma (&str
) == FAIL
)
7522 inst
.error
= _("pre-indexed expression expected");
7527 if (ldst_extend (&str
) == FAIL
)
7530 skip_whitespace (str
);
7534 inst
.error
= _("missing ]");
7538 skip_whitespace (str
);
7543 as_warn (_("%s register same as write-back base"),
7544 ((inst
.instruction
& LOAD_BIT
)
7545 ? _("destination") : _("source")));
7547 inst
.instruction
|= WRITE_BACK
;
7551 else if (*str
== '=')
7553 if ((inst
.instruction
& LOAD_BIT
) == 0)
7555 inst
.error
= _("invalid pseudo operation");
7559 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7562 skip_whitespace (str
);
7564 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7567 if (inst
.reloc
.exp
.X_op
!= O_constant
7568 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7570 inst
.error
= _("constant expression expected");
7574 if (inst
.reloc
.exp
.X_op
== O_constant
)
7576 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7580 /* This can be done with a mov instruction. */
7581 inst
.instruction
&= LITERAL_MASK
;
7582 inst
.instruction
|= (INST_IMMEDIATE
7583 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
7584 inst
.instruction
|= value
& 0xfff;
7589 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
7593 /* This can be done with a mvn instruction. */
7594 inst
.instruction
&= LITERAL_MASK
;
7595 inst
.instruction
|= (INST_IMMEDIATE
7596 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
7597 inst
.instruction
|= value
& 0xfff;
7603 /* Insert into literal pool. */
7604 if (add_to_lit_pool () == FAIL
)
7607 inst
.error
= _("literal pool insertion failed");
7611 /* Change the instruction exp to point to the pool. */
7612 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
7613 inst
.reloc
.pc_rel
= 1;
7614 inst
.instruction
|= (REG_PC
<< 16);
7619 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7622 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
7624 /* PC rel adjust. */
7625 inst
.reloc
.exp
.X_add_number
-= 8;
7627 inst
.reloc
.pc_rel
= 1;
7628 inst
.instruction
|= (REG_PC
<< 16);
7632 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7642 skip_whitespace (str
);
7644 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7647 inst
.error
= BAD_ARGS
;
7651 if (skip_past_comma (& str
) == FAIL
)
7653 inst
.error
= _("address expected");
7663 skip_whitespace (str
);
7665 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7668 /* ldrt/strt always use post-indexed addressing, so if the base is
7669 the same as Rd, we warn. */
7670 if (conflict_reg
== reg
)
7671 as_warn (_("%s register same as write-back base"),
7672 ((inst
.instruction
& LOAD_BIT
)
7673 ? _("destination") : _("source")));
7675 skip_whitespace (str
);
7681 if (skip_past_comma (&str
) == SUCCESS
)
7683 /* [Rn],... (post inc) */
7684 if (ldst_extend (&str
) == FAIL
)
7690 skip_whitespace (str
);
7692 /* Skip a write-back '!'. */
7696 inst
.instruction
|= INDEX_UP
;
7701 inst
.error
= _("post-indexed expression expected");
7707 inst
.error
= _("post-indexed expression expected");
7715 ldst_extend_v4 (str
)
7725 if (my_get_expression (& inst
.reloc
.exp
, str
))
7728 if (inst
.reloc
.exp
.X_op
== O_constant
)
7730 int value
= inst
.reloc
.exp
.X_add_number
;
7732 if (value
< -255 || value
> 255)
7734 inst
.error
= _("address offset too large");
7744 /* Halfword and signextension instructions have the
7745 immediate value split across bits 11..8 and bits 3..0. */
7746 inst
.instruction
|= (add
| HWOFFSET_IMM
7747 | ((value
>> 4) << 8) | (value
& 0xF));
7751 inst
.instruction
|= HWOFFSET_IMM
;
7752 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7753 inst
.reloc
.pc_rel
= 0;
7766 if (reg_required_here (str
, 0) == FAIL
)
7769 inst
.instruction
|= add
;
7774 /* Halfword and signed-byte load/store operations. */
7783 skip_whitespace (str
);
7785 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
7788 inst
.error
= BAD_ARGS
;
7792 if (skip_past_comma (& str
) == FAIL
)
7794 inst
.error
= _("address expected");
7804 skip_whitespace (str
);
7806 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7809 /* Conflicts can occur on stores as well as loads. */
7810 conflict_reg
= (conflict_reg
== reg
);
7812 skip_whitespace (str
);
7818 if (skip_past_comma (&str
) == SUCCESS
)
7820 /* [Rn],... (post inc) */
7821 if (ldst_extend_v4 (&str
) == FAIL
)
7824 as_warn (_("%s register same as write-back base"),
7825 ((inst
.instruction
& LOAD_BIT
)
7826 ? _("destination") : _("source")));
7831 inst
.instruction
|= HWOFFSET_IMM
;
7833 skip_whitespace (str
);
7838 as_warn (_("%s register same as write-back base"),
7839 ((inst
.instruction
& LOAD_BIT
)
7840 ? _("destination") : _("source")));
7842 inst
.instruction
|= WRITE_BACK
;
7845 inst
.instruction
|= INDEX_UP
;
7852 if (skip_past_comma (&str
) == FAIL
)
7854 inst
.error
= _("pre-indexed expression expected");
7859 if (ldst_extend_v4 (&str
) == FAIL
)
7862 skip_whitespace (str
);
7866 inst
.error
= _("missing ]");
7870 skip_whitespace (str
);
7875 as_warn (_("%s register same as write-back base"),
7876 ((inst
.instruction
& LOAD_BIT
)
7877 ? _("destination") : _("source")));
7879 inst
.instruction
|= WRITE_BACK
;
7883 else if (*str
== '=')
7885 if ((inst
.instruction
& LOAD_BIT
) == 0)
7887 inst
.error
= _("invalid pseudo operation");
7891 /* XXX Does this work correctly for half-word/byte ops? */
7892 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7895 skip_whitespace (str
);
7897 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7900 if (inst
.reloc
.exp
.X_op
!= O_constant
7901 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7903 inst
.error
= _("constant expression expected");
7907 if (inst
.reloc
.exp
.X_op
== O_constant
)
7909 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
7913 /* This can be done with a mov instruction. */
7914 inst
.instruction
&= LITERAL_MASK
;
7915 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
7916 inst
.instruction
|= value
& 0xfff;
7921 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
7925 /* This can be done with a mvn instruction. */
7926 inst
.instruction
&= LITERAL_MASK
;
7927 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
7928 inst
.instruction
|= value
& 0xfff;
7934 /* Insert into literal pool. */
7935 if (add_to_lit_pool () == FAIL
)
7938 inst
.error
= _("literal pool insertion failed");
7942 /* Change the instruction exp to point to the pool. */
7943 inst
.instruction
|= HWOFFSET_IMM
;
7944 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
7945 inst
.reloc
.pc_rel
= 1;
7946 inst
.instruction
|= (REG_PC
<< 16);
7951 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7954 inst
.instruction
|= HWOFFSET_IMM
;
7955 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
7957 /* PC rel adjust. */
7958 inst
.reloc
.exp
.X_add_number
-= 8;
7960 inst
.reloc
.pc_rel
= 1;
7961 inst
.instruction
|= (REG_PC
<< 16);
7965 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
7973 char * str
= * strp
;
7977 /* We come back here if we get ranges concatenated by '+' or '|'. */
7992 skip_whitespace (str
);
7994 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
8003 inst
.error
= _("bad range in register list");
8007 for (i
= cur_reg
+ 1; i
< reg
; i
++)
8009 if (range
& (1 << i
))
8011 (_("Warning: duplicated register (r%d) in register list"),
8019 if (range
& (1 << reg
))
8020 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8022 else if (reg
<= cur_reg
)
8023 as_tsktsk (_("Warning: register range not in ascending order"));
8028 while (skip_past_comma (&str
) != FAIL
8029 || (in_range
= 1, *str
++ == '-'));
8031 skip_whitespace (str
);
8035 inst
.error
= _("missing `}'");
8043 if (my_get_expression (&expr
, &str
))
8046 if (expr
.X_op
== O_constant
)
8048 if (expr
.X_add_number
8049 != (expr
.X_add_number
& 0x0000ffff))
8051 inst
.error
= _("invalid register mask");
8055 if ((range
& expr
.X_add_number
) != 0)
8057 int regno
= range
& expr
.X_add_number
;
8060 regno
= (1 << regno
) - 1;
8062 (_("Warning: duplicated register (r%d) in register list"),
8066 range
|= expr
.X_add_number
;
8070 if (inst
.reloc
.type
!= 0)
8072 inst
.error
= _("expression too complex");
8076 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
8077 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
8078 inst
.reloc
.pc_rel
= 0;
8082 skip_whitespace (str
);
8084 if (*str
== '|' || *str
== '+')
8090 while (another_range
);
8103 skip_whitespace (str
);
8105 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
8108 if (base_reg
== REG_PC
)
8110 inst
.error
= _("r15 not allowed as base register");
8114 skip_whitespace (str
);
8118 inst
.instruction
|= WRITE_BACK
;
8122 if (skip_past_comma (&str
) == FAIL
8123 || (range
= reg_list (&str
)) == FAIL
)
8126 inst
.error
= BAD_ARGS
;
8133 inst
.instruction
|= LDM_TYPE_2_OR_3
;
8136 if (inst
.instruction
& WRITE_BACK
)
8138 /* Check for unpredictable uses of writeback. */
8139 if (inst
.instruction
& LOAD_BIT
)
8141 /* Not allowed in LDM type 2. */
8142 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
8143 && ((range
& (1 << REG_PC
)) == 0))
8144 as_warn (_("writeback of base register is UNPREDICTABLE"));
8145 /* Only allowed if base reg not in list for other types. */
8146 else if (range
& (1 << base_reg
))
8147 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8151 /* Not allowed for type 2. */
8152 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
8153 as_warn (_("writeback of base register is UNPREDICTABLE"));
8154 /* Only allowed if base reg not in list, or first in list. */
8155 else if ((range
& (1 << base_reg
))
8156 && (range
& ((1 << base_reg
) - 1)))
8157 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8161 inst
.instruction
|= range
;
8169 skip_whitespace (str
);
8171 /* Allow optional leading '#'. */
8172 if (is_immediate_prefix (*str
))
8175 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8178 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8179 inst
.reloc
.pc_rel
= 0;
8189 skip_whitespace (str
);
8191 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
8196 inst
.error
= _("r15 not allowed in swap");
8200 if (skip_past_comma (&str
) == FAIL
8201 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
8204 inst
.error
= BAD_ARGS
;
8210 inst
.error
= _("r15 not allowed in swap");
8214 if (skip_past_comma (&str
) == FAIL
8217 inst
.error
= BAD_ARGS
;
8221 skip_whitespace (str
);
8223 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8228 inst
.error
= BAD_PC
;
8232 skip_whitespace (str
);
8236 inst
.error
= _("missing ]");
8247 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8254 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8255 required for the instruction. */
8257 /* arm_parse_reloc () works on input_line_pointer.
8258 We actually want to parse the operands to the branch instruction
8259 passed in 'str'. Save the input pointer and restore it later. */
8260 save_in
= input_line_pointer
;
8261 input_line_pointer
= str
;
8262 if (inst
.reloc
.exp
.X_op
== O_symbol
8264 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
8266 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
8267 inst
.reloc
.pc_rel
= 0;
8268 /* Modify str to point to after parsed operands, otherwise
8269 end_of_line() will complain about the (PLT) left in str. */
8270 str
= input_line_pointer
;
8274 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8275 inst
.reloc
.pc_rel
= 1;
8277 input_line_pointer
= save_in
;
8280 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
8281 inst
.reloc
.pc_rel
= 1;
8282 #endif /* OBJ_ELF */
8293 skip_whitespace (str
);
8295 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
8297 inst
.error
= BAD_ARGS
;
8301 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
8303 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8312 /* Co-processor data operation.
8313 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
8314 skip_whitespace (str
);
8316 if (co_proc_number (&str
) == FAIL
)
8319 inst
.error
= BAD_ARGS
;
8323 if (skip_past_comma (&str
) == FAIL
8324 || cp_opc_expr (&str
, 20,4) == FAIL
)
8327 inst
.error
= BAD_ARGS
;
8331 if (skip_past_comma (&str
) == FAIL
8332 || cp_reg_required_here (&str
, 12) == FAIL
)
8335 inst
.error
= BAD_ARGS
;
8339 if (skip_past_comma (&str
) == FAIL
8340 || cp_reg_required_here (&str
, 16) == FAIL
)
8343 inst
.error
= BAD_ARGS
;
8347 if (skip_past_comma (&str
) == FAIL
8348 || cp_reg_required_here (&str
, 0) == FAIL
)
8351 inst
.error
= BAD_ARGS
;
8355 if (skip_past_comma (&str
) == SUCCESS
)
8357 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8360 inst
.error
= BAD_ARGS
;
8372 /* Co-processor register load/store.
8373 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
8375 skip_whitespace (str
);
8377 if (co_proc_number (&str
) == FAIL
)
8380 inst
.error
= BAD_ARGS
;
8384 if (skip_past_comma (&str
) == FAIL
8385 || cp_reg_required_here (&str
, 12) == FAIL
)
8388 inst
.error
= BAD_ARGS
;
8392 if (skip_past_comma (&str
) == FAIL
8393 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8396 inst
.error
= BAD_ARGS
;
8407 /* Co-processor register transfer.
8408 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
8410 skip_whitespace (str
);
8412 if (co_proc_number (&str
) == FAIL
)
8415 inst
.error
= BAD_ARGS
;
8419 if (skip_past_comma (&str
) == FAIL
8420 || cp_opc_expr (&str
, 21, 3) == FAIL
)
8423 inst
.error
= BAD_ARGS
;
8427 if (skip_past_comma (&str
) == FAIL
8428 || reg_required_here (&str
, 12) == FAIL
)
8431 inst
.error
= BAD_ARGS
;
8435 if (skip_past_comma (&str
) == FAIL
8436 || cp_reg_required_here (&str
, 16) == FAIL
)
8439 inst
.error
= BAD_ARGS
;
8443 if (skip_past_comma (&str
) == FAIL
8444 || cp_reg_required_here (&str
, 0) == FAIL
)
8447 inst
.error
= BAD_ARGS
;
8451 if (skip_past_comma (&str
) == SUCCESS
)
8453 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
8456 inst
.error
= BAD_ARGS
;
8468 /* FP control registers.
8469 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
8471 skip_whitespace (str
);
8473 if (reg_required_here (&str
, 12) == FAIL
)
8476 inst
.error
= BAD_ARGS
;
8487 skip_whitespace (str
);
8489 if (fp_reg_required_here (&str
, 12) == FAIL
)
8492 inst
.error
= BAD_ARGS
;
8496 if (skip_past_comma (&str
) == FAIL
8497 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8500 inst
.error
= BAD_ARGS
;
8513 skip_whitespace (str
);
8515 if (fp_reg_required_here (&str
, 12) == FAIL
)
8518 inst
.error
= BAD_ARGS
;
8522 /* Get Number of registers to transfer. */
8523 if (skip_past_comma (&str
) == FAIL
8524 || my_get_expression (&inst
.reloc
.exp
, &str
))
8527 inst
.error
= _("constant expression expected");
8531 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8533 inst
.error
= _("constant value required for number of registers");
8537 num_regs
= inst
.reloc
.exp
.X_add_number
;
8539 if (num_regs
< 1 || num_regs
> 4)
8541 inst
.error
= _("number of registers must be in the range [1:4]");
8548 inst
.instruction
|= CP_T_X
;
8551 inst
.instruction
|= CP_T_Y
;
8554 inst
.instruction
|= CP_T_Y
| CP_T_X
;
8562 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
8568 /* The instruction specified "ea" or "fd", so we can only accept
8569 [Rn]{!}. The instruction does not really support stacking or
8570 unstacking, so we have to emulate these by setting appropriate
8571 bits and offsets. */
8572 if (skip_past_comma (&str
) == FAIL
8576 inst
.error
= BAD_ARGS
;
8581 skip_whitespace (str
);
8583 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
8586 skip_whitespace (str
);
8590 inst
.error
= BAD_ARGS
;
8602 _("r15 not allowed as base register with write-back");
8609 if (inst
.instruction
& CP_T_Pre
)
8611 /* Pre-decrement. */
8612 offset
= 3 * num_regs
;
8614 inst
.instruction
|= CP_T_WB
;
8618 /* Post-increment. */
8621 inst
.instruction
|= CP_T_WB
;
8622 offset
= 3 * num_regs
;
8626 /* No write-back, so convert this into a standard pre-increment
8627 instruction -- aesthetically more pleasing. */
8628 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
8633 inst
.instruction
|= offset
;
8635 else if (skip_past_comma (&str
) == FAIL
8636 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
8639 inst
.error
= BAD_ARGS
;
8650 skip_whitespace (str
);
8652 if (fp_reg_required_here (&str
, 12) == FAIL
)
8655 inst
.error
= BAD_ARGS
;
8659 if (skip_past_comma (&str
) == FAIL
8660 || fp_reg_required_here (&str
, 16) == FAIL
)
8663 inst
.error
= BAD_ARGS
;
8667 if (skip_past_comma (&str
) == FAIL
8668 || fp_op2 (&str
) == FAIL
)
8671 inst
.error
= BAD_ARGS
;
8679 do_fpa_monadic (str
)
8682 skip_whitespace (str
);
8684 if (fp_reg_required_here (&str
, 12) == FAIL
)
8687 inst
.error
= BAD_ARGS
;
8691 if (skip_past_comma (&str
) == FAIL
8692 || fp_op2 (&str
) == FAIL
)
8695 inst
.error
= BAD_ARGS
;
8706 skip_whitespace (str
);
8708 if (fp_reg_required_here (&str
, 16) == FAIL
)
8711 inst
.error
= BAD_ARGS
;
8715 if (skip_past_comma (&str
) == FAIL
8716 || fp_op2 (&str
) == FAIL
)
8719 inst
.error
= BAD_ARGS
;
8727 do_fpa_from_reg (str
)
8730 skip_whitespace (str
);
8732 if (fp_reg_required_here (&str
, 16) == FAIL
)
8735 inst
.error
= BAD_ARGS
;
8739 if (skip_past_comma (&str
) == FAIL
8740 || reg_required_here (&str
, 12) == FAIL
)
8743 inst
.error
= BAD_ARGS
;
8754 skip_whitespace (str
);
8756 if (reg_required_here (&str
, 12) == FAIL
)
8759 if (skip_past_comma (&str
) == FAIL
8760 || fp_reg_required_here (&str
, 0) == FAIL
)
8763 inst
.error
= BAD_ARGS
;
8771 vfp_sp_reg_required_here (str
, pos
)
8773 enum vfp_sp_reg_pos pos
;
8778 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
8783 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
8787 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
8791 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
8800 /* In the few cases where we might be able to accept something else
8801 this error can be overridden. */
8802 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
8804 /* Restore the start point. */
8810 vfp_dp_reg_required_here (str
, pos
)
8812 enum vfp_dp_reg_pos pos
;
8817 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
8822 inst
.instruction
|= reg
<< 12;
8826 inst
.instruction
|= reg
<< 16;
8830 inst
.instruction
|= reg
<< 0;
8839 /* In the few cases where we might be able to accept something else
8840 this error can be overridden. */
8841 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8843 /* Restore the start point. */
8849 do_vfp_sp_monadic (str
)
8852 skip_whitespace (str
);
8854 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8857 if (skip_past_comma (&str
) == FAIL
8858 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8861 inst
.error
= BAD_ARGS
;
8869 do_vfp_dp_monadic (str
)
8872 skip_whitespace (str
);
8874 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8877 if (skip_past_comma (&str
) == FAIL
8878 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8881 inst
.error
= BAD_ARGS
;
8889 do_vfp_sp_dyadic (str
)
8892 skip_whitespace (str
);
8894 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8897 if (skip_past_comma (&str
) == FAIL
8898 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
8899 || skip_past_comma (&str
) == FAIL
8900 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8903 inst
.error
= BAD_ARGS
;
8911 do_vfp_dp_dyadic (str
)
8914 skip_whitespace (str
);
8916 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8919 if (skip_past_comma (&str
) == FAIL
8920 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
8921 || skip_past_comma (&str
) == FAIL
8922 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8925 inst
.error
= BAD_ARGS
;
8933 do_vfp_reg_from_sp (str
)
8936 skip_whitespace (str
);
8938 if (reg_required_here (&str
, 12) == FAIL
)
8941 if (skip_past_comma (&str
) == FAIL
8942 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8945 inst
.error
= BAD_ARGS
;
8953 do_vfp_sp_reg2 (str
)
8956 skip_whitespace (str
);
8958 if (reg_required_here (&str
, 12) == FAIL
)
8961 if (skip_past_comma (&str
) == FAIL
8962 || reg_required_here (&str
, 16) == FAIL
8963 || skip_past_comma (&str
) == FAIL
)
8966 inst
.error
= BAD_ARGS
;
8970 /* We require exactly two consecutive SP registers. */
8971 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
8974 inst
.error
= _("only two consecutive VFP SP registers allowed here");
8981 do_vfp_sp_from_reg (str
)
8984 skip_whitespace (str
);
8986 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
8989 if (skip_past_comma (&str
) == FAIL
8990 || reg_required_here (&str
, 12) == FAIL
)
8993 inst
.error
= BAD_ARGS
;
9001 do_vfp_reg_from_dp (str
)
9004 skip_whitespace (str
);
9006 if (reg_required_here (&str
, 12) == FAIL
)
9009 if (skip_past_comma (&str
) == FAIL
9010 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9013 inst
.error
= BAD_ARGS
;
9021 do_vfp_reg2_from_dp (str
)
9024 skip_whitespace (str
);
9026 if (reg_required_here (&str
, 12) == FAIL
)
9029 if (skip_past_comma (&str
) == FAIL
9030 || reg_required_here (&str
, 16) == FAIL
9031 || skip_past_comma (&str
) == FAIL
9032 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9035 inst
.error
= BAD_ARGS
;
9043 do_vfp_dp_from_reg (str
)
9046 skip_whitespace (str
);
9048 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
9051 if (skip_past_comma (&str
) == FAIL
9052 || reg_required_here (&str
, 12) == FAIL
)
9055 inst
.error
= BAD_ARGS
;
9063 do_vfp_dp_from_reg2 (str
)
9066 skip_whitespace (str
);
9068 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9071 if (skip_past_comma (&str
) == FAIL
9072 || reg_required_here (&str
, 12) == FAIL
9073 || skip_past_comma (&str
) == FAIL
9074 || reg_required_here (&str
, 16))
9077 inst
.error
= BAD_ARGS
;
9084 static const struct vfp_reg
*
9091 const struct vfp_reg
*vreg
;
9095 /* Find the end of the current token. */
9100 while (ISALPHA (c
));
9105 for (vreg
= vfp_regs
+ 0;
9106 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
9109 if (strcmp (start
, vreg
->name
) == 0)
9122 vfp_psr_required_here (str
)
9126 const struct vfp_reg
*vreg
;
9128 vreg
= vfp_psr_parse (str
);
9132 inst
.instruction
|= vreg
->regno
;
9136 inst
.error
= _("VFP system register expected");
9143 do_vfp_reg_from_ctrl (str
)
9146 skip_whitespace (str
);
9148 if (reg_required_here (&str
, 12) == FAIL
)
9151 if (skip_past_comma (&str
) == FAIL
9152 || vfp_psr_required_here (&str
) == FAIL
)
9155 inst
.error
= BAD_ARGS
;
9163 do_vfp_ctrl_from_reg (str
)
9166 skip_whitespace (str
);
9168 if (vfp_psr_required_here (&str
) == FAIL
)
9171 if (skip_past_comma (&str
) == FAIL
9172 || reg_required_here (&str
, 12) == FAIL
)
9175 inst
.error
= BAD_ARGS
;
9183 do_vfp_sp_ldst (str
)
9186 skip_whitespace (str
);
9188 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9191 inst
.error
= BAD_ARGS
;
9195 if (skip_past_comma (&str
) == FAIL
9196 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9199 inst
.error
= BAD_ARGS
;
9207 do_vfp_dp_ldst (str
)
9210 skip_whitespace (str
);
9212 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9215 inst
.error
= BAD_ARGS
;
9219 if (skip_past_comma (&str
) == FAIL
9220 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
9223 inst
.error
= BAD_ARGS
;
9230 /* Parse and encode a VFP SP register list, storing the initial
9231 register in position POS and returning the range as the result. If
9232 the string is invalid return FAIL (an invalid range). */
9234 vfp_sp_reg_list (str
, pos
)
9236 enum vfp_sp_reg_pos pos
;
9244 unsigned long mask
= 0;
9251 skip_whitespace (*str
);
9253 tempinst
= inst
.instruction
;
9257 inst
.instruction
= 0;
9259 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
9262 if (count
== 0 || base_reg
> new_base
)
9264 base_reg
= new_base
;
9265 base_bits
= inst
.instruction
;
9268 if (mask
& (1 << new_base
))
9270 inst
.error
= _("invalid register list");
9274 if ((mask
>> new_base
) != 0 && ! warned
)
9276 as_tsktsk (_("register list not in ascending order"));
9280 mask
|= 1 << new_base
;
9283 skip_whitespace (*str
);
9285 if (**str
== '-') /* We have the start of a range expression */
9292 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
9295 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
9299 if (high_range
<= new_base
)
9301 inst
.error
= _("register range not in ascending order");
9305 for (new_base
++; new_base
<= high_range
; new_base
++)
9307 if (mask
& (1 << new_base
))
9309 inst
.error
= _("invalid register list");
9313 mask
|= 1 << new_base
;
9318 while (skip_past_comma (str
) != FAIL
);
9322 inst
.error
= _("invalid register list");
9330 /* Sanity check -- should have raised a parse error above. */
9331 if (count
== 0 || count
> 32)
9334 /* Final test -- the registers must be consecutive. */
9337 if ((mask
& (1 << base_reg
++)) == 0)
9339 inst
.error
= _("non-contiguous register range");
9344 inst
.instruction
= tempinst
| base_bits
;
9349 vfp_dp_reg_list (str
)
9357 unsigned long mask
= 0;
9364 skip_whitespace (*str
);
9366 tempinst
= inst
.instruction
;
9370 inst
.instruction
= 0;
9372 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
9375 if (count
== 0 || base_reg
> new_base
)
9377 base_reg
= new_base
;
9378 range
= inst
.instruction
;
9381 if (mask
& (1 << new_base
))
9383 inst
.error
= _("invalid register list");
9387 if ((mask
>> new_base
) != 0 && ! warned
)
9389 as_tsktsk (_("register list not in ascending order"));
9393 mask
|= 1 << new_base
;
9396 skip_whitespace (*str
);
9398 if (**str
== '-') /* We have the start of a range expression */
9405 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
9408 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
9412 if (high_range
<= new_base
)
9414 inst
.error
= _("register range not in ascending order");
9418 for (new_base
++; new_base
<= high_range
; new_base
++)
9420 if (mask
& (1 << new_base
))
9422 inst
.error
= _("invalid register list");
9426 mask
|= 1 << new_base
;
9431 while (skip_past_comma (str
) != FAIL
);
9435 inst
.error
= _("invalid register list");
9443 /* Sanity check -- should have raised a parse error above. */
9444 if (count
== 0 || count
> 16)
9447 /* Final test -- the registers must be consecutive. */
9450 if ((mask
& (1 << base_reg
++)) == 0)
9452 inst
.error
= _("non-contiguous register range");
9457 inst
.instruction
= tempinst
;
9462 vfp_sp_ldstm (str
, ldstm_type
)
9464 enum vfp_ldstm_type ldstm_type
;
9468 skip_whitespace (str
);
9470 if (reg_required_here (&str
, 16) == FAIL
)
9473 skip_whitespace (str
);
9477 inst
.instruction
|= WRITE_BACK
;
9480 else if (ldstm_type
!= VFP_LDSTMIA
)
9482 inst
.error
= _("this addressing mode requires base-register writeback");
9486 if (skip_past_comma (&str
) == FAIL
9487 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
9490 inst
.error
= BAD_ARGS
;
9494 inst
.instruction
|= range
;
9499 vfp_dp_ldstm (str
, ldstm_type
)
9501 enum vfp_ldstm_type ldstm_type
;
9505 skip_whitespace (str
);
9507 if (reg_required_here (&str
, 16) == FAIL
)
9510 skip_whitespace (str
);
9514 inst
.instruction
|= WRITE_BACK
;
9517 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
9519 inst
.error
= _("this addressing mode requires base-register writeback");
9523 if (skip_past_comma (&str
) == FAIL
9524 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
9527 inst
.error
= BAD_ARGS
;
9531 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
9534 inst
.instruction
|= range
;
9539 do_vfp_sp_ldstmia (str
)
9542 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
9546 do_vfp_sp_ldstmdb (str
)
9549 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
9553 do_vfp_dp_ldstmia (str
)
9556 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
9560 do_vfp_dp_ldstmdb (str
)
9563 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
9567 do_vfp_xp_ldstmia (str
)
9570 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
9574 do_vfp_xp_ldstmdb (str
)
9577 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
9581 do_vfp_sp_compare_z (str
)
9584 skip_whitespace (str
);
9586 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9589 inst
.error
= BAD_ARGS
;
9597 do_vfp_dp_compare_z (str
)
9600 skip_whitespace (str
);
9602 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9605 inst
.error
= BAD_ARGS
;
9613 do_vfp_dp_sp_cvt (str
)
9616 skip_whitespace (str
);
9618 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
9621 if (skip_past_comma (&str
) == FAIL
9622 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
9625 inst
.error
= BAD_ARGS
;
9633 do_vfp_sp_dp_cvt (str
)
9636 skip_whitespace (str
);
9638 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
9641 if (skip_past_comma (&str
) == FAIL
9642 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
9645 inst
.error
= BAD_ARGS
;
9652 /* Thumb specific routines. */
9654 /* Parse and validate that a register is of the right form, this saves
9655 repeated checking of this information in many similar cases.
9656 Unlike the 32-bit case we do not insert the register into the opcode
9657 here, since the position is often unknown until the full instruction
9661 thumb_reg (strp
, hi_lo
)
9667 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
9675 inst
.error
= _("lo register required");
9683 inst
.error
= _("hi register required");
9695 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9699 thumb_add_sub (str
, subtract
)
9703 int Rd
, Rs
, Rn
= FAIL
;
9705 skip_whitespace (str
);
9707 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9708 || skip_past_comma (&str
) == FAIL
)
9711 inst
.error
= BAD_ARGS
;
9715 if (is_immediate_prefix (*str
))
9719 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9724 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9727 if (skip_past_comma (&str
) == FAIL
)
9729 /* Two operand format, shuffle the registers
9730 and pretend there are 3. */
9734 else if (is_immediate_prefix (*str
))
9737 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9740 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9744 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9745 for the latter case, EXPR contains the immediate that was found. */
9748 /* All register format. */
9749 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
9753 inst
.error
= _("dest and source1 must be the same register");
9757 /* Can't do this for SUB. */
9760 inst
.error
= _("subtract valid only on lo regs");
9764 inst
.instruction
= (T_OPCODE_ADD_HI
9765 | (Rd
> 7 ? THUMB_H1
: 0)
9766 | (Rn
> 7 ? THUMB_H2
: 0));
9767 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
9771 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
9772 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
9777 /* Immediate expression, now things start to get nasty. */
9779 /* First deal with HI regs, only very restricted cases allowed:
9780 Adjusting SP, and using PC or SP to get an address. */
9781 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
9782 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
9784 inst
.error
= _("invalid Hi register with immediate");
9788 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9790 /* Value isn't known yet, all we can do is store all the fragments
9791 we know about in the instruction and let the reloc hacking
9793 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
9794 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9798 int offset
= inst
.reloc
.exp
.X_add_number
;
9808 /* Quick check, in case offset is MIN_INT. */
9811 inst
.error
= _("immediate value out of range");
9815 /* Note - you cannot convert a subtract of 0 into an
9816 add of 0 because the carry flag is set differently. */
9817 else if (offset
> 0)
9822 if (offset
& ~0x1fc)
9824 inst
.error
= _("invalid immediate value for stack adjust");
9827 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
9828 inst
.instruction
|= offset
>> 2;
9830 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
9833 || (offset
& ~0x3fc))
9835 inst
.error
= _("invalid immediate for address calculation");
9838 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
9840 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
9846 inst
.error
= _("immediate value out of range");
9849 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
9850 inst
.instruction
|= (Rd
<< 8) | offset
;
9856 inst
.error
= _("immediate value out of range");
9859 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
9860 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
9869 thumb_shift (str
, shift
)
9873 int Rd
, Rs
, Rn
= FAIL
;
9875 skip_whitespace (str
);
9877 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9878 || skip_past_comma (&str
) == FAIL
)
9881 inst
.error
= BAD_ARGS
;
9885 if (is_immediate_prefix (*str
))
9887 /* Two operand immediate format, set Rs to Rd. */
9890 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9895 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9898 if (skip_past_comma (&str
) == FAIL
)
9900 /* Two operand format, shuffle the registers
9901 and pretend there are 3. */
9905 else if (is_immediate_prefix (*str
))
9908 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9911 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9915 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9916 for the latter case, EXPR contains the immediate that was found. */
9922 inst
.error
= _("source1 and dest must be same register");
9928 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
9929 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
9930 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
9933 inst
.instruction
|= Rd
| (Rn
<< 3);
9939 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
9940 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
9941 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
9944 if (inst
.reloc
.exp
.X_op
!= O_constant
)
9946 /* Value isn't known yet, create a dummy reloc and let reloc
9947 hacking fix it up. */
9948 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
9952 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
9954 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
9956 inst
.error
= _("invalid immediate for shift");
9960 /* Shifts of zero are handled by converting to LSL. */
9961 if (shift_value
== 0)
9962 inst
.instruction
= T_OPCODE_LSL_I
;
9964 /* Shifts of 32 are encoded as a shift of zero. */
9965 if (shift_value
== 32)
9968 inst
.instruction
|= shift_value
<< 6;
9971 inst
.instruction
|= Rd
| (Rs
<< 3);
9978 thumb_mov_compare (str
, move
)
9984 skip_whitespace (str
);
9986 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
9987 || skip_past_comma (&str
) == FAIL
)
9990 inst
.error
= BAD_ARGS
;
9994 if (move
!= THUMB_CPY
&& is_immediate_prefix (*str
))
9997 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10000 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10005 if (move
!= THUMB_CPY
&& Rs
< 8 && Rd
< 8)
10007 if (move
== THUMB_MOVE
)
10008 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10009 since a MOV instruction produces unpredictable results. */
10010 inst
.instruction
= T_OPCODE_ADD_I3
;
10012 inst
.instruction
= T_OPCODE_CMP_LR
;
10013 inst
.instruction
|= Rd
| (Rs
<< 3);
10017 if (move
== THUMB_MOVE
)
10018 inst
.instruction
= T_OPCODE_MOV_HR
;
10019 else if (move
!= THUMB_CPY
)
10020 inst
.instruction
= T_OPCODE_CMP_HR
;
10023 inst
.instruction
|= THUMB_H1
;
10026 inst
.instruction
|= THUMB_H2
;
10028 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
10035 inst
.error
= _("only lo regs allowed with immediate");
10039 if (move
== THUMB_MOVE
)
10040 inst
.instruction
= T_OPCODE_MOV_I8
;
10042 inst
.instruction
= T_OPCODE_CMP_I8
;
10044 inst
.instruction
|= Rd
<< 8;
10046 if (inst
.reloc
.exp
.X_op
!= O_constant
)
10047 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
10050 unsigned value
= inst
.reloc
.exp
.X_add_number
;
10054 inst
.error
= _("invalid immediate");
10058 inst
.instruction
|= value
;
10066 thumb_load_store (str
, load_store
, size
)
10071 int Rd
, Rb
, Ro
= FAIL
;
10073 skip_whitespace (str
);
10075 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10076 || skip_past_comma (&str
) == FAIL
)
10079 inst
.error
= BAD_ARGS
;
10086 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
10089 if (skip_past_comma (&str
) != FAIL
)
10091 if (is_immediate_prefix (*str
))
10094 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10097 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10102 inst
.reloc
.exp
.X_op
= O_constant
;
10103 inst
.reloc
.exp
.X_add_number
= 0;
10108 inst
.error
= _("expected ']'");
10113 else if (*str
== '=')
10115 if (load_store
!= THUMB_LOAD
)
10117 inst
.error
= _("invalid pseudo operation");
10121 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
10124 skip_whitespace (str
);
10126 if (my_get_expression (& inst
.reloc
.exp
, & str
))
10131 if ( inst
.reloc
.exp
.X_op
!= O_constant
10132 && inst
.reloc
.exp
.X_op
!= O_symbol
)
10134 inst
.error
= "Constant expression expected";
10138 if (inst
.reloc
.exp
.X_op
== O_constant
10139 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
10141 /* This can be done with a mov instruction. */
10143 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
10144 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
10148 /* Insert into literal pool. */
10149 if (add_to_lit_pool () == FAIL
)
10152 inst
.error
= "literal pool insertion failed";
10156 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10157 inst
.reloc
.pc_rel
= 1;
10158 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10159 /* Adjust ARM pipeline offset to Thumb. */
10160 inst
.reloc
.exp
.X_add_number
+= 4;
10166 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10169 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
10170 inst
.reloc
.pc_rel
= 1;
10171 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
10172 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10177 if (Rb
== REG_PC
|| Rb
== REG_SP
)
10179 if (size
!= THUMB_WORD
)
10181 inst
.error
= _("byte or halfword not valid for base register");
10184 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
10186 inst
.error
= _("r15 based store not allowed");
10189 else if (Ro
!= FAIL
)
10191 inst
.error
= _("invalid base register for register offset");
10196 inst
.instruction
= T_OPCODE_LDR_PC
;
10197 else if (load_store
== THUMB_LOAD
)
10198 inst
.instruction
= T_OPCODE_LDR_SP
;
10200 inst
.instruction
= T_OPCODE_STR_SP
;
10202 inst
.instruction
|= Rd
<< 8;
10203 if (inst
.reloc
.exp
.X_op
== O_constant
)
10205 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10207 if (offset
& ~0x3fc)
10209 inst
.error
= _("invalid offset");
10213 inst
.instruction
|= offset
>> 2;
10216 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10220 inst
.error
= _("invalid base register in load/store");
10223 else if (Ro
== FAIL
)
10225 /* Immediate offset. */
10226 if (size
== THUMB_WORD
)
10227 inst
.instruction
= (load_store
== THUMB_LOAD
10228 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
10229 else if (size
== THUMB_HALFWORD
)
10230 inst
.instruction
= (load_store
== THUMB_LOAD
10231 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
10233 inst
.instruction
= (load_store
== THUMB_LOAD
10234 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
10236 inst
.instruction
|= Rd
| (Rb
<< 3);
10238 if (inst
.reloc
.exp
.X_op
== O_constant
)
10240 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
10242 if (offset
& ~(0x1f << size
))
10244 inst
.error
= _("invalid offset");
10247 inst
.instruction
|= (offset
>> size
) << 6;
10250 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
10254 /* Register offset. */
10255 if (size
== THUMB_WORD
)
10256 inst
.instruction
= (load_store
== THUMB_LOAD
10257 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
10258 else if (size
== THUMB_HALFWORD
)
10259 inst
.instruction
= (load_store
== THUMB_LOAD
10260 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
10262 inst
.instruction
= (load_store
== THUMB_LOAD
10263 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
10265 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
10271 /* A register must be given at this point.
10273 Shift is the place to put it in inst.instruction.
10275 Restores input start point on err.
10276 Returns the reg#, or FAIL. */
10279 mav_reg_required_here (str
, shift
, regtype
)
10282 enum arm_reg_type regtype
;
10285 char *start
= *str
;
10287 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
10290 inst
.instruction
|= reg
<< shift
;
10295 /* Restore the start point. */
10298 /* In the few cases where we might be able to accept something else
10299 this error can be overridden. */
10300 inst
.error
= _(all_reg_maps
[regtype
].expected
);
10305 /* Cirrus Maverick Instructions. */
10307 /* Wrapper functions. */
10310 do_mav_binops_1a (str
)
10313 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
10317 do_mav_binops_1b (str
)
10320 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
10324 do_mav_binops_1c (str
)
10327 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
10331 do_mav_binops_1d (str
)
10334 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10338 do_mav_binops_1e (str
)
10341 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10345 do_mav_binops_1f (str
)
10348 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
10352 do_mav_binops_1g (str
)
10355 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
10359 do_mav_binops_1h (str
)
10362 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
10366 do_mav_binops_1i (str
)
10369 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
10373 do_mav_binops_1j (str
)
10376 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
10380 do_mav_binops_1k (str
)
10383 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
10387 do_mav_binops_1l (str
)
10390 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
10394 do_mav_binops_1m (str
)
10397 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
10401 do_mav_binops_1n (str
)
10404 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10408 do_mav_binops_1o (str
)
10411 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10415 do_mav_binops_2a (str
)
10418 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
10422 do_mav_binops_2b (str
)
10425 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
10429 do_mav_binops_2c (str
)
10432 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10436 do_mav_binops_3a (str
)
10439 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
10443 do_mav_binops_3b (str
)
10446 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
10450 do_mav_binops_3c (str
)
10453 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
10457 do_mav_binops_3d (str
)
10460 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
10464 do_mav_triple_4a (str
)
10467 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
10471 do_mav_triple_4b (str
)
10474 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
10478 do_mav_triple_5a (str
)
10481 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10485 do_mav_triple_5b (str
)
10488 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10492 do_mav_triple_5c (str
)
10495 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10499 do_mav_triple_5d (str
)
10502 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10506 do_mav_triple_5e (str
)
10509 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
10513 do_mav_triple_5f (str
)
10516 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
10520 do_mav_triple_5g (str
)
10523 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10527 do_mav_triple_5h (str
)
10530 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10534 do_mav_quad_6a (str
)
10537 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
10542 do_mav_quad_6b (str
)
10545 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
10549 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
10551 do_mav_dspsc_1 (str
)
10554 skip_whitespace (str
);
10557 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
10558 || skip_past_comma (&str
) == FAIL
10559 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
10562 inst
.error
= BAD_ARGS
;
10570 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
10572 do_mav_dspsc_2 (str
)
10575 skip_whitespace (str
);
10578 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
10579 || skip_past_comma (&str
) == FAIL
10580 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
10583 inst
.error
= BAD_ARGS
;
10592 do_mav_shift_1 (str
)
10595 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
10599 do_mav_shift_2 (str
)
10602 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
10606 do_mav_ldst_1 (str
)
10609 do_mav_ldst (str
, REG_TYPE_MVF
);
10613 do_mav_ldst_2 (str
)
10616 do_mav_ldst (str
, REG_TYPE_MVD
);
10620 do_mav_ldst_3 (str
)
10623 do_mav_ldst (str
, REG_TYPE_MVFX
);
10627 do_mav_ldst_4 (str
)
10630 do_mav_ldst (str
, REG_TYPE_MVDX
);
10633 /* Isnsn like "foo X,Y". */
10636 do_mav_binops (str
, mode
, reg0
, reg1
)
10639 enum arm_reg_type reg0
;
10640 enum arm_reg_type reg1
;
10642 int shift0
, shift1
;
10644 shift0
= mode
& 0xff;
10645 shift1
= (mode
>> 8) & 0xff;
10647 skip_whitespace (str
);
10649 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10650 || skip_past_comma (&str
) == FAIL
10651 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
10654 inst
.error
= BAD_ARGS
;
10660 /* Isnsn like "foo X,Y,Z". */
10663 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
10666 enum arm_reg_type reg0
;
10667 enum arm_reg_type reg1
;
10668 enum arm_reg_type reg2
;
10670 int shift0
, shift1
, shift2
;
10672 shift0
= mode
& 0xff;
10673 shift1
= (mode
>> 8) & 0xff;
10674 shift2
= (mode
>> 16) & 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
10681 || skip_past_comma (&str
) == FAIL
10682 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
10685 inst
.error
= BAD_ARGS
;
10691 /* Isnsn like "foo W,X,Y,Z".
10692 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
10695 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
10698 enum arm_reg_type reg0
;
10699 enum arm_reg_type reg1
;
10700 enum arm_reg_type reg2
;
10701 enum arm_reg_type reg3
;
10703 int shift0
, shift1
, shift2
, shift3
;
10705 shift0
= mode
& 0xff;
10706 shift1
= (mode
>> 8) & 0xff;
10707 shift2
= (mode
>> 16) & 0xff;
10708 shift3
= (mode
>> 24) & 0xff;
10710 skip_whitespace (str
);
10712 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
10713 || skip_past_comma (&str
) == FAIL
10714 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
10715 || skip_past_comma (&str
) == FAIL
10716 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
10717 || skip_past_comma (&str
) == FAIL
10718 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
10721 inst
.error
= BAD_ARGS
;
10727 /* Maverick shift immediate instructions.
10728 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10729 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
10732 do_mav_shift (str
, reg0
, reg1
)
10734 enum arm_reg_type reg0
;
10735 enum arm_reg_type reg1
;
10740 skip_whitespace (str
);
10744 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10745 || skip_past_comma (&str
) == FAIL
10746 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
10747 || skip_past_comma (&str
) == FAIL
)
10750 inst
.error
= BAD_ARGS
;
10754 /* Calculate the immediate operand.
10755 The operand is a 7bit signed number. */
10756 skip_whitespace (str
);
10761 if (!ISDIGIT (*str
) && *str
!= '-')
10763 inst
.error
= _("expecting immediate, 7bit operand");
10773 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
10774 imm
= imm
* 10 + *str
- '0';
10778 inst
.error
= _("immediate out of range");
10782 /* Make negative imm's into 7bit signed numbers. */
10789 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10790 Bits 5-7 of the insn should have bits 4-6 of the immediate.
10791 Bit 4 should be 0. */
10792 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
10794 inst
.instruction
|= imm
;
10799 mav_parse_offset (str
, negative
)
10808 skip_whitespace (p
);
10821 inst
.error
= _("offset expected");
10825 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
10826 offset
= offset
* 10 + *p
- '0';
10830 inst
.error
= _("offset out of range");
10836 return *negative
? -offset
: offset
;
10839 /* Maverick load/store instructions.
10840 <insn><cond> CRd,[Rn,<offset>]{!}.
10841 <insn><cond> CRd,[Rn],<offset>. */
10844 do_mav_ldst (str
, reg0
)
10846 enum arm_reg_type reg0
;
10848 int offset
, negative
;
10850 skip_whitespace (str
);
10852 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
10853 || skip_past_comma (&str
) == FAIL
10855 || reg_required_here (&str
, 16) == FAIL
)
10858 if (skip_past_comma (&str
) == SUCCESS
)
10860 /* You are here: "<offset>]{!}". */
10861 inst
.instruction
|= PRE_INDEX
;
10863 offset
= mav_parse_offset (&str
, &negative
);
10870 inst
.error
= _("missing ]");
10876 inst
.instruction
|= WRITE_BACK
;
10882 /* You are here: "], <offset>". */
10885 inst
.error
= _("missing ]");
10889 if (skip_past_comma (&str
) == FAIL
10890 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
10893 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
10899 inst
.instruction
|= CP_T_UD
; /* Positive, so set bit U. */
10901 inst
.instruction
|= offset
>> 2;
10907 inst
.error
= BAD_ARGS
;
10918 /* Handle the Format 4 instructions that do not have equivalents in other
10919 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10928 skip_whitespace (str
);
10930 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
10931 || skip_past_comma (&str
) == FAIL
10932 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10934 inst
.error
= BAD_ARGS
;
10938 if (skip_past_comma (&str
) != FAIL
)
10940 /* Three operand format not allowed for TST, CMN, NEG and MVN.
10941 (It isn't allowed for CMP either, but that isn't handled by this
10943 if (inst
.instruction
== T_OPCODE_TST
10944 || inst
.instruction
== T_OPCODE_CMN
10945 || inst
.instruction
== T_OPCODE_NEG
10946 || inst
.instruction
== T_OPCODE_MVN
)
10948 inst
.error
= BAD_ARGS
;
10952 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
10957 inst
.error
= _("dest and source1 must be the same register");
10963 if (inst
.instruction
== T_OPCODE_MUL
10965 as_tsktsk (_("Rs and Rd must be different in MUL"));
10967 inst
.instruction
|= Rd
| (Rs
<< 3);
10975 thumb_add_sub (str
, 0);
10982 thumb_shift (str
, THUMB_ASR
);
10989 if (my_get_expression (&inst
.reloc
.exp
, &str
))
10991 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
10992 inst
.reloc
.pc_rel
= 1;
10997 do_t_branch12 (str
)
11000 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11002 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
11003 inst
.reloc
.pc_rel
= 1;
11007 /* Find the real, Thumb encoded start of a Thumb function. */
11010 find_real_start (symbolP
)
11014 const char * name
= S_GET_NAME (symbolP
);
11015 symbolS
* new_target
;
11017 /* This definition must agree with the one in gcc/config/arm/thumb.c. */
11018 #define STUB_NAME ".real_start_of"
11023 /* Names that start with '.' are local labels, not function entry points.
11024 The compiler may generate BL instructions to these labels because it
11025 needs to perform a branch to a far away location. */
11026 if (name
[0] == '.')
11029 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
11030 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
11032 new_target
= symbol_find (real_start
);
11034 if (new_target
== NULL
)
11036 as_warn ("Failed to find real start of function: %s\n", name
);
11037 new_target
= symbolP
;
11046 do_t_branch23 (str
)
11049 if (my_get_expression (& inst
.reloc
.exp
, & str
))
11052 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
11053 inst
.reloc
.pc_rel
= 1;
11056 /* If the destination of the branch is a defined symbol which does not have
11057 the THUMB_FUNC attribute, then we must be calling a function which has
11058 the (interfacearm) attribute. We look for the Thumb entry point to that
11059 function and change the branch to refer to that function instead. */
11060 if ( inst
.reloc
.exp
.X_op
== O_symbol
11061 && inst
.reloc
.exp
.X_add_symbol
!= NULL
11062 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
11063 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
11064 inst
.reloc
.exp
.X_add_symbol
=
11065 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
11074 skip_whitespace (str
);
11076 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
11079 /* This sets THUMB_H2 from the top bit of reg. */
11080 inst
.instruction
|= reg
<< 3;
11082 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
11083 should cause the alignment to be checked once it is known. This is
11084 because BX PC only works if the instruction is word aligned. */
11093 thumb_mov_compare (str
, THUMB_COMPARE
);
11103 skip_whitespace (str
);
11105 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
11109 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11113 if (skip_past_comma (&str
) == FAIL
11114 || (range
= reg_list (&str
)) == FAIL
)
11117 inst
.error
= BAD_ARGS
;
11121 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11123 /* This really doesn't seem worth it. */
11124 inst
.reloc
.type
= BFD_RELOC_NONE
;
11125 inst
.error
= _("expression too complex");
11131 inst
.error
= _("only lo-regs valid in load/store multiple");
11135 inst
.instruction
|= (Rb
<< 8) | range
;
11143 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
11150 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
11157 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
11166 skip_whitespace (str
);
11168 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11169 || skip_past_comma (&str
) == FAIL
11171 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11172 || skip_past_comma (&str
) == FAIL
11173 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
11177 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
11181 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
11189 thumb_shift (str
, THUMB_LSL
);
11196 thumb_shift (str
, THUMB_LSR
);
11203 thumb_mov_compare (str
, THUMB_MOVE
);
11207 do_t_push_pop (str
)
11212 skip_whitespace (str
);
11214 if ((range
= reg_list (&str
)) == FAIL
)
11217 inst
.error
= BAD_ARGS
;
11221 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11223 /* This really doesn't seem worth it. */
11224 inst
.reloc
.type
= BFD_RELOC_NONE
;
11225 inst
.error
= _("expression too complex");
11231 if ((inst
.instruction
== T_OPCODE_PUSH
11232 && (range
& ~0xff) == 1 << REG_LR
)
11233 || (inst
.instruction
== T_OPCODE_POP
11234 && (range
& ~0xff) == 1 << REG_PC
))
11236 inst
.instruction
|= THUMB_PP_PC_LR
;
11241 inst
.error
= _("invalid register list to push/pop instruction");
11246 inst
.instruction
|= range
;
11254 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
11261 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
11268 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
11275 thumb_add_sub (str
, 1);
11282 skip_whitespace (str
);
11284 if (my_get_expression (&inst
.reloc
.exp
, &str
))
11287 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
11297 /* This is a pseudo-op of the form "adr rd, label" to be converted
11298 into a relative address of the form "add rd, pc, #label-.-4". */
11299 skip_whitespace (str
);
11301 /* Store Rd in temporary location inside instruction. */
11302 if ((reg
= reg_required_here (&str
, 4)) == FAIL
11303 || (reg
> 7) /* For Thumb reg must be r0..r7. */
11304 || skip_past_comma (&str
) == FAIL
11305 || my_get_expression (&inst
.reloc
.exp
, &str
))
11308 inst
.error
= BAD_ARGS
;
11312 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
11313 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
11314 inst
.reloc
.pc_rel
= 1;
11315 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
11321 insert_reg (r
, htab
)
11322 const struct reg_entry
*r
;
11323 struct hash_control
*htab
;
11325 int len
= strlen (r
->name
) + 2;
11326 char * buf
= (char *) xmalloc (len
);
11327 char * buf2
= (char *) xmalloc (len
);
11330 #ifdef REGISTER_PREFIX
11331 buf
[i
++] = REGISTER_PREFIX
;
11334 strcpy (buf
+ i
, r
->name
);
11336 for (i
= 0; buf
[i
]; i
++)
11337 buf2
[i
] = TOUPPER (buf
[i
]);
11341 hash_insert (htab
, buf
, (PTR
) r
);
11342 hash_insert (htab
, buf2
, (PTR
) r
);
11346 build_reg_hsh (map
)
11347 struct reg_map
*map
;
11349 const struct reg_entry
*r
;
11351 if ((map
->htab
= hash_new ()) == NULL
)
11352 as_fatal (_("virtual memory exhausted"));
11354 for (r
= map
->names
; r
->name
!= NULL
; r
++)
11355 insert_reg (r
, map
->htab
);
11359 insert_reg_alias (str
, regnum
, htab
)
11362 struct hash_control
*htab
;
11365 struct reg_entry
*new = xmalloc (sizeof (struct reg_entry
));
11366 const char *name
= xmalloc (strlen (str
) + 1);
11368 strcpy ((char *) name
, str
);
11371 new->number
= regnum
;
11372 new->builtin
= FALSE
;
11374 error
= hash_insert (htab
, name
, (PTR
) new);
11377 as_bad (_("failed to create an alias for %s, reason: %s"),
11379 free ((char *) name
);
11384 /* Look for the .req directive. This is of the form:
11386 new_register_name .req existing_register_name
11388 If we find one, or if it looks sufficiently like one that we want to
11389 handle any error here, return non-zero. Otherwise return zero. */
11391 create_register_alias (newname
, p
)
11399 skip_whitespace (q
);
11404 if (*q
&& !strncmp (q
, ".req ", 5))
11409 #ifdef IGNORE_OPCODE_CASE
11410 newname
= original_case_string
;
11412 copy_of_str
= newname
;
11415 skip_whitespace (q
);
11417 for (r
= q
; *r
!= '\0'; r
++)
11423 enum arm_reg_type new_type
, old_type
;
11428 old_type
= arm_reg_parse_any (q
);
11431 new_type
= arm_reg_parse_any (newname
);
11433 if (new_type
== REG_TYPE_MAX
)
11435 if (old_type
!= REG_TYPE_MAX
)
11437 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
11438 insert_reg_alias (newname
, old_regno
,
11439 all_reg_maps
[old_type
].htab
);
11442 as_warn (_("register '%s' does not exist\n"), q
);
11444 else if (old_type
== REG_TYPE_MAX
)
11446 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11451 /* Do not warn about redefinitions to the same alias. */
11452 if (new_type
!= old_type
11453 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
11454 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
11455 as_warn (_("ignoring redefinition of register alias '%s'"),
11461 as_warn (_("ignoring incomplete .req pseuso op"));
11472 set_constant_flonums ()
11476 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
11477 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
11481 /* Iterate over the base tables to create the instruction patterns. */
11483 build_arm_ops_hsh ()
11487 static struct obstack insn_obstack
;
11489 obstack_begin (&insn_obstack
, 4000);
11491 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
11493 const struct asm_opcode
*insn
= insns
+ i
;
11495 if (insn
->cond_offset
!= 0)
11497 /* Insn supports conditional execution. Build the varaints
11498 and insert them in the hash table. */
11499 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
11501 unsigned len
= strlen (insn
->template);
11502 struct asm_opcode
*new;
11505 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
11506 /* All condition codes are two characters. */
11507 template = obstack_alloc (&insn_obstack
, len
+ 3);
11509 strncpy (template, insn
->template, insn
->cond_offset
);
11510 strcpy (template + insn
->cond_offset
, conds
[j
].template);
11511 if (len
> insn
->cond_offset
)
11512 strcpy (template + insn
->cond_offset
+ 2,
11513 insn
->template + insn
->cond_offset
);
11514 new->template = template;
11515 new->cond_offset
= 0;
11516 new->variant
= insn
->variant
;
11517 new->parms
= insn
->parms
;
11518 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
11520 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
11523 /* Finally, insert the unconditional insn in the table directly;
11524 no need to build a copy. */
11525 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
11529 #if 0 /* Suppressed - for now. */
11530 #if defined OBJ_ELF || defined OBJ_COFF
11533 #define arm_Note Elf_External_Note
11537 unsigned char namesz
[4]; /* Size of entry's owner string. */
11538 unsigned char descsz
[4]; /* Size of the note descriptor. */
11539 unsigned char type
[4]; /* Interpretation of the descriptor. */
11540 char name
[1]; /* Start of the name+desc data. */
11544 /* The description is kept to a fix sized in order to make updating
11545 it and merging it easier. */
11546 #define ARM_NOTE_DESCRIPTION_LENGTH 8
11549 arm_add_note (name
, description
, type
)
11551 const char * description
;
11554 arm_Note note ATTRIBUTE_UNUSED
;
11556 unsigned int name_len
;
11558 name_len
= (strlen (name
) + 1 + 3) & ~3;
11560 p
= frag_more (sizeof (note
.namesz
));
11561 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
11563 p
= frag_more (sizeof (note
.descsz
));
11564 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
11566 p
= frag_more (sizeof (note
.type
));
11567 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
11569 p
= frag_more (name_len
);
11572 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
11573 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
11574 frag_align (2, 0, 0);
11585 if ( (arm_ops_hsh
= hash_new ()) == NULL
11586 || (arm_tops_hsh
= hash_new ()) == NULL
11587 || (arm_cond_hsh
= hash_new ()) == NULL
11588 || (arm_shift_hsh
= hash_new ()) == NULL
11589 || (arm_psr_hsh
= hash_new ()) == NULL
)
11590 as_fatal (_("virtual memory exhausted"));
11592 build_arm_ops_hsh ();
11593 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
11594 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
11595 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
11596 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
11597 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
11598 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
11599 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
11600 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
11602 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
11603 build_reg_hsh (all_reg_maps
+ i
);
11605 set_constant_flonums ();
11607 /* Set the cpu variant based on the command-line options. We prefer
11608 -mcpu= over -march= if both are set (as for GCC); and we prefer
11609 -mfpu= over any other way of setting the floating point unit.
11610 Use of legacy options with new options are faulted. */
11611 if (legacy_cpu
!= -1)
11613 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
11614 as_bad (_("use of old and new-style options to set CPU type"));
11616 mcpu_cpu_opt
= legacy_cpu
;
11618 else if (mcpu_cpu_opt
== -1)
11619 mcpu_cpu_opt
= march_cpu_opt
;
11621 if (legacy_fpu
!= -1)
11623 if (mfpu_opt
!= -1)
11624 as_bad (_("use of old and new-style options to set FPU type"));
11626 mfpu_opt
= legacy_fpu
;
11628 else if (mfpu_opt
== -1)
11630 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
11631 /* Some environments specify a default FPU. If they don't, infer it
11632 from the processor. */
11633 if (mcpu_fpu_opt
!= -1)
11634 mfpu_opt
= mcpu_fpu_opt
;
11636 mfpu_opt
= march_fpu_opt
;
11638 mfpu_opt
= FPU_DEFAULT
;
11642 if (mfpu_opt
== -1)
11644 if (mcpu_cpu_opt
== -1)
11645 mfpu_opt
= FPU_DEFAULT
;
11646 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
11647 mfpu_opt
= FPU_ARCH_VFP_V2
;
11649 mfpu_opt
= FPU_ARCH_FPA
;
11652 if (mcpu_cpu_opt
== -1)
11653 mcpu_cpu_opt
= CPU_DEFAULT
;
11655 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
11657 #if defined OBJ_COFF || defined OBJ_ELF
11659 unsigned int flags
= 0;
11661 /* Set the flags in the private structure. */
11662 if (uses_apcs_26
) flags
|= F_APCS26
;
11663 if (support_interwork
) flags
|= F_INTERWORK
;
11664 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
11665 if (pic_code
) flags
|= F_PIC
;
11666 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
11667 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
11669 flags
|= F_SOFT_FLOAT
;
11671 switch (mfloat_abi_opt
)
11673 case ARM_FLOAT_ABI_SOFT
:
11674 case ARM_FLOAT_ABI_SOFTFP
:
11675 flags
|= F_SOFT_FLOAT
;
11678 case ARM_FLOAT_ABI_HARD
:
11679 if (flags
& F_SOFT_FLOAT
)
11680 as_bad (_("hard-float conflicts with specified fpu"));
11683 /* Using VFP conventions (even if soft-float). */
11684 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
11686 #if defined OBJ_ELF
11687 if (cpu_variant
& FPU_ARCH_MAVERICK
)
11688 flags
|= EF_ARM_MAVERICK_FLOAT
;
11691 bfd_set_private_flags (stdoutput
, flags
);
11693 /* We have run out flags in the COFF header to encode the
11694 status of ATPCS support, so instead we create a dummy,
11695 empty, debug section called .arm.atpcs. */
11700 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
11704 bfd_set_section_flags
11705 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
11706 bfd_set_section_size (stdoutput
, sec
, 0);
11707 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
11713 /* Record the CPU type as well. */
11714 switch (cpu_variant
& ARM_CPU_MASK
)
11717 mach
= bfd_mach_arm_2
;
11720 case ARM_3
: /* Also ARM_250. */
11721 mach
= bfd_mach_arm_2a
;
11724 case ARM_6
: /* Also ARM_7. */
11725 mach
= bfd_mach_arm_3
;
11729 mach
= bfd_mach_arm_unknown
;
11733 /* Catch special cases. */
11734 if (cpu_variant
& ARM_CEXT_IWMMXT
)
11735 mach
= bfd_mach_arm_iWMMXt
;
11736 else if (cpu_variant
& ARM_CEXT_XSCALE
)
11737 mach
= bfd_mach_arm_XScale
;
11738 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
11739 mach
= bfd_mach_arm_ep9312
;
11740 else if (cpu_variant
& ARM_EXT_V5E
)
11741 mach
= bfd_mach_arm_5TE
;
11742 else if (cpu_variant
& ARM_EXT_V5
)
11744 if (cpu_variant
& ARM_EXT_V4T
)
11745 mach
= bfd_mach_arm_5T
;
11747 mach
= bfd_mach_arm_5
;
11749 else if (cpu_variant
& ARM_EXT_V4
)
11751 if (cpu_variant
& ARM_EXT_V4T
)
11752 mach
= bfd_mach_arm_4T
;
11754 mach
= bfd_mach_arm_4
;
11756 else if (cpu_variant
& ARM_EXT_V3M
)
11757 mach
= bfd_mach_arm_3M
;
11759 #if 0 /* Suppressed - for now. */
11760 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11762 /* Create a .note section to fully identify this arm binary. */
11764 #define NOTE_ARCH_STRING "arch: "
11766 #if defined OBJ_COFF && ! defined NT_VERSION
11767 #define NT_VERSION 1
11772 segT current_seg
= now_seg
;
11773 subsegT current_subseg
= now_subseg
;
11774 asection
* arm_arch
;
11775 const char * arch_string
;
11777 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
11780 bfd_set_section_flags (stdoutput
, arm_arch
,
11781 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
11782 | SEC_HAS_CONTENTS
);
11784 arm_arch
->output_section
= arm_arch
;
11785 subseg_set (arm_arch
, 0);
11790 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
11791 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
11792 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
11793 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
11794 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
11795 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
11796 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
11797 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
11798 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
11799 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
11800 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
11801 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
11802 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
11805 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
11807 subseg_set (current_seg
, current_subseg
);
11810 #endif /* Suppressed code. */
11812 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
11815 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11816 for use in the a.out file, and stores them in the array pointed to by buf.
11817 This knows about the endian-ness of the target machine and does
11818 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
11819 2 (short) and 4 (long) Floating numbers are put out as a series of
11820 LITTLENUMS (shorts, here at least). */
11823 md_number_to_chars (buf
, val
, n
)
11828 if (target_big_endian
)
11829 number_to_chars_bigendian (buf
, val
, n
);
11831 number_to_chars_littleendian (buf
, val
, n
);
11835 md_chars_to_number (buf
, n
)
11840 unsigned char * where
= (unsigned char *) buf
;
11842 if (target_big_endian
)
11847 result
|= (*where
++ & 255);
11855 result
|= (where
[n
] & 255);
11862 /* Turn a string in input_line_pointer into a floating point constant
11863 of type TYPE, and store the appropriate bytes in *LITP. The number
11864 of LITTLENUMS emitted is stored in *SIZEP. An error message is
11865 returned, or NULL on OK.
11867 Note that fp constants aren't represent in the normal way on the ARM.
11868 In big endian mode, things are as expected. However, in little endian
11869 mode fp constants are big-endian word-wise, and little-endian byte-wise
11870 within the words. For example, (double) 1.1 in big endian mode is
11871 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11872 the byte sequence 99 99 f1 3f 9a 99 99 99.
11874 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
11877 md_atof (type
, litP
, sizeP
)
11883 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
11915 return _("bad call to MD_ATOF()");
11918 t
= atof_ieee (input_line_pointer
, type
, words
);
11920 input_line_pointer
= t
;
11923 if (target_big_endian
)
11925 for (i
= 0; i
< prec
; i
++)
11927 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11933 if (cpu_variant
& FPU_ARCH_VFP
)
11934 for (i
= prec
- 1; i
>= 0; i
--)
11936 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
11940 /* For a 4 byte float the order of elements in `words' is 1 0.
11941 For an 8 byte float the order is 1 0 3 2. */
11942 for (i
= 0; i
< prec
; i
+= 2)
11944 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
11945 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
11953 /* The knowledge of the PC's pipeline offset is built into the insns
11957 md_pcrel_from (fixP
)
11961 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
11962 && fixP
->fx_subsy
== NULL
)
11965 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
11967 /* PC relative addressing on the Thumb is slightly odd
11968 as the bottom two bits of the PC are forced to zero
11969 for the calculation. */
11970 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
11974 /* The pattern was adjusted to accommodate CE's off-by-one fixups,
11975 so we un-adjust here to compensate for the accommodation. */
11976 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
11978 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
11982 /* Round up a section size to the appropriate boundary. */
11985 md_section_align (segment
, size
)
11986 segT segment ATTRIBUTE_UNUSED
;
11992 /* Round all sects to multiple of 4. */
11993 return (size
+ 3) & ~3;
11997 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
11998 Otherwise we have no need to default values of symbols. */
12001 md_undefined_symbol (name
)
12002 char * name ATTRIBUTE_UNUSED
;
12005 if (name
[0] == '_' && name
[1] == 'G'
12006 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
12010 if (symbol_find (name
))
12011 as_bad ("GOT already in the symbol table");
12013 GOT_symbol
= symbol_new (name
, undefined_section
,
12014 (valueT
) 0, & zero_address_frag
);
12024 /* arm_reg_parse () := if it looks like a register, return its token and
12025 advance the pointer. */
12028 arm_reg_parse (ccp
, htab
)
12029 register char ** ccp
;
12030 struct hash_control
*htab
;
12032 char * start
= * ccp
;
12035 struct reg_entry
* reg
;
12037 #ifdef REGISTER_PREFIX
12038 if (*start
!= REGISTER_PREFIX
)
12043 #ifdef OPTIONAL_REGISTER_PREFIX
12044 if (*p
== OPTIONAL_REGISTER_PREFIX
)
12048 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
12052 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
12056 reg
= (struct reg_entry
*) hash_find (htab
, start
);
12062 return reg
->number
;
12068 /* Search for the following register name in each of the possible reg name
12069 tables. Return the classification if found, or REG_TYPE_MAX if not
12071 static enum arm_reg_type
12072 arm_reg_parse_any (cp
)
12077 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
12078 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
12079 return (enum arm_reg_type
) i
;
12081 return REG_TYPE_MAX
;
12085 md_apply_fix3 (fixP
, valP
, seg
)
12090 offsetT value
= * valP
;
12092 unsigned int newimm
;
12093 unsigned long temp
;
12095 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
12096 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
12098 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
12100 /* Note whether this will delete the relocation. */
12102 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12103 doesn't work fully.) */
12104 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
12105 && !fixP
->fx_pcrel
)
12107 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
12111 /* If this symbol is in a different section then we need to leave it for
12112 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
12113 so we have to undo it's effects here. */
12114 if (fixP
->fx_pcrel
)
12116 if (fixP
->fx_addsy
!= NULL
12117 && S_IS_DEFINED (fixP
->fx_addsy
)
12118 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
12121 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12122 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12126 value
+= md_pcrel_from (fixP
);
12130 /* Remember value for emit_reloc. */
12131 fixP
->fx_addnumber
= value
;
12133 switch (fixP
->fx_r_type
)
12135 case BFD_RELOC_ARM_IMMEDIATE
:
12136 newimm
= validate_immediate (value
);
12137 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12139 /* If the instruction will fail, see if we can fix things up by
12140 changing the opcode. */
12141 if (newimm
== (unsigned int) FAIL
12142 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
12144 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12145 _("invalid constant (%lx) after fixup"),
12146 (unsigned long) value
);
12150 newimm
|= (temp
& 0xfffff000);
12151 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12155 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12157 unsigned int highpart
= 0;
12158 unsigned int newinsn
= 0xe1a00000; /* nop. */
12160 newimm
= validate_immediate (value
);
12161 temp
= md_chars_to_number (buf
, INSN_SIZE
);
12163 /* If the instruction will fail, see if we can fix things up by
12164 changing the opcode. */
12165 if (newimm
== (unsigned int) FAIL
12166 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
12168 /* No ? OK - try using two ADD instructions to generate
12170 newimm
= validate_immediate_twopart (value
, & highpart
);
12172 /* Yes - then make sure that the second instruction is
12174 if (newimm
!= (unsigned int) FAIL
)
12176 /* Still No ? Try using a negated value. */
12177 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
12178 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
12179 /* Otherwise - give up. */
12182 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12183 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12188 /* Replace the first operand in the 2nd instruction (which
12189 is the PC) with the destination register. We have
12190 already added in the PC in the first instruction and we
12191 do not want to do it again. */
12192 newinsn
&= ~ 0xf0000;
12193 newinsn
|= ((newinsn
& 0x0f000) << 4);
12196 newimm
|= (temp
& 0xfffff000);
12197 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
12199 highpart
|= (newinsn
& 0xfffff000);
12200 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
12204 case BFD_RELOC_ARM_OFFSET_IMM
:
12210 if (validate_offset_imm (value
, 0) == FAIL
)
12212 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12213 _("bad immediate value for offset (%ld)"),
12218 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12219 newval
&= 0xff7ff000;
12220 newval
|= value
| (sign
? INDEX_UP
: 0);
12221 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12224 case BFD_RELOC_ARM_OFFSET_IMM8
:
12225 case BFD_RELOC_ARM_HWLITERAL
:
12231 if (validate_offset_imm (value
, 1) == FAIL
)
12233 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
12234 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12235 _("invalid literal constant: pool needs to be closer"));
12237 as_bad (_("bad immediate value for half-word offset (%ld)"),
12242 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12243 newval
&= 0xff7ff0f0;
12244 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
12245 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12248 case BFD_RELOC_ARM_LITERAL
:
12254 if (validate_offset_imm (value
, 0) == FAIL
)
12256 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12257 _("invalid literal constant: pool needs to be closer"));
12261 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12262 newval
&= 0xff7ff000;
12263 newval
|= value
| (sign
? INDEX_UP
: 0);
12264 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12267 case BFD_RELOC_ARM_SHIFT_IMM
:
12268 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12269 if (((unsigned long) value
) > 32
12271 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
12273 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12274 _("shift expression is too large"));
12279 /* Shifts of zero must be done as lsl. */
12281 else if (value
== 32)
12283 newval
&= 0xfffff07f;
12284 newval
|= (value
& 0x1f) << 7;
12285 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12288 case BFD_RELOC_ARM_SWI
:
12289 if (arm_data
->thumb_mode
)
12291 if (((unsigned long) value
) > 0xff)
12292 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12293 _("invalid swi expression"));
12294 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
12296 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12300 if (((unsigned long) value
) > 0x00ffffff)
12301 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12302 _("invalid swi expression"));
12303 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
12305 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12309 case BFD_RELOC_ARM_MULTI
:
12310 if (((unsigned long) value
) > 0xffff)
12311 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12312 _("invalid expression in load/store multiple"));
12313 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
12314 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12317 case BFD_RELOC_ARM_PCREL_BRANCH
:
12318 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12320 /* Sign-extend a 24-bit number. */
12321 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12325 value
= fixP
->fx_offset
;
12328 /* We are going to store value (shifted right by two) in the
12329 instruction, in a 24 bit, signed field. Thus we need to check
12330 that none of the top 8 bits of the shifted value (top 7 bits of
12331 the unshifted, unsigned value) are set, or that they are all set. */
12332 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
12333 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
12336 /* Normally we would be stuck at this point, since we cannot store
12337 the absolute address that is the destination of the branch in the
12338 24 bits of the branch instruction. If however, we happen to know
12339 that the destination of the branch is in the same section as the
12340 branch instruction itself, then we can compute the relocation for
12341 ourselves and not have to bother the linker with it.
12343 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12344 because I have not worked out how to do this for OBJ_COFF or
12347 && fixP
->fx_addsy
!= NULL
12348 && S_IS_DEFINED (fixP
->fx_addsy
)
12349 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
12351 /* Get pc relative value to go into the branch. */
12354 /* Permit a backward branch provided that enough bits
12355 are set. Allow a forwards branch, provided that
12356 enough bits are clear. */
12357 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
12358 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
12362 if (! fixP
->fx_done
)
12364 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12365 _("GAS can't handle same-section branch dest >= 0x04000000"));
12369 value
+= SEXT24 (newval
);
12371 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
12372 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
12373 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12374 _("out of range branch"));
12376 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
12377 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12380 case BFD_RELOC_ARM_PCREL_BLX
:
12383 newval
= md_chars_to_number (buf
, INSN_SIZE
);
12387 value
= fixP
->fx_offset
;
12389 hbit
= (value
>> 1) & 1;
12390 value
= (value
>> 2) & 0x00ffffff;
12391 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
12392 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
12393 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12397 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
12398 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12400 addressT diff
= (newval
& 0xff) << 1;
12405 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
12406 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12407 _("branch out of range"));
12408 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
12410 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12413 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
12414 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12416 addressT diff
= (newval
& 0x7ff) << 1;
12421 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
12422 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12423 _("branch out of range"));
12424 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
12426 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12429 case BFD_RELOC_THUMB_PCREL_BLX
:
12430 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12435 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12436 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
12437 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
12438 if (diff
& 0x400000)
12441 value
= fixP
->fx_offset
;
12445 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
12446 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12447 _("branch with link out of range"));
12449 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
12450 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
12451 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
12452 /* For a BLX instruction, make sure that the relocation is rounded up
12453 to a word boundary. This follows the semantics of the instruction
12454 which specifies that bit 1 of the target address will come from bit
12455 1 of the base address. */
12456 newval2
= (newval2
+ 1) & ~ 1;
12457 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12458 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
12463 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12464 md_number_to_chars (buf
, value
, 1);
12466 else if (!target_oabi
)
12468 value
= fixP
->fx_offset
;
12469 md_number_to_chars (buf
, value
, 1);
12475 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12476 md_number_to_chars (buf
, value
, 2);
12478 else if (!target_oabi
)
12480 value
= fixP
->fx_offset
;
12481 md_number_to_chars (buf
, value
, 2);
12487 case BFD_RELOC_ARM_GOT32
:
12488 case BFD_RELOC_ARM_GOTOFF
:
12489 md_number_to_chars (buf
, 0, 4);
12493 case BFD_RELOC_RVA
:
12495 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
12496 md_number_to_chars (buf
, value
, 4);
12498 else if (!target_oabi
)
12500 value
= fixP
->fx_offset
;
12501 md_number_to_chars (buf
, value
, 4);
12507 case BFD_RELOC_ARM_PLT32
:
12508 /* It appears the instruction is fully prepared at this point. */
12512 case BFD_RELOC_ARM_CP_OFF_IMM
:
12514 if (value
< -1023 || value
> 1023 || (value
& 3))
12515 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12516 _("illegal value for co-processor offset"));
12519 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12520 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
12521 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12524 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
12526 if (value
< -255 || value
> 255)
12527 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12528 _("Illegal value for co-processor offset"));
12531 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
12532 newval
|= value
| (sign
? INDEX_UP
: 0);
12533 md_number_to_chars (buf
, newval
, INSN_SIZE
);
12536 case BFD_RELOC_ARM_THUMB_OFFSET
:
12537 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12538 /* Exactly what ranges, and where the offset is inserted depends
12539 on the type of instruction, we can establish this from the
12541 switch (newval
>> 12)
12543 case 4: /* PC load. */
12544 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12545 forced to zero for these loads, so we will need to round
12546 up the offset if the instruction address is not word
12547 aligned (since the final address produced must be, and
12548 we can only describe word-aligned immediate offsets). */
12550 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
12551 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12552 _("invalid offset, target not word aligned (0x%08X)"),
12553 (unsigned int) (fixP
->fx_frag
->fr_address
12554 + fixP
->fx_where
+ value
));
12556 if ((value
+ 2) & ~0x3fe)
12557 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12558 _("invalid offset, value too big (0x%08lX)"),
12561 /* Round up, since pc will be rounded down. */
12562 newval
|= (value
+ 2) >> 2;
12565 case 9: /* SP load/store. */
12566 if (value
& ~0x3fc)
12567 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12568 _("invalid offset, value too big (0x%08lX)"),
12570 newval
|= value
>> 2;
12573 case 6: /* Word load/store. */
12575 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12576 _("invalid offset, value too big (0x%08lX)"),
12578 newval
|= value
<< 4; /* 6 - 2. */
12581 case 7: /* Byte load/store. */
12583 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12584 _("invalid offset, value too big (0x%08lX)"),
12586 newval
|= value
<< 6;
12589 case 8: /* Halfword load/store. */
12591 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12592 _("invalid offset, value too big (0x%08lX)"),
12594 newval
|= value
<< 5; /* 6 - 1. */
12598 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12599 "Unable to process relocation for thumb opcode: %lx",
12600 (unsigned long) newval
);
12603 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12606 case BFD_RELOC_ARM_THUMB_ADD
:
12607 /* This is a complicated relocation, since we use it for all of
12608 the following immediate relocations:
12612 9bit ADD/SUB SP word-aligned
12613 10bit ADD PC/SP word-aligned
12615 The type of instruction being processed is encoded in the
12622 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12624 int rd
= (newval
>> 4) & 0xf;
12625 int rs
= newval
& 0xf;
12626 int subtract
= newval
& 0x8000;
12630 if (value
& ~0x1fc)
12631 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12632 _("invalid immediate for stack address calculation"));
12633 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
12634 newval
|= value
>> 2;
12636 else if (rs
== REG_PC
|| rs
== REG_SP
)
12640 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12641 _("invalid immediate for address calculation (value = 0x%08lX)"),
12642 (unsigned long) value
);
12643 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
12645 newval
|= value
>> 2;
12650 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12651 _("invalid 8bit immediate"));
12652 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
12653 newval
|= (rd
<< 8) | value
;
12658 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12659 _("invalid 3bit immediate"));
12660 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
12661 newval
|= rd
| (rs
<< 3) | (value
<< 6);
12664 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12667 case BFD_RELOC_ARM_THUMB_IMM
:
12668 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
12669 switch (newval
>> 11)
12671 case 0x04: /* 8bit immediate MOV. */
12672 case 0x05: /* 8bit immediate CMP. */
12673 if (value
< 0 || value
> 255)
12674 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12675 _("invalid immediate: %ld is too large"),
12683 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12686 case BFD_RELOC_ARM_THUMB_SHIFT
:
12687 /* 5bit shift value (0..31). */
12688 if (value
< 0 || value
> 31)
12689 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12690 _("illegal Thumb shift value: %ld"), (long) value
);
12691 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
12692 newval
|= value
<< 6;
12693 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
12696 case BFD_RELOC_VTABLE_INHERIT
:
12697 case BFD_RELOC_VTABLE_ENTRY
:
12701 case BFD_RELOC_NONE
:
12703 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
12704 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
12708 /* Translate internal representation of relocation info to BFD target
12712 tc_gen_reloc (section
, fixp
)
12713 asection
* section ATTRIBUTE_UNUSED
;
12717 bfd_reloc_code_real_type code
;
12719 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
12721 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
12722 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
12723 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
12725 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
12727 if (fixp
->fx_pcrel
== 0)
12728 reloc
->addend
= fixp
->fx_offset
;
12730 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12731 #else /* OBJ_ELF */
12732 reloc
->addend
= fixp
->fx_offset
;
12735 switch (fixp
->fx_r_type
)
12738 if (fixp
->fx_pcrel
)
12740 code
= BFD_RELOC_8_PCREL
;
12745 if (fixp
->fx_pcrel
)
12747 code
= BFD_RELOC_16_PCREL
;
12752 if (fixp
->fx_pcrel
)
12754 code
= BFD_RELOC_32_PCREL
;
12758 case BFD_RELOC_ARM_PCREL_BRANCH
:
12759 case BFD_RELOC_ARM_PCREL_BLX
:
12760 case BFD_RELOC_RVA
:
12761 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
12762 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
12763 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
12764 case BFD_RELOC_THUMB_PCREL_BLX
:
12765 case BFD_RELOC_VTABLE_ENTRY
:
12766 case BFD_RELOC_VTABLE_INHERIT
:
12767 code
= fixp
->fx_r_type
;
12770 case BFD_RELOC_ARM_LITERAL
:
12771 case BFD_RELOC_ARM_HWLITERAL
:
12772 /* If this is called then the a literal has
12773 been referenced across a section boundary. */
12774 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12775 _("literal referenced across section boundary"));
12779 case BFD_RELOC_ARM_GOT32
:
12780 case BFD_RELOC_ARM_GOTOFF
:
12781 case BFD_RELOC_ARM_PLT32
:
12782 code
= fixp
->fx_r_type
;
12786 case BFD_RELOC_ARM_IMMEDIATE
:
12787 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12788 _("internal relocation (type: IMMEDIATE) not fixed up"));
12791 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
12792 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12793 _("ADRL used for a symbol not defined in the same file"));
12796 case BFD_RELOC_ARM_OFFSET_IMM
:
12797 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12798 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12805 switch (fixp
->fx_r_type
)
12807 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
12808 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
12809 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
12810 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
12811 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
12812 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
12813 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
12814 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
12815 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
12816 default: type
= _("<unknown>"); break;
12818 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12819 _("cannot represent %s relocation in this object file format"),
12826 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
12828 && fixp
->fx_addsy
== GOT_symbol
)
12830 code
= BFD_RELOC_ARM_GOTPC
;
12831 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
12835 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
12837 if (reloc
->howto
== NULL
)
12839 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
12840 _("cannot represent %s relocation in this object file format"),
12841 bfd_get_reloc_code_name (code
));
12845 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12846 vtable entry to be used in the relocation's section offset. */
12847 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12848 reloc
->address
= fixp
->fx_offset
;
12854 md_estimate_size_before_relax (fragP
, segtype
)
12855 fragS
* fragP ATTRIBUTE_UNUSED
;
12856 segT segtype ATTRIBUTE_UNUSED
;
12858 as_fatal (_("md_estimate_size_before_relax\n"));
12870 as_bad ("%s -- `%s'", inst
.error
, str
);
12874 to
= frag_more (inst
.size
);
12876 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
12878 assert (inst
.size
== (2 * THUMB_SIZE
));
12879 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
12880 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
12882 else if (inst
.size
> INSN_SIZE
)
12884 assert (inst
.size
== (2 * INSN_SIZE
));
12885 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
12886 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
12889 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
12891 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
12892 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
12893 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
12897 dwarf2_emit_insn (inst
.size
);
12909 /* Align the instruction.
12910 This may not be the right thing to do but ... */
12915 /* Align the previous label if needed. */
12916 if (last_label_seen
!= NULL
)
12918 symbol_set_frag (last_label_seen
, frag_now
);
12919 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
12920 S_SET_SEGMENT (last_label_seen
, now_seg
);
12923 memset (&inst
, '\0', sizeof (inst
));
12924 inst
.reloc
.type
= BFD_RELOC_NONE
;
12926 skip_whitespace (str
);
12928 /* Scan up to the end of the op-code, which must end in white space or
12930 for (start
= p
= str
; *p
!= '\0'; p
++)
12936 as_bad (_("no operator -- statement `%s'\n"), str
);
12942 const struct thumb_opcode
* opcode
;
12946 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
12951 /* Check that this instruction is supported for this CPU. */
12952 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
12954 as_bad (_("selected processor does not support `%s'"), str
);
12958 mapping_state (MAP_THUMB
);
12959 inst
.instruction
= opcode
->value
;
12960 inst
.size
= opcode
->size
;
12961 (*opcode
->parms
) (p
);
12968 const struct asm_opcode
* opcode
;
12972 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
12977 /* Check that this instruction is supported for this CPU. */
12978 if ((opcode
->variant
& cpu_variant
) == 0)
12980 as_bad (_("selected processor does not support `%s'"), str
);
12984 mapping_state (MAP_ARM
);
12985 inst
.instruction
= opcode
->value
;
12986 inst
.size
= INSN_SIZE
;
12987 (*opcode
->parms
) (p
);
12993 /* It wasn't an instruction, but it might be a register alias of the form
12995 if (create_register_alias (str
, p
))
12998 as_bad (_("bad instruction `%s'"), start
);
13002 Invocation line includes a switch not recognized by the base assembler.
13003 See if it's a processor-specific option.
13005 This routine is somewhat complicated by the need for backwards
13006 compatibility (since older releases of gcc can't be changed).
13007 The new options try to make the interface as compatible as
13010 New options (supported) are:
13012 -mcpu=<cpu name> Assemble for selected processor
13013 -march=<architecture name> Assemble for selected architecture
13014 -mfpu=<fpu architecture> Assemble for selected FPU.
13015 -EB/-mbig-endian Big-endian
13016 -EL/-mlittle-endian Little-endian
13017 -k Generate PIC code
13018 -mthumb Start in Thumb mode
13019 -mthumb-interwork Code supports ARM/Thumb interworking
13021 For now we will also provide support for:
13023 -mapcs-32 32-bit Program counter
13024 -mapcs-26 26-bit Program counter
13025 -macps-float Floats passed in FP registers
13026 -mapcs-reentrant Reentrant code
13028 (sometime these will probably be replaced with -mapcs=<list of options>
13029 and -matpcs=<list of options>)
13031 The remaining options are only supported for back-wards compatibility.
13032 Cpu variants, the arm part is optional:
13033 -m[arm]1 Currently not supported.
13034 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
13035 -m[arm]3 Arm 3 processor
13036 -m[arm]6[xx], Arm 6 processors
13037 -m[arm]7[xx][t][[d]m] Arm 7 processors
13038 -m[arm]8[10] Arm 8 processors
13039 -m[arm]9[20][tdmi] Arm 9 processors
13040 -mstrongarm[110[0]] StrongARM processors
13041 -mxscale XScale processors
13042 -m[arm]v[2345[t[e]]] Arm architectures
13043 -mall All (except the ARM1)
13045 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
13046 -mfpe-old (No float load/store multiples)
13047 -mvfpxd VFP Single precision
13049 -mno-fpu Disable all floating point instructions
13051 The following CPU names are recognized:
13052 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13053 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13054 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13055 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13056 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13057 arm10t arm10e, arm1020t, arm1020e, arm10200e,
13058 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13062 const char * md_shortopts
= "m:k";
13064 #ifdef ARM_BI_ENDIAN
13065 #define OPTION_EB (OPTION_MD_BASE + 0)
13066 #define OPTION_EL (OPTION_MD_BASE + 1)
13068 #if TARGET_BYTES_BIG_ENDIAN
13069 #define OPTION_EB (OPTION_MD_BASE + 0)
13071 #define OPTION_EL (OPTION_MD_BASE + 1)
13075 struct option md_longopts
[] =
13078 {"EB", no_argument
, NULL
, OPTION_EB
},
13081 {"EL", no_argument
, NULL
, OPTION_EL
},
13083 {NULL
, no_argument
, NULL
, 0}
13086 size_t md_longopts_size
= sizeof (md_longopts
);
13088 struct arm_option_table
13090 char *option
; /* Option name to match. */
13091 char *help
; /* Help information. */
13092 int *var
; /* Variable to change. */
13093 int value
; /* What to change it to. */
13094 char *deprecated
; /* If non-null, print this message. */
13097 struct arm_option_table arm_opts
[] =
13099 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
13100 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
13101 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13102 &support_interwork
, 1, NULL
},
13103 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
13104 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
13105 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
13106 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
13108 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
13109 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
13110 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
13111 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
13114 /* These are recognized by the assembler, but have no affect on code. */
13115 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
13116 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
13118 /* DON'T add any new processors to this list -- we want the whole list
13119 to go away... Add them to the processors table instead. */
13120 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13121 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
13122 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13123 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
13124 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13125 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
13126 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13127 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
13128 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13129 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
13130 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13131 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
13132 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13133 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
13134 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13135 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
13136 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13137 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
13138 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13139 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
13140 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13141 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
13142 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13143 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
13144 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13145 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
13146 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13147 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
13148 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13149 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
13150 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13151 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
13152 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13153 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
13154 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13155 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
13156 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13157 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
13158 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13159 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
13160 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13161 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
13162 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13163 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
13164 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13165 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
13166 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13167 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13168 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13169 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
13170 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13171 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
13172 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13173 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
13174 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13175 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
13176 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13177 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
13178 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13179 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
13180 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13181 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
13182 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13183 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
13184 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13185 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
13186 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13187 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
13188 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
13189 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13190 N_("use -mcpu=strongarm110")},
13191 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13192 N_("use -mcpu=strongarm1100")},
13193 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
13194 N_("use -mcpu=strongarm1110")},
13195 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
13196 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
13197 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
13199 /* Architecture variants -- don't add any more to this list either. */
13200 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13201 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
13202 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13203 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
13204 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13205 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
13206 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13207 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
13208 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13209 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
13210 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13211 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
13212 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13213 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
13214 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13215 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
13216 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13217 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
13219 /* Floating point variants -- don't add any more to this list either. */
13220 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
13221 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
13222 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
13223 {"mno-fpu", NULL
, &legacy_fpu
, 0,
13224 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13226 {NULL
, NULL
, NULL
, 0, NULL
}
13229 struct arm_cpu_option_table
13233 /* For some CPUs we assume an FPU unless the user explicitly sets
13238 /* This list should, at a minimum, contain all the cpu names
13239 recognized by GCC. */
13240 static struct arm_cpu_option_table arm_cpus
[] =
13242 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13243 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13244 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13245 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13246 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13247 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13248 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13249 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13250 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13251 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13252 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13253 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13254 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13255 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13256 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13257 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13258 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13259 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13260 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13261 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13262 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13263 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13264 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13265 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13266 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13267 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13268 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13269 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13270 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13271 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13272 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13273 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13274 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13275 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13276 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13277 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13278 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13279 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13280 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13281 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13282 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13283 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13284 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13285 /* For V5 or later processors we default to using VFP; but the user
13286 should really set the FPU type explicitly. */
13287 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13288 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13289 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
13290 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13291 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13292 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
13293 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13294 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13295 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13296 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13297 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
13298 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
13299 {"arm1136js", ARM_ARCH_V6
, FPU_NONE
},
13300 {"arm1136jfs", ARM_ARCH_V6
, FPU_ARCH_VFP_V2
},
13301 /* ??? XSCALE is really an architecture. */
13302 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13303 /* ??? iwmmxt is not a processor. */
13304 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
13305 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
13307 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_ARCH_MAVERICK
},
13311 struct arm_arch_option_table
13318 /* This list should, at a minimum, contain all the architecture names
13319 recognized by GCC. */
13320 static struct arm_arch_option_table arm_archs
[] =
13322 {"all", ARM_ANY
, FPU_ARCH_FPA
},
13323 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
13324 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
13325 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13326 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
13327 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
13328 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
13329 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
13330 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
13331 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
13332 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
13333 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
13334 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
13335 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
13336 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
13337 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
13338 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
13339 {"armv6", ARM_ARCH_V6
, FPU_ARCH_VFP
},
13340 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
13341 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
13345 /* ISA extensions in the co-processor space. */
13346 struct arm_arch_extension_table
13352 static struct arm_arch_extension_table arm_extensions
[] =
13354 {"maverick", ARM_CEXT_MAVERICK
},
13355 {"xscale", ARM_CEXT_XSCALE
},
13356 {"iwmmxt", ARM_CEXT_IWMMXT
},
13360 struct arm_fpu_option_table
13366 /* This list should, at a minimum, contain all the fpu names
13367 recognized by GCC. */
13368 static struct arm_fpu_option_table arm_fpus
[] =
13370 {"softfpa", FPU_NONE
},
13371 {"fpe", FPU_ARCH_FPE
},
13372 {"fpe2", FPU_ARCH_FPE
},
13373 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
13374 {"fpa", FPU_ARCH_FPA
},
13375 {"fpa10", FPU_ARCH_FPA
},
13376 {"fpa11", FPU_ARCH_FPA
},
13377 {"arm7500fe", FPU_ARCH_FPA
},
13378 {"softvfp", FPU_ARCH_VFP
},
13379 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
13380 {"vfp", FPU_ARCH_VFP_V2
},
13381 {"vfp9", FPU_ARCH_VFP_V2
},
13382 {"vfp10", FPU_ARCH_VFP_V2
},
13383 {"vfp10-r0", FPU_ARCH_VFP_V1
},
13384 {"vfpxd", FPU_ARCH_VFP_V1xD
},
13385 {"arm1020t", FPU_ARCH_VFP_V1
},
13386 {"arm1020e", FPU_ARCH_VFP_V2
},
13387 {"arm1136jfs", FPU_ARCH_VFP_V2
},
13388 {"maverick", FPU_ARCH_MAVERICK
},
13392 struct arm_float_abi_option_table
13398 static struct arm_float_abi_option_table arm_float_abis
[] =
13400 {"hard", ARM_FLOAT_ABI_HARD
},
13401 {"softfp", ARM_FLOAT_ABI_SOFTFP
},
13402 {"soft", ARM_FLOAT_ABI_SOFT
},
13406 struct arm_long_option_table
13408 char *option
; /* Substring to match. */
13409 char *help
; /* Help information. */
13410 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
13411 char *deprecated
; /* If non-null, print this message. */
13415 arm_parse_extension (str
, opt_p
)
13419 while (str
!= NULL
&& *str
!= 0)
13421 struct arm_arch_extension_table
*opt
;
13427 as_bad (_("invalid architectural extension"));
13432 ext
= strchr (str
, '+');
13435 optlen
= ext
- str
;
13437 optlen
= strlen (str
);
13441 as_bad (_("missing architectural extension"));
13445 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
13446 if (strncmp (opt
->name
, str
, optlen
) == 0)
13448 *opt_p
|= opt
->value
;
13452 if (opt
->name
== NULL
)
13454 as_bad (_("unknown architectural extnsion `%s'"), str
);
13465 arm_parse_cpu (str
)
13468 struct arm_cpu_option_table
*opt
;
13469 char *ext
= strchr (str
, '+');
13473 optlen
= ext
- str
;
13475 optlen
= strlen (str
);
13479 as_bad (_("missing cpu name `%s'"), str
);
13483 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
13484 if (strncmp (opt
->name
, str
, optlen
) == 0)
13486 mcpu_cpu_opt
= opt
->value
;
13487 mcpu_fpu_opt
= opt
->default_fpu
;
13490 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
13495 as_bad (_("unknown cpu `%s'"), str
);
13500 arm_parse_arch (str
)
13503 struct arm_arch_option_table
*opt
;
13504 char *ext
= strchr (str
, '+');
13508 optlen
= ext
- str
;
13510 optlen
= strlen (str
);
13514 as_bad (_("missing architecture name `%s'"), str
);
13519 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
13520 if (strcmp (opt
->name
, str
) == 0)
13522 march_cpu_opt
= opt
->value
;
13523 march_fpu_opt
= opt
->default_fpu
;
13526 return arm_parse_extension (ext
, &march_cpu_opt
);
13531 as_bad (_("unknown architecture `%s'\n"), str
);
13536 arm_parse_fpu (str
)
13539 struct arm_fpu_option_table
*opt
;
13541 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
13542 if (strcmp (opt
->name
, str
) == 0)
13544 mfpu_opt
= opt
->value
;
13548 as_bad (_("unknown floating point format `%s'\n"), str
);
13553 arm_parse_float_abi (str
)
13556 struct arm_float_abi_option_table
*opt
;
13558 for (opt
= arm_float_abis
; opt
->name
!= NULL
; opt
++)
13559 if (strcmp (opt
->name
, str
) == 0)
13561 mfloat_abi_opt
= opt
->value
;
13565 as_bad (_("unknown floating point abi `%s'\n"), str
);
13569 struct arm_long_option_table arm_long_opts
[] =
13571 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
13572 arm_parse_cpu
, NULL
},
13573 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
13574 arm_parse_arch
, NULL
},
13575 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
13576 arm_parse_fpu
, NULL
},
13577 {"mfloat-abi=", N_("<abi>\t assemble for floating point ABI <abi>"),
13578 arm_parse_float_abi
, NULL
},
13579 {NULL
, NULL
, 0, NULL
}
13583 md_parse_option (c
, arg
)
13587 struct arm_option_table
*opt
;
13588 struct arm_long_option_table
*lopt
;
13594 target_big_endian
= 1;
13600 target_big_endian
= 0;
13605 /* Listing option. Just ignore these, we don't support additional
13610 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13612 if (c
== opt
->option
[0]
13613 && ((arg
== NULL
&& opt
->option
[1] == 0)
13614 || strcmp (arg
, opt
->option
+ 1) == 0))
13616 #if WARN_DEPRECATED
13617 /* If the option is deprecated, tell the user. */
13618 if (opt
->deprecated
!= NULL
)
13619 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
13620 arg
? arg
: "", _(opt
->deprecated
));
13623 if (opt
->var
!= NULL
)
13624 *opt
->var
= opt
->value
;
13630 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13632 /* These options are expected to have an argument. */
13633 if (c
== lopt
->option
[0]
13635 && strncmp (arg
, lopt
->option
+ 1,
13636 strlen (lopt
->option
+ 1)) == 0)
13638 #if WARN_DEPRECATED
13639 /* If the option is deprecated, tell the user. */
13640 if (lopt
->deprecated
!= NULL
)
13641 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
13642 _(lopt
->deprecated
));
13645 /* Call the sup-option parser. */
13646 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
13650 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
13661 struct arm_option_table
*opt
;
13662 struct arm_long_option_table
*lopt
;
13664 fprintf (fp
, _(" ARM-specific assembler options:\n"));
13666 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
13667 if (opt
->help
!= NULL
)
13668 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
13670 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
13671 if (lopt
->help
!= NULL
)
13672 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
13676 -EB assemble code for a big-endian cpu\n"));
13681 -EL assemble code for a little-endian cpu\n"));
13685 /* We need to be able to fix up arbitrary expressions in some statements.
13686 This is so that we can handle symbols that are an arbitrary distance from
13687 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13688 which returns part of an address in a form which will be valid for
13689 a data instruction. We do this by pushing the expression into a symbol
13690 in the expr_section, and creating a fix for that. */
13693 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
13702 arm_fix_data
* arm_data
;
13710 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
13714 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
13719 /* Mark whether the fix is to a THUMB instruction, or an ARM
13721 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
13722 new_fix
->tc_fix_data
= (PTR
) arm_data
;
13723 arm_data
->thumb_mode
= thumb_mode
;
13726 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
13729 cons_fix_new_arm (frag
, where
, size
, exp
)
13735 bfd_reloc_code_real_type type
;
13739 FIXME: @@ Should look at CPU word size. */
13743 type
= BFD_RELOC_8
;
13746 type
= BFD_RELOC_16
;
13750 type
= BFD_RELOC_32
;
13753 type
= BFD_RELOC_64
;
13757 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
13760 /* A good place to do this, although this was probably not intended
13761 for this kind of use. We need to dump the literal pool before
13762 references are made to a null symbol pointer. */
13767 literal_pool
* pool
;
13769 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
13771 /* Put it at the end of the relevent section. */
13772 subseg_set (pool
->section
, pool
->sub_section
);
13778 arm_start_line_hook ()
13780 last_label_seen
= NULL
;
13784 arm_frob_label (sym
)
13787 last_label_seen
= sym
;
13789 ARM_SET_THUMB (sym
, thumb_mode
);
13791 #if defined OBJ_COFF || defined OBJ_ELF
13792 ARM_SET_INTERWORK (sym
, support_interwork
);
13795 /* Note - do not allow local symbols (.Lxxx) to be labeled
13796 as Thumb functions. This is because these labels, whilst
13797 they exist inside Thumb code, are not the entry points for
13798 possible ARM->Thumb calls. Also, these labels can be used
13799 as part of a computed goto or switch statement. eg gcc
13800 can generate code that looks like this:
13802 ldr r2, [pc, .Laaa]
13812 The first instruction loads the address of the jump table.
13813 The second instruction converts a table index into a byte offset.
13814 The third instruction gets the jump address out of the table.
13815 The fourth instruction performs the jump.
13817 If the address stored at .Laaa is that of a symbol which has the
13818 Thumb_Func bit set, then the linker will arrange for this address
13819 to have the bottom bit set, which in turn would mean that the
13820 address computation performed by the third instruction would end
13821 up with the bottom bit set. Since the ARM is capable of unaligned
13822 word loads, the instruction would then load the incorrect address
13823 out of the jump table, and chaos would ensue. */
13824 if (label_is_thumb_function_name
13825 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
13826 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
13828 /* When the address of a Thumb function is taken the bottom
13829 bit of that address should be set. This will allow
13830 interworking between Arm and Thumb functions to work
13833 THUMB_SET_FUNC (sym
, 1);
13835 label_is_thumb_function_name
= FALSE
;
13839 /* Adjust the symbol table. This marks Thumb symbols as distinct from
13843 arm_adjust_symtab ()
13848 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13850 if (ARM_IS_THUMB (sym
))
13852 if (THUMB_IS_FUNC (sym
))
13854 /* Mark the symbol as a Thumb function. */
13855 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
13856 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
13857 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
13859 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
13860 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
13862 as_bad (_("%s: unexpected function type: %d"),
13863 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
13865 else switch (S_GET_STORAGE_CLASS (sym
))
13868 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
13871 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
13874 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
13882 if (ARM_IS_INTERWORK (sym
))
13883 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
13890 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
13892 if (ARM_IS_THUMB (sym
))
13894 elf_symbol_type
* elf_sym
;
13896 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
13897 bind
= ELF_ST_BIND (elf_sym
);
13899 /* If it's a .thumb_func, declare it as so,
13900 otherwise tag label as .code 16. */
13901 if (THUMB_IS_FUNC (sym
))
13902 elf_sym
->internal_elf_sym
.st_info
=
13903 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
13905 elf_sym
->internal_elf_sym
.st_info
=
13906 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
13913 arm_data_in_code ()
13915 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
13917 *input_line_pointer
= '/';
13918 input_line_pointer
+= 5;
13919 *input_line_pointer
= 0;
13927 arm_canonicalize_symbol_name (name
)
13932 if (thumb_mode
&& (len
= strlen (name
)) > 5
13933 && streq (name
+ len
- 5, "/data"))
13934 *(name
+ len
- 5) = 0;
13939 #if defined OBJ_COFF || defined OBJ_ELF
13941 arm_validate_fix (fixP
)
13944 /* If the destination of the branch is a defined symbol which does not have
13945 the THUMB_FUNC attribute, then we must be calling a function which has
13946 the (interfacearm) attribute. We look for the Thumb entry point to that
13947 function and change the branch to refer to that function instead. */
13948 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
13949 && fixP
->fx_addsy
!= NULL
13950 && S_IS_DEFINED (fixP
->fx_addsy
)
13951 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
13953 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
13959 arm_force_relocation (fixp
)
13962 #if defined (OBJ_COFF) && defined (TE_PE)
13963 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
13967 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
13968 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
13969 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
13970 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
13974 /* Resolve these relocations even if the symbol is extern or weak. */
13975 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
13976 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
13977 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
13980 return generic_force_reloc (fixp
);
13984 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
13985 local labels from being added to the output symbol table when they
13986 are used with the ADRL pseudo op. The ADRL relocation should always
13987 be resolved before the binbary is emitted, so it is safe to say that
13988 it is adjustable. */
13991 arm_fix_adjustable (fixP
)
13994 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
14001 /* Relocations against Thumb function names must be left unadjusted,
14002 so that the linker can use this information to correctly set the
14003 bottom bit of their addresses. The MIPS version of this function
14004 also prevents relocations that are mips-16 specific, but I do not
14005 know why it does this.
14008 There is one other problem that ought to be addressed here, but
14009 which currently is not: Taking the address of a label (rather
14010 than a function) and then later jumping to that address. Such
14011 addresses also ought to have their bottom bit set (assuming that
14012 they reside in Thumb code), but at the moment they will not. */
14015 arm_fix_adjustable (fixP
)
14018 if (fixP
->fx_addsy
== NULL
)
14021 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
14022 && fixP
->fx_subsy
== NULL
)
14025 /* We need the symbol name for the VTABLE entries. */
14026 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
14027 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
14030 /* Don't allow symbols to be discarded on GOT related relocs. */
14031 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
14032 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
14033 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
14040 elf32_arm_target_format ()
14042 if (target_big_endian
)
14045 return "elf32-bigarm-oabi";
14047 return "elf32-bigarm";
14052 return "elf32-littlearm-oabi";
14054 return "elf32-littlearm";
14059 armelf_frob_symbol (symp
, puntp
)
14063 elf_frob_symbol (symp
, puntp
);
14066 static bfd_reloc_code_real_type
14076 bfd_reloc_code_real_type reloc
;
14080 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14081 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
14082 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
14083 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14084 branch instructions generated by GCC for PLT relocs. */
14085 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
14086 { NULL
, 0, BFD_RELOC_UNUSED
}
14090 for (i
= 0, ip
= input_line_pointer
;
14091 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
14093 id
[i
] = TOLOWER (*ip
);
14095 for (i
= 0; reloc_map
[i
].str
; i
++)
14096 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
14099 input_line_pointer
+= reloc_map
[i
].len
;
14101 return reloc_map
[i
].reloc
;
14105 s_arm_elf_cons (nbytes
)
14110 #ifdef md_flush_pending_output
14111 md_flush_pending_output ();
14114 if (is_it_end_of_statement ())
14116 demand_empty_rest_of_line ();
14120 #ifdef md_cons_align
14121 md_cons_align (nbytes
);
14124 mapping_state (MAP_DATA
);
14127 bfd_reloc_code_real_type reloc
;
14129 expression (& exp
);
14131 if (exp
.X_op
== O_symbol
14132 && * input_line_pointer
== '('
14133 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
14135 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
14136 int size
= bfd_get_reloc_size (howto
);
14139 as_bad ("%s relocations do not fit in %d bytes",
14140 howto
->name
, nbytes
);
14143 register char *p
= frag_more ((int) nbytes
);
14144 int offset
= nbytes
- size
;
14146 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
14151 emit_expr (&exp
, (unsigned int) nbytes
);
14153 while (*input_line_pointer
++ == ',');
14155 /* Put terminator back into stream. */
14156 input_line_pointer
--;
14157 demand_empty_rest_of_line ();
14160 #endif /* OBJ_ELF */
14162 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
14163 of an rs_align_code fragment. */
14166 arm_handle_align (fragP
)
14169 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14170 static char const thumb_noop
[2] = { 0xc0, 0x46 };
14171 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14172 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
14174 int bytes
, fix
, noop_size
;
14178 if (fragP
->fr_type
!= rs_align_code
)
14181 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
14182 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
14185 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14186 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
14188 if (fragP
->tc_frag_data
)
14190 if (target_big_endian
)
14191 noop
= thumb_bigend_noop
;
14194 noop_size
= sizeof (thumb_noop
);
14198 if (target_big_endian
)
14199 noop
= arm_bigend_noop
;
14202 noop_size
= sizeof (arm_noop
);
14205 if (bytes
& (noop_size
- 1))
14207 fix
= bytes
& (noop_size
- 1);
14208 memset (p
, 0, fix
);
14213 while (bytes
>= noop_size
)
14215 memcpy (p
, noop
, noop_size
);
14217 bytes
-= noop_size
;
14221 fragP
->fr_fix
+= fix
;
14222 fragP
->fr_var
= noop_size
;
14225 /* Called from md_do_align. Used to create an alignment
14226 frag in a code section. */
14229 arm_frag_align_code (n
, max
)
14235 /* We assume that there will never be a requirement
14236 to support alignments greater than 32 bytes. */
14237 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
14238 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14240 p
= frag_var (rs_align_code
,
14241 MAX_MEM_FOR_RS_ALIGN_CODE
,
14243 (relax_substateT
) max
,
14251 /* Perform target specific initialisation of a frag. */
14254 arm_init_frag (fragP
)
14257 /* Record whether this frag is in an ARM or a THUMB area. */
14258 fragP
->tc_frag_data
= thumb_mode
;