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. */
59 /* Co-processor space extensions. */
60 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
61 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 #define ARM_CEXT_IWMMXT 0x00200000 /* Intel Wireless MMX technology coprocessor. */
64 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
65 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
67 three more to cover cores prior to ARM6. Finally, there are cores which
68 implement further extensions in the co-processor space. */
69 #define ARM_ARCH_V1 ARM_EXT_V1
70 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
71 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
72 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
73 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
75 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
79 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
86 /* Processors with specific extensions in the co-processor space. */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
90 /* Some useful combinations: */
91 #define ARM_ANY 0x0000ffff /* Any basic core. */
92 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
93 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
94 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
97 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
98 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
99 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
100 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
101 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
102 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
105 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
108 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
113 /* Types of processor to assemble for. */
114 #define ARM_1 ARM_ARCH_V1
115 #define ARM_2 ARM_ARCH_V2
116 #define ARM_3 ARM_ARCH_V2S
117 #define ARM_250 ARM_ARCH_V2S
118 #define ARM_6 ARM_ARCH_V3
119 #define ARM_7 ARM_ARCH_V3
120 #define ARM_8 ARM_ARCH_V4
121 #define ARM_9 ARM_ARCH_V4T
122 #define ARM_STRONG ARM_ARCH_V4
123 #define ARM_CPU_MASK 0x0000000f /* XXX? */
126 #if defined __XSCALE__
127 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
129 #if defined __thumb__
130 #define CPU_DEFAULT (ARM_ARCH_V5T)
132 #define CPU_DEFAULT ARM_ANY
138 #define FPU_DEFAULT FPU_ARCH_FPA
143 #define FPU_DEFAULT FPU_ARCH_VFP /* Soft-float, but VFP order. */
145 /* Legacy a.out format. */
146 #define FPU_DEFAULT FPU_ARCH_FPA /* Soft-float, but FPA order. */
150 /* For backwards compatibility we default to the FPA. */
152 #define FPU_DEFAULT FPU_ARCH_FPA
155 #define streq(a, b) (strcmp (a, b) == 0)
156 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
158 static unsigned long cpu_variant
;
159 static int target_oabi
= 0;
161 /* Flags stored in private area of BFD structure. */
162 static int uses_apcs_26
= FALSE
;
163 static int atpcs
= FALSE
;
164 static int support_interwork
= FALSE
;
165 static int uses_apcs_float
= FALSE
;
166 static int pic_code
= FALSE
;
168 /* Variables that we set while parsing command-line options. Once all
169 options have been read we re-process these values to set the real
171 static int legacy_cpu
= -1;
172 static int legacy_fpu
= -1;
174 static int mcpu_cpu_opt
= -1;
175 static int mcpu_fpu_opt
= -1;
176 static int march_cpu_opt
= -1;
177 static int march_fpu_opt
= -1;
178 static int mfpu_opt
= -1;
180 /* This array holds the chars that always start a comment. If the
181 pre-processor is disabled, these aren't very useful. */
182 const char comment_chars
[] = "@";
184 /* This array holds the chars that only start a comment at the beginning of
185 a line. If the line seems to have the form '# 123 filename'
186 .line and .file directives will appear in the pre-processed output. */
187 /* Note that input_file.c hand checks for '#' at the beginning of the
188 first line of the input file. This is because the compiler outputs
189 #NO_APP at the beginning of its output. */
190 /* Also note that comments like this one will always work. */
191 const char line_comment_chars
[] = "#";
193 const char line_separator_chars
[] = ";";
195 /* Chars that can be used to separate mant
196 from exp in floating point numbers. */
197 const char EXP_CHARS
[] = "eE";
199 /* Chars that mean this number is a floating point constant. */
203 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
205 /* Prefix characters that indicate the start of an immediate
207 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
210 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
211 symbolS
* GOT_symbol
;
214 /* Size of relocation record. */
215 const int md_reloc_size
= 8;
217 /* 0: assemble for ARM,
218 1: assemble for Thumb,
219 2: assemble for Thumb even though target CPU does not support thumb
221 static int thumb_mode
= 0;
223 typedef struct arm_fix
231 unsigned long instruction
;
235 bfd_reloc_code_real_type type
;
252 struct asm_shift_properties
254 enum asm_shift_index index
;
255 unsigned long bit_field
;
256 unsigned int allows_0
: 1;
257 unsigned int allows_32
: 1;
260 static const struct asm_shift_properties shift_properties
[] =
262 { SHIFT_LSL
, 0, 1, 0},
263 { SHIFT_LSR
, 0x20, 0, 1},
264 { SHIFT_ASR
, 0x40, 0, 1},
265 { SHIFT_ROR
, 0x60, 0, 0},
266 { SHIFT_RRX
, 0x60, 0, 0}
269 struct asm_shift_name
272 const struct asm_shift_properties
* properties
;
275 static const struct asm_shift_name shift_names
[] =
277 { "asl", shift_properties
+ SHIFT_LSL
},
278 { "lsl", shift_properties
+ SHIFT_LSL
},
279 { "lsr", shift_properties
+ SHIFT_LSR
},
280 { "asr", shift_properties
+ SHIFT_ASR
},
281 { "ror", shift_properties
+ SHIFT_ROR
},
282 { "rrx", shift_properties
+ SHIFT_RRX
},
283 { "ASL", shift_properties
+ SHIFT_LSL
},
284 { "LSL", shift_properties
+ SHIFT_LSL
},
285 { "LSR", shift_properties
+ SHIFT_LSR
},
286 { "ASR", shift_properties
+ SHIFT_ASR
},
287 { "ROR", shift_properties
+ SHIFT_ROR
},
288 { "RRX", shift_properties
+ SHIFT_RRX
}
291 #define NO_SHIFT_RESTRICT 1
292 #define SHIFT_RESTRICT 0
294 #define NUM_FLOAT_VALS 8
296 const char * fp_const
[] =
298 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
301 /* Number of littlenums required to hold an extended precision number. */
302 #define MAX_LITTLENUMS 6
304 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
309 /* Whether a Co-processor load/store operation accepts write-back forms. */
318 #define CP_T_X 0x00008000
319 #define CP_T_Y 0x00400000
320 #define CP_T_Pre 0x01000000
321 #define CP_T_UD 0x00800000
322 #define CP_T_WB 0x00200000
324 #define CONDS_BIT 0x00100000
325 #define LOAD_BIT 0x00100000
327 #define DOUBLE_LOAD_FLAG 0x00000001
331 const char * template;
335 #define COND_ALWAYS 0xe0000000
336 #define COND_MASK 0xf0000000
338 static const struct asm_cond conds
[] =
342 {"cs", 0x20000000}, {"hs", 0x20000000},
343 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
360 const char *template;
365 /* The bit that distnguishes CPSR and SPSR. */
366 #define SPSR_BIT (1 << 22)
368 /* How many bits to shift the PSR_xxx bits up by. */
371 #define PSR_c (1 << 0)
372 #define PSR_x (1 << 1)
373 #define PSR_s (1 << 2)
374 #define PSR_f (1 << 3)
376 static const struct asm_psr psrs
[] =
378 {"CPSR", TRUE
, PSR_c
| PSR_f
},
379 {"CPSR_all", TRUE
, PSR_c
| PSR_f
},
380 {"SPSR", FALSE
, PSR_c
| PSR_f
},
381 {"SPSR_all", FALSE
, PSR_c
| PSR_f
},
382 {"CPSR_flg", TRUE
, PSR_f
},
383 {"CPSR_f", TRUE
, PSR_f
},
384 {"SPSR_flg", FALSE
, PSR_f
},
385 {"SPSR_f", FALSE
, PSR_f
},
386 {"CPSR_c", TRUE
, PSR_c
},
387 {"CPSR_ctl", TRUE
, PSR_c
},
388 {"SPSR_c", FALSE
, PSR_c
},
389 {"SPSR_ctl", FALSE
, PSR_c
},
390 {"CPSR_x", TRUE
, PSR_x
},
391 {"CPSR_s", TRUE
, PSR_s
},
392 {"SPSR_x", FALSE
, PSR_x
},
393 {"SPSR_s", FALSE
, PSR_s
},
394 /* Combinations of flags. */
395 {"CPSR_fs", TRUE
, PSR_f
| PSR_s
},
396 {"CPSR_fx", TRUE
, PSR_f
| PSR_x
},
397 {"CPSR_fc", TRUE
, PSR_f
| PSR_c
},
398 {"CPSR_sf", TRUE
, PSR_s
| PSR_f
},
399 {"CPSR_sx", TRUE
, PSR_s
| PSR_x
},
400 {"CPSR_sc", TRUE
, PSR_s
| PSR_c
},
401 {"CPSR_xf", TRUE
, PSR_x
| PSR_f
},
402 {"CPSR_xs", TRUE
, PSR_x
| PSR_s
},
403 {"CPSR_xc", TRUE
, PSR_x
| PSR_c
},
404 {"CPSR_cf", TRUE
, PSR_c
| PSR_f
},
405 {"CPSR_cs", TRUE
, PSR_c
| PSR_s
},
406 {"CPSR_cx", TRUE
, PSR_c
| PSR_x
},
407 {"CPSR_fsx", TRUE
, PSR_f
| PSR_s
| PSR_x
},
408 {"CPSR_fsc", TRUE
, PSR_f
| PSR_s
| PSR_c
},
409 {"CPSR_fxs", TRUE
, PSR_f
| PSR_x
| PSR_s
},
410 {"CPSR_fxc", TRUE
, PSR_f
| PSR_x
| PSR_c
},
411 {"CPSR_fcs", TRUE
, PSR_f
| PSR_c
| PSR_s
},
412 {"CPSR_fcx", TRUE
, PSR_f
| PSR_c
| PSR_x
},
413 {"CPSR_sfx", TRUE
, PSR_s
| PSR_f
| PSR_x
},
414 {"CPSR_sfc", TRUE
, PSR_s
| PSR_f
| PSR_c
},
415 {"CPSR_sxf", TRUE
, PSR_s
| PSR_x
| PSR_f
},
416 {"CPSR_sxc", TRUE
, PSR_s
| PSR_x
| PSR_c
},
417 {"CPSR_scf", TRUE
, PSR_s
| PSR_c
| PSR_f
},
418 {"CPSR_scx", TRUE
, PSR_s
| PSR_c
| PSR_x
},
419 {"CPSR_xfs", TRUE
, PSR_x
| PSR_f
| PSR_s
},
420 {"CPSR_xfc", TRUE
, PSR_x
| PSR_f
| PSR_c
},
421 {"CPSR_xsf", TRUE
, PSR_x
| PSR_s
| PSR_f
},
422 {"CPSR_xsc", TRUE
, PSR_x
| PSR_s
| PSR_c
},
423 {"CPSR_xcf", TRUE
, PSR_x
| PSR_c
| PSR_f
},
424 {"CPSR_xcs", TRUE
, PSR_x
| PSR_c
| PSR_s
},
425 {"CPSR_cfs", TRUE
, PSR_c
| PSR_f
| PSR_s
},
426 {"CPSR_cfx", TRUE
, PSR_c
| PSR_f
| PSR_x
},
427 {"CPSR_csf", TRUE
, PSR_c
| PSR_s
| PSR_f
},
428 {"CPSR_csx", TRUE
, PSR_c
| PSR_s
| PSR_x
},
429 {"CPSR_cxf", TRUE
, PSR_c
| PSR_x
| PSR_f
},
430 {"CPSR_cxs", TRUE
, PSR_c
| PSR_x
| PSR_s
},
431 {"CPSR_fsxc", TRUE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
432 {"CPSR_fscx", TRUE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
433 {"CPSR_fxsc", TRUE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
434 {"CPSR_fxcs", TRUE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
435 {"CPSR_fcsx", TRUE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
436 {"CPSR_fcxs", TRUE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
437 {"CPSR_sfxc", TRUE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
438 {"CPSR_sfcx", TRUE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
439 {"CPSR_sxfc", TRUE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
440 {"CPSR_sxcf", TRUE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
441 {"CPSR_scfx", TRUE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
442 {"CPSR_scxf", TRUE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
443 {"CPSR_xfsc", TRUE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
444 {"CPSR_xfcs", TRUE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
445 {"CPSR_xsfc", TRUE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
446 {"CPSR_xscf", TRUE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
447 {"CPSR_xcfs", TRUE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
448 {"CPSR_xcsf", TRUE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
449 {"CPSR_cfsx", TRUE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
450 {"CPSR_cfxs", TRUE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
451 {"CPSR_csfx", TRUE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
452 {"CPSR_csxf", TRUE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
453 {"CPSR_cxfs", TRUE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
454 {"CPSR_cxsf", TRUE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
455 {"SPSR_fs", FALSE
, PSR_f
| PSR_s
},
456 {"SPSR_fx", FALSE
, PSR_f
| PSR_x
},
457 {"SPSR_fc", FALSE
, PSR_f
| PSR_c
},
458 {"SPSR_sf", FALSE
, PSR_s
| PSR_f
},
459 {"SPSR_sx", FALSE
, PSR_s
| PSR_x
},
460 {"SPSR_sc", FALSE
, PSR_s
| PSR_c
},
461 {"SPSR_xf", FALSE
, PSR_x
| PSR_f
},
462 {"SPSR_xs", FALSE
, PSR_x
| PSR_s
},
463 {"SPSR_xc", FALSE
, PSR_x
| PSR_c
},
464 {"SPSR_cf", FALSE
, PSR_c
| PSR_f
},
465 {"SPSR_cs", FALSE
, PSR_c
| PSR_s
},
466 {"SPSR_cx", FALSE
, PSR_c
| PSR_x
},
467 {"SPSR_fsx", FALSE
, PSR_f
| PSR_s
| PSR_x
},
468 {"SPSR_fsc", FALSE
, PSR_f
| PSR_s
| PSR_c
},
469 {"SPSR_fxs", FALSE
, PSR_f
| PSR_x
| PSR_s
},
470 {"SPSR_fxc", FALSE
, PSR_f
| PSR_x
| PSR_c
},
471 {"SPSR_fcs", FALSE
, PSR_f
| PSR_c
| PSR_s
},
472 {"SPSR_fcx", FALSE
, PSR_f
| PSR_c
| PSR_x
},
473 {"SPSR_sfx", FALSE
, PSR_s
| PSR_f
| PSR_x
},
474 {"SPSR_sfc", FALSE
, PSR_s
| PSR_f
| PSR_c
},
475 {"SPSR_sxf", FALSE
, PSR_s
| PSR_x
| PSR_f
},
476 {"SPSR_sxc", FALSE
, PSR_s
| PSR_x
| PSR_c
},
477 {"SPSR_scf", FALSE
, PSR_s
| PSR_c
| PSR_f
},
478 {"SPSR_scx", FALSE
, PSR_s
| PSR_c
| PSR_x
},
479 {"SPSR_xfs", FALSE
, PSR_x
| PSR_f
| PSR_s
},
480 {"SPSR_xfc", FALSE
, PSR_x
| PSR_f
| PSR_c
},
481 {"SPSR_xsf", FALSE
, PSR_x
| PSR_s
| PSR_f
},
482 {"SPSR_xsc", FALSE
, PSR_x
| PSR_s
| PSR_c
},
483 {"SPSR_xcf", FALSE
, PSR_x
| PSR_c
| PSR_f
},
484 {"SPSR_xcs", FALSE
, PSR_x
| PSR_c
| PSR_s
},
485 {"SPSR_cfs", FALSE
, PSR_c
| PSR_f
| PSR_s
},
486 {"SPSR_cfx", FALSE
, PSR_c
| PSR_f
| PSR_x
},
487 {"SPSR_csf", FALSE
, PSR_c
| PSR_s
| PSR_f
},
488 {"SPSR_csx", FALSE
, PSR_c
| PSR_s
| PSR_x
},
489 {"SPSR_cxf", FALSE
, PSR_c
| PSR_x
| PSR_f
},
490 {"SPSR_cxs", FALSE
, PSR_c
| PSR_x
| PSR_s
},
491 {"SPSR_fsxc", FALSE
, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
492 {"SPSR_fscx", FALSE
, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
493 {"SPSR_fxsc", FALSE
, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
494 {"SPSR_fxcs", FALSE
, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
495 {"SPSR_fcsx", FALSE
, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
496 {"SPSR_fcxs", FALSE
, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
497 {"SPSR_sfxc", FALSE
, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
498 {"SPSR_sfcx", FALSE
, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
499 {"SPSR_sxfc", FALSE
, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
500 {"SPSR_sxcf", FALSE
, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
501 {"SPSR_scfx", FALSE
, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
502 {"SPSR_scxf", FALSE
, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
503 {"SPSR_xfsc", FALSE
, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
504 {"SPSR_xfcs", FALSE
, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
505 {"SPSR_xsfc", FALSE
, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
506 {"SPSR_xscf", FALSE
, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
507 {"SPSR_xcfs", FALSE
, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
508 {"SPSR_xcsf", FALSE
, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
509 {"SPSR_cfsx", FALSE
, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
510 {"SPSR_cfxs", FALSE
, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
511 {"SPSR_csfx", FALSE
, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
512 {"SPSR_csxf", FALSE
, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
513 {"SPSR_cxfs", FALSE
, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
514 {"SPSR_cxsf", FALSE
, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
521 IWMMXT_REG_WR_OR_WC
= 2,
525 enum iwmmxt_insn_type
548 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
553 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
558 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
561 /* VFP system registers. */
568 static const struct vfp_reg vfp_regs
[] =
570 {"fpsid", 0x00000000},
571 {"FPSID", 0x00000000},
572 {"fpscr", 0x00010000},
573 {"FPSCR", 0x00010000},
574 {"fpexc", 0x00080000},
575 {"FPEXC", 0x00080000}
578 /* Structure for a hash table entry for a register. */
585 /* Some well known registers that we refer to directly elsewhere. */
590 #define wr_register(reg) ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
591 #define wc_register(reg) ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
592 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
594 /* These are the standard names. Users can add aliases with .req. */
595 /* Integer Register Numbers. */
596 static const struct reg_entry rn_table
[] =
598 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
599 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
600 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
601 {"r12", 12}, {"r13", REG_SP
}, {"r14", REG_LR
}, {"r15", REG_PC
},
602 /* ATPCS Synonyms. */
603 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
604 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
605 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
606 /* Well-known aliases. */
608 {"sb", 9}, {"sl", 10}, {"fp", 11},
609 {"ip", 12}, {"sp", REG_SP
}, {"lr", REG_LR
}, {"pc", REG_PC
},
613 #define WR_PREFIX 0x200
614 #define WC_PREFIX 0x400
616 static const struct reg_entry iwmmxt_table
[] =
618 /* Intel Wireless MMX technology register names. */
619 { "wr0", 0x0 | WR_PREFIX
}, {"wr1", 0x1 | WR_PREFIX
},
620 { "wr2", 0x2 | WR_PREFIX
}, {"wr3", 0x3 | WR_PREFIX
},
621 { "wr4", 0x4 | WR_PREFIX
}, {"wr5", 0x5 | WR_PREFIX
},
622 { "wr6", 0x6 | WR_PREFIX
}, {"wr7", 0x7 | WR_PREFIX
},
623 { "wr8", 0x8 | WR_PREFIX
}, {"wr9", 0x9 | WR_PREFIX
},
624 { "wr10", 0xa | WR_PREFIX
}, {"wr11", 0xb | WR_PREFIX
},
625 { "wr12", 0xc | WR_PREFIX
}, {"wr13", 0xd | WR_PREFIX
},
626 { "wr14", 0xe | WR_PREFIX
}, {"wr15", 0xf | WR_PREFIX
},
627 { "wcid", 0x0 | WC_PREFIX
}, {"wcon", 0x1 | WC_PREFIX
},
628 {"wcssf", 0x2 | WC_PREFIX
}, {"wcasf", 0x3 | WC_PREFIX
},
629 {"wcgr0", 0x8 | WC_PREFIX
}, {"wcgr1", 0x9 | WC_PREFIX
},
630 {"wcgr2", 0xa | WC_PREFIX
}, {"wcgr3", 0xb | WC_PREFIX
},
632 { "wR0", 0x0 | WR_PREFIX
}, {"wR1", 0x1 | WR_PREFIX
},
633 { "wR2", 0x2 | WR_PREFIX
}, {"wR3", 0x3 | WR_PREFIX
},
634 { "wR4", 0x4 | WR_PREFIX
}, {"wR5", 0x5 | WR_PREFIX
},
635 { "wR6", 0x6 | WR_PREFIX
}, {"wR7", 0x7 | WR_PREFIX
},
636 { "wR8", 0x8 | WR_PREFIX
}, {"wR9", 0x9 | WR_PREFIX
},
637 { "wR10", 0xa | WR_PREFIX
}, {"wR11", 0xb | WR_PREFIX
},
638 { "wR12", 0xc | WR_PREFIX
}, {"wR13", 0xd | WR_PREFIX
},
639 { "wR14", 0xe | WR_PREFIX
}, {"wR15", 0xf | WR_PREFIX
},
640 { "wCID", 0x0 | WC_PREFIX
}, {"wCon", 0x1 | WC_PREFIX
},
641 {"wCSSF", 0x2 | WC_PREFIX
}, {"wCASF", 0x3 | WC_PREFIX
},
642 {"wCGR0", 0x8 | WC_PREFIX
}, {"wCGR1", 0x9 | WC_PREFIX
},
643 {"wCGR2", 0xa | WC_PREFIX
}, {"wCGR3", 0xb | WC_PREFIX
},
647 /* Co-processor Numbers. */
648 static const struct reg_entry cp_table
[] =
650 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
651 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
652 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
653 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
657 /* Co-processor Register Numbers. */
658 static const struct reg_entry cn_table
[] =
660 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
661 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
662 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
663 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
664 /* Not really valid, but kept for back-wards compatibility. */
665 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
666 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
667 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
668 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
673 static const struct reg_entry fn_table
[] =
675 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
676 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
680 /* VFP SP Registers. */
681 static const struct reg_entry sn_table
[] =
683 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
684 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
685 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
686 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
687 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
688 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
689 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
690 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
694 /* VFP DP Registers. */
695 static const struct reg_entry dn_table
[] =
697 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
698 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
699 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
700 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
704 /* Maverick DSP coprocessor registers. */
705 static const struct reg_entry mav_mvf_table
[] =
707 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
708 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
709 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
710 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
714 static const struct reg_entry mav_mvd_table
[] =
716 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
717 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
718 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
719 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
723 static const struct reg_entry mav_mvfx_table
[] =
725 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
726 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
727 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
728 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
732 static const struct reg_entry mav_mvdx_table
[] =
734 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
735 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
736 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
737 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
741 static const struct reg_entry mav_mvax_table
[] =
743 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
747 static const struct reg_entry mav_dspsc_table
[] =
755 const struct reg_entry
*names
;
757 struct hash_control
*htab
;
758 const char *expected
;
761 struct reg_map all_reg_maps
[] =
763 {rn_table
, 15, NULL
, N_("ARM register expected")},
764 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
765 {cn_table
, 15, NULL
, N_("co-processor register expected")},
766 {fn_table
, 7, NULL
, N_("FPA register expected")},
767 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
768 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
769 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
770 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
771 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
772 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVDX register expected")},
773 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
774 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
775 {iwmmxt_table
, 23, NULL
, N_("Intel Wireless MMX technology register expected")},
778 /* Enumeration matching entries in table above. */
782 #define REG_TYPE_FIRST REG_TYPE_RN
794 REG_TYPE_IWMMXT
= 12,
799 /* Functions called by parser. */
800 /* ARM instructions. */
801 static void do_arit
PARAMS ((char *));
802 static void do_cmp
PARAMS ((char *));
803 static void do_mov
PARAMS ((char *));
804 static void do_ldst
PARAMS ((char *));
805 static void do_ldstt
PARAMS ((char *));
806 static void do_ldmstm
PARAMS ((char *));
807 static void do_branch
PARAMS ((char *));
808 static void do_swi
PARAMS ((char *));
810 /* Pseudo Op codes. */
811 static void do_adr
PARAMS ((char *));
812 static void do_adrl
PARAMS ((char *));
813 static void do_empty
PARAMS ((char *));
816 static void do_mul
PARAMS ((char *));
817 static void do_mla
PARAMS ((char *));
820 static void do_swap
PARAMS ((char *));
823 static void do_msr
PARAMS ((char *));
824 static void do_mrs
PARAMS ((char *));
827 static void do_mull
PARAMS ((char *));
830 static void do_ldstv4
PARAMS ((char *));
833 static void do_bx
PARAMS ((char *));
836 static void do_blx
PARAMS ((char *));
837 static void do_bkpt
PARAMS ((char *));
838 static void do_clz
PARAMS ((char *));
839 static void do_lstc2
PARAMS ((char *));
840 static void do_cdp2
PARAMS ((char *));
841 static void do_co_reg2
PARAMS ((char *));
844 static void do_smla
PARAMS ((char *));
845 static void do_smlal
PARAMS ((char *));
846 static void do_smul
PARAMS ((char *));
847 static void do_qadd
PARAMS ((char *));
850 static void do_pld
PARAMS ((char *));
851 static void do_ldrd
PARAMS ((char *));
852 static void do_co_reg2c
PARAMS ((char *));
855 static void do_bxj
PARAMS ((char *));
857 /* Coprocessor Instructions. */
858 static void do_cdp
PARAMS ((char *));
859 static void do_lstc
PARAMS ((char *));
860 static void do_co_reg
PARAMS ((char *));
862 /* FPA instructions. */
863 static void do_fpa_ctrl
PARAMS ((char *));
864 static void do_fpa_ldst
PARAMS ((char *));
865 static void do_fpa_ldmstm
PARAMS ((char *));
866 static void do_fpa_dyadic
PARAMS ((char *));
867 static void do_fpa_monadic
PARAMS ((char *));
868 static void do_fpa_cmp
PARAMS ((char *));
869 static void do_fpa_from_reg
PARAMS ((char *));
870 static void do_fpa_to_reg
PARAMS ((char *));
872 /* VFP instructions. */
873 static void do_vfp_sp_monadic
PARAMS ((char *));
874 static void do_vfp_dp_monadic
PARAMS ((char *));
875 static void do_vfp_sp_dyadic
PARAMS ((char *));
876 static void do_vfp_dp_dyadic
PARAMS ((char *));
877 static void do_vfp_reg_from_sp
PARAMS ((char *));
878 static void do_vfp_sp_from_reg
PARAMS ((char *));
879 static void do_vfp_sp_reg2
PARAMS ((char *));
880 static void do_vfp_reg_from_dp
PARAMS ((char *));
881 static void do_vfp_reg2_from_dp
PARAMS ((char *));
882 static void do_vfp_dp_from_reg
PARAMS ((char *));
883 static void do_vfp_dp_from_reg2
PARAMS ((char *));
884 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
885 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
886 static void do_vfp_sp_ldst
PARAMS ((char *));
887 static void do_vfp_dp_ldst
PARAMS ((char *));
888 static void do_vfp_sp_ldstmia
PARAMS ((char *));
889 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
890 static void do_vfp_dp_ldstmia
PARAMS ((char *));
891 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
892 static void do_vfp_xp_ldstmia
PARAMS ((char *));
893 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
894 static void do_vfp_sp_compare_z
PARAMS ((char *));
895 static void do_vfp_dp_compare_z
PARAMS ((char *));
896 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
897 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
900 static void do_xsc_mia
PARAMS ((char *));
901 static void do_xsc_mar
PARAMS ((char *));
902 static void do_xsc_mra
PARAMS ((char *));
905 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
907 static void do_mav_binops_1a
PARAMS ((char *));
908 static void do_mav_binops_1b
PARAMS ((char *));
909 static void do_mav_binops_1c
PARAMS ((char *));
910 static void do_mav_binops_1d
PARAMS ((char *));
911 static void do_mav_binops_1e
PARAMS ((char *));
912 static void do_mav_binops_1f
PARAMS ((char *));
913 static void do_mav_binops_1g
PARAMS ((char *));
914 static void do_mav_binops_1h
PARAMS ((char *));
915 static void do_mav_binops_1i
PARAMS ((char *));
916 static void do_mav_binops_1j
PARAMS ((char *));
917 static void do_mav_binops_1k
PARAMS ((char *));
918 static void do_mav_binops_1l
PARAMS ((char *));
919 static void do_mav_binops_1m
PARAMS ((char *));
920 static void do_mav_binops_1n
PARAMS ((char *));
921 static void do_mav_binops_1o
PARAMS ((char *));
922 static void do_mav_binops_2a
PARAMS ((char *));
923 static void do_mav_binops_2b
PARAMS ((char *));
924 static void do_mav_binops_2c
PARAMS ((char *));
925 static void do_mav_binops_3a
PARAMS ((char *));
926 static void do_mav_binops_3b
PARAMS ((char *));
927 static void do_mav_binops_3c
PARAMS ((char *));
928 static void do_mav_binops_3d
PARAMS ((char *));
929 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
932 static void do_mav_triple_4a
PARAMS ((char *));
933 static void do_mav_triple_4b
PARAMS ((char *));
934 static void do_mav_triple_5a
PARAMS ((char *));
935 static void do_mav_triple_5b
PARAMS ((char *));
936 static void do_mav_triple_5c
PARAMS ((char *));
937 static void do_mav_triple_5d
PARAMS ((char *));
938 static void do_mav_triple_5e
PARAMS ((char *));
939 static void do_mav_triple_5f
PARAMS ((char *));
940 static void do_mav_triple_5g
PARAMS ((char *));
941 static void do_mav_triple_5h
PARAMS ((char *));
942 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
946 static void do_mav_quad_6a
PARAMS ((char *));
947 static void do_mav_quad_6b
PARAMS ((char *));
948 static void do_mav_dspsc_1
PARAMS ((char *));
949 static void do_mav_dspsc_2
PARAMS ((char *));
950 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
952 static void do_mav_shift_1
PARAMS ((char *));
953 static void do_mav_shift_2
PARAMS ((char *));
954 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
955 static void do_mav_ldst_1
PARAMS ((char *));
956 static void do_mav_ldst_2
PARAMS ((char *));
957 static void do_mav_ldst_3
PARAMS ((char *));
958 static void do_mav_ldst_4
PARAMS ((char *));
960 static int mav_reg_required_here
PARAMS ((char **, int,
962 static int mav_parse_offset
PARAMS ((char **, int *));
964 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
966 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
967 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
968 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
969 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
971 static int add_to_lit_pool
PARAMS ((void));
972 static unsigned validate_immediate
PARAMS ((unsigned));
973 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
975 static int validate_offset_imm
PARAMS ((unsigned int, int));
976 static void opcode_select
PARAMS ((int));
977 static void end_of_line
PARAMS ((char *));
978 static int reg_required_here
PARAMS ((char **, int));
979 static int psr_required_here
PARAMS ((char **));
980 static int co_proc_number
PARAMS ((char **));
981 static int cp_opc_expr
PARAMS ((char **, int, int));
982 static int cp_reg_required_here
PARAMS ((char **, int));
983 static int fp_reg_required_here
PARAMS ((char **, int));
984 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
985 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
986 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
987 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
988 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
989 static long vfp_dp_reg_list
PARAMS ((char **));
990 static int vfp_psr_required_here
PARAMS ((char **str
));
991 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
992 static int cp_address_offset
PARAMS ((char **));
993 static int cp_address_required_here
PARAMS ((char **, int));
994 static int my_get_float_expression
PARAMS ((char **));
995 static int skip_past_comma
PARAMS ((char **));
996 static int walk_no_bignums
PARAMS ((symbolS
*));
997 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
998 static int data_op2
PARAMS ((char **));
999 static int fp_op2
PARAMS ((char **));
1000 static long reg_list
PARAMS ((char **));
1001 static void thumb_load_store
PARAMS ((char *, int, int));
1002 static int decode_shift
PARAMS ((char **, int));
1003 static int ldst_extend
PARAMS ((char **));
1004 static int ldst_extend_v4
PARAMS ((char **));
1005 static void thumb_add_sub
PARAMS ((char *, int));
1006 static void insert_reg
PARAMS ((const struct reg_entry
*,
1007 struct hash_control
*));
1008 static void thumb_shift
PARAMS ((char *, int));
1009 static void thumb_mov_compare
PARAMS ((char *, int));
1010 static void build_arm_ops_hsh
PARAMS ((void));
1011 static void set_constant_flonums
PARAMS ((void));
1012 static valueT md_chars_to_number
PARAMS ((char *, int));
1013 static void build_reg_hsh
PARAMS ((struct reg_map
*));
1014 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
1015 static int create_register_alias
PARAMS ((char *, char *));
1016 static void output_inst
PARAMS ((const char *));
1017 static int accum0_required_here
PARAMS ((char **));
1018 static int ld_mode_required_here
PARAMS ((char **));
1019 static void do_branch25
PARAMS ((char *));
1020 static symbolS
* find_real_start
PARAMS ((symbolS
*));
1022 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
1025 static int wreg_required_here
PARAMS ((char **, int, enum wreg_type
));
1026 static void do_iwmmxt_byte_addr
PARAMS ((char *));
1027 static void do_iwmmxt_tandc
PARAMS ((char *));
1028 static void do_iwmmxt_tbcst
PARAMS ((char *));
1029 static void do_iwmmxt_textrc
PARAMS ((char *));
1030 static void do_iwmmxt_textrm
PARAMS ((char *));
1031 static void do_iwmmxt_tinsr
PARAMS ((char *));
1032 static void do_iwmmxt_tmcr
PARAMS ((char *));
1033 static void do_iwmmxt_tmcrr
PARAMS ((char *));
1034 static void do_iwmmxt_tmia
PARAMS ((char *));
1035 static void do_iwmmxt_tmovmsk
PARAMS ((char *));
1036 static void do_iwmmxt_tmrc
PARAMS ((char *));
1037 static void do_iwmmxt_tmrrc
PARAMS ((char *));
1038 static void do_iwmmxt_torc
PARAMS ((char *));
1039 static void do_iwmmxt_waligni
PARAMS ((char *));
1040 static void do_iwmmxt_wmov
PARAMS ((char *));
1041 static void do_iwmmxt_word_addr
PARAMS ((char *));
1042 static void do_iwmmxt_wrwr
PARAMS ((char *));
1043 static void do_iwmmxt_wrwrwcg
PARAMS ((char *));
1044 static void do_iwmmxt_wrwrwr
PARAMS ((char *));
1045 static void do_iwmmxt_wshufh
PARAMS ((char *));
1046 static void do_iwmmxt_wzero
PARAMS ((char *));
1047 static int cp_byte_address_offset
PARAMS ((char **));
1048 static int cp_byte_address_required_here
PARAMS ((char **));
1050 /* ARM instructions take 4bytes in the object file, Thumb instructions
1054 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
1055 #define MAV_MODE1 0x100c
1057 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
1058 #define MAV_MODE2 0x0c10
1060 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
1061 #define MAV_MODE3 0x1000
1063 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
1064 #define MAV_MODE4 0x0c0010
1066 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
1067 #define MAV_MODE5 0x00100c
1069 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
1070 #define MAV_MODE6 0x00100c05
1074 /* Basic string to match. */
1075 const char * template;
1077 /* Basic instruction code. */
1078 unsigned long value
;
1080 /* Offset into the template where the condition code (if any) will be.
1081 If zero, then the instruction is never conditional. */
1082 unsigned cond_offset
;
1084 /* Which architecture variant provides this instruction. */
1085 unsigned long variant
;
1087 /* Function to call to parse args. */
1088 void (* parms
) PARAMS ((char *));
1091 static const struct asm_opcode insns
[] =
1093 /* Core ARM Instructions. */
1094 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
1095 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
1096 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
1097 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
1098 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
1099 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
1100 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
1101 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
1102 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
1103 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
1104 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
1105 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
1106 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
1107 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
1108 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1109 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1110 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1111 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1112 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1113 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1115 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1116 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1117 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1118 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1119 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1120 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1121 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1122 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1123 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1124 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1125 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1126 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1128 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1129 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1130 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1131 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1133 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1134 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1135 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1136 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1137 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1138 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1139 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1140 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1142 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1143 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1144 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1145 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1146 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1147 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1148 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1149 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1151 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1152 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1153 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1154 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1155 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1156 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1157 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1158 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1160 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1162 /* XXX This is the wrong place to do this. Think multi-arch. */
1163 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1164 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1166 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1167 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1171 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1172 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1173 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1175 /* ARM 2 multiplies. */
1176 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1177 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1178 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1179 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1181 /* Generic copressor instructions. */
1182 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1183 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1184 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1185 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1186 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1187 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1188 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1190 /* ARM 3 - swp instructions. */
1191 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1192 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1194 /* ARM 6 Status register instructions. */
1195 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1196 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1197 /* ScottB: our code uses 0xe128f000 for msr.
1198 NickC: but this is wrong because the bits 16 through 19 are
1199 handled by the PSR_xxx defines above. */
1201 /* ARM 7M long multiplies. */
1202 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1203 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1204 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1205 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1206 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1207 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1208 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1209 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1211 /* ARM Architecture 4. */
1212 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1213 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1214 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1215 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1217 /* ARM Architecture 4T. */
1218 /* Note: bx (and blx) are required on V5, even if the processor does
1219 not support Thumb. */
1220 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1222 /* ARM Architecture 5T. */
1223 /* Note: blx has 2 variants, so the .value is set dynamically.
1224 Only one of the variants has conditional execution. */
1225 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1226 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1227 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1228 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1229 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1230 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1231 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1232 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1233 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1234 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1236 /* ARM Architecture 5TExP. */
1237 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1238 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1239 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1240 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1242 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1243 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1245 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1246 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1247 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1248 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1250 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1251 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1252 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1253 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1255 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1256 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1258 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1259 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1260 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1261 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1263 /* ARM Architecture 5TE. */
1264 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1265 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1266 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1268 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1269 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1271 /* ARM Architecture 5TEJ. */
1272 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1274 /* Core FPA instruction set (V1). */
1275 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1276 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1277 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1278 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1280 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1281 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1282 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1283 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1285 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1286 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1287 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1288 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1290 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1291 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1292 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1297 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1304 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1310 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1317 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1323 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1330 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1336 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1343 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1349 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1356 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1362 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1369 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1375 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1382 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1388 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1390 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1391 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1392 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1394 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1395 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1396 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1397 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1398 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1399 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1400 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1401 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1402 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1403 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1404 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1405 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1407 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1408 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1409 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1410 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1411 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1412 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1413 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1414 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1415 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1416 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1417 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1418 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1420 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1421 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1422 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1423 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1424 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1425 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1426 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1427 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1428 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1429 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1430 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1431 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1433 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1434 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1435 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1436 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1437 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1438 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1439 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1440 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1441 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1442 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1443 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1444 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1446 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1447 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1448 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1449 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1450 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1451 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1452 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1453 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1454 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1455 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1456 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1457 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1459 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1460 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1461 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1462 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1463 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1464 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1465 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1466 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1467 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1468 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1469 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1470 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1472 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1473 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1474 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1475 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1476 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1477 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1478 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1479 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1480 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1481 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1482 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1483 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1485 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1486 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1487 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1488 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1489 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1490 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1491 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1492 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1493 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1494 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1495 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1496 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1498 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1499 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1500 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1505 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1512 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1518 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1525 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1531 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1538 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1544 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1551 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1552 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1553 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1554 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1555 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1556 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1557 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1558 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1559 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1560 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1561 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1563 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1564 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1565 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1566 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1567 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1568 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1569 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1570 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1571 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1572 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1573 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1574 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1576 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1577 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1578 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1579 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1580 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1581 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1582 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1583 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1584 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1585 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1586 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1587 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1589 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1590 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1591 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1592 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1593 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1594 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1595 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1596 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1597 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1598 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1599 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1600 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1602 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1603 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1604 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1605 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1606 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1607 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1608 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1609 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1610 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1611 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1612 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1613 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1615 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1616 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1617 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1618 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1619 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1620 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1621 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1622 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1623 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1624 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1625 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1626 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1628 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1629 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1630 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1631 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1632 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1633 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1634 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1635 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1636 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1637 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1638 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1639 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1641 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1642 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1643 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1644 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1645 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1646 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1647 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1648 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1649 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1650 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1651 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1652 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1654 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1655 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1656 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1657 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1658 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1659 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1660 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1661 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1662 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1663 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1664 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1665 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1667 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1668 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1669 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1670 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1671 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1672 not be an optional suffix, but part of the instruction. To be
1673 compatible, we accept either. */
1674 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1675 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1677 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1678 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1679 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1680 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1681 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1682 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1683 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1684 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1685 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1686 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1687 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1688 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1690 /* The implementation of the FIX instruction is broken on some
1691 assemblers, in that it accepts a precision specifier as well as a
1692 rounding specifier, despite the fact that this is meaningless.
1693 To be more compatible, we accept it as well, though of course it
1694 does not set any bits. */
1695 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1696 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1697 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1698 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1699 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1700 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1701 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1702 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1703 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1704 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1705 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1706 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1707 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1709 /* Instructions that were new with the real FPA, call them V2. */
1710 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1711 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1712 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1713 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1714 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1715 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1717 /* VFP V1xD (single precision). */
1718 /* Moves and type conversions. */
1719 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1720 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1721 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1722 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1723 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1724 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1725 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1726 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1727 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1728 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1729 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1730 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1732 /* Memory operations. */
1733 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1734 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1735 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1736 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1737 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1738 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1739 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1740 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1741 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1742 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1743 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1744 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1745 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1746 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1747 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1748 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1749 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1750 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1752 /* Monadic operations. */
1753 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1754 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1755 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1757 /* Dyadic operations. */
1758 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1759 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1760 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1761 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1762 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1763 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1764 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1765 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1766 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1769 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1770 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1771 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1772 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1774 /* VFP V1 (Double precision). */
1775 /* Moves and type conversions. */
1776 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1777 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1778 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1779 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1780 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1781 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1782 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1783 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1784 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1785 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1786 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1787 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1788 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1790 /* Memory operations. */
1791 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1792 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1793 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1794 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1795 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1796 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1797 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1798 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1799 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1800 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1802 /* Monadic operations. */
1803 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1804 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1805 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1807 /* Dyadic operations. */
1808 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1809 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1810 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1811 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1812 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1813 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1814 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1815 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1816 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1819 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1820 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1821 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1822 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1825 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1826 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1827 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1828 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1830 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1831 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1832 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1833 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1834 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1835 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1836 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1837 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1838 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1840 /* Intel Wireless MMX technology instructions. */
1841 {"tandcb", 0xee130130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1842 {"tandch", 0xee530130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1843 {"tandcw", 0xee930130, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tandc
},
1844 {"tbcstb", 0xee400010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1845 {"tbcsth", 0xee400050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1846 {"tbcstw", 0xee400090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tbcst
},
1847 {"textrcb", 0xee130170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1848 {"textrch", 0xee530170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1849 {"textrcw", 0xee930170, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_textrc
},
1850 {"textrmub", 0xee100070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1851 {"textrmuh", 0xee500070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1852 {"textrmuw", 0xee900070, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1853 {"textrmsb", 0xee100078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1854 {"textrmsh", 0xee500078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1855 {"textrmsw", 0xee900078, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_textrm
},
1856 {"tinsrb", 0xee600010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1857 {"tinsrh", 0xee600050, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1858 {"tinsrw", 0xee600090, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tinsr
},
1859 {"tmcr", 0xee000110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcr
},
1860 {"tmcrr", 0xec400000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmcrr
},
1861 {"tmia", 0xee200010, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1862 {"tmiaph", 0xee280010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1863 {"tmiabb", 0xee2c0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1864 {"tmiabt", 0xee2d0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1865 {"tmiatb", 0xee2e0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1866 {"tmiatt", 0xee2f0010, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_tmia
},
1867 {"tmovmskb", 0xee100030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1868 {"tmovmskh", 0xee500030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1869 {"tmovmskw", 0xee900030, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_tmovmsk
},
1870 {"tmrc", 0xee100110, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrc
},
1871 {"tmrrc", 0xec500000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_tmrrc
},
1872 {"torcb", 0xee130150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1873 {"torch", 0xee530150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1874 {"torcw", 0xee930150, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_torc
},
1875 {"waccb", 0xee0001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1876 {"wacch", 0xee4001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1877 {"waccw", 0xee8001c0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1878 {"waddbss", 0xee300180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1879 {"waddb", 0xee000180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1880 {"waddbus", 0xee100180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1881 {"waddhss", 0xee700180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1882 {"waddh", 0xee400180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1883 {"waddhus", 0xee500180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1884 {"waddwss", 0xeeb00180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1885 {"waddw", 0xee800180, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1886 {"waddwus", 0xee900180, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1887 {"waligni", 0xee000020, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_waligni
},
1888 {"walignr0", 0xee800020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1889 {"walignr1", 0xee900020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1890 {"walignr2", 0xeea00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1891 {"walignr3", 0xeeb00020, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1892 {"wand", 0xee200000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1893 {"wandn", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1894 {"wavg2b", 0xee800000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1895 {"wavg2br", 0xee900000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1896 {"wavg2h", 0xeec00000, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1897 {"wavg2hr", 0xeed00000, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1898 {"wcmpeqb", 0xee000060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1899 {"wcmpeqh", 0xee400060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1900 {"wcmpeqw", 0xee800060, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1901 {"wcmpgtub", 0xee100060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1902 {"wcmpgtuh", 0xee500060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1903 {"wcmpgtuw", 0xee900060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1904 {"wcmpgtsb", 0xee300060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1905 {"wcmpgtsh", 0xee700060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1906 {"wcmpgtsw", 0xeeb00060, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1907 {"wldrb", 0xec100000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1908 {"wldrh", 0xec100100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1909 {"wldrw", 0xec100200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1910 {"wldrd", 0xec100300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1911 {"wmacs", 0xee600100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1912 {"wmacsz", 0xee700100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1913 {"wmacu", 0xee400100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1914 {"wmacuz", 0xee500100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1915 {"wmadds", 0xeea00100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1916 {"wmaddu", 0xee800100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1917 {"wmaxsb", 0xee200160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1918 {"wmaxsh", 0xee600160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1919 {"wmaxsw", 0xeea00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1920 {"wmaxub", 0xee000160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1921 {"wmaxuh", 0xee400160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1922 {"wmaxuw", 0xee800160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1923 {"wminsb", 0xee300160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1924 {"wminsh", 0xee700160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1925 {"wminsw", 0xeeb00160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1926 {"wminub", 0xee100160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1927 {"wminuh", 0xee500160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1928 {"wminuw", 0xee900160, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1929 {"wmov", 0xee000000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wmov
},
1930 {"wmulsm", 0xee300100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1931 {"wmulsl", 0xee200100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1932 {"wmulum", 0xee100100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1933 {"wmulul", 0xee000100, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1934 {"wor", 0xee000000, 3, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1935 {"wpackhss", 0xee700080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1936 {"wpackhus", 0xee500080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1937 {"wpackwss", 0xeeb00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1938 {"wpackwus", 0xee900080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1939 {"wpackdss", 0xeef00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1940 {"wpackdus", 0xeed00080, 8, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1941 {"wrorh", 0xee700040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1942 {"wrorhg", 0xee700148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1943 {"wrorw", 0xeeb00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1944 {"wrorwg", 0xeeb00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1945 {"wrord", 0xeef00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1946 {"wrordg", 0xeef00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1947 {"wsadb", 0xee000120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1948 {"wsadbz", 0xee100120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1949 {"wsadh", 0xee400120, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1950 {"wsadhz", 0xee500120, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1951 {"wshufh", 0xee0001e0, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wshufh
},
1952 {"wsllh", 0xee500040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1953 {"wsllhg", 0xee500148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1954 {"wsllw", 0xee900040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1955 {"wsllwg", 0xee900148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1956 {"wslld", 0xeed00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1957 {"wslldg", 0xeed00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1958 {"wsrah", 0xee400040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1959 {"wsrahg", 0xee400148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1960 {"wsraw", 0xee800040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1961 {"wsrawg", 0xee800148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1962 {"wsrad", 0xeec00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1963 {"wsradg", 0xeec00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1964 {"wsrlh", 0xee600040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1965 {"wsrlhg", 0xee600148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1966 {"wsrlw", 0xeea00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1967 {"wsrlwg", 0xeea00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1968 {"wsrld", 0xeee00040, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1969 {"wsrldg", 0xeee00148, 6, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwcg
},
1970 {"wstrb", 0xec000000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1971 {"wstrh", 0xec000100, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_byte_addr
},
1972 {"wstrw", 0xec000200, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1973 {"wstrd", 0xec000300, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_word_addr
},
1974 {"wsubbss", 0xee3001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1975 {"wsubb", 0xee0001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1976 {"wsubbus", 0xee1001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1977 {"wsubhss", 0xee7001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1978 {"wsubh", 0xee4001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1979 {"wsubhus", 0xee5001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1980 {"wsubwss", 0xeeb001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1981 {"wsubw", 0xee8001a0, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1982 {"wsubwus", 0xee9001a0, 7, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1983 {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1984 {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1985 {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1986 {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1987 {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1988 {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1989 {"wunpckihb", 0xee1000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1990 {"wunpckihh", 0xee5000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1991 {"wunpckihw", 0xee9000c0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1992 {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1993 {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1994 {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1995 {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1996 {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1997 {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwr
},
1998 {"wunpckilb", 0xee1000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
1999 {"wunpckilh", 0xee5000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2000 {"wunpckilw", 0xee9000e0, 9, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2001 {"wxor", 0xee100000, 4, ARM_CEXT_IWMMXT
, do_iwmmxt_wrwrwr
},
2002 {"wzero", 0xee300000, 5, ARM_CEXT_IWMMXT
, do_iwmmxt_wzero
},
2004 /* Cirrus Maverick instructions. */
2005 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2006 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2007 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2008 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2009 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
2010 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
2011 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
2012 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
2013 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
2014 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
2015 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2016 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2017 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
2018 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
2019 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2020 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2021 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
2022 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
2023 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2024 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2025 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2026 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2027 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2028 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2029 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
2030 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
2031 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
2032 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
2033 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
2034 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
2035 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2036 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2037 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
2038 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
2039 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
2040 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
2041 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
2042 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
2043 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2044 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2045 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
2046 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
2047 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
2048 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
2049 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
2050 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
2051 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
2052 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
2053 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
2054 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
2055 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2056 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2057 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
2058 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
2059 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2060 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2061 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2062 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2063 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
2064 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
2065 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2066 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2067 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
2068 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
2069 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2070 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2071 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2072 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2073 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2074 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
2075 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2076 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
2077 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2078 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
2079 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2080 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
2083 /* Defines for various bits that we will want to toggle. */
2084 #define INST_IMMEDIATE 0x02000000
2085 #define OFFSET_REG 0x02000000
2086 #define HWOFFSET_IMM 0x00400000
2087 #define SHIFT_BY_REG 0x00000010
2088 #define PRE_INDEX 0x01000000
2089 #define INDEX_UP 0x00800000
2090 #define WRITE_BACK 0x00200000
2091 #define LDM_TYPE_2_OR_3 0x00400000
2093 #define LITERAL_MASK 0xf000f000
2094 #define OPCODE_MASK 0xfe1fffff
2095 #define V4_STR_BIT 0x00000020
2097 #define DATA_OP_SHIFT 21
2099 /* Codes to distinguish the arithmetic instructions. */
2100 #define OPCODE_AND 0
2101 #define OPCODE_EOR 1
2102 #define OPCODE_SUB 2
2103 #define OPCODE_RSB 3
2104 #define OPCODE_ADD 4
2105 #define OPCODE_ADC 5
2106 #define OPCODE_SBC 6
2107 #define OPCODE_RSC 7
2108 #define OPCODE_TST 8
2109 #define OPCODE_TEQ 9
2110 #define OPCODE_CMP 10
2111 #define OPCODE_CMN 11
2112 #define OPCODE_ORR 12
2113 #define OPCODE_MOV 13
2114 #define OPCODE_BIC 14
2115 #define OPCODE_MVN 15
2117 /* Thumb v1 (ARMv4T). */
2118 static void do_t_nop
PARAMS ((char *));
2119 static void do_t_arit
PARAMS ((char *));
2120 static void do_t_add
PARAMS ((char *));
2121 static void do_t_asr
PARAMS ((char *));
2122 static void do_t_branch9
PARAMS ((char *));
2123 static void do_t_branch12
PARAMS ((char *));
2124 static void do_t_branch23
PARAMS ((char *));
2125 static void do_t_bx
PARAMS ((char *));
2126 static void do_t_compare
PARAMS ((char *));
2127 static void do_t_ldmstm
PARAMS ((char *));
2128 static void do_t_ldr
PARAMS ((char *));
2129 static void do_t_ldrb
PARAMS ((char *));
2130 static void do_t_ldrh
PARAMS ((char *));
2131 static void do_t_lds
PARAMS ((char *));
2132 static void do_t_lsl
PARAMS ((char *));
2133 static void do_t_lsr
PARAMS ((char *));
2134 static void do_t_mov
PARAMS ((char *));
2135 static void do_t_push_pop
PARAMS ((char *));
2136 static void do_t_str
PARAMS ((char *));
2137 static void do_t_strb
PARAMS ((char *));
2138 static void do_t_strh
PARAMS ((char *));
2139 static void do_t_sub
PARAMS ((char *));
2140 static void do_t_swi
PARAMS ((char *));
2141 static void do_t_adr
PARAMS ((char *));
2143 /* Thumb v2 (ARMv5T). */
2144 static void do_t_blx
PARAMS ((char *));
2145 static void do_t_bkpt
PARAMS ((char *));
2147 #define T_OPCODE_MUL 0x4340
2148 #define T_OPCODE_TST 0x4200
2149 #define T_OPCODE_CMN 0x42c0
2150 #define T_OPCODE_NEG 0x4240
2151 #define T_OPCODE_MVN 0x43c0
2153 #define T_OPCODE_ADD_R3 0x1800
2154 #define T_OPCODE_SUB_R3 0x1a00
2155 #define T_OPCODE_ADD_HI 0x4400
2156 #define T_OPCODE_ADD_ST 0xb000
2157 #define T_OPCODE_SUB_ST 0xb080
2158 #define T_OPCODE_ADD_SP 0xa800
2159 #define T_OPCODE_ADD_PC 0xa000
2160 #define T_OPCODE_ADD_I8 0x3000
2161 #define T_OPCODE_SUB_I8 0x3800
2162 #define T_OPCODE_ADD_I3 0x1c00
2163 #define T_OPCODE_SUB_I3 0x1e00
2165 #define T_OPCODE_ASR_R 0x4100
2166 #define T_OPCODE_LSL_R 0x4080
2167 #define T_OPCODE_LSR_R 0x40c0
2168 #define T_OPCODE_ASR_I 0x1000
2169 #define T_OPCODE_LSL_I 0x0000
2170 #define T_OPCODE_LSR_I 0x0800
2172 #define T_OPCODE_MOV_I8 0x2000
2173 #define T_OPCODE_CMP_I8 0x2800
2174 #define T_OPCODE_CMP_LR 0x4280
2175 #define T_OPCODE_MOV_HR 0x4600
2176 #define T_OPCODE_CMP_HR 0x4500
2178 #define T_OPCODE_LDR_PC 0x4800
2179 #define T_OPCODE_LDR_SP 0x9800
2180 #define T_OPCODE_STR_SP 0x9000
2181 #define T_OPCODE_LDR_IW 0x6800
2182 #define T_OPCODE_STR_IW 0x6000
2183 #define T_OPCODE_LDR_IH 0x8800
2184 #define T_OPCODE_STR_IH 0x8000
2185 #define T_OPCODE_LDR_IB 0x7800
2186 #define T_OPCODE_STR_IB 0x7000
2187 #define T_OPCODE_LDR_RW 0x5800
2188 #define T_OPCODE_STR_RW 0x5000
2189 #define T_OPCODE_LDR_RH 0x5a00
2190 #define T_OPCODE_STR_RH 0x5200
2191 #define T_OPCODE_LDR_RB 0x5c00
2192 #define T_OPCODE_STR_RB 0x5400
2194 #define T_OPCODE_PUSH 0xb400
2195 #define T_OPCODE_POP 0xbc00
2197 #define T_OPCODE_BRANCH 0xe7fe
2199 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
2201 #define THUMB_SIZE 2 /* Size of thumb instruction. */
2202 #define THUMB_REG_LO 0x1
2203 #define THUMB_REG_HI 0x2
2204 #define THUMB_REG_ANY 0x3
2206 #define THUMB_H1 0x0080
2207 #define THUMB_H2 0x0040
2213 #define THUMB_MOVE 0
2214 #define THUMB_COMPARE 1
2216 #define THUMB_LOAD 0
2217 #define THUMB_STORE 1
2219 #define THUMB_PP_PC_LR 0x0100
2221 /* These three are used for immediate shifts, do not alter. */
2222 #define THUMB_WORD 2
2223 #define THUMB_HALFWORD 1
2224 #define THUMB_BYTE 0
2228 /* Basic string to match. */
2229 const char * template;
2231 /* Basic instruction code. */
2232 unsigned long value
;
2236 /* Which CPU variants this exists for. */
2237 unsigned long variant
;
2239 /* Function to call to parse args. */
2240 void (* parms
) PARAMS ((char *));
2243 static const struct thumb_opcode tinsns
[] =
2245 /* Thumb v1 (ARMv4T). */
2246 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
2247 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
2248 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
2249 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
2250 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
2251 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2252 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2253 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2254 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2255 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2256 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2257 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2258 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2259 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2260 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2261 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2262 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2263 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
2264 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
2265 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2266 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2267 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
2268 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
2269 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
2270 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
2271 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
2272 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2273 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2274 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2275 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2276 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2277 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2278 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2279 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2280 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2281 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2282 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2283 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2284 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2285 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2286 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2287 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2288 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2289 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2290 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2291 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2292 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2293 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2294 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2295 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2296 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2297 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2298 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2299 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2300 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2302 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2303 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2304 /* Thumb v2 (ARMv5T). */
2305 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2306 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2309 #define BAD_ARGS _("bad arguments to instruction")
2310 #define BAD_PC _("r15 not allowed here")
2311 #define BAD_COND _("instruction is not conditional")
2312 #define ERR_NO_ACCUM _("acc0 expected")
2314 static struct hash_control
* arm_ops_hsh
= NULL
;
2315 static struct hash_control
* arm_tops_hsh
= NULL
;
2316 static struct hash_control
* arm_cond_hsh
= NULL
;
2317 static struct hash_control
* arm_shift_hsh
= NULL
;
2318 static struct hash_control
* arm_psr_hsh
= NULL
;
2320 /* This table describes all the machine specific pseudo-ops the assembler
2321 has to support. The fields are:
2322 pseudo-op name without dot
2323 function to call to execute this pseudo-op
2324 Integer arg to pass to the function. */
2326 static void s_req
PARAMS ((int));
2327 static void s_align
PARAMS ((int));
2328 static void s_bss
PARAMS ((int));
2329 static void s_even
PARAMS ((int));
2330 static void s_ltorg
PARAMS ((int));
2331 static void s_arm
PARAMS ((int));
2332 static void s_thumb
PARAMS ((int));
2333 static void s_code
PARAMS ((int));
2334 static void s_force_thumb
PARAMS ((int));
2335 static void s_thumb_func
PARAMS ((int));
2336 static void s_thumb_set
PARAMS ((int));
2338 static void s_arm_elf_cons
PARAMS ((int));
2341 static int my_get_expression
PARAMS ((expressionS
*, char **));
2343 const pseudo_typeS md_pseudo_table
[] =
2345 /* Never called becasue '.req' does not start line. */
2346 { "req", s_req
, 0 },
2347 { "bss", s_bss
, 0 },
2348 { "align", s_align
, 0 },
2349 { "arm", s_arm
, 0 },
2350 { "thumb", s_thumb
, 0 },
2351 { "code", s_code
, 0 },
2352 { "force_thumb", s_force_thumb
, 0 },
2353 { "thumb_func", s_thumb_func
, 0 },
2354 { "thumb_set", s_thumb_set
, 0 },
2355 { "even", s_even
, 0 },
2356 { "ltorg", s_ltorg
, 0 },
2357 { "pool", s_ltorg
, 0 },
2359 { "word", s_arm_elf_cons
, 4 },
2360 { "long", s_arm_elf_cons
, 4 },
2364 { "extend", float_cons
, 'x' },
2365 { "ldouble", float_cons
, 'x' },
2366 { "packed", float_cons
, 'p' },
2370 /* Other internal functions. */
2371 static int arm_parse_extension
PARAMS ((char *, int *));
2372 static int arm_parse_cpu
PARAMS ((char *));
2373 static int arm_parse_arch
PARAMS ((char *));
2374 static int arm_parse_fpu
PARAMS ((char *));
2375 #if defined OBJ_COFF || defined OBJ_ELF
2376 static void arm_add_note
PARAMS ((const char *, const char *, unsigned int));
2379 /* Stuff needed to resolve the label ambiguity
2389 symbolS
* last_label_seen
;
2390 static int label_is_thumb_function_name
= FALSE
;
2392 /* Literal Pool stuff. */
2394 #define MAX_LITERAL_POOL_SIZE 1024
2396 /* Literal pool structure. Held on a per-section
2397 and per-sub-section basis. */
2398 typedef struct literal_pool
2400 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2401 unsigned int next_free_entry
;
2405 subsegT sub_section
;
2406 struct literal_pool
* next
;
2409 /* Pointer to a linked list of literal pools. */
2410 literal_pool
* list_of_pools
= NULL
;
2412 static literal_pool
* find_literal_pool
PARAMS ((void));
2413 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2415 static literal_pool
*
2416 find_literal_pool ()
2418 literal_pool
* pool
;
2420 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2422 if (pool
->section
== now_seg
2423 && pool
->sub_section
== now_subseg
)
2430 static literal_pool
*
2431 find_or_make_literal_pool ()
2433 /* Next literal pool ID number. */
2434 static unsigned int latest_pool_num
= 1;
2435 literal_pool
* pool
;
2437 pool
= find_literal_pool ();
2441 /* Create a new pool. */
2442 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2446 pool
->next_free_entry
= 0;
2447 pool
->section
= now_seg
;
2448 pool
->sub_section
= now_subseg
;
2449 pool
->next
= list_of_pools
;
2450 pool
->symbol
= NULL
;
2452 /* Add it to the list. */
2453 list_of_pools
= pool
;
2456 /* New pools, and emptied pools, will have a NULL symbol. */
2457 if (pool
->symbol
== NULL
)
2459 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2460 (valueT
) 0, &zero_address_frag
);
2461 pool
->id
= latest_pool_num
++;
2468 /* Add the literal in the global 'inst'
2469 structure to the relevent literal pool. */
2473 literal_pool
* pool
;
2476 pool
= find_or_make_literal_pool ();
2478 /* Check if this literal value is already in the pool. */
2479 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2481 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2482 && (inst
.reloc
.exp
.X_op
== O_constant
)
2483 && (pool
->literals
[entry
].X_add_number
2484 == inst
.reloc
.exp
.X_add_number
)
2485 && (pool
->literals
[entry
].X_unsigned
2486 == inst
.reloc
.exp
.X_unsigned
))
2489 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2490 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2491 && (pool
->literals
[entry
].X_add_number
2492 == inst
.reloc
.exp
.X_add_number
)
2493 && (pool
->literals
[entry
].X_add_symbol
2494 == inst
.reloc
.exp
.X_add_symbol
)
2495 && (pool
->literals
[entry
].X_op_symbol
2496 == inst
.reloc
.exp
.X_op_symbol
))
2500 /* Do we need to create a new entry? */
2501 if (entry
== pool
->next_free_entry
)
2503 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2505 inst
.error
= _("literal pool overflow");
2509 pool
->literals
[entry
] = inst
.reloc
.exp
;
2510 pool
->next_free_entry
+= 1;
2513 inst
.reloc
.exp
.X_op
= O_symbol
;
2514 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2515 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2520 /* Can't use symbol_new here, so have to create a symbol and then at
2521 a later date assign it a value. Thats what these functions do. */
2524 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2526 const char * name
; /* It is copied, the caller can modify. */
2527 segT segment
; /* Segment identifier (SEG_<something>). */
2528 valueT valu
; /* Symbol value. */
2529 fragS
* frag
; /* Associated fragment. */
2531 unsigned int name_length
;
2532 char * preserved_copy_of_name
;
2534 name_length
= strlen (name
) + 1; /* +1 for \0. */
2535 obstack_grow (¬es
, name
, name_length
);
2536 preserved_copy_of_name
= obstack_finish (¬es
);
2537 #ifdef STRIP_UNDERSCORE
2538 if (preserved_copy_of_name
[0] == '_')
2539 preserved_copy_of_name
++;
2542 #ifdef tc_canonicalize_symbol_name
2543 preserved_copy_of_name
=
2544 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2547 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2549 S_SET_SEGMENT (symbolP
, segment
);
2550 S_SET_VALUE (symbolP
, valu
);
2551 symbol_clear_list_pointers (symbolP
);
2553 symbol_set_frag (symbolP
, frag
);
2555 /* Link to end of symbol chain. */
2557 extern int symbol_table_frozen
;
2558 if (symbol_table_frozen
)
2562 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2564 obj_symbol_new_hook (symbolP
);
2566 #ifdef tc_symbol_new_hook
2567 tc_symbol_new_hook (symbolP
);
2571 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2572 #endif /* DEBUG_SYMS */
2575 /* Check that an immediate is valid.
2576 If so, convert it to the right format. */
2579 validate_immediate (val
)
2585 #define rotate_left(v, n) (v << n | v >> (32 - n))
2587 for (i
= 0; i
< 32; i
+= 2)
2588 if ((a
= rotate_left (val
, i
)) <= 0xff)
2589 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2594 /* Check to see if an immediate can be computed as two seperate immediate
2595 values, added together. We already know that this value cannot be
2596 computed by just one ARM instruction. */
2599 validate_immediate_twopart (val
, highpart
)
2601 unsigned int * highpart
;
2606 for (i
= 0; i
< 32; i
+= 2)
2607 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2613 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2615 else if (a
& 0xff0000)
2619 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2623 assert (a
& 0xff000000);
2624 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2627 return (a
& 0xff) | (i
<< 7);
2634 validate_offset_imm (val
, hwse
)
2638 if ((hwse
&& val
> 255) || val
> 4095)
2645 int a ATTRIBUTE_UNUSED
;
2647 as_bad (_("invalid syntax for .req directive"));
2652 int ignore ATTRIBUTE_UNUSED
;
2654 /* We don't support putting frags in the BSS segment, we fake it by
2655 marking in_bss, then looking at s_skip for clues. */
2656 subseg_set (bss_section
, 0);
2657 demand_empty_rest_of_line ();
2662 int ignore ATTRIBUTE_UNUSED
;
2664 /* Never make frag if expect extra pass. */
2666 frag_align (1, 0, 0);
2668 record_alignment (now_seg
, 1);
2670 demand_empty_rest_of_line ();
2675 int ignored ATTRIBUTE_UNUSED
;
2678 literal_pool
* pool
;
2681 pool
= find_literal_pool ();
2683 || pool
->symbol
== NULL
2684 || pool
->next_free_entry
== 0)
2687 /* Align pool as you have word accesses.
2688 Only make a frag if we have to. */
2690 frag_align (2, 0, 0);
2692 record_alignment (now_seg
, 2);
2694 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
2696 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
2697 (valueT
) frag_now_fix (), frag_now
);
2698 symbol_table_insert (pool
->symbol
);
2700 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
2702 #if defined OBJ_COFF || defined OBJ_ELF
2703 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
2706 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2707 /* First output the expression in the instruction to the pool. */
2708 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
2710 /* Mark the pool as empty. */
2711 pool
->next_free_entry
= 0;
2712 pool
->symbol
= NULL
;
2715 /* Same as s_align_ptwo but align 0 => align 2. */
2719 int unused ATTRIBUTE_UNUSED
;
2722 register long temp_fill
;
2723 long max_alignment
= 15;
2725 temp
= get_absolute_expression ();
2726 if (temp
> max_alignment
)
2727 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2730 as_bad (_("alignment negative. 0 assumed."));
2734 if (*input_line_pointer
== ',')
2736 input_line_pointer
++;
2737 temp_fill
= get_absolute_expression ();
2745 /* Only make a frag if we HAVE to. */
2746 if (temp
&& !need_pass_2
)
2747 frag_align (temp
, (int) temp_fill
, 0);
2748 demand_empty_rest_of_line ();
2750 record_alignment (now_seg
, temp
);
2754 s_force_thumb (ignore
)
2755 int ignore ATTRIBUTE_UNUSED
;
2757 /* If we are not already in thumb mode go into it, EVEN if
2758 the target processor does not support thumb instructions.
2759 This is used by gcc/config/arm/lib1funcs.asm for example
2760 to compile interworking support functions even if the
2761 target processor should not support interworking. */
2766 record_alignment (now_seg
, 1);
2769 demand_empty_rest_of_line ();
2773 s_thumb_func (ignore
)
2774 int ignore ATTRIBUTE_UNUSED
;
2779 /* The following label is the name/address of the start of a Thumb function.
2780 We need to know this for the interworking support. */
2781 label_is_thumb_function_name
= TRUE
;
2783 demand_empty_rest_of_line ();
2786 /* Perform a .set directive, but also mark the alias as
2787 being a thumb function. */
2793 /* XXX the following is a duplicate of the code for s_set() in read.c
2794 We cannot just call that code as we need to get at the symbol that
2796 register char * name
;
2797 register char delim
;
2798 register char * end_name
;
2799 register symbolS
* symbolP
;
2801 /* Especial apologies for the random logic:
2802 This just grew, and could be parsed much more simply!
2804 name
= input_line_pointer
;
2805 delim
= get_symbol_end ();
2806 end_name
= input_line_pointer
;
2811 if (*input_line_pointer
!= ',')
2814 as_bad (_("expected comma after name \"%s\""), name
);
2816 ignore_rest_of_line ();
2820 input_line_pointer
++;
2823 if (name
[0] == '.' && name
[1] == '\0')
2825 /* XXX - this should not happen to .thumb_set. */
2829 if ((symbolP
= symbol_find (name
)) == NULL
2830 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2833 /* When doing symbol listings, play games with dummy fragments living
2834 outside the normal fragment chain to record the file and line info
2836 if (listing
& LISTING_SYMBOLS
)
2838 extern struct list_info_struct
* listing_tail
;
2839 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2841 memset (dummy_frag
, 0, sizeof (fragS
));
2842 dummy_frag
->fr_type
= rs_fill
;
2843 dummy_frag
->line
= listing_tail
;
2844 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2845 dummy_frag
->fr_symbol
= symbolP
;
2849 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2852 /* "set" symbols are local unless otherwise specified. */
2853 SF_SET_LOCAL (symbolP
);
2854 #endif /* OBJ_COFF */
2855 } /* Make a new symbol. */
2857 symbol_table_insert (symbolP
);
2862 && S_IS_DEFINED (symbolP
)
2863 && S_GET_SEGMENT (symbolP
) != reg_section
)
2864 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2866 pseudo_set (symbolP
);
2868 demand_empty_rest_of_line ();
2870 /* XXX Now we come to the Thumb specific bit of code. */
2872 THUMB_SET_FUNC (symbolP
, 1);
2873 ARM_SET_THUMB (symbolP
, 1);
2874 #if defined OBJ_ELF || defined OBJ_COFF
2875 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2880 opcode_select (width
)
2888 if (! (cpu_variant
& ARM_EXT_V4T
))
2889 as_bad (_("selected processor does not support THUMB opcodes"));
2892 /* No need to force the alignment, since we will have been
2893 coming from ARM mode, which is word-aligned. */
2894 record_alignment (now_seg
, 1);
2901 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2902 as_bad (_("selected processor does not support ARM opcodes"));
2907 frag_align (2, 0, 0);
2909 record_alignment (now_seg
, 1);
2914 as_bad (_("invalid instruction size selected (%d)"), width
);
2920 int ignore ATTRIBUTE_UNUSED
;
2923 demand_empty_rest_of_line ();
2928 int ignore ATTRIBUTE_UNUSED
;
2931 demand_empty_rest_of_line ();
2936 int unused ATTRIBUTE_UNUSED
;
2940 temp
= get_absolute_expression ();
2945 opcode_select (temp
);
2949 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2957 skip_whitespace (str
);
2959 if (*str
!= '\0' && !inst
.error
)
2960 inst
.error
= _("garbage following instruction");
2964 skip_past_comma (str
)
2967 char * p
= * str
, c
;
2970 while ((c
= *p
) == ' ' || c
== ',')
2973 if (c
== ',' && comma
++)
2981 return comma
? SUCCESS
: FAIL
;
2984 /* A standard register must be given at this point.
2985 SHIFT is the place to put it in inst.instruction.
2986 Restores input start point on error.
2987 Returns the reg#, or FAIL. */
2990 reg_required_here (str
, shift
)
2994 static char buff
[128]; /* XXX */
2996 char * start
= * str
;
2998 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
3001 inst
.instruction
|= reg
<< shift
;
3005 /* Restore the start point, we may have got a reg of the wrong class. */
3008 /* In the few cases where we might be able to accept something else
3009 this error can be overridden. */
3010 sprintf (buff
, _("register expected, not '%.100s'"), start
);
3016 /* A Intel Wireless MMX technology register
3017 must be given at this point.
3018 Shift is the place to put it in inst.instruction.
3019 Restores input start point on err.
3020 Returns the reg#, or FAIL. */
3023 wreg_required_here (str
, shift
, reg_type
)
3026 enum wreg_type reg_type
;
3028 static char buff
[128];
3030 char * start
= *str
;
3032 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_IWMMXT
].htab
)) != FAIL
)
3034 if (wr_register (reg
)
3035 && (reg_type
== IWMMXT_REG_WR
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3038 inst
.instruction
|= (reg
^ WR_PREFIX
) << shift
;
3041 else if (wc_register (reg
)
3042 && (reg_type
== IWMMXT_REG_WC
|| reg_type
== IWMMXT_REG_WR_OR_WC
))
3045 inst
.instruction
|= (reg
^ WC_PREFIX
) << shift
;
3048 else if ((wcg_register (reg
) && reg_type
== IWMMXT_REG_WCG
))
3051 inst
.instruction
|= ((reg
^ WC_PREFIX
) - 8) << shift
;
3056 /* Restore the start point, we may have got a reg of the wrong class. */
3059 /* In the few cases where we might be able to accept
3060 something else this error can be overridden. */
3061 sprintf (buff
, _("Intel Wireless MMX technology register expected, not '%.100s'"), start
);
3067 static const struct asm_psr
*
3069 register char ** ccp
;
3071 char * start
= * ccp
;
3074 const struct asm_psr
* psr
;
3078 /* Skip to the end of the next word in the input stream. */
3083 while (ISALPHA (c
) || c
== '_');
3085 /* Terminate the word. */
3088 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
3089 feature for ease of use and backwards compatibility. */
3090 if (!strncmp (start
, "cpsr", 4))
3091 strncpy (start
, "CPSR", 4);
3092 else if (!strncmp (start
, "spsr", 4))
3093 strncpy (start
, "SPSR", 4);
3095 /* Now locate the word in the psr hash table. */
3096 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
3098 /* Restore the input stream. */
3101 /* If we found a valid match, advance the
3102 stream pointer past the end of the word. */
3108 /* Parse the input looking for a PSR flag. */
3111 psr_required_here (str
)
3114 char * start
= * str
;
3115 const struct asm_psr
* psr
;
3117 psr
= arm_psr_parse (str
);
3121 /* If this is the SPSR that is being modified, set the R bit. */
3123 inst
.instruction
|= SPSR_BIT
;
3125 /* Set the psr flags in the MSR instruction. */
3126 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
3131 /* In the few cases where we might be able to accept
3132 something else this error can be overridden. */
3133 inst
.error
= _("flag for {c}psr instruction expected");
3135 /* Restore the start point. */
3141 co_proc_number (str
)
3144 int processor
, pchar
;
3147 skip_whitespace (*str
);
3150 /* The data sheet seems to imply that just a number on its own is valid
3151 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
3153 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
3159 if (pchar
>= '0' && pchar
<= '9')
3161 processor
= pchar
- '0';
3162 if (**str
>= '0' && **str
<= '9')
3164 processor
= processor
* 10 + *(*str
)++ - '0';
3167 inst
.error
= _("illegal co-processor number");
3174 inst
.error
= _("bad or missing co-processor number");
3179 inst
.instruction
|= processor
<< 8;
3184 cp_opc_expr (str
, where
, length
)
3191 skip_whitespace (* str
);
3193 memset (&expr
, '\0', sizeof (expr
));
3195 if (my_get_expression (&expr
, str
))
3197 if (expr
.X_op
!= O_constant
)
3199 inst
.error
= _("bad or missing expression");
3203 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
3205 inst
.error
= _("immediate co-processor expression too large");
3209 inst
.instruction
|= expr
.X_add_number
<< where
;
3214 cp_reg_required_here (str
, where
)
3219 char * start
= *str
;
3221 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
3223 inst
.instruction
|= reg
<< where
;
3227 /* In the few cases where we might be able to accept something else
3228 this error can be overridden. */
3229 inst
.error
= _("co-processor register expected");
3231 /* Restore the start point. */
3237 fp_reg_required_here (str
, where
)
3242 char * start
= * str
;
3244 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
3246 inst
.instruction
|= reg
<< where
;
3250 /* In the few cases where we might be able to accept something else
3251 this error can be overridden. */
3252 inst
.error
= _("floating point register expected");
3254 /* Restore the start point. */
3260 cp_address_offset (str
)
3265 skip_whitespace (* str
);
3267 if (! is_immediate_prefix (**str
))
3269 inst
.error
= _("immediate expression expected");
3275 if (my_get_expression (& inst
.reloc
.exp
, str
))
3278 if (inst
.reloc
.exp
.X_op
== O_constant
)
3280 offset
= inst
.reloc
.exp
.X_add_number
;
3284 inst
.error
= _("co-processor address must be word aligned");
3288 if (offset
> 1023 || offset
< -1023)
3290 inst
.error
= _("offset too large");
3295 inst
.instruction
|= INDEX_UP
;
3299 inst
.instruction
|= offset
>> 2;
3302 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3308 cp_address_required_here (str
, wb_ok
)
3321 skip_whitespace (p
);
3323 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3326 skip_whitespace (p
);
3332 skip_whitespace (p
);
3336 /* As an extension to the official ARM syntax we allow:
3340 as a short hand for:
3343 inst
.instruction
|= PRE_INDEX
| INDEX_UP
;
3348 if (skip_past_comma (& p
) == FAIL
)
3350 inst
.error
= _("comma expected after closing square bracket");
3354 skip_whitespace (p
);
3361 write_back
= WRITE_BACK
;
3365 inst
.error
= _("pc may not be used in post-increment");
3369 if (cp_address_offset (& p
) == FAIL
)
3373 pre_inc
= PRE_INDEX
| INDEX_UP
;
3379 /* [Rn], {<expr>} */
3382 skip_whitespace (p
);
3384 if (my_get_expression (& inst
.reloc
.exp
, & p
))
3387 if (inst
.reloc
.exp
.X_op
== O_constant
)
3389 option
= inst
.reloc
.exp
.X_add_number
;
3391 if (option
> 255 || option
< 0)
3393 inst
.error
= _("'option' field too large");
3397 skip_whitespace (p
);
3401 inst
.error
= _("'}' expected at end of 'option' field");
3407 inst
.instruction
|= option
;
3408 inst
.instruction
|= INDEX_UP
;
3413 inst
.error
= _("non-constant expressions for 'option' field not supported");
3419 inst
.error
= _("# or { expected after comma");
3425 /* '['Rn, #expr']'[!] */
3427 if (skip_past_comma (& p
) == FAIL
)
3429 inst
.error
= _("pre-indexed expression expected");
3433 pre_inc
= PRE_INDEX
;
3435 if (cp_address_offset (& p
) == FAIL
)
3438 skip_whitespace (p
);
3442 inst
.error
= _("missing ]");
3446 skip_whitespace (p
);
3448 if (wb_ok
&& *p
== '!')
3452 inst
.error
= _("pc may not be used with write-back");
3457 write_back
= WRITE_BACK
;
3463 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3466 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3467 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3468 inst
.reloc
.pc_rel
= 1;
3469 inst
.instruction
|= (REG_PC
<< 16);
3470 pre_inc
= PRE_INDEX
;
3473 inst
.instruction
|= write_back
| pre_inc
;
3479 cp_byte_address_offset (str
)
3484 skip_whitespace (* str
);
3486 if (! is_immediate_prefix (**str
))
3488 inst
.error
= _("immediate expression expected");
3494 if (my_get_expression (& inst
.reloc
.exp
, str
))
3497 if (inst
.reloc
.exp
.X_op
== O_constant
)
3499 offset
= inst
.reloc
.exp
.X_add_number
;
3501 if (offset
> 255 || offset
< -255)
3503 inst
.error
= _("offset too large");
3508 inst
.instruction
|= INDEX_UP
;
3512 inst
.instruction
|= offset
;
3515 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3521 cp_byte_address_required_here (str
)
3533 skip_whitespace (p
);
3535 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3538 skip_whitespace (p
);
3544 if (skip_past_comma (& p
) == SUCCESS
)
3547 write_back
= WRITE_BACK
;
3551 inst
.error
= _("pc may not be used in post-increment");
3555 if (cp_byte_address_offset (& p
) == FAIL
)
3559 pre_inc
= PRE_INDEX
| INDEX_UP
;
3563 /* '['Rn, #expr']'[!] */
3565 if (skip_past_comma (& p
) == FAIL
)
3567 inst
.error
= _("pre-indexed expression expected");
3571 pre_inc
= PRE_INDEX
;
3573 if (cp_byte_address_offset (& p
) == FAIL
)
3576 skip_whitespace (p
);
3580 inst
.error
= _("missing ]");
3584 skip_whitespace (p
);
3590 inst
.error
= _("pc may not be used with write-back");
3595 write_back
= WRITE_BACK
;
3601 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3604 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM_S2
;
3605 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3606 inst
.reloc
.pc_rel
= 1;
3607 inst
.instruction
|= (REG_PC
<< 16);
3608 pre_inc
= PRE_INDEX
;
3611 inst
.instruction
|= write_back
| pre_inc
;
3620 /* Do nothing really. */
3631 /* Only one syntax. */
3632 skip_whitespace (str
);
3634 if (reg_required_here (&str
, 12) == FAIL
)
3636 inst
.error
= BAD_ARGS
;
3640 if (skip_past_comma (&str
) == FAIL
)
3642 inst
.error
= _("comma expected after register name");
3646 skip_whitespace (str
);
3648 if ( strcmp (str
, "CPSR") == 0
3649 || strcmp (str
, "SPSR") == 0
3650 /* Lower case versions for backwards compatability. */
3651 || strcmp (str
, "cpsr") == 0
3652 || strcmp (str
, "spsr") == 0)
3655 /* This is for backwards compatability with older toolchains. */
3656 else if ( strcmp (str
, "cpsr_all") == 0
3657 || strcmp (str
, "spsr_all") == 0)
3661 inst
.error
= _("CPSR or SPSR expected");
3665 if (* str
== 's' || * str
== 'S')
3666 inst
.instruction
|= SPSR_BIT
;
3672 /* Two possible forms:
3673 "{C|S}PSR_<field>, Rm",
3674 "{C|S}PSR_f, #expression". */
3680 skip_whitespace (str
);
3682 if (psr_required_here (& str
) == FAIL
)
3685 if (skip_past_comma (& str
) == FAIL
)
3687 inst
.error
= _("comma missing after psr flags");
3691 skip_whitespace (str
);
3693 if (reg_required_here (& str
, 0) != FAIL
)
3700 if (! is_immediate_prefix (* str
))
3703 _("only a register or immediate value can follow a psr flag");
3710 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3713 _("only a register or immediate value can follow a psr flag");
3717 #if 0 /* The first edition of the ARM architecture manual stated that
3718 writing anything other than the flags with an immediate operation
3719 had UNPREDICTABLE effects. This constraint was removed in the
3720 second edition of the specification. */
3721 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3722 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3724 inst
.error
= _("immediate value cannot be used to set this field");
3729 inst
.instruction
|= INST_IMMEDIATE
;
3731 if (inst
.reloc
.exp
.X_add_symbol
)
3733 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3734 inst
.reloc
.pc_rel
= 0;
3738 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3740 if (value
== (unsigned) FAIL
)
3742 inst
.error
= _("invalid constant");
3746 inst
.instruction
|= value
;
3753 /* Long Multiply Parser
3754 UMULL RdLo, RdHi, Rm, Rs
3755 SMULL RdLo, RdHi, Rm, Rs
3756 UMLAL RdLo, RdHi, Rm, Rs
3757 SMLAL RdLo, RdHi, Rm, Rs. */
3763 int rdlo
, rdhi
, rm
, rs
;
3765 /* Only one format "rdlo, rdhi, rm, rs". */
3766 skip_whitespace (str
);
3768 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3770 inst
.error
= BAD_ARGS
;
3774 if (skip_past_comma (&str
) == FAIL
3775 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3777 inst
.error
= BAD_ARGS
;
3781 if (skip_past_comma (&str
) == FAIL
3782 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3784 inst
.error
= BAD_ARGS
;
3788 /* rdhi, rdlo and rm must all be different. */
3789 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3790 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3792 if (skip_past_comma (&str
) == FAIL
3793 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3795 inst
.error
= BAD_ARGS
;
3799 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3801 inst
.error
= BAD_PC
;
3815 /* Only one format "rd, rm, rs". */
3816 skip_whitespace (str
);
3818 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3820 inst
.error
= BAD_ARGS
;
3826 inst
.error
= BAD_PC
;
3830 if (skip_past_comma (&str
) == FAIL
3831 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3833 inst
.error
= BAD_ARGS
;
3839 inst
.error
= BAD_PC
;
3844 as_tsktsk (_("rd and rm should be different in mul"));
3846 if (skip_past_comma (&str
) == FAIL
3847 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3849 inst
.error
= BAD_ARGS
;
3855 inst
.error
= BAD_PC
;
3869 /* Only one format "rd, rm, rs, rn". */
3870 skip_whitespace (str
);
3872 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3874 inst
.error
= BAD_ARGS
;
3880 inst
.error
= BAD_PC
;
3884 if (skip_past_comma (&str
) == FAIL
3885 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3887 inst
.error
= BAD_ARGS
;
3893 inst
.error
= BAD_PC
;
3898 as_tsktsk (_("rd and rm should be different in mla"));
3900 if (skip_past_comma (&str
) == FAIL
3901 || (rd
= reg_required_here (&str
, 8)) == FAIL
3902 || skip_past_comma (&str
) == FAIL
3903 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3905 inst
.error
= BAD_ARGS
;
3909 if (rd
== REG_PC
|| rm
== REG_PC
)
3911 inst
.error
= BAD_PC
;
3919 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3920 Advances *str to the next non-alphanumeric.
3921 Returns 0, or else FAIL (in which case sets inst.error).
3923 (In a future XScale, there may be accumulators other than zero.
3924 At that time this routine and its callers can be upgraded to suit.) */
3927 accum0_required_here (str
)
3930 static char buff
[128]; /* Note the address is taken. Hence, static. */
3933 int result
= 0; /* The accum number. */
3935 skip_whitespace (p
);
3937 *str
= p
; /* Advance caller's string pointer too. */
3942 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3944 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3946 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3951 *p
= c
; /* Unzap. */
3952 *str
= p
; /* Caller's string pointer to after match. */
3956 /* Expects **str -> after a comma. May be leading blanks.
3957 Advances *str, recognizing a load mode, and setting inst.instruction.
3958 Returns rn, or else FAIL (in which case may set inst.error
3959 and not advance str)
3961 Note: doesn't know Rd, so no err checks that require such knowledge. */
3964 ld_mode_required_here (string
)
3967 char * str
= * string
;
3971 skip_whitespace (str
);
3977 skip_whitespace (str
);
3979 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3982 skip_whitespace (str
);
3988 if (skip_past_comma (& str
) == SUCCESS
)
3990 /* [Rn],... (post inc) */
3991 if (ldst_extend_v4 (&str
) == FAIL
)
3996 skip_whitespace (str
);
4001 inst
.instruction
|= WRITE_BACK
;
4004 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
4010 if (skip_past_comma (& str
) == FAIL
)
4012 inst
.error
= _("pre-indexed expression expected");
4018 if (ldst_extend_v4 (&str
) == FAIL
)
4021 skip_whitespace (str
);
4023 if (* str
++ != ']')
4025 inst
.error
= _("missing ]");
4029 skip_whitespace (str
);
4034 inst
.instruction
|= WRITE_BACK
;
4038 else if (* str
== '=') /* ldr's "r,=label" syntax */
4039 /* We should never reach here, because <text> = <expression> is
4040 caught gas/read.c read_a_source_file() as a .set operation. */
4042 else /* PC +- 8 bit immediate offset. */
4044 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4047 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
4048 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
4049 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
4050 inst
.reloc
.pc_rel
= 1;
4051 inst
.instruction
|= (REG_PC
<< 16);
4057 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
4063 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4064 SMLAxy{cond} Rd,Rm,Rs,Rn
4065 SMLAWy{cond} Rd,Rm,Rs,Rn
4066 Error if any register is R15. */
4074 skip_whitespace (str
);
4076 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4077 || skip_past_comma (& str
) == FAIL
4078 || (rm
= reg_required_here (& str
, 0)) == FAIL
4079 || skip_past_comma (& str
) == FAIL
4080 || (rs
= reg_required_here (& str
, 8)) == FAIL
4081 || skip_past_comma (& str
) == FAIL
4082 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
4083 inst
.error
= BAD_ARGS
;
4085 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
4086 inst
.error
= BAD_PC
;
4092 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4093 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4094 Error if any register is R15.
4095 Warning if Rdlo == Rdhi. */
4101 int rdlo
, rdhi
, rm
, rs
;
4103 skip_whitespace (str
);
4105 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
4106 || skip_past_comma (& str
) == FAIL
4107 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
4108 || skip_past_comma (& str
) == FAIL
4109 || (rm
= reg_required_here (& str
, 0)) == FAIL
4110 || skip_past_comma (& str
) == FAIL
4111 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4113 inst
.error
= BAD_ARGS
;
4117 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4119 inst
.error
= BAD_PC
;
4124 as_tsktsk (_("rdhi and rdlo must be different"));
4129 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4130 SMULxy{cond} Rd,Rm,Rs
4131 Error if any register is R15. */
4139 skip_whitespace (str
);
4141 if ((rd
= reg_required_here (& str
, 16)) == FAIL
4142 || skip_past_comma (& str
) == FAIL
4143 || (rm
= reg_required_here (& str
, 0)) == FAIL
4144 || skip_past_comma (& str
) == FAIL
4145 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
4146 inst
.error
= BAD_ARGS
;
4148 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
4149 inst
.error
= BAD_PC
;
4155 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4156 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4157 Error if any register is R15. */
4165 skip_whitespace (str
);
4167 if ((rd
= reg_required_here (& str
, 12)) == FAIL
4168 || skip_past_comma (& str
) == FAIL
4169 || (rm
= reg_required_here (& str
, 0)) == FAIL
4170 || skip_past_comma (& str
) == FAIL
4171 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4172 inst
.error
= BAD_ARGS
;
4174 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
4175 inst
.error
= BAD_PC
;
4181 /* ARM V5E (el Segundo)
4182 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4183 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4185 These are equivalent to the XScale instructions MAR and MRA,
4186 respectively, when coproc == 0, opcode == 0, and CRm == 0.
4188 Result unpredicatable if Rd or Rn is R15. */
4196 skip_whitespace (str
);
4198 if (co_proc_number (& str
) == FAIL
)
4201 inst
.error
= BAD_ARGS
;
4205 if (skip_past_comma (& str
) == FAIL
4206 || cp_opc_expr (& str
, 4, 4) == FAIL
)
4209 inst
.error
= BAD_ARGS
;
4213 if (skip_past_comma (& str
) == FAIL
4214 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
4217 inst
.error
= BAD_ARGS
;
4221 if (skip_past_comma (& str
) == FAIL
4222 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
4225 inst
.error
= BAD_ARGS
;
4229 /* Unpredictable result if rd or rn is R15. */
4230 if (rd
== REG_PC
|| rn
== REG_PC
)
4232 (_("Warning: instruction unpredictable when using r15"));
4234 if (skip_past_comma (& str
) == FAIL
4235 || cp_reg_required_here (& str
, 0) == FAIL
)
4238 inst
.error
= BAD_ARGS
;
4245 /* ARM V5 count-leading-zeroes instruction (argument parse)
4246 CLZ{<cond>} <Rd>, <Rm>
4247 Condition defaults to COND_ALWAYS.
4248 Error if Rd or Rm are R15. */
4256 skip_whitespace (str
);
4258 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
4259 || (skip_past_comma (& str
) == FAIL
)
4260 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
4261 inst
.error
= BAD_ARGS
;
4263 else if (rd
== REG_PC
|| rm
== REG_PC
)
4264 inst
.error
= BAD_PC
;
4270 /* ARM V5 (argument parse)
4271 LDC2{L} <coproc>, <CRd>, <addressing mode>
4272 STC2{L} <coproc>, <CRd>, <addressing mode>
4273 Instruction is not conditional, and has 0xf in the codition field.
4274 Otherwise, it's the same as LDC/STC. */
4280 skip_whitespace (str
);
4282 if (co_proc_number (& str
) == FAIL
)
4285 inst
.error
= BAD_ARGS
;
4287 else if (skip_past_comma (& str
) == FAIL
4288 || cp_reg_required_here (& str
, 12) == FAIL
)
4291 inst
.error
= BAD_ARGS
;
4293 else if (skip_past_comma (& str
) == FAIL
4294 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
4297 inst
.error
= BAD_ARGS
;
4303 /* ARM V5 (argument parse)
4304 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4305 Instruction is not conditional, and has 0xf in the condition field.
4306 Otherwise, it's the same as CDP. */
4312 skip_whitespace (str
);
4314 if (co_proc_number (& str
) == FAIL
)
4317 inst
.error
= BAD_ARGS
;
4321 if (skip_past_comma (& str
) == FAIL
4322 || cp_opc_expr (& str
, 20,4) == FAIL
)
4325 inst
.error
= BAD_ARGS
;
4329 if (skip_past_comma (& str
) == FAIL
4330 || cp_reg_required_here (& str
, 12) == FAIL
)
4333 inst
.error
= BAD_ARGS
;
4337 if (skip_past_comma (& str
) == FAIL
4338 || cp_reg_required_here (& str
, 16) == FAIL
)
4341 inst
.error
= BAD_ARGS
;
4345 if (skip_past_comma (& str
) == FAIL
4346 || cp_reg_required_here (& str
, 0) == FAIL
)
4349 inst
.error
= BAD_ARGS
;
4353 if (skip_past_comma (& str
) == SUCCESS
)
4355 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4358 inst
.error
= BAD_ARGS
;
4366 /* ARM V5 (argument parse)
4367 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4368 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4369 Instruction is not conditional, and has 0xf in the condition field.
4370 Otherwise, it's the same as MCR/MRC. */
4376 skip_whitespace (str
);
4378 if (co_proc_number (& str
) == FAIL
)
4381 inst
.error
= BAD_ARGS
;
4385 if (skip_past_comma (& str
) == FAIL
4386 || cp_opc_expr (& str
, 21, 3) == FAIL
)
4389 inst
.error
= BAD_ARGS
;
4393 if (skip_past_comma (& str
) == FAIL
4394 || reg_required_here (& str
, 12) == FAIL
)
4397 inst
.error
= BAD_ARGS
;
4401 if (skip_past_comma (& str
) == FAIL
4402 || cp_reg_required_here (& str
, 16) == FAIL
)
4405 inst
.error
= BAD_ARGS
;
4409 if (skip_past_comma (& str
) == FAIL
4410 || cp_reg_required_here (& str
, 0) == FAIL
)
4413 inst
.error
= BAD_ARGS
;
4417 if (skip_past_comma (& str
) == SUCCESS
)
4419 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
4422 inst
.error
= BAD_ARGS
;
4430 /* ARM v5TEJ. Jump to Jazelle code. */
4437 skip_whitespace (str
);
4439 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
4441 inst
.error
= BAD_ARGS
;
4445 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
4447 as_tsktsk (_("use of r15 in bxj is not really useful"));
4452 /* THUMB V5 breakpoint instruction (argument parse)
4460 unsigned long number
;
4462 skip_whitespace (str
);
4464 /* Allow optional leading '#'. */
4465 if (is_immediate_prefix (*str
))
4468 memset (& expr
, '\0', sizeof (expr
));
4469 if (my_get_expression (& expr
, & str
)
4470 || (expr
.X_op
!= O_constant
4471 /* As a convenience we allow 'bkpt' without an operand. */
4472 && expr
.X_op
!= O_absent
))
4474 inst
.error
= _("bad expression");
4478 number
= expr
.X_add_number
;
4480 /* Check it fits an 8 bit unsigned. */
4481 if (number
!= (number
& 0xff))
4483 inst
.error
= _("immediate value out of range");
4487 inst
.instruction
|= number
;
4492 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4493 Expects inst.instruction is set for BLX(1).
4494 Note: this is cloned from do_branch, and the reloc changed to be a
4495 new one that can cope with setting one extra bit (the H bit). */
4501 if (my_get_expression (& inst
.reloc
.exp
, & str
))
4508 /* ScottB: February 5, 1998 */
4509 /* Check to see of PLT32 reloc required for the instruction. */
4511 /* arm_parse_reloc() works on input_line_pointer.
4512 We actually want to parse the operands to the branch instruction
4513 passed in 'str'. Save the input pointer and restore it later. */
4514 save_in
= input_line_pointer
;
4515 input_line_pointer
= str
;
4517 if (inst
.reloc
.exp
.X_op
== O_symbol
4519 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
4521 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
4522 inst
.reloc
.pc_rel
= 0;
4523 /* Modify str to point to after parsed operands, otherwise
4524 end_of_line() will complain about the (PLT) left in str. */
4525 str
= input_line_pointer
;
4529 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4530 inst
.reloc
.pc_rel
= 1;
4533 input_line_pointer
= save_in
;
4536 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
4537 inst
.reloc
.pc_rel
= 1;
4538 #endif /* OBJ_ELF */
4543 /* ARM V5 branch-link-exchange instruction (argument parse)
4544 BLX <target_addr> ie BLX(1)
4545 BLX{<condition>} <Rm> ie BLX(2)
4546 Unfortunately, there are two different opcodes for this mnemonic.
4547 So, the insns[].value is not used, and the code here zaps values
4548 into inst.instruction.
4549 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4558 skip_whitespace (mystr
);
4559 rm
= reg_required_here (& mystr
, 0);
4561 /* The above may set inst.error. Ignore his opinion. */
4566 /* Arg is a register.
4567 Use the condition code our caller put in inst.instruction.
4568 Pass ourselves off as a BX with a funny opcode. */
4569 inst
.instruction
|= 0x012fff30;
4574 /* This must be is BLX <target address>, no condition allowed. */
4575 if (inst
.instruction
!= COND_ALWAYS
)
4577 inst
.error
= BAD_COND
;
4581 inst
.instruction
= 0xfafffffe;
4583 /* Process like a B/BL, but with a different reloc.
4584 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4589 /* ARM V5 Thumb BLX (argument parse)
4590 BLX <target_addr> which is BLX(1)
4591 BLX <Rm> which is BLX(2)
4592 Unfortunately, there are two different opcodes for this mnemonic.
4593 So, the tinsns[].value is not used, and the code here zaps values
4594 into inst.instruction. */
4603 skip_whitespace (mystr
);
4604 inst
.instruction
= 0x4780;
4606 /* Note that this call is to the ARM register recognizer. BLX(2)
4607 uses the ARM register space, not the Thumb one, so a call to
4608 thumb_reg() would be wrong. */
4609 rm
= reg_required_here (& mystr
, 3);
4614 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4619 /* No ARM register. This must be BLX(1). Change the .instruction. */
4620 inst
.instruction
= 0xf7ffeffe;
4623 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4626 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4627 inst
.reloc
.pc_rel
= 1;
4630 end_of_line (mystr
);
4633 /* ARM V5 breakpoint instruction (argument parse)
4634 BKPT <16 bit unsigned immediate>
4635 Instruction is not conditional.
4636 The bit pattern given in insns[] has the COND_ALWAYS condition,
4637 and it is an error if the caller tried to override that. */
4644 unsigned long number
;
4646 skip_whitespace (str
);
4648 /* Allow optional leading '#'. */
4649 if (is_immediate_prefix (* str
))
4652 memset (& expr
, '\0', sizeof (expr
));
4654 if (my_get_expression (& expr
, & str
)
4655 || (expr
.X_op
!= O_constant
4656 /* As a convenience we allow 'bkpt' without an operand. */
4657 && expr
.X_op
!= O_absent
))
4659 inst
.error
= _("bad expression");
4663 number
= expr
.X_add_number
;
4665 /* Check it fits a 16 bit unsigned. */
4666 if (number
!= (number
& 0xffff))
4668 inst
.error
= _("immediate value out of range");
4672 /* Top 12 of 16 bits to bits 19:8. */
4673 inst
.instruction
|= (number
& 0xfff0) << 4;
4675 /* Bottom 4 of 16 bits to bits 3:0. */
4676 inst
.instruction
|= number
& 0xf;
4681 static unsigned long check_iwmmxt_insn
PARAMS ((char *, enum iwmmxt_insn_type
, int));
4683 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
4685 static unsigned long
4686 check_iwmmxt_insn (str
, insn_type
, immediate_size
)
4688 enum iwmmxt_insn_type insn_type
;
4692 const char * inst_error
;
4694 unsigned long number
;
4696 inst_error
= inst
.error
;
4698 inst
.error
= BAD_ARGS
;
4699 skip_whitespace (str
);
4704 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
4709 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
)) == FAIL
)
4714 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4715 || skip_past_comma (&str
) == FAIL
4716 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4721 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4722 || skip_past_comma (&str
) == FAIL
4723 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4724 || skip_past_comma (&str
) == FAIL
4725 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4730 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4731 || skip_past_comma (&str
) == FAIL
4732 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4733 || skip_past_comma (&str
) == FAIL
4734 || wreg_required_here (&str
, 0, IWMMXT_REG_WCG
) == FAIL
))
4739 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4740 || skip_past_comma (&str
) == FAIL
4741 || reg_required_here (&str
, 12) == FAIL
))
4746 if ((reg_required_here (&str
, 12) == FAIL
4747 || skip_past_comma (&str
) == FAIL
4748 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
))
4753 if ((wreg_required_here (&str
, 5, IWMMXT_REG_WR
) == FAIL
4754 || skip_past_comma (&str
) == FAIL
4755 || reg_required_here (&str
, 0) == FAIL
4756 || skip_past_comma (&str
) == FAIL
4757 || reg_required_here (&str
, 12) == FAIL
))
4762 if ((wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4763 || skip_past_comma (&str
) == FAIL
4764 || reg_required_here (&str
, 12) == FAIL
4765 || skip_past_comma (&str
) == FAIL
4766 || reg_required_here (&str
, 16) == FAIL
))
4771 if ((reg_required_here (&str
, 12) == FAIL
4772 || skip_past_comma (&str
) == FAIL
4773 || reg_required_here (&str
, 16) == FAIL
4774 || skip_past_comma (&str
) == FAIL
4775 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
))
4780 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
4781 || skip_past_comma (&str
) == FAIL
4782 || reg_required_here (&str
, 12) == FAIL
))
4787 if ((reg_required_here (&str
, 12) == FAIL
4788 || skip_past_comma (&str
) == FAIL
4789 || wreg_required_here (&str
, 16, IWMMXT_REG_WC
) == FAIL
))
4794 if ((wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4795 || skip_past_comma (&str
) == FAIL
4796 || reg_required_here (&str
, 12) == FAIL
4797 || skip_past_comma (&str
) == FAIL
))
4802 if ((reg_required_here (&str
, 12) == FAIL
4803 || skip_past_comma (&str
) == FAIL
))
4808 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4809 || skip_past_comma (&str
) == FAIL
4810 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4811 || skip_past_comma (&str
) == FAIL
4812 || wreg_required_here (&str
, 0, IWMMXT_REG_WR
) == FAIL
4813 || skip_past_comma (&str
) == FAIL
))
4818 if ((reg_required_here (&str
, 12) == FAIL
4819 || skip_past_comma (&str
) == FAIL
4820 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4821 || skip_past_comma (&str
) == FAIL
))
4826 if ((wreg_required_here (&str
, 12, IWMMXT_REG_WR
) == FAIL
4827 || skip_past_comma (&str
) == FAIL
4828 || wreg_required_here (&str
, 16, IWMMXT_REG_WR
) == FAIL
4829 || skip_past_comma (&str
) == FAIL
))
4834 if (immediate_size
== 0)
4837 inst
.error
= inst_error
;
4842 skip_whitespace (str
);
4844 /* Allow optional leading '#'. */
4845 if (is_immediate_prefix (* str
))
4848 memset (& expr
, '\0', sizeof (expr
));
4850 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4852 inst
.error
= _("bad or missing expression");
4856 number
= expr
.X_add_number
;
4858 if (number
!= (number
& immediate_size
))
4860 inst
.error
= _("immediate value out of range");
4864 inst
.error
= inst_error
;
4870 do_iwmmxt_byte_addr (str
)
4873 int op
= (inst
.instruction
& 0x300) >> 8;
4876 inst
.instruction
&= ~0x300;
4877 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
4879 skip_whitespace (str
);
4881 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
4882 || skip_past_comma (& str
) == FAIL
4883 || cp_byte_address_required_here (&str
) == FAIL
)
4886 inst
.error
= BAD_ARGS
;
4891 if (wc_register (reg
))
4893 as_bad (_("non-word size not supported with control register"));
4894 inst
.instruction
|= 0xf0000100;
4895 inst
.instruction
&= ~0x00400000;
4900 do_iwmmxt_tandc (str
)
4905 reg
= check_iwmmxt_insn (str
, check_rd
, 0);
4907 if (reg
!= REG_PC
&& !inst
.error
)
4908 inst
.error
= _("only r15 allowed here");
4913 do_iwmmxt_tbcst (str
)
4916 check_iwmmxt_insn (str
, check_tbcst
, 0);
4922 do_iwmmxt_textrc (str
)
4925 unsigned long number
;
4927 if ((number
= check_iwmmxt_insn (str
, check_textrc
, 7)) == (unsigned long) FAIL
)
4930 inst
.instruction
|= number
& 0x7;
4935 do_iwmmxt_textrm (str
)
4938 unsigned long number
;
4940 if ((number
= check_iwmmxt_insn (str
, check_textrm
, 7)) == (unsigned long) FAIL
)
4943 inst
.instruction
|= number
& 0x7;
4947 do_iwmmxt_tinsr (str
)
4950 unsigned long number
;
4952 if ((number
= check_iwmmxt_insn (str
, check_tinsr
, 7)) == (unsigned long) FAIL
)
4955 inst
.instruction
|= number
& 0x7;
4960 do_iwmmxt_tmcr (str
)
4963 check_iwmmxt_insn (str
, check_tmcr
, 0);
4969 do_iwmmxt_tmcrr (str
)
4972 check_iwmmxt_insn (str
, check_tmcrr
, 0);
4978 do_iwmmxt_tmia (str
)
4981 check_iwmmxt_insn (str
, check_tmia
, 0);
4987 do_iwmmxt_tmovmsk (str
)
4990 check_iwmmxt_insn (str
, check_tmovmsk
, 0);
4996 do_iwmmxt_tmrc (str
)
4999 check_iwmmxt_insn (str
, check_tmrc
, 0);
5005 do_iwmmxt_tmrrc (str
)
5008 check_iwmmxt_insn (str
, check_tmrrc
, 0);
5014 do_iwmmxt_torc (str
)
5017 check_iwmmxt_insn (str
, check_rd
, 0);
5022 do_iwmmxt_waligni (str
)
5025 unsigned long number
;
5027 if ((number
= check_iwmmxt_insn (str
, check_waligni
, 7)) == (unsigned long) FAIL
)
5030 inst
.instruction
|= ((number
& 0x7) << 20);
5035 do_iwmmxt_wmov (str
)
5038 if (check_iwmmxt_insn (str
, check_wrwr
, 0) == (unsigned long) FAIL
)
5041 inst
.instruction
|= ((inst
.instruction
>> 16) & 0xf);
5046 do_iwmmxt_word_addr (str
)
5049 int op
= (inst
.instruction
& 0x300) >> 8;
5052 inst
.instruction
&= ~0x300;
5053 inst
.instruction
|= (op
& 1) << 22 | (op
& 2) << 7;
5055 skip_whitespace (str
);
5057 if ((reg
= wreg_required_here (&str
, 12, IWMMXT_REG_WR_OR_WC
)) == FAIL
5058 || skip_past_comma (& str
) == FAIL
5059 || cp_address_required_here (& str
, CP_WB_OK
) == FAIL
)
5062 inst
.error
= BAD_ARGS
;
5067 if (wc_register (reg
))
5069 if ((inst
.instruction
& COND_MASK
) != COND_ALWAYS
)
5070 as_bad (_("conditional execution not supported with control register"));
5072 as_bad (_("non-word size not supported with control register"));
5073 inst
.instruction
|= 0xf0000100;
5074 inst
.instruction
&= ~0x00400000;
5079 do_iwmmxt_wrwr (str
)
5082 check_iwmmxt_insn (str
, check_wrwr
, 0);
5088 do_iwmmxt_wrwrwcg (str
)
5091 check_iwmmxt_insn (str
, check_wrwrwcg
, 0);
5097 do_iwmmxt_wrwrwr (str
)
5100 check_iwmmxt_insn (str
, check_wrwrwr
, 0);
5106 do_iwmmxt_wshufh (str
)
5109 unsigned long number
;
5111 if ((number
= check_iwmmxt_insn (str
, check_wshufh
, 0xff)) == (unsigned long) FAIL
)
5114 inst
.instruction
|= ((number
& 0xf0) << 16) | (number
& 0xf);
5119 do_iwmmxt_wzero (str
)
5122 if (check_iwmmxt_insn (str
, check_wr
, 0) == (unsigned long) FAIL
)
5125 inst
.instruction
|= ((inst
.instruction
& 0xf) << 12) | ((inst
.instruction
& 0xf) << 16);
5129 /* Xscale multiply-accumulate (argument parse)
5132 MIAxycc acc0,Rm,Rs. */
5141 if (accum0_required_here (& str
) == FAIL
)
5142 inst
.error
= ERR_NO_ACCUM
;
5144 else if (skip_past_comma (& str
) == FAIL
5145 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
5146 inst
.error
= BAD_ARGS
;
5148 else if (skip_past_comma (& str
) == FAIL
5149 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
5150 inst
.error
= BAD_ARGS
;
5152 /* inst.instruction has now been zapped with both rm and rs. */
5153 else if (rm
== REG_PC
|| rs
== REG_PC
)
5154 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
5160 /* Xscale move-accumulator-register (argument parse)
5162 MARcc acc0,RdLo,RdHi. */
5170 if (accum0_required_here (& str
) == FAIL
)
5171 inst
.error
= ERR_NO_ACCUM
;
5173 else if (skip_past_comma (& str
) == FAIL
5174 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5175 inst
.error
= BAD_ARGS
;
5177 else if (skip_past_comma (& str
) == FAIL
5178 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5179 inst
.error
= BAD_ARGS
;
5181 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5182 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5183 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5189 /* Xscale move-register-accumulator (argument parse)
5191 MRAcc RdLo,RdHi,acc0. */
5200 skip_whitespace (str
);
5202 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
5203 inst
.error
= BAD_ARGS
;
5205 else if (skip_past_comma (& str
) == FAIL
5206 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
5207 inst
.error
= BAD_ARGS
;
5209 else if (skip_past_comma (& str
) == FAIL
5210 || accum0_required_here (& str
) == FAIL
)
5211 inst
.error
= ERR_NO_ACCUM
;
5213 /* inst.instruction has now been zapped with both rdlo and rdhi. */
5214 else if (rdlo
== rdhi
)
5215 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
5217 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
5218 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
5223 /* ARMv5TE: Preload-Cache
5227 Syntactically, like LDR with B=1, W=0, L=1. */
5235 skip_whitespace (str
);
5239 inst
.error
= _("'[' expected after PLD mnemonic");
5244 skip_whitespace (str
);
5246 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
5249 skip_whitespace (str
);
5255 skip_whitespace (str
);
5257 /* Post-indexed addressing is not allowed with PLD. */
5258 if (skip_past_comma (&str
) == SUCCESS
)
5261 = _("post-indexed expression used in preload instruction");
5264 else if (*str
== '!') /* [Rn]! */
5266 inst
.error
= _("writeback used in preload instruction");
5270 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
5272 else /* [Rn, ...] */
5274 if (skip_past_comma (& str
) == FAIL
)
5276 inst
.error
= _("pre-indexed expression expected");
5280 if (ldst_extend (&str
) == FAIL
)
5283 skip_whitespace (str
);
5287 inst
.error
= _("missing ]");
5292 skip_whitespace (str
);
5294 if (* str
== '!') /* [Rn]! */
5296 inst
.error
= _("writeback used in preload instruction");
5300 inst
.instruction
|= PRE_INDEX
;
5306 /* ARMv5TE load-consecutive (argument parse)
5319 skip_whitespace (str
);
5321 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
5323 inst
.error
= BAD_ARGS
;
5327 if (skip_past_comma (& str
) == FAIL
5328 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
5331 inst
.error
= BAD_ARGS
;
5335 /* inst.instruction has now been zapped with Rd and the addressing mode. */
5336 if (rd
& 1) /* Unpredictable result if Rd is odd. */
5338 inst
.error
= _("destination register must be even");
5344 inst
.error
= _("r14 not allowed here");
5348 if (((rd
== rn
) || (rd
+ 1 == rn
))
5349 && ((inst
.instruction
& WRITE_BACK
)
5350 || (!(inst
.instruction
& PRE_INDEX
))))
5351 as_warn (_("pre/post-indexing used when modified address register is destination"));
5353 /* For an index-register load, the index register must not overlap the
5354 destination (even if not write-back). */
5355 if ((inst
.instruction
& V4_STR_BIT
) == 0
5356 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
5358 int rm
= inst
.instruction
& 0x0000000f;
5360 if (rm
== rd
|| (rm
== rd
+ 1))
5361 as_warn (_("ldrd destination registers must not overlap index register"));
5367 /* Returns the index into fp_values of a floating point number,
5368 or -1 if not in the table. */
5371 my_get_float_expression (str
)
5374 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5380 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
5382 /* Look for a raw floating point number. */
5383 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
5384 && is_end_of_line
[(unsigned char) *save_in
])
5386 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5388 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5390 if (words
[j
] != fp_values
[i
][j
])
5394 if (j
== MAX_LITTLENUMS
)
5402 /* Try and parse a more complex expression, this will probably fail
5403 unless the code uses a floating point prefix (eg "0f"). */
5404 save_in
= input_line_pointer
;
5405 input_line_pointer
= *str
;
5406 if (expression (&exp
) == absolute_section
5407 && exp
.X_op
== O_big
5408 && exp
.X_add_number
< 0)
5410 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5412 if (gen_to_words (words
, 5, (long) 15) == 0)
5414 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
5416 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
5418 if (words
[j
] != fp_values
[i
][j
])
5422 if (j
== MAX_LITTLENUMS
)
5424 *str
= input_line_pointer
;
5425 input_line_pointer
= save_in
;
5432 *str
= input_line_pointer
;
5433 input_line_pointer
= save_in
;
5437 /* Return TRUE if anything in the expression is a bignum. */
5440 walk_no_bignums (sp
)
5443 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
5446 if (symbol_get_value_expression (sp
)->X_add_symbol
)
5448 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
5449 || (symbol_get_value_expression (sp
)->X_op_symbol
5450 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
5456 static int in_my_get_expression
= 0;
5459 my_get_expression (ep
, str
)
5466 save_in
= input_line_pointer
;
5467 input_line_pointer
= *str
;
5468 in_my_get_expression
= 1;
5469 seg
= expression (ep
);
5470 in_my_get_expression
= 0;
5472 if (ep
->X_op
== O_illegal
)
5474 /* We found a bad expression in md_operand(). */
5475 *str
= input_line_pointer
;
5476 input_line_pointer
= save_in
;
5481 if (seg
!= absolute_section
5482 && seg
!= text_section
5483 && seg
!= data_section
5484 && seg
!= bss_section
5485 && seg
!= undefined_section
)
5487 inst
.error
= _("bad_segment");
5488 *str
= input_line_pointer
;
5489 input_line_pointer
= save_in
;
5494 /* Get rid of any bignums now, so that we don't generate an error for which
5495 we can't establish a line number later on. Big numbers are never valid
5496 in instructions, which is where this routine is always called. */
5497 if (ep
->X_op
== O_big
5498 || (ep
->X_add_symbol
5499 && (walk_no_bignums (ep
->X_add_symbol
)
5501 && walk_no_bignums (ep
->X_op_symbol
)))))
5503 inst
.error
= _("invalid constant");
5504 *str
= input_line_pointer
;
5505 input_line_pointer
= save_in
;
5509 *str
= input_line_pointer
;
5510 input_line_pointer
= save_in
;
5514 /* We handle all bad expressions here, so that we can report the faulty
5515 instruction in the error message. */
5520 if (in_my_get_expression
)
5522 expr
->X_op
= O_illegal
;
5523 if (inst
.error
== NULL
)
5524 inst
.error
= _("bad expression");
5528 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5532 decode_shift (str
, unrestrict
)
5536 const struct asm_shift_name
* shift
;
5540 skip_whitespace (* str
);
5542 for (p
= * str
; ISALPHA (* p
); p
++)
5547 inst
.error
= _("shift expression expected");
5553 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
5558 inst
.error
= _("shift expression expected");
5562 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
5564 if (shift
->properties
->index
== SHIFT_RRX
)
5567 inst
.instruction
|= shift
->properties
->bit_field
;
5571 skip_whitespace (p
);
5573 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
5575 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
5579 else if (! is_immediate_prefix (* p
))
5581 inst
.error
= (unrestrict
5582 ? _("shift requires register or #expression")
5583 : _("shift requires #expression"));
5591 if (my_get_expression (& inst
.reloc
.exp
, & p
))
5594 /* Validate some simple #expressions. */
5595 if (inst
.reloc
.exp
.X_op
== O_constant
)
5597 unsigned num
= inst
.reloc
.exp
.X_add_number
;
5599 /* Reject operations greater than 32. */
5601 /* Reject a shift of 0 unless the mode allows it. */
5602 || (num
== 0 && shift
->properties
->allows_0
== 0)
5603 /* Reject a shift of 32 unless the mode allows it. */
5604 || (num
== 32 && shift
->properties
->allows_32
== 0)
5607 /* As a special case we allow a shift of zero for
5608 modes that do not support it to be recoded as an
5609 logical shift left of zero (ie nothing). We warn
5610 about this though. */
5613 as_warn (_("shift of 0 ignored."));
5614 shift
= & shift_names
[0];
5615 assert (shift
->properties
->index
== SHIFT_LSL
);
5619 inst
.error
= _("invalid immediate shift");
5624 /* Shifts of 32 are encoded as 0, for those shifts that
5629 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
5633 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
5634 inst
.reloc
.pc_rel
= 0;
5635 inst
.instruction
|= shift
->properties
->bit_field
;
5642 /* Do those data_ops which can take a negative immediate constant
5643 by altering the instuction. A bit of a hack really.
5647 by inverting the second operand, and
5650 by negating the second operand. */
5653 negate_data_op (instruction
, value
)
5654 unsigned long * instruction
;
5655 unsigned long value
;
5658 unsigned long negated
, inverted
;
5660 negated
= validate_immediate (-value
);
5661 inverted
= validate_immediate (~value
);
5663 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
5666 /* First negates. */
5667 case OPCODE_SUB
: /* ADD <-> SUB */
5668 new_inst
= OPCODE_ADD
;
5673 new_inst
= OPCODE_SUB
;
5677 case OPCODE_CMP
: /* CMP <-> CMN */
5678 new_inst
= OPCODE_CMN
;
5683 new_inst
= OPCODE_CMP
;
5687 /* Now Inverted ops. */
5688 case OPCODE_MOV
: /* MOV <-> MVN */
5689 new_inst
= OPCODE_MVN
;
5694 new_inst
= OPCODE_MOV
;
5698 case OPCODE_AND
: /* AND <-> BIC */
5699 new_inst
= OPCODE_BIC
;
5704 new_inst
= OPCODE_AND
;
5708 case OPCODE_ADC
: /* ADC <-> SBC */
5709 new_inst
= OPCODE_SBC
;
5714 new_inst
= OPCODE_ADC
;
5718 /* We cannot do anything. */
5723 if (value
== (unsigned) FAIL
)
5726 *instruction
&= OPCODE_MASK
;
5727 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
5738 skip_whitespace (* str
);
5740 if (reg_required_here (str
, 0) != FAIL
)
5742 if (skip_past_comma (str
) == SUCCESS
)
5743 /* Shift operation on register. */
5744 return decode_shift (str
, NO_SHIFT_RESTRICT
);
5750 /* Immediate expression. */
5751 if (is_immediate_prefix (**str
))
5756 if (my_get_expression (&inst
.reloc
.exp
, str
))
5759 if (inst
.reloc
.exp
.X_add_symbol
)
5761 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5762 inst
.reloc
.pc_rel
= 0;
5766 if (skip_past_comma (str
) == SUCCESS
)
5768 /* #x, y -- ie explicit rotation by Y. */
5769 if (my_get_expression (&expr
, str
))
5772 if (expr
.X_op
!= O_constant
)
5774 inst
.error
= _("constant expression expected");
5778 /* Rotate must be a multiple of 2. */
5779 if (((unsigned) expr
.X_add_number
) > 30
5780 || (expr
.X_add_number
& 1) != 0
5781 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
5783 inst
.error
= _("invalid constant");
5786 inst
.instruction
|= INST_IMMEDIATE
;
5787 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
5788 inst
.instruction
|= expr
.X_add_number
<< 7;
5792 /* Implicit rotation, select a suitable one. */
5793 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5797 /* Can't be done. Perhaps the code reads something like
5798 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
5799 if ((value
= negate_data_op (&inst
.instruction
,
5800 inst
.reloc
.exp
.X_add_number
))
5803 inst
.error
= _("invalid constant");
5808 inst
.instruction
|= value
;
5811 inst
.instruction
|= INST_IMMEDIATE
;
5816 inst
.error
= _("register or shift expression expected");
5825 skip_whitespace (* str
);
5827 if (fp_reg_required_here (str
, 0) != FAIL
)
5831 /* Immediate expression. */
5832 if (*((*str
)++) == '#')
5838 skip_whitespace (* str
);
5840 /* First try and match exact strings, this is to guarantee
5841 that some formats will work even for cross assembly. */
5843 for (i
= 0; fp_const
[i
]; i
++)
5845 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
5849 *str
+= strlen (fp_const
[i
]);
5850 if (is_end_of_line
[(unsigned char) **str
])
5852 inst
.instruction
|= i
+ 8;
5859 /* Just because we didn't get a match doesn't mean that the
5860 constant isn't valid, just that it is in a format that we
5861 don't automatically recognize. Try parsing it with
5862 the standard expression routines. */
5863 if ((i
= my_get_float_expression (str
)) >= 0)
5865 inst
.instruction
|= i
+ 8;
5869 inst
.error
= _("invalid floating point immediate expression");
5873 _("floating point register or immediate expression expected");
5882 skip_whitespace (str
);
5884 if (reg_required_here (&str
, 12) == FAIL
5885 || skip_past_comma (&str
) == FAIL
5886 || reg_required_here (&str
, 16) == FAIL
5887 || skip_past_comma (&str
) == FAIL
5888 || data_op2 (&str
) == FAIL
)
5891 inst
.error
= BAD_ARGS
;
5903 /* This is a pseudo-op of the form "adr rd, label" to be converted
5904 into a relative address of the form "add rd, pc, #label-.-8". */
5905 skip_whitespace (str
);
5907 if (reg_required_here (&str
, 12) == FAIL
5908 || skip_past_comma (&str
) == FAIL
5909 || my_get_expression (&inst
.reloc
.exp
, &str
))
5912 inst
.error
= BAD_ARGS
;
5916 /* Frag hacking will turn this into a sub instruction if the offset turns
5917 out to be negative. */
5918 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
5919 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
5920 inst
.reloc
.pc_rel
= 1;
5929 /* This is a pseudo-op of the form "adrl rd, label" to be converted
5930 into a relative address of the form:
5931 add rd, pc, #low(label-.-8)"
5932 add rd, rd, #high(label-.-8)" */
5934 skip_whitespace (str
);
5936 if (reg_required_here (&str
, 12) == FAIL
5937 || skip_past_comma (&str
) == FAIL
5938 || my_get_expression (&inst
.reloc
.exp
, &str
))
5941 inst
.error
= BAD_ARGS
;
5947 /* Frag hacking will turn this into a sub instruction if the offset turns
5948 out to be negative. */
5949 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
5950 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
5951 inst
.reloc
.pc_rel
= 1;
5952 inst
.size
= INSN_SIZE
* 2;
5961 skip_whitespace (str
);
5963 if (reg_required_here (&str
, 16) == FAIL
)
5966 inst
.error
= BAD_ARGS
;
5970 if (skip_past_comma (&str
) == FAIL
5971 || data_op2 (&str
) == FAIL
)
5974 inst
.error
= BAD_ARGS
;
5986 skip_whitespace (str
);
5988 if (reg_required_here (&str
, 12) == FAIL
)
5991 inst
.error
= BAD_ARGS
;
5995 if (skip_past_comma (&str
) == FAIL
5996 || data_op2 (&str
) == FAIL
)
5999 inst
.error
= BAD_ARGS
;
6018 if (my_get_expression (& inst
.reloc
.exp
, str
))
6021 if (inst
.reloc
.exp
.X_op
== O_constant
)
6023 int value
= inst
.reloc
.exp
.X_add_number
;
6025 if (value
< -4095 || value
> 4095)
6027 inst
.error
= _("address offset too large");
6037 inst
.instruction
|= add
| value
;
6041 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6042 inst
.reloc
.pc_rel
= 0;
6055 if (reg_required_here (str
, 0) == FAIL
)
6058 inst
.instruction
|= add
| OFFSET_REG
;
6059 if (skip_past_comma (str
) == SUCCESS
)
6060 return decode_shift (str
, SHIFT_RESTRICT
);
6074 skip_whitespace (str
);
6076 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
6079 inst
.error
= BAD_ARGS
;
6083 if (skip_past_comma (&str
) == FAIL
)
6085 inst
.error
= _("address expected");
6095 skip_whitespace (str
);
6097 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6100 /* Conflicts can occur on stores as well as loads. */
6101 conflict_reg
= (conflict_reg
== reg
);
6103 skip_whitespace (str
);
6109 if (skip_past_comma (&str
) == SUCCESS
)
6111 /* [Rn],... (post inc) */
6112 if (ldst_extend (&str
) == FAIL
)
6115 as_warn (_("%s register same as write-back base"),
6116 ((inst
.instruction
& LOAD_BIT
)
6117 ? _("destination") : _("source")));
6122 skip_whitespace (str
);
6127 as_warn (_("%s register same as write-back base"),
6128 ((inst
.instruction
& LOAD_BIT
)
6129 ? _("destination") : _("source")));
6131 inst
.instruction
|= WRITE_BACK
;
6134 inst
.instruction
|= INDEX_UP
;
6141 if (skip_past_comma (&str
) == FAIL
)
6143 inst
.error
= _("pre-indexed expression expected");
6148 if (ldst_extend (&str
) == FAIL
)
6151 skip_whitespace (str
);
6155 inst
.error
= _("missing ]");
6159 skip_whitespace (str
);
6164 as_warn (_("%s register same as write-back base"),
6165 ((inst
.instruction
& LOAD_BIT
)
6166 ? _("destination") : _("source")));
6168 inst
.instruction
|= WRITE_BACK
;
6172 else if (*str
== '=')
6174 if ((inst
.instruction
& LOAD_BIT
) == 0)
6176 inst
.error
= _("invalid pseudo operation");
6180 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6183 skip_whitespace (str
);
6185 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6188 if (inst
.reloc
.exp
.X_op
!= O_constant
6189 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6191 inst
.error
= _("constant expression expected");
6195 if (inst
.reloc
.exp
.X_op
== O_constant
)
6197 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6201 /* This can be done with a mov instruction. */
6202 inst
.instruction
&= LITERAL_MASK
;
6203 inst
.instruction
|= (INST_IMMEDIATE
6204 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
6205 inst
.instruction
|= value
& 0xfff;
6210 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
6214 /* This can be done with a mvn instruction. */
6215 inst
.instruction
&= LITERAL_MASK
;
6216 inst
.instruction
|= (INST_IMMEDIATE
6217 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
6218 inst
.instruction
|= value
& 0xfff;
6224 /* Insert into literal pool. */
6225 if (add_to_lit_pool () == FAIL
)
6228 inst
.error
= _("literal pool insertion failed");
6232 /* Change the instruction exp to point to the pool. */
6233 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
6234 inst
.reloc
.pc_rel
= 1;
6235 inst
.instruction
|= (REG_PC
<< 16);
6240 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6243 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
6245 /* PC rel adjust. */
6246 inst
.reloc
.exp
.X_add_number
-= 8;
6248 inst
.reloc
.pc_rel
= 1;
6249 inst
.instruction
|= (REG_PC
<< 16);
6253 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6264 skip_whitespace (str
);
6266 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6269 inst
.error
= BAD_ARGS
;
6273 if (skip_past_comma (& str
) == FAIL
)
6275 inst
.error
= _("address expected");
6285 skip_whitespace (str
);
6287 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6290 /* ldrt/strt always use post-indexed addressing, so if the base is
6291 the same as Rd, we warn. */
6292 if (conflict_reg
== reg
)
6293 as_warn (_("%s register same as write-back base"),
6294 ((inst
.instruction
& LOAD_BIT
)
6295 ? _("destination") : _("source")));
6297 skip_whitespace (str
);
6303 if (skip_past_comma (&str
) == SUCCESS
)
6305 /* [Rn],... (post inc) */
6306 if (ldst_extend (&str
) == FAIL
)
6312 skip_whitespace (str
);
6314 /* Skip a write-back '!'. */
6318 inst
.instruction
|= INDEX_UP
;
6323 inst
.error
= _("post-indexed expression expected");
6329 inst
.error
= _("post-indexed expression expected");
6338 ldst_extend_v4 (str
)
6348 if (my_get_expression (& inst
.reloc
.exp
, str
))
6351 if (inst
.reloc
.exp
.X_op
== O_constant
)
6353 int value
= inst
.reloc
.exp
.X_add_number
;
6355 if (value
< -255 || value
> 255)
6357 inst
.error
= _("address offset too large");
6367 /* Halfword and signextension instructions have the
6368 immediate value split across bits 11..8 and bits 3..0. */
6369 inst
.instruction
|= (add
| HWOFFSET_IMM
6370 | ((value
>> 4) << 8) | (value
& 0xF));
6374 inst
.instruction
|= HWOFFSET_IMM
;
6375 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6376 inst
.reloc
.pc_rel
= 0;
6389 if (reg_required_here (str
, 0) == FAIL
)
6392 inst
.instruction
|= add
;
6397 /* Halfword and signed-byte load/store operations. */
6406 skip_whitespace (str
);
6408 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
6411 inst
.error
= BAD_ARGS
;
6415 if (skip_past_comma (& str
) == FAIL
)
6417 inst
.error
= _("address expected");
6427 skip_whitespace (str
);
6429 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6432 /* Conflicts can occur on stores as well as loads. */
6433 conflict_reg
= (conflict_reg
== reg
);
6435 skip_whitespace (str
);
6441 if (skip_past_comma (&str
) == SUCCESS
)
6443 /* [Rn],... (post inc) */
6444 if (ldst_extend_v4 (&str
) == FAIL
)
6447 as_warn (_("%s register same as write-back base"),
6448 ((inst
.instruction
& LOAD_BIT
)
6449 ? _("destination") : _("source")));
6454 inst
.instruction
|= HWOFFSET_IMM
;
6456 skip_whitespace (str
);
6461 as_warn (_("%s register same as write-back base"),
6462 ((inst
.instruction
& LOAD_BIT
)
6463 ? _("destination") : _("source")));
6465 inst
.instruction
|= WRITE_BACK
;
6468 inst
.instruction
|= INDEX_UP
;
6475 if (skip_past_comma (&str
) == FAIL
)
6477 inst
.error
= _("pre-indexed expression expected");
6482 if (ldst_extend_v4 (&str
) == FAIL
)
6485 skip_whitespace (str
);
6489 inst
.error
= _("missing ]");
6493 skip_whitespace (str
);
6498 as_warn (_("%s register same as write-back base"),
6499 ((inst
.instruction
& LOAD_BIT
)
6500 ? _("destination") : _("source")));
6502 inst
.instruction
|= WRITE_BACK
;
6506 else if (*str
== '=')
6508 if ((inst
.instruction
& LOAD_BIT
) == 0)
6510 inst
.error
= _("invalid pseudo operation");
6514 /* XXX Does this work correctly for half-word/byte ops? */
6515 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
6518 skip_whitespace (str
);
6520 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6523 if (inst
.reloc
.exp
.X_op
!= O_constant
6524 && inst
.reloc
.exp
.X_op
!= O_symbol
)
6526 inst
.error
= _("constant expression expected");
6530 if (inst
.reloc
.exp
.X_op
== O_constant
)
6532 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
6536 /* This can be done with a mov instruction. */
6537 inst
.instruction
&= LITERAL_MASK
;
6538 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
6539 inst
.instruction
|= value
& 0xfff;
6544 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
6548 /* This can be done with a mvn instruction. */
6549 inst
.instruction
&= LITERAL_MASK
;
6550 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
6551 inst
.instruction
|= value
& 0xfff;
6557 /* Insert into literal pool. */
6558 if (add_to_lit_pool () == FAIL
)
6561 inst
.error
= _("literal pool insertion failed");
6565 /* Change the instruction exp to point to the pool. */
6566 inst
.instruction
|= HWOFFSET_IMM
;
6567 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
6568 inst
.reloc
.pc_rel
= 1;
6569 inst
.instruction
|= (REG_PC
<< 16);
6574 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6577 inst
.instruction
|= HWOFFSET_IMM
;
6578 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
6580 /* PC rel adjust. */
6581 inst
.reloc
.exp
.X_add_number
-= 8;
6583 inst
.reloc
.pc_rel
= 1;
6584 inst
.instruction
|= (REG_PC
<< 16);
6588 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
6597 char * str
= * strp
;
6601 /* We come back here if we get ranges concatenated by '+' or '|'. */
6616 skip_whitespace (str
);
6618 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
6627 inst
.error
= _("bad range in register list");
6631 for (i
= cur_reg
+ 1; i
< reg
; i
++)
6633 if (range
& (1 << i
))
6635 (_("Warning: duplicated register (r%d) in register list"),
6643 if (range
& (1 << reg
))
6644 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6646 else if (reg
<= cur_reg
)
6647 as_tsktsk (_("Warning: register range not in ascending order"));
6652 while (skip_past_comma (&str
) != FAIL
6653 || (in_range
= 1, *str
++ == '-'));
6655 skip_whitespace (str
);
6659 inst
.error
= _("missing `}'");
6667 if (my_get_expression (&expr
, &str
))
6670 if (expr
.X_op
== O_constant
)
6672 if (expr
.X_add_number
6673 != (expr
.X_add_number
& 0x0000ffff))
6675 inst
.error
= _("invalid register mask");
6679 if ((range
& expr
.X_add_number
) != 0)
6681 int regno
= range
& expr
.X_add_number
;
6684 regno
= (1 << regno
) - 1;
6686 (_("Warning: duplicated register (r%d) in register list"),
6690 range
|= expr
.X_add_number
;
6694 if (inst
.reloc
.type
!= 0)
6696 inst
.error
= _("expression too complex");
6700 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
6701 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
6702 inst
.reloc
.pc_rel
= 0;
6706 skip_whitespace (str
);
6708 if (*str
== '|' || *str
== '+')
6714 while (another_range
);
6727 skip_whitespace (str
);
6729 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
6732 if (base_reg
== REG_PC
)
6734 inst
.error
= _("r15 not allowed as base register");
6738 skip_whitespace (str
);
6742 inst
.instruction
|= WRITE_BACK
;
6746 if (skip_past_comma (&str
) == FAIL
6747 || (range
= reg_list (&str
)) == FAIL
)
6750 inst
.error
= BAD_ARGS
;
6757 inst
.instruction
|= LDM_TYPE_2_OR_3
;
6760 if (inst
.instruction
& WRITE_BACK
)
6762 /* Check for unpredictable uses of writeback. */
6763 if (inst
.instruction
& LOAD_BIT
)
6765 /* Not allowed in LDM type 2. */
6766 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
6767 && ((range
& (1 << REG_PC
)) == 0))
6768 as_warn (_("writeback of base register is UNPREDICTABLE"));
6769 /* Only allowed if base reg not in list for other types. */
6770 else if (range
& (1 << base_reg
))
6771 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6775 /* Not allowed for type 2. */
6776 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
6777 as_warn (_("writeback of base register is UNPREDICTABLE"));
6778 /* Only allowed if base reg not in list, or first in list. */
6779 else if ((range
& (1 << base_reg
))
6780 && (range
& ((1 << base_reg
) - 1)))
6781 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6785 inst
.instruction
|= range
;
6794 skip_whitespace (str
);
6796 /* Allow optional leading '#'. */
6797 if (is_immediate_prefix (*str
))
6800 if (my_get_expression (& inst
.reloc
.exp
, & str
))
6803 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
6804 inst
.reloc
.pc_rel
= 0;
6816 skip_whitespace (str
);
6818 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
6823 inst
.error
= _("r15 not allowed in swap");
6827 if (skip_past_comma (&str
) == FAIL
6828 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
6831 inst
.error
= BAD_ARGS
;
6837 inst
.error
= _("r15 not allowed in swap");
6841 if (skip_past_comma (&str
) == FAIL
6844 inst
.error
= BAD_ARGS
;
6848 skip_whitespace (str
);
6850 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6855 inst
.error
= BAD_PC
;
6859 skip_whitespace (str
);
6863 inst
.error
= _("missing ]");
6875 if (my_get_expression (&inst
.reloc
.exp
, &str
))
6882 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6883 required for the instruction. */
6885 /* arm_parse_reloc () works on input_line_pointer.
6886 We actually want to parse the operands to the branch instruction
6887 passed in 'str'. Save the input pointer and restore it later. */
6888 save_in
= input_line_pointer
;
6889 input_line_pointer
= str
;
6890 if (inst
.reloc
.exp
.X_op
== O_symbol
6892 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
6894 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
6895 inst
.reloc
.pc_rel
= 0;
6896 /* Modify str to point to after parsed operands, otherwise
6897 end_of_line() will complain about the (PLT) left in str. */
6898 str
= input_line_pointer
;
6902 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6903 inst
.reloc
.pc_rel
= 1;
6905 input_line_pointer
= save_in
;
6908 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
6909 inst
.reloc
.pc_rel
= 1;
6910 #endif /* OBJ_ELF */
6922 skip_whitespace (str
);
6924 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
6926 inst
.error
= BAD_ARGS
;
6930 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
6932 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6941 /* Co-processor data operation.
6942 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
6943 skip_whitespace (str
);
6945 if (co_proc_number (&str
) == FAIL
)
6948 inst
.error
= BAD_ARGS
;
6952 if (skip_past_comma (&str
) == FAIL
6953 || cp_opc_expr (&str
, 20,4) == FAIL
)
6956 inst
.error
= BAD_ARGS
;
6960 if (skip_past_comma (&str
) == FAIL
6961 || cp_reg_required_here (&str
, 12) == FAIL
)
6964 inst
.error
= BAD_ARGS
;
6968 if (skip_past_comma (&str
) == FAIL
6969 || cp_reg_required_here (&str
, 16) == FAIL
)
6972 inst
.error
= BAD_ARGS
;
6976 if (skip_past_comma (&str
) == FAIL
6977 || cp_reg_required_here (&str
, 0) == FAIL
)
6980 inst
.error
= BAD_ARGS
;
6984 if (skip_past_comma (&str
) == SUCCESS
)
6986 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6989 inst
.error
= BAD_ARGS
;
7002 /* Co-processor register load/store.
7003 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
7005 skip_whitespace (str
);
7007 if (co_proc_number (&str
) == FAIL
)
7010 inst
.error
= BAD_ARGS
;
7014 if (skip_past_comma (&str
) == FAIL
7015 || cp_reg_required_here (&str
, 12) == FAIL
)
7018 inst
.error
= BAD_ARGS
;
7022 if (skip_past_comma (&str
) == FAIL
7023 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7026 inst
.error
= BAD_ARGS
;
7038 /* Co-processor register transfer.
7039 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
7041 skip_whitespace (str
);
7043 if (co_proc_number (&str
) == FAIL
)
7046 inst
.error
= BAD_ARGS
;
7050 if (skip_past_comma (&str
) == FAIL
7051 || cp_opc_expr (&str
, 21, 3) == FAIL
)
7054 inst
.error
= BAD_ARGS
;
7058 if (skip_past_comma (&str
) == FAIL
7059 || reg_required_here (&str
, 12) == FAIL
)
7062 inst
.error
= BAD_ARGS
;
7066 if (skip_past_comma (&str
) == FAIL
7067 || cp_reg_required_here (&str
, 16) == FAIL
)
7070 inst
.error
= BAD_ARGS
;
7074 if (skip_past_comma (&str
) == FAIL
7075 || cp_reg_required_here (&str
, 0) == FAIL
)
7078 inst
.error
= BAD_ARGS
;
7082 if (skip_past_comma (&str
) == SUCCESS
)
7084 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
7087 inst
.error
= BAD_ARGS
;
7100 /* FP control registers.
7101 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
7103 skip_whitespace (str
);
7105 if (reg_required_here (&str
, 12) == FAIL
)
7108 inst
.error
= BAD_ARGS
;
7120 skip_whitespace (str
);
7122 if (fp_reg_required_here (&str
, 12) == FAIL
)
7125 inst
.error
= BAD_ARGS
;
7129 if (skip_past_comma (&str
) == FAIL
7130 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7133 inst
.error
= BAD_ARGS
;
7146 skip_whitespace (str
);
7148 if (fp_reg_required_here (&str
, 12) == FAIL
)
7151 inst
.error
= BAD_ARGS
;
7155 /* Get Number of registers to transfer. */
7156 if (skip_past_comma (&str
) == FAIL
7157 || my_get_expression (&inst
.reloc
.exp
, &str
))
7160 inst
.error
= _("constant expression expected");
7164 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7166 inst
.error
= _("constant value required for number of registers");
7170 num_regs
= inst
.reloc
.exp
.X_add_number
;
7172 if (num_regs
< 1 || num_regs
> 4)
7174 inst
.error
= _("number of registers must be in the range [1:4]");
7181 inst
.instruction
|= CP_T_X
;
7184 inst
.instruction
|= CP_T_Y
;
7187 inst
.instruction
|= CP_T_Y
| CP_T_X
;
7195 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
7201 /* The instruction specified "ea" or "fd", so we can only accept
7202 [Rn]{!}. The instruction does not really support stacking or
7203 unstacking, so we have to emulate these by setting appropriate
7204 bits and offsets. */
7205 if (skip_past_comma (&str
) == FAIL
7209 inst
.error
= BAD_ARGS
;
7214 skip_whitespace (str
);
7216 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
7219 skip_whitespace (str
);
7223 inst
.error
= BAD_ARGS
;
7235 _("r15 not allowed as base register with write-back");
7242 if (inst
.instruction
& CP_T_Pre
)
7244 /* Pre-decrement. */
7245 offset
= 3 * num_regs
;
7247 inst
.instruction
|= CP_T_WB
;
7251 /* Post-increment. */
7254 inst
.instruction
|= CP_T_WB
;
7255 offset
= 3 * num_regs
;
7259 /* No write-back, so convert this into a standard pre-increment
7260 instruction -- aesthetically more pleasing. */
7261 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
7266 inst
.instruction
|= offset
;
7268 else if (skip_past_comma (&str
) == FAIL
7269 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
7272 inst
.error
= BAD_ARGS
;
7283 skip_whitespace (str
);
7285 if (fp_reg_required_here (&str
, 12) == FAIL
)
7288 inst
.error
= BAD_ARGS
;
7292 if (skip_past_comma (&str
) == FAIL
7293 || fp_reg_required_here (&str
, 16) == FAIL
)
7296 inst
.error
= BAD_ARGS
;
7300 if (skip_past_comma (&str
) == FAIL
7301 || fp_op2 (&str
) == FAIL
)
7304 inst
.error
= BAD_ARGS
;
7313 do_fpa_monadic (str
)
7316 skip_whitespace (str
);
7318 if (fp_reg_required_here (&str
, 12) == FAIL
)
7321 inst
.error
= BAD_ARGS
;
7325 if (skip_past_comma (&str
) == FAIL
7326 || fp_op2 (&str
) == FAIL
)
7329 inst
.error
= BAD_ARGS
;
7341 skip_whitespace (str
);
7343 if (fp_reg_required_here (&str
, 16) == FAIL
)
7346 inst
.error
= BAD_ARGS
;
7350 if (skip_past_comma (&str
) == FAIL
7351 || fp_op2 (&str
) == FAIL
)
7354 inst
.error
= BAD_ARGS
;
7363 do_fpa_from_reg (str
)
7366 skip_whitespace (str
);
7368 if (fp_reg_required_here (&str
, 16) == FAIL
)
7371 inst
.error
= BAD_ARGS
;
7375 if (skip_past_comma (&str
) == FAIL
7376 || reg_required_here (&str
, 12) == FAIL
)
7379 inst
.error
= BAD_ARGS
;
7391 skip_whitespace (str
);
7393 if (reg_required_here (&str
, 12) == FAIL
)
7396 if (skip_past_comma (&str
) == FAIL
7397 || fp_reg_required_here (&str
, 0) == FAIL
)
7400 inst
.error
= BAD_ARGS
;
7409 vfp_sp_reg_required_here (str
, pos
)
7411 enum vfp_sp_reg_pos pos
;
7416 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
7421 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
7425 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
7429 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
7438 /* In the few cases where we might be able to accept something else
7439 this error can be overridden. */
7440 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7442 /* Restore the start point. */
7448 vfp_dp_reg_required_here (str
, pos
)
7450 enum vfp_dp_reg_pos pos
;
7455 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
7460 inst
.instruction
|= reg
<< 12;
7464 inst
.instruction
|= reg
<< 16;
7468 inst
.instruction
|= reg
<< 0;
7477 /* In the few cases where we might be able to accept something else
7478 this error can be overridden. */
7479 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7481 /* Restore the start point. */
7487 do_vfp_sp_monadic (str
)
7490 skip_whitespace (str
);
7492 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7495 if (skip_past_comma (&str
) == FAIL
7496 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7499 inst
.error
= BAD_ARGS
;
7508 do_vfp_dp_monadic (str
)
7511 skip_whitespace (str
);
7513 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7516 if (skip_past_comma (&str
) == FAIL
7517 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7520 inst
.error
= BAD_ARGS
;
7529 do_vfp_sp_dyadic (str
)
7532 skip_whitespace (str
);
7534 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7537 if (skip_past_comma (&str
) == FAIL
7538 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
7539 || skip_past_comma (&str
) == FAIL
7540 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7543 inst
.error
= BAD_ARGS
;
7552 do_vfp_dp_dyadic (str
)
7555 skip_whitespace (str
);
7557 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7560 if (skip_past_comma (&str
) == FAIL
7561 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
7562 || skip_past_comma (&str
) == FAIL
7563 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7566 inst
.error
= BAD_ARGS
;
7575 do_vfp_reg_from_sp (str
)
7578 skip_whitespace (str
);
7580 if (reg_required_here (&str
, 12) == FAIL
)
7583 if (skip_past_comma (&str
) == FAIL
7584 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7587 inst
.error
= BAD_ARGS
;
7596 do_vfp_sp_reg2 (str
)
7599 skip_whitespace (str
);
7601 if (reg_required_here (&str
, 12) == FAIL
)
7604 if (skip_past_comma (&str
) == FAIL
7605 || reg_required_here (&str
, 16) == FAIL
7606 || skip_past_comma (&str
) == FAIL
)
7609 inst
.error
= BAD_ARGS
;
7613 /* We require exactly two consecutive SP registers. */
7614 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
7617 inst
.error
= _("only two consecutive VFP SP registers allowed here");
7625 do_vfp_sp_from_reg (str
)
7628 skip_whitespace (str
);
7630 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
7633 if (skip_past_comma (&str
) == FAIL
7634 || reg_required_here (&str
, 12) == FAIL
)
7637 inst
.error
= BAD_ARGS
;
7646 do_vfp_reg_from_dp (str
)
7649 skip_whitespace (str
);
7651 if (reg_required_here (&str
, 12) == FAIL
)
7654 if (skip_past_comma (&str
) == FAIL
7655 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7658 inst
.error
= BAD_ARGS
;
7667 do_vfp_reg2_from_dp (str
)
7670 skip_whitespace (str
);
7672 if (reg_required_here (&str
, 12) == FAIL
)
7675 if (skip_past_comma (&str
) == FAIL
7676 || reg_required_here (&str
, 16) == FAIL
7677 || skip_past_comma (&str
) == FAIL
7678 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7681 inst
.error
= BAD_ARGS
;
7690 do_vfp_dp_from_reg (str
)
7693 skip_whitespace (str
);
7695 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
7698 if (skip_past_comma (&str
) == FAIL
7699 || reg_required_here (&str
, 12) == FAIL
)
7702 inst
.error
= BAD_ARGS
;
7711 do_vfp_dp_from_reg2 (str
)
7714 skip_whitespace (str
);
7716 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7719 if (skip_past_comma (&str
) == FAIL
7720 || reg_required_here (&str
, 12) == FAIL
7721 || skip_past_comma (&str
) == FAIL
7722 || reg_required_here (&str
, 16))
7725 inst
.error
= BAD_ARGS
;
7733 static const struct vfp_reg
*
7740 const struct vfp_reg
*vreg
;
7744 /* Find the end of the current token. */
7749 while (ISALPHA (c
));
7754 for (vreg
= vfp_regs
+ 0;
7755 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
7758 if (strcmp (start
, vreg
->name
) == 0)
7771 vfp_psr_required_here (str
)
7775 const struct vfp_reg
*vreg
;
7777 vreg
= vfp_psr_parse (str
);
7781 inst
.instruction
|= vreg
->regno
;
7785 inst
.error
= _("VFP system register expected");
7792 do_vfp_reg_from_ctrl (str
)
7795 skip_whitespace (str
);
7797 if (reg_required_here (&str
, 12) == FAIL
)
7800 if (skip_past_comma (&str
) == FAIL
7801 || vfp_psr_required_here (&str
) == FAIL
)
7804 inst
.error
= BAD_ARGS
;
7813 do_vfp_ctrl_from_reg (str
)
7816 skip_whitespace (str
);
7818 if (vfp_psr_required_here (&str
) == FAIL
)
7821 if (skip_past_comma (&str
) == FAIL
7822 || reg_required_here (&str
, 12) == FAIL
)
7825 inst
.error
= BAD_ARGS
;
7834 do_vfp_sp_ldst (str
)
7837 skip_whitespace (str
);
7839 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7842 inst
.error
= BAD_ARGS
;
7846 if (skip_past_comma (&str
) == FAIL
7847 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7850 inst
.error
= BAD_ARGS
;
7859 do_vfp_dp_ldst (str
)
7862 skip_whitespace (str
);
7864 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7867 inst
.error
= BAD_ARGS
;
7871 if (skip_past_comma (&str
) == FAIL
7872 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
7875 inst
.error
= BAD_ARGS
;
7883 /* Parse and encode a VFP SP register list, storing the initial
7884 register in position POS and returning the range as the result. If
7885 the string is invalid return FAIL (an invalid range). */
7887 vfp_sp_reg_list (str
, pos
)
7889 enum vfp_sp_reg_pos pos
;
7897 unsigned long mask
= 0;
7904 skip_whitespace (*str
);
7906 tempinst
= inst
.instruction
;
7910 inst
.instruction
= 0;
7912 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
7915 if (count
== 0 || base_reg
> new_base
)
7917 base_reg
= new_base
;
7918 base_bits
= inst
.instruction
;
7921 if (mask
& (1 << new_base
))
7923 inst
.error
= _("invalid register list");
7927 if ((mask
>> new_base
) != 0 && ! warned
)
7929 as_tsktsk (_("register list not in ascending order"));
7933 mask
|= 1 << new_base
;
7936 skip_whitespace (*str
);
7938 if (**str
== '-') /* We have the start of a range expression */
7945 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
7948 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
7952 if (high_range
<= new_base
)
7954 inst
.error
= _("register range not in ascending order");
7958 for (new_base
++; new_base
<= high_range
; new_base
++)
7960 if (mask
& (1 << new_base
))
7962 inst
.error
= _("invalid register list");
7966 mask
|= 1 << new_base
;
7971 while (skip_past_comma (str
) != FAIL
);
7975 inst
.error
= _("invalid register list");
7983 /* Sanity check -- should have raised a parse error above. */
7984 if (count
== 0 || count
> 32)
7987 /* Final test -- the registers must be consecutive. */
7990 if ((mask
& (1 << base_reg
++)) == 0)
7992 inst
.error
= _("non-contiguous register range");
7997 inst
.instruction
= tempinst
| base_bits
;
8002 vfp_dp_reg_list (str
)
8010 unsigned long mask
= 0;
8017 skip_whitespace (*str
);
8019 tempinst
= inst
.instruction
;
8023 inst
.instruction
= 0;
8025 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
8028 if (count
== 0 || base_reg
> new_base
)
8030 base_reg
= new_base
;
8031 range
= inst
.instruction
;
8034 if (mask
& (1 << new_base
))
8036 inst
.error
= _("invalid register list");
8040 if ((mask
>> new_base
) != 0 && ! warned
)
8042 as_tsktsk (_("register list not in ascending order"));
8046 mask
|= 1 << new_base
;
8049 skip_whitespace (*str
);
8051 if (**str
== '-') /* We have the start of a range expression */
8058 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
8061 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
8065 if (high_range
<= new_base
)
8067 inst
.error
= _("register range not in ascending order");
8071 for (new_base
++; new_base
<= high_range
; new_base
++)
8073 if (mask
& (1 << new_base
))
8075 inst
.error
= _("invalid register list");
8079 mask
|= 1 << new_base
;
8084 while (skip_past_comma (str
) != FAIL
);
8088 inst
.error
= _("invalid register list");
8096 /* Sanity check -- should have raised a parse error above. */
8097 if (count
== 0 || count
> 16)
8100 /* Final test -- the registers must be consecutive. */
8103 if ((mask
& (1 << base_reg
++)) == 0)
8105 inst
.error
= _("non-contiguous register range");
8110 inst
.instruction
= tempinst
;
8115 vfp_sp_ldstm (str
, ldstm_type
)
8117 enum vfp_ldstm_type ldstm_type
;
8121 skip_whitespace (str
);
8123 if (reg_required_here (&str
, 16) == FAIL
)
8126 skip_whitespace (str
);
8130 inst
.instruction
|= WRITE_BACK
;
8133 else if (ldstm_type
!= VFP_LDSTMIA
)
8135 inst
.error
= _("this addressing mode requires base-register writeback");
8139 if (skip_past_comma (&str
) == FAIL
8140 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
8143 inst
.error
= BAD_ARGS
;
8147 inst
.instruction
|= range
;
8152 vfp_dp_ldstm (str
, ldstm_type
)
8154 enum vfp_ldstm_type ldstm_type
;
8158 skip_whitespace (str
);
8160 if (reg_required_here (&str
, 16) == FAIL
)
8163 skip_whitespace (str
);
8167 inst
.instruction
|= WRITE_BACK
;
8170 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
8172 inst
.error
= _("this addressing mode requires base-register writeback");
8176 if (skip_past_comma (&str
) == FAIL
8177 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
8180 inst
.error
= BAD_ARGS
;
8184 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
8187 inst
.instruction
|= range
;
8192 do_vfp_sp_ldstmia (str
)
8195 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
8199 do_vfp_sp_ldstmdb (str
)
8202 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
8206 do_vfp_dp_ldstmia (str
)
8209 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
8213 do_vfp_dp_ldstmdb (str
)
8216 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
8220 do_vfp_xp_ldstmia (str
)
8223 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
8227 do_vfp_xp_ldstmdb (str
)
8230 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
8234 do_vfp_sp_compare_z (str
)
8237 skip_whitespace (str
);
8239 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8242 inst
.error
= BAD_ARGS
;
8251 do_vfp_dp_compare_z (str
)
8254 skip_whitespace (str
);
8256 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8259 inst
.error
= BAD_ARGS
;
8268 do_vfp_dp_sp_cvt (str
)
8271 skip_whitespace (str
);
8273 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
8276 if (skip_past_comma (&str
) == FAIL
8277 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
8280 inst
.error
= BAD_ARGS
;
8289 do_vfp_sp_dp_cvt (str
)
8292 skip_whitespace (str
);
8294 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
8297 if (skip_past_comma (&str
) == FAIL
8298 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
8301 inst
.error
= BAD_ARGS
;
8309 /* Thumb specific routines. */
8311 /* Parse and validate that a register is of the right form, this saves
8312 repeated checking of this information in many similar cases.
8313 Unlike the 32-bit case we do not insert the register into the opcode
8314 here, since the position is often unknown until the full instruction
8318 thumb_reg (strp
, hi_lo
)
8324 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
8332 inst
.error
= _("lo register required");
8340 inst
.error
= _("hi register required");
8352 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8356 thumb_add_sub (str
, subtract
)
8360 int Rd
, Rs
, Rn
= FAIL
;
8362 skip_whitespace (str
);
8364 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8365 || skip_past_comma (&str
) == FAIL
)
8368 inst
.error
= BAD_ARGS
;
8372 if (is_immediate_prefix (*str
))
8376 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8381 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8384 if (skip_past_comma (&str
) == FAIL
)
8386 /* Two operand format, shuffle the registers
8387 and pretend there are 3. */
8391 else if (is_immediate_prefix (*str
))
8394 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8397 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8401 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8402 for the latter case, EXPR contains the immediate that was found. */
8405 /* All register format. */
8406 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
8410 inst
.error
= _("dest and source1 must be the same register");
8414 /* Can't do this for SUB. */
8417 inst
.error
= _("subtract valid only on lo regs");
8421 inst
.instruction
= (T_OPCODE_ADD_HI
8422 | (Rd
> 7 ? THUMB_H1
: 0)
8423 | (Rn
> 7 ? THUMB_H2
: 0));
8424 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
8428 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
8429 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
8434 /* Immediate expression, now things start to get nasty. */
8436 /* First deal with HI regs, only very restricted cases allowed:
8437 Adjusting SP, and using PC or SP to get an address. */
8438 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
8439 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
8441 inst
.error
= _("invalid Hi register with immediate");
8445 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8447 /* Value isn't known yet, all we can do is store all the fragments
8448 we know about in the instruction and let the reloc hacking
8450 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
8451 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8455 int offset
= inst
.reloc
.exp
.X_add_number
;
8465 /* Quick check, in case offset is MIN_INT. */
8468 inst
.error
= _("immediate value out of range");
8472 /* Note - you cannot convert a subtract of 0 into an
8473 add of 0 because the carry flag is set differently. */
8474 else if (offset
> 0)
8479 if (offset
& ~0x1fc)
8481 inst
.error
= _("invalid immediate value for stack adjust");
8484 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
8485 inst
.instruction
|= offset
>> 2;
8487 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
8490 || (offset
& ~0x3fc))
8492 inst
.error
= _("invalid immediate for address calculation");
8495 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
8497 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
8503 inst
.error
= _("immediate value out of range");
8506 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
8507 inst
.instruction
|= (Rd
<< 8) | offset
;
8513 inst
.error
= _("immediate value out of range");
8516 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
8517 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
8526 thumb_shift (str
, shift
)
8530 int Rd
, Rs
, Rn
= FAIL
;
8532 skip_whitespace (str
);
8534 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8535 || skip_past_comma (&str
) == FAIL
)
8538 inst
.error
= BAD_ARGS
;
8542 if (is_immediate_prefix (*str
))
8544 /* Two operand immediate format, set Rs to Rd. */
8547 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8552 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8555 if (skip_past_comma (&str
) == FAIL
)
8557 /* Two operand format, shuffle the registers
8558 and pretend there are 3. */
8562 else if (is_immediate_prefix (*str
))
8565 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8568 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8572 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8573 for the latter case, EXPR contains the immediate that was found. */
8579 inst
.error
= _("source1 and dest must be same register");
8585 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
8586 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
8587 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
8590 inst
.instruction
|= Rd
| (Rn
<< 3);
8596 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
8597 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
8598 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
8601 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8603 /* Value isn't known yet, create a dummy reloc and let reloc
8604 hacking fix it up. */
8605 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
8609 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
8611 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
8613 inst
.error
= _("invalid immediate for shift");
8617 /* Shifts of zero are handled by converting to LSL. */
8618 if (shift_value
== 0)
8619 inst
.instruction
= T_OPCODE_LSL_I
;
8621 /* Shifts of 32 are encoded as a shift of zero. */
8622 if (shift_value
== 32)
8625 inst
.instruction
|= shift_value
<< 6;
8628 inst
.instruction
|= Rd
| (Rs
<< 3);
8635 thumb_mov_compare (str
, move
)
8641 skip_whitespace (str
);
8643 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
8644 || skip_past_comma (&str
) == FAIL
)
8647 inst
.error
= BAD_ARGS
;
8651 if (is_immediate_prefix (*str
))
8654 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8657 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8662 if (Rs
< 8 && Rd
< 8)
8664 if (move
== THUMB_MOVE
)
8665 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8666 since a MOV instruction produces unpredictable results. */
8667 inst
.instruction
= T_OPCODE_ADD_I3
;
8669 inst
.instruction
= T_OPCODE_CMP_LR
;
8670 inst
.instruction
|= Rd
| (Rs
<< 3);
8674 if (move
== THUMB_MOVE
)
8675 inst
.instruction
= T_OPCODE_MOV_HR
;
8677 inst
.instruction
= T_OPCODE_CMP_HR
;
8680 inst
.instruction
|= THUMB_H1
;
8683 inst
.instruction
|= THUMB_H2
;
8685 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
8692 inst
.error
= _("only lo regs allowed with immediate");
8696 if (move
== THUMB_MOVE
)
8697 inst
.instruction
= T_OPCODE_MOV_I8
;
8699 inst
.instruction
= T_OPCODE_CMP_I8
;
8701 inst
.instruction
|= Rd
<< 8;
8703 if (inst
.reloc
.exp
.X_op
!= O_constant
)
8704 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
8707 unsigned value
= inst
.reloc
.exp
.X_add_number
;
8711 inst
.error
= _("invalid immediate");
8715 inst
.instruction
|= value
;
8723 thumb_load_store (str
, load_store
, size
)
8728 int Rd
, Rb
, Ro
= FAIL
;
8730 skip_whitespace (str
);
8732 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8733 || skip_past_comma (&str
) == FAIL
)
8736 inst
.error
= BAD_ARGS
;
8743 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8746 if (skip_past_comma (&str
) != FAIL
)
8748 if (is_immediate_prefix (*str
))
8751 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8754 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8759 inst
.reloc
.exp
.X_op
= O_constant
;
8760 inst
.reloc
.exp
.X_add_number
= 0;
8765 inst
.error
= _("expected ']'");
8770 else if (*str
== '=')
8772 if (load_store
!= THUMB_LOAD
)
8774 inst
.error
= _("invalid pseudo operation");
8778 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
8781 skip_whitespace (str
);
8783 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8788 if ( inst
.reloc
.exp
.X_op
!= O_constant
8789 && inst
.reloc
.exp
.X_op
!= O_symbol
)
8791 inst
.error
= "Constant expression expected";
8795 if (inst
.reloc
.exp
.X_op
== O_constant
8796 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
8798 /* This can be done with a mov instruction. */
8800 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
8801 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
8805 /* Insert into literal pool. */
8806 if (add_to_lit_pool () == FAIL
)
8809 inst
.error
= "literal pool insertion failed";
8813 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8814 inst
.reloc
.pc_rel
= 1;
8815 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8816 /* Adjust ARM pipeline offset to Thumb. */
8817 inst
.reloc
.exp
.X_add_number
+= 4;
8823 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8826 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
8827 inst
.reloc
.pc_rel
= 1;
8828 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
8829 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8834 if (Rb
== REG_PC
|| Rb
== REG_SP
)
8836 if (size
!= THUMB_WORD
)
8838 inst
.error
= _("byte or halfword not valid for base register");
8841 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
8843 inst
.error
= _("r15 based store not allowed");
8846 else if (Ro
!= FAIL
)
8848 inst
.error
= _("invalid base register for register offset");
8853 inst
.instruction
= T_OPCODE_LDR_PC
;
8854 else if (load_store
== THUMB_LOAD
)
8855 inst
.instruction
= T_OPCODE_LDR_SP
;
8857 inst
.instruction
= T_OPCODE_STR_SP
;
8859 inst
.instruction
|= Rd
<< 8;
8860 if (inst
.reloc
.exp
.X_op
== O_constant
)
8862 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8864 if (offset
& ~0x3fc)
8866 inst
.error
= _("invalid offset");
8870 inst
.instruction
|= offset
>> 2;
8873 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8877 inst
.error
= _("invalid base register in load/store");
8880 else if (Ro
== FAIL
)
8882 /* Immediate offset. */
8883 if (size
== THUMB_WORD
)
8884 inst
.instruction
= (load_store
== THUMB_LOAD
8885 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
8886 else if (size
== THUMB_HALFWORD
)
8887 inst
.instruction
= (load_store
== THUMB_LOAD
8888 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
8890 inst
.instruction
= (load_store
== THUMB_LOAD
8891 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
8893 inst
.instruction
|= Rd
| (Rb
<< 3);
8895 if (inst
.reloc
.exp
.X_op
== O_constant
)
8897 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
8899 if (offset
& ~(0x1f << size
))
8901 inst
.error
= _("invalid offset");
8904 inst
.instruction
|= (offset
>> size
) << 6;
8907 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
8911 /* Register offset. */
8912 if (size
== THUMB_WORD
)
8913 inst
.instruction
= (load_store
== THUMB_LOAD
8914 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
8915 else if (size
== THUMB_HALFWORD
)
8916 inst
.instruction
= (load_store
== THUMB_LOAD
8917 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
8919 inst
.instruction
= (load_store
== THUMB_LOAD
8920 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
8922 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8928 /* A register must be given at this point.
8930 Shift is the place to put it in inst.instruction.
8932 Restores input start point on err.
8933 Returns the reg#, or FAIL. */
8936 mav_reg_required_here (str
, shift
, regtype
)
8939 enum arm_reg_type regtype
;
8944 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
8947 inst
.instruction
|= reg
<< shift
;
8952 /* Restore the start point. */
8955 /* In the few cases where we might be able to accept something else
8956 this error can be overridden. */
8957 inst
.error
= _(all_reg_maps
[regtype
].expected
);
8962 /* Cirrus Maverick Instructions. */
8964 /* Wrapper functions. */
8967 do_mav_binops_1a (str
)
8970 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
8974 do_mav_binops_1b (str
)
8977 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
8981 do_mav_binops_1c (str
)
8984 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
8988 do_mav_binops_1d (str
)
8991 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8995 do_mav_binops_1e (str
)
8998 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9002 do_mav_binops_1f (str
)
9005 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
9009 do_mav_binops_1g (str
)
9012 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
9016 do_mav_binops_1h (str
)
9019 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
9023 do_mav_binops_1i (str
)
9026 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
9030 do_mav_binops_1j (str
)
9033 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
9037 do_mav_binops_1k (str
)
9040 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
9044 do_mav_binops_1l (str
)
9047 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
9051 do_mav_binops_1m (str
)
9054 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
9058 do_mav_binops_1n (str
)
9061 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9065 do_mav_binops_1o (str
)
9068 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9072 do_mav_binops_2a (str
)
9075 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
9079 do_mav_binops_2b (str
)
9082 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
9086 do_mav_binops_2c (str
)
9089 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9093 do_mav_binops_3a (str
)
9096 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
9100 do_mav_binops_3b (str
)
9103 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
9107 do_mav_binops_3c (str
)
9110 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
9114 do_mav_binops_3d (str
)
9117 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
9121 do_mav_triple_4a (str
)
9124 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
9128 do_mav_triple_4b (str
)
9131 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
9135 do_mav_triple_5a (str
)
9138 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9142 do_mav_triple_5b (str
)
9145 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9149 do_mav_triple_5c (str
)
9152 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9156 do_mav_triple_5d (str
)
9159 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9163 do_mav_triple_5e (str
)
9166 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
9170 do_mav_triple_5f (str
)
9173 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
9177 do_mav_triple_5g (str
)
9180 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9184 do_mav_triple_5h (str
)
9187 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9191 do_mav_quad_6a (str
)
9194 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
9199 do_mav_quad_6b (str
)
9202 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
9206 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
9208 do_mav_dspsc_1 (str
)
9211 skip_whitespace (str
);
9214 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
9215 || skip_past_comma (&str
) == FAIL
9216 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
9219 inst
.error
= BAD_ARGS
;
9227 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
9229 do_mav_dspsc_2 (str
)
9232 skip_whitespace (str
);
9235 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
9236 || skip_past_comma (&str
) == FAIL
9237 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
9240 inst
.error
= BAD_ARGS
;
9249 do_mav_shift_1 (str
)
9252 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
9256 do_mav_shift_2 (str
)
9259 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
9266 do_mav_ldst (str
, REG_TYPE_MVF
);
9273 do_mav_ldst (str
, REG_TYPE_MVD
);
9280 do_mav_ldst (str
, REG_TYPE_MVFX
);
9287 do_mav_ldst (str
, REG_TYPE_MVDX
);
9290 /* Isnsn like "foo X,Y". */
9293 do_mav_binops (str
, mode
, reg0
, reg1
)
9296 enum arm_reg_type reg0
;
9297 enum arm_reg_type reg1
;
9301 shift0
= mode
& 0xff;
9302 shift1
= (mode
>> 8) & 0xff;
9304 skip_whitespace (str
);
9306 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9307 || skip_past_comma (&str
) == FAIL
9308 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
9311 inst
.error
= BAD_ARGS
;
9317 /* Isnsn like "foo X,Y,Z". */
9320 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
9323 enum arm_reg_type reg0
;
9324 enum arm_reg_type reg1
;
9325 enum arm_reg_type reg2
;
9327 int shift0
, shift1
, shift2
;
9329 shift0
= mode
& 0xff;
9330 shift1
= (mode
>> 8) & 0xff;
9331 shift2
= (mode
>> 16) & 0xff;
9333 skip_whitespace (str
);
9335 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9336 || skip_past_comma (&str
) == FAIL
9337 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9338 || skip_past_comma (&str
) == FAIL
9339 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
9342 inst
.error
= BAD_ARGS
;
9348 /* Isnsn like "foo W,X,Y,Z".
9349 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
9352 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
9355 enum arm_reg_type reg0
;
9356 enum arm_reg_type reg1
;
9357 enum arm_reg_type reg2
;
9358 enum arm_reg_type reg3
;
9360 int shift0
, shift1
, shift2
, shift3
;
9362 shift0
= mode
& 0xff;
9363 shift1
= (mode
>> 8) & 0xff;
9364 shift2
= (mode
>> 16) & 0xff;
9365 shift3
= (mode
>> 24) & 0xff;
9367 skip_whitespace (str
);
9369 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
9370 || skip_past_comma (&str
) == FAIL
9371 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
9372 || skip_past_comma (&str
) == FAIL
9373 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
9374 || skip_past_comma (&str
) == FAIL
9375 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
9378 inst
.error
= BAD_ARGS
;
9384 /* Maverick shift immediate instructions.
9385 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9386 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
9389 do_mav_shift (str
, reg0
, reg1
)
9391 enum arm_reg_type reg0
;
9392 enum arm_reg_type reg1
;
9397 skip_whitespace (str
);
9401 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9402 || skip_past_comma (&str
) == FAIL
9403 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
9404 || skip_past_comma (&str
) == FAIL
)
9407 inst
.error
= BAD_ARGS
;
9411 /* Calculate the immediate operand.
9412 The operand is a 7bit signed number. */
9413 skip_whitespace (str
);
9418 if (!ISDIGIT (*str
) && *str
!= '-')
9420 inst
.error
= _("expecting immediate, 7bit operand");
9430 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
9431 imm
= imm
* 10 + *str
- '0';
9435 inst
.error
= _("immediate out of range");
9439 /* Make negative imm's into 7bit signed numbers. */
9446 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9447 Bits 5-7 of the insn should have bits 4-6 of the immediate.
9448 Bit 4 should be 0. */
9449 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
9451 inst
.instruction
|= imm
;
9456 mav_parse_offset (str
, negative
)
9465 skip_whitespace (p
);
9478 inst
.error
= _("offset expected");
9482 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
9483 offset
= offset
* 10 + *p
- '0';
9487 inst
.error
= _("offset out of range");
9493 return *negative
? -offset
: offset
;
9496 /* Maverick load/store instructions.
9497 <insn><cond> CRd,[Rn,<offset>]{!}.
9498 <insn><cond> CRd,[Rn],<offset>. */
9501 do_mav_ldst (str
, reg0
)
9503 enum arm_reg_type reg0
;
9505 int offset
, negative
;
9507 skip_whitespace (str
);
9509 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
9510 || skip_past_comma (&str
) == FAIL
9512 || reg_required_here (&str
, 16) == FAIL
)
9515 if (skip_past_comma (&str
) == SUCCESS
)
9517 /* You are here: "<offset>]{!}". */
9518 inst
.instruction
|= PRE_INDEX
;
9520 offset
= mav_parse_offset (&str
, &negative
);
9527 inst
.error
= _("missing ]");
9533 inst
.instruction
|= WRITE_BACK
;
9539 /* You are here: "], <offset>". */
9542 inst
.error
= _("missing ]");
9546 if (skip_past_comma (&str
) == FAIL
9547 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
9550 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
9556 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
9558 inst
.instruction
|= offset
>> 2;
9564 inst
.error
= BAD_ARGS
;
9577 /* Handle the Format 4 instructions that do not have equivalents in other
9578 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9587 skip_whitespace (str
);
9589 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9590 || skip_past_comma (&str
) == FAIL
9591 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9593 inst
.error
= BAD_ARGS
;
9597 if (skip_past_comma (&str
) != FAIL
)
9599 /* Three operand format not allowed for TST, CMN, NEG and MVN.
9600 (It isn't allowed for CMP either, but that isn't handled by this
9602 if (inst
.instruction
== T_OPCODE_TST
9603 || inst
.instruction
== T_OPCODE_CMN
9604 || inst
.instruction
== T_OPCODE_NEG
9605 || inst
.instruction
== T_OPCODE_MVN
)
9607 inst
.error
= BAD_ARGS
;
9611 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9616 inst
.error
= _("dest and source1 must be the same register");
9622 if (inst
.instruction
== T_OPCODE_MUL
9624 as_tsktsk (_("Rs and Rd must be different in MUL"));
9626 inst
.instruction
|= Rd
| (Rs
<< 3);
9634 thumb_add_sub (str
, 0);
9641 thumb_shift (str
, THUMB_ASR
);
9648 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9650 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
9651 inst
.reloc
.pc_rel
= 1;
9659 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9661 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
9662 inst
.reloc
.pc_rel
= 1;
9666 /* Find the real, Thumb encoded start of a Thumb function. */
9669 find_real_start (symbolP
)
9673 const char * name
= S_GET_NAME (symbolP
);
9674 symbolS
* new_target
;
9676 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
9677 #define STUB_NAME ".real_start_of"
9682 /* Names that start with '.' are local labels, not function entry points.
9683 The compiler may generate BL instructions to these labels because it
9684 needs to perform a branch to a far away location. */
9688 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
9689 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
9691 new_target
= symbol_find (real_start
);
9693 if (new_target
== NULL
)
9695 as_warn ("Failed to find real start of function: %s\n", name
);
9696 new_target
= symbolP
;
9708 if (my_get_expression (& inst
.reloc
.exp
, & str
))
9711 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
9712 inst
.reloc
.pc_rel
= 1;
9715 /* If the destination of the branch is a defined symbol which does not have
9716 the THUMB_FUNC attribute, then we must be calling a function which has
9717 the (interfacearm) attribute. We look for the Thumb entry point to that
9718 function and change the branch to refer to that function instead. */
9719 if ( inst
.reloc
.exp
.X_op
== O_symbol
9720 && inst
.reloc
.exp
.X_add_symbol
!= NULL
9721 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
9722 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
9723 inst
.reloc
.exp
.X_add_symbol
=
9724 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
9733 skip_whitespace (str
);
9735 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
9738 /* This sets THUMB_H2 from the top bit of reg. */
9739 inst
.instruction
|= reg
<< 3;
9741 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
9742 should cause the alignment to be checked once it is known. This is
9743 because BX PC only works if the instruction is word aligned. */
9752 thumb_mov_compare (str
, THUMB_COMPARE
);
9762 skip_whitespace (str
);
9764 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
9768 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9772 if (skip_past_comma (&str
) == FAIL
9773 || (range
= reg_list (&str
)) == FAIL
)
9776 inst
.error
= BAD_ARGS
;
9780 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9782 /* This really doesn't seem worth it. */
9783 inst
.reloc
.type
= BFD_RELOC_NONE
;
9784 inst
.error
= _("expression too complex");
9790 inst
.error
= _("only lo-regs valid in load/store multiple");
9794 inst
.instruction
|= (Rb
<< 8) | range
;
9802 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
9809 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
9816 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
9825 skip_whitespace (str
);
9827 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9828 || skip_past_comma (&str
) == FAIL
9830 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9831 || skip_past_comma (&str
) == FAIL
9832 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
9836 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
9840 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
9848 thumb_shift (str
, THUMB_LSL
);
9855 thumb_shift (str
, THUMB_LSR
);
9862 thumb_mov_compare (str
, THUMB_MOVE
);
9871 skip_whitespace (str
);
9873 if ((range
= reg_list (&str
)) == FAIL
)
9876 inst
.error
= BAD_ARGS
;
9880 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
9882 /* This really doesn't seem worth it. */
9883 inst
.reloc
.type
= BFD_RELOC_NONE
;
9884 inst
.error
= _("expression too complex");
9890 if ((inst
.instruction
== T_OPCODE_PUSH
9891 && (range
& ~0xff) == 1 << REG_LR
)
9892 || (inst
.instruction
== T_OPCODE_POP
9893 && (range
& ~0xff) == 1 << REG_PC
))
9895 inst
.instruction
|= THUMB_PP_PC_LR
;
9900 inst
.error
= _("invalid register list to push/pop instruction");
9905 inst
.instruction
|= range
;
9913 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
9920 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
9927 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
9934 thumb_add_sub (str
, 1);
9941 skip_whitespace (str
);
9943 if (my_get_expression (&inst
.reloc
.exp
, &str
))
9946 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
9957 /* This is a pseudo-op of the form "adr rd, label" to be converted
9958 into a relative address of the form "add rd, pc, #label-.-4". */
9959 skip_whitespace (str
);
9961 /* Store Rd in temporary location inside instruction. */
9962 if ((reg
= reg_required_here (&str
, 4)) == FAIL
9963 || (reg
> 7) /* For Thumb reg must be r0..r7. */
9964 || skip_past_comma (&str
) == FAIL
9965 || my_get_expression (&inst
.reloc
.exp
, &str
))
9968 inst
.error
= BAD_ARGS
;
9972 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
9973 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
9974 inst
.reloc
.pc_rel
= 1;
9975 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
9981 insert_reg (r
, htab
)
9982 const struct reg_entry
*r
;
9983 struct hash_control
*htab
;
9985 int len
= strlen (r
->name
) + 2;
9986 char * buf
= (char *) xmalloc (len
);
9987 char * buf2
= (char *) xmalloc (len
);
9990 #ifdef REGISTER_PREFIX
9991 buf
[i
++] = REGISTER_PREFIX
;
9994 strcpy (buf
+ i
, r
->name
);
9996 for (i
= 0; buf
[i
]; i
++)
9997 buf2
[i
] = TOUPPER (buf
[i
]);
10001 hash_insert (htab
, buf
, (PTR
) r
);
10002 hash_insert (htab
, buf2
, (PTR
) r
);
10006 build_reg_hsh (map
)
10007 struct reg_map
*map
;
10009 const struct reg_entry
*r
;
10011 if ((map
->htab
= hash_new ()) == NULL
)
10012 as_fatal (_("virtual memory exhausted"));
10014 for (r
= map
->names
; r
->name
!= NULL
; r
++)
10015 insert_reg (r
, map
->htab
);
10019 insert_reg_alias (str
, regnum
, htab
)
10022 struct hash_control
*htab
;
10024 struct reg_entry
*new =
10025 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
10026 char *name
= xmalloc (strlen (str
) + 1);
10027 strcpy (name
, str
);
10030 new->number
= regnum
;
10032 hash_insert (htab
, name
, (PTR
) new);
10035 /* Look for the .req directive. This is of the form:
10037 newname .req existing_name
10039 If we find one, or if it looks sufficiently like one that we want to
10040 handle any error here, return non-zero. Otherwise return zero. */
10042 create_register_alias (newname
, p
)
10050 skip_whitespace (q
);
10055 if (*q
&& !strncmp (q
, ".req ", 5))
10060 #ifdef IGNORE_OPCODE_CASE
10061 newname
= original_case_string
;
10063 copy_of_str
= newname
;
10066 skip_whitespace (q
);
10068 for (r
= q
; *r
!= '\0'; r
++)
10074 enum arm_reg_type new_type
, old_type
;
10079 old_type
= arm_reg_parse_any (q
);
10082 new_type
= arm_reg_parse_any (newname
);
10084 if (new_type
== REG_TYPE_MAX
)
10086 if (old_type
!= REG_TYPE_MAX
)
10088 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
10089 insert_reg_alias (newname
, old_regno
,
10090 all_reg_maps
[old_type
].htab
);
10093 as_warn (_("register '%s' does not exist\n"), q
);
10095 else if (old_type
== REG_TYPE_MAX
)
10097 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10102 /* Do not warn about redefinitions to the same alias. */
10103 if (new_type
!= old_type
10104 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
10105 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
10106 as_warn (_("ignoring redefinition of register alias '%s'"),
10112 as_warn (_("ignoring incomplete .req pseuso op"));
10122 set_constant_flonums ()
10126 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
10127 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
10131 /* Iterate over the base tables to create the instruction patterns. */
10133 build_arm_ops_hsh ()
10137 static struct obstack insn_obstack
;
10139 obstack_begin (&insn_obstack
, 4000);
10141 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
10143 const struct asm_opcode
*insn
= insns
+ i
;
10145 if (insn
->cond_offset
!= 0)
10147 /* Insn supports conditional execution. Build the varaints
10148 and insert them in the hash table. */
10149 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
10151 unsigned len
= strlen (insn
->template);
10152 struct asm_opcode
*new;
10155 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
10156 /* All condition codes are two characters. */
10157 template = obstack_alloc (&insn_obstack
, len
+ 3);
10159 strncpy (template, insn
->template, insn
->cond_offset
);
10160 strcpy (template + insn
->cond_offset
, conds
[j
].template);
10161 if (len
> insn
->cond_offset
)
10162 strcpy (template + insn
->cond_offset
+ 2,
10163 insn
->template + insn
->cond_offset
);
10164 new->template = template;
10165 new->cond_offset
= 0;
10166 new->variant
= insn
->variant
;
10167 new->parms
= insn
->parms
;
10168 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
10170 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
10173 /* Finally, insert the unconditional insn in the table directly;
10174 no need to build a copy. */
10175 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
10179 #if defined OBJ_ELF || defined OBJ_COFF
10182 #define arm_Note Elf_External_Note
10186 unsigned char namesz
[4]; /* Size of entry's owner string. */
10187 unsigned char descsz
[4]; /* Size of the note descriptor. */
10188 unsigned char type
[4]; /* Interpretation of the descriptor. */
10189 char name
[1]; /* Start of the name+desc data. */
10193 /* The description is kept to a fix sized in order to make updating
10194 it and merging it easier. */
10195 #define ARM_NOTE_DESCRIPTION_LENGTH 8
10198 arm_add_note (name
, description
, type
)
10200 const char * description
;
10203 arm_Note note ATTRIBUTE_UNUSED
;
10205 unsigned int name_len
;
10207 name_len
= (strlen (name
) + 1 + 3) & ~3;
10209 p
= frag_more (sizeof (note
.namesz
));
10210 md_number_to_chars (p
, (valueT
) name_len
, sizeof (note
.namesz
));
10212 p
= frag_more (sizeof (note
.descsz
));
10213 md_number_to_chars (p
, (valueT
) ARM_NOTE_DESCRIPTION_LENGTH
, sizeof (note
.descsz
));
10215 p
= frag_more (sizeof (note
.type
));
10216 md_number_to_chars (p
, (valueT
) type
, sizeof (note
.type
));
10218 p
= frag_more (name_len
);
10221 p
= frag_more (ARM_NOTE_DESCRIPTION_LENGTH
);
10222 strncpy (p
, description
, ARM_NOTE_DESCRIPTION_LENGTH
);
10223 frag_align (2, 0, 0);
10233 if ( (arm_ops_hsh
= hash_new ()) == NULL
10234 || (arm_tops_hsh
= hash_new ()) == NULL
10235 || (arm_cond_hsh
= hash_new ()) == NULL
10236 || (arm_shift_hsh
= hash_new ()) == NULL
10237 || (arm_psr_hsh
= hash_new ()) == NULL
)
10238 as_fatal (_("virtual memory exhausted"));
10240 build_arm_ops_hsh ();
10241 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
10242 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
10243 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
10244 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
10245 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
10246 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
10247 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
10248 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
10250 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10251 build_reg_hsh (all_reg_maps
+ i
);
10253 set_constant_flonums ();
10255 /* Set the cpu variant based on the command-line options. We prefer
10256 -mcpu= over -march= if both are set (as for GCC); and we prefer
10257 -mfpu= over any other way of setting the floating point unit.
10258 Use of legacy options with new options are faulted. */
10259 if (legacy_cpu
!= -1)
10261 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
10262 as_bad (_("use of old and new-style options to set CPU type"));
10264 mcpu_cpu_opt
= legacy_cpu
;
10266 else if (mcpu_cpu_opt
== -1)
10267 mcpu_cpu_opt
= march_cpu_opt
;
10269 if (legacy_fpu
!= -1)
10271 if (mfpu_opt
!= -1)
10272 as_bad (_("use of old and new-style options to set FPU type"));
10274 mfpu_opt
= legacy_fpu
;
10276 else if (mfpu_opt
== -1)
10278 #if !(defined (TE_LINUX) || defined (TE_NetBSD))
10279 /* Some environments specify a default FPU. If they don't, infer it
10280 from the processor. */
10281 if (mcpu_fpu_opt
!= -1)
10282 mfpu_opt
= mcpu_fpu_opt
;
10284 mfpu_opt
= march_fpu_opt
;
10286 mfpu_opt
= FPU_DEFAULT
;
10290 if (mfpu_opt
== -1)
10292 if (mcpu_cpu_opt
== -1)
10293 mfpu_opt
= FPU_DEFAULT
;
10294 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
10295 mfpu_opt
= FPU_ARCH_VFP_V2
;
10297 mfpu_opt
= FPU_ARCH_FPA
;
10300 if (mcpu_cpu_opt
== -1)
10301 mcpu_cpu_opt
= CPU_DEFAULT
;
10303 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
10305 #if defined OBJ_COFF || defined OBJ_ELF
10307 unsigned int flags
= 0;
10309 /* Set the flags in the private structure. */
10310 if (uses_apcs_26
) flags
|= F_APCS26
;
10311 if (support_interwork
) flags
|= F_INTERWORK
;
10312 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
10313 if (pic_code
) flags
|= F_PIC
;
10314 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
10315 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
10316 flags
|= F_SOFT_FLOAT
;
10317 /* Using VFP conventions (even if soft-float). */
10318 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
10320 #if defined OBJ_ELF
10321 if (cpu_variant
& ARM_CEXT_MAVERICK
)
10323 flags
&= ~ F_SOFT_FLOAT
;
10324 flags
|= EF_ARM_MAVERICK_FLOAT
;
10328 bfd_set_private_flags (stdoutput
, flags
);
10330 /* We have run out flags in the COFF header to encode the
10331 status of ATPCS support, so instead we create a dummy,
10332 empty, debug section called .arm.atpcs. */
10337 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
10341 bfd_set_section_flags
10342 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
10343 bfd_set_section_size (stdoutput
, sec
, 0);
10344 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
10350 /* Record the CPU type as well. */
10351 switch (cpu_variant
& ARM_CPU_MASK
)
10354 mach
= bfd_mach_arm_2
;
10357 case ARM_3
: /* Also ARM_250. */
10358 mach
= bfd_mach_arm_2a
;
10361 case ARM_6
: /* Also ARM_7. */
10362 mach
= bfd_mach_arm_3
;
10366 mach
= bfd_mach_arm_unknown
;
10370 /* Catch special cases. */
10371 if (cpu_variant
& ARM_CEXT_IWMMXT
)
10372 mach
= bfd_mach_arm_iWMMXt
;
10373 else if (cpu_variant
& ARM_CEXT_XSCALE
)
10374 mach
= bfd_mach_arm_XScale
;
10375 else if (cpu_variant
& ARM_CEXT_MAVERICK
)
10376 mach
= bfd_mach_arm_ep9312
;
10377 else if (cpu_variant
& ARM_EXT_V5E
)
10378 mach
= bfd_mach_arm_5TE
;
10379 else if (cpu_variant
& ARM_EXT_V5
)
10381 if (cpu_variant
& ARM_EXT_V4T
)
10382 mach
= bfd_mach_arm_5T
;
10384 mach
= bfd_mach_arm_5
;
10386 else if (cpu_variant
& ARM_EXT_V4
)
10388 if (cpu_variant
& ARM_EXT_V4T
)
10389 mach
= bfd_mach_arm_4T
;
10391 mach
= bfd_mach_arm_4
;
10393 else if (cpu_variant
& ARM_EXT_V3M
)
10394 mach
= bfd_mach_arm_3M
;
10396 #if 0 /* Suppressed - for now. */
10397 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10399 /* Create a .note section to fully identify this arm binary. */
10401 #define NOTE_ARCH_STRING "arch: "
10403 #if defined OBJ_COFF && ! defined NT_VERSION
10404 #define NT_VERSION 1
10409 segT current_seg
= now_seg
;
10410 subsegT current_subseg
= now_subseg
;
10411 asection
* arm_arch
;
10412 const char * arch_string
;
10414 arm_arch
= bfd_make_section_old_way (stdoutput
, ARM_NOTE_SECTION
);
10417 bfd_set_section_flags (stdoutput
, arm_arch
,
10418 SEC_DATA
| SEC_ALLOC
| SEC_LOAD
| SEC_LINK_ONCE \
10419 | SEC_HAS_CONTENTS
);
10421 arm_arch
->output_section
= arm_arch
;
10422 subseg_set (arm_arch
, 0);
10427 case bfd_mach_arm_unknown
: arch_string
= "unknown"; break;
10428 case bfd_mach_arm_2
: arch_string
= "armv2"; break;
10429 case bfd_mach_arm_2a
: arch_string
= "armv2a"; break;
10430 case bfd_mach_arm_3
: arch_string
= "armv3"; break;
10431 case bfd_mach_arm_3M
: arch_string
= "armv3M"; break;
10432 case bfd_mach_arm_4
: arch_string
= "armv4"; break;
10433 case bfd_mach_arm_4T
: arch_string
= "armv4t"; break;
10434 case bfd_mach_arm_5
: arch_string
= "armv5"; break;
10435 case bfd_mach_arm_5T
: arch_string
= "armv5t"; break;
10436 case bfd_mach_arm_5TE
: arch_string
= "armv5te"; break;
10437 case bfd_mach_arm_XScale
: arch_string
= "XScale"; break;
10438 case bfd_mach_arm_ep9312
: arch_string
= "ep9312"; break;
10439 case bfd_mach_arm_iWMMXt
: arch_string
= "iWMMXt"; break;
10442 arm_add_note (NOTE_ARCH_STRING
, arch_string
, NT_ARCH
);
10444 subseg_set (current_seg
, current_subseg
);
10447 #endif /* Suppressed code. */
10449 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
10452 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10453 for use in the a.out file, and stores them in the array pointed to by buf.
10454 This knows about the endian-ness of the target machine and does
10455 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
10456 2 (short) and 4 (long) Floating numbers are put out as a series of
10457 LITTLENUMS (shorts, here at least). */
10460 md_number_to_chars (buf
, val
, n
)
10465 if (target_big_endian
)
10466 number_to_chars_bigendian (buf
, val
, n
);
10468 number_to_chars_littleendian (buf
, val
, n
);
10472 md_chars_to_number (buf
, n
)
10477 unsigned char * where
= (unsigned char *) buf
;
10479 if (target_big_endian
)
10484 result
|= (*where
++ & 255);
10492 result
|= (where
[n
] & 255);
10499 /* Turn a string in input_line_pointer into a floating point constant
10500 of type TYPE, and store the appropriate bytes in *LITP. The number
10501 of LITTLENUMS emitted is stored in *SIZEP. An error message is
10502 returned, or NULL on OK.
10504 Note that fp constants aren't represent in the normal way on the ARM.
10505 In big endian mode, things are as expected. However, in little endian
10506 mode fp constants are big-endian word-wise, and little-endian byte-wise
10507 within the words. For example, (double) 1.1 in big endian mode is
10508 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10509 the byte sequence 99 99 f1 3f 9a 99 99 99.
10511 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
10514 md_atof (type
, litP
, sizeP
)
10520 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
10552 return _("bad call to MD_ATOF()");
10555 t
= atof_ieee (input_line_pointer
, type
, words
);
10557 input_line_pointer
= t
;
10560 if (target_big_endian
)
10562 for (i
= 0; i
< prec
; i
++)
10564 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10570 if (cpu_variant
& FPU_ARCH_VFP
)
10571 for (i
= prec
- 1; i
>= 0; i
--)
10573 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
10577 /* For a 4 byte float the order of elements in `words' is 1 0.
10578 For an 8 byte float the order is 1 0 3 2. */
10579 for (i
= 0; i
< prec
; i
+= 2)
10581 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
10582 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
10590 /* The knowledge of the PC's pipeline offset is built into the insns
10594 md_pcrel_from (fixP
)
10598 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
10599 && fixP
->fx_subsy
== NULL
)
10602 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
10604 /* PC relative addressing on the Thumb is slightly odd
10605 as the bottom two bits of the PC are forced to zero
10606 for the calculation. */
10607 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
10611 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10612 so we un-adjust here to compensate for the accomodation. */
10613 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
10615 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
10619 /* Round up a section size to the appropriate boundary. */
10622 md_section_align (segment
, size
)
10623 segT segment ATTRIBUTE_UNUSED
;
10629 /* Round all sects to multiple of 4. */
10630 return (size
+ 3) & ~3;
10634 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10635 Otherwise we have no need to default values of symbols. */
10638 md_undefined_symbol (name
)
10639 char * name ATTRIBUTE_UNUSED
;
10642 if (name
[0] == '_' && name
[1] == 'G'
10643 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
10647 if (symbol_find (name
))
10648 as_bad ("GOT already in the symbol table");
10650 GOT_symbol
= symbol_new (name
, undefined_section
,
10651 (valueT
) 0, & zero_address_frag
);
10661 /* arm_reg_parse () := if it looks like a register, return its token and
10662 advance the pointer. */
10665 arm_reg_parse (ccp
, htab
)
10666 register char ** ccp
;
10667 struct hash_control
*htab
;
10669 char * start
= * ccp
;
10672 struct reg_entry
* reg
;
10674 #ifdef REGISTER_PREFIX
10675 if (*start
!= REGISTER_PREFIX
)
10680 #ifdef OPTIONAL_REGISTER_PREFIX
10681 if (*p
== OPTIONAL_REGISTER_PREFIX
)
10685 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
10689 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
10693 reg
= (struct reg_entry
*) hash_find (htab
, start
);
10699 return reg
->number
;
10705 /* Search for the following register name in each of the possible reg name
10706 tables. Return the classification if found, or REG_TYPE_MAX if not
10708 static enum arm_reg_type
10709 arm_reg_parse_any (cp
)
10714 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
10715 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
10716 return (enum arm_reg_type
) i
;
10718 return REG_TYPE_MAX
;
10722 md_apply_fix3 (fixP
, valP
, seg
)
10727 offsetT value
= * valP
;
10729 unsigned int newimm
;
10730 unsigned long temp
;
10732 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
10733 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
10735 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
10737 /* Note whether this will delete the relocation. */
10739 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10740 doesn't work fully.) */
10741 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
10742 && !fixP
->fx_pcrel
)
10744 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
10748 /* If this symbol is in a different section then we need to leave it for
10749 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
10750 so we have to undo it's effects here. */
10751 if (fixP
->fx_pcrel
)
10753 if (fixP
->fx_addsy
!= NULL
10754 && S_IS_DEFINED (fixP
->fx_addsy
)
10755 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
10758 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
10759 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
10763 value
+= md_pcrel_from (fixP
);
10767 /* Remember value for emit_reloc. */
10768 fixP
->fx_addnumber
= value
;
10770 switch (fixP
->fx_r_type
)
10772 case BFD_RELOC_ARM_IMMEDIATE
:
10773 newimm
= validate_immediate (value
);
10774 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10776 /* If the instruction will fail, see if we can fix things up by
10777 changing the opcode. */
10778 if (newimm
== (unsigned int) FAIL
10779 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
10781 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10782 _("invalid constant (%lx) after fixup"),
10783 (unsigned long) value
);
10787 newimm
|= (temp
& 0xfffff000);
10788 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10792 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10794 unsigned int highpart
= 0;
10795 unsigned int newinsn
= 0xe1a00000; /* nop. */
10797 newimm
= validate_immediate (value
);
10798 temp
= md_chars_to_number (buf
, INSN_SIZE
);
10800 /* If the instruction will fail, see if we can fix things up by
10801 changing the opcode. */
10802 if (newimm
== (unsigned int) FAIL
10803 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
10805 /* No ? OK - try using two ADD instructions to generate
10807 newimm
= validate_immediate_twopart (value
, & highpart
);
10809 /* Yes - then make sure that the second instruction is
10811 if (newimm
!= (unsigned int) FAIL
)
10813 /* Still No ? Try using a negated value. */
10814 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
10815 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
10816 /* Otherwise - give up. */
10819 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10820 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10825 /* Replace the first operand in the 2nd instruction (which
10826 is the PC) with the destination register. We have
10827 already added in the PC in the first instruction and we
10828 do not want to do it again. */
10829 newinsn
&= ~ 0xf0000;
10830 newinsn
|= ((newinsn
& 0x0f000) << 4);
10833 newimm
|= (temp
& 0xfffff000);
10834 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
10836 highpart
|= (newinsn
& 0xfffff000);
10837 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
10841 case BFD_RELOC_ARM_OFFSET_IMM
:
10847 if (validate_offset_imm (value
, 0) == FAIL
)
10849 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10850 _("bad immediate value for offset (%ld)"),
10855 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10856 newval
&= 0xff7ff000;
10857 newval
|= value
| (sign
? INDEX_UP
: 0);
10858 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10861 case BFD_RELOC_ARM_OFFSET_IMM8
:
10862 case BFD_RELOC_ARM_HWLITERAL
:
10868 if (validate_offset_imm (value
, 1) == FAIL
)
10870 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
10871 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10872 _("invalid literal constant: pool needs to be closer"));
10874 as_bad (_("bad immediate value for half-word offset (%ld)"),
10879 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10880 newval
&= 0xff7ff0f0;
10881 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
10882 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10885 case BFD_RELOC_ARM_LITERAL
:
10891 if (validate_offset_imm (value
, 0) == FAIL
)
10893 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10894 _("invalid literal constant: pool needs to be closer"));
10898 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10899 newval
&= 0xff7ff000;
10900 newval
|= value
| (sign
? INDEX_UP
: 0);
10901 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10904 case BFD_RELOC_ARM_SHIFT_IMM
:
10905 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10906 if (((unsigned long) value
) > 32
10908 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
10910 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10911 _("shift expression is too large"));
10916 /* Shifts of zero must be done as lsl. */
10918 else if (value
== 32)
10920 newval
&= 0xfffff07f;
10921 newval
|= (value
& 0x1f) << 7;
10922 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10925 case BFD_RELOC_ARM_SWI
:
10926 if (arm_data
->thumb_mode
)
10928 if (((unsigned long) value
) > 0xff)
10929 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10930 _("invalid swi expression"));
10931 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
10933 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10937 if (((unsigned long) value
) > 0x00ffffff)
10938 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10939 _("invalid swi expression"));
10940 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
10942 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10946 case BFD_RELOC_ARM_MULTI
:
10947 if (((unsigned long) value
) > 0xffff)
10948 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10949 _("invalid expression in load/store multiple"));
10950 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
10951 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10954 case BFD_RELOC_ARM_PCREL_BRANCH
:
10955 newval
= md_chars_to_number (buf
, INSN_SIZE
);
10957 /* Sign-extend a 24-bit number. */
10958 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10962 value
= fixP
->fx_offset
;
10965 /* We are going to store value (shifted right by two) in the
10966 instruction, in a 24 bit, signed field. Thus we need to check
10967 that none of the top 8 bits of the shifted value (top 7 bits of
10968 the unshifted, unsigned value) are set, or that they are all set. */
10969 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
10970 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
10973 /* Normally we would be stuck at this point, since we cannot store
10974 the absolute address that is the destination of the branch in the
10975 24 bits of the branch instruction. If however, we happen to know
10976 that the destination of the branch is in the same section as the
10977 branch instruciton itself, then we can compute the relocation for
10978 ourselves and not have to bother the linker with it.
10980 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10981 because I have not worked out how to do this for OBJ_COFF or
10984 && fixP
->fx_addsy
!= NULL
10985 && S_IS_DEFINED (fixP
->fx_addsy
)
10986 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
10988 /* Get pc relative value to go into the branch. */
10991 /* Permit a backward branch provided that enough bits
10992 are set. Allow a forwards branch, provided that
10993 enough bits are clear. */
10994 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
10995 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
10999 if (! fixP
->fx_done
)
11001 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11002 _("GAS can't handle same-section branch dest >= 0x04000000"));
11006 value
+= SEXT24 (newval
);
11008 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
11009 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
11010 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11011 _("out of range branch"));
11013 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
11014 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11017 case BFD_RELOC_ARM_PCREL_BLX
:
11020 newval
= md_chars_to_number (buf
, INSN_SIZE
);
11024 value
= fixP
->fx_offset
;
11026 hbit
= (value
>> 1) & 1;
11027 value
= (value
>> 2) & 0x00ffffff;
11028 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
11029 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
11030 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11034 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
11035 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11037 addressT diff
= (newval
& 0xff) << 1;
11042 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
11043 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11044 _("branch out of range"));
11045 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
11047 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11050 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
11051 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11053 addressT diff
= (newval
& 0x7ff) << 1;
11058 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
11059 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11060 _("branch out of range"));
11061 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
11063 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11066 case BFD_RELOC_THUMB_PCREL_BLX
:
11067 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11072 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11073 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
11074 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
11075 if (diff
& 0x400000)
11078 value
= fixP
->fx_offset
;
11082 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
11083 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11084 _("branch with link out of range"));
11086 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
11087 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
11088 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
11089 /* For a BLX instruction, make sure that the relocation is rounded up
11090 to a word boundary. This follows the semantics of the instruction
11091 which specifies that bit 1 of the target address will come from bit
11092 1 of the base address. */
11093 newval2
= (newval2
+ 1) & ~ 1;
11094 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11095 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
11100 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11101 md_number_to_chars (buf
, value
, 1);
11103 else if (!target_oabi
)
11105 value
= fixP
->fx_offset
;
11106 md_number_to_chars (buf
, value
, 1);
11112 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11113 md_number_to_chars (buf
, value
, 2);
11115 else if (!target_oabi
)
11117 value
= fixP
->fx_offset
;
11118 md_number_to_chars (buf
, value
, 2);
11124 case BFD_RELOC_ARM_GOT32
:
11125 case BFD_RELOC_ARM_GOTOFF
:
11126 md_number_to_chars (buf
, 0, 4);
11130 case BFD_RELOC_RVA
:
11132 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
11133 md_number_to_chars (buf
, value
, 4);
11135 else if (!target_oabi
)
11137 value
= fixP
->fx_offset
;
11138 md_number_to_chars (buf
, value
, 4);
11144 case BFD_RELOC_ARM_PLT32
:
11145 /* It appears the instruction is fully prepared at this point. */
11149 case BFD_RELOC_ARM_CP_OFF_IMM
:
11151 if (value
< -1023 || value
> 1023 || (value
& 3))
11152 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11153 _("illegal value for co-processor offset"));
11156 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11157 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
11158 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11161 case BFD_RELOC_ARM_CP_OFF_IMM_S2
:
11163 if (value
< -255 || value
> 255)
11164 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11165 _("Illegal value for co-processor offset"));
11168 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
11169 newval
|= value
| (sign
? INDEX_UP
: 0);
11170 md_number_to_chars (buf
, newval
, INSN_SIZE
);
11173 case BFD_RELOC_ARM_THUMB_OFFSET
:
11174 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11175 /* Exactly what ranges, and where the offset is inserted depends
11176 on the type of instruction, we can establish this from the
11178 switch (newval
>> 12)
11180 case 4: /* PC load. */
11181 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11182 forced to zero for these loads, so we will need to round
11183 up the offset if the instruction address is not word
11184 aligned (since the final address produced must be, and
11185 we can only describe word-aligned immediate offsets). */
11187 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
11188 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11189 _("invalid offset, target not word aligned (0x%08X)"),
11190 (unsigned int) (fixP
->fx_frag
->fr_address
11191 + fixP
->fx_where
+ value
));
11193 if ((value
+ 2) & ~0x3fe)
11194 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11195 _("invalid offset, value too big (0x%08lX)"),
11198 /* Round up, since pc will be rounded down. */
11199 newval
|= (value
+ 2) >> 2;
11202 case 9: /* SP load/store. */
11203 if (value
& ~0x3fc)
11204 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11205 _("invalid offset, value too big (0x%08lX)"),
11207 newval
|= value
>> 2;
11210 case 6: /* Word load/store. */
11212 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11213 _("invalid offset, value too big (0x%08lX)"),
11215 newval
|= value
<< 4; /* 6 - 2. */
11218 case 7: /* Byte load/store. */
11220 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11221 _("invalid offset, value too big (0x%08lX)"),
11223 newval
|= value
<< 6;
11226 case 8: /* Halfword load/store. */
11228 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11229 _("invalid offset, value too big (0x%08lX)"),
11231 newval
|= value
<< 5; /* 6 - 1. */
11235 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11236 "Unable to process relocation for thumb opcode: %lx",
11237 (unsigned long) newval
);
11240 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11243 case BFD_RELOC_ARM_THUMB_ADD
:
11244 /* This is a complicated relocation, since we use it for all of
11245 the following immediate relocations:
11249 9bit ADD/SUB SP word-aligned
11250 10bit ADD PC/SP word-aligned
11252 The type of instruction being processed is encoded in the
11259 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11261 int rd
= (newval
>> 4) & 0xf;
11262 int rs
= newval
& 0xf;
11263 int subtract
= newval
& 0x8000;
11267 if (value
& ~0x1fc)
11268 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11269 _("invalid immediate for stack address calculation"));
11270 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
11271 newval
|= value
>> 2;
11273 else if (rs
== REG_PC
|| rs
== REG_SP
)
11277 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11278 _("invalid immediate for address calculation (value = 0x%08lX)"),
11279 (unsigned long) value
);
11280 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
11282 newval
|= value
>> 2;
11287 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11288 _("invalid 8bit immediate"));
11289 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
11290 newval
|= (rd
<< 8) | value
;
11295 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11296 _("invalid 3bit immediate"));
11297 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
11298 newval
|= rd
| (rs
<< 3) | (value
<< 6);
11301 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11304 case BFD_RELOC_ARM_THUMB_IMM
:
11305 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
11306 switch (newval
>> 11)
11308 case 0x04: /* 8bit immediate MOV. */
11309 case 0x05: /* 8bit immediate CMP. */
11310 if (value
< 0 || value
> 255)
11311 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11312 _("invalid immediate: %ld is too large"),
11320 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11323 case BFD_RELOC_ARM_THUMB_SHIFT
:
11324 /* 5bit shift value (0..31). */
11325 if (value
< 0 || value
> 31)
11326 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11327 _("illegal Thumb shift value: %ld"), (long) value
);
11328 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
11329 newval
|= value
<< 6;
11330 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
11333 case BFD_RELOC_VTABLE_INHERIT
:
11334 case BFD_RELOC_VTABLE_ENTRY
:
11338 case BFD_RELOC_NONE
:
11340 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
11341 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
11345 /* Translate internal representation of relocation info to BFD target
11349 tc_gen_reloc (section
, fixp
)
11350 asection
* section ATTRIBUTE_UNUSED
;
11354 bfd_reloc_code_real_type code
;
11356 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
11358 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
11359 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
11360 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
11362 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
11364 if (fixp
->fx_pcrel
== 0)
11365 reloc
->addend
= fixp
->fx_offset
;
11367 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11368 #else /* OBJ_ELF */
11369 reloc
->addend
= fixp
->fx_offset
;
11372 switch (fixp
->fx_r_type
)
11375 if (fixp
->fx_pcrel
)
11377 code
= BFD_RELOC_8_PCREL
;
11382 if (fixp
->fx_pcrel
)
11384 code
= BFD_RELOC_16_PCREL
;
11389 if (fixp
->fx_pcrel
)
11391 code
= BFD_RELOC_32_PCREL
;
11395 case BFD_RELOC_ARM_PCREL_BRANCH
:
11396 case BFD_RELOC_ARM_PCREL_BLX
:
11397 case BFD_RELOC_RVA
:
11398 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
11399 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
11400 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
11401 case BFD_RELOC_THUMB_PCREL_BLX
:
11402 case BFD_RELOC_VTABLE_ENTRY
:
11403 case BFD_RELOC_VTABLE_INHERIT
:
11404 code
= fixp
->fx_r_type
;
11407 case BFD_RELOC_ARM_LITERAL
:
11408 case BFD_RELOC_ARM_HWLITERAL
:
11409 /* If this is called then the a literal has
11410 been referenced across a section boundary. */
11411 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11412 _("literal referenced across section boundary"));
11416 case BFD_RELOC_ARM_GOT32
:
11417 case BFD_RELOC_ARM_GOTOFF
:
11418 case BFD_RELOC_ARM_PLT32
:
11419 code
= fixp
->fx_r_type
;
11423 case BFD_RELOC_ARM_IMMEDIATE
:
11424 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11425 _("internal relocation (type: IMMEDIATE) not fixed up"));
11428 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
11429 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11430 _("ADRL used for a symbol not defined in the same file"));
11433 case BFD_RELOC_ARM_OFFSET_IMM
:
11434 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11435 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11442 switch (fixp
->fx_r_type
)
11444 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
11445 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
11446 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
11447 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
11448 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
11449 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
11450 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
11451 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
11452 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
11453 default: type
= _("<unknown>"); break;
11455 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11456 _("cannot represent %s relocation in this object file format"),
11463 if ((code
== BFD_RELOC_32_PCREL
|| code
== BFD_RELOC_32
)
11465 && fixp
->fx_addsy
== GOT_symbol
)
11467 code
= BFD_RELOC_ARM_GOTPC
;
11468 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
11472 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
11474 if (reloc
->howto
== NULL
)
11476 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
11477 _("cannot represent %s relocation in this object file format"),
11478 bfd_get_reloc_code_name (code
));
11482 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11483 vtable entry to be used in the relocation's section offset. */
11484 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11485 reloc
->address
= fixp
->fx_offset
;
11491 md_estimate_size_before_relax (fragP
, segtype
)
11492 fragS
* fragP ATTRIBUTE_UNUSED
;
11493 segT segtype ATTRIBUTE_UNUSED
;
11495 as_fatal (_("md_estimate_size_before_relax\n"));
11507 as_bad ("%s -- `%s'", inst
.error
, str
);
11511 to
= frag_more (inst
.size
);
11513 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
11515 assert (inst
.size
== (2 * THUMB_SIZE
));
11516 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
11517 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
11519 else if (inst
.size
> INSN_SIZE
)
11521 assert (inst
.size
== (2 * INSN_SIZE
));
11522 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
11523 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
11526 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
11528 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
11529 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
11530 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
11534 dwarf2_emit_insn (inst
.size
);
11546 /* Align the instruction.
11547 This may not be the right thing to do but ... */
11552 /* Align the previous label if needed. */
11553 if (last_label_seen
!= NULL
)
11555 symbol_set_frag (last_label_seen
, frag_now
);
11556 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
11557 S_SET_SEGMENT (last_label_seen
, now_seg
);
11560 memset (&inst
, '\0', sizeof (inst
));
11561 inst
.reloc
.type
= BFD_RELOC_NONE
;
11563 skip_whitespace (str
);
11565 /* Scan up to the end of the op-code, which must end in white space or
11567 for (start
= p
= str
; *p
!= '\0'; p
++)
11573 as_bad (_("no operator -- statement `%s'\n"), str
);
11579 const struct thumb_opcode
* opcode
;
11583 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
11588 /* Check that this instruction is supported for this CPU. */
11589 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
11591 as_bad (_("selected processor does not support `%s'"), str
);
11595 inst
.instruction
= opcode
->value
;
11596 inst
.size
= opcode
->size
;
11597 (*opcode
->parms
) (p
);
11604 const struct asm_opcode
* opcode
;
11608 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
11613 /* Check that this instruction is supported for this CPU. */
11614 if ((opcode
->variant
& cpu_variant
) == 0)
11616 as_bad (_("selected processor does not support `%s'"), str
);
11620 inst
.instruction
= opcode
->value
;
11621 inst
.size
= INSN_SIZE
;
11622 (*opcode
->parms
) (p
);
11628 /* It wasn't an instruction, but it might be a register alias of the form
11630 if (create_register_alias (str
, p
))
11633 as_bad (_("bad instruction `%s'"), start
);
11637 Invocation line includes a switch not recognized by the base assembler.
11638 See if it's a processor-specific option.
11640 This routine is somewhat complicated by the need for backwards
11641 compatibility (since older releases of gcc can't be changed).
11642 The new options try to make the interface as compatible as
11645 New options (supported) are:
11647 -mcpu=<cpu name> Assemble for selected processor
11648 -march=<architecture name> Assemble for selected architecture
11649 -mfpu=<fpu architecture> Assemble for selected FPU.
11650 -EB/-mbig-endian Big-endian
11651 -EL/-mlittle-endian Little-endian
11652 -k Generate PIC code
11653 -mthumb Start in Thumb mode
11654 -mthumb-interwork Code supports ARM/Thumb interworking
11656 For now we will also provide support for:
11658 -mapcs-32 32-bit Program counter
11659 -mapcs-26 26-bit Program counter
11660 -macps-float Floats passed in FP registers
11661 -mapcs-reentrant Reentrant code
11663 (sometime these will probably be replaced with -mapcs=<list of options>
11664 and -matpcs=<list of options>)
11666 The remaining options are only supported for back-wards compatibility.
11667 Cpu variants, the arm part is optional:
11668 -m[arm]1 Currently not supported.
11669 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
11670 -m[arm]3 Arm 3 processor
11671 -m[arm]6[xx], Arm 6 processors
11672 -m[arm]7[xx][t][[d]m] Arm 7 processors
11673 -m[arm]8[10] Arm 8 processors
11674 -m[arm]9[20][tdmi] Arm 9 processors
11675 -mstrongarm[110[0]] StrongARM processors
11676 -mxscale XScale processors
11677 -m[arm]v[2345[t[e]]] Arm architectures
11678 -mall All (except the ARM1)
11680 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
11681 -mfpe-old (No float load/store multiples)
11682 -mvfpxd VFP Single precision
11684 -mno-fpu Disable all floating point instructions
11686 The following CPU names are recognized:
11687 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11688 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11689 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11690 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11691 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11692 arm10t arm10e, arm1020t, arm1020e, arm10200e,
11693 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11697 const char * md_shortopts
= "m:k";
11699 #ifdef ARM_BI_ENDIAN
11700 #define OPTION_EB (OPTION_MD_BASE + 0)
11701 #define OPTION_EL (OPTION_MD_BASE + 1)
11703 #if TARGET_BYTES_BIG_ENDIAN
11704 #define OPTION_EB (OPTION_MD_BASE + 0)
11706 #define OPTION_EL (OPTION_MD_BASE + 1)
11710 struct option md_longopts
[] =
11713 {"EB", no_argument
, NULL
, OPTION_EB
},
11716 {"EL", no_argument
, NULL
, OPTION_EL
},
11718 {NULL
, no_argument
, NULL
, 0}
11721 size_t md_longopts_size
= sizeof (md_longopts
);
11723 struct arm_option_table
11725 char *option
; /* Option name to match. */
11726 char *help
; /* Help information. */
11727 int *var
; /* Variable to change. */
11728 int value
; /* What to change it to. */
11729 char *deprecated
; /* If non-null, print this message. */
11732 struct arm_option_table arm_opts
[] =
11734 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
11735 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
11736 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11737 &support_interwork
, 1, NULL
},
11738 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
11739 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
11740 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
11741 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
11743 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
11744 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
11745 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
11746 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
11749 /* These are recognized by the assembler, but have no affect on code. */
11750 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
11751 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
11753 /* DON'T add any new processors to this list -- we want the whole list
11754 to go away... Add them to the processors table instead. */
11755 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11756 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
11757 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11758 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
11759 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11760 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
11761 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11762 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
11763 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11764 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
11765 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11766 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
11767 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11768 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
11769 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11770 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
11771 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11772 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
11773 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11774 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
11775 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11776 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
11777 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11778 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
11779 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11780 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
11781 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11782 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
11783 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11784 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
11785 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11786 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
11787 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11788 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
11789 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11790 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
11791 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11792 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
11793 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11794 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
11795 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11796 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
11797 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11798 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
11799 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11800 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
11801 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11802 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11803 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11804 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
11805 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11806 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
11807 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11808 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
11809 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11810 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
11811 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11812 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
11813 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11814 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
11815 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11816 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
11817 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11818 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
11819 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11820 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
11821 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11822 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
11823 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
11824 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11825 N_("use -mcpu=strongarm110")},
11826 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11827 N_("use -mcpu=strongarm1100")},
11828 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
11829 N_("use -mcpu=strongarm1110")},
11830 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
11831 {"miwmmxt", NULL
, &legacy_cpu
, ARM_ARCH_IWMMXT
, N_("use -mcpu=iwmmxt")},
11832 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
11834 /* Architecture variants -- don't add any more to this list either. */
11835 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11836 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
11837 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11838 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
11839 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11840 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
11841 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11842 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
11843 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11844 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
11845 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11846 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
11847 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11848 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
11849 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11850 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
11851 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11852 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
11854 /* Floating point variants -- don't add any more to this list either. */
11855 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
11856 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
11857 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
11858 {"mno-fpu", NULL
, &legacy_fpu
, 0,
11859 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11861 {NULL
, NULL
, NULL
, 0, NULL
}
11864 struct arm_cpu_option_table
11868 /* For some CPUs we assume an FPU unless the user explicitly sets
11873 /* This list should, at a minimum, contain all the cpu names
11874 recognized by GCC. */
11875 static struct arm_cpu_option_table arm_cpus
[] =
11877 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11878 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11879 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11880 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11881 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11882 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11883 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11884 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11885 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11886 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11887 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11888 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11889 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11890 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11891 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11892 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11893 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11894 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11895 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11896 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11897 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11898 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11899 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11900 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11901 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11902 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11903 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11904 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11905 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11906 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11907 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11908 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11909 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11910 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11911 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11912 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11913 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11914 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11915 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11916 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11917 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11918 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11919 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11920 /* For V5 or later processors we default to using VFP; but the user
11921 should really set the FPU type explicitly. */
11922 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11923 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11924 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
11925 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11926 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11927 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
11928 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11929 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
11930 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11931 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11932 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
11933 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
11934 /* ??? XSCALE is really an architecture. */
11935 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
11936 /* ??? iwmmxt is not a processor. */
11937 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP_V2
},
11938 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
11940 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
11944 struct arm_arch_option_table
11951 /* This list should, at a minimum, contain all the architecture names
11952 recognized by GCC. */
11953 static struct arm_arch_option_table arm_archs
[] =
11955 {"all", ARM_ANY
, FPU_ARCH_FPA
},
11956 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
11957 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
11958 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11959 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
11960 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
11961 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
11962 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
11963 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
11964 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
11965 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
11966 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
11967 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
11968 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
11969 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
11970 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
11971 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
11972 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
11973 {"iwmmxt", ARM_ARCH_IWMMXT
, FPU_ARCH_VFP
},
11977 /* ISA extensions in the co-processor space. */
11978 struct arm_arch_extension_table
11984 static struct arm_arch_extension_table arm_extensions
[] =
11986 {"maverick", ARM_CEXT_MAVERICK
},
11987 {"xscale", ARM_CEXT_XSCALE
},
11988 {"iwmmxt", ARM_CEXT_IWMMXT
},
11992 struct arm_fpu_option_table
11998 /* This list should, at a minimum, contain all the fpu names
11999 recognized by GCC. */
12000 static struct arm_fpu_option_table arm_fpus
[] =
12002 {"softfpa", FPU_NONE
},
12003 {"fpe", FPU_ARCH_FPE
},
12004 {"fpe2", FPU_ARCH_FPE
},
12005 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
12006 {"fpa", FPU_ARCH_FPA
},
12007 {"fpa10", FPU_ARCH_FPA
},
12008 {"fpa11", FPU_ARCH_FPA
},
12009 {"arm7500fe", FPU_ARCH_FPA
},
12010 {"softvfp", FPU_ARCH_VFP
},
12011 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
12012 {"vfp", FPU_ARCH_VFP_V2
},
12013 {"vfp9", FPU_ARCH_VFP_V2
},
12014 {"vfp10", FPU_ARCH_VFP_V2
},
12015 {"vfp10-r0", FPU_ARCH_VFP_V1
},
12016 {"vfpxd", FPU_ARCH_VFP_V1xD
},
12017 {"arm1020t", FPU_ARCH_VFP_V1
},
12018 {"arm1020e", FPU_ARCH_VFP_V2
},
12022 struct arm_long_option_table
12024 char *option
; /* Substring to match. */
12025 char *help
; /* Help information. */
12026 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
12027 char *deprecated
; /* If non-null, print this message. */
12031 arm_parse_extension (str
, opt_p
)
12035 while (str
!= NULL
&& *str
!= 0)
12037 struct arm_arch_extension_table
*opt
;
12043 as_bad (_("invalid architectural extension"));
12048 ext
= strchr (str
, '+');
12051 optlen
= ext
- str
;
12053 optlen
= strlen (str
);
12057 as_bad (_("missing architectural extension"));
12061 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
12062 if (strncmp (opt
->name
, str
, optlen
) == 0)
12064 *opt_p
|= opt
->value
;
12068 if (opt
->name
== NULL
)
12070 as_bad (_("unknown architectural extnsion `%s'"), str
);
12081 arm_parse_cpu (str
)
12084 struct arm_cpu_option_table
*opt
;
12085 char *ext
= strchr (str
, '+');
12089 optlen
= ext
- str
;
12091 optlen
= strlen (str
);
12095 as_bad (_("missing cpu name `%s'"), str
);
12099 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
12100 if (strncmp (opt
->name
, str
, optlen
) == 0)
12102 mcpu_cpu_opt
= opt
->value
;
12103 mcpu_fpu_opt
= opt
->default_fpu
;
12106 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
12111 as_bad (_("unknown cpu `%s'"), str
);
12116 arm_parse_arch (str
)
12119 struct arm_arch_option_table
*opt
;
12120 char *ext
= strchr (str
, '+');
12124 optlen
= ext
- str
;
12126 optlen
= strlen (str
);
12130 as_bad (_("missing architecture name `%s'"), str
);
12135 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
12136 if (strcmp (opt
->name
, str
) == 0)
12138 march_cpu_opt
= opt
->value
;
12139 march_fpu_opt
= opt
->default_fpu
;
12142 return arm_parse_extension (ext
, &march_cpu_opt
);
12147 as_bad (_("unknown architecture `%s'\n"), str
);
12152 arm_parse_fpu (str
)
12155 struct arm_fpu_option_table
*opt
;
12157 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
12158 if (strcmp (opt
->name
, str
) == 0)
12160 mfpu_opt
= opt
->value
;
12164 as_bad (_("unknown floating point format `%s'\n"), str
);
12168 struct arm_long_option_table arm_long_opts
[] =
12170 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
12171 arm_parse_cpu
, NULL
},
12172 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
12173 arm_parse_arch
, NULL
},
12174 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
12175 arm_parse_fpu
, NULL
},
12176 {NULL
, NULL
, 0, NULL
}
12180 md_parse_option (c
, arg
)
12184 struct arm_option_table
*opt
;
12185 struct arm_long_option_table
*lopt
;
12191 target_big_endian
= 1;
12197 target_big_endian
= 0;
12202 /* Listing option. Just ignore these, we don't support additional
12207 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12209 if (c
== opt
->option
[0]
12210 && ((arg
== NULL
&& opt
->option
[1] == 0)
12211 || strcmp (arg
, opt
->option
+ 1) == 0))
12213 #if WARN_DEPRECATED
12214 /* If the option is deprecated, tell the user. */
12215 if (opt
->deprecated
!= NULL
)
12216 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
12217 arg
? arg
: "", _(opt
->deprecated
));
12220 if (opt
->var
!= NULL
)
12221 *opt
->var
= opt
->value
;
12227 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12229 /* These options are expected to have an argument. */
12230 if (c
== lopt
->option
[0]
12232 && strncmp (arg
, lopt
->option
+ 1,
12233 strlen (lopt
->option
+ 1)) == 0)
12235 #if WARN_DEPRECATED
12236 /* If the option is deprecated, tell the user. */
12237 if (lopt
->deprecated
!= NULL
)
12238 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
12239 _(lopt
->deprecated
));
12242 /* Call the sup-option parser. */
12243 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
12247 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
12258 struct arm_option_table
*opt
;
12259 struct arm_long_option_table
*lopt
;
12261 fprintf (fp
, _(" ARM-specific assembler options:\n"));
12263 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
12264 if (opt
->help
!= NULL
)
12265 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
12267 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
12268 if (lopt
->help
!= NULL
)
12269 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
12273 -EB assemble code for a big-endian cpu\n"));
12278 -EL assemble code for a little-endian cpu\n"));
12282 /* We need to be able to fix up arbitrary expressions in some statements.
12283 This is so that we can handle symbols that are an arbitrary distance from
12284 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12285 which returns part of an address in a form which will be valid for
12286 a data instruction. We do this by pushing the expression into a symbol
12287 in the expr_section, and creating a fix for that. */
12290 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
12299 arm_fix_data
* arm_data
;
12307 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
12311 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
12316 /* Mark whether the fix is to a THUMB instruction, or an ARM
12318 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
12319 new_fix
->tc_fix_data
= (PTR
) arm_data
;
12320 arm_data
->thumb_mode
= thumb_mode
;
12325 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
12328 cons_fix_new_arm (frag
, where
, size
, exp
)
12334 bfd_reloc_code_real_type type
;
12338 FIXME: @@ Should look at CPU word size. */
12342 type
= BFD_RELOC_8
;
12345 type
= BFD_RELOC_16
;
12349 type
= BFD_RELOC_32
;
12352 type
= BFD_RELOC_64
;
12356 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
12359 /* A good place to do this, although this was probably not intended
12360 for this kind of use. We need to dump the literal pool before
12361 references are made to a null symbol pointer. */
12366 literal_pool
* pool
;
12368 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
12370 /* Put it at the end of the relevent section. */
12371 subseg_set (pool
->section
, pool
->sub_section
);
12377 arm_start_line_hook ()
12379 last_label_seen
= NULL
;
12383 arm_frob_label (sym
)
12386 last_label_seen
= sym
;
12388 ARM_SET_THUMB (sym
, thumb_mode
);
12390 #if defined OBJ_COFF || defined OBJ_ELF
12391 ARM_SET_INTERWORK (sym
, support_interwork
);
12394 /* Note - do not allow local symbols (.Lxxx) to be labeled
12395 as Thumb functions. This is because these labels, whilst
12396 they exist inside Thumb code, are not the entry points for
12397 possible ARM->Thumb calls. Also, these labels can be used
12398 as part of a computed goto or switch statement. eg gcc
12399 can generate code that looks like this:
12401 ldr r2, [pc, .Laaa]
12411 The first instruction loads the address of the jump table.
12412 The second instruction converts a table index into a byte offset.
12413 The third instruction gets the jump address out of the table.
12414 The fourth instruction performs the jump.
12416 If the address stored at .Laaa is that of a symbol which has the
12417 Thumb_Func bit set, then the linker will arrange for this address
12418 to have the bottom bit set, which in turn would mean that the
12419 address computation performed by the third instruction would end
12420 up with the bottom bit set. Since the ARM is capable of unaligned
12421 word loads, the instruction would then load the incorrect address
12422 out of the jump table, and chaos would ensue. */
12423 if (label_is_thumb_function_name
12424 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
12425 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
12427 /* When the address of a Thumb function is taken the bottom
12428 bit of that address should be set. This will allow
12429 interworking between Arm and Thumb functions to work
12432 THUMB_SET_FUNC (sym
, 1);
12434 label_is_thumb_function_name
= FALSE
;
12438 /* Adjust the symbol table. This marks Thumb symbols as distinct from
12442 arm_adjust_symtab ()
12447 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12449 if (ARM_IS_THUMB (sym
))
12451 if (THUMB_IS_FUNC (sym
))
12453 /* Mark the symbol as a Thumb function. */
12454 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
12455 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
12456 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
12458 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
12459 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
12461 as_bad (_("%s: unexpected function type: %d"),
12462 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
12464 else switch (S_GET_STORAGE_CLASS (sym
))
12467 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
12470 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
12473 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
12481 if (ARM_IS_INTERWORK (sym
))
12482 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
12489 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
12491 if (ARM_IS_THUMB (sym
))
12493 elf_symbol_type
* elf_sym
;
12495 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
12496 bind
= ELF_ST_BIND (elf_sym
);
12498 /* If it's a .thumb_func, declare it as so,
12499 otherwise tag label as .code 16. */
12500 if (THUMB_IS_FUNC (sym
))
12501 elf_sym
->internal_elf_sym
.st_info
=
12502 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
12504 elf_sym
->internal_elf_sym
.st_info
=
12505 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
12512 arm_data_in_code ()
12514 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
12516 *input_line_pointer
= '/';
12517 input_line_pointer
+= 5;
12518 *input_line_pointer
= 0;
12526 arm_canonicalize_symbol_name (name
)
12531 if (thumb_mode
&& (len
= strlen (name
)) > 5
12532 && streq (name
+ len
- 5, "/data"))
12533 *(name
+ len
- 5) = 0;
12538 #if defined OBJ_COFF || defined OBJ_ELF
12540 arm_validate_fix (fixP
)
12543 /* If the destination of the branch is a defined symbol which does not have
12544 the THUMB_FUNC attribute, then we must be calling a function which has
12545 the (interfacearm) attribute. We look for the Thumb entry point to that
12546 function and change the branch to refer to that function instead. */
12547 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
12548 && fixP
->fx_addsy
!= NULL
12549 && S_IS_DEFINED (fixP
->fx_addsy
)
12550 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
12552 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
12558 arm_force_relocation (fixp
)
12561 #if defined (OBJ_COFF) && defined (TE_PE)
12562 if (fixp
->fx_r_type
== BFD_RELOC_RVA
)
12566 if (fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
12567 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
12568 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
12569 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
12573 /* Resolve these relocations even if the symbol is extern or weak. */
12574 if (fixp
->fx_r_type
== BFD_RELOC_ARM_IMMEDIATE
12575 || fixp
->fx_r_type
== BFD_RELOC_ARM_OFFSET_IMM
12576 || fixp
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12579 return generic_force_reloc (fixp
);
12583 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
12584 local labels from being added to the output symbol table when they
12585 are used with the ADRL pseudo op. The ADRL relocation should always
12586 be resolved before the binbary is emitted, so it is safe to say that
12587 it is adjustable. */
12590 arm_fix_adjustable (fixP
)
12593 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
12600 /* Relocations against Thumb function names must be left unadjusted,
12601 so that the linker can use this information to correctly set the
12602 bottom bit of their addresses. The MIPS version of this function
12603 also prevents relocations that are mips-16 specific, but I do not
12604 know why it does this.
12607 There is one other problem that ought to be addressed here, but
12608 which currently is not: Taking the address of a label (rather
12609 than a function) and then later jumping to that address. Such
12610 addresses also ought to have their bottom bit set (assuming that
12611 they reside in Thumb code), but at the moment they will not. */
12614 arm_fix_adjustable (fixP
)
12617 if (fixP
->fx_addsy
== NULL
)
12620 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
12621 && fixP
->fx_subsy
== NULL
)
12624 /* We need the symbol name for the VTABLE entries. */
12625 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
12626 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
12629 /* Don't allow symbols to be discarded on GOT related relocs. */
12630 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
12631 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
12632 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
12639 elf32_arm_target_format ()
12641 if (target_big_endian
)
12644 return "elf32-bigarm-oabi";
12646 return "elf32-bigarm";
12651 return "elf32-littlearm-oabi";
12653 return "elf32-littlearm";
12658 armelf_frob_symbol (symp
, puntp
)
12662 elf_frob_symbol (symp
, puntp
);
12665 static bfd_reloc_code_real_type
12675 bfd_reloc_code_real_type reloc
;
12679 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12680 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
12681 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
12682 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12683 branch instructions generated by GCC for PLT relocs. */
12684 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
12685 { NULL
, 0, BFD_RELOC_UNUSED
}
12689 for (i
= 0, ip
= input_line_pointer
;
12690 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
12692 id
[i
] = TOLOWER (*ip
);
12694 for (i
= 0; reloc_map
[i
].str
; i
++)
12695 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
12698 input_line_pointer
+= reloc_map
[i
].len
;
12700 return reloc_map
[i
].reloc
;
12704 s_arm_elf_cons (nbytes
)
12709 #ifdef md_flush_pending_output
12710 md_flush_pending_output ();
12713 if (is_it_end_of_statement ())
12715 demand_empty_rest_of_line ();
12719 #ifdef md_cons_align
12720 md_cons_align (nbytes
);
12725 bfd_reloc_code_real_type reloc
;
12727 expression (& exp
);
12729 if (exp
.X_op
== O_symbol
12730 && * input_line_pointer
== '('
12731 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
12733 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
12734 int size
= bfd_get_reloc_size (howto
);
12737 as_bad ("%s relocations do not fit in %d bytes",
12738 howto
->name
, nbytes
);
12741 register char *p
= frag_more ((int) nbytes
);
12742 int offset
= nbytes
- size
;
12744 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
12749 emit_expr (&exp
, (unsigned int) nbytes
);
12751 while (*input_line_pointer
++ == ',');
12753 /* Put terminator back into stream. */
12754 input_line_pointer
--;
12755 demand_empty_rest_of_line ();
12758 #endif /* OBJ_ELF */
12760 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
12761 of an rs_align_code fragment. */
12764 arm_handle_align (fragP
)
12767 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12768 static char const thumb_noop
[2] = { 0xc0, 0x46 };
12769 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12770 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
12772 int bytes
, fix
, noop_size
;
12776 if (fragP
->fr_type
!= rs_align_code
)
12779 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
12780 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
12783 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12784 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
12786 if (fragP
->tc_frag_data
)
12788 if (target_big_endian
)
12789 noop
= thumb_bigend_noop
;
12792 noop_size
= sizeof (thumb_noop
);
12796 if (target_big_endian
)
12797 noop
= arm_bigend_noop
;
12800 noop_size
= sizeof (arm_noop
);
12803 if (bytes
& (noop_size
- 1))
12805 fix
= bytes
& (noop_size
- 1);
12806 memset (p
, 0, fix
);
12811 while (bytes
>= noop_size
)
12813 memcpy (p
, noop
, noop_size
);
12815 bytes
-= noop_size
;
12819 fragP
->fr_fix
+= fix
;
12820 fragP
->fr_var
= noop_size
;
12823 /* Called from md_do_align. Used to create an alignment
12824 frag in a code section. */
12827 arm_frag_align_code (n
, max
)
12833 /* We assume that there will never be a requirment
12834 to support alignments greater than 32 bytes. */
12835 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
12836 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12838 p
= frag_var (rs_align_code
,
12839 MAX_MEM_FOR_RS_ALIGN_CODE
,
12841 (relax_substateT
) max
,
12849 /* Perform target specific initialisation of a frag. */
12852 arm_init_frag (fragP
)
12855 /* Record whether this frag is in an ARM or a THUMB area. */
12856 fragP
->tc_frag_data
= thumb_mode
;