1 /* tc-arm.c -- Assemble for the ARM
2 Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
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. */
63 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
64 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
65 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
66 three more to cover cores prior to ARM6. Finally, there are cores which
67 implement further extensions in the co-processor space. */
68 #define ARM_ARCH_V1 ARM_EXT_V1
69 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
70 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
71 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
72 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
73 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
74 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
75 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
76 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
77 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
78 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
79 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
80 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
82 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
83 #define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
85 /* Processors with specific extensions in the co-processor space. */
86 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
88 /* Some useful combinations: */
89 #define ARM_ANY 0x0000ffff /* Any basic core. */
90 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
91 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
92 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
95 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
96 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
97 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
98 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
99 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
100 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
103 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
104 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
106 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
107 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
108 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
109 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
111 /* Types of processor to assemble for. */
112 #define ARM_1 ARM_ARCH_V1
113 #define ARM_2 ARM_ARCH_V2
114 #define ARM_3 ARM_ARCH_V2S
115 #define ARM_250 ARM_ARCH_V2S
116 #define ARM_6 ARM_ARCH_V3
117 #define ARM_7 ARM_ARCH_V3
118 #define ARM_8 ARM_ARCH_V4
119 #define ARM_9 ARM_ARCH_V4T
120 #define ARM_STRONG ARM_ARCH_V4
121 #define ARM_CPU_MASK 0x0000000f /* XXX? */
124 #if defined __XSCALE__
125 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
127 #if defined __thumb__
128 #define CPU_DEFAULT (ARM_ARCH_V5T)
130 #define CPU_DEFAULT ARM_ANY
135 /* For backwards compatibility we default to the FPA. */
137 #define FPU_DEFAULT FPU_ARCH_FPA
140 #define streq(a, b) (strcmp (a, b) == 0)
141 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
143 static unsigned long cpu_variant
;
144 static int target_oabi
= 0;
146 /* Flags stored in private area of BFD structure. */
147 static int uses_apcs_26
= false;
148 static int atpcs
= false;
149 static int support_interwork
= false;
150 static int uses_apcs_float
= false;
151 static int pic_code
= false;
153 /* Variables that we set while parsing command-line options. Once all
154 options have been read we re-process these values to set the real
156 static int legacy_cpu
= -1;
157 static int legacy_fpu
= -1;
159 static int mcpu_cpu_opt
= -1;
160 static int mcpu_fpu_opt
= -1;
161 static int march_cpu_opt
= -1;
162 static int march_fpu_opt
= -1;
163 static int mfpu_opt
= -1;
165 /* This array holds the chars that always start a comment. If the
166 pre-processor is disabled, these aren't very useful. */
167 const char comment_chars
[] = "@";
169 /* This array holds the chars that only start a comment at the beginning of
170 a line. If the line seems to have the form '# 123 filename'
171 .line and .file directives will appear in the pre-processed output. */
172 /* Note that input_file.c hand checks for '#' at the beginning of the
173 first line of the input file. This is because the compiler outputs
174 #NO_APP at the beginning of its output. */
175 /* Also note that comments like this one will always work. */
176 const char line_comment_chars
[] = "#";
178 const char line_separator_chars
[] = ";";
180 /* Chars that can be used to separate mant
181 from exp in floating point numbers. */
182 const char EXP_CHARS
[] = "eE";
184 /* Chars that mean this number is a floating point constant. */
188 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
190 /* Prefix characters that indicate the start of an immediate
192 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
195 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
196 symbolS
* GOT_symbol
;
199 /* Size of relocation record. */
200 const int md_reloc_size
= 8;
202 /* 0: assemble for ARM,
203 1: assemble for Thumb,
204 2: assemble for Thumb even though target CPU does not support thumb
206 static int thumb_mode
= 0;
208 typedef struct arm_fix
216 unsigned long instruction
;
220 bfd_reloc_code_real_type type
;
237 struct asm_shift_properties
239 enum asm_shift_index index
;
240 unsigned long bit_field
;
241 unsigned int allows_0
: 1;
242 unsigned int allows_32
: 1;
245 static const struct asm_shift_properties shift_properties
[] =
247 { SHIFT_LSL
, 0, 1, 0},
248 { SHIFT_LSR
, 0x20, 0, 1},
249 { SHIFT_ASR
, 0x40, 0, 1},
250 { SHIFT_ROR
, 0x60, 0, 0},
251 { SHIFT_RRX
, 0x60, 0, 0}
254 struct asm_shift_name
257 const struct asm_shift_properties
* properties
;
260 static const struct asm_shift_name shift_names
[] =
262 { "asl", shift_properties
+ SHIFT_LSL
},
263 { "lsl", shift_properties
+ SHIFT_LSL
},
264 { "lsr", shift_properties
+ SHIFT_LSR
},
265 { "asr", shift_properties
+ SHIFT_ASR
},
266 { "ror", shift_properties
+ SHIFT_ROR
},
267 { "rrx", shift_properties
+ SHIFT_RRX
},
268 { "ASL", shift_properties
+ SHIFT_LSL
},
269 { "LSL", shift_properties
+ SHIFT_LSL
},
270 { "LSR", shift_properties
+ SHIFT_LSR
},
271 { "ASR", shift_properties
+ SHIFT_ASR
},
272 { "ROR", shift_properties
+ SHIFT_ROR
},
273 { "RRX", shift_properties
+ SHIFT_RRX
}
276 #define NO_SHIFT_RESTRICT 1
277 #define SHIFT_RESTRICT 0
279 #define NUM_FLOAT_VALS 8
281 const char * fp_const
[] =
283 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
286 /* Number of littlenums required to hold an extended precision number. */
287 #define MAX_LITTLENUMS 6
289 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
294 /* Whether a Co-processor load/store operation accepts write-back forms. */
303 #define CP_T_X 0x00008000
304 #define CP_T_Y 0x00400000
305 #define CP_T_Pre 0x01000000
306 #define CP_T_UD 0x00800000
307 #define CP_T_WB 0x00200000
309 #define CONDS_BIT 0x00100000
310 #define LOAD_BIT 0x00100000
312 #define DOUBLE_LOAD_FLAG 0x00000001
316 const char * template;
320 #define COND_ALWAYS 0xe0000000
321 #define COND_MASK 0xf0000000
323 static const struct asm_cond conds
[] =
327 {"cs", 0x20000000}, {"hs", 0x20000000},
328 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
345 const char * template;
350 /* The bit that distnguishes CPSR and SPSR. */
351 #define SPSR_BIT (1 << 22)
353 /* How many bits to shift the PSR_xxx bits up by. */
356 #define PSR_c (1 << 0)
357 #define PSR_x (1 << 1)
358 #define PSR_s (1 << 2)
359 #define PSR_f (1 << 3)
361 static const struct asm_psr psrs
[] =
363 {"CPSR", true, PSR_c
| PSR_f
},
364 {"CPSR_all", true, PSR_c
| PSR_f
},
365 {"SPSR", false, PSR_c
| PSR_f
},
366 {"SPSR_all", false, PSR_c
| PSR_f
},
367 {"CPSR_flg", true, PSR_f
},
368 {"CPSR_f", true, PSR_f
},
369 {"SPSR_flg", false, PSR_f
},
370 {"SPSR_f", false, PSR_f
},
371 {"CPSR_c", true, PSR_c
},
372 {"CPSR_ctl", true, PSR_c
},
373 {"SPSR_c", false, PSR_c
},
374 {"SPSR_ctl", false, PSR_c
},
375 {"CPSR_x", true, PSR_x
},
376 {"CPSR_s", true, PSR_s
},
377 {"SPSR_x", false, PSR_x
},
378 {"SPSR_s", false, PSR_s
},
379 /* Combinations of flags. */
380 {"CPSR_fs", true, PSR_f
| PSR_s
},
381 {"CPSR_fx", true, PSR_f
| PSR_x
},
382 {"CPSR_fc", true, PSR_f
| PSR_c
},
383 {"CPSR_sf", true, PSR_s
| PSR_f
},
384 {"CPSR_sx", true, PSR_s
| PSR_x
},
385 {"CPSR_sc", true, PSR_s
| PSR_c
},
386 {"CPSR_xf", true, PSR_x
| PSR_f
},
387 {"CPSR_xs", true, PSR_x
| PSR_s
},
388 {"CPSR_xc", true, PSR_x
| PSR_c
},
389 {"CPSR_cf", true, PSR_c
| PSR_f
},
390 {"CPSR_cs", true, PSR_c
| PSR_s
},
391 {"CPSR_cx", true, PSR_c
| PSR_x
},
392 {"CPSR_fsx", true, PSR_f
| PSR_s
| PSR_x
},
393 {"CPSR_fsc", true, PSR_f
| PSR_s
| PSR_c
},
394 {"CPSR_fxs", true, PSR_f
| PSR_x
| PSR_s
},
395 {"CPSR_fxc", true, PSR_f
| PSR_x
| PSR_c
},
396 {"CPSR_fcs", true, PSR_f
| PSR_c
| PSR_s
},
397 {"CPSR_fcx", true, PSR_f
| PSR_c
| PSR_x
},
398 {"CPSR_sfx", true, PSR_s
| PSR_f
| PSR_x
},
399 {"CPSR_sfc", true, PSR_s
| PSR_f
| PSR_c
},
400 {"CPSR_sxf", true, PSR_s
| PSR_x
| PSR_f
},
401 {"CPSR_sxc", true, PSR_s
| PSR_x
| PSR_c
},
402 {"CPSR_scf", true, PSR_s
| PSR_c
| PSR_f
},
403 {"CPSR_scx", true, PSR_s
| PSR_c
| PSR_x
},
404 {"CPSR_xfs", true, PSR_x
| PSR_f
| PSR_s
},
405 {"CPSR_xfc", true, PSR_x
| PSR_f
| PSR_c
},
406 {"CPSR_xsf", true, PSR_x
| PSR_s
| PSR_f
},
407 {"CPSR_xsc", true, PSR_x
| PSR_s
| PSR_c
},
408 {"CPSR_xcf", true, PSR_x
| PSR_c
| PSR_f
},
409 {"CPSR_xcs", true, PSR_x
| PSR_c
| PSR_s
},
410 {"CPSR_cfs", true, PSR_c
| PSR_f
| PSR_s
},
411 {"CPSR_cfx", true, PSR_c
| PSR_f
| PSR_x
},
412 {"CPSR_csf", true, PSR_c
| PSR_s
| PSR_f
},
413 {"CPSR_csx", true, PSR_c
| PSR_s
| PSR_x
},
414 {"CPSR_cxf", true, PSR_c
| PSR_x
| PSR_f
},
415 {"CPSR_cxs", true, PSR_c
| PSR_x
| PSR_s
},
416 {"CPSR_fsxc", true, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
417 {"CPSR_fscx", true, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
418 {"CPSR_fxsc", true, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
419 {"CPSR_fxcs", true, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
420 {"CPSR_fcsx", true, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
421 {"CPSR_fcxs", true, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
422 {"CPSR_sfxc", true, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
423 {"CPSR_sfcx", true, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
424 {"CPSR_sxfc", true, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
425 {"CPSR_sxcf", true, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
426 {"CPSR_scfx", true, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
427 {"CPSR_scxf", true, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
428 {"CPSR_xfsc", true, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
429 {"CPSR_xfcs", true, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
430 {"CPSR_xsfc", true, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
431 {"CPSR_xscf", true, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
432 {"CPSR_xcfs", true, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
433 {"CPSR_xcsf", true, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
434 {"CPSR_cfsx", true, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
435 {"CPSR_cfxs", true, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
436 {"CPSR_csfx", true, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
437 {"CPSR_csxf", true, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
438 {"CPSR_cxfs", true, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
439 {"CPSR_cxsf", true, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
440 {"SPSR_fs", false, PSR_f
| PSR_s
},
441 {"SPSR_fx", false, PSR_f
| PSR_x
},
442 {"SPSR_fc", false, PSR_f
| PSR_c
},
443 {"SPSR_sf", false, PSR_s
| PSR_f
},
444 {"SPSR_sx", false, PSR_s
| PSR_x
},
445 {"SPSR_sc", false, PSR_s
| PSR_c
},
446 {"SPSR_xf", false, PSR_x
| PSR_f
},
447 {"SPSR_xs", false, PSR_x
| PSR_s
},
448 {"SPSR_xc", false, PSR_x
| PSR_c
},
449 {"SPSR_cf", false, PSR_c
| PSR_f
},
450 {"SPSR_cs", false, PSR_c
| PSR_s
},
451 {"SPSR_cx", false, PSR_c
| PSR_x
},
452 {"SPSR_fsx", false, PSR_f
| PSR_s
| PSR_x
},
453 {"SPSR_fsc", false, PSR_f
| PSR_s
| PSR_c
},
454 {"SPSR_fxs", false, PSR_f
| PSR_x
| PSR_s
},
455 {"SPSR_fxc", false, PSR_f
| PSR_x
| PSR_c
},
456 {"SPSR_fcs", false, PSR_f
| PSR_c
| PSR_s
},
457 {"SPSR_fcx", false, PSR_f
| PSR_c
| PSR_x
},
458 {"SPSR_sfx", false, PSR_s
| PSR_f
| PSR_x
},
459 {"SPSR_sfc", false, PSR_s
| PSR_f
| PSR_c
},
460 {"SPSR_sxf", false, PSR_s
| PSR_x
| PSR_f
},
461 {"SPSR_sxc", false, PSR_s
| PSR_x
| PSR_c
},
462 {"SPSR_scf", false, PSR_s
| PSR_c
| PSR_f
},
463 {"SPSR_scx", false, PSR_s
| PSR_c
| PSR_x
},
464 {"SPSR_xfs", false, PSR_x
| PSR_f
| PSR_s
},
465 {"SPSR_xfc", false, PSR_x
| PSR_f
| PSR_c
},
466 {"SPSR_xsf", false, PSR_x
| PSR_s
| PSR_f
},
467 {"SPSR_xsc", false, PSR_x
| PSR_s
| PSR_c
},
468 {"SPSR_xcf", false, PSR_x
| PSR_c
| PSR_f
},
469 {"SPSR_xcs", false, PSR_x
| PSR_c
| PSR_s
},
470 {"SPSR_cfs", false, PSR_c
| PSR_f
| PSR_s
},
471 {"SPSR_cfx", false, PSR_c
| PSR_f
| PSR_x
},
472 {"SPSR_csf", false, PSR_c
| PSR_s
| PSR_f
},
473 {"SPSR_csx", false, PSR_c
| PSR_s
| PSR_x
},
474 {"SPSR_cxf", false, PSR_c
| PSR_x
| PSR_f
},
475 {"SPSR_cxs", false, PSR_c
| PSR_x
| PSR_s
},
476 {"SPSR_fsxc", false, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
477 {"SPSR_fscx", false, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
478 {"SPSR_fxsc", false, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
479 {"SPSR_fxcs", false, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
480 {"SPSR_fcsx", false, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
481 {"SPSR_fcxs", false, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
482 {"SPSR_sfxc", false, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
483 {"SPSR_sfcx", false, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
484 {"SPSR_sxfc", false, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
485 {"SPSR_sxcf", false, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
486 {"SPSR_scfx", false, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
487 {"SPSR_scxf", false, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
488 {"SPSR_xfsc", false, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
489 {"SPSR_xfcs", false, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
490 {"SPSR_xsfc", false, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
491 {"SPSR_xscf", false, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
492 {"SPSR_xcfs", false, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
493 {"SPSR_xcsf", false, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
494 {"SPSR_cfsx", false, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
495 {"SPSR_cfxs", false, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
496 {"SPSR_csfx", false, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
497 {"SPSR_csxf", false, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
498 {"SPSR_cxfs", false, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
499 {"SPSR_cxsf", false, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
504 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
509 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
514 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
517 /* VFP system registers. */
524 static const struct vfp_reg vfp_regs
[] =
526 {"fpsid", 0x00000000},
527 {"FPSID", 0x00000000},
528 {"fpscr", 0x00010000},
529 {"FPSCR", 0x00010000},
530 {"fpexc", 0x00080000},
531 {"FPEXC", 0x00080000}
534 /* Structure for a hash table entry for a register. */
541 /* Some well known registers that we refer to directly elsewhere. */
546 /* These are the standard names. Users can add aliases with .req. */
547 /* Integer Register Numbers. */
548 static const struct reg_entry rn_table
[] =
550 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
551 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
552 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
553 {"r12", 12}, {"r13", REG_SP
}, {"r14", REG_LR
}, {"r15", REG_PC
},
554 /* ATPCS Synonyms. */
555 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
556 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
557 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
558 /* Well-known aliases. */
560 {"sb", 9}, {"sl", 10}, {"fp", 11},
561 {"ip", 12}, {"sp", REG_SP
}, {"lr", REG_LR
}, {"pc", REG_PC
},
565 /* Co-processor Numbers. */
566 static const struct reg_entry cp_table
[] =
568 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
569 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
570 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
571 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
575 /* Co-processor Register Numbers. */
576 static const struct reg_entry cn_table
[] =
578 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
579 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
580 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
581 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
582 /* Not really valid, but kept for back-wards compatibility. */
583 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
584 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
585 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
586 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
591 static const struct reg_entry fn_table
[] =
593 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
594 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
598 /* VFP SP Registers. */
599 static const struct reg_entry sn_table
[] =
601 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
602 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
603 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
604 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
605 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
606 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
607 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
608 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
612 /* VFP DP Registers. */
613 static const struct reg_entry dn_table
[] =
615 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
616 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
617 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
618 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
622 /* Maverick DSP coprocessor registers. */
623 static const struct reg_entry mav_mvf_table
[] =
625 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
626 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
627 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
628 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
632 static const struct reg_entry mav_mvd_table
[] =
634 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
635 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
636 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
637 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
641 static const struct reg_entry mav_mvfx_table
[] =
643 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
644 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
645 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
646 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
650 static const struct reg_entry mav_mvdx_table
[] =
652 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
653 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
654 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
655 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
659 static const struct reg_entry mav_mvax_table
[] =
661 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
665 static const struct reg_entry mav_dspsc_table
[] =
673 const struct reg_entry
*names
;
675 struct hash_control
*htab
;
676 const char *expected
;
679 struct reg_map all_reg_maps
[] =
681 {rn_table
, 15, NULL
, N_("ARM register expected")},
682 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
683 {cn_table
, 15, NULL
, N_("co-processor register expected")},
684 {fn_table
, 7, NULL
, N_("FPA register expected")},
685 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
686 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
687 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
688 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
689 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
690 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
691 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
692 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
695 /* Enumeration matching entries in table above. */
699 #define REG_TYPE_FIRST REG_TYPE_RN
715 /* Functions called by parser. */
716 /* ARM instructions. */
717 static void do_arit
PARAMS ((char *));
718 static void do_cmp
PARAMS ((char *));
719 static void do_mov
PARAMS ((char *));
720 static void do_ldst
PARAMS ((char *));
721 static void do_ldstt
PARAMS ((char *));
722 static void do_ldmstm
PARAMS ((char *));
723 static void do_branch
PARAMS ((char *));
724 static void do_swi
PARAMS ((char *));
726 /* Pseudo Op codes. */
727 static void do_adr
PARAMS ((char *));
728 static void do_adrl
PARAMS ((char *));
729 static void do_empty
PARAMS ((char *));
732 static void do_mul
PARAMS ((char *));
733 static void do_mla
PARAMS ((char *));
736 static void do_swap
PARAMS ((char *));
739 static void do_msr
PARAMS ((char *));
740 static void do_mrs
PARAMS ((char *));
743 static void do_mull
PARAMS ((char *));
746 static void do_ldstv4
PARAMS ((char *));
749 static void do_bx
PARAMS ((char *));
752 static void do_blx
PARAMS ((char *));
753 static void do_bkpt
PARAMS ((char *));
754 static void do_clz
PARAMS ((char *));
755 static void do_lstc2
PARAMS ((char *));
756 static void do_cdp2
PARAMS ((char *));
757 static void do_co_reg2
PARAMS ((char *));
760 static void do_smla
PARAMS ((char *));
761 static void do_smlal
PARAMS ((char *));
762 static void do_smul
PARAMS ((char *));
763 static void do_qadd
PARAMS ((char *));
766 static void do_pld
PARAMS ((char *));
767 static void do_ldrd
PARAMS ((char *));
768 static void do_co_reg2c
PARAMS ((char *));
771 static void do_bxj
PARAMS ((char *));
773 /* Coprocessor Instructions. */
774 static void do_cdp
PARAMS ((char *));
775 static void do_lstc
PARAMS ((char *));
776 static void do_co_reg
PARAMS ((char *));
778 /* FPA instructions. */
779 static void do_fpa_ctrl
PARAMS ((char *));
780 static void do_fpa_ldst
PARAMS ((char *));
781 static void do_fpa_ldmstm
PARAMS ((char *));
782 static void do_fpa_dyadic
PARAMS ((char *));
783 static void do_fpa_monadic
PARAMS ((char *));
784 static void do_fpa_cmp
PARAMS ((char *));
785 static void do_fpa_from_reg
PARAMS ((char *));
786 static void do_fpa_to_reg
PARAMS ((char *));
788 /* VFP instructions. */
789 static void do_vfp_sp_monadic
PARAMS ((char *));
790 static void do_vfp_dp_monadic
PARAMS ((char *));
791 static void do_vfp_sp_dyadic
PARAMS ((char *));
792 static void do_vfp_dp_dyadic
PARAMS ((char *));
793 static void do_vfp_reg_from_sp
PARAMS ((char *));
794 static void do_vfp_sp_from_reg
PARAMS ((char *));
795 static void do_vfp_sp_reg2
PARAMS ((char *));
796 static void do_vfp_reg_from_dp
PARAMS ((char *));
797 static void do_vfp_reg2_from_dp
PARAMS ((char *));
798 static void do_vfp_dp_from_reg
PARAMS ((char *));
799 static void do_vfp_dp_from_reg2
PARAMS ((char *));
800 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
801 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
802 static void do_vfp_sp_ldst
PARAMS ((char *));
803 static void do_vfp_dp_ldst
PARAMS ((char *));
804 static void do_vfp_sp_ldstmia
PARAMS ((char *));
805 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
806 static void do_vfp_dp_ldstmia
PARAMS ((char *));
807 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
808 static void do_vfp_xp_ldstmia
PARAMS ((char *));
809 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
810 static void do_vfp_sp_compare_z
PARAMS ((char *));
811 static void do_vfp_dp_compare_z
PARAMS ((char *));
812 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
813 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
816 static void do_xsc_mia
PARAMS ((char *));
817 static void do_xsc_mar
PARAMS ((char *));
818 static void do_xsc_mra
PARAMS ((char *));
821 static void do_mav_binops
PARAMS ((char *, int, enum arm_reg_type
,
823 static void do_mav_binops_1a
PARAMS ((char *));
824 static void do_mav_binops_1b
PARAMS ((char *));
825 static void do_mav_binops_1c
PARAMS ((char *));
826 static void do_mav_binops_1d
PARAMS ((char *));
827 static void do_mav_binops_1e
PARAMS ((char *));
828 static void do_mav_binops_1f
PARAMS ((char *));
829 static void do_mav_binops_1g
PARAMS ((char *));
830 static void do_mav_binops_1h
PARAMS ((char *));
831 static void do_mav_binops_1i
PARAMS ((char *));
832 static void do_mav_binops_1j
PARAMS ((char *));
833 static void do_mav_binops_1k
PARAMS ((char *));
834 static void do_mav_binops_1l
PARAMS ((char *));
835 static void do_mav_binops_1m
PARAMS ((char *));
836 static void do_mav_binops_1n
PARAMS ((char *));
837 static void do_mav_binops_1o
PARAMS ((char *));
838 static void do_mav_binops_2a
PARAMS ((char *));
839 static void do_mav_binops_2b
PARAMS ((char *));
840 static void do_mav_binops_2c
PARAMS ((char *));
841 static void do_mav_binops_3a
PARAMS ((char *));
842 static void do_mav_binops_3b
PARAMS ((char *));
843 static void do_mav_binops_3c
PARAMS ((char *));
844 static void do_mav_binops_3d
PARAMS ((char *));
845 static void do_mav_triple
PARAMS ((char *, int, enum arm_reg_type
,
848 static void do_mav_triple_4a
PARAMS ((char *));
849 static void do_mav_triple_4b
PARAMS ((char *));
850 static void do_mav_triple_5a
PARAMS ((char *));
851 static void do_mav_triple_5b
PARAMS ((char *));
852 static void do_mav_triple_5c
PARAMS ((char *));
853 static void do_mav_triple_5d
PARAMS ((char *));
854 static void do_mav_triple_5e
PARAMS ((char *));
855 static void do_mav_triple_5f
PARAMS ((char *));
856 static void do_mav_triple_5g
PARAMS ((char *));
857 static void do_mav_triple_5h
PARAMS ((char *));
858 static void do_mav_quad
PARAMS ((char *, int, enum arm_reg_type
,
862 static void do_mav_quad_6a
PARAMS ((char *));
863 static void do_mav_quad_6b
PARAMS ((char *));
864 static void do_mav_dspsc_1
PARAMS ((char *));
865 static void do_mav_dspsc_2
PARAMS ((char *));
866 static void do_mav_shift
PARAMS ((char *, enum arm_reg_type
,
868 static void do_mav_shift_1
PARAMS ((char *));
869 static void do_mav_shift_2
PARAMS ((char *));
870 static void do_mav_ldst
PARAMS ((char *, enum arm_reg_type
));
871 static void do_mav_ldst_1
PARAMS ((char *));
872 static void do_mav_ldst_2
PARAMS ((char *));
873 static void do_mav_ldst_3
PARAMS ((char *));
874 static void do_mav_ldst_4
PARAMS ((char *));
876 static int mav_reg_required_here
PARAMS ((char **, int,
878 static int mav_parse_offset
PARAMS ((char **, int *));
880 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
882 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
883 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
884 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
885 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
887 static int add_to_lit_pool
PARAMS ((void));
888 static unsigned validate_immediate
PARAMS ((unsigned));
889 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
891 static int validate_offset_imm
PARAMS ((unsigned int, int));
892 static void opcode_select
PARAMS ((int));
893 static void end_of_line
PARAMS ((char *));
894 static int reg_required_here
PARAMS ((char **, int));
895 static int psr_required_here
PARAMS ((char **));
896 static int co_proc_number
PARAMS ((char **));
897 static int cp_opc_expr
PARAMS ((char **, int, int));
898 static int cp_reg_required_here
PARAMS ((char **, int));
899 static int fp_reg_required_here
PARAMS ((char **, int));
900 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
901 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
902 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
903 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
904 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
905 static long vfp_dp_reg_list
PARAMS ((char **));
906 static int vfp_psr_required_here
PARAMS ((char **str
));
907 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
908 static int cp_address_offset
PARAMS ((char **));
909 static int cp_address_required_here
PARAMS ((char **, int));
910 static int my_get_float_expression
PARAMS ((char **));
911 static int skip_past_comma
PARAMS ((char **));
912 static int walk_no_bignums
PARAMS ((symbolS
*));
913 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
914 static int data_op2
PARAMS ((char **));
915 static int fp_op2
PARAMS ((char **));
916 static long reg_list
PARAMS ((char **));
917 static void thumb_load_store
PARAMS ((char *, int, int));
918 static int decode_shift
PARAMS ((char **, int));
919 static int ldst_extend
PARAMS ((char **));
920 static int ldst_extend_v4
PARAMS ((char **));
921 static void thumb_add_sub
PARAMS ((char *, int));
922 static void insert_reg
PARAMS ((const struct reg_entry
*,
923 struct hash_control
*));
924 static void thumb_shift
PARAMS ((char *, int));
925 static void thumb_mov_compare
PARAMS ((char *, int));
926 static void build_arm_ops_hsh
PARAMS ((void));
927 static void set_constant_flonums
PARAMS ((void));
928 static valueT md_chars_to_number
PARAMS ((char *, int));
929 static void build_reg_hsh
PARAMS ((struct reg_map
*));
930 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
931 static int create_register_alias
PARAMS ((char *, char *));
932 static void output_inst
PARAMS ((const char *));
933 static int accum0_required_here
PARAMS ((char **));
934 static int ld_mode_required_here
PARAMS ((char **));
935 static void do_branch25
PARAMS ((char *));
936 static symbolS
* find_real_start
PARAMS ((symbolS
*));
938 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
941 /* ARM instructions take 4bytes in the object file, Thumb instructions
945 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
946 #define MAV_MODE1 0x100c
948 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
949 #define MAV_MODE2 0x0c10
951 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
952 #define MAV_MODE3 0x1000
954 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
955 #define MAV_MODE4 0x0c0010
957 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
958 #define MAV_MODE5 0x00100c
960 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
961 #define MAV_MODE6 0x00100c05
965 /* Basic string to match. */
966 const char * template;
968 /* Basic instruction code. */
971 /* Offset into the template where the condition code (if any) will be.
972 If zero, then the instruction is never conditional. */
973 unsigned cond_offset
;
975 /* Which architecture variant provides this instruction. */
976 unsigned long variant
;
978 /* Function to call to parse args. */
979 void (* parms
) PARAMS ((char *));
982 static const struct asm_opcode insns
[] =
984 /* Core ARM Instructions. */
985 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
986 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
987 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
988 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
989 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
990 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
991 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
992 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
993 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
994 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
995 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
996 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
997 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
998 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
999 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
1000 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
1001 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
1002 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
1003 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
1004 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1006 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1007 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1008 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1009 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1010 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1011 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1012 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1013 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1014 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1015 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1016 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1017 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1019 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1020 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1021 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1022 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1024 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1025 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1026 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1027 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1028 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1029 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1030 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1031 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1033 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1034 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1035 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1036 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1037 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1038 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1039 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1040 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1042 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1043 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1044 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1045 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1046 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1047 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1048 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1049 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1051 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1053 /* XXX This is the wrong place to do this. Think multi-arch. */
1054 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1055 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1057 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1058 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1062 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1063 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1064 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1066 /* ARM 2 multiplies. */
1067 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1068 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1069 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1070 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1072 /* Generic copressor instructions. */
1073 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1074 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1075 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1076 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1077 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1078 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1079 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1081 /* ARM 3 - swp instructions. */
1082 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1083 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1085 /* ARM 6 Status register instructions. */
1086 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1087 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1088 /* ScottB: our code uses 0xe128f000 for msr.
1089 NickC: but this is wrong because the bits 16 through 19 are
1090 handled by the PSR_xxx defines above. */
1092 /* ARM 7M long multiplies. */
1093 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1094 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1095 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1096 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1097 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1098 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1099 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1100 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1102 /* ARM Architecture 4. */
1103 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1104 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1105 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1106 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1108 /* ARM Architecture 4T. */
1109 /* Note: bx (and blx) are required on V5, even if the processor does
1110 not support Thumb. */
1111 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1113 /* ARM Architecture 5T. */
1114 /* Note: blx has 2 variants, so the .value is set dynamically.
1115 Only one of the variants has conditional execution. */
1116 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1117 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1118 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1119 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1120 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1121 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1122 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1123 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1124 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1125 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1127 /* ARM Architecture 5TExP. */
1128 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1129 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1130 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1131 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1133 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1134 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1136 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1137 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1138 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1139 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1141 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1142 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1143 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1144 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1146 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1147 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1149 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1150 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1151 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1152 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1154 /* ARM Architecture 5TE. */
1155 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1156 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1157 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1159 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1160 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1162 /* ARM Architecture 5TEJ. */
1163 {"bxj", 0xe12fff20, 3, ARM_EXT_V5J
, do_bxj
},
1165 /* Core FPA instruction set (V1). */
1166 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1167 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1168 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1169 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1171 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1172 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1173 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1174 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1176 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1177 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1178 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1179 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1181 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1182 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1183 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1184 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1185 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1186 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1187 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1188 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1189 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1190 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1191 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1192 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1194 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1195 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1196 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1197 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1198 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1199 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1200 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1201 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1202 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1203 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1204 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1205 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1207 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1208 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1209 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1210 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1211 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1212 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1213 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1214 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1215 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1216 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1217 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1218 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1220 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1221 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1222 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1223 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1224 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1225 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1226 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1227 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1228 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1229 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1230 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1231 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1233 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1234 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1235 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1236 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1237 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1238 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1239 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1240 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1241 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1242 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1243 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1244 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1246 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1247 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1248 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1249 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1250 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1251 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1252 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1253 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1254 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1255 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1256 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1257 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1259 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1260 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1261 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1262 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1263 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1264 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1265 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1266 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1267 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1268 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1269 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1270 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1272 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1273 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1274 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1275 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1276 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1277 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1278 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1279 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1280 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1281 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1282 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1283 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1285 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1286 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1287 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1288 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1289 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1290 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1291 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1292 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1302 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1304 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1315 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1317 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1328 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1330 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1341 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1343 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1354 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1356 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1367 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1369 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1380 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1382 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1383 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1384 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1385 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1386 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1387 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1389 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1390 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1391 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1392 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1393 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1394 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1395 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1396 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1397 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1398 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1399 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1400 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1402 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1403 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1404 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1405 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1406 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1407 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1408 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1409 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1410 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1411 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1412 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1413 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1415 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1416 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1417 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1418 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1419 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1420 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1421 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1422 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1423 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1424 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1425 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1426 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1428 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1429 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1430 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1431 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1432 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1433 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1434 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1435 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1436 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1437 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1438 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1439 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1441 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1442 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1443 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1444 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1445 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1446 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1447 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1448 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1449 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1450 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1451 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1452 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1454 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1455 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1456 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1457 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1458 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1459 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1460 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1461 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1462 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1463 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1464 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1465 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1467 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1468 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1469 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1470 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1471 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1472 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1473 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1474 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1475 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1476 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1477 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1478 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1480 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1481 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1482 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1483 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1484 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1485 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1486 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1487 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1488 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1489 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1490 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1491 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1493 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1494 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1495 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1496 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1497 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1498 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1499 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1500 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1510 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1512 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1523 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1525 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1536 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1538 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1549 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1551 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1552 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1553 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1554 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1555 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1556 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1558 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1559 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1560 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1561 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1562 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1563 not be an optional suffix, but part of the instruction. To be
1564 compatible, we accept either. */
1565 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1566 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1568 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1569 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1570 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1571 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1572 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1573 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1574 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1575 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1576 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1577 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1578 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1579 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1581 /* The implementation of the FIX instruction is broken on some
1582 assemblers, in that it accepts a precision specifier as well as a
1583 rounding specifier, despite the fact that this is meaningless.
1584 To be more compatible, we accept it as well, though of course it
1585 does not set any bits. */
1586 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1587 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1588 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1589 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1590 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1591 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1592 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1593 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1594 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1595 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1596 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1597 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1598 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1600 /* Instructions that were new with the real FPA, call them V2. */
1601 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1602 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1603 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1604 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1605 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1606 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1608 /* VFP V1xD (single precision). */
1609 /* Moves and type conversions. */
1610 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1611 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1612 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1613 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1614 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1615 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1616 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1617 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1618 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1619 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1620 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1621 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1623 /* Memory operations. */
1624 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1625 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1626 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1627 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1628 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1629 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1630 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1631 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1632 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1633 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1634 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1635 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1636 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1637 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1638 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1639 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1640 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1641 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1643 /* Monadic operations. */
1644 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1645 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1646 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1648 /* Dyadic operations. */
1649 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1650 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1651 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1652 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1653 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1654 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1655 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1656 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1657 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1660 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1661 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1662 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1663 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1665 /* VFP V1 (Double precision). */
1666 /* Moves and type conversions. */
1667 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1668 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1669 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1670 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1671 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1672 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1673 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1674 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1675 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1676 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1677 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1678 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1679 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1681 /* Memory operations. */
1682 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1683 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1684 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1685 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1686 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1687 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1688 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1689 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1690 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1691 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1693 /* Monadic operations. */
1694 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1695 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1696 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1698 /* Dyadic operations. */
1699 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1700 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1701 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1702 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1703 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1704 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1705 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1706 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1707 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1710 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1711 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1712 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1713 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1716 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1717 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1718 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1719 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1721 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1722 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_xsc_mia
},
1723 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1724 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1725 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1726 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1727 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_xsc_mia
},
1728 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_xsc_mar
},
1729 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_xsc_mra
},
1731 /* Cirrus Maverick instructions. */
1732 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
1733 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
1734 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
1735 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
1736 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_1
},
1737 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_mav_ldst_2
},
1738 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_3
},
1739 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_mav_ldst_4
},
1740 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_2a
},
1741 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1a
},
1742 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
1743 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
1744 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_2b
},
1745 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1b
},
1746 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
1747 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
1748 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_2c
},
1749 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1c
},
1750 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
1751 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
1752 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
1753 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
1754 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
1755 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
1756 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3a
},
1757 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3b
},
1758 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3c
},
1759 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_mav_binops_3d
},
1760 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_1
},
1761 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_mav_dspsc_2
},
1762 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
1763 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
1764 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1f
},
1765 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1g
},
1766 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1h
},
1767 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1i
},
1768 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1j
},
1769 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1k
},
1770 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
1771 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
1772 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1l
},
1773 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_mav_binops_1m
},
1774 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4a
},
1775 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_mav_triple_4b
},
1776 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_1
},
1777 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_mav_shift_2
},
1778 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5a
},
1779 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5b
},
1780 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5c
},
1781 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5d
},
1782 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
1783 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
1784 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1d
},
1785 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_mav_binops_1e
},
1786 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
1787 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
1788 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
1789 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
1790 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5e
},
1791 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_mav_triple_5f
},
1792 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
1793 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
1794 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1n
},
1795 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_mav_binops_1o
},
1796 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
1797 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
1798 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
1799 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
1800 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
1801 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5h
},
1802 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
1803 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_mav_triple_5g
},
1804 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
1805 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_mav_quad_6a
},
1806 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
1807 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_mav_quad_6b
},
1810 /* Defines for various bits that we will want to toggle. */
1811 #define INST_IMMEDIATE 0x02000000
1812 #define OFFSET_REG 0x02000000
1813 #define HWOFFSET_IMM 0x00400000
1814 #define SHIFT_BY_REG 0x00000010
1815 #define PRE_INDEX 0x01000000
1816 #define INDEX_UP 0x00800000
1817 #define WRITE_BACK 0x00200000
1818 #define LDM_TYPE_2_OR_3 0x00400000
1820 #define LITERAL_MASK 0xf000f000
1821 #define OPCODE_MASK 0xfe1fffff
1822 #define V4_STR_BIT 0x00000020
1824 #define DATA_OP_SHIFT 21
1826 /* Codes to distinguish the arithmetic instructions. */
1827 #define OPCODE_AND 0
1828 #define OPCODE_EOR 1
1829 #define OPCODE_SUB 2
1830 #define OPCODE_RSB 3
1831 #define OPCODE_ADD 4
1832 #define OPCODE_ADC 5
1833 #define OPCODE_SBC 6
1834 #define OPCODE_RSC 7
1835 #define OPCODE_TST 8
1836 #define OPCODE_TEQ 9
1837 #define OPCODE_CMP 10
1838 #define OPCODE_CMN 11
1839 #define OPCODE_ORR 12
1840 #define OPCODE_MOV 13
1841 #define OPCODE_BIC 14
1842 #define OPCODE_MVN 15
1844 /* Thumb v1 (ARMv4T). */
1845 static void do_t_nop
PARAMS ((char *));
1846 static void do_t_arit
PARAMS ((char *));
1847 static void do_t_add
PARAMS ((char *));
1848 static void do_t_asr
PARAMS ((char *));
1849 static void do_t_branch9
PARAMS ((char *));
1850 static void do_t_branch12
PARAMS ((char *));
1851 static void do_t_branch23
PARAMS ((char *));
1852 static void do_t_bx
PARAMS ((char *));
1853 static void do_t_compare
PARAMS ((char *));
1854 static void do_t_ldmstm
PARAMS ((char *));
1855 static void do_t_ldr
PARAMS ((char *));
1856 static void do_t_ldrb
PARAMS ((char *));
1857 static void do_t_ldrh
PARAMS ((char *));
1858 static void do_t_lds
PARAMS ((char *));
1859 static void do_t_lsl
PARAMS ((char *));
1860 static void do_t_lsr
PARAMS ((char *));
1861 static void do_t_mov
PARAMS ((char *));
1862 static void do_t_push_pop
PARAMS ((char *));
1863 static void do_t_str
PARAMS ((char *));
1864 static void do_t_strb
PARAMS ((char *));
1865 static void do_t_strh
PARAMS ((char *));
1866 static void do_t_sub
PARAMS ((char *));
1867 static void do_t_swi
PARAMS ((char *));
1868 static void do_t_adr
PARAMS ((char *));
1870 /* Thumb v2 (ARMv5T). */
1871 static void do_t_blx
PARAMS ((char *));
1872 static void do_t_bkpt
PARAMS ((char *));
1874 #define T_OPCODE_MUL 0x4340
1875 #define T_OPCODE_TST 0x4200
1876 #define T_OPCODE_CMN 0x42c0
1877 #define T_OPCODE_NEG 0x4240
1878 #define T_OPCODE_MVN 0x43c0
1880 #define T_OPCODE_ADD_R3 0x1800
1881 #define T_OPCODE_SUB_R3 0x1a00
1882 #define T_OPCODE_ADD_HI 0x4400
1883 #define T_OPCODE_ADD_ST 0xb000
1884 #define T_OPCODE_SUB_ST 0xb080
1885 #define T_OPCODE_ADD_SP 0xa800
1886 #define T_OPCODE_ADD_PC 0xa000
1887 #define T_OPCODE_ADD_I8 0x3000
1888 #define T_OPCODE_SUB_I8 0x3800
1889 #define T_OPCODE_ADD_I3 0x1c00
1890 #define T_OPCODE_SUB_I3 0x1e00
1892 #define T_OPCODE_ASR_R 0x4100
1893 #define T_OPCODE_LSL_R 0x4080
1894 #define T_OPCODE_LSR_R 0x40c0
1895 #define T_OPCODE_ASR_I 0x1000
1896 #define T_OPCODE_LSL_I 0x0000
1897 #define T_OPCODE_LSR_I 0x0800
1899 #define T_OPCODE_MOV_I8 0x2000
1900 #define T_OPCODE_CMP_I8 0x2800
1901 #define T_OPCODE_CMP_LR 0x4280
1902 #define T_OPCODE_MOV_HR 0x4600
1903 #define T_OPCODE_CMP_HR 0x4500
1905 #define T_OPCODE_LDR_PC 0x4800
1906 #define T_OPCODE_LDR_SP 0x9800
1907 #define T_OPCODE_STR_SP 0x9000
1908 #define T_OPCODE_LDR_IW 0x6800
1909 #define T_OPCODE_STR_IW 0x6000
1910 #define T_OPCODE_LDR_IH 0x8800
1911 #define T_OPCODE_STR_IH 0x8000
1912 #define T_OPCODE_LDR_IB 0x7800
1913 #define T_OPCODE_STR_IB 0x7000
1914 #define T_OPCODE_LDR_RW 0x5800
1915 #define T_OPCODE_STR_RW 0x5000
1916 #define T_OPCODE_LDR_RH 0x5a00
1917 #define T_OPCODE_STR_RH 0x5200
1918 #define T_OPCODE_LDR_RB 0x5c00
1919 #define T_OPCODE_STR_RB 0x5400
1921 #define T_OPCODE_PUSH 0xb400
1922 #define T_OPCODE_POP 0xbc00
1924 #define T_OPCODE_BRANCH 0xe7fe
1926 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
1928 #define THUMB_SIZE 2 /* Size of thumb instruction. */
1929 #define THUMB_REG_LO 0x1
1930 #define THUMB_REG_HI 0x2
1931 #define THUMB_REG_ANY 0x3
1933 #define THUMB_H1 0x0080
1934 #define THUMB_H2 0x0040
1940 #define THUMB_MOVE 0
1941 #define THUMB_COMPARE 1
1943 #define THUMB_LOAD 0
1944 #define THUMB_STORE 1
1946 #define THUMB_PP_PC_LR 0x0100
1948 /* These three are used for immediate shifts, do not alter. */
1949 #define THUMB_WORD 2
1950 #define THUMB_HALFWORD 1
1951 #define THUMB_BYTE 0
1955 /* Basic string to match. */
1956 const char * template;
1958 /* Basic instruction code. */
1959 unsigned long value
;
1963 /* Which CPU variants this exists for. */
1964 unsigned long variant
;
1966 /* Function to call to parse args. */
1967 void (* parms
) PARAMS ((char *));
1970 static const struct thumb_opcode tinsns
[] =
1972 /* Thumb v1 (ARMv4T). */
1973 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
1974 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
1975 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
1976 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
1977 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
1978 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1979 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1980 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1981 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1982 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1983 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1984 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1985 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1986 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1987 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1988 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1989 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1990 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1991 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
1992 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1993 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1994 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1995 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
1996 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
1997 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
1998 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
1999 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
2000 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
2001 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
2002 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2003 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
2004 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
2005 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
2006 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2007 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2008 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2009 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2010 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2011 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2012 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2013 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2014 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2015 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2016 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2017 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2018 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2019 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2020 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2021 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2022 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2023 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2024 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2025 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2026 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2027 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2029 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2030 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2031 /* Thumb v2 (ARMv5T). */
2032 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2033 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2036 #define BAD_ARGS _("bad arguments to instruction")
2037 #define BAD_PC _("r15 not allowed here")
2038 #define BAD_COND _("instruction is not conditional")
2039 #define ERR_NO_ACCUM _("acc0 expected")
2041 static struct hash_control
* arm_ops_hsh
= NULL
;
2042 static struct hash_control
* arm_tops_hsh
= NULL
;
2043 static struct hash_control
* arm_cond_hsh
= NULL
;
2044 static struct hash_control
* arm_shift_hsh
= NULL
;
2045 static struct hash_control
* arm_psr_hsh
= NULL
;
2047 /* This table describes all the machine specific pseudo-ops the assembler
2048 has to support. The fields are:
2049 pseudo-op name without dot
2050 function to call to execute this pseudo-op
2051 Integer arg to pass to the function. */
2053 static void s_req
PARAMS ((int));
2054 static void s_align
PARAMS ((int));
2055 static void s_bss
PARAMS ((int));
2056 static void s_even
PARAMS ((int));
2057 static void s_ltorg
PARAMS ((int));
2058 static void s_arm
PARAMS ((int));
2059 static void s_thumb
PARAMS ((int));
2060 static void s_code
PARAMS ((int));
2061 static void s_force_thumb
PARAMS ((int));
2062 static void s_thumb_func
PARAMS ((int));
2063 static void s_thumb_set
PARAMS ((int));
2064 static void arm_s_text
PARAMS ((int));
2065 static void arm_s_data
PARAMS ((int));
2066 static void arm_s_section
PARAMS ((int));
2068 static void s_arm_elf_cons
PARAMS ((int));
2071 static int my_get_expression
PARAMS ((expressionS
*, char **));
2073 const pseudo_typeS md_pseudo_table
[] =
2075 /* Never called becasue '.req' does not start line. */
2076 { "req", s_req
, 0 },
2077 { "bss", s_bss
, 0 },
2078 { "align", s_align
, 0 },
2079 { "arm", s_arm
, 0 },
2080 { "thumb", s_thumb
, 0 },
2081 { "code", s_code
, 0 },
2082 { "force_thumb", s_force_thumb
, 0 },
2083 { "thumb_func", s_thumb_func
, 0 },
2084 { "thumb_set", s_thumb_set
, 0 },
2085 { "even", s_even
, 0 },
2086 { "ltorg", s_ltorg
, 0 },
2087 { "pool", s_ltorg
, 0 },
2088 /* Allow for the effect of section changes. */
2089 { "text", arm_s_text
, 0 },
2090 { "data", arm_s_data
, 0 },
2091 { "section", arm_s_section
, 0 },
2092 { "section.s", arm_s_section
, 0 },
2093 { "sect", arm_s_section
, 0 },
2094 { "sect.s", arm_s_section
, 0 },
2096 { "word", s_arm_elf_cons
, 4 },
2097 { "long", s_arm_elf_cons
, 4 },
2098 { "file", dwarf2_directive_file
, 0 },
2099 { "loc", dwarf2_directive_loc
, 0 },
2103 { "extend", float_cons
, 'x' },
2104 { "ldouble", float_cons
, 'x' },
2105 { "packed", float_cons
, 'p' },
2109 /* Other internal functions. */
2110 static int arm_parse_extension
PARAMS ((char *, int *));
2111 static int arm_parse_cpu
PARAMS ((char *));
2112 static int arm_parse_arch
PARAMS ((char *));
2113 static int arm_parse_fpu
PARAMS ((char *));
2115 /* Stuff needed to resolve the label ambiguity
2125 symbolS
* last_label_seen
;
2126 static int label_is_thumb_function_name
= false;
2128 /* Literal stuff. */
2130 #define MAX_LITERAL_POOL_SIZE 1024
2132 typedef struct literalS
2134 struct expressionS exp
;
2135 struct arm_it
* inst
;
2138 literalT literals
[MAX_LITERAL_POOL_SIZE
];
2140 /* Next free entry in the pool. */
2141 int next_literal_pool_place
= 0;
2143 /* Next literal pool number. */
2144 int lit_pool_num
= 1;
2146 symbolS
* current_poolP
= NULL
;
2153 if (current_poolP
== NULL
)
2154 current_poolP
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2155 (valueT
) 0, &zero_address_frag
);
2157 /* Check if this literal value is already in the pool: */
2158 while (lit_count
< next_literal_pool_place
)
2160 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
2161 && inst
.reloc
.exp
.X_op
== O_constant
2162 && (literals
[lit_count
].exp
.X_add_number
2163 == inst
.reloc
.exp
.X_add_number
)
2164 && literals
[lit_count
].exp
.X_unsigned
== inst
.reloc
.exp
.X_unsigned
)
2167 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
2168 && inst
.reloc
.exp
.X_op
== O_symbol
2169 && (literals
[lit_count
].exp
.X_add_number
2170 == inst
.reloc
.exp
.X_add_number
)
2171 && (literals
[lit_count
].exp
.X_add_symbol
2172 == inst
.reloc
.exp
.X_add_symbol
)
2173 && (literals
[lit_count
].exp
.X_op_symbol
2174 == inst
.reloc
.exp
.X_op_symbol
))
2180 if (lit_count
== next_literal_pool_place
) /* New entry. */
2182 if (next_literal_pool_place
>= MAX_LITERAL_POOL_SIZE
)
2184 inst
.error
= _("literal pool overflow");
2188 literals
[next_literal_pool_place
].exp
= inst
.reloc
.exp
;
2189 lit_count
= next_literal_pool_place
++;
2192 inst
.reloc
.exp
.X_op
= O_symbol
;
2193 inst
.reloc
.exp
.X_add_number
= (lit_count
) * 4 - 8;
2194 inst
.reloc
.exp
.X_add_symbol
= current_poolP
;
2199 /* Can't use symbol_new here, so have to create a symbol and then at
2200 a later date assign it a value. Thats what these functions do. */
2203 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2205 const char * name
; /* It is copied, the caller can modify. */
2206 segT segment
; /* Segment identifier (SEG_<something>). */
2207 valueT valu
; /* Symbol value. */
2208 fragS
* frag
; /* Associated fragment. */
2210 unsigned int name_length
;
2211 char * preserved_copy_of_name
;
2213 name_length
= strlen (name
) + 1; /* +1 for \0. */
2214 obstack_grow (¬es
, name
, name_length
);
2215 preserved_copy_of_name
= obstack_finish (¬es
);
2216 #ifdef STRIP_UNDERSCORE
2217 if (preserved_copy_of_name
[0] == '_')
2218 preserved_copy_of_name
++;
2221 #ifdef tc_canonicalize_symbol_name
2222 preserved_copy_of_name
=
2223 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2226 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2228 S_SET_SEGMENT (symbolP
, segment
);
2229 S_SET_VALUE (symbolP
, valu
);
2230 symbol_clear_list_pointers (symbolP
);
2232 symbol_set_frag (symbolP
, frag
);
2234 /* Link to end of symbol chain. */
2236 extern int symbol_table_frozen
;
2237 if (symbol_table_frozen
)
2241 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2243 obj_symbol_new_hook (symbolP
);
2245 #ifdef tc_symbol_new_hook
2246 tc_symbol_new_hook (symbolP
);
2250 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2251 #endif /* DEBUG_SYMS */
2254 /* Check that an immediate is valid.
2255 If so, convert it to the right format. */
2258 validate_immediate (val
)
2264 #define rotate_left(v, n) (v << n | v >> (32 - n))
2266 for (i
= 0; i
< 32; i
+= 2)
2267 if ((a
= rotate_left (val
, i
)) <= 0xff)
2268 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2273 /* Check to see if an immediate can be computed as two seperate immediate
2274 values, added together. We already know that this value cannot be
2275 computed by just one ARM instruction. */
2278 validate_immediate_twopart (val
, highpart
)
2280 unsigned int * highpart
;
2285 for (i
= 0; i
< 32; i
+= 2)
2286 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2292 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2294 else if (a
& 0xff0000)
2298 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2302 assert (a
& 0xff000000);
2303 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2306 return (a
& 0xff) | (i
<< 7);
2313 validate_offset_imm (val
, hwse
)
2317 if ((hwse
&& val
> 255) || val
> 4095)
2324 int a ATTRIBUTE_UNUSED
;
2326 as_bad (_("invalid syntax for .req directive"));
2331 int ignore ATTRIBUTE_UNUSED
;
2333 /* We don't support putting frags in the BSS segment, we fake it by
2334 marking in_bss, then looking at s_skip for clues. */
2335 subseg_set (bss_section
, 0);
2336 demand_empty_rest_of_line ();
2341 int ignore ATTRIBUTE_UNUSED
;
2343 /* Never make frag if expect extra pass. */
2345 frag_align (1, 0, 0);
2347 record_alignment (now_seg
, 1);
2349 demand_empty_rest_of_line ();
2354 int ignored ATTRIBUTE_UNUSED
;
2359 if (current_poolP
== NULL
)
2362 /* Align pool as you have word accesses.
2363 Only make a frag if we have to. */
2365 frag_align (2, 0, 0);
2367 record_alignment (now_seg
, 2);
2369 sprintf (sym_name
, "$$lit_\002%x", lit_pool_num
++);
2371 symbol_locate (current_poolP
, sym_name
, now_seg
,
2372 (valueT
) frag_now_fix (), frag_now
);
2373 symbol_table_insert (current_poolP
);
2375 ARM_SET_THUMB (current_poolP
, thumb_mode
);
2377 #if defined OBJ_COFF || defined OBJ_ELF
2378 ARM_SET_INTERWORK (current_poolP
, support_interwork
);
2381 while (lit_count
< next_literal_pool_place
)
2382 /* First output the expression in the instruction to the pool. */
2383 emit_expr (&(literals
[lit_count
++].exp
), 4); /* .word */
2385 next_literal_pool_place
= 0;
2386 current_poolP
= NULL
;
2389 /* Same as s_align_ptwo but align 0 => align 2. */
2393 int unused ATTRIBUTE_UNUSED
;
2396 register long temp_fill
;
2397 long max_alignment
= 15;
2399 temp
= get_absolute_expression ();
2400 if (temp
> max_alignment
)
2401 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2404 as_bad (_("alignment negative. 0 assumed."));
2408 if (*input_line_pointer
== ',')
2410 input_line_pointer
++;
2411 temp_fill
= get_absolute_expression ();
2419 /* Only make a frag if we HAVE to. */
2420 if (temp
&& !need_pass_2
)
2421 frag_align (temp
, (int) temp_fill
, 0);
2422 demand_empty_rest_of_line ();
2424 record_alignment (now_seg
, temp
);
2428 s_force_thumb (ignore
)
2429 int ignore ATTRIBUTE_UNUSED
;
2431 /* If we are not already in thumb mode go into it, EVEN if
2432 the target processor does not support thumb instructions.
2433 This is used by gcc/config/arm/lib1funcs.asm for example
2434 to compile interworking support functions even if the
2435 target processor should not support interworking. */
2440 record_alignment (now_seg
, 1);
2443 demand_empty_rest_of_line ();
2447 s_thumb_func (ignore
)
2448 int ignore ATTRIBUTE_UNUSED
;
2453 /* The following label is the name/address of the start of a Thumb function.
2454 We need to know this for the interworking support. */
2455 label_is_thumb_function_name
= true;
2457 demand_empty_rest_of_line ();
2460 /* Perform a .set directive, but also mark the alias as
2461 being a thumb function. */
2467 /* XXX the following is a duplicate of the code for s_set() in read.c
2468 We cannot just call that code as we need to get at the symbol that
2470 register char * name
;
2471 register char delim
;
2472 register char * end_name
;
2473 register symbolS
* symbolP
;
2475 /* Especial apologies for the random logic:
2476 This just grew, and could be parsed much more simply!
2478 name
= input_line_pointer
;
2479 delim
= get_symbol_end ();
2480 end_name
= input_line_pointer
;
2485 if (*input_line_pointer
!= ',')
2488 as_bad (_("expected comma after name \"%s\""), name
);
2490 ignore_rest_of_line ();
2494 input_line_pointer
++;
2497 if (name
[0] == '.' && name
[1] == '\0')
2499 /* XXX - this should not happen to .thumb_set. */
2503 if ((symbolP
= symbol_find (name
)) == NULL
2504 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2507 /* When doing symbol listings, play games with dummy fragments living
2508 outside the normal fragment chain to record the file and line info
2510 if (listing
& LISTING_SYMBOLS
)
2512 extern struct list_info_struct
* listing_tail
;
2513 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2515 memset (dummy_frag
, 0, sizeof (fragS
));
2516 dummy_frag
->fr_type
= rs_fill
;
2517 dummy_frag
->line
= listing_tail
;
2518 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2519 dummy_frag
->fr_symbol
= symbolP
;
2523 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2526 /* "set" symbols are local unless otherwise specified. */
2527 SF_SET_LOCAL (symbolP
);
2528 #endif /* OBJ_COFF */
2529 } /* Make a new symbol. */
2531 symbol_table_insert (symbolP
);
2536 && S_IS_DEFINED (symbolP
)
2537 && S_GET_SEGMENT (symbolP
) != reg_section
)
2538 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2540 pseudo_set (symbolP
);
2542 demand_empty_rest_of_line ();
2544 /* XXX Now we come to the Thumb specific bit of code. */
2546 THUMB_SET_FUNC (symbolP
, 1);
2547 ARM_SET_THUMB (symbolP
, 1);
2548 #if defined OBJ_ELF || defined OBJ_COFF
2549 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2553 /* If we change section we must dump the literal pool first. */
2559 if (now_seg
!= text_section
)
2563 obj_elf_text (ignore
);
2573 if (flag_readonly_data_in_text
)
2575 if (now_seg
!= text_section
)
2578 else if (now_seg
!= data_section
)
2582 obj_elf_data (ignore
);
2589 arm_s_section (ignore
)
2595 obj_elf_section (ignore
);
2598 obj_coff_section (ignore
);
2603 opcode_select (width
)
2611 if (! (cpu_variant
& ARM_EXT_V4T
))
2612 as_bad (_("selected processor does not support THUMB opcodes"));
2615 /* No need to force the alignment, since we will have been
2616 coming from ARM mode, which is word-aligned. */
2617 record_alignment (now_seg
, 1);
2624 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2625 as_bad (_("selected processor does not support ARM opcodes"));
2630 frag_align (2, 0, 0);
2632 record_alignment (now_seg
, 1);
2637 as_bad (_("invalid instruction size selected (%d)"), width
);
2643 int ignore ATTRIBUTE_UNUSED
;
2646 demand_empty_rest_of_line ();
2651 int ignore ATTRIBUTE_UNUSED
;
2654 demand_empty_rest_of_line ();
2659 int unused ATTRIBUTE_UNUSED
;
2663 temp
= get_absolute_expression ();
2668 opcode_select (temp
);
2672 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2680 skip_whitespace (str
);
2682 if (*str
!= '\0' && !inst
.error
)
2683 inst
.error
= _("garbage following instruction");
2687 skip_past_comma (str
)
2690 char * p
= * str
, c
;
2693 while ((c
= *p
) == ' ' || c
== ',')
2696 if (c
== ',' && comma
++)
2704 return comma
? SUCCESS
: FAIL
;
2707 /* A standard register must be given at this point.
2708 SHIFT is the place to put it in inst.instruction.
2709 Restores input start point on error.
2710 Returns the reg#, or FAIL. */
2713 reg_required_here (str
, shift
)
2717 static char buff
[128]; /* XXX */
2719 char * start
= * str
;
2721 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
2724 inst
.instruction
|= reg
<< shift
;
2728 /* Restore the start point, we may have got a reg of the wrong class. */
2731 /* In the few cases where we might be able to accept something else
2732 this error can be overridden. */
2733 sprintf (buff
, _("register expected, not '%.100s'"), start
);
2739 static const struct asm_psr
*
2741 register char ** ccp
;
2743 char * start
= * ccp
;
2746 const struct asm_psr
* psr
;
2750 /* Skip to the end of the next word in the input stream. */
2755 while (ISALPHA (c
) || c
== '_');
2757 /* Terminate the word. */
2760 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2761 feature for ease of use and backwards compatibility. */
2762 if (!strncmp (start
, "cpsr", 4))
2763 strncpy (start
, "CPSR", 4);
2764 else if (!strncmp (start
, "spsr", 4))
2765 strncpy (start
, "SPSR", 4);
2767 /* Now locate the word in the psr hash table. */
2768 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2770 /* Restore the input stream. */
2773 /* If we found a valid match, advance the
2774 stream pointer past the end of the word. */
2780 /* Parse the input looking for a PSR flag. */
2783 psr_required_here (str
)
2786 char * start
= * str
;
2787 const struct asm_psr
* psr
;
2789 psr
= arm_psr_parse (str
);
2793 /* If this is the SPSR that is being modified, set the R bit. */
2795 inst
.instruction
|= SPSR_BIT
;
2797 /* Set the psr flags in the MSR instruction. */
2798 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2803 /* In the few cases where we might be able to accept
2804 something else this error can be overridden. */
2805 inst
.error
= _("flag for {c}psr instruction expected");
2807 /* Restore the start point. */
2813 co_proc_number (str
)
2816 int processor
, pchar
;
2819 skip_whitespace (*str
);
2822 /* The data sheet seems to imply that just a number on its own is valid
2823 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2825 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2831 if (pchar
>= '0' && pchar
<= '9')
2833 processor
= pchar
- '0';
2834 if (**str
>= '0' && **str
<= '9')
2836 processor
= processor
* 10 + *(*str
)++ - '0';
2839 inst
.error
= _("illegal co-processor number");
2846 inst
.error
= _("bad or missing co-processor number");
2851 inst
.instruction
|= processor
<< 8;
2856 cp_opc_expr (str
, where
, length
)
2863 skip_whitespace (* str
);
2865 memset (&expr
, '\0', sizeof (expr
));
2867 if (my_get_expression (&expr
, str
))
2869 if (expr
.X_op
!= O_constant
)
2871 inst
.error
= _("bad or missing expression");
2875 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2877 inst
.error
= _("immediate co-processor expression too large");
2881 inst
.instruction
|= expr
.X_add_number
<< where
;
2886 cp_reg_required_here (str
, where
)
2891 char * start
= *str
;
2893 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2895 inst
.instruction
|= reg
<< where
;
2899 /* In the few cases where we might be able to accept something else
2900 this error can be overridden. */
2901 inst
.error
= _("co-processor register expected");
2903 /* Restore the start point. */
2909 fp_reg_required_here (str
, where
)
2914 char * start
= * str
;
2916 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2918 inst
.instruction
|= reg
<< where
;
2922 /* In the few cases where we might be able to accept something else
2923 this error can be overridden. */
2924 inst
.error
= _("floating point register expected");
2926 /* Restore the start point. */
2932 cp_address_offset (str
)
2937 skip_whitespace (* str
);
2939 if (! is_immediate_prefix (**str
))
2941 inst
.error
= _("immediate expression expected");
2947 if (my_get_expression (& inst
.reloc
.exp
, str
))
2950 if (inst
.reloc
.exp
.X_op
== O_constant
)
2952 offset
= inst
.reloc
.exp
.X_add_number
;
2956 inst
.error
= _("co-processor address must be word aligned");
2960 if (offset
> 1023 || offset
< -1023)
2962 inst
.error
= _("offset too large");
2967 inst
.instruction
|= INDEX_UP
;
2971 inst
.instruction
|= offset
>> 2;
2974 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2980 cp_address_required_here (str
, wb_ok
)
2993 skip_whitespace (p
);
2995 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2998 skip_whitespace (p
);
3004 if (wb_ok
&& skip_past_comma (& p
) == SUCCESS
)
3007 write_back
= WRITE_BACK
;
3011 inst
.error
= _("pc may not be used in post-increment");
3015 if (cp_address_offset (& p
) == FAIL
)
3019 pre_inc
= PRE_INDEX
| INDEX_UP
;
3023 /* '['Rn, #expr']'[!] */
3025 if (skip_past_comma (& p
) == FAIL
)
3027 inst
.error
= _("pre-indexed expression expected");
3031 pre_inc
= PRE_INDEX
;
3033 if (cp_address_offset (& p
) == FAIL
)
3036 skip_whitespace (p
);
3040 inst
.error
= _("missing ]");
3044 skip_whitespace (p
);
3046 if (wb_ok
&& *p
== '!')
3050 inst
.error
= _("pc may not be used with write-back");
3055 write_back
= WRITE_BACK
;
3061 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3064 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3065 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3066 inst
.reloc
.pc_rel
= 1;
3067 inst
.instruction
|= (REG_PC
<< 16);
3068 pre_inc
= PRE_INDEX
;
3071 inst
.instruction
|= write_back
| pre_inc
;
3080 /* Do nothing really. */
3091 /* Only one syntax. */
3092 skip_whitespace (str
);
3094 if (reg_required_here (&str
, 12) == FAIL
)
3096 inst
.error
= BAD_ARGS
;
3100 if (skip_past_comma (&str
) == FAIL
)
3102 inst
.error
= _("comma expected after register name");
3106 skip_whitespace (str
);
3108 if ( strcmp (str
, "CPSR") == 0
3109 || strcmp (str
, "SPSR") == 0
3110 /* Lower case versions for backwards compatability. */
3111 || strcmp (str
, "cpsr") == 0
3112 || strcmp (str
, "spsr") == 0)
3115 /* This is for backwards compatability with older toolchains. */
3116 else if ( strcmp (str
, "cpsr_all") == 0
3117 || strcmp (str
, "spsr_all") == 0)
3121 inst
.error
= _("CPSR or SPSR expected");
3125 if (* str
== 's' || * str
== 'S')
3126 inst
.instruction
|= SPSR_BIT
;
3132 /* Two possible forms:
3133 "{C|S}PSR_<field>, Rm",
3134 "{C|S}PSR_f, #expression". */
3140 skip_whitespace (str
);
3142 if (psr_required_here (& str
) == FAIL
)
3145 if (skip_past_comma (& str
) == FAIL
)
3147 inst
.error
= _("comma missing after psr flags");
3151 skip_whitespace (str
);
3153 if (reg_required_here (& str
, 0) != FAIL
)
3160 if (! is_immediate_prefix (* str
))
3163 _("only a register or immediate value can follow a psr flag");
3170 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3173 _("only a register or immediate value can follow a psr flag");
3177 #if 0 /* The first edition of the ARM architecture manual stated that
3178 writing anything other than the flags with an immediate operation
3179 had UNPREDICTABLE effects. This constraint was removed in the
3180 second edition of the specification. */
3181 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3182 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3184 inst
.error
= _("immediate value cannot be used to set this field");
3189 inst
.instruction
|= INST_IMMEDIATE
;
3191 if (inst
.reloc
.exp
.X_add_symbol
)
3193 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3194 inst
.reloc
.pc_rel
= 0;
3198 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3200 if (value
== (unsigned) FAIL
)
3202 inst
.error
= _("invalid constant");
3206 inst
.instruction
|= value
;
3213 /* Long Multiply Parser
3214 UMULL RdLo, RdHi, Rm, Rs
3215 SMULL RdLo, RdHi, Rm, Rs
3216 UMLAL RdLo, RdHi, Rm, Rs
3217 SMLAL RdLo, RdHi, Rm, Rs. */
3223 int rdlo
, rdhi
, rm
, rs
;
3225 /* Only one format "rdlo, rdhi, rm, rs". */
3226 skip_whitespace (str
);
3228 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3230 inst
.error
= BAD_ARGS
;
3234 if (skip_past_comma (&str
) == FAIL
3235 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3237 inst
.error
= BAD_ARGS
;
3241 if (skip_past_comma (&str
) == FAIL
3242 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3244 inst
.error
= BAD_ARGS
;
3248 /* rdhi, rdlo and rm must all be different. */
3249 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3250 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3252 if (skip_past_comma (&str
) == FAIL
3253 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3255 inst
.error
= BAD_ARGS
;
3259 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3261 inst
.error
= BAD_PC
;
3275 /* Only one format "rd, rm, rs". */
3276 skip_whitespace (str
);
3278 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3280 inst
.error
= BAD_ARGS
;
3286 inst
.error
= BAD_PC
;
3290 if (skip_past_comma (&str
) == FAIL
3291 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3293 inst
.error
= BAD_ARGS
;
3299 inst
.error
= BAD_PC
;
3304 as_tsktsk (_("rd and rm should be different in mul"));
3306 if (skip_past_comma (&str
) == FAIL
3307 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3309 inst
.error
= BAD_ARGS
;
3315 inst
.error
= BAD_PC
;
3329 /* Only one format "rd, rm, rs, rn". */
3330 skip_whitespace (str
);
3332 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3334 inst
.error
= BAD_ARGS
;
3340 inst
.error
= BAD_PC
;
3344 if (skip_past_comma (&str
) == FAIL
3345 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3347 inst
.error
= BAD_ARGS
;
3353 inst
.error
= BAD_PC
;
3358 as_tsktsk (_("rd and rm should be different in mla"));
3360 if (skip_past_comma (&str
) == FAIL
3361 || (rd
= reg_required_here (&str
, 8)) == FAIL
3362 || skip_past_comma (&str
) == FAIL
3363 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3365 inst
.error
= BAD_ARGS
;
3369 if (rd
== REG_PC
|| rm
== REG_PC
)
3371 inst
.error
= BAD_PC
;
3379 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3380 Advances *str to the next non-alphanumeric.
3381 Returns 0, or else FAIL (in which case sets inst.error).
3383 (In a future XScale, there may be accumulators other than zero.
3384 At that time this routine and its callers can be upgraded to suit.) */
3387 accum0_required_here (str
)
3390 static char buff
[128]; /* Note the address is taken. Hence, static. */
3393 int result
= 0; /* The accum number. */
3395 skip_whitespace (p
);
3397 *str
= p
; /* Advance caller's string pointer too. */
3402 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3404 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3406 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3411 *p
= c
; /* Unzap. */
3412 *str
= p
; /* Caller's string pointer to after match. */
3416 /* Expects **str -> after a comma. May be leading blanks.
3417 Advances *str, recognizing a load mode, and setting inst.instruction.
3418 Returns rn, or else FAIL (in which case may set inst.error
3419 and not advance str)
3421 Note: doesn't know Rd, so no err checks that require such knowledge. */
3424 ld_mode_required_here (string
)
3427 char * str
= * string
;
3431 skip_whitespace (str
);
3437 skip_whitespace (str
);
3439 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3442 skip_whitespace (str
);
3448 if (skip_past_comma (& str
) == SUCCESS
)
3450 /* [Rn],... (post inc) */
3451 if (ldst_extend_v4 (&str
) == FAIL
)
3456 skip_whitespace (str
);
3461 inst
.instruction
|= WRITE_BACK
;
3464 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3470 if (skip_past_comma (& str
) == FAIL
)
3472 inst
.error
= _("pre-indexed expression expected");
3478 if (ldst_extend_v4 (&str
) == FAIL
)
3481 skip_whitespace (str
);
3483 if (* str
++ != ']')
3485 inst
.error
= _("missing ]");
3489 skip_whitespace (str
);
3494 inst
.instruction
|= WRITE_BACK
;
3498 else if (* str
== '=') /* ldr's "r,=label" syntax */
3499 /* We should never reach here, because <text> = <expression> is
3500 caught gas/read.c read_a_source_file() as a .set operation. */
3502 else /* PC +- 8 bit immediate offset. */
3504 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3507 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3508 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3509 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3510 inst
.reloc
.pc_rel
= 1;
3511 inst
.instruction
|= (REG_PC
<< 16);
3517 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3523 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3524 SMLAxy{cond} Rd,Rm,Rs,Rn
3525 SMLAWy{cond} Rd,Rm,Rs,Rn
3526 Error if any register is R15. */
3534 skip_whitespace (str
);
3536 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3537 || skip_past_comma (& str
) == FAIL
3538 || (rm
= reg_required_here (& str
, 0)) == FAIL
3539 || skip_past_comma (& str
) == FAIL
3540 || (rs
= reg_required_here (& str
, 8)) == FAIL
3541 || skip_past_comma (& str
) == FAIL
3542 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3543 inst
.error
= BAD_ARGS
;
3545 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3546 inst
.error
= BAD_PC
;
3552 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3553 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3554 Error if any register is R15.
3555 Warning if Rdlo == Rdhi. */
3561 int rdlo
, rdhi
, rm
, rs
;
3563 skip_whitespace (str
);
3565 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3566 || skip_past_comma (& str
) == FAIL
3567 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3568 || skip_past_comma (& str
) == FAIL
3569 || (rm
= reg_required_here (& str
, 0)) == FAIL
3570 || skip_past_comma (& str
) == FAIL
3571 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3573 inst
.error
= BAD_ARGS
;
3577 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3579 inst
.error
= BAD_PC
;
3584 as_tsktsk (_("rdhi and rdlo must be different"));
3589 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3590 SMULxy{cond} Rd,Rm,Rs
3591 Error if any register is R15. */
3599 skip_whitespace (str
);
3601 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3602 || skip_past_comma (& str
) == FAIL
3603 || (rm
= reg_required_here (& str
, 0)) == FAIL
3604 || skip_past_comma (& str
) == FAIL
3605 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3606 inst
.error
= BAD_ARGS
;
3608 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3609 inst
.error
= BAD_PC
;
3615 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3616 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3617 Error if any register is R15. */
3625 skip_whitespace (str
);
3627 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3628 || skip_past_comma (& str
) == FAIL
3629 || (rm
= reg_required_here (& str
, 0)) == FAIL
3630 || skip_past_comma (& str
) == FAIL
3631 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3632 inst
.error
= BAD_ARGS
;
3634 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3635 inst
.error
= BAD_PC
;
3641 /* ARM V5E (el Segundo)
3642 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3643 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3645 These are equivalent to the XScale instructions MAR and MRA,
3646 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3648 Result unpredicatable if Rd or Rn is R15. */
3656 skip_whitespace (str
);
3658 if (co_proc_number (& str
) == FAIL
)
3661 inst
.error
= BAD_ARGS
;
3665 if (skip_past_comma (& str
) == FAIL
3666 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3669 inst
.error
= BAD_ARGS
;
3673 if (skip_past_comma (& str
) == FAIL
3674 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3677 inst
.error
= BAD_ARGS
;
3681 if (skip_past_comma (& str
) == FAIL
3682 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3685 inst
.error
= BAD_ARGS
;
3689 /* Unpredictable result if rd or rn is R15. */
3690 if (rd
== REG_PC
|| rn
== REG_PC
)
3692 (_("Warning: instruction unpredictable when using r15"));
3694 if (skip_past_comma (& str
) == FAIL
3695 || cp_reg_required_here (& str
, 0) == FAIL
)
3698 inst
.error
= BAD_ARGS
;
3705 /* ARM V5 count-leading-zeroes instruction (argument parse)
3706 CLZ{<cond>} <Rd>, <Rm>
3707 Condition defaults to COND_ALWAYS.
3708 Error if Rd or Rm are R15. */
3716 skip_whitespace (str
);
3718 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3719 || (skip_past_comma (& str
) == FAIL
)
3720 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3721 inst
.error
= BAD_ARGS
;
3723 else if (rd
== REG_PC
|| rm
== REG_PC
)
3724 inst
.error
= BAD_PC
;
3730 /* ARM V5 (argument parse)
3731 LDC2{L} <coproc>, <CRd>, <addressing mode>
3732 STC2{L} <coproc>, <CRd>, <addressing mode>
3733 Instruction is not conditional, and has 0xf in the codition field.
3734 Otherwise, it's the same as LDC/STC. */
3740 skip_whitespace (str
);
3742 if (co_proc_number (& str
) == FAIL
)
3745 inst
.error
= BAD_ARGS
;
3747 else if (skip_past_comma (& str
) == FAIL
3748 || cp_reg_required_here (& str
, 12) == FAIL
)
3751 inst
.error
= BAD_ARGS
;
3753 else if (skip_past_comma (& str
) == FAIL
3754 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3757 inst
.error
= BAD_ARGS
;
3763 /* ARM V5 (argument parse)
3764 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3765 Instruction is not conditional, and has 0xf in the condition field.
3766 Otherwise, it's the same as CDP. */
3772 skip_whitespace (str
);
3774 if (co_proc_number (& str
) == FAIL
)
3777 inst
.error
= BAD_ARGS
;
3781 if (skip_past_comma (& str
) == FAIL
3782 || cp_opc_expr (& str
, 20,4) == FAIL
)
3785 inst
.error
= BAD_ARGS
;
3789 if (skip_past_comma (& str
) == FAIL
3790 || cp_reg_required_here (& str
, 12) == FAIL
)
3793 inst
.error
= BAD_ARGS
;
3797 if (skip_past_comma (& str
) == FAIL
3798 || cp_reg_required_here (& str
, 16) == FAIL
)
3801 inst
.error
= BAD_ARGS
;
3805 if (skip_past_comma (& str
) == FAIL
3806 || cp_reg_required_here (& str
, 0) == FAIL
)
3809 inst
.error
= BAD_ARGS
;
3813 if (skip_past_comma (& str
) == SUCCESS
)
3815 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3818 inst
.error
= BAD_ARGS
;
3826 /* ARM V5 (argument parse)
3827 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3828 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3829 Instruction is not conditional, and has 0xf in the condition field.
3830 Otherwise, it's the same as MCR/MRC. */
3836 skip_whitespace (str
);
3838 if (co_proc_number (& str
) == FAIL
)
3841 inst
.error
= BAD_ARGS
;
3845 if (skip_past_comma (& str
) == FAIL
3846 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3849 inst
.error
= BAD_ARGS
;
3853 if (skip_past_comma (& str
) == FAIL
3854 || reg_required_here (& str
, 12) == FAIL
)
3857 inst
.error
= BAD_ARGS
;
3861 if (skip_past_comma (& str
) == FAIL
3862 || cp_reg_required_here (& str
, 16) == FAIL
)
3865 inst
.error
= BAD_ARGS
;
3869 if (skip_past_comma (& str
) == FAIL
3870 || cp_reg_required_here (& str
, 0) == FAIL
)
3873 inst
.error
= BAD_ARGS
;
3877 if (skip_past_comma (& str
) == SUCCESS
)
3879 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3882 inst
.error
= BAD_ARGS
;
3890 /* ARM v5TEJ. Jump to Jazelle code. */
3897 skip_whitespace (str
);
3899 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3901 inst
.error
= BAD_ARGS
;
3905 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3907 as_tsktsk (_("use of r15 in bxj is not really useful"));
3912 /* THUMB V5 breakpoint instruction (argument parse)
3920 unsigned long number
;
3922 skip_whitespace (str
);
3924 /* Allow optional leading '#'. */
3925 if (is_immediate_prefix (*str
))
3928 memset (& expr
, '\0', sizeof (expr
));
3929 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
3931 inst
.error
= _("bad or missing expression");
3935 number
= expr
.X_add_number
;
3937 /* Check it fits an 8 bit unsigned. */
3938 if (number
!= (number
& 0xff))
3940 inst
.error
= _("immediate value out of range");
3944 inst
.instruction
|= number
;
3949 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3950 Expects inst.instruction is set for BLX(1).
3951 Note: this is cloned from do_branch, and the reloc changed to be a
3952 new one that can cope with setting one extra bit (the H bit). */
3958 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3965 /* ScottB: February 5, 1998 */
3966 /* Check to see of PLT32 reloc required for the instruction. */
3968 /* arm_parse_reloc() works on input_line_pointer.
3969 We actually want to parse the operands to the branch instruction
3970 passed in 'str'. Save the input pointer and restore it later. */
3971 save_in
= input_line_pointer
;
3972 input_line_pointer
= str
;
3974 if (inst
.reloc
.exp
.X_op
== O_symbol
3976 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
3978 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
3979 inst
.reloc
.pc_rel
= 0;
3980 /* Modify str to point to after parsed operands, otherwise
3981 end_of_line() will complain about the (PLT) left in str. */
3982 str
= input_line_pointer
;
3986 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3987 inst
.reloc
.pc_rel
= 1;
3990 input_line_pointer
= save_in
;
3993 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3994 inst
.reloc
.pc_rel
= 1;
3995 #endif /* OBJ_ELF */
4000 /* ARM V5 branch-link-exchange instruction (argument parse)
4001 BLX <target_addr> ie BLX(1)
4002 BLX{<condition>} <Rm> ie BLX(2)
4003 Unfortunately, there are two different opcodes for this mnemonic.
4004 So, the insns[].value is not used, and the code here zaps values
4005 into inst.instruction.
4006 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4015 skip_whitespace (mystr
);
4016 rm
= reg_required_here (& mystr
, 0);
4018 /* The above may set inst.error. Ignore his opinion. */
4023 /* Arg is a register.
4024 Use the condition code our caller put in inst.instruction.
4025 Pass ourselves off as a BX with a funny opcode. */
4026 inst
.instruction
|= 0x012fff30;
4031 /* This must be is BLX <target address>, no condition allowed. */
4032 if (inst
.instruction
!= COND_ALWAYS
)
4034 inst
.error
= BAD_COND
;
4038 inst
.instruction
= 0xfafffffe;
4040 /* Process like a B/BL, but with a different reloc.
4041 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4046 /* ARM V5 Thumb BLX (argument parse)
4047 BLX <target_addr> which is BLX(1)
4048 BLX <Rm> which is BLX(2)
4049 Unfortunately, there are two different opcodes for this mnemonic.
4050 So, the tinsns[].value is not used, and the code here zaps values
4051 into inst.instruction. */
4060 skip_whitespace (mystr
);
4061 inst
.instruction
= 0x4780;
4063 /* Note that this call is to the ARM register recognizer. BLX(2)
4064 uses the ARM register space, not the Thumb one, so a call to
4065 thumb_reg() would be wrong. */
4066 rm
= reg_required_here (& mystr
, 3);
4071 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4076 /* No ARM register. This must be BLX(1). Change the .instruction. */
4077 inst
.instruction
= 0xf7ffeffe;
4080 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4083 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4084 inst
.reloc
.pc_rel
= 1;
4087 end_of_line (mystr
);
4090 /* ARM V5 breakpoint instruction (argument parse)
4091 BKPT <16 bit unsigned immediate>
4092 Instruction is not conditional.
4093 The bit pattern given in insns[] has the COND_ALWAYS condition,
4094 and it is an error if the caller tried to override that. */
4101 unsigned long number
;
4103 skip_whitespace (str
);
4105 /* Allow optional leading '#'. */
4106 if (is_immediate_prefix (* str
))
4109 memset (& expr
, '\0', sizeof (expr
));
4111 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4113 inst
.error
= _("bad or missing expression");
4117 number
= expr
.X_add_number
;
4119 /* Check it fits a 16 bit unsigned. */
4120 if (number
!= (number
& 0xffff))
4122 inst
.error
= _("immediate value out of range");
4126 /* Top 12 of 16 bits to bits 19:8. */
4127 inst
.instruction
|= (number
& 0xfff0) << 4;
4129 /* Bottom 4 of 16 bits to bits 3:0. */
4130 inst
.instruction
|= number
& 0xf;
4135 /* Xscale multiply-accumulate (argument parse)
4138 MIAxycc acc0,Rm,Rs. */
4147 if (accum0_required_here (& str
) == FAIL
)
4148 inst
.error
= ERR_NO_ACCUM
;
4150 else if (skip_past_comma (& str
) == FAIL
4151 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
4152 inst
.error
= BAD_ARGS
;
4154 else if (skip_past_comma (& str
) == FAIL
4155 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
4156 inst
.error
= BAD_ARGS
;
4158 /* inst.instruction has now been zapped with both rm and rs. */
4159 else if (rm
== REG_PC
|| rs
== REG_PC
)
4160 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
4166 /* Xscale move-accumulator-register (argument parse)
4168 MARcc acc0,RdLo,RdHi. */
4176 if (accum0_required_here (& str
) == FAIL
)
4177 inst
.error
= ERR_NO_ACCUM
;
4179 else if (skip_past_comma (& str
) == FAIL
4180 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
4181 inst
.error
= BAD_ARGS
;
4183 else if (skip_past_comma (& str
) == FAIL
4184 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
4185 inst
.error
= BAD_ARGS
;
4187 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4188 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
4189 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
4195 /* Xscale move-register-accumulator (argument parse)
4197 MRAcc RdLo,RdHi,acc0. */
4206 skip_whitespace (str
);
4208 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
4209 inst
.error
= BAD_ARGS
;
4211 else if (skip_past_comma (& str
) == FAIL
4212 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
4213 inst
.error
= BAD_ARGS
;
4215 else if (skip_past_comma (& str
) == FAIL
4216 || accum0_required_here (& str
) == FAIL
)
4217 inst
.error
= ERR_NO_ACCUM
;
4219 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4220 else if (rdlo
== rdhi
)
4221 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
4223 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
4224 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
4229 /* ARMv5TE: Preload-Cache
4233 Syntactically, like LDR with B=1, W=0, L=1. */
4241 skip_whitespace (str
);
4245 inst
.error
= _("'[' expected after PLD mnemonic");
4250 skip_whitespace (str
);
4252 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
4255 skip_whitespace (str
);
4261 skip_whitespace (str
);
4263 /* Post-indexed addressing is not allowed with PLD. */
4264 if (skip_past_comma (&str
) == SUCCESS
)
4267 = _("post-indexed expression used in preload instruction");
4270 else if (*str
== '!') /* [Rn]! */
4272 inst
.error
= _("writeback used in preload instruction");
4276 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
4278 else /* [Rn, ...] */
4280 if (skip_past_comma (& str
) == FAIL
)
4282 inst
.error
= _("pre-indexed expression expected");
4286 if (ldst_extend (&str
) == FAIL
)
4289 skip_whitespace (str
);
4293 inst
.error
= _("missing ]");
4298 skip_whitespace (str
);
4300 if (* str
== '!') /* [Rn]! */
4302 inst
.error
= _("writeback used in preload instruction");
4306 inst
.instruction
|= PRE_INDEX
;
4312 /* ARMv5TE load-consecutive (argument parse)
4325 skip_whitespace (str
);
4327 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
4329 inst
.error
= BAD_ARGS
;
4333 if (skip_past_comma (& str
) == FAIL
4334 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
4337 inst
.error
= BAD_ARGS
;
4341 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4342 if (rd
& 1) /* Unpredictable result if Rd is odd. */
4344 inst
.error
= _("destination register must be even");
4350 inst
.error
= _("r14 not allowed here");
4354 if (((rd
== rn
) || (rd
+ 1 == rn
))
4355 && ((inst
.instruction
& WRITE_BACK
)
4356 || (!(inst
.instruction
& PRE_INDEX
))))
4357 as_warn (_("pre/post-indexing used when modified address register is destination"));
4359 /* For an index-register load, the index register must not overlap the
4360 destination (even if not write-back). */
4361 if ((inst
.instruction
& V4_STR_BIT
) == 0
4362 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
4364 int rm
= inst
.instruction
& 0x0000000f;
4366 if (rm
== rd
|| (rm
== rd
+ 1))
4367 as_warn (_("ldrd destination registers must not overlap index register"));
4373 /* Returns the index into fp_values of a floating point number,
4374 or -1 if not in the table. */
4377 my_get_float_expression (str
)
4380 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
4386 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
4388 /* Look for a raw floating point number. */
4389 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
4390 && is_end_of_line
[(unsigned char) *save_in
])
4392 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4394 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4396 if (words
[j
] != fp_values
[i
][j
])
4400 if (j
== MAX_LITTLENUMS
)
4408 /* Try and parse a more complex expression, this will probably fail
4409 unless the code uses a floating point prefix (eg "0f"). */
4410 save_in
= input_line_pointer
;
4411 input_line_pointer
= *str
;
4412 if (expression (&exp
) == absolute_section
4413 && exp
.X_op
== O_big
4414 && exp
.X_add_number
< 0)
4416 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4418 if (gen_to_words (words
, 5, (long) 15) == 0)
4420 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4422 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4424 if (words
[j
] != fp_values
[i
][j
])
4428 if (j
== MAX_LITTLENUMS
)
4430 *str
= input_line_pointer
;
4431 input_line_pointer
= save_in
;
4438 *str
= input_line_pointer
;
4439 input_line_pointer
= save_in
;
4443 /* Return true if anything in the expression is a bignum. */
4446 walk_no_bignums (sp
)
4449 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
4452 if (symbol_get_value_expression (sp
)->X_add_symbol
)
4454 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
4455 || (symbol_get_value_expression (sp
)->X_op_symbol
4456 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
4462 static int in_my_get_expression
= 0;
4465 my_get_expression (ep
, str
)
4472 save_in
= input_line_pointer
;
4473 input_line_pointer
= *str
;
4474 in_my_get_expression
= 1;
4475 seg
= expression (ep
);
4476 in_my_get_expression
= 0;
4478 if (ep
->X_op
== O_illegal
)
4480 /* We found a bad expression in md_operand(). */
4481 *str
= input_line_pointer
;
4482 input_line_pointer
= save_in
;
4487 if (seg
!= absolute_section
4488 && seg
!= text_section
4489 && seg
!= data_section
4490 && seg
!= bss_section
4491 && seg
!= undefined_section
)
4493 inst
.error
= _("bad_segment");
4494 *str
= input_line_pointer
;
4495 input_line_pointer
= save_in
;
4500 /* Get rid of any bignums now, so that we don't generate an error for which
4501 we can't establish a line number later on. Big numbers are never valid
4502 in instructions, which is where this routine is always called. */
4503 if (ep
->X_op
== O_big
4504 || (ep
->X_add_symbol
4505 && (walk_no_bignums (ep
->X_add_symbol
)
4507 && walk_no_bignums (ep
->X_op_symbol
)))))
4509 inst
.error
= _("invalid constant");
4510 *str
= input_line_pointer
;
4511 input_line_pointer
= save_in
;
4515 *str
= input_line_pointer
;
4516 input_line_pointer
= save_in
;
4520 /* We handle all bad expressions here, so that we can report the faulty
4521 instruction in the error message. */
4526 if (in_my_get_expression
)
4528 expr
->X_op
= O_illegal
;
4529 if (inst
.error
== NULL
)
4530 inst
.error
= _("bad expression");
4534 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4538 decode_shift (str
, unrestrict
)
4542 const struct asm_shift_name
* shift
;
4546 skip_whitespace (* str
);
4548 for (p
= * str
; ISALPHA (* p
); p
++)
4553 inst
.error
= _("shift expression expected");
4559 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
4564 inst
.error
= _("shift expression expected");
4568 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
4570 if (shift
->properties
->index
== SHIFT_RRX
)
4573 inst
.instruction
|= shift
->properties
->bit_field
;
4577 skip_whitespace (p
);
4579 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
4581 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
4585 else if (! is_immediate_prefix (* p
))
4587 inst
.error
= (unrestrict
4588 ? _("shift requires register or #expression")
4589 : _("shift requires #expression"));
4597 if (my_get_expression (& inst
.reloc
.exp
, & p
))
4600 /* Validate some simple #expressions. */
4601 if (inst
.reloc
.exp
.X_op
== O_constant
)
4603 unsigned num
= inst
.reloc
.exp
.X_add_number
;
4605 /* Reject operations greater than 32. */
4607 /* Reject a shift of 0 unless the mode allows it. */
4608 || (num
== 0 && shift
->properties
->allows_0
== 0)
4609 /* Reject a shift of 32 unless the mode allows it. */
4610 || (num
== 32 && shift
->properties
->allows_32
== 0)
4613 /* As a special case we allow a shift of zero for
4614 modes that do not support it to be recoded as an
4615 logical shift left of zero (ie nothing). We warn
4616 about this though. */
4619 as_warn (_("shift of 0 ignored."));
4620 shift
= & shift_names
[0];
4621 assert (shift
->properties
->index
== SHIFT_LSL
);
4625 inst
.error
= _("invalid immediate shift");
4630 /* Shifts of 32 are encoded as 0, for those shifts that
4635 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
4639 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
4640 inst
.reloc
.pc_rel
= 0;
4641 inst
.instruction
|= shift
->properties
->bit_field
;
4648 /* Do those data_ops which can take a negative immediate constant
4649 by altering the instuction. A bit of a hack really.
4653 by inverting the second operand, and
4656 by negating the second operand. */
4659 negate_data_op (instruction
, value
)
4660 unsigned long * instruction
;
4661 unsigned long value
;
4664 unsigned long negated
, inverted
;
4666 negated
= validate_immediate (-value
);
4667 inverted
= validate_immediate (~value
);
4669 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
4672 /* First negates. */
4673 case OPCODE_SUB
: /* ADD <-> SUB */
4674 new_inst
= OPCODE_ADD
;
4679 new_inst
= OPCODE_SUB
;
4683 case OPCODE_CMP
: /* CMP <-> CMN */
4684 new_inst
= OPCODE_CMN
;
4689 new_inst
= OPCODE_CMP
;
4693 /* Now Inverted ops. */
4694 case OPCODE_MOV
: /* MOV <-> MVN */
4695 new_inst
= OPCODE_MVN
;
4700 new_inst
= OPCODE_MOV
;
4704 case OPCODE_AND
: /* AND <-> BIC */
4705 new_inst
= OPCODE_BIC
;
4710 new_inst
= OPCODE_AND
;
4714 case OPCODE_ADC
: /* ADC <-> SBC */
4715 new_inst
= OPCODE_SBC
;
4720 new_inst
= OPCODE_ADC
;
4724 /* We cannot do anything. */
4729 if (value
== (unsigned) FAIL
)
4732 *instruction
&= OPCODE_MASK
;
4733 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
4744 skip_whitespace (* str
);
4746 if (reg_required_here (str
, 0) != FAIL
)
4748 if (skip_past_comma (str
) == SUCCESS
)
4749 /* Shift operation on register. */
4750 return decode_shift (str
, NO_SHIFT_RESTRICT
);
4756 /* Immediate expression. */
4757 if (is_immediate_prefix (**str
))
4762 if (my_get_expression (&inst
.reloc
.exp
, str
))
4765 if (inst
.reloc
.exp
.X_add_symbol
)
4767 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4768 inst
.reloc
.pc_rel
= 0;
4772 if (skip_past_comma (str
) == SUCCESS
)
4774 /* #x, y -- ie explicit rotation by Y. */
4775 if (my_get_expression (&expr
, str
))
4778 if (expr
.X_op
!= O_constant
)
4780 inst
.error
= _("constant expression expected");
4784 /* Rotate must be a multiple of 2. */
4785 if (((unsigned) expr
.X_add_number
) > 30
4786 || (expr
.X_add_number
& 1) != 0
4787 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
4789 inst
.error
= _("invalid constant");
4792 inst
.instruction
|= INST_IMMEDIATE
;
4793 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
4794 inst
.instruction
|= expr
.X_add_number
<< 7;
4798 /* Implicit rotation, select a suitable one. */
4799 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4803 /* Can't be done. Perhaps the code reads something like
4804 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4805 if ((value
= negate_data_op (&inst
.instruction
,
4806 inst
.reloc
.exp
.X_add_number
))
4809 inst
.error
= _("invalid constant");
4814 inst
.instruction
|= value
;
4817 inst
.instruction
|= INST_IMMEDIATE
;
4822 inst
.error
= _("register or shift expression expected");
4831 skip_whitespace (* str
);
4833 if (fp_reg_required_here (str
, 0) != FAIL
)
4837 /* Immediate expression. */
4838 if (*((*str
)++) == '#')
4844 skip_whitespace (* str
);
4846 /* First try and match exact strings, this is to guarantee
4847 that some formats will work even for cross assembly. */
4849 for (i
= 0; fp_const
[i
]; i
++)
4851 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
4855 *str
+= strlen (fp_const
[i
]);
4856 if (is_end_of_line
[(unsigned char) **str
])
4858 inst
.instruction
|= i
+ 8;
4865 /* Just because we didn't get a match doesn't mean that the
4866 constant isn't valid, just that it is in a format that we
4867 don't automatically recognize. Try parsing it with
4868 the standard expression routines. */
4869 if ((i
= my_get_float_expression (str
)) >= 0)
4871 inst
.instruction
|= i
+ 8;
4875 inst
.error
= _("invalid floating point immediate expression");
4879 _("floating point register or immediate expression expected");
4888 skip_whitespace (str
);
4890 if (reg_required_here (&str
, 12) == FAIL
4891 || skip_past_comma (&str
) == FAIL
4892 || reg_required_here (&str
, 16) == FAIL
4893 || skip_past_comma (&str
) == FAIL
4894 || data_op2 (&str
) == FAIL
)
4897 inst
.error
= BAD_ARGS
;
4909 /* This is a pseudo-op of the form "adr rd, label" to be converted
4910 into a relative address of the form "add rd, pc, #label-.-8". */
4911 skip_whitespace (str
);
4913 if (reg_required_here (&str
, 12) == FAIL
4914 || skip_past_comma (&str
) == FAIL
4915 || my_get_expression (&inst
.reloc
.exp
, &str
))
4918 inst
.error
= BAD_ARGS
;
4922 /* Frag hacking will turn this into a sub instruction if the offset turns
4923 out to be negative. */
4924 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4925 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
4926 inst
.reloc
.pc_rel
= 1;
4935 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4936 into a relative address of the form:
4937 add rd, pc, #low(label-.-8)"
4938 add rd, rd, #high(label-.-8)" */
4940 skip_whitespace (str
);
4942 if (reg_required_here (&str
, 12) == FAIL
4943 || skip_past_comma (&str
) == FAIL
4944 || my_get_expression (&inst
.reloc
.exp
, &str
))
4947 inst
.error
= BAD_ARGS
;
4953 /* Frag hacking will turn this into a sub instruction if the offset turns
4954 out to be negative. */
4955 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
4956 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
4957 inst
.reloc
.pc_rel
= 1;
4958 inst
.size
= INSN_SIZE
* 2;
4967 skip_whitespace (str
);
4969 if (reg_required_here (&str
, 16) == FAIL
)
4972 inst
.error
= BAD_ARGS
;
4976 if (skip_past_comma (&str
) == FAIL
4977 || data_op2 (&str
) == FAIL
)
4980 inst
.error
= BAD_ARGS
;
4992 skip_whitespace (str
);
4994 if (reg_required_here (&str
, 12) == FAIL
)
4997 inst
.error
= BAD_ARGS
;
5001 if (skip_past_comma (&str
) == FAIL
5002 || data_op2 (&str
) == FAIL
)
5005 inst
.error
= BAD_ARGS
;
5024 if (my_get_expression (& inst
.reloc
.exp
, str
))
5027 if (inst
.reloc
.exp
.X_op
== O_constant
)
5029 int value
= inst
.reloc
.exp
.X_add_number
;
5031 if (value
< -4095 || value
> 4095)
5033 inst
.error
= _("address offset too large");
5043 inst
.instruction
|= add
| value
;
5047 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5048 inst
.reloc
.pc_rel
= 0;
5061 if (reg_required_here (str
, 0) == FAIL
)
5064 inst
.instruction
|= add
| OFFSET_REG
;
5065 if (skip_past_comma (str
) == SUCCESS
)
5066 return decode_shift (str
, SHIFT_RESTRICT
);
5080 skip_whitespace (str
);
5082 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
5085 inst
.error
= BAD_ARGS
;
5089 if (skip_past_comma (&str
) == FAIL
)
5091 inst
.error
= _("address expected");
5101 skip_whitespace (str
);
5103 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5106 /* Conflicts can occur on stores as well as loads. */
5107 conflict_reg
= (conflict_reg
== reg
);
5109 skip_whitespace (str
);
5115 if (skip_past_comma (&str
) == SUCCESS
)
5117 /* [Rn],... (post inc) */
5118 if (ldst_extend (&str
) == FAIL
)
5121 as_warn (_("%s register same as write-back base"),
5122 ((inst
.instruction
& LOAD_BIT
)
5123 ? _("destination") : _("source")));
5128 skip_whitespace (str
);
5133 as_warn (_("%s register same as write-back base"),
5134 ((inst
.instruction
& LOAD_BIT
)
5135 ? _("destination") : _("source")));
5137 inst
.instruction
|= WRITE_BACK
;
5140 inst
.instruction
|= INDEX_UP
;
5147 if (skip_past_comma (&str
) == FAIL
)
5149 inst
.error
= _("pre-indexed expression expected");
5154 if (ldst_extend (&str
) == FAIL
)
5157 skip_whitespace (str
);
5161 inst
.error
= _("missing ]");
5165 skip_whitespace (str
);
5170 as_warn (_("%s register same as write-back base"),
5171 ((inst
.instruction
& LOAD_BIT
)
5172 ? _("destination") : _("source")));
5174 inst
.instruction
|= WRITE_BACK
;
5178 else if (*str
== '=')
5180 if ((inst
.instruction
& LOAD_BIT
) == 0)
5182 inst
.error
= _("invalid pseudo operation");
5186 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5189 skip_whitespace (str
);
5191 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5194 if (inst
.reloc
.exp
.X_op
!= O_constant
5195 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5197 inst
.error
= _("constant expression expected");
5201 if (inst
.reloc
.exp
.X_op
== O_constant
)
5203 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5207 /* This can be done with a mov instruction. */
5208 inst
.instruction
&= LITERAL_MASK
;
5209 inst
.instruction
|= (INST_IMMEDIATE
5210 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
5211 inst
.instruction
|= value
& 0xfff;
5216 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
5220 /* This can be done with a mvn instruction. */
5221 inst
.instruction
&= LITERAL_MASK
;
5222 inst
.instruction
|= (INST_IMMEDIATE
5223 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
5224 inst
.instruction
|= value
& 0xfff;
5230 /* Insert into literal pool. */
5231 if (add_to_lit_pool () == FAIL
)
5234 inst
.error
= _("literal pool insertion failed");
5238 /* Change the instruction exp to point to the pool. */
5239 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
5240 inst
.reloc
.pc_rel
= 1;
5241 inst
.instruction
|= (REG_PC
<< 16);
5246 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5249 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5251 /* PC rel adjust. */
5252 inst
.reloc
.exp
.X_add_number
-= 8;
5254 inst
.reloc
.pc_rel
= 1;
5255 inst
.instruction
|= (REG_PC
<< 16);
5259 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5270 skip_whitespace (str
);
5272 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5275 inst
.error
= BAD_ARGS
;
5279 if (skip_past_comma (& str
) == FAIL
)
5281 inst
.error
= _("address expected");
5291 skip_whitespace (str
);
5293 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5296 /* ldrt/strt always use post-indexed addressing, so if the base is
5297 the same as Rd, we warn. */
5298 if (conflict_reg
== reg
)
5299 as_warn (_("%s register same as write-back base"),
5300 ((inst
.instruction
& LOAD_BIT
)
5301 ? _("destination") : _("source")));
5303 skip_whitespace (str
);
5309 if (skip_past_comma (&str
) == SUCCESS
)
5311 /* [Rn],... (post inc) */
5312 if (ldst_extend (&str
) == FAIL
)
5318 skip_whitespace (str
);
5320 /* Skip a write-back '!'. */
5324 inst
.instruction
|= INDEX_UP
;
5329 inst
.error
= _("post-indexed expression expected");
5335 inst
.error
= _("post-indexed expression expected");
5344 ldst_extend_v4 (str
)
5354 if (my_get_expression (& inst
.reloc
.exp
, str
))
5357 if (inst
.reloc
.exp
.X_op
== O_constant
)
5359 int value
= inst
.reloc
.exp
.X_add_number
;
5361 if (value
< -255 || value
> 255)
5363 inst
.error
= _("address offset too large");
5373 /* Halfword and signextension instructions have the
5374 immediate value split across bits 11..8 and bits 3..0. */
5375 inst
.instruction
|= (add
| HWOFFSET_IMM
5376 | ((value
>> 4) << 8) | (value
& 0xF));
5380 inst
.instruction
|= HWOFFSET_IMM
;
5381 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5382 inst
.reloc
.pc_rel
= 0;
5395 if (reg_required_here (str
, 0) == FAIL
)
5398 inst
.instruction
|= add
;
5403 /* Halfword and signed-byte load/store operations. */
5412 skip_whitespace (str
);
5414 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5417 inst
.error
= BAD_ARGS
;
5421 if (skip_past_comma (& str
) == FAIL
)
5423 inst
.error
= _("address expected");
5433 skip_whitespace (str
);
5435 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5438 /* Conflicts can occur on stores as well as loads. */
5439 conflict_reg
= (conflict_reg
== reg
);
5441 skip_whitespace (str
);
5447 if (skip_past_comma (&str
) == SUCCESS
)
5449 /* [Rn],... (post inc) */
5450 if (ldst_extend_v4 (&str
) == FAIL
)
5453 as_warn (_("%s register same as write-back base"),
5454 ((inst
.instruction
& LOAD_BIT
)
5455 ? _("destination") : _("source")));
5460 inst
.instruction
|= HWOFFSET_IMM
;
5462 skip_whitespace (str
);
5467 as_warn (_("%s register same as write-back base"),
5468 ((inst
.instruction
& LOAD_BIT
)
5469 ? _("destination") : _("source")));
5471 inst
.instruction
|= WRITE_BACK
;
5474 inst
.instruction
|= INDEX_UP
;
5481 if (skip_past_comma (&str
) == FAIL
)
5483 inst
.error
= _("pre-indexed expression expected");
5488 if (ldst_extend_v4 (&str
) == FAIL
)
5491 skip_whitespace (str
);
5495 inst
.error
= _("missing ]");
5499 skip_whitespace (str
);
5504 as_warn (_("%s register same as write-back base"),
5505 ((inst
.instruction
& LOAD_BIT
)
5506 ? _("destination") : _("source")));
5508 inst
.instruction
|= WRITE_BACK
;
5512 else if (*str
== '=')
5514 if ((inst
.instruction
& LOAD_BIT
) == 0)
5516 inst
.error
= _("invalid pseudo operation");
5520 /* XXX Does this work correctly for half-word/byte ops? */
5521 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5524 skip_whitespace (str
);
5526 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5529 if (inst
.reloc
.exp
.X_op
!= O_constant
5530 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5532 inst
.error
= _("constant expression expected");
5536 if (inst
.reloc
.exp
.X_op
== O_constant
)
5538 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5542 /* This can be done with a mov instruction. */
5543 inst
.instruction
&= LITERAL_MASK
;
5544 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
5545 inst
.instruction
|= value
& 0xfff;
5550 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
5554 /* This can be done with a mvn instruction. */
5555 inst
.instruction
&= LITERAL_MASK
;
5556 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
5557 inst
.instruction
|= value
& 0xfff;
5563 /* Insert into literal pool. */
5564 if (add_to_lit_pool () == FAIL
)
5567 inst
.error
= _("literal pool insertion failed");
5571 /* Change the instruction exp to point to the pool. */
5572 inst
.instruction
|= HWOFFSET_IMM
;
5573 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
5574 inst
.reloc
.pc_rel
= 1;
5575 inst
.instruction
|= (REG_PC
<< 16);
5580 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5583 inst
.instruction
|= HWOFFSET_IMM
;
5584 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5586 /* PC rel adjust. */
5587 inst
.reloc
.exp
.X_add_number
-= 8;
5589 inst
.reloc
.pc_rel
= 1;
5590 inst
.instruction
|= (REG_PC
<< 16);
5594 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5603 char * str
= * strp
;
5607 /* We come back here if we get ranges concatenated by '+' or '|'. */
5622 skip_whitespace (str
);
5624 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
5633 inst
.error
= _("bad range in register list");
5637 for (i
= cur_reg
+ 1; i
< reg
; i
++)
5639 if (range
& (1 << i
))
5641 (_("Warning: duplicated register (r%d) in register list"),
5649 if (range
& (1 << reg
))
5650 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
5652 else if (reg
<= cur_reg
)
5653 as_tsktsk (_("Warning: register range not in ascending order"));
5658 while (skip_past_comma (&str
) != FAIL
5659 || (in_range
= 1, *str
++ == '-'));
5661 skip_whitespace (str
);
5665 inst
.error
= _("missing `}'");
5673 if (my_get_expression (&expr
, &str
))
5676 if (expr
.X_op
== O_constant
)
5678 if (expr
.X_add_number
5679 != (expr
.X_add_number
& 0x0000ffff))
5681 inst
.error
= _("invalid register mask");
5685 if ((range
& expr
.X_add_number
) != 0)
5687 int regno
= range
& expr
.X_add_number
;
5690 regno
= (1 << regno
) - 1;
5692 (_("Warning: duplicated register (r%d) in register list"),
5696 range
|= expr
.X_add_number
;
5700 if (inst
.reloc
.type
!= 0)
5702 inst
.error
= _("expression too complex");
5706 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
5707 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
5708 inst
.reloc
.pc_rel
= 0;
5712 skip_whitespace (str
);
5714 if (*str
== '|' || *str
== '+')
5720 while (another_range
);
5733 skip_whitespace (str
);
5735 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
5738 if (base_reg
== REG_PC
)
5740 inst
.error
= _("r15 not allowed as base register");
5744 skip_whitespace (str
);
5748 inst
.instruction
|= WRITE_BACK
;
5752 if (skip_past_comma (&str
) == FAIL
5753 || (range
= reg_list (&str
)) == FAIL
)
5756 inst
.error
= BAD_ARGS
;
5763 inst
.instruction
|= LDM_TYPE_2_OR_3
;
5766 inst
.instruction
|= range
;
5775 skip_whitespace (str
);
5777 /* Allow optional leading '#'. */
5778 if (is_immediate_prefix (*str
))
5781 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5784 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
5785 inst
.reloc
.pc_rel
= 0;
5797 skip_whitespace (str
);
5799 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5804 inst
.error
= _("r15 not allowed in swap");
5808 if (skip_past_comma (&str
) == FAIL
5809 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
5812 inst
.error
= BAD_ARGS
;
5818 inst
.error
= _("r15 not allowed in swap");
5822 if (skip_past_comma (&str
) == FAIL
5825 inst
.error
= BAD_ARGS
;
5829 skip_whitespace (str
);
5831 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5836 inst
.error
= BAD_PC
;
5840 skip_whitespace (str
);
5844 inst
.error
= _("missing ]");
5856 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5863 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5864 required for the instruction. */
5866 /* arm_parse_reloc () works on input_line_pointer.
5867 We actually want to parse the operands to the branch instruction
5868 passed in 'str'. Save the input pointer and restore it later. */
5869 save_in
= input_line_pointer
;
5870 input_line_pointer
= str
;
5871 if (inst
.reloc
.exp
.X_op
== O_symbol
5873 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5875 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5876 inst
.reloc
.pc_rel
= 0;
5877 /* Modify str to point to after parsed operands, otherwise
5878 end_of_line() will complain about the (PLT) left in str. */
5879 str
= input_line_pointer
;
5883 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5884 inst
.reloc
.pc_rel
= 1;
5886 input_line_pointer
= save_in
;
5889 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5890 inst
.reloc
.pc_rel
= 1;
5891 #endif /* OBJ_ELF */
5903 skip_whitespace (str
);
5905 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
5907 inst
.error
= BAD_ARGS
;
5911 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5913 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
5922 /* Co-processor data operation.
5923 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5924 skip_whitespace (str
);
5926 if (co_proc_number (&str
) == FAIL
)
5929 inst
.error
= BAD_ARGS
;
5933 if (skip_past_comma (&str
) == FAIL
5934 || cp_opc_expr (&str
, 20,4) == FAIL
)
5937 inst
.error
= BAD_ARGS
;
5941 if (skip_past_comma (&str
) == FAIL
5942 || cp_reg_required_here (&str
, 12) == FAIL
)
5945 inst
.error
= BAD_ARGS
;
5949 if (skip_past_comma (&str
) == FAIL
5950 || cp_reg_required_here (&str
, 16) == FAIL
)
5953 inst
.error
= BAD_ARGS
;
5957 if (skip_past_comma (&str
) == FAIL
5958 || cp_reg_required_here (&str
, 0) == FAIL
)
5961 inst
.error
= BAD_ARGS
;
5965 if (skip_past_comma (&str
) == SUCCESS
)
5967 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
5970 inst
.error
= BAD_ARGS
;
5983 /* Co-processor register load/store.
5984 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5986 skip_whitespace (str
);
5988 if (co_proc_number (&str
) == FAIL
)
5991 inst
.error
= BAD_ARGS
;
5995 if (skip_past_comma (&str
) == FAIL
5996 || cp_reg_required_here (&str
, 12) == FAIL
)
5999 inst
.error
= BAD_ARGS
;
6003 if (skip_past_comma (&str
) == FAIL
6004 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6007 inst
.error
= BAD_ARGS
;
6019 /* Co-processor register transfer.
6020 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6022 skip_whitespace (str
);
6024 if (co_proc_number (&str
) == FAIL
)
6027 inst
.error
= BAD_ARGS
;
6031 if (skip_past_comma (&str
) == FAIL
6032 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6035 inst
.error
= BAD_ARGS
;
6039 if (skip_past_comma (&str
) == FAIL
6040 || reg_required_here (&str
, 12) == FAIL
)
6043 inst
.error
= BAD_ARGS
;
6047 if (skip_past_comma (&str
) == FAIL
6048 || cp_reg_required_here (&str
, 16) == FAIL
)
6051 inst
.error
= BAD_ARGS
;
6055 if (skip_past_comma (&str
) == FAIL
6056 || cp_reg_required_here (&str
, 0) == FAIL
)
6059 inst
.error
= BAD_ARGS
;
6063 if (skip_past_comma (&str
) == SUCCESS
)
6065 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6068 inst
.error
= BAD_ARGS
;
6081 /* FP control registers.
6082 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6084 skip_whitespace (str
);
6086 if (reg_required_here (&str
, 12) == FAIL
)
6089 inst
.error
= BAD_ARGS
;
6101 skip_whitespace (str
);
6103 if (fp_reg_required_here (&str
, 12) == FAIL
)
6106 inst
.error
= BAD_ARGS
;
6110 if (skip_past_comma (&str
) == FAIL
6111 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6114 inst
.error
= BAD_ARGS
;
6127 skip_whitespace (str
);
6129 if (fp_reg_required_here (&str
, 12) == FAIL
)
6132 inst
.error
= BAD_ARGS
;
6136 /* Get Number of registers to transfer. */
6137 if (skip_past_comma (&str
) == FAIL
6138 || my_get_expression (&inst
.reloc
.exp
, &str
))
6141 inst
.error
= _("constant expression expected");
6145 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6147 inst
.error
= _("constant value required for number of registers");
6151 num_regs
= inst
.reloc
.exp
.X_add_number
;
6153 if (num_regs
< 1 || num_regs
> 4)
6155 inst
.error
= _("number of registers must be in the range [1:4]");
6162 inst
.instruction
|= CP_T_X
;
6165 inst
.instruction
|= CP_T_Y
;
6168 inst
.instruction
|= CP_T_Y
| CP_T_X
;
6176 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
6182 /* The instruction specified "ea" or "fd", so we can only accept
6183 [Rn]{!}. The instruction does not really support stacking or
6184 unstacking, so we have to emulate these by setting appropriate
6185 bits and offsets. */
6186 if (skip_past_comma (&str
) == FAIL
6190 inst
.error
= BAD_ARGS
;
6195 skip_whitespace (str
);
6197 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6200 skip_whitespace (str
);
6204 inst
.error
= BAD_ARGS
;
6216 _("r15 not allowed as base register with write-back");
6223 if (inst
.instruction
& CP_T_Pre
)
6225 /* Pre-decrement. */
6226 offset
= 3 * num_regs
;
6228 inst
.instruction
|= CP_T_WB
;
6232 /* Post-increment. */
6235 inst
.instruction
|= CP_T_WB
;
6236 offset
= 3 * num_regs
;
6240 /* No write-back, so convert this into a standard pre-increment
6241 instruction -- aesthetically more pleasing. */
6242 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
6247 inst
.instruction
|= offset
;
6249 else if (skip_past_comma (&str
) == FAIL
6250 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6253 inst
.error
= BAD_ARGS
;
6264 skip_whitespace (str
);
6266 if (fp_reg_required_here (&str
, 12) == FAIL
)
6269 inst
.error
= BAD_ARGS
;
6273 if (skip_past_comma (&str
) == FAIL
6274 || fp_reg_required_here (&str
, 16) == FAIL
)
6277 inst
.error
= BAD_ARGS
;
6281 if (skip_past_comma (&str
) == FAIL
6282 || fp_op2 (&str
) == FAIL
)
6285 inst
.error
= BAD_ARGS
;
6294 do_fpa_monadic (str
)
6297 skip_whitespace (str
);
6299 if (fp_reg_required_here (&str
, 12) == FAIL
)
6302 inst
.error
= BAD_ARGS
;
6306 if (skip_past_comma (&str
) == FAIL
6307 || fp_op2 (&str
) == FAIL
)
6310 inst
.error
= BAD_ARGS
;
6322 skip_whitespace (str
);
6324 if (fp_reg_required_here (&str
, 16) == FAIL
)
6327 inst
.error
= BAD_ARGS
;
6331 if (skip_past_comma (&str
) == FAIL
6332 || fp_op2 (&str
) == FAIL
)
6335 inst
.error
= BAD_ARGS
;
6344 do_fpa_from_reg (str
)
6347 skip_whitespace (str
);
6349 if (fp_reg_required_here (&str
, 16) == FAIL
)
6352 inst
.error
= BAD_ARGS
;
6356 if (skip_past_comma (&str
) == FAIL
6357 || reg_required_here (&str
, 12) == FAIL
)
6360 inst
.error
= BAD_ARGS
;
6372 skip_whitespace (str
);
6374 if (reg_required_here (&str
, 12) == FAIL
)
6377 if (skip_past_comma (&str
) == FAIL
6378 || fp_reg_required_here (&str
, 0) == FAIL
)
6381 inst
.error
= BAD_ARGS
;
6390 vfp_sp_reg_required_here (str
, pos
)
6392 enum vfp_sp_reg_pos pos
;
6397 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
6402 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
6406 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
6410 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
6419 /* In the few cases where we might be able to accept something else
6420 this error can be overridden. */
6421 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
6423 /* Restore the start point. */
6429 vfp_dp_reg_required_here (str
, pos
)
6431 enum vfp_dp_reg_pos pos
;
6436 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
6441 inst
.instruction
|= reg
<< 12;
6445 inst
.instruction
|= reg
<< 16;
6449 inst
.instruction
|= reg
<< 0;
6458 /* In the few cases where we might be able to accept something else
6459 this error can be overridden. */
6460 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
6462 /* Restore the start point. */
6468 do_vfp_sp_monadic (str
)
6471 skip_whitespace (str
);
6473 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6476 if (skip_past_comma (&str
) == FAIL
6477 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
6480 inst
.error
= BAD_ARGS
;
6489 do_vfp_dp_monadic (str
)
6492 skip_whitespace (str
);
6494 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6497 if (skip_past_comma (&str
) == FAIL
6498 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6501 inst
.error
= BAD_ARGS
;
6510 do_vfp_sp_dyadic (str
)
6513 skip_whitespace (str
);
6515 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6518 if (skip_past_comma (&str
) == FAIL
6519 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
6520 || skip_past_comma (&str
) == FAIL
6521 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
6524 inst
.error
= BAD_ARGS
;
6533 do_vfp_dp_dyadic (str
)
6536 skip_whitespace (str
);
6538 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6541 if (skip_past_comma (&str
) == FAIL
6542 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
6543 || skip_past_comma (&str
) == FAIL
6544 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6547 inst
.error
= BAD_ARGS
;
6556 do_vfp_reg_from_sp (str
)
6559 skip_whitespace (str
);
6561 if (reg_required_here (&str
, 12) == FAIL
)
6564 if (skip_past_comma (&str
) == FAIL
6565 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
6568 inst
.error
= BAD_ARGS
;
6577 do_vfp_sp_reg2 (str
)
6580 skip_whitespace (str
);
6582 if (reg_required_here (&str
, 12) == FAIL
)
6585 if (skip_past_comma (&str
) == FAIL
6586 || reg_required_here (&str
, 16) == FAIL
6587 || skip_past_comma (&str
) == FAIL
)
6590 inst
.error
= BAD_ARGS
;
6594 /* We require exactly two consecutive SP registers. */
6595 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
6598 inst
.error
= _("only two consecutive VFP SP registers allowed here");
6606 do_vfp_sp_from_reg (str
)
6609 skip_whitespace (str
);
6611 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
6614 if (skip_past_comma (&str
) == FAIL
6615 || reg_required_here (&str
, 12) == FAIL
)
6618 inst
.error
= BAD_ARGS
;
6627 do_vfp_reg_from_dp (str
)
6630 skip_whitespace (str
);
6632 if (reg_required_here (&str
, 12) == FAIL
)
6635 if (skip_past_comma (&str
) == FAIL
6636 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
6639 inst
.error
= BAD_ARGS
;
6648 do_vfp_reg2_from_dp (str
)
6651 skip_whitespace (str
);
6653 if (reg_required_here (&str
, 12) == FAIL
)
6656 if (skip_past_comma (&str
) == FAIL
6657 || reg_required_here (&str
, 16) == FAIL
6658 || skip_past_comma (&str
) == FAIL
6659 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6662 inst
.error
= BAD_ARGS
;
6671 do_vfp_dp_from_reg (str
)
6674 skip_whitespace (str
);
6676 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
6679 if (skip_past_comma (&str
) == FAIL
6680 || reg_required_here (&str
, 12) == FAIL
)
6683 inst
.error
= BAD_ARGS
;
6692 do_vfp_dp_from_reg2 (str
)
6695 skip_whitespace (str
);
6697 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6700 if (skip_past_comma (&str
) == FAIL
6701 || reg_required_here (&str
, 12) == FAIL
6702 || skip_past_comma (&str
) == FAIL
6703 || reg_required_here (&str
, 16))
6706 inst
.error
= BAD_ARGS
;
6714 static const struct vfp_reg
*
6721 const struct vfp_reg
*vreg
;
6725 /* Find the end of the current token. */
6730 while (ISALPHA (c
));
6735 for (vreg
= vfp_regs
+ 0;
6736 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
6739 if (strcmp (start
, vreg
->name
) == 0)
6752 vfp_psr_required_here (str
)
6756 const struct vfp_reg
*vreg
;
6758 vreg
= vfp_psr_parse (str
);
6762 inst
.instruction
|= vreg
->regno
;
6766 inst
.error
= _("VFP system register expected");
6773 do_vfp_reg_from_ctrl (str
)
6776 skip_whitespace (str
);
6778 if (reg_required_here (&str
, 12) == FAIL
)
6781 if (skip_past_comma (&str
) == FAIL
6782 || vfp_psr_required_here (&str
) == FAIL
)
6785 inst
.error
= BAD_ARGS
;
6794 do_vfp_ctrl_from_reg (str
)
6797 skip_whitespace (str
);
6799 if (vfp_psr_required_here (&str
) == FAIL
)
6802 if (skip_past_comma (&str
) == FAIL
6803 || reg_required_here (&str
, 12) == FAIL
)
6806 inst
.error
= BAD_ARGS
;
6815 do_vfp_sp_ldst (str
)
6818 skip_whitespace (str
);
6820 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6823 inst
.error
= BAD_ARGS
;
6827 if (skip_past_comma (&str
) == FAIL
6828 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
6831 inst
.error
= BAD_ARGS
;
6840 do_vfp_dp_ldst (str
)
6843 skip_whitespace (str
);
6845 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6848 inst
.error
= BAD_ARGS
;
6852 if (skip_past_comma (&str
) == FAIL
6853 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
6856 inst
.error
= BAD_ARGS
;
6864 /* Parse and encode a VFP SP register list, storing the initial
6865 register in position POS and returning the range as the result. If
6866 the string is invalid return FAIL (an invalid range). */
6868 vfp_sp_reg_list (str
, pos
)
6870 enum vfp_sp_reg_pos pos
;
6878 unsigned long mask
= 0;
6885 skip_whitespace (*str
);
6887 tempinst
= inst
.instruction
;
6891 inst
.instruction
= 0;
6893 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
6896 if (count
== 0 || base_reg
> new_base
)
6898 base_reg
= new_base
;
6899 base_bits
= inst
.instruction
;
6902 if (mask
& (1 << new_base
))
6904 inst
.error
= _("invalid register list");
6908 if ((mask
>> new_base
) != 0 && ! warned
)
6910 as_tsktsk (_("register list not in ascending order"));
6914 mask
|= 1 << new_base
;
6917 skip_whitespace (*str
);
6919 if (**str
== '-') /* We have the start of a range expression */
6926 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
6929 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
6933 if (high_range
<= new_base
)
6935 inst
.error
= _("register range not in ascending order");
6939 for (new_base
++; new_base
<= high_range
; new_base
++)
6941 if (mask
& (1 << new_base
))
6943 inst
.error
= _("invalid register list");
6947 mask
|= 1 << new_base
;
6952 while (skip_past_comma (str
) != FAIL
);
6956 inst
.error
= _("invalid register list");
6964 /* Sanity check -- should have raised a parse error above. */
6965 if (count
== 0 || count
> 32)
6968 /* Final test -- the registers must be consecutive. */
6971 if ((mask
& (1 << base_reg
++)) == 0)
6973 inst
.error
= _("non-contiguous register range");
6978 inst
.instruction
= tempinst
| base_bits
;
6983 vfp_dp_reg_list (str
)
6991 unsigned long mask
= 0;
6998 skip_whitespace (*str
);
7000 tempinst
= inst
.instruction
;
7004 inst
.instruction
= 0;
7006 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
7009 if (count
== 0 || base_reg
> new_base
)
7011 base_reg
= new_base
;
7012 range
= inst
.instruction
;
7015 if (mask
& (1 << new_base
))
7017 inst
.error
= _("invalid register list");
7021 if ((mask
>> new_base
) != 0 && ! warned
)
7023 as_tsktsk (_("register list not in ascending order"));
7027 mask
|= 1 << new_base
;
7030 skip_whitespace (*str
);
7032 if (**str
== '-') /* We have the start of a range expression */
7039 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7042 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7046 if (high_range
<= new_base
)
7048 inst
.error
= _("register range not in ascending order");
7052 for (new_base
++; new_base
<= high_range
; new_base
++)
7054 if (mask
& (1 << new_base
))
7056 inst
.error
= _("invalid register list");
7060 mask
|= 1 << new_base
;
7065 while (skip_past_comma (str
) != FAIL
);
7069 inst
.error
= _("invalid register list");
7077 /* Sanity check -- should have raised a parse error above. */
7078 if (count
== 0 || count
> 16)
7081 /* Final test -- the registers must be consecutive. */
7084 if ((mask
& (1 << base_reg
++)) == 0)
7086 inst
.error
= _("non-contiguous register range");
7091 inst
.instruction
= tempinst
;
7096 vfp_sp_ldstm (str
, ldstm_type
)
7098 enum vfp_ldstm_type ldstm_type
;
7102 skip_whitespace (str
);
7104 if (reg_required_here (&str
, 16) == FAIL
)
7107 skip_whitespace (str
);
7111 inst
.instruction
|= WRITE_BACK
;
7114 else if (ldstm_type
!= VFP_LDSTMIA
)
7116 inst
.error
= _("this addressing mode requires base-register writeback");
7120 if (skip_past_comma (&str
) == FAIL
7121 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
7124 inst
.error
= BAD_ARGS
;
7128 inst
.instruction
|= range
;
7133 vfp_dp_ldstm (str
, ldstm_type
)
7135 enum vfp_ldstm_type ldstm_type
;
7139 skip_whitespace (str
);
7141 if (reg_required_here (&str
, 16) == FAIL
)
7144 skip_whitespace (str
);
7148 inst
.instruction
|= WRITE_BACK
;
7151 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7153 inst
.error
= _("this addressing mode requires base-register writeback");
7157 if (skip_past_comma (&str
) == FAIL
7158 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
7161 inst
.error
= BAD_ARGS
;
7165 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7168 inst
.instruction
|= range
;
7173 do_vfp_sp_ldstmia (str
)
7176 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7180 do_vfp_sp_ldstmdb (str
)
7183 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7187 do_vfp_dp_ldstmia (str
)
7190 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
7194 do_vfp_dp_ldstmdb (str
)
7197 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
7201 do_vfp_xp_ldstmia (str
)
7204 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
7208 do_vfp_xp_ldstmdb (str
)
7211 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
7215 do_vfp_sp_compare_z (str
)
7218 skip_whitespace (str
);
7220 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7223 inst
.error
= BAD_ARGS
;
7232 do_vfp_dp_compare_z (str
)
7235 skip_whitespace (str
);
7237 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7240 inst
.error
= BAD_ARGS
;
7249 do_vfp_dp_sp_cvt (str
)
7252 skip_whitespace (str
);
7254 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7257 if (skip_past_comma (&str
) == FAIL
7258 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7261 inst
.error
= BAD_ARGS
;
7270 do_vfp_sp_dp_cvt (str
)
7273 skip_whitespace (str
);
7275 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7278 if (skip_past_comma (&str
) == FAIL
7279 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7282 inst
.error
= BAD_ARGS
;
7290 /* Thumb specific routines. */
7292 /* Parse and validate that a register is of the right form, this saves
7293 repeated checking of this information in many similar cases.
7294 Unlike the 32-bit case we do not insert the register into the opcode
7295 here, since the position is often unknown until the full instruction
7299 thumb_reg (strp
, hi_lo
)
7305 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
7313 inst
.error
= _("lo register required");
7321 inst
.error
= _("hi register required");
7333 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
7337 thumb_add_sub (str
, subtract
)
7341 int Rd
, Rs
, Rn
= FAIL
;
7343 skip_whitespace (str
);
7345 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
7346 || skip_past_comma (&str
) == FAIL
)
7349 inst
.error
= BAD_ARGS
;
7353 if (is_immediate_prefix (*str
))
7357 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7362 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7365 if (skip_past_comma (&str
) == FAIL
)
7367 /* Two operand format, shuffle the registers
7368 and pretend there are 3. */
7372 else if (is_immediate_prefix (*str
))
7375 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7378 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7382 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7383 for the latter case, EXPR contains the immediate that was found. */
7386 /* All register format. */
7387 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
7391 inst
.error
= _("dest and source1 must be the same register");
7395 /* Can't do this for SUB. */
7398 inst
.error
= _("subtract valid only on lo regs");
7402 inst
.instruction
= (T_OPCODE_ADD_HI
7403 | (Rd
> 7 ? THUMB_H1
: 0)
7404 | (Rn
> 7 ? THUMB_H2
: 0));
7405 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
7409 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
7410 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
7415 /* Immediate expression, now things start to get nasty. */
7417 /* First deal with HI regs, only very restricted cases allowed:
7418 Adjusting SP, and using PC or SP to get an address. */
7419 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
7420 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
7422 inst
.error
= _("invalid Hi register with immediate");
7426 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7428 /* Value isn't known yet, all we can do is store all the fragments
7429 we know about in the instruction and let the reloc hacking
7431 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
7432 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
7436 int offset
= inst
.reloc
.exp
.X_add_number
;
7446 /* Quick check, in case offset is MIN_INT. */
7449 inst
.error
= _("immediate value out of range");
7453 /* Note - you cannot convert a subtract of 0 into an
7454 add of 0 because the carry flag is set differently. */
7455 else if (offset
> 0)
7460 if (offset
& ~0x1fc)
7462 inst
.error
= _("invalid immediate value for stack adjust");
7465 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
7466 inst
.instruction
|= offset
>> 2;
7468 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
7471 || (offset
& ~0x3fc))
7473 inst
.error
= _("invalid immediate for address calculation");
7476 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
7478 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
7484 inst
.error
= _("immediate value out of range");
7487 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
7488 inst
.instruction
|= (Rd
<< 8) | offset
;
7494 inst
.error
= _("immediate value out of range");
7497 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
7498 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
7507 thumb_shift (str
, shift
)
7511 int Rd
, Rs
, Rn
= FAIL
;
7513 skip_whitespace (str
);
7515 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7516 || skip_past_comma (&str
) == FAIL
)
7519 inst
.error
= BAD_ARGS
;
7523 if (is_immediate_prefix (*str
))
7525 /* Two operand immediate format, set Rs to Rd. */
7528 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7533 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7536 if (skip_past_comma (&str
) == FAIL
)
7538 /* Two operand format, shuffle the registers
7539 and pretend there are 3. */
7543 else if (is_immediate_prefix (*str
))
7546 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7549 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7553 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7554 for the latter case, EXPR contains the immediate that was found. */
7560 inst
.error
= _("source1 and dest must be same register");
7566 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
7567 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
7568 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
7571 inst
.instruction
|= Rd
| (Rn
<< 3);
7577 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
7578 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
7579 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
7582 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7584 /* Value isn't known yet, create a dummy reloc and let reloc
7585 hacking fix it up. */
7586 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
7590 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
7592 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
7594 inst
.error
= _("invalid immediate for shift");
7598 /* Shifts of zero are handled by converting to LSL. */
7599 if (shift_value
== 0)
7600 inst
.instruction
= T_OPCODE_LSL_I
;
7602 /* Shifts of 32 are encoded as a shift of zero. */
7603 if (shift_value
== 32)
7606 inst
.instruction
|= shift_value
<< 6;
7609 inst
.instruction
|= Rd
| (Rs
<< 3);
7616 thumb_mov_compare (str
, move
)
7622 skip_whitespace (str
);
7624 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
7625 || skip_past_comma (&str
) == FAIL
)
7628 inst
.error
= BAD_ARGS
;
7632 if (is_immediate_prefix (*str
))
7635 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7638 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7643 if (Rs
< 8 && Rd
< 8)
7645 if (move
== THUMB_MOVE
)
7646 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
7647 since a MOV instruction produces unpredictable results. */
7648 inst
.instruction
= T_OPCODE_ADD_I3
;
7650 inst
.instruction
= T_OPCODE_CMP_LR
;
7651 inst
.instruction
|= Rd
| (Rs
<< 3);
7655 if (move
== THUMB_MOVE
)
7656 inst
.instruction
= T_OPCODE_MOV_HR
;
7658 inst
.instruction
= T_OPCODE_CMP_HR
;
7661 inst
.instruction
|= THUMB_H1
;
7664 inst
.instruction
|= THUMB_H2
;
7666 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
7673 inst
.error
= _("only lo regs allowed with immediate");
7677 if (move
== THUMB_MOVE
)
7678 inst
.instruction
= T_OPCODE_MOV_I8
;
7680 inst
.instruction
= T_OPCODE_CMP_I8
;
7682 inst
.instruction
|= Rd
<< 8;
7684 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7685 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
7688 unsigned value
= inst
.reloc
.exp
.X_add_number
;
7692 inst
.error
= _("invalid immediate");
7696 inst
.instruction
|= value
;
7704 thumb_load_store (str
, load_store
, size
)
7709 int Rd
, Rb
, Ro
= FAIL
;
7711 skip_whitespace (str
);
7713 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7714 || skip_past_comma (&str
) == FAIL
)
7717 inst
.error
= BAD_ARGS
;
7724 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7727 if (skip_past_comma (&str
) != FAIL
)
7729 if (is_immediate_prefix (*str
))
7732 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7735 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7740 inst
.reloc
.exp
.X_op
= O_constant
;
7741 inst
.reloc
.exp
.X_add_number
= 0;
7746 inst
.error
= _("expected ']'");
7751 else if (*str
== '=')
7753 if (load_store
!= THUMB_LOAD
)
7755 inst
.error
= _("invalid pseudo operation");
7759 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7762 skip_whitespace (str
);
7764 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7769 if ( inst
.reloc
.exp
.X_op
!= O_constant
7770 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7772 inst
.error
= "Constant expression expected";
7776 if (inst
.reloc
.exp
.X_op
== O_constant
7777 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
7779 /* This can be done with a mov instruction. */
7781 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
7782 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7786 /* Insert into literal pool. */
7787 if (add_to_lit_pool () == FAIL
)
7790 inst
.error
= "literal pool insertion failed";
7794 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7795 inst
.reloc
.pc_rel
= 1;
7796 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
7797 /* Adjust ARM pipeline offset to Thumb. */
7798 inst
.reloc
.exp
.X_add_number
+= 4;
7804 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7807 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
7808 inst
.reloc
.pc_rel
= 1;
7809 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
7810 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7815 if (Rb
== REG_PC
|| Rb
== REG_SP
)
7817 if (size
!= THUMB_WORD
)
7819 inst
.error
= _("byte or halfword not valid for base register");
7822 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
7824 inst
.error
= _("r15 based store not allowed");
7827 else if (Ro
!= FAIL
)
7829 inst
.error
= _("invalid base register for register offset");
7834 inst
.instruction
= T_OPCODE_LDR_PC
;
7835 else if (load_store
== THUMB_LOAD
)
7836 inst
.instruction
= T_OPCODE_LDR_SP
;
7838 inst
.instruction
= T_OPCODE_STR_SP
;
7840 inst
.instruction
|= Rd
<< 8;
7841 if (inst
.reloc
.exp
.X_op
== O_constant
)
7843 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
7845 if (offset
& ~0x3fc)
7847 inst
.error
= _("invalid offset");
7851 inst
.instruction
|= offset
>> 2;
7854 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7858 inst
.error
= _("invalid base register in load/store");
7861 else if (Ro
== FAIL
)
7863 /* Immediate offset. */
7864 if (size
== THUMB_WORD
)
7865 inst
.instruction
= (load_store
== THUMB_LOAD
7866 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
7867 else if (size
== THUMB_HALFWORD
)
7868 inst
.instruction
= (load_store
== THUMB_LOAD
7869 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
7871 inst
.instruction
= (load_store
== THUMB_LOAD
7872 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
7874 inst
.instruction
|= Rd
| (Rb
<< 3);
7876 if (inst
.reloc
.exp
.X_op
== O_constant
)
7878 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
7880 if (offset
& ~(0x1f << size
))
7882 inst
.error
= _("invalid offset");
7885 inst
.instruction
|= (offset
>> size
) << 6;
7888 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7892 /* Register offset. */
7893 if (size
== THUMB_WORD
)
7894 inst
.instruction
= (load_store
== THUMB_LOAD
7895 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
7896 else if (size
== THUMB_HALFWORD
)
7897 inst
.instruction
= (load_store
== THUMB_LOAD
7898 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
7900 inst
.instruction
= (load_store
== THUMB_LOAD
7901 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
7903 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
7909 /* A register must be given at this point.
7911 Shift is the place to put it in inst.instruction.
7913 Restores input start point on err.
7914 Returns the reg#, or FAIL. */
7917 mav_reg_required_here (str
, shift
, regtype
)
7920 enum arm_reg_type regtype
;
7925 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
7928 inst
.instruction
|= reg
<< shift
;
7933 /* Restore the start point. */
7936 /* In the few cases where we might be able to accept something else
7937 this error can be overridden. */
7938 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7943 /* Cirrus Maverick Instructions. */
7945 /* Wrapper functions. */
7948 do_mav_binops_1a (str
)
7951 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
7955 do_mav_binops_1b (str
)
7958 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
7962 do_mav_binops_1c (str
)
7965 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
7969 do_mav_binops_1d (str
)
7972 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
7976 do_mav_binops_1e (str
)
7979 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
7983 do_mav_binops_1f (str
)
7986 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
7990 do_mav_binops_1g (str
)
7993 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
7997 do_mav_binops_1h (str
)
8000 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8004 do_mav_binops_1i (str
)
8007 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8011 do_mav_binops_1j (str
)
8014 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8018 do_mav_binops_1k (str
)
8021 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8025 do_mav_binops_1l (str
)
8028 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8032 do_mav_binops_1m (str
)
8035 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8039 do_mav_binops_1n (str
)
8042 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8046 do_mav_binops_1o (str
)
8049 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8053 do_mav_binops_2a (str
)
8056 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8060 do_mav_binops_2b (str
)
8063 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8067 do_mav_binops_2c (str
)
8070 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8074 do_mav_binops_3a (str
)
8077 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8081 do_mav_binops_3b (str
)
8084 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8088 do_mav_binops_3c (str
)
8091 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8095 do_mav_binops_3d (str
)
8098 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8102 do_mav_triple_4a (str
)
8105 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8109 do_mav_triple_4b (str
)
8112 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8116 do_mav_triple_5a (str
)
8119 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8123 do_mav_triple_5b (str
)
8126 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8130 do_mav_triple_5c (str
)
8133 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8137 do_mav_triple_5d (str
)
8140 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8144 do_mav_triple_5e (str
)
8147 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8151 do_mav_triple_5f (str
)
8154 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8158 do_mav_triple_5g (str
)
8161 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8165 do_mav_triple_5h (str
)
8168 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8172 do_mav_quad_6a (str
)
8175 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8180 do_mav_quad_6b (str
)
8183 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8187 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
8189 do_mav_dspsc_1 (str
)
8192 skip_whitespace (str
);
8195 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8196 || skip_past_comma (&str
) == FAIL
8197 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
8200 inst
.error
= BAD_ARGS
;
8208 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
8210 do_mav_dspsc_2 (str
)
8213 skip_whitespace (str
);
8216 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
8217 || skip_past_comma (&str
) == FAIL
8218 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8221 inst
.error
= BAD_ARGS
;
8230 do_mav_shift_1 (str
)
8233 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8237 do_mav_shift_2 (str
)
8240 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8247 do_mav_ldst (str
, REG_TYPE_MVF
);
8254 do_mav_ldst (str
, REG_TYPE_MVD
);
8261 do_mav_ldst (str
, REG_TYPE_MVFX
);
8268 do_mav_ldst (str
, REG_TYPE_MVDX
);
8271 /* Isnsn like "foo X,Y". */
8274 do_mav_binops (str
, mode
, reg0
, reg1
)
8277 enum arm_reg_type reg0
;
8278 enum arm_reg_type reg1
;
8282 shift0
= mode
& 0xff;
8283 shift1
= (mode
>> 8) & 0xff;
8285 skip_whitespace (str
);
8287 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8288 || skip_past_comma (&str
) == FAIL
8289 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8292 inst
.error
= BAD_ARGS
;
8298 /* Isnsn like "foo X,Y,Z". */
8301 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
8304 enum arm_reg_type reg0
;
8305 enum arm_reg_type reg1
;
8306 enum arm_reg_type reg2
;
8308 int shift0
, shift1
, shift2
;
8310 shift0
= mode
& 0xff;
8311 shift1
= (mode
>> 8) & 0xff;
8312 shift2
= (mode
>> 16) & 0xff;
8314 skip_whitespace (str
);
8316 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8317 || skip_past_comma (&str
) == FAIL
8318 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8319 || skip_past_comma (&str
) == FAIL
8320 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8323 inst
.error
= BAD_ARGS
;
8329 /* Isnsn like "foo W,X,Y,Z".
8330 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8333 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
8336 enum arm_reg_type reg0
;
8337 enum arm_reg_type reg1
;
8338 enum arm_reg_type reg2
;
8339 enum arm_reg_type reg3
;
8341 int shift0
, shift1
, shift2
, shift3
;
8343 shift0
= mode
& 0xff;
8344 shift1
= (mode
>> 8) & 0xff;
8345 shift2
= (mode
>> 16) & 0xff;
8346 shift3
= (mode
>> 24) & 0xff;
8348 skip_whitespace (str
);
8350 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8351 || skip_past_comma (&str
) == FAIL
8352 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8353 || skip_past_comma (&str
) == FAIL
8354 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8355 || skip_past_comma (&str
) == FAIL
8356 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8359 inst
.error
= BAD_ARGS
;
8365 /* Maverick shift immediate instructions.
8366 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8367 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8370 do_mav_shift (str
, reg0
, reg1
)
8372 enum arm_reg_type reg0
;
8373 enum arm_reg_type reg1
;
8378 skip_whitespace (str
);
8382 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8383 || skip_past_comma (&str
) == FAIL
8384 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8385 || skip_past_comma (&str
) == FAIL
)
8388 inst
.error
= BAD_ARGS
;
8392 /* Calculate the immediate operand.
8393 The operand is a 7bit signed number. */
8394 skip_whitespace (str
);
8399 if (!ISDIGIT (*str
) && *str
!= '-')
8401 inst
.error
= _("expecting immediate, 7bit operand");
8411 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
8412 imm
= imm
* 10 + *str
- '0';
8416 inst
.error
= _("immediate out of range");
8420 /* Make negative imm's into 7bit signed numbers. */
8427 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
8428 Bits 5-7 of the insn should have bits 4-6 of the immediate.
8429 Bit 4 should be 0. */
8430 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
8432 inst
.instruction
|= imm
;
8437 mav_parse_offset (str
, negative
)
8446 skip_whitespace (p
);
8459 inst
.error
= _("offset expected");
8463 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
8464 offset
= offset
* 10 + *p
- '0';
8468 inst
.error
= _("offset out of range");
8474 return *negative
? -offset
: offset
;
8477 /* Maverick load/store instructions.
8478 <insn><cond> CRd,[Rn,<offset>]{!}.
8479 <insn><cond> CRd,[Rn],<offset>. */
8482 do_mav_ldst (str
, reg0
)
8484 enum arm_reg_type reg0
;
8486 int offset
, negative
;
8488 skip_whitespace (str
);
8490 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8491 || skip_past_comma (&str
) == FAIL
8493 || reg_required_here (&str
, 16) == FAIL
)
8496 if (skip_past_comma (&str
) == SUCCESS
)
8498 /* You are here: "<offset>]{!}". */
8499 inst
.instruction
|= PRE_INDEX
;
8501 offset
= mav_parse_offset (&str
, &negative
);
8508 inst
.error
= _("missing ]");
8514 inst
.instruction
|= WRITE_BACK
;
8520 /* You are here: "], <offset>". */
8523 inst
.error
= _("missing ]");
8527 if (skip_past_comma (&str
) == FAIL
8528 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
8531 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
8537 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
8539 inst
.instruction
|= offset
>> 2;
8545 inst
.error
= BAD_ARGS
;
8558 /* Handle the Format 4 instructions that do not have equivalents in other
8559 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
8568 skip_whitespace (str
);
8570 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8571 || skip_past_comma (&str
) == FAIL
8572 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8574 inst
.error
= BAD_ARGS
;
8578 if (skip_past_comma (&str
) != FAIL
)
8580 /* Three operand format not allowed for TST, CMN, NEG and MVN.
8581 (It isn't allowed for CMP either, but that isn't handled by this
8583 if (inst
.instruction
== T_OPCODE_TST
8584 || inst
.instruction
== T_OPCODE_CMN
8585 || inst
.instruction
== T_OPCODE_NEG
8586 || inst
.instruction
== T_OPCODE_MVN
)
8588 inst
.error
= BAD_ARGS
;
8592 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8597 inst
.error
= _("dest and source1 must be the same register");
8603 if (inst
.instruction
== T_OPCODE_MUL
8605 as_tsktsk (_("Rs and Rd must be different in MUL"));
8607 inst
.instruction
|= Rd
| (Rs
<< 3);
8615 thumb_add_sub (str
, 0);
8622 thumb_shift (str
, THUMB_ASR
);
8629 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8631 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
8632 inst
.reloc
.pc_rel
= 1;
8640 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8642 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
8643 inst
.reloc
.pc_rel
= 1;
8647 /* Find the real, Thumb encoded start of a Thumb function. */
8650 find_real_start (symbolP
)
8654 const char * name
= S_GET_NAME (symbolP
);
8655 symbolS
* new_target
;
8657 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
8658 #define STUB_NAME ".real_start_of"
8663 /* Names that start with '.' are local labels, not function entry points.
8664 The compiler may generate BL instructions to these labels because it
8665 needs to perform a branch to a far away location. */
8669 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
8670 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
8672 new_target
= symbol_find (real_start
);
8674 if (new_target
== NULL
)
8676 as_warn ("Failed to find real start of function: %s\n", name
);
8677 new_target
= symbolP
;
8689 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8692 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
8693 inst
.reloc
.pc_rel
= 1;
8696 /* If the destination of the branch is a defined symbol which does not have
8697 the THUMB_FUNC attribute, then we must be calling a function which has
8698 the (interfacearm) attribute. We look for the Thumb entry point to that
8699 function and change the branch to refer to that function instead. */
8700 if ( inst
.reloc
.exp
.X_op
== O_symbol
8701 && inst
.reloc
.exp
.X_add_symbol
!= NULL
8702 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
8703 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
8704 inst
.reloc
.exp
.X_add_symbol
=
8705 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
8714 skip_whitespace (str
);
8716 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8719 /* This sets THUMB_H2 from the top bit of reg. */
8720 inst
.instruction
|= reg
<< 3;
8722 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
8723 should cause the alignment to be checked once it is known. This is
8724 because BX PC only works if the instruction is word aligned. */
8733 thumb_mov_compare (str
, THUMB_COMPARE
);
8743 skip_whitespace (str
);
8745 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8749 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
8753 if (skip_past_comma (&str
) == FAIL
8754 || (range
= reg_list (&str
)) == FAIL
)
8757 inst
.error
= BAD_ARGS
;
8761 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8763 /* This really doesn't seem worth it. */
8764 inst
.reloc
.type
= BFD_RELOC_NONE
;
8765 inst
.error
= _("expression too complex");
8771 inst
.error
= _("only lo-regs valid in load/store multiple");
8775 inst
.instruction
|= (Rb
<< 8) | range
;
8783 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
8790 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
8797 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
8806 skip_whitespace (str
);
8808 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8809 || skip_past_comma (&str
) == FAIL
8811 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8812 || skip_past_comma (&str
) == FAIL
8813 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8817 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
8821 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8829 thumb_shift (str
, THUMB_LSL
);
8836 thumb_shift (str
, THUMB_LSR
);
8843 thumb_mov_compare (str
, THUMB_MOVE
);
8852 skip_whitespace (str
);
8854 if ((range
= reg_list (&str
)) == FAIL
)
8857 inst
.error
= BAD_ARGS
;
8861 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8863 /* This really doesn't seem worth it. */
8864 inst
.reloc
.type
= BFD_RELOC_NONE
;
8865 inst
.error
= _("expression too complex");
8871 if ((inst
.instruction
== T_OPCODE_PUSH
8872 && (range
& ~0xff) == 1 << REG_LR
)
8873 || (inst
.instruction
== T_OPCODE_POP
8874 && (range
& ~0xff) == 1 << REG_PC
))
8876 inst
.instruction
|= THUMB_PP_PC_LR
;
8881 inst
.error
= _("invalid register list to push/pop instruction");
8886 inst
.instruction
|= range
;
8894 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
8901 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
8908 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
8915 thumb_add_sub (str
, 1);
8922 skip_whitespace (str
);
8924 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8927 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8938 /* This is a pseudo-op of the form "adr rd, label" to be converted
8939 into a relative address of the form "add rd, pc, #label-.-4". */
8940 skip_whitespace (str
);
8942 /* Store Rd in temporary location inside instruction. */
8943 if ((reg
= reg_required_here (&str
, 4)) == FAIL
8944 || (reg
> 7) /* For Thumb reg must be r0..r7. */
8945 || skip_past_comma (&str
) == FAIL
8946 || my_get_expression (&inst
.reloc
.exp
, &str
))
8949 inst
.error
= BAD_ARGS
;
8953 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8954 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
8955 inst
.reloc
.pc_rel
= 1;
8956 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
8962 insert_reg (r
, htab
)
8963 const struct reg_entry
*r
;
8964 struct hash_control
*htab
;
8966 int len
= strlen (r
->name
) + 2;
8967 char * buf
= (char *) xmalloc (len
);
8968 char * buf2
= (char *) xmalloc (len
);
8971 #ifdef REGISTER_PREFIX
8972 buf
[i
++] = REGISTER_PREFIX
;
8975 strcpy (buf
+ i
, r
->name
);
8977 for (i
= 0; buf
[i
]; i
++)
8978 buf2
[i
] = TOUPPER (buf
[i
]);
8982 hash_insert (htab
, buf
, (PTR
) r
);
8983 hash_insert (htab
, buf2
, (PTR
) r
);
8988 struct reg_map
*map
;
8990 const struct reg_entry
*r
;
8992 if ((map
->htab
= hash_new ()) == NULL
)
8993 as_fatal (_("virtual memory exhausted"));
8995 for (r
= map
->names
; r
->name
!= NULL
; r
++)
8996 insert_reg (r
, map
->htab
);
9000 insert_reg_alias (str
, regnum
, htab
)
9003 struct hash_control
*htab
;
9005 struct reg_entry
*new =
9006 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
9007 char *name
= xmalloc (strlen (str
) + 1);
9011 new->number
= regnum
;
9013 hash_insert (htab
, name
, (PTR
) new);
9016 /* Look for the .req directive. This is of the form:
9018 newname .req existing_name
9020 If we find one, or if it looks sufficiently like one that we want to
9021 handle any error here, return non-zero. Otherwise return zero. */
9023 create_register_alias (newname
, p
)
9031 skip_whitespace (q
);
9036 if (*q
&& !strncmp (q
, ".req ", 5))
9041 #ifdef IGNORE_OPCODE_CASE
9042 newname
= original_case_string
;
9044 copy_of_str
= newname
;
9047 skip_whitespace (q
);
9049 for (r
= q
; *r
!= '\0'; r
++)
9055 enum arm_reg_type new_type
, old_type
;
9060 old_type
= arm_reg_parse_any (q
);
9063 new_type
= arm_reg_parse_any (newname
);
9065 if (new_type
== REG_TYPE_MAX
)
9067 if (old_type
!= REG_TYPE_MAX
)
9069 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9070 insert_reg_alias (newname
, old_regno
,
9071 all_reg_maps
[old_type
].htab
);
9074 as_warn (_("register '%s' does not exist\n"), q
);
9076 else if (old_type
== REG_TYPE_MAX
)
9078 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9083 /* Do not warn about redefinitions to the same alias. */
9084 if (new_type
!= old_type
9085 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9086 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9087 as_warn (_("ignoring redefinition of register alias '%s'"),
9093 as_warn (_("ignoring incomplete .req pseuso op"));
9103 set_constant_flonums ()
9107 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9108 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9112 /* Iterate over the base tables to create the instruction patterns. */
9114 build_arm_ops_hsh ()
9118 static struct obstack insn_obstack
;
9120 obstack_begin (&insn_obstack
, 4000);
9122 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
9124 const struct asm_opcode
*insn
= insns
+ i
;
9126 if (insn
->cond_offset
!= 0)
9128 /* Insn supports conditional execution. Build the varaints
9129 and insert them in the hash table. */
9130 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
9132 unsigned len
= strlen (insn
->template);
9133 struct asm_opcode
*new;
9136 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
9137 /* All condition codes are two characters. */
9138 template = obstack_alloc (&insn_obstack
, len
+ 3);
9140 strncpy (template, insn
->template, insn
->cond_offset
);
9141 strcpy (template + insn
->cond_offset
, conds
[j
].template);
9142 if (len
> insn
->cond_offset
)
9143 strcpy (template + insn
->cond_offset
+ 2,
9144 insn
->template + insn
->cond_offset
);
9145 new->template = template;
9146 new->cond_offset
= 0;
9147 new->variant
= insn
->variant
;
9148 new->parms
= insn
->parms
;
9149 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
9151 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
9154 /* Finally, insert the unconditional insn in the table directly;
9155 no need to build a copy. */
9156 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
9166 if ( (arm_ops_hsh
= hash_new ()) == NULL
9167 || (arm_tops_hsh
= hash_new ()) == NULL
9168 || (arm_cond_hsh
= hash_new ()) == NULL
9169 || (arm_shift_hsh
= hash_new ()) == NULL
9170 || (arm_psr_hsh
= hash_new ()) == NULL
)
9171 as_fatal (_("virtual memory exhausted"));
9173 build_arm_ops_hsh ();
9174 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
9175 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
9176 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
9177 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
9178 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
9179 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
9180 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
9181 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
9183 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
9184 build_reg_hsh (all_reg_maps
+ i
);
9186 set_constant_flonums ();
9188 /* Set the cpu variant based on the command-line options. We prefer
9189 -mcpu= over -march= if both are set (as for GCC); and we prefer
9190 -mfpu= over any other way of setting the floating point unit.
9191 Use of legacy options with new options are faulted. */
9192 if (legacy_cpu
!= -1)
9194 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
9195 as_bad (_("use of old and new-style options to set CPU type"));
9197 mcpu_cpu_opt
= legacy_cpu
;
9199 else if (mcpu_cpu_opt
== -1)
9200 mcpu_cpu_opt
= march_cpu_opt
;
9202 if (legacy_fpu
!= -1)
9205 as_bad (_("use of old and new-style options to set FPU type"));
9207 mfpu_opt
= legacy_fpu
;
9209 else if (mfpu_opt
== -1)
9211 if (mcpu_fpu_opt
!= -1)
9212 mfpu_opt
= mcpu_fpu_opt
;
9214 mfpu_opt
= march_fpu_opt
;
9219 if (mcpu_cpu_opt
== -1)
9220 mfpu_opt
= FPU_DEFAULT
;
9221 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
9222 mfpu_opt
= FPU_ARCH_VFP_V2
;
9224 mfpu_opt
= FPU_ARCH_FPA
;
9227 if (mcpu_cpu_opt
== -1)
9228 mcpu_cpu_opt
= CPU_DEFAULT
;
9230 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
9232 #if defined OBJ_COFF || defined OBJ_ELF
9234 unsigned int flags
= 0;
9236 /* Set the flags in the private structure. */
9237 if (uses_apcs_26
) flags
|= F_APCS26
;
9238 if (support_interwork
) flags
|= F_INTERWORK
;
9239 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
9240 if (pic_code
) flags
|= F_PIC
;
9241 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
9242 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
9243 flags
|= F_SOFT_FLOAT
;
9244 /* Using VFP conventions (even if soft-float). */
9245 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
9248 bfd_set_private_flags (stdoutput
, flags
);
9250 /* We have run out flags in the COFF header to encode the
9251 status of ATPCS support, so instead we create a dummy,
9252 empty, debug section called .arm.atpcs. */
9257 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
9261 bfd_set_section_flags
9262 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
9263 bfd_set_section_size (stdoutput
, sec
, 0);
9264 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
9270 /* Record the CPU type as well. */
9271 switch (cpu_variant
& ARM_CPU_MASK
)
9274 mach
= bfd_mach_arm_2
;
9277 case ARM_3
: /* Also ARM_250. */
9278 mach
= bfd_mach_arm_2a
;
9281 case ARM_6
: /* Also ARM_7. */
9282 mach
= bfd_mach_arm_3
;
9286 mach
= bfd_mach_arm_4
;
9290 /* Catch special cases. */
9291 if (cpu_variant
& ARM_CEXT_XSCALE
)
9292 mach
= bfd_mach_arm_XScale
;
9293 else if (cpu_variant
& ARM_EXT_V5E
)
9294 mach
= bfd_mach_arm_5TE
;
9295 else if (cpu_variant
& ARM_EXT_V5
)
9297 if (cpu_variant
& ARM_EXT_V4T
)
9298 mach
= bfd_mach_arm_5T
;
9300 mach
= bfd_mach_arm_5
;
9302 else if (cpu_variant
& ARM_EXT_V4
)
9304 if (cpu_variant
& ARM_EXT_V4T
)
9305 mach
= bfd_mach_arm_4T
;
9307 mach
= bfd_mach_arm_4
;
9309 else if (cpu_variant
& ARM_EXT_V3M
)
9310 mach
= bfd_mach_arm_3M
;
9312 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
9315 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
9316 for use in the a.out file, and stores them in the array pointed to by buf.
9317 This knows about the endian-ness of the target machine and does
9318 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
9319 2 (short) and 4 (long) Floating numbers are put out as a series of
9320 LITTLENUMS (shorts, here at least). */
9323 md_number_to_chars (buf
, val
, n
)
9328 if (target_big_endian
)
9329 number_to_chars_bigendian (buf
, val
, n
);
9331 number_to_chars_littleendian (buf
, val
, n
);
9335 md_chars_to_number (buf
, n
)
9340 unsigned char * where
= (unsigned char *) buf
;
9342 if (target_big_endian
)
9347 result
|= (*where
++ & 255);
9355 result
|= (where
[n
] & 255);
9362 /* Turn a string in input_line_pointer into a floating point constant
9363 of type TYPE, and store the appropriate bytes in *LITP. The number
9364 of LITTLENUMS emitted is stored in *SIZEP. An error message is
9365 returned, or NULL on OK.
9367 Note that fp constants aren't represent in the normal way on the ARM.
9368 In big endian mode, things are as expected. However, in little endian
9369 mode fp constants are big-endian word-wise, and little-endian byte-wise
9370 within the words. For example, (double) 1.1 in big endian mode is
9371 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
9372 the byte sequence 99 99 f1 3f 9a 99 99 99.
9374 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
9377 md_atof (type
, litP
, sizeP
)
9383 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
9415 return _("bad call to MD_ATOF()");
9418 t
= atof_ieee (input_line_pointer
, type
, words
);
9420 input_line_pointer
= t
;
9423 if (target_big_endian
)
9425 for (i
= 0; i
< prec
; i
++)
9427 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
9433 if (cpu_variant
& FPU_ARCH_VFP
)
9434 for (i
= prec
- 1; i
>= 0; i
--)
9436 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
9440 /* For a 4 byte float the order of elements in `words' is 1 0.
9441 For an 8 byte float the order is 1 0 3 2. */
9442 for (i
= 0; i
< prec
; i
+= 2)
9444 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
9445 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
9453 /* The knowledge of the PC's pipeline offset is built into the insns
9457 md_pcrel_from (fixP
)
9461 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
9462 && fixP
->fx_subsy
== NULL
)
9465 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
9467 /* PC relative addressing on the Thumb is slightly odd
9468 as the bottom two bits of the PC are forced to zero
9469 for the calculation. */
9470 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
9474 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
9475 so we un-adjust here to compensate for the accomodation. */
9476 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
9478 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
9482 /* Round up a section size to the appropriate boundary. */
9485 md_section_align (segment
, size
)
9486 segT segment ATTRIBUTE_UNUSED
;
9492 /* Round all sects to multiple of 4. */
9493 return (size
+ 3) & ~3;
9497 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
9498 Otherwise we have no need to default values of symbols. */
9501 md_undefined_symbol (name
)
9502 char * name ATTRIBUTE_UNUSED
;
9505 if (name
[0] == '_' && name
[1] == 'G'
9506 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
9510 if (symbol_find (name
))
9511 as_bad ("GOT already in the symbol table");
9513 GOT_symbol
= symbol_new (name
, undefined_section
,
9514 (valueT
) 0, & zero_address_frag
);
9524 /* arm_reg_parse () := if it looks like a register, return its token and
9525 advance the pointer. */
9528 arm_reg_parse (ccp
, htab
)
9529 register char ** ccp
;
9530 struct hash_control
*htab
;
9532 char * start
= * ccp
;
9535 struct reg_entry
* reg
;
9537 #ifdef REGISTER_PREFIX
9538 if (*start
!= REGISTER_PREFIX
)
9543 #ifdef OPTIONAL_REGISTER_PREFIX
9544 if (*p
== OPTIONAL_REGISTER_PREFIX
)
9548 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
9552 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
9556 reg
= (struct reg_entry
*) hash_find (htab
, start
);
9568 /* Search for the following register name in each of the possible reg name
9569 tables. Return the classification if found, or REG_TYPE_MAX if not
9571 static enum arm_reg_type
9572 arm_reg_parse_any (cp
)
9577 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
9578 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
9579 return (enum arm_reg_type
) i
;
9581 return REG_TYPE_MAX
;
9585 md_apply_fix3 (fixP
, valP
, seg
)
9590 offsetT value
= * valP
;
9592 unsigned int newimm
;
9595 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
9596 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
9598 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
9600 /* Note whether this will delete the relocation. */
9602 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
9603 doesn't work fully.) */
9604 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
9607 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
9611 /* If this symbol is in a different section then we need to leave it for
9612 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
9613 so we have to undo it's effects here. */
9616 if (fixP
->fx_addsy
!= NULL
9617 && S_IS_DEFINED (fixP
->fx_addsy
)
9618 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
9621 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
9622 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
9626 value
+= md_pcrel_from (fixP
);
9630 /* Remember value for emit_reloc. */
9631 fixP
->fx_addnumber
= value
;
9633 switch (fixP
->fx_r_type
)
9635 case BFD_RELOC_ARM_IMMEDIATE
:
9636 newimm
= validate_immediate (value
);
9637 temp
= md_chars_to_number (buf
, INSN_SIZE
);
9639 /* If the instruction will fail, see if we can fix things up by
9640 changing the opcode. */
9641 if (newimm
== (unsigned int) FAIL
9642 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
9644 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9645 _("invalid constant (%lx) after fixup"),
9646 (unsigned long) value
);
9650 newimm
|= (temp
& 0xfffff000);
9651 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
9654 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
9656 unsigned int highpart
= 0;
9657 unsigned int newinsn
= 0xe1a00000; /* nop. */
9658 newimm
= validate_immediate (value
);
9659 temp
= md_chars_to_number (buf
, INSN_SIZE
);
9661 /* If the instruction will fail, see if we can fix things up by
9662 changing the opcode. */
9663 if (newimm
== (unsigned int) FAIL
9664 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
9666 /* No ? OK - try using two ADD instructions to generate
9668 newimm
= validate_immediate_twopart (value
, & highpart
);
9670 /* Yes - then make sure that the second instruction is
9672 if (newimm
!= (unsigned int) FAIL
)
9674 /* Still No ? Try using a negated value. */
9675 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
9676 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
9677 /* Otherwise - give up. */
9680 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9681 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
9686 /* Replace the first operand in the 2nd instruction (which
9687 is the PC) with the destination register. We have
9688 already added in the PC in the first instruction and we
9689 do not want to do it again. */
9690 newinsn
&= ~ 0xf0000;
9691 newinsn
|= ((newinsn
& 0x0f000) << 4);
9694 newimm
|= (temp
& 0xfffff000);
9695 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
9697 highpart
|= (newinsn
& 0xfffff000);
9698 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
9702 case BFD_RELOC_ARM_OFFSET_IMM
:
9708 if (validate_offset_imm (value
, 0) == FAIL
)
9710 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9711 _("bad immediate value for offset (%ld)"),
9716 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9717 newval
&= 0xff7ff000;
9718 newval
|= value
| (sign
? INDEX_UP
: 0);
9719 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9722 case BFD_RELOC_ARM_OFFSET_IMM8
:
9723 case BFD_RELOC_ARM_HWLITERAL
:
9729 if (validate_offset_imm (value
, 1) == FAIL
)
9731 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
9732 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9733 _("invalid literal constant: pool needs to be closer"));
9735 as_bad (_("bad immediate value for half-word offset (%ld)"),
9740 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9741 newval
&= 0xff7ff0f0;
9742 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
9743 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9746 case BFD_RELOC_ARM_LITERAL
:
9752 if (validate_offset_imm (value
, 0) == FAIL
)
9754 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9755 _("invalid literal constant: pool needs to be closer"));
9759 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9760 newval
&= 0xff7ff000;
9761 newval
|= value
| (sign
? INDEX_UP
: 0);
9762 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9765 case BFD_RELOC_ARM_SHIFT_IMM
:
9766 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9767 if (((unsigned long) value
) > 32
9769 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
9771 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9772 _("shift expression is too large"));
9777 /* Shifts of zero must be done as lsl. */
9779 else if (value
== 32)
9781 newval
&= 0xfffff07f;
9782 newval
|= (value
& 0x1f) << 7;
9783 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9786 case BFD_RELOC_ARM_SWI
:
9787 if (arm_data
->thumb_mode
)
9789 if (((unsigned long) value
) > 0xff)
9790 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9791 _("invalid swi expression"));
9792 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
9794 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9798 if (((unsigned long) value
) > 0x00ffffff)
9799 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9800 _("invalid swi expression"));
9801 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
9803 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9807 case BFD_RELOC_ARM_MULTI
:
9808 if (((unsigned long) value
) > 0xffff)
9809 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9810 _("invalid expression in load/store multiple"));
9811 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
9812 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9815 case BFD_RELOC_ARM_PCREL_BRANCH
:
9816 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9818 /* Sign-extend a 24-bit number. */
9819 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
9823 value
= fixP
->fx_offset
;
9826 /* We are going to store value (shifted right by two) in the
9827 instruction, in a 24 bit, signed field. Thus we need to check
9828 that none of the top 8 bits of the shifted value (top 7 bits of
9829 the unshifted, unsigned value) are set, or that they are all set. */
9830 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
9831 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
9834 /* Normally we would be stuck at this point, since we cannot store
9835 the absolute address that is the destination of the branch in the
9836 24 bits of the branch instruction. If however, we happen to know
9837 that the destination of the branch is in the same section as the
9838 branch instruciton itself, then we can compute the relocation for
9839 ourselves and not have to bother the linker with it.
9841 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
9842 because I have not worked out how to do this for OBJ_COFF or
9845 && fixP
->fx_addsy
!= NULL
9846 && S_IS_DEFINED (fixP
->fx_addsy
)
9847 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
9849 /* Get pc relative value to go into the branch. */
9852 /* Permit a backward branch provided that enough bits
9853 are set. Allow a forwards branch, provided that
9854 enough bits are clear. */
9855 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
9856 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
9860 if (! fixP
->fx_done
)
9862 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9863 _("GAS can't handle same-section branch dest >= 0x04000000"));
9867 value
+= SEXT24 (newval
);
9869 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
9870 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
9871 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9872 _("out of range branch"));
9874 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
9875 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9878 case BFD_RELOC_ARM_PCREL_BLX
:
9881 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9885 value
= fixP
->fx_offset
;
9887 hbit
= (value
>> 1) & 1;
9888 value
= (value
>> 2) & 0x00ffffff;
9889 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
9890 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
9891 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9895 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
9896 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9898 addressT diff
= (newval
& 0xff) << 1;
9903 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
9904 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9905 _("branch out of range"));
9906 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
9908 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9911 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
9912 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9914 addressT diff
= (newval
& 0x7ff) << 1;
9919 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
9920 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9921 _("branch out of range"));
9922 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
9924 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9927 case BFD_RELOC_THUMB_PCREL_BLX
:
9928 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
9933 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9934 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
9935 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
9936 if (diff
& 0x400000)
9939 value
= fixP
->fx_offset
;
9943 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
9944 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9945 _("branch with link out of range"));
9947 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
9948 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
9949 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
9950 /* For a BLX instruction, make sure that the relocation is rounded up
9951 to a word boundary. This follows the semantics of the instruction
9952 which specifies that bit 1 of the target address will come from bit
9953 1 of the base address. */
9954 newval2
= (newval2
+ 1) & ~ 1;
9955 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9956 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
9961 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9962 md_number_to_chars (buf
, value
, 1);
9964 else if (!target_oabi
)
9966 value
= fixP
->fx_offset
;
9967 md_number_to_chars (buf
, value
, 1);
9973 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9974 md_number_to_chars (buf
, value
, 2);
9976 else if (!target_oabi
)
9978 value
= fixP
->fx_offset
;
9979 md_number_to_chars (buf
, value
, 2);
9985 case BFD_RELOC_ARM_GOT32
:
9986 case BFD_RELOC_ARM_GOTOFF
:
9987 md_number_to_chars (buf
, 0, 4);
9993 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9994 md_number_to_chars (buf
, value
, 4);
9996 else if (!target_oabi
)
9998 value
= fixP
->fx_offset
;
9999 md_number_to_chars (buf
, value
, 4);
10005 case BFD_RELOC_ARM_PLT32
:
10006 /* It appears the instruction is fully prepared at this point. */
10010 case BFD_RELOC_ARM_GOTPC
:
10011 md_number_to_chars (buf
, value
, 4);
10014 case BFD_RELOC_ARM_CP_OFF_IMM
:
10016 if (value
< -1023 || value
> 1023 || (value
& 3))
10017 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10018 _("illegal value for co-processor offset"));
10021 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
10022 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
10023 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10026 case BFD_RELOC_ARM_THUMB_OFFSET
:
10027 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10028 /* Exactly what ranges, and where the offset is inserted depends
10029 on the type of instruction, we can establish this from the
10031 switch (newval
>> 12)
10033 case 4: /* PC load. */
10034 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
10035 forced to zero for these loads, so we will need to round
10036 up the offset if the instruction address is not word
10037 aligned (since the final address produced must be, and
10038 we can only describe word-aligned immediate offsets). */
10040 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
10041 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10042 _("invalid offset, target not word aligned (0x%08X)"),
10043 (unsigned int) (fixP
->fx_frag
->fr_address
10044 + fixP
->fx_where
+ value
));
10046 if ((value
+ 2) & ~0x3fe)
10047 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10048 _("invalid offset, value too big (0x%08lX)"), value
);
10050 /* Round up, since pc will be rounded down. */
10051 newval
|= (value
+ 2) >> 2;
10054 case 9: /* SP load/store. */
10055 if (value
& ~0x3fc)
10056 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10057 _("invalid offset, value too big (0x%08lX)"), value
);
10058 newval
|= value
>> 2;
10061 case 6: /* Word load/store. */
10063 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10064 _("invalid offset, value too big (0x%08lX)"), value
);
10065 newval
|= value
<< 4; /* 6 - 2. */
10068 case 7: /* Byte load/store. */
10070 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10071 _("invalid offset, value too big (0x%08lX)"), value
);
10072 newval
|= value
<< 6;
10075 case 8: /* Halfword load/store. */
10077 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10078 _("invalid offset, value too big (0x%08lX)"), value
);
10079 newval
|= value
<< 5; /* 6 - 1. */
10083 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10084 "Unable to process relocation for thumb opcode: %lx",
10085 (unsigned long) newval
);
10088 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10091 case BFD_RELOC_ARM_THUMB_ADD
:
10092 /* This is a complicated relocation, since we use it for all of
10093 the following immediate relocations:
10097 9bit ADD/SUB SP word-aligned
10098 10bit ADD PC/SP word-aligned
10100 The type of instruction being processed is encoded in the
10107 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10109 int rd
= (newval
>> 4) & 0xf;
10110 int rs
= newval
& 0xf;
10111 int subtract
= newval
& 0x8000;
10115 if (value
& ~0x1fc)
10116 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10117 _("invalid immediate for stack address calculation"));
10118 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
10119 newval
|= value
>> 2;
10121 else if (rs
== REG_PC
|| rs
== REG_SP
)
10125 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10126 _("invalid immediate for address calculation (value = 0x%08lX)"),
10127 (unsigned long) value
);
10128 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
10130 newval
|= value
>> 2;
10135 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10136 _("invalid 8bit immediate"));
10137 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
10138 newval
|= (rd
<< 8) | value
;
10143 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10144 _("invalid 3bit immediate"));
10145 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
10146 newval
|= rd
| (rs
<< 3) | (value
<< 6);
10149 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10152 case BFD_RELOC_ARM_THUMB_IMM
:
10153 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10154 switch (newval
>> 11)
10156 case 0x04: /* 8bit immediate MOV. */
10157 case 0x05: /* 8bit immediate CMP. */
10158 if (value
< 0 || value
> 255)
10159 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10160 _("invalid immediate: %ld is too large"),
10168 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10171 case BFD_RELOC_ARM_THUMB_SHIFT
:
10172 /* 5bit shift value (0..31). */
10173 if (value
< 0 || value
> 31)
10174 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10175 _("illegal Thumb shift value: %ld"), (long) value
);
10176 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
10177 newval
|= value
<< 6;
10178 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10181 case BFD_RELOC_VTABLE_INHERIT
:
10182 case BFD_RELOC_VTABLE_ENTRY
:
10186 case BFD_RELOC_NONE
:
10188 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10189 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
10193 /* Translate internal representation of relocation info to BFD target
10197 tc_gen_reloc (section
, fixp
)
10198 asection
* section ATTRIBUTE_UNUSED
;
10202 bfd_reloc_code_real_type code
;
10204 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
10206 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
10207 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
10208 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
10210 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
10212 if (fixp
->fx_pcrel
== 0)
10213 reloc
->addend
= fixp
->fx_offset
;
10215 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
10216 #else /* OBJ_ELF */
10217 reloc
->addend
= fixp
->fx_offset
;
10220 switch (fixp
->fx_r_type
)
10223 if (fixp
->fx_pcrel
)
10225 code
= BFD_RELOC_8_PCREL
;
10230 if (fixp
->fx_pcrel
)
10232 code
= BFD_RELOC_16_PCREL
;
10237 if (fixp
->fx_pcrel
)
10239 code
= BFD_RELOC_32_PCREL
;
10243 case BFD_RELOC_ARM_PCREL_BRANCH
:
10244 case BFD_RELOC_ARM_PCREL_BLX
:
10245 case BFD_RELOC_RVA
:
10246 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
10247 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
10248 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
10249 case BFD_RELOC_THUMB_PCREL_BLX
:
10250 case BFD_RELOC_VTABLE_ENTRY
:
10251 case BFD_RELOC_VTABLE_INHERIT
:
10252 code
= fixp
->fx_r_type
;
10255 case BFD_RELOC_ARM_LITERAL
:
10256 case BFD_RELOC_ARM_HWLITERAL
:
10257 /* If this is called then the a literal has been referenced across
10258 a section boundary - possibly due to an implicit dump. */
10259 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10260 _("literal referenced across section boundary (Implicit dump?)"));
10264 case BFD_RELOC_ARM_GOT32
:
10265 case BFD_RELOC_ARM_GOTOFF
:
10266 case BFD_RELOC_ARM_PLT32
:
10267 code
= fixp
->fx_r_type
;
10271 case BFD_RELOC_ARM_IMMEDIATE
:
10272 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10273 _("internal relocation (type %d) not fixed up (IMMEDIATE)"),
10277 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10278 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10279 _("ADRL used for a symbol not defined in the same file"));
10282 case BFD_RELOC_ARM_OFFSET_IMM
:
10283 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10284 _("internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
10292 switch (fixp
->fx_r_type
)
10294 case BFD_RELOC_ARM_IMMEDIATE
: type
= "IMMEDIATE"; break;
10295 case BFD_RELOC_ARM_OFFSET_IMM
: type
= "OFFSET_IMM"; break;
10296 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
10297 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
10298 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
10299 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
10300 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
10301 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
10302 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
10303 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
10304 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
10305 default: type
= _("<unknown>"); break;
10307 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10308 _("cannot represent %s relocation in this object file format"),
10315 if (code
== BFD_RELOC_32_PCREL
10317 && fixp
->fx_addsy
== GOT_symbol
)
10319 code
= BFD_RELOC_ARM_GOTPC
;
10320 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
10324 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
10326 if (reloc
->howto
== NULL
)
10328 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10329 _("cannot represent %s relocation in this object file format"),
10330 bfd_get_reloc_code_name (code
));
10334 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
10335 vtable entry to be used in the relocation's section offset. */
10336 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
10337 reloc
->address
= fixp
->fx_offset
;
10343 md_estimate_size_before_relax (fragP
, segtype
)
10344 fragS
* fragP ATTRIBUTE_UNUSED
;
10345 segT segtype ATTRIBUTE_UNUSED
;
10347 as_fatal (_("md_estimate_size_before_relax\n"));
10359 as_bad ("%s -- `%s'", inst
.error
, str
);
10363 to
= frag_more (inst
.size
);
10365 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
10367 assert (inst
.size
== (2 * THUMB_SIZE
));
10368 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
10369 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
10371 else if (inst
.size
> INSN_SIZE
)
10373 assert (inst
.size
== (2 * INSN_SIZE
));
10374 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
10375 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
10378 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
10380 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
10381 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
10382 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
10386 dwarf2_emit_insn (inst
.size
);
10398 /* Align the instruction.
10399 This may not be the right thing to do but ... */
10404 /* Align the previous label if needed. */
10405 if (last_label_seen
!= NULL
)
10407 symbol_set_frag (last_label_seen
, frag_now
);
10408 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
10409 S_SET_SEGMENT (last_label_seen
, now_seg
);
10412 memset (&inst
, '\0', sizeof (inst
));
10413 inst
.reloc
.type
= BFD_RELOC_NONE
;
10415 skip_whitespace (str
);
10417 /* Scan up to the end of the op-code, which must end in white space or
10419 for (start
= p
= str
; *p
!= '\0'; p
++)
10425 as_bad (_("no operator -- statement `%s'\n"), str
);
10431 const struct thumb_opcode
* opcode
;
10435 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
10440 /* Check that this instruction is supported for this CPU. */
10441 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
10443 as_bad (_("selected processor does not support `%s'"), str
);
10447 inst
.instruction
= opcode
->value
;
10448 inst
.size
= opcode
->size
;
10449 (*opcode
->parms
) (p
);
10456 const struct asm_opcode
* opcode
;
10460 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
10465 /* Check that this instruction is supported for this CPU. */
10466 if ((opcode
->variant
& cpu_variant
) == 0)
10468 as_bad (_("selected processor does not support `%s'"), str
);
10472 inst
.instruction
= opcode
->value
;
10473 inst
.size
= INSN_SIZE
;
10474 (*opcode
->parms
) (p
);
10480 /* It wasn't an instruction, but it might be a register alias of the form
10482 if (create_register_alias (str
, p
))
10485 as_bad (_("bad instruction `%s'"), start
);
10489 Invocation line includes a switch not recognized by the base assembler.
10490 See if it's a processor-specific option.
10492 This routine is somewhat complicated by the need for backwards
10493 compatibility (since older releases of gcc can't be changed).
10494 The new options try to make the interface as compatible as
10497 New options (supported) are:
10499 -mcpu=<cpu name> Assemble for selected processor
10500 -march=<architecture name> Assemble for selected architecture
10501 -mfpu=<fpu architecture> Assemble for selected FPU.
10502 -EB/-mbig-endian Big-endian
10503 -EL/-mlittle-endian Little-endian
10504 -k Generate PIC code
10505 -mthumb Start in Thumb mode
10506 -mthumb-interwork Code supports ARM/Thumb interworking
10508 For now we will also provide support for
10510 -mapcs-32 32-bit Program counter
10511 -mapcs-26 26-bit Program counter
10512 -macps-float Floats passed in FP registers
10513 -mapcs-reentrant Reentrant code
10515 (sometime these will probably be replaced with -mapcs=<list of options>
10516 and -matpcs=<list of options>)
10518 The remaining options are only supported for back-wards compatibility.
10519 Cpu variants, the arm part is optional:
10520 -m[arm]1 Currently not supported.
10521 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
10522 -m[arm]3 Arm 3 processor
10523 -m[arm]6[xx], Arm 6 processors
10524 -m[arm]7[xx][t][[d]m] Arm 7 processors
10525 -m[arm]8[10] Arm 8 processors
10526 -m[arm]9[20][tdmi] Arm 9 processors
10527 -mstrongarm[110[0]] StrongARM processors
10528 -mxscale XScale processors
10529 -m[arm]v[2345[t[e]]] Arm architectures
10530 -mall All (except the ARM1)
10532 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
10533 -mfpe-old (No float load/store multiples)
10534 -mvfpxd VFP Single precision
10536 -mno-fpu Disable all floating point instructions
10538 The following CPU names are recognized:
10539 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
10540 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
10541 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
10542 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
10543 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
10544 arm10t arm10e, arm1020t, arm1020e, arm10200e,
10545 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
10549 CONST
char * md_shortopts
= "m:k";
10551 #ifdef ARM_BI_ENDIAN
10552 #define OPTION_EB (OPTION_MD_BASE + 0)
10553 #define OPTION_EL (OPTION_MD_BASE + 1)
10555 #if TARGET_BYTES_BIG_ENDIAN
10556 #define OPTION_EB (OPTION_MD_BASE + 0)
10558 #define OPTION_EL (OPTION_MD_BASE + 1)
10562 struct option md_longopts
[] =
10565 {"EB", no_argument
, NULL
, OPTION_EB
},
10568 {"EL", no_argument
, NULL
, OPTION_EL
},
10570 {NULL
, no_argument
, NULL
, 0}
10573 size_t md_longopts_size
= sizeof (md_longopts
);
10575 struct arm_option_table
10577 char *option
; /* Option name to match. */
10578 char *help
; /* Help information. */
10579 int *var
; /* Variable to change. */
10580 int value
; /* What to change it to. */
10581 char *deprecated
; /* If non-null, print this message. */
10584 struct arm_option_table arm_opts
[] =
10586 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
10587 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
10588 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
10589 &support_interwork
, 1, NULL
},
10590 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
10591 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
10592 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
10593 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
10595 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
10596 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
10597 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
10598 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
10601 /* These are recognized by the assembler, but have no affect on code. */
10602 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
10603 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
10605 /* DON'T add any new processors to this list -- we want the whole list
10606 to go away... Add them to the processors table instead. */
10607 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
10608 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
10609 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
10610 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
10611 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
10612 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
10613 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
10614 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
10615 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
10616 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
10617 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
10618 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
10619 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
10620 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
10621 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
10622 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
10623 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
10624 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
10625 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
10626 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
10627 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
10628 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
10629 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
10630 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
10631 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
10632 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
10633 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
10634 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
10635 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
10636 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
10637 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
10638 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
10639 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
10640 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
10641 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
10642 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
10643 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
10644 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
10645 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
10646 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
10647 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
10648 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
10649 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
10650 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
10651 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
10652 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
10653 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10654 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10655 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10656 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10657 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
10658 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
10659 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
10660 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
10661 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
10662 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
10663 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
10664 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
10665 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
10666 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
10667 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
10668 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
10669 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
10670 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
10671 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
10672 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
10673 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
10674 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
10675 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
10676 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10677 N_("use -mcpu=strongarm110")},
10678 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10679 N_("use -mcpu=strongarm1100")},
10680 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10681 N_("use -mcpu=strongarm1110")},
10682 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
10683 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
10685 /* Architecture variants -- don't add any more to this list either. */
10686 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
10687 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
10688 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
10689 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
10690 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
10691 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
10692 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
10693 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
10694 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
10695 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
10696 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
10697 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
10698 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
10699 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
10700 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
10701 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
10702 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
10703 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
10705 /* Floating point variants -- don't add any more to this list either. */
10706 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
10707 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
10708 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
10709 {"mno-fpu", NULL
, &legacy_fpu
, 0,
10710 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
10712 {NULL
, NULL
, NULL
, 0, NULL
}
10715 struct arm_cpu_option_table
10719 /* For some CPUs we assume an FPU unless the user explicitly sets
10724 /* This list should, at a minimum, contain all the cpu names
10725 recognized by GCC. */
10726 static struct arm_cpu_option_table arm_cpus
[] =
10728 {"all", ARM_ANY
, FPU_ARCH_FPA
},
10729 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
10730 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
10731 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10732 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10733 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10734 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10735 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10736 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10737 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10738 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10739 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10740 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10741 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10742 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10743 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10744 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10745 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10746 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10747 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10748 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10749 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10750 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10751 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10752 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10753 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10754 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10755 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10756 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10757 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10758 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10759 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10760 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10761 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10762 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10763 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10764 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10765 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10766 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10767 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10768 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10769 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10770 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10771 /* For V5 or later processors we default to using VFP; but the user
10772 should really set the FPU type explicitly. */
10773 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10774 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10775 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
10776 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10777 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10778 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10779 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10780 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
10781 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10782 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10783 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
10784 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10785 /* ??? XSCALE is really an architecture. */
10786 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
10787 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
10789 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
10793 struct arm_arch_option_table
10800 /* This list should, at a minimum, contain all the architecture names
10801 recognized by GCC. */
10802 static struct arm_arch_option_table arm_archs
[] =
10804 {"all", ARM_ANY
, FPU_ARCH_FPA
},
10805 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
10806 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
10807 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10808 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10809 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10810 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10811 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10812 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
10813 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10814 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
10815 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
10816 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
10817 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
10818 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
10819 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
10820 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
10821 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
10825 /* ISA extensions in the co-processor space. */
10826 struct arm_arch_extension_table
10832 static struct arm_arch_extension_table arm_extensions
[] =
10834 {"maverick", ARM_CEXT_MAVERICK
},
10835 {"xscale", ARM_CEXT_XSCALE
},
10839 struct arm_fpu_option_table
10845 /* This list should, at a minimum, contain all the fpu names
10846 recognized by GCC. */
10847 static struct arm_fpu_option_table arm_fpus
[] =
10849 {"softfpa", FPU_NONE
},
10850 {"fpe", FPU_ARCH_FPE
},
10851 {"fpe2", FPU_ARCH_FPE
},
10852 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
10853 {"fpa", FPU_ARCH_FPA
},
10854 {"fpa10", FPU_ARCH_FPA
},
10855 {"fpa11", FPU_ARCH_FPA
},
10856 {"arm7500fe", FPU_ARCH_FPA
},
10857 {"softvfp", FPU_ARCH_VFP
},
10858 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
10859 {"vfp", FPU_ARCH_VFP_V2
},
10860 {"vfp9", FPU_ARCH_VFP_V2
},
10861 {"vfp10", FPU_ARCH_VFP_V2
},
10862 {"vfp10-r0", FPU_ARCH_VFP_V1
},
10863 {"vfpxd", FPU_ARCH_VFP_V1xD
},
10864 {"arm1020t", FPU_ARCH_VFP_V1
},
10865 {"arm1020e", FPU_ARCH_VFP_V2
},
10869 struct arm_long_option_table
10871 char *option
; /* Substring to match. */
10872 char *help
; /* Help information. */
10873 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
10874 char *deprecated
; /* If non-null, print this message. */
10878 arm_parse_extension (str
, opt_p
)
10882 while (str
!= NULL
&& *str
!= 0)
10884 struct arm_arch_extension_table
*opt
;
10890 as_bad (_("invalid architectural extension"));
10895 ext
= strchr (str
, '+');
10898 optlen
= ext
- str
;
10900 optlen
= strlen (str
);
10904 as_bad (_("missing architectural extension"));
10908 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
10909 if (strncmp (opt
->name
, str
, optlen
) == 0)
10911 *opt_p
|= opt
->value
;
10915 if (opt
->name
== NULL
)
10917 as_bad (_("unknown architectural extnsion `%s'"), str
);
10928 arm_parse_cpu (str
)
10931 struct arm_cpu_option_table
*opt
;
10932 char *ext
= strchr (str
, '+');
10936 optlen
= ext
- str
;
10938 optlen
= strlen (str
);
10942 as_bad (_("missing cpu name `%s'"), str
);
10946 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
10947 if (strncmp (opt
->name
, str
, optlen
) == 0)
10949 mcpu_cpu_opt
= opt
->value
;
10950 mcpu_fpu_opt
= opt
->default_fpu
;
10953 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
10958 as_bad (_("unknown cpu `%s'"), str
);
10963 arm_parse_arch (str
)
10966 struct arm_arch_option_table
*opt
;
10967 char *ext
= strchr (str
, '+');
10971 optlen
= ext
- str
;
10973 optlen
= strlen (str
);
10977 as_bad (_("missing architecture name `%s'"), str
);
10982 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
10983 if (strcmp (opt
->name
, str
) == 0)
10985 march_cpu_opt
= opt
->value
;
10986 march_fpu_opt
= opt
->default_fpu
;
10989 return arm_parse_extension (ext
, &march_cpu_opt
);
10994 as_bad (_("unknown architecture `%s'\n"), str
);
10999 arm_parse_fpu (str
)
11002 struct arm_fpu_option_table
*opt
;
11004 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
11005 if (strcmp (opt
->name
, str
) == 0)
11007 mfpu_opt
= opt
->value
;
11011 as_bad (_("unknown floating point format `%s'\n"), str
);
11015 struct arm_long_option_table arm_long_opts
[] =
11017 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
11018 arm_parse_cpu
, NULL
},
11019 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
11020 arm_parse_arch
, NULL
},
11021 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
11022 arm_parse_fpu
, NULL
},
11023 {NULL
, NULL
, 0, NULL
}
11027 md_parse_option (c
, arg
)
11031 struct arm_option_table
*opt
;
11032 struct arm_long_option_table
*lopt
;
11038 target_big_endian
= 1;
11044 target_big_endian
= 0;
11049 /* Listing option. Just ignore these, we don't support additional
11054 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
11056 if (c
== opt
->option
[0]
11057 && ((arg
== NULL
&& opt
->option
[1] == 0)
11058 || strcmp (arg
, opt
->option
+ 1) == 0))
11060 #if WARN_DEPRECATED
11061 /* If the option is deprecated, tell the user. */
11062 if (opt
->deprecated
!= NULL
)
11063 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
11064 arg
? arg
: "", _(opt
->deprecated
));
11067 if (opt
->var
!= NULL
)
11068 *opt
->var
= opt
->value
;
11074 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
11076 /* These options are expected to have an argument. */
11077 if (c
== lopt
->option
[0]
11079 && strncmp (arg
, lopt
->option
+ 1,
11080 strlen (lopt
->option
+ 1)) == 0)
11082 #if WARN_DEPRECATED
11083 /* If the option is deprecated, tell the user. */
11084 if (lopt
->deprecated
!= NULL
)
11085 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
11086 _(lopt
->deprecated
));
11089 /* Call the sup-option parser. */
11090 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
11094 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
11105 struct arm_option_table
*opt
;
11106 struct arm_long_option_table
*lopt
;
11108 fprintf (fp
, _(" ARM-specific assembler options:\n"));
11110 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
11111 if (opt
->help
!= NULL
)
11112 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
11114 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
11115 if (lopt
->help
!= NULL
)
11116 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
11120 -EB assemble code for a big-endian cpu\n"));
11125 -EL assemble code for a little-endian cpu\n"));
11129 /* We need to be able to fix up arbitrary expressions in some statements.
11130 This is so that we can handle symbols that are an arbitrary distance from
11131 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
11132 which returns part of an address in a form which will be valid for
11133 a data instruction. We do this by pushing the expression into a symbol
11134 in the expr_section, and creating a fix for that. */
11137 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
11146 arm_fix_data
* arm_data
;
11154 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
11158 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
11163 /* Mark whether the fix is to a THUMB instruction, or an ARM
11165 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
11166 new_fix
->tc_fix_data
= (PTR
) arm_data
;
11167 arm_data
->thumb_mode
= thumb_mode
;
11172 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
11175 cons_fix_new_arm (frag
, where
, size
, exp
)
11181 bfd_reloc_code_real_type type
;
11185 FIXME: @@ Should look at CPU word size. */
11189 type
= BFD_RELOC_8
;
11192 type
= BFD_RELOC_16
;
11196 type
= BFD_RELOC_32
;
11199 type
= BFD_RELOC_64
;
11203 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
11206 /* A good place to do this, although this was probably not intended
11207 for this kind of use. We need to dump the literal pool before
11208 references are made to a null symbol pointer. */
11213 if (current_poolP
== NULL
)
11216 /* Put it at the end of text section. */
11217 subseg_set (text_section
, 0);
11222 arm_start_line_hook ()
11224 last_label_seen
= NULL
;
11228 arm_frob_label (sym
)
11231 last_label_seen
= sym
;
11233 ARM_SET_THUMB (sym
, thumb_mode
);
11235 #if defined OBJ_COFF || defined OBJ_ELF
11236 ARM_SET_INTERWORK (sym
, support_interwork
);
11239 /* Note - do not allow local symbols (.Lxxx) to be labeled
11240 as Thumb functions. This is because these labels, whilst
11241 they exist inside Thumb code, are not the entry points for
11242 possible ARM->Thumb calls. Also, these labels can be used
11243 as part of a computed goto or switch statement. eg gcc
11244 can generate code that looks like this:
11246 ldr r2, [pc, .Laaa]
11256 The first instruction loads the address of the jump table.
11257 The second instruction converts a table index into a byte offset.
11258 The third instruction gets the jump address out of the table.
11259 The fourth instruction performs the jump.
11261 If the address stored at .Laaa is that of a symbol which has the
11262 Thumb_Func bit set, then the linker will arrange for this address
11263 to have the bottom bit set, which in turn would mean that the
11264 address computation performed by the third instruction would end
11265 up with the bottom bit set. Since the ARM is capable of unaligned
11266 word loads, the instruction would then load the incorrect address
11267 out of the jump table, and chaos would ensue. */
11268 if (label_is_thumb_function_name
11269 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
11270 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
11272 /* When the address of a Thumb function is taken the bottom
11273 bit of that address should be set. This will allow
11274 interworking between Arm and Thumb functions to work
11277 THUMB_SET_FUNC (sym
, 1);
11279 label_is_thumb_function_name
= false;
11283 /* Adjust the symbol table. This marks Thumb symbols as distinct from
11287 arm_adjust_symtab ()
11292 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
11294 if (ARM_IS_THUMB (sym
))
11296 if (THUMB_IS_FUNC (sym
))
11298 /* Mark the symbol as a Thumb function. */
11299 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
11300 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
11301 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
11303 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
11304 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
11306 as_bad (_("%s: unexpected function type: %d"),
11307 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
11309 else switch (S_GET_STORAGE_CLASS (sym
))
11312 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
11315 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
11318 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
11326 if (ARM_IS_INTERWORK (sym
))
11327 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
11334 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
11336 if (ARM_IS_THUMB (sym
))
11338 elf_symbol_type
* elf_sym
;
11340 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
11341 bind
= ELF_ST_BIND (elf_sym
);
11343 /* If it's a .thumb_func, declare it as so,
11344 otherwise tag label as .code 16. */
11345 if (THUMB_IS_FUNC (sym
))
11346 elf_sym
->internal_elf_sym
.st_info
=
11347 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
11349 elf_sym
->internal_elf_sym
.st_info
=
11350 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
11357 arm_data_in_code ()
11359 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
11361 *input_line_pointer
= '/';
11362 input_line_pointer
+= 5;
11363 *input_line_pointer
= 0;
11371 arm_canonicalize_symbol_name (name
)
11376 if (thumb_mode
&& (len
= strlen (name
)) > 5
11377 && streq (name
+ len
- 5, "/data"))
11378 *(name
+ len
- 5) = 0;
11384 arm_validate_fix (fixP
)
11387 /* If the destination of the branch is a defined symbol which does not have
11388 the THUMB_FUNC attribute, then we must be calling a function which has
11389 the (interfacearm) attribute. We look for the Thumb entry point to that
11390 function and change the branch to refer to that function instead. */
11391 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
11392 && fixP
->fx_addsy
!= NULL
11393 && S_IS_DEFINED (fixP
->fx_addsy
)
11394 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
11396 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
11404 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
11405 local labels from being added to the output symbol table when they
11406 are used with the ADRL pseudo op. The ADRL relocation should always
11407 be resolved before the binbary is emitted, so it is safe to say that
11408 it is adjustable. */
11411 arm_fix_adjustable (fixP
)
11414 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
11420 /* Relocations against Thumb function names must be left unadjusted,
11421 so that the linker can use this information to correctly set the
11422 bottom bit of their addresses. The MIPS version of this function
11423 also prevents relocations that are mips-16 specific, but I do not
11424 know why it does this.
11427 There is one other problem that ought to be addressed here, but
11428 which currently is not: Taking the address of a label (rather
11429 than a function) and then later jumping to that address. Such
11430 addresses also ought to have their bottom bit set (assuming that
11431 they reside in Thumb code), but at the moment they will not. */
11434 arm_fix_adjustable (fixP
)
11437 if (fixP
->fx_addsy
== NULL
)
11440 /* Prevent all adjustments to global symbols. */
11441 if (S_IS_EXTERN (fixP
->fx_addsy
))
11444 if (S_IS_WEAK (fixP
->fx_addsy
))
11447 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
11448 && fixP
->fx_subsy
== NULL
)
11451 /* We need the symbol name for the VTABLE entries. */
11452 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
11453 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11460 elf32_arm_target_format ()
11462 if (target_big_endian
)
11465 return "elf32-bigarm-oabi";
11467 return "elf32-bigarm";
11472 return "elf32-littlearm-oabi";
11474 return "elf32-littlearm";
11479 armelf_frob_symbol (symp
, puntp
)
11483 elf_frob_symbol (symp
, puntp
);
11487 arm_force_relocation (fixp
)
11490 if ( fixp
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
11491 || fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
11492 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11493 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11494 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
11495 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
11501 static bfd_reloc_code_real_type
11511 bfd_reloc_code_real_type reloc
;
11515 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
11516 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
11517 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
11518 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
11519 branch instructions generated by GCC for PLT relocs. */
11520 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
11521 { NULL
, 0, BFD_RELOC_UNUSED
}
11525 for (i
= 0, ip
= input_line_pointer
;
11526 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
11528 id
[i
] = TOLOWER (*ip
);
11530 for (i
= 0; reloc_map
[i
].str
; i
++)
11531 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
11534 input_line_pointer
+= reloc_map
[i
].len
;
11536 return reloc_map
[i
].reloc
;
11540 s_arm_elf_cons (nbytes
)
11545 #ifdef md_flush_pending_output
11546 md_flush_pending_output ();
11549 if (is_it_end_of_statement ())
11551 demand_empty_rest_of_line ();
11555 #ifdef md_cons_align
11556 md_cons_align (nbytes
);
11561 bfd_reloc_code_real_type reloc
;
11563 expression (& exp
);
11565 if (exp
.X_op
== O_symbol
11566 && * input_line_pointer
== '('
11567 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
11569 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
11570 int size
= bfd_get_reloc_size (howto
);
11573 as_bad ("%s relocations do not fit in %d bytes",
11574 howto
->name
, nbytes
);
11577 register char *p
= frag_more ((int) nbytes
);
11578 int offset
= nbytes
- size
;
11580 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
11585 emit_expr (&exp
, (unsigned int) nbytes
);
11587 while (*input_line_pointer
++ == ',');
11589 /* Put terminator back into stream. */
11590 input_line_pointer
--;
11591 demand_empty_rest_of_line ();
11594 #endif /* OBJ_ELF */
11596 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
11597 of an rs_align_code fragment. */
11600 arm_handle_align (fragP
)
11603 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
11604 static char const thumb_noop
[2] = { 0xc0, 0x46 };
11605 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
11606 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
11608 int bytes
, fix
, noop_size
;
11612 if (fragP
->fr_type
!= rs_align_code
)
11615 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
11616 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
11619 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
11620 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
11622 if (fragP
->tc_frag_data
)
11624 if (target_big_endian
)
11625 noop
= thumb_bigend_noop
;
11628 noop_size
= sizeof (thumb_noop
);
11632 if (target_big_endian
)
11633 noop
= arm_bigend_noop
;
11636 noop_size
= sizeof (arm_noop
);
11639 if (bytes
& (noop_size
- 1))
11641 fix
= bytes
& (noop_size
- 1);
11642 memset (p
, 0, fix
);
11647 while (bytes
>= noop_size
)
11649 memcpy (p
, noop
, noop_size
);
11651 bytes
-= noop_size
;
11655 fragP
->fr_fix
+= fix
;
11656 fragP
->fr_var
= noop_size
;
11659 /* Called from md_do_align. Used to create an alignment
11660 frag in a code section. */
11663 arm_frag_align_code (n
, max
)
11669 /* We assume that there will never be a requirment
11670 to support alignments greater than 32 bytes. */
11671 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
11672 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
11674 p
= frag_var (rs_align_code
,
11675 MAX_MEM_FOR_RS_ALIGN_CODE
,
11677 (relax_substateT
) max
,
11685 /* Perform target specific initialisation of a frag. */
11688 arm_init_frag (fragP
)
11691 /* Record whether this frag is in an ARM or a THUMB area. */
11692 fragP
->tc_frag_data
= thumb_mode
;