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));
2065 static void s_arm_elf_cons
PARAMS ((int));
2068 static int my_get_expression
PARAMS ((expressionS
*, char **));
2070 const pseudo_typeS md_pseudo_table
[] =
2072 /* Never called becasue '.req' does not start line. */
2073 { "req", s_req
, 0 },
2074 { "bss", s_bss
, 0 },
2075 { "align", s_align
, 0 },
2076 { "arm", s_arm
, 0 },
2077 { "thumb", s_thumb
, 0 },
2078 { "code", s_code
, 0 },
2079 { "force_thumb", s_force_thumb
, 0 },
2080 { "thumb_func", s_thumb_func
, 0 },
2081 { "thumb_set", s_thumb_set
, 0 },
2082 { "even", s_even
, 0 },
2083 { "ltorg", s_ltorg
, 0 },
2084 { "pool", s_ltorg
, 0 },
2086 { "word", s_arm_elf_cons
, 4 },
2087 { "long", s_arm_elf_cons
, 4 },
2088 { "file", (void (*) PARAMS ((int))) dwarf2_directive_file
, 0 },
2089 { "loc", dwarf2_directive_loc
, 0 },
2093 { "extend", float_cons
, 'x' },
2094 { "ldouble", float_cons
, 'x' },
2095 { "packed", float_cons
, 'p' },
2099 /* Other internal functions. */
2100 static int arm_parse_extension
PARAMS ((char *, int *));
2101 static int arm_parse_cpu
PARAMS ((char *));
2102 static int arm_parse_arch
PARAMS ((char *));
2103 static int arm_parse_fpu
PARAMS ((char *));
2105 /* Stuff needed to resolve the label ambiguity
2115 symbolS
* last_label_seen
;
2116 static int label_is_thumb_function_name
= false;
2118 /* Literal Pool stuff. */
2120 #define MAX_LITERAL_POOL_SIZE 1024
2122 /* Literal pool structure. Held on a per-section
2123 and per-sub-section basis. */
2124 typedef struct literal_pool
2126 expressionS literals
[MAX_LITERAL_POOL_SIZE
];
2127 unsigned int next_free_entry
;
2131 subsegT sub_section
;
2132 struct literal_pool
* next
;
2135 /* Pointer to a linked list of literal pools. */
2136 literal_pool
* list_of_pools
= NULL
;
2138 static literal_pool
* find_literal_pool
PARAMS ((void));
2139 static literal_pool
* find_or_make_literal_pool
PARAMS ((void));
2141 static literal_pool
*
2142 find_literal_pool ()
2144 literal_pool
* pool
;
2146 for (pool
= list_of_pools
; pool
!= NULL
; pool
= pool
->next
)
2148 if (pool
->section
== now_seg
2149 && pool
->sub_section
== now_subseg
)
2156 static literal_pool
*
2157 find_or_make_literal_pool ()
2159 /* Next literal pool ID number. */
2160 static unsigned int latest_pool_num
= 1;
2161 literal_pool
* pool
;
2163 pool
= find_literal_pool ();
2167 /* Create a new pool. */
2168 pool
= (literal_pool
*) xmalloc (sizeof (* pool
));
2172 pool
->next_free_entry
= 0;
2173 pool
->section
= now_seg
;
2174 pool
->sub_section
= now_subseg
;
2175 pool
->next
= list_of_pools
;
2176 pool
->symbol
= NULL
;
2178 /* Add it to the list. */
2179 list_of_pools
= pool
;
2182 /* New pools, and emptied pools, will have a NULL symbol. */
2183 if (pool
->symbol
== NULL
)
2185 pool
->symbol
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2186 (valueT
) 0, &zero_address_frag
);
2187 pool
->id
= latest_pool_num
++;
2194 /* Add the literal in the global 'inst'
2195 structure to the relevent literal pool. */
2199 literal_pool
* pool
;
2202 pool
= find_or_make_literal_pool ();
2204 /* Check if this literal value is already in the pool. */
2205 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2207 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2208 && (inst
.reloc
.exp
.X_op
== O_constant
)
2209 && (pool
->literals
[entry
].X_add_number
2210 == inst
.reloc
.exp
.X_add_number
)
2211 && (pool
->literals
[entry
].X_unsigned
2212 == inst
.reloc
.exp
.X_unsigned
))
2215 if ((pool
->literals
[entry
].X_op
== inst
.reloc
.exp
.X_op
)
2216 && (inst
.reloc
.exp
.X_op
== O_symbol
)
2217 && (pool
->literals
[entry
].X_add_number
2218 == inst
.reloc
.exp
.X_add_number
)
2219 && (pool
->literals
[entry
].X_add_symbol
2220 == inst
.reloc
.exp
.X_add_symbol
)
2221 && (pool
->literals
[entry
].X_op_symbol
2222 == inst
.reloc
.exp
.X_op_symbol
))
2226 /* Do we need to create a new entry? */
2227 if (entry
== pool
->next_free_entry
)
2229 if (entry
>= MAX_LITERAL_POOL_SIZE
)
2231 inst
.error
= _("literal pool overflow");
2235 pool
->literals
[entry
] = inst
.reloc
.exp
;
2236 pool
->next_free_entry
+= 1;
2239 inst
.reloc
.exp
.X_op
= O_symbol
;
2240 inst
.reloc
.exp
.X_add_number
= ((int) entry
) * 4 - 8;
2241 inst
.reloc
.exp
.X_add_symbol
= pool
->symbol
;
2246 /* Can't use symbol_new here, so have to create a symbol and then at
2247 a later date assign it a value. Thats what these functions do. */
2250 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2252 const char * name
; /* It is copied, the caller can modify. */
2253 segT segment
; /* Segment identifier (SEG_<something>). */
2254 valueT valu
; /* Symbol value. */
2255 fragS
* frag
; /* Associated fragment. */
2257 unsigned int name_length
;
2258 char * preserved_copy_of_name
;
2260 name_length
= strlen (name
) + 1; /* +1 for \0. */
2261 obstack_grow (¬es
, name
, name_length
);
2262 preserved_copy_of_name
= obstack_finish (¬es
);
2263 #ifdef STRIP_UNDERSCORE
2264 if (preserved_copy_of_name
[0] == '_')
2265 preserved_copy_of_name
++;
2268 #ifdef tc_canonicalize_symbol_name
2269 preserved_copy_of_name
=
2270 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2273 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2275 S_SET_SEGMENT (symbolP
, segment
);
2276 S_SET_VALUE (symbolP
, valu
);
2277 symbol_clear_list_pointers (symbolP
);
2279 symbol_set_frag (symbolP
, frag
);
2281 /* Link to end of symbol chain. */
2283 extern int symbol_table_frozen
;
2284 if (symbol_table_frozen
)
2288 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2290 obj_symbol_new_hook (symbolP
);
2292 #ifdef tc_symbol_new_hook
2293 tc_symbol_new_hook (symbolP
);
2297 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2298 #endif /* DEBUG_SYMS */
2301 /* Check that an immediate is valid.
2302 If so, convert it to the right format. */
2305 validate_immediate (val
)
2311 #define rotate_left(v, n) (v << n | v >> (32 - n))
2313 for (i
= 0; i
< 32; i
+= 2)
2314 if ((a
= rotate_left (val
, i
)) <= 0xff)
2315 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2320 /* Check to see if an immediate can be computed as two seperate immediate
2321 values, added together. We already know that this value cannot be
2322 computed by just one ARM instruction. */
2325 validate_immediate_twopart (val
, highpart
)
2327 unsigned int * highpart
;
2332 for (i
= 0; i
< 32; i
+= 2)
2333 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2339 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2341 else if (a
& 0xff0000)
2345 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2349 assert (a
& 0xff000000);
2350 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2353 return (a
& 0xff) | (i
<< 7);
2360 validate_offset_imm (val
, hwse
)
2364 if ((hwse
&& val
> 255) || val
> 4095)
2371 int a ATTRIBUTE_UNUSED
;
2373 as_bad (_("invalid syntax for .req directive"));
2378 int ignore ATTRIBUTE_UNUSED
;
2380 /* We don't support putting frags in the BSS segment, we fake it by
2381 marking in_bss, then looking at s_skip for clues. */
2382 subseg_set (bss_section
, 0);
2383 demand_empty_rest_of_line ();
2388 int ignore ATTRIBUTE_UNUSED
;
2390 /* Never make frag if expect extra pass. */
2392 frag_align (1, 0, 0);
2394 record_alignment (now_seg
, 1);
2396 demand_empty_rest_of_line ();
2401 int ignored ATTRIBUTE_UNUSED
;
2404 literal_pool
* pool
;
2407 pool
= find_literal_pool ();
2409 || pool
->symbol
== NULL
2410 || pool
->next_free_entry
== 0)
2413 /* Align pool as you have word accesses.
2414 Only make a frag if we have to. */
2416 frag_align (2, 0, 0);
2418 record_alignment (now_seg
, 2);
2420 sprintf (sym_name
, "$$lit_\002%x", pool
->id
);
2422 symbol_locate (pool
->symbol
, sym_name
, now_seg
,
2423 (valueT
) frag_now_fix (), frag_now
);
2424 symbol_table_insert (pool
->symbol
);
2426 ARM_SET_THUMB (pool
->symbol
, thumb_mode
);
2428 #if defined OBJ_COFF || defined OBJ_ELF
2429 ARM_SET_INTERWORK (pool
->symbol
, support_interwork
);
2432 for (entry
= 0; entry
< pool
->next_free_entry
; entry
++)
2433 /* First output the expression in the instruction to the pool. */
2434 emit_expr (&(pool
->literals
[entry
]), 4); /* .word */
2436 /* Mark the pool as empty. */
2437 pool
->next_free_entry
= 0;
2438 pool
->symbol
= NULL
;
2441 /* Same as s_align_ptwo but align 0 => align 2. */
2445 int unused ATTRIBUTE_UNUSED
;
2448 register long temp_fill
;
2449 long max_alignment
= 15;
2451 temp
= get_absolute_expression ();
2452 if (temp
> max_alignment
)
2453 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2456 as_bad (_("alignment negative. 0 assumed."));
2460 if (*input_line_pointer
== ',')
2462 input_line_pointer
++;
2463 temp_fill
= get_absolute_expression ();
2471 /* Only make a frag if we HAVE to. */
2472 if (temp
&& !need_pass_2
)
2473 frag_align (temp
, (int) temp_fill
, 0);
2474 demand_empty_rest_of_line ();
2476 record_alignment (now_seg
, temp
);
2480 s_force_thumb (ignore
)
2481 int ignore ATTRIBUTE_UNUSED
;
2483 /* If we are not already in thumb mode go into it, EVEN if
2484 the target processor does not support thumb instructions.
2485 This is used by gcc/config/arm/lib1funcs.asm for example
2486 to compile interworking support functions even if the
2487 target processor should not support interworking. */
2492 record_alignment (now_seg
, 1);
2495 demand_empty_rest_of_line ();
2499 s_thumb_func (ignore
)
2500 int ignore ATTRIBUTE_UNUSED
;
2505 /* The following label is the name/address of the start of a Thumb function.
2506 We need to know this for the interworking support. */
2507 label_is_thumb_function_name
= true;
2509 demand_empty_rest_of_line ();
2512 /* Perform a .set directive, but also mark the alias as
2513 being a thumb function. */
2519 /* XXX the following is a duplicate of the code for s_set() in read.c
2520 We cannot just call that code as we need to get at the symbol that
2522 register char * name
;
2523 register char delim
;
2524 register char * end_name
;
2525 register symbolS
* symbolP
;
2527 /* Especial apologies for the random logic:
2528 This just grew, and could be parsed much more simply!
2530 name
= input_line_pointer
;
2531 delim
= get_symbol_end ();
2532 end_name
= input_line_pointer
;
2537 if (*input_line_pointer
!= ',')
2540 as_bad (_("expected comma after name \"%s\""), name
);
2542 ignore_rest_of_line ();
2546 input_line_pointer
++;
2549 if (name
[0] == '.' && name
[1] == '\0')
2551 /* XXX - this should not happen to .thumb_set. */
2555 if ((symbolP
= symbol_find (name
)) == NULL
2556 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2559 /* When doing symbol listings, play games with dummy fragments living
2560 outside the normal fragment chain to record the file and line info
2562 if (listing
& LISTING_SYMBOLS
)
2564 extern struct list_info_struct
* listing_tail
;
2565 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2567 memset (dummy_frag
, 0, sizeof (fragS
));
2568 dummy_frag
->fr_type
= rs_fill
;
2569 dummy_frag
->line
= listing_tail
;
2570 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2571 dummy_frag
->fr_symbol
= symbolP
;
2575 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2578 /* "set" symbols are local unless otherwise specified. */
2579 SF_SET_LOCAL (symbolP
);
2580 #endif /* OBJ_COFF */
2581 } /* Make a new symbol. */
2583 symbol_table_insert (symbolP
);
2588 && S_IS_DEFINED (symbolP
)
2589 && S_GET_SEGMENT (symbolP
) != reg_section
)
2590 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2592 pseudo_set (symbolP
);
2594 demand_empty_rest_of_line ();
2596 /* XXX Now we come to the Thumb specific bit of code. */
2598 THUMB_SET_FUNC (symbolP
, 1);
2599 ARM_SET_THUMB (symbolP
, 1);
2600 #if defined OBJ_ELF || defined OBJ_COFF
2601 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2606 opcode_select (width
)
2614 if (! (cpu_variant
& ARM_EXT_V4T
))
2615 as_bad (_("selected processor does not support THUMB opcodes"));
2618 /* No need to force the alignment, since we will have been
2619 coming from ARM mode, which is word-aligned. */
2620 record_alignment (now_seg
, 1);
2627 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2628 as_bad (_("selected processor does not support ARM opcodes"));
2633 frag_align (2, 0, 0);
2635 record_alignment (now_seg
, 1);
2640 as_bad (_("invalid instruction size selected (%d)"), width
);
2646 int ignore ATTRIBUTE_UNUSED
;
2649 demand_empty_rest_of_line ();
2654 int ignore ATTRIBUTE_UNUSED
;
2657 demand_empty_rest_of_line ();
2662 int unused ATTRIBUTE_UNUSED
;
2666 temp
= get_absolute_expression ();
2671 opcode_select (temp
);
2675 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2683 skip_whitespace (str
);
2685 if (*str
!= '\0' && !inst
.error
)
2686 inst
.error
= _("garbage following instruction");
2690 skip_past_comma (str
)
2693 char * p
= * str
, c
;
2696 while ((c
= *p
) == ' ' || c
== ',')
2699 if (c
== ',' && comma
++)
2707 return comma
? SUCCESS
: FAIL
;
2710 /* A standard register must be given at this point.
2711 SHIFT is the place to put it in inst.instruction.
2712 Restores input start point on error.
2713 Returns the reg#, or FAIL. */
2716 reg_required_here (str
, shift
)
2720 static char buff
[128]; /* XXX */
2722 char * start
= * str
;
2724 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
2727 inst
.instruction
|= reg
<< shift
;
2731 /* Restore the start point, we may have got a reg of the wrong class. */
2734 /* In the few cases where we might be able to accept something else
2735 this error can be overridden. */
2736 sprintf (buff
, _("register expected, not '%.100s'"), start
);
2742 static const struct asm_psr
*
2744 register char ** ccp
;
2746 char * start
= * ccp
;
2749 const struct asm_psr
* psr
;
2753 /* Skip to the end of the next word in the input stream. */
2758 while (ISALPHA (c
) || c
== '_');
2760 /* Terminate the word. */
2763 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2764 feature for ease of use and backwards compatibility. */
2765 if (!strncmp (start
, "cpsr", 4))
2766 strncpy (start
, "CPSR", 4);
2767 else if (!strncmp (start
, "spsr", 4))
2768 strncpy (start
, "SPSR", 4);
2770 /* Now locate the word in the psr hash table. */
2771 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2773 /* Restore the input stream. */
2776 /* If we found a valid match, advance the
2777 stream pointer past the end of the word. */
2783 /* Parse the input looking for a PSR flag. */
2786 psr_required_here (str
)
2789 char * start
= * str
;
2790 const struct asm_psr
* psr
;
2792 psr
= arm_psr_parse (str
);
2796 /* If this is the SPSR that is being modified, set the R bit. */
2798 inst
.instruction
|= SPSR_BIT
;
2800 /* Set the psr flags in the MSR instruction. */
2801 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2806 /* In the few cases where we might be able to accept
2807 something else this error can be overridden. */
2808 inst
.error
= _("flag for {c}psr instruction expected");
2810 /* Restore the start point. */
2816 co_proc_number (str
)
2819 int processor
, pchar
;
2822 skip_whitespace (*str
);
2825 /* The data sheet seems to imply that just a number on its own is valid
2826 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2828 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2834 if (pchar
>= '0' && pchar
<= '9')
2836 processor
= pchar
- '0';
2837 if (**str
>= '0' && **str
<= '9')
2839 processor
= processor
* 10 + *(*str
)++ - '0';
2842 inst
.error
= _("illegal co-processor number");
2849 inst
.error
= _("bad or missing co-processor number");
2854 inst
.instruction
|= processor
<< 8;
2859 cp_opc_expr (str
, where
, length
)
2866 skip_whitespace (* str
);
2868 memset (&expr
, '\0', sizeof (expr
));
2870 if (my_get_expression (&expr
, str
))
2872 if (expr
.X_op
!= O_constant
)
2874 inst
.error
= _("bad or missing expression");
2878 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2880 inst
.error
= _("immediate co-processor expression too large");
2884 inst
.instruction
|= expr
.X_add_number
<< where
;
2889 cp_reg_required_here (str
, where
)
2894 char * start
= *str
;
2896 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2898 inst
.instruction
|= reg
<< where
;
2902 /* In the few cases where we might be able to accept something else
2903 this error can be overridden. */
2904 inst
.error
= _("co-processor register expected");
2906 /* Restore the start point. */
2912 fp_reg_required_here (str
, where
)
2917 char * start
= * str
;
2919 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2921 inst
.instruction
|= reg
<< where
;
2925 /* In the few cases where we might be able to accept something else
2926 this error can be overridden. */
2927 inst
.error
= _("floating point register expected");
2929 /* Restore the start point. */
2935 cp_address_offset (str
)
2940 skip_whitespace (* str
);
2942 if (! is_immediate_prefix (**str
))
2944 inst
.error
= _("immediate expression expected");
2950 if (my_get_expression (& inst
.reloc
.exp
, str
))
2953 if (inst
.reloc
.exp
.X_op
== O_constant
)
2955 offset
= inst
.reloc
.exp
.X_add_number
;
2959 inst
.error
= _("co-processor address must be word aligned");
2963 if (offset
> 1023 || offset
< -1023)
2965 inst
.error
= _("offset too large");
2970 inst
.instruction
|= INDEX_UP
;
2974 inst
.instruction
|= offset
>> 2;
2977 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2983 cp_address_required_here (str
, wb_ok
)
2996 skip_whitespace (p
);
2998 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
3001 skip_whitespace (p
);
3007 if (wb_ok
&& skip_past_comma (& p
) == SUCCESS
)
3010 write_back
= WRITE_BACK
;
3014 inst
.error
= _("pc may not be used in post-increment");
3018 if (cp_address_offset (& p
) == FAIL
)
3022 pre_inc
= PRE_INDEX
| INDEX_UP
;
3026 /* '['Rn, #expr']'[!] */
3028 if (skip_past_comma (& p
) == FAIL
)
3030 inst
.error
= _("pre-indexed expression expected");
3034 pre_inc
= PRE_INDEX
;
3036 if (cp_address_offset (& p
) == FAIL
)
3039 skip_whitespace (p
);
3043 inst
.error
= _("missing ]");
3047 skip_whitespace (p
);
3049 if (wb_ok
&& *p
== '!')
3053 inst
.error
= _("pc may not be used with write-back");
3058 write_back
= WRITE_BACK
;
3064 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3067 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3068 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3069 inst
.reloc
.pc_rel
= 1;
3070 inst
.instruction
|= (REG_PC
<< 16);
3071 pre_inc
= PRE_INDEX
;
3074 inst
.instruction
|= write_back
| pre_inc
;
3083 /* Do nothing really. */
3094 /* Only one syntax. */
3095 skip_whitespace (str
);
3097 if (reg_required_here (&str
, 12) == FAIL
)
3099 inst
.error
= BAD_ARGS
;
3103 if (skip_past_comma (&str
) == FAIL
)
3105 inst
.error
= _("comma expected after register name");
3109 skip_whitespace (str
);
3111 if ( strcmp (str
, "CPSR") == 0
3112 || strcmp (str
, "SPSR") == 0
3113 /* Lower case versions for backwards compatability. */
3114 || strcmp (str
, "cpsr") == 0
3115 || strcmp (str
, "spsr") == 0)
3118 /* This is for backwards compatability with older toolchains. */
3119 else if ( strcmp (str
, "cpsr_all") == 0
3120 || strcmp (str
, "spsr_all") == 0)
3124 inst
.error
= _("CPSR or SPSR expected");
3128 if (* str
== 's' || * str
== 'S')
3129 inst
.instruction
|= SPSR_BIT
;
3135 /* Two possible forms:
3136 "{C|S}PSR_<field>, Rm",
3137 "{C|S}PSR_f, #expression". */
3143 skip_whitespace (str
);
3145 if (psr_required_here (& str
) == FAIL
)
3148 if (skip_past_comma (& str
) == FAIL
)
3150 inst
.error
= _("comma missing after psr flags");
3154 skip_whitespace (str
);
3156 if (reg_required_here (& str
, 0) != FAIL
)
3163 if (! is_immediate_prefix (* str
))
3166 _("only a register or immediate value can follow a psr flag");
3173 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3176 _("only a register or immediate value can follow a psr flag");
3180 #if 0 /* The first edition of the ARM architecture manual stated that
3181 writing anything other than the flags with an immediate operation
3182 had UNPREDICTABLE effects. This constraint was removed in the
3183 second edition of the specification. */
3184 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3185 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3187 inst
.error
= _("immediate value cannot be used to set this field");
3192 inst
.instruction
|= INST_IMMEDIATE
;
3194 if (inst
.reloc
.exp
.X_add_symbol
)
3196 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3197 inst
.reloc
.pc_rel
= 0;
3201 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3203 if (value
== (unsigned) FAIL
)
3205 inst
.error
= _("invalid constant");
3209 inst
.instruction
|= value
;
3216 /* Long Multiply Parser
3217 UMULL RdLo, RdHi, Rm, Rs
3218 SMULL RdLo, RdHi, Rm, Rs
3219 UMLAL RdLo, RdHi, Rm, Rs
3220 SMLAL RdLo, RdHi, Rm, Rs. */
3226 int rdlo
, rdhi
, rm
, rs
;
3228 /* Only one format "rdlo, rdhi, rm, rs". */
3229 skip_whitespace (str
);
3231 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3233 inst
.error
= BAD_ARGS
;
3237 if (skip_past_comma (&str
) == FAIL
3238 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3240 inst
.error
= BAD_ARGS
;
3244 if (skip_past_comma (&str
) == FAIL
3245 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3247 inst
.error
= BAD_ARGS
;
3251 /* rdhi, rdlo and rm must all be different. */
3252 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3253 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3255 if (skip_past_comma (&str
) == FAIL
3256 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3258 inst
.error
= BAD_ARGS
;
3262 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3264 inst
.error
= BAD_PC
;
3278 /* Only one format "rd, rm, rs". */
3279 skip_whitespace (str
);
3281 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3283 inst
.error
= BAD_ARGS
;
3289 inst
.error
= BAD_PC
;
3293 if (skip_past_comma (&str
) == FAIL
3294 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3296 inst
.error
= BAD_ARGS
;
3302 inst
.error
= BAD_PC
;
3307 as_tsktsk (_("rd and rm should be different in mul"));
3309 if (skip_past_comma (&str
) == FAIL
3310 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3312 inst
.error
= BAD_ARGS
;
3318 inst
.error
= BAD_PC
;
3332 /* Only one format "rd, rm, rs, rn". */
3333 skip_whitespace (str
);
3335 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3337 inst
.error
= BAD_ARGS
;
3343 inst
.error
= BAD_PC
;
3347 if (skip_past_comma (&str
) == FAIL
3348 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3350 inst
.error
= BAD_ARGS
;
3356 inst
.error
= BAD_PC
;
3361 as_tsktsk (_("rd and rm should be different in mla"));
3363 if (skip_past_comma (&str
) == FAIL
3364 || (rd
= reg_required_here (&str
, 8)) == FAIL
3365 || skip_past_comma (&str
) == FAIL
3366 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3368 inst
.error
= BAD_ARGS
;
3372 if (rd
== REG_PC
|| rm
== REG_PC
)
3374 inst
.error
= BAD_PC
;
3382 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3383 Advances *str to the next non-alphanumeric.
3384 Returns 0, or else FAIL (in which case sets inst.error).
3386 (In a future XScale, there may be accumulators other than zero.
3387 At that time this routine and its callers can be upgraded to suit.) */
3390 accum0_required_here (str
)
3393 static char buff
[128]; /* Note the address is taken. Hence, static. */
3396 int result
= 0; /* The accum number. */
3398 skip_whitespace (p
);
3400 *str
= p
; /* Advance caller's string pointer too. */
3405 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3407 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3409 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3414 *p
= c
; /* Unzap. */
3415 *str
= p
; /* Caller's string pointer to after match. */
3419 /* Expects **str -> after a comma. May be leading blanks.
3420 Advances *str, recognizing a load mode, and setting inst.instruction.
3421 Returns rn, or else FAIL (in which case may set inst.error
3422 and not advance str)
3424 Note: doesn't know Rd, so no err checks that require such knowledge. */
3427 ld_mode_required_here (string
)
3430 char * str
= * string
;
3434 skip_whitespace (str
);
3440 skip_whitespace (str
);
3442 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3445 skip_whitespace (str
);
3451 if (skip_past_comma (& str
) == SUCCESS
)
3453 /* [Rn],... (post inc) */
3454 if (ldst_extend_v4 (&str
) == FAIL
)
3459 skip_whitespace (str
);
3464 inst
.instruction
|= WRITE_BACK
;
3467 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3473 if (skip_past_comma (& str
) == FAIL
)
3475 inst
.error
= _("pre-indexed expression expected");
3481 if (ldst_extend_v4 (&str
) == FAIL
)
3484 skip_whitespace (str
);
3486 if (* str
++ != ']')
3488 inst
.error
= _("missing ]");
3492 skip_whitespace (str
);
3497 inst
.instruction
|= WRITE_BACK
;
3501 else if (* str
== '=') /* ldr's "r,=label" syntax */
3502 /* We should never reach here, because <text> = <expression> is
3503 caught gas/read.c read_a_source_file() as a .set operation. */
3505 else /* PC +- 8 bit immediate offset. */
3507 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3510 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3511 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3512 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3513 inst
.reloc
.pc_rel
= 1;
3514 inst
.instruction
|= (REG_PC
<< 16);
3520 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3526 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3527 SMLAxy{cond} Rd,Rm,Rs,Rn
3528 SMLAWy{cond} Rd,Rm,Rs,Rn
3529 Error if any register is R15. */
3537 skip_whitespace (str
);
3539 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3540 || skip_past_comma (& str
) == FAIL
3541 || (rm
= reg_required_here (& str
, 0)) == FAIL
3542 || skip_past_comma (& str
) == FAIL
3543 || (rs
= reg_required_here (& str
, 8)) == FAIL
3544 || skip_past_comma (& str
) == FAIL
3545 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3546 inst
.error
= BAD_ARGS
;
3548 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3549 inst
.error
= BAD_PC
;
3555 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3556 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3557 Error if any register is R15.
3558 Warning if Rdlo == Rdhi. */
3564 int rdlo
, rdhi
, rm
, rs
;
3566 skip_whitespace (str
);
3568 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3569 || skip_past_comma (& str
) == FAIL
3570 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3571 || skip_past_comma (& str
) == FAIL
3572 || (rm
= reg_required_here (& str
, 0)) == FAIL
3573 || skip_past_comma (& str
) == FAIL
3574 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3576 inst
.error
= BAD_ARGS
;
3580 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3582 inst
.error
= BAD_PC
;
3587 as_tsktsk (_("rdhi and rdlo must be different"));
3592 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3593 SMULxy{cond} Rd,Rm,Rs
3594 Error if any register is R15. */
3602 skip_whitespace (str
);
3604 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3605 || skip_past_comma (& str
) == FAIL
3606 || (rm
= reg_required_here (& str
, 0)) == FAIL
3607 || skip_past_comma (& str
) == FAIL
3608 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3609 inst
.error
= BAD_ARGS
;
3611 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3612 inst
.error
= BAD_PC
;
3618 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3619 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3620 Error if any register is R15. */
3628 skip_whitespace (str
);
3630 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3631 || skip_past_comma (& str
) == FAIL
3632 || (rm
= reg_required_here (& str
, 0)) == FAIL
3633 || skip_past_comma (& str
) == FAIL
3634 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3635 inst
.error
= BAD_ARGS
;
3637 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3638 inst
.error
= BAD_PC
;
3644 /* ARM V5E (el Segundo)
3645 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3646 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3648 These are equivalent to the XScale instructions MAR and MRA,
3649 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3651 Result unpredicatable if Rd or Rn is R15. */
3659 skip_whitespace (str
);
3661 if (co_proc_number (& str
) == FAIL
)
3664 inst
.error
= BAD_ARGS
;
3668 if (skip_past_comma (& str
) == FAIL
3669 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3672 inst
.error
= BAD_ARGS
;
3676 if (skip_past_comma (& str
) == FAIL
3677 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3680 inst
.error
= BAD_ARGS
;
3684 if (skip_past_comma (& str
) == FAIL
3685 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3688 inst
.error
= BAD_ARGS
;
3692 /* Unpredictable result if rd or rn is R15. */
3693 if (rd
== REG_PC
|| rn
== REG_PC
)
3695 (_("Warning: instruction unpredictable when using r15"));
3697 if (skip_past_comma (& str
) == FAIL
3698 || cp_reg_required_here (& str
, 0) == FAIL
)
3701 inst
.error
= BAD_ARGS
;
3708 /* ARM V5 count-leading-zeroes instruction (argument parse)
3709 CLZ{<cond>} <Rd>, <Rm>
3710 Condition defaults to COND_ALWAYS.
3711 Error if Rd or Rm are R15. */
3719 skip_whitespace (str
);
3721 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3722 || (skip_past_comma (& str
) == FAIL
)
3723 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3724 inst
.error
= BAD_ARGS
;
3726 else if (rd
== REG_PC
|| rm
== REG_PC
)
3727 inst
.error
= BAD_PC
;
3733 /* ARM V5 (argument parse)
3734 LDC2{L} <coproc>, <CRd>, <addressing mode>
3735 STC2{L} <coproc>, <CRd>, <addressing mode>
3736 Instruction is not conditional, and has 0xf in the codition field.
3737 Otherwise, it's the same as LDC/STC. */
3743 skip_whitespace (str
);
3745 if (co_proc_number (& str
) == FAIL
)
3748 inst
.error
= BAD_ARGS
;
3750 else if (skip_past_comma (& str
) == FAIL
3751 || cp_reg_required_here (& str
, 12) == FAIL
)
3754 inst
.error
= BAD_ARGS
;
3756 else if (skip_past_comma (& str
) == FAIL
3757 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3760 inst
.error
= BAD_ARGS
;
3766 /* ARM V5 (argument parse)
3767 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3768 Instruction is not conditional, and has 0xf in the condition field.
3769 Otherwise, it's the same as CDP. */
3775 skip_whitespace (str
);
3777 if (co_proc_number (& str
) == FAIL
)
3780 inst
.error
= BAD_ARGS
;
3784 if (skip_past_comma (& str
) == FAIL
3785 || cp_opc_expr (& str
, 20,4) == FAIL
)
3788 inst
.error
= BAD_ARGS
;
3792 if (skip_past_comma (& str
) == FAIL
3793 || cp_reg_required_here (& str
, 12) == FAIL
)
3796 inst
.error
= BAD_ARGS
;
3800 if (skip_past_comma (& str
) == FAIL
3801 || cp_reg_required_here (& str
, 16) == FAIL
)
3804 inst
.error
= BAD_ARGS
;
3808 if (skip_past_comma (& str
) == FAIL
3809 || cp_reg_required_here (& str
, 0) == FAIL
)
3812 inst
.error
= BAD_ARGS
;
3816 if (skip_past_comma (& str
) == SUCCESS
)
3818 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3821 inst
.error
= BAD_ARGS
;
3829 /* ARM V5 (argument parse)
3830 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3831 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3832 Instruction is not conditional, and has 0xf in the condition field.
3833 Otherwise, it's the same as MCR/MRC. */
3839 skip_whitespace (str
);
3841 if (co_proc_number (& str
) == FAIL
)
3844 inst
.error
= BAD_ARGS
;
3848 if (skip_past_comma (& str
) == FAIL
3849 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3852 inst
.error
= BAD_ARGS
;
3856 if (skip_past_comma (& str
) == FAIL
3857 || reg_required_here (& str
, 12) == FAIL
)
3860 inst
.error
= BAD_ARGS
;
3864 if (skip_past_comma (& str
) == FAIL
3865 || cp_reg_required_here (& str
, 16) == FAIL
)
3868 inst
.error
= BAD_ARGS
;
3872 if (skip_past_comma (& str
) == FAIL
3873 || cp_reg_required_here (& str
, 0) == FAIL
)
3876 inst
.error
= BAD_ARGS
;
3880 if (skip_past_comma (& str
) == SUCCESS
)
3882 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3885 inst
.error
= BAD_ARGS
;
3893 /* ARM v5TEJ. Jump to Jazelle code. */
3900 skip_whitespace (str
);
3902 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
3904 inst
.error
= BAD_ARGS
;
3908 /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
3910 as_tsktsk (_("use of r15 in bxj is not really useful"));
3915 /* THUMB V5 breakpoint instruction (argument parse)
3923 unsigned long number
;
3925 skip_whitespace (str
);
3927 /* Allow optional leading '#'. */
3928 if (is_immediate_prefix (*str
))
3931 memset (& expr
, '\0', sizeof (expr
));
3932 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
3934 inst
.error
= _("bad or missing expression");
3938 number
= expr
.X_add_number
;
3940 /* Check it fits an 8 bit unsigned. */
3941 if (number
!= (number
& 0xff))
3943 inst
.error
= _("immediate value out of range");
3947 inst
.instruction
|= number
;
3952 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3953 Expects inst.instruction is set for BLX(1).
3954 Note: this is cloned from do_branch, and the reloc changed to be a
3955 new one that can cope with setting one extra bit (the H bit). */
3961 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3968 /* ScottB: February 5, 1998 */
3969 /* Check to see of PLT32 reloc required for the instruction. */
3971 /* arm_parse_reloc() works on input_line_pointer.
3972 We actually want to parse the operands to the branch instruction
3973 passed in 'str'. Save the input pointer and restore it later. */
3974 save_in
= input_line_pointer
;
3975 input_line_pointer
= str
;
3977 if (inst
.reloc
.exp
.X_op
== O_symbol
3979 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
3981 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
3982 inst
.reloc
.pc_rel
= 0;
3983 /* Modify str to point to after parsed operands, otherwise
3984 end_of_line() will complain about the (PLT) left in str. */
3985 str
= input_line_pointer
;
3989 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3990 inst
.reloc
.pc_rel
= 1;
3993 input_line_pointer
= save_in
;
3996 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3997 inst
.reloc
.pc_rel
= 1;
3998 #endif /* OBJ_ELF */
4003 /* ARM V5 branch-link-exchange instruction (argument parse)
4004 BLX <target_addr> ie BLX(1)
4005 BLX{<condition>} <Rm> ie BLX(2)
4006 Unfortunately, there are two different opcodes for this mnemonic.
4007 So, the insns[].value is not used, and the code here zaps values
4008 into inst.instruction.
4009 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
4018 skip_whitespace (mystr
);
4019 rm
= reg_required_here (& mystr
, 0);
4021 /* The above may set inst.error. Ignore his opinion. */
4026 /* Arg is a register.
4027 Use the condition code our caller put in inst.instruction.
4028 Pass ourselves off as a BX with a funny opcode. */
4029 inst
.instruction
|= 0x012fff30;
4034 /* This must be is BLX <target address>, no condition allowed. */
4035 if (inst
.instruction
!= COND_ALWAYS
)
4037 inst
.error
= BAD_COND
;
4041 inst
.instruction
= 0xfafffffe;
4043 /* Process like a B/BL, but with a different reloc.
4044 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4049 /* ARM V5 Thumb BLX (argument parse)
4050 BLX <target_addr> which is BLX(1)
4051 BLX <Rm> which is BLX(2)
4052 Unfortunately, there are two different opcodes for this mnemonic.
4053 So, the tinsns[].value is not used, and the code here zaps values
4054 into inst.instruction. */
4063 skip_whitespace (mystr
);
4064 inst
.instruction
= 0x4780;
4066 /* Note that this call is to the ARM register recognizer. BLX(2)
4067 uses the ARM register space, not the Thumb one, so a call to
4068 thumb_reg() would be wrong. */
4069 rm
= reg_required_here (& mystr
, 3);
4074 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4079 /* No ARM register. This must be BLX(1). Change the .instruction. */
4080 inst
.instruction
= 0xf7ffeffe;
4083 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4086 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4087 inst
.reloc
.pc_rel
= 1;
4090 end_of_line (mystr
);
4093 /* ARM V5 breakpoint instruction (argument parse)
4094 BKPT <16 bit unsigned immediate>
4095 Instruction is not conditional.
4096 The bit pattern given in insns[] has the COND_ALWAYS condition,
4097 and it is an error if the caller tried to override that. */
4104 unsigned long number
;
4106 skip_whitespace (str
);
4108 /* Allow optional leading '#'. */
4109 if (is_immediate_prefix (* str
))
4112 memset (& expr
, '\0', sizeof (expr
));
4114 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4116 inst
.error
= _("bad or missing expression");
4120 number
= expr
.X_add_number
;
4122 /* Check it fits a 16 bit unsigned. */
4123 if (number
!= (number
& 0xffff))
4125 inst
.error
= _("immediate value out of range");
4129 /* Top 12 of 16 bits to bits 19:8. */
4130 inst
.instruction
|= (number
& 0xfff0) << 4;
4132 /* Bottom 4 of 16 bits to bits 3:0. */
4133 inst
.instruction
|= number
& 0xf;
4138 /* Xscale multiply-accumulate (argument parse)
4141 MIAxycc acc0,Rm,Rs. */
4150 if (accum0_required_here (& str
) == FAIL
)
4151 inst
.error
= ERR_NO_ACCUM
;
4153 else if (skip_past_comma (& str
) == FAIL
4154 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
4155 inst
.error
= BAD_ARGS
;
4157 else if (skip_past_comma (& str
) == FAIL
4158 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
4159 inst
.error
= BAD_ARGS
;
4161 /* inst.instruction has now been zapped with both rm and rs. */
4162 else if (rm
== REG_PC
|| rs
== REG_PC
)
4163 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
4169 /* Xscale move-accumulator-register (argument parse)
4171 MARcc acc0,RdLo,RdHi. */
4179 if (accum0_required_here (& str
) == FAIL
)
4180 inst
.error
= ERR_NO_ACCUM
;
4182 else if (skip_past_comma (& str
) == FAIL
4183 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
4184 inst
.error
= BAD_ARGS
;
4186 else if (skip_past_comma (& str
) == FAIL
4187 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
4188 inst
.error
= BAD_ARGS
;
4190 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4191 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
4192 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
4198 /* Xscale move-register-accumulator (argument parse)
4200 MRAcc RdLo,RdHi,acc0. */
4209 skip_whitespace (str
);
4211 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
4212 inst
.error
= BAD_ARGS
;
4214 else if (skip_past_comma (& str
) == FAIL
4215 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
4216 inst
.error
= BAD_ARGS
;
4218 else if (skip_past_comma (& str
) == FAIL
4219 || accum0_required_here (& str
) == FAIL
)
4220 inst
.error
= ERR_NO_ACCUM
;
4222 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4223 else if (rdlo
== rdhi
)
4224 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
4226 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
4227 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
4232 /* ARMv5TE: Preload-Cache
4236 Syntactically, like LDR with B=1, W=0, L=1. */
4244 skip_whitespace (str
);
4248 inst
.error
= _("'[' expected after PLD mnemonic");
4253 skip_whitespace (str
);
4255 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
4258 skip_whitespace (str
);
4264 skip_whitespace (str
);
4266 /* Post-indexed addressing is not allowed with PLD. */
4267 if (skip_past_comma (&str
) == SUCCESS
)
4270 = _("post-indexed expression used in preload instruction");
4273 else if (*str
== '!') /* [Rn]! */
4275 inst
.error
= _("writeback used in preload instruction");
4279 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
4281 else /* [Rn, ...] */
4283 if (skip_past_comma (& str
) == FAIL
)
4285 inst
.error
= _("pre-indexed expression expected");
4289 if (ldst_extend (&str
) == FAIL
)
4292 skip_whitespace (str
);
4296 inst
.error
= _("missing ]");
4301 skip_whitespace (str
);
4303 if (* str
== '!') /* [Rn]! */
4305 inst
.error
= _("writeback used in preload instruction");
4309 inst
.instruction
|= PRE_INDEX
;
4315 /* ARMv5TE load-consecutive (argument parse)
4328 skip_whitespace (str
);
4330 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
4332 inst
.error
= BAD_ARGS
;
4336 if (skip_past_comma (& str
) == FAIL
4337 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
4340 inst
.error
= BAD_ARGS
;
4344 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4345 if (rd
& 1) /* Unpredictable result if Rd is odd. */
4347 inst
.error
= _("destination register must be even");
4353 inst
.error
= _("r14 not allowed here");
4357 if (((rd
== rn
) || (rd
+ 1 == rn
))
4358 && ((inst
.instruction
& WRITE_BACK
)
4359 || (!(inst
.instruction
& PRE_INDEX
))))
4360 as_warn (_("pre/post-indexing used when modified address register is destination"));
4362 /* For an index-register load, the index register must not overlap the
4363 destination (even if not write-back). */
4364 if ((inst
.instruction
& V4_STR_BIT
) == 0
4365 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
4367 int rm
= inst
.instruction
& 0x0000000f;
4369 if (rm
== rd
|| (rm
== rd
+ 1))
4370 as_warn (_("ldrd destination registers must not overlap index register"));
4376 /* Returns the index into fp_values of a floating point number,
4377 or -1 if not in the table. */
4380 my_get_float_expression (str
)
4383 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
4389 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
4391 /* Look for a raw floating point number. */
4392 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
4393 && is_end_of_line
[(unsigned char) *save_in
])
4395 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4397 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4399 if (words
[j
] != fp_values
[i
][j
])
4403 if (j
== MAX_LITTLENUMS
)
4411 /* Try and parse a more complex expression, this will probably fail
4412 unless the code uses a floating point prefix (eg "0f"). */
4413 save_in
= input_line_pointer
;
4414 input_line_pointer
= *str
;
4415 if (expression (&exp
) == absolute_section
4416 && exp
.X_op
== O_big
4417 && exp
.X_add_number
< 0)
4419 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4421 if (gen_to_words (words
, 5, (long) 15) == 0)
4423 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4425 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4427 if (words
[j
] != fp_values
[i
][j
])
4431 if (j
== MAX_LITTLENUMS
)
4433 *str
= input_line_pointer
;
4434 input_line_pointer
= save_in
;
4441 *str
= input_line_pointer
;
4442 input_line_pointer
= save_in
;
4446 /* Return true if anything in the expression is a bignum. */
4449 walk_no_bignums (sp
)
4452 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
4455 if (symbol_get_value_expression (sp
)->X_add_symbol
)
4457 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
4458 || (symbol_get_value_expression (sp
)->X_op_symbol
4459 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
4465 static int in_my_get_expression
= 0;
4468 my_get_expression (ep
, str
)
4475 save_in
= input_line_pointer
;
4476 input_line_pointer
= *str
;
4477 in_my_get_expression
= 1;
4478 seg
= expression (ep
);
4479 in_my_get_expression
= 0;
4481 if (ep
->X_op
== O_illegal
)
4483 /* We found a bad expression in md_operand(). */
4484 *str
= input_line_pointer
;
4485 input_line_pointer
= save_in
;
4490 if (seg
!= absolute_section
4491 && seg
!= text_section
4492 && seg
!= data_section
4493 && seg
!= bss_section
4494 && seg
!= undefined_section
)
4496 inst
.error
= _("bad_segment");
4497 *str
= input_line_pointer
;
4498 input_line_pointer
= save_in
;
4503 /* Get rid of any bignums now, so that we don't generate an error for which
4504 we can't establish a line number later on. Big numbers are never valid
4505 in instructions, which is where this routine is always called. */
4506 if (ep
->X_op
== O_big
4507 || (ep
->X_add_symbol
4508 && (walk_no_bignums (ep
->X_add_symbol
)
4510 && walk_no_bignums (ep
->X_op_symbol
)))))
4512 inst
.error
= _("invalid constant");
4513 *str
= input_line_pointer
;
4514 input_line_pointer
= save_in
;
4518 *str
= input_line_pointer
;
4519 input_line_pointer
= save_in
;
4523 /* We handle all bad expressions here, so that we can report the faulty
4524 instruction in the error message. */
4529 if (in_my_get_expression
)
4531 expr
->X_op
= O_illegal
;
4532 if (inst
.error
== NULL
)
4533 inst
.error
= _("bad expression");
4537 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4541 decode_shift (str
, unrestrict
)
4545 const struct asm_shift_name
* shift
;
4549 skip_whitespace (* str
);
4551 for (p
= * str
; ISALPHA (* p
); p
++)
4556 inst
.error
= _("shift expression expected");
4562 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
4567 inst
.error
= _("shift expression expected");
4571 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
4573 if (shift
->properties
->index
== SHIFT_RRX
)
4576 inst
.instruction
|= shift
->properties
->bit_field
;
4580 skip_whitespace (p
);
4582 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
4584 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
4588 else if (! is_immediate_prefix (* p
))
4590 inst
.error
= (unrestrict
4591 ? _("shift requires register or #expression")
4592 : _("shift requires #expression"));
4600 if (my_get_expression (& inst
.reloc
.exp
, & p
))
4603 /* Validate some simple #expressions. */
4604 if (inst
.reloc
.exp
.X_op
== O_constant
)
4606 unsigned num
= inst
.reloc
.exp
.X_add_number
;
4608 /* Reject operations greater than 32. */
4610 /* Reject a shift of 0 unless the mode allows it. */
4611 || (num
== 0 && shift
->properties
->allows_0
== 0)
4612 /* Reject a shift of 32 unless the mode allows it. */
4613 || (num
== 32 && shift
->properties
->allows_32
== 0)
4616 /* As a special case we allow a shift of zero for
4617 modes that do not support it to be recoded as an
4618 logical shift left of zero (ie nothing). We warn
4619 about this though. */
4622 as_warn (_("shift of 0 ignored."));
4623 shift
= & shift_names
[0];
4624 assert (shift
->properties
->index
== SHIFT_LSL
);
4628 inst
.error
= _("invalid immediate shift");
4633 /* Shifts of 32 are encoded as 0, for those shifts that
4638 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
4642 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
4643 inst
.reloc
.pc_rel
= 0;
4644 inst
.instruction
|= shift
->properties
->bit_field
;
4651 /* Do those data_ops which can take a negative immediate constant
4652 by altering the instuction. A bit of a hack really.
4656 by inverting the second operand, and
4659 by negating the second operand. */
4662 negate_data_op (instruction
, value
)
4663 unsigned long * instruction
;
4664 unsigned long value
;
4667 unsigned long negated
, inverted
;
4669 negated
= validate_immediate (-value
);
4670 inverted
= validate_immediate (~value
);
4672 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
4675 /* First negates. */
4676 case OPCODE_SUB
: /* ADD <-> SUB */
4677 new_inst
= OPCODE_ADD
;
4682 new_inst
= OPCODE_SUB
;
4686 case OPCODE_CMP
: /* CMP <-> CMN */
4687 new_inst
= OPCODE_CMN
;
4692 new_inst
= OPCODE_CMP
;
4696 /* Now Inverted ops. */
4697 case OPCODE_MOV
: /* MOV <-> MVN */
4698 new_inst
= OPCODE_MVN
;
4703 new_inst
= OPCODE_MOV
;
4707 case OPCODE_AND
: /* AND <-> BIC */
4708 new_inst
= OPCODE_BIC
;
4713 new_inst
= OPCODE_AND
;
4717 case OPCODE_ADC
: /* ADC <-> SBC */
4718 new_inst
= OPCODE_SBC
;
4723 new_inst
= OPCODE_ADC
;
4727 /* We cannot do anything. */
4732 if (value
== (unsigned) FAIL
)
4735 *instruction
&= OPCODE_MASK
;
4736 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
4747 skip_whitespace (* str
);
4749 if (reg_required_here (str
, 0) != FAIL
)
4751 if (skip_past_comma (str
) == SUCCESS
)
4752 /* Shift operation on register. */
4753 return decode_shift (str
, NO_SHIFT_RESTRICT
);
4759 /* Immediate expression. */
4760 if (is_immediate_prefix (**str
))
4765 if (my_get_expression (&inst
.reloc
.exp
, str
))
4768 if (inst
.reloc
.exp
.X_add_symbol
)
4770 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4771 inst
.reloc
.pc_rel
= 0;
4775 if (skip_past_comma (str
) == SUCCESS
)
4777 /* #x, y -- ie explicit rotation by Y. */
4778 if (my_get_expression (&expr
, str
))
4781 if (expr
.X_op
!= O_constant
)
4783 inst
.error
= _("constant expression expected");
4787 /* Rotate must be a multiple of 2. */
4788 if (((unsigned) expr
.X_add_number
) > 30
4789 || (expr
.X_add_number
& 1) != 0
4790 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
4792 inst
.error
= _("invalid constant");
4795 inst
.instruction
|= INST_IMMEDIATE
;
4796 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
4797 inst
.instruction
|= expr
.X_add_number
<< 7;
4801 /* Implicit rotation, select a suitable one. */
4802 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4806 /* Can't be done. Perhaps the code reads something like
4807 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4808 if ((value
= negate_data_op (&inst
.instruction
,
4809 inst
.reloc
.exp
.X_add_number
))
4812 inst
.error
= _("invalid constant");
4817 inst
.instruction
|= value
;
4820 inst
.instruction
|= INST_IMMEDIATE
;
4825 inst
.error
= _("register or shift expression expected");
4834 skip_whitespace (* str
);
4836 if (fp_reg_required_here (str
, 0) != FAIL
)
4840 /* Immediate expression. */
4841 if (*((*str
)++) == '#')
4847 skip_whitespace (* str
);
4849 /* First try and match exact strings, this is to guarantee
4850 that some formats will work even for cross assembly. */
4852 for (i
= 0; fp_const
[i
]; i
++)
4854 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
4858 *str
+= strlen (fp_const
[i
]);
4859 if (is_end_of_line
[(unsigned char) **str
])
4861 inst
.instruction
|= i
+ 8;
4868 /* Just because we didn't get a match doesn't mean that the
4869 constant isn't valid, just that it is in a format that we
4870 don't automatically recognize. Try parsing it with
4871 the standard expression routines. */
4872 if ((i
= my_get_float_expression (str
)) >= 0)
4874 inst
.instruction
|= i
+ 8;
4878 inst
.error
= _("invalid floating point immediate expression");
4882 _("floating point register or immediate expression expected");
4891 skip_whitespace (str
);
4893 if (reg_required_here (&str
, 12) == FAIL
4894 || skip_past_comma (&str
) == FAIL
4895 || reg_required_here (&str
, 16) == FAIL
4896 || skip_past_comma (&str
) == FAIL
4897 || data_op2 (&str
) == FAIL
)
4900 inst
.error
= BAD_ARGS
;
4912 /* This is a pseudo-op of the form "adr rd, label" to be converted
4913 into a relative address of the form "add rd, pc, #label-.-8". */
4914 skip_whitespace (str
);
4916 if (reg_required_here (&str
, 12) == FAIL
4917 || skip_past_comma (&str
) == FAIL
4918 || my_get_expression (&inst
.reloc
.exp
, &str
))
4921 inst
.error
= BAD_ARGS
;
4925 /* Frag hacking will turn this into a sub instruction if the offset turns
4926 out to be negative. */
4927 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4928 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
4929 inst
.reloc
.pc_rel
= 1;
4938 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4939 into a relative address of the form:
4940 add rd, pc, #low(label-.-8)"
4941 add rd, rd, #high(label-.-8)" */
4943 skip_whitespace (str
);
4945 if (reg_required_here (&str
, 12) == FAIL
4946 || skip_past_comma (&str
) == FAIL
4947 || my_get_expression (&inst
.reloc
.exp
, &str
))
4950 inst
.error
= BAD_ARGS
;
4956 /* Frag hacking will turn this into a sub instruction if the offset turns
4957 out to be negative. */
4958 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
4959 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
4960 inst
.reloc
.pc_rel
= 1;
4961 inst
.size
= INSN_SIZE
* 2;
4970 skip_whitespace (str
);
4972 if (reg_required_here (&str
, 16) == FAIL
)
4975 inst
.error
= BAD_ARGS
;
4979 if (skip_past_comma (&str
) == FAIL
4980 || data_op2 (&str
) == FAIL
)
4983 inst
.error
= BAD_ARGS
;
4995 skip_whitespace (str
);
4997 if (reg_required_here (&str
, 12) == FAIL
)
5000 inst
.error
= BAD_ARGS
;
5004 if (skip_past_comma (&str
) == FAIL
5005 || data_op2 (&str
) == FAIL
)
5008 inst
.error
= BAD_ARGS
;
5027 if (my_get_expression (& inst
.reloc
.exp
, str
))
5030 if (inst
.reloc
.exp
.X_op
== O_constant
)
5032 int value
= inst
.reloc
.exp
.X_add_number
;
5034 if (value
< -4095 || value
> 4095)
5036 inst
.error
= _("address offset too large");
5046 inst
.instruction
|= add
| value
;
5050 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5051 inst
.reloc
.pc_rel
= 0;
5064 if (reg_required_here (str
, 0) == FAIL
)
5067 inst
.instruction
|= add
| OFFSET_REG
;
5068 if (skip_past_comma (str
) == SUCCESS
)
5069 return decode_shift (str
, SHIFT_RESTRICT
);
5083 skip_whitespace (str
);
5085 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
5088 inst
.error
= BAD_ARGS
;
5092 if (skip_past_comma (&str
) == FAIL
)
5094 inst
.error
= _("address expected");
5104 skip_whitespace (str
);
5106 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5109 /* Conflicts can occur on stores as well as loads. */
5110 conflict_reg
= (conflict_reg
== reg
);
5112 skip_whitespace (str
);
5118 if (skip_past_comma (&str
) == SUCCESS
)
5120 /* [Rn],... (post inc) */
5121 if (ldst_extend (&str
) == FAIL
)
5124 as_warn (_("%s register same as write-back base"),
5125 ((inst
.instruction
& LOAD_BIT
)
5126 ? _("destination") : _("source")));
5131 skip_whitespace (str
);
5136 as_warn (_("%s register same as write-back base"),
5137 ((inst
.instruction
& LOAD_BIT
)
5138 ? _("destination") : _("source")));
5140 inst
.instruction
|= WRITE_BACK
;
5143 inst
.instruction
|= INDEX_UP
;
5150 if (skip_past_comma (&str
) == FAIL
)
5152 inst
.error
= _("pre-indexed expression expected");
5157 if (ldst_extend (&str
) == FAIL
)
5160 skip_whitespace (str
);
5164 inst
.error
= _("missing ]");
5168 skip_whitespace (str
);
5173 as_warn (_("%s register same as write-back base"),
5174 ((inst
.instruction
& LOAD_BIT
)
5175 ? _("destination") : _("source")));
5177 inst
.instruction
|= WRITE_BACK
;
5181 else if (*str
== '=')
5183 if ((inst
.instruction
& LOAD_BIT
) == 0)
5185 inst
.error
= _("invalid pseudo operation");
5189 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5192 skip_whitespace (str
);
5194 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5197 if (inst
.reloc
.exp
.X_op
!= O_constant
5198 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5200 inst
.error
= _("constant expression expected");
5204 if (inst
.reloc
.exp
.X_op
== O_constant
)
5206 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5210 /* This can be done with a mov instruction. */
5211 inst
.instruction
&= LITERAL_MASK
;
5212 inst
.instruction
|= (INST_IMMEDIATE
5213 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
5214 inst
.instruction
|= value
& 0xfff;
5219 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
5223 /* This can be done with a mvn instruction. */
5224 inst
.instruction
&= LITERAL_MASK
;
5225 inst
.instruction
|= (INST_IMMEDIATE
5226 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
5227 inst
.instruction
|= value
& 0xfff;
5233 /* Insert into literal pool. */
5234 if (add_to_lit_pool () == FAIL
)
5237 inst
.error
= _("literal pool insertion failed");
5241 /* Change the instruction exp to point to the pool. */
5242 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
5243 inst
.reloc
.pc_rel
= 1;
5244 inst
.instruction
|= (REG_PC
<< 16);
5249 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5252 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5254 /* PC rel adjust. */
5255 inst
.reloc
.exp
.X_add_number
-= 8;
5257 inst
.reloc
.pc_rel
= 1;
5258 inst
.instruction
|= (REG_PC
<< 16);
5262 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5273 skip_whitespace (str
);
5275 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5278 inst
.error
= BAD_ARGS
;
5282 if (skip_past_comma (& str
) == FAIL
)
5284 inst
.error
= _("address expected");
5294 skip_whitespace (str
);
5296 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5299 /* ldrt/strt always use post-indexed addressing, so if the base is
5300 the same as Rd, we warn. */
5301 if (conflict_reg
== reg
)
5302 as_warn (_("%s register same as write-back base"),
5303 ((inst
.instruction
& LOAD_BIT
)
5304 ? _("destination") : _("source")));
5306 skip_whitespace (str
);
5312 if (skip_past_comma (&str
) == SUCCESS
)
5314 /* [Rn],... (post inc) */
5315 if (ldst_extend (&str
) == FAIL
)
5321 skip_whitespace (str
);
5323 /* Skip a write-back '!'. */
5327 inst
.instruction
|= INDEX_UP
;
5332 inst
.error
= _("post-indexed expression expected");
5338 inst
.error
= _("post-indexed expression expected");
5347 ldst_extend_v4 (str
)
5357 if (my_get_expression (& inst
.reloc
.exp
, str
))
5360 if (inst
.reloc
.exp
.X_op
== O_constant
)
5362 int value
= inst
.reloc
.exp
.X_add_number
;
5364 if (value
< -255 || value
> 255)
5366 inst
.error
= _("address offset too large");
5376 /* Halfword and signextension instructions have the
5377 immediate value split across bits 11..8 and bits 3..0. */
5378 inst
.instruction
|= (add
| HWOFFSET_IMM
5379 | ((value
>> 4) << 8) | (value
& 0xF));
5383 inst
.instruction
|= HWOFFSET_IMM
;
5384 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5385 inst
.reloc
.pc_rel
= 0;
5398 if (reg_required_here (str
, 0) == FAIL
)
5401 inst
.instruction
|= add
;
5406 /* Halfword and signed-byte load/store operations. */
5415 skip_whitespace (str
);
5417 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5420 inst
.error
= BAD_ARGS
;
5424 if (skip_past_comma (& str
) == FAIL
)
5426 inst
.error
= _("address expected");
5436 skip_whitespace (str
);
5438 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5441 /* Conflicts can occur on stores as well as loads. */
5442 conflict_reg
= (conflict_reg
== reg
);
5444 skip_whitespace (str
);
5450 if (skip_past_comma (&str
) == SUCCESS
)
5452 /* [Rn],... (post inc) */
5453 if (ldst_extend_v4 (&str
) == FAIL
)
5456 as_warn (_("%s register same as write-back base"),
5457 ((inst
.instruction
& LOAD_BIT
)
5458 ? _("destination") : _("source")));
5463 inst
.instruction
|= HWOFFSET_IMM
;
5465 skip_whitespace (str
);
5470 as_warn (_("%s register same as write-back base"),
5471 ((inst
.instruction
& LOAD_BIT
)
5472 ? _("destination") : _("source")));
5474 inst
.instruction
|= WRITE_BACK
;
5477 inst
.instruction
|= INDEX_UP
;
5484 if (skip_past_comma (&str
) == FAIL
)
5486 inst
.error
= _("pre-indexed expression expected");
5491 if (ldst_extend_v4 (&str
) == FAIL
)
5494 skip_whitespace (str
);
5498 inst
.error
= _("missing ]");
5502 skip_whitespace (str
);
5507 as_warn (_("%s register same as write-back base"),
5508 ((inst
.instruction
& LOAD_BIT
)
5509 ? _("destination") : _("source")));
5511 inst
.instruction
|= WRITE_BACK
;
5515 else if (*str
== '=')
5517 if ((inst
.instruction
& LOAD_BIT
) == 0)
5519 inst
.error
= _("invalid pseudo operation");
5523 /* XXX Does this work correctly for half-word/byte ops? */
5524 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5527 skip_whitespace (str
);
5529 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5532 if (inst
.reloc
.exp
.X_op
!= O_constant
5533 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5535 inst
.error
= _("constant expression expected");
5539 if (inst
.reloc
.exp
.X_op
== O_constant
)
5541 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5545 /* This can be done with a mov instruction. */
5546 inst
.instruction
&= LITERAL_MASK
;
5547 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
5548 inst
.instruction
|= value
& 0xfff;
5553 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
5557 /* This can be done with a mvn instruction. */
5558 inst
.instruction
&= LITERAL_MASK
;
5559 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
5560 inst
.instruction
|= value
& 0xfff;
5566 /* Insert into literal pool. */
5567 if (add_to_lit_pool () == FAIL
)
5570 inst
.error
= _("literal pool insertion failed");
5574 /* Change the instruction exp to point to the pool. */
5575 inst
.instruction
|= HWOFFSET_IMM
;
5576 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
5577 inst
.reloc
.pc_rel
= 1;
5578 inst
.instruction
|= (REG_PC
<< 16);
5583 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5586 inst
.instruction
|= HWOFFSET_IMM
;
5587 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5589 /* PC rel adjust. */
5590 inst
.reloc
.exp
.X_add_number
-= 8;
5592 inst
.reloc
.pc_rel
= 1;
5593 inst
.instruction
|= (REG_PC
<< 16);
5597 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5606 char * str
= * strp
;
5610 /* We come back here if we get ranges concatenated by '+' or '|'. */
5625 skip_whitespace (str
);
5627 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
5636 inst
.error
= _("bad range in register list");
5640 for (i
= cur_reg
+ 1; i
< reg
; i
++)
5642 if (range
& (1 << i
))
5644 (_("Warning: duplicated register (r%d) in register list"),
5652 if (range
& (1 << reg
))
5653 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
5655 else if (reg
<= cur_reg
)
5656 as_tsktsk (_("Warning: register range not in ascending order"));
5661 while (skip_past_comma (&str
) != FAIL
5662 || (in_range
= 1, *str
++ == '-'));
5664 skip_whitespace (str
);
5668 inst
.error
= _("missing `}'");
5676 if (my_get_expression (&expr
, &str
))
5679 if (expr
.X_op
== O_constant
)
5681 if (expr
.X_add_number
5682 != (expr
.X_add_number
& 0x0000ffff))
5684 inst
.error
= _("invalid register mask");
5688 if ((range
& expr
.X_add_number
) != 0)
5690 int regno
= range
& expr
.X_add_number
;
5693 regno
= (1 << regno
) - 1;
5695 (_("Warning: duplicated register (r%d) in register list"),
5699 range
|= expr
.X_add_number
;
5703 if (inst
.reloc
.type
!= 0)
5705 inst
.error
= _("expression too complex");
5709 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
5710 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
5711 inst
.reloc
.pc_rel
= 0;
5715 skip_whitespace (str
);
5717 if (*str
== '|' || *str
== '+')
5723 while (another_range
);
5736 skip_whitespace (str
);
5738 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
5741 if (base_reg
== REG_PC
)
5743 inst
.error
= _("r15 not allowed as base register");
5747 skip_whitespace (str
);
5751 inst
.instruction
|= WRITE_BACK
;
5755 if (skip_past_comma (&str
) == FAIL
5756 || (range
= reg_list (&str
)) == FAIL
)
5759 inst
.error
= BAD_ARGS
;
5766 inst
.instruction
|= LDM_TYPE_2_OR_3
;
5769 if (inst
.instruction
& WRITE_BACK
)
5771 /* Check for unpredictable uses of writeback. */
5772 if (inst
.instruction
& LOAD_BIT
)
5774 /* Not allowed in LDM type 2. */
5775 if ((inst
.instruction
& LDM_TYPE_2_OR_3
)
5776 && ((range
& (1 << REG_PC
)) == 0))
5777 as_warn (_("writeback of base register is UNPREDICTABLE"));
5778 /* Only allowed if base reg not in list for other types. */
5779 else if (range
& (1 << base_reg
))
5780 as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
5784 /* Not allowed for type 2. */
5785 if (inst
.instruction
& LDM_TYPE_2_OR_3
)
5786 as_warn (_("writeback of base register is UNPREDICTABLE"));
5787 /* Only allowed if base reg not in list, or first in list. */
5788 else if ((range
& (1 << base_reg
))
5789 && (range
& ((1 << base_reg
) - 1)))
5790 as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
5794 inst
.instruction
|= range
;
5803 skip_whitespace (str
);
5805 /* Allow optional leading '#'. */
5806 if (is_immediate_prefix (*str
))
5809 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5812 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
5813 inst
.reloc
.pc_rel
= 0;
5825 skip_whitespace (str
);
5827 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5832 inst
.error
= _("r15 not allowed in swap");
5836 if (skip_past_comma (&str
) == FAIL
5837 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
5840 inst
.error
= BAD_ARGS
;
5846 inst
.error
= _("r15 not allowed in swap");
5850 if (skip_past_comma (&str
) == FAIL
5853 inst
.error
= BAD_ARGS
;
5857 skip_whitespace (str
);
5859 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5864 inst
.error
= BAD_PC
;
5868 skip_whitespace (str
);
5872 inst
.error
= _("missing ]");
5884 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5891 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5892 required for the instruction. */
5894 /* arm_parse_reloc () works on input_line_pointer.
5895 We actually want to parse the operands to the branch instruction
5896 passed in 'str'. Save the input pointer and restore it later. */
5897 save_in
= input_line_pointer
;
5898 input_line_pointer
= str
;
5899 if (inst
.reloc
.exp
.X_op
== O_symbol
5901 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5903 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5904 inst
.reloc
.pc_rel
= 0;
5905 /* Modify str to point to after parsed operands, otherwise
5906 end_of_line() will complain about the (PLT) left in str. */
5907 str
= input_line_pointer
;
5911 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5912 inst
.reloc
.pc_rel
= 1;
5914 input_line_pointer
= save_in
;
5917 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5918 inst
.reloc
.pc_rel
= 1;
5919 #endif /* OBJ_ELF */
5931 skip_whitespace (str
);
5933 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
5935 inst
.error
= BAD_ARGS
;
5939 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5941 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
5950 /* Co-processor data operation.
5951 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5952 skip_whitespace (str
);
5954 if (co_proc_number (&str
) == FAIL
)
5957 inst
.error
= BAD_ARGS
;
5961 if (skip_past_comma (&str
) == FAIL
5962 || cp_opc_expr (&str
, 20,4) == FAIL
)
5965 inst
.error
= BAD_ARGS
;
5969 if (skip_past_comma (&str
) == FAIL
5970 || cp_reg_required_here (&str
, 12) == FAIL
)
5973 inst
.error
= BAD_ARGS
;
5977 if (skip_past_comma (&str
) == FAIL
5978 || cp_reg_required_here (&str
, 16) == FAIL
)
5981 inst
.error
= BAD_ARGS
;
5985 if (skip_past_comma (&str
) == FAIL
5986 || cp_reg_required_here (&str
, 0) == FAIL
)
5989 inst
.error
= BAD_ARGS
;
5993 if (skip_past_comma (&str
) == SUCCESS
)
5995 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
5998 inst
.error
= BAD_ARGS
;
6011 /* Co-processor register load/store.
6012 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
6014 skip_whitespace (str
);
6016 if (co_proc_number (&str
) == FAIL
)
6019 inst
.error
= BAD_ARGS
;
6023 if (skip_past_comma (&str
) == FAIL
6024 || cp_reg_required_here (&str
, 12) == FAIL
)
6027 inst
.error
= BAD_ARGS
;
6031 if (skip_past_comma (&str
) == FAIL
6032 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6035 inst
.error
= BAD_ARGS
;
6047 /* Co-processor register transfer.
6048 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
6050 skip_whitespace (str
);
6052 if (co_proc_number (&str
) == FAIL
)
6055 inst
.error
= BAD_ARGS
;
6059 if (skip_past_comma (&str
) == FAIL
6060 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6063 inst
.error
= BAD_ARGS
;
6067 if (skip_past_comma (&str
) == FAIL
6068 || reg_required_here (&str
, 12) == FAIL
)
6071 inst
.error
= BAD_ARGS
;
6075 if (skip_past_comma (&str
) == FAIL
6076 || cp_reg_required_here (&str
, 16) == FAIL
)
6079 inst
.error
= BAD_ARGS
;
6083 if (skip_past_comma (&str
) == FAIL
6084 || cp_reg_required_here (&str
, 0) == FAIL
)
6087 inst
.error
= BAD_ARGS
;
6091 if (skip_past_comma (&str
) == SUCCESS
)
6093 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6096 inst
.error
= BAD_ARGS
;
6109 /* FP control registers.
6110 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6112 skip_whitespace (str
);
6114 if (reg_required_here (&str
, 12) == FAIL
)
6117 inst
.error
= BAD_ARGS
;
6129 skip_whitespace (str
);
6131 if (fp_reg_required_here (&str
, 12) == FAIL
)
6134 inst
.error
= BAD_ARGS
;
6138 if (skip_past_comma (&str
) == FAIL
6139 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6142 inst
.error
= BAD_ARGS
;
6155 skip_whitespace (str
);
6157 if (fp_reg_required_here (&str
, 12) == FAIL
)
6160 inst
.error
= BAD_ARGS
;
6164 /* Get Number of registers to transfer. */
6165 if (skip_past_comma (&str
) == FAIL
6166 || my_get_expression (&inst
.reloc
.exp
, &str
))
6169 inst
.error
= _("constant expression expected");
6173 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6175 inst
.error
= _("constant value required for number of registers");
6179 num_regs
= inst
.reloc
.exp
.X_add_number
;
6181 if (num_regs
< 1 || num_regs
> 4)
6183 inst
.error
= _("number of registers must be in the range [1:4]");
6190 inst
.instruction
|= CP_T_X
;
6193 inst
.instruction
|= CP_T_Y
;
6196 inst
.instruction
|= CP_T_Y
| CP_T_X
;
6204 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
6210 /* The instruction specified "ea" or "fd", so we can only accept
6211 [Rn]{!}. The instruction does not really support stacking or
6212 unstacking, so we have to emulate these by setting appropriate
6213 bits and offsets. */
6214 if (skip_past_comma (&str
) == FAIL
6218 inst
.error
= BAD_ARGS
;
6223 skip_whitespace (str
);
6225 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6228 skip_whitespace (str
);
6232 inst
.error
= BAD_ARGS
;
6244 _("r15 not allowed as base register with write-back");
6251 if (inst
.instruction
& CP_T_Pre
)
6253 /* Pre-decrement. */
6254 offset
= 3 * num_regs
;
6256 inst
.instruction
|= CP_T_WB
;
6260 /* Post-increment. */
6263 inst
.instruction
|= CP_T_WB
;
6264 offset
= 3 * num_regs
;
6268 /* No write-back, so convert this into a standard pre-increment
6269 instruction -- aesthetically more pleasing. */
6270 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
6275 inst
.instruction
|= offset
;
6277 else if (skip_past_comma (&str
) == FAIL
6278 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6281 inst
.error
= BAD_ARGS
;
6292 skip_whitespace (str
);
6294 if (fp_reg_required_here (&str
, 12) == FAIL
)
6297 inst
.error
= BAD_ARGS
;
6301 if (skip_past_comma (&str
) == FAIL
6302 || fp_reg_required_here (&str
, 16) == FAIL
)
6305 inst
.error
= BAD_ARGS
;
6309 if (skip_past_comma (&str
) == FAIL
6310 || fp_op2 (&str
) == FAIL
)
6313 inst
.error
= BAD_ARGS
;
6322 do_fpa_monadic (str
)
6325 skip_whitespace (str
);
6327 if (fp_reg_required_here (&str
, 12) == FAIL
)
6330 inst
.error
= BAD_ARGS
;
6334 if (skip_past_comma (&str
) == FAIL
6335 || fp_op2 (&str
) == FAIL
)
6338 inst
.error
= BAD_ARGS
;
6350 skip_whitespace (str
);
6352 if (fp_reg_required_here (&str
, 16) == FAIL
)
6355 inst
.error
= BAD_ARGS
;
6359 if (skip_past_comma (&str
) == FAIL
6360 || fp_op2 (&str
) == FAIL
)
6363 inst
.error
= BAD_ARGS
;
6372 do_fpa_from_reg (str
)
6375 skip_whitespace (str
);
6377 if (fp_reg_required_here (&str
, 16) == FAIL
)
6380 inst
.error
= BAD_ARGS
;
6384 if (skip_past_comma (&str
) == FAIL
6385 || reg_required_here (&str
, 12) == FAIL
)
6388 inst
.error
= BAD_ARGS
;
6400 skip_whitespace (str
);
6402 if (reg_required_here (&str
, 12) == FAIL
)
6405 if (skip_past_comma (&str
) == FAIL
6406 || fp_reg_required_here (&str
, 0) == FAIL
)
6409 inst
.error
= BAD_ARGS
;
6418 vfp_sp_reg_required_here (str
, pos
)
6420 enum vfp_sp_reg_pos pos
;
6425 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
6430 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
6434 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
6438 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
6447 /* In the few cases where we might be able to accept something else
6448 this error can be overridden. */
6449 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
6451 /* Restore the start point. */
6457 vfp_dp_reg_required_here (str
, pos
)
6459 enum vfp_dp_reg_pos pos
;
6464 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
6469 inst
.instruction
|= reg
<< 12;
6473 inst
.instruction
|= reg
<< 16;
6477 inst
.instruction
|= reg
<< 0;
6486 /* In the few cases where we might be able to accept something else
6487 this error can be overridden. */
6488 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
6490 /* Restore the start point. */
6496 do_vfp_sp_monadic (str
)
6499 skip_whitespace (str
);
6501 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6504 if (skip_past_comma (&str
) == FAIL
6505 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
6508 inst
.error
= BAD_ARGS
;
6517 do_vfp_dp_monadic (str
)
6520 skip_whitespace (str
);
6522 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6525 if (skip_past_comma (&str
) == FAIL
6526 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6529 inst
.error
= BAD_ARGS
;
6538 do_vfp_sp_dyadic (str
)
6541 skip_whitespace (str
);
6543 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6546 if (skip_past_comma (&str
) == FAIL
6547 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
6548 || skip_past_comma (&str
) == FAIL
6549 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
6552 inst
.error
= BAD_ARGS
;
6561 do_vfp_dp_dyadic (str
)
6564 skip_whitespace (str
);
6566 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6569 if (skip_past_comma (&str
) == FAIL
6570 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
6571 || skip_past_comma (&str
) == FAIL
6572 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6575 inst
.error
= BAD_ARGS
;
6584 do_vfp_reg_from_sp (str
)
6587 skip_whitespace (str
);
6589 if (reg_required_here (&str
, 12) == FAIL
)
6592 if (skip_past_comma (&str
) == FAIL
6593 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
6596 inst
.error
= BAD_ARGS
;
6605 do_vfp_sp_reg2 (str
)
6608 skip_whitespace (str
);
6610 if (reg_required_here (&str
, 12) == FAIL
)
6613 if (skip_past_comma (&str
) == FAIL
6614 || reg_required_here (&str
, 16) == FAIL
6615 || skip_past_comma (&str
) == FAIL
)
6618 inst
.error
= BAD_ARGS
;
6622 /* We require exactly two consecutive SP registers. */
6623 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
6626 inst
.error
= _("only two consecutive VFP SP registers allowed here");
6634 do_vfp_sp_from_reg (str
)
6637 skip_whitespace (str
);
6639 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
6642 if (skip_past_comma (&str
) == FAIL
6643 || reg_required_here (&str
, 12) == FAIL
)
6646 inst
.error
= BAD_ARGS
;
6655 do_vfp_reg_from_dp (str
)
6658 skip_whitespace (str
);
6660 if (reg_required_here (&str
, 12) == FAIL
)
6663 if (skip_past_comma (&str
) == FAIL
6664 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
6667 inst
.error
= BAD_ARGS
;
6676 do_vfp_reg2_from_dp (str
)
6679 skip_whitespace (str
);
6681 if (reg_required_here (&str
, 12) == FAIL
)
6684 if (skip_past_comma (&str
) == FAIL
6685 || reg_required_here (&str
, 16) == FAIL
6686 || skip_past_comma (&str
) == FAIL
6687 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6690 inst
.error
= BAD_ARGS
;
6699 do_vfp_dp_from_reg (str
)
6702 skip_whitespace (str
);
6704 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
6707 if (skip_past_comma (&str
) == FAIL
6708 || reg_required_here (&str
, 12) == FAIL
)
6711 inst
.error
= BAD_ARGS
;
6720 do_vfp_dp_from_reg2 (str
)
6723 skip_whitespace (str
);
6725 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6728 if (skip_past_comma (&str
) == FAIL
6729 || reg_required_here (&str
, 12) == FAIL
6730 || skip_past_comma (&str
) == FAIL
6731 || reg_required_here (&str
, 16))
6734 inst
.error
= BAD_ARGS
;
6742 static const struct vfp_reg
*
6749 const struct vfp_reg
*vreg
;
6753 /* Find the end of the current token. */
6758 while (ISALPHA (c
));
6763 for (vreg
= vfp_regs
+ 0;
6764 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
6767 if (strcmp (start
, vreg
->name
) == 0)
6780 vfp_psr_required_here (str
)
6784 const struct vfp_reg
*vreg
;
6786 vreg
= vfp_psr_parse (str
);
6790 inst
.instruction
|= vreg
->regno
;
6794 inst
.error
= _("VFP system register expected");
6801 do_vfp_reg_from_ctrl (str
)
6804 skip_whitespace (str
);
6806 if (reg_required_here (&str
, 12) == FAIL
)
6809 if (skip_past_comma (&str
) == FAIL
6810 || vfp_psr_required_here (&str
) == FAIL
)
6813 inst
.error
= BAD_ARGS
;
6822 do_vfp_ctrl_from_reg (str
)
6825 skip_whitespace (str
);
6827 if (vfp_psr_required_here (&str
) == FAIL
)
6830 if (skip_past_comma (&str
) == FAIL
6831 || reg_required_here (&str
, 12) == FAIL
)
6834 inst
.error
= BAD_ARGS
;
6843 do_vfp_sp_ldst (str
)
6846 skip_whitespace (str
);
6848 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6851 inst
.error
= BAD_ARGS
;
6855 if (skip_past_comma (&str
) == FAIL
6856 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
6859 inst
.error
= BAD_ARGS
;
6868 do_vfp_dp_ldst (str
)
6871 skip_whitespace (str
);
6873 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6876 inst
.error
= BAD_ARGS
;
6880 if (skip_past_comma (&str
) == FAIL
6881 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
6884 inst
.error
= BAD_ARGS
;
6892 /* Parse and encode a VFP SP register list, storing the initial
6893 register in position POS and returning the range as the result. If
6894 the string is invalid return FAIL (an invalid range). */
6896 vfp_sp_reg_list (str
, pos
)
6898 enum vfp_sp_reg_pos pos
;
6906 unsigned long mask
= 0;
6913 skip_whitespace (*str
);
6915 tempinst
= inst
.instruction
;
6919 inst
.instruction
= 0;
6921 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
6924 if (count
== 0 || base_reg
> new_base
)
6926 base_reg
= new_base
;
6927 base_bits
= inst
.instruction
;
6930 if (mask
& (1 << new_base
))
6932 inst
.error
= _("invalid register list");
6936 if ((mask
>> new_base
) != 0 && ! warned
)
6938 as_tsktsk (_("register list not in ascending order"));
6942 mask
|= 1 << new_base
;
6945 skip_whitespace (*str
);
6947 if (**str
== '-') /* We have the start of a range expression */
6954 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
6957 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
6961 if (high_range
<= new_base
)
6963 inst
.error
= _("register range not in ascending order");
6967 for (new_base
++; new_base
<= high_range
; new_base
++)
6969 if (mask
& (1 << new_base
))
6971 inst
.error
= _("invalid register list");
6975 mask
|= 1 << new_base
;
6980 while (skip_past_comma (str
) != FAIL
);
6984 inst
.error
= _("invalid register list");
6992 /* Sanity check -- should have raised a parse error above. */
6993 if (count
== 0 || count
> 32)
6996 /* Final test -- the registers must be consecutive. */
6999 if ((mask
& (1 << base_reg
++)) == 0)
7001 inst
.error
= _("non-contiguous register range");
7006 inst
.instruction
= tempinst
| base_bits
;
7011 vfp_dp_reg_list (str
)
7019 unsigned long mask
= 0;
7026 skip_whitespace (*str
);
7028 tempinst
= inst
.instruction
;
7032 inst
.instruction
= 0;
7034 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
7037 if (count
== 0 || base_reg
> new_base
)
7039 base_reg
= new_base
;
7040 range
= inst
.instruction
;
7043 if (mask
& (1 << new_base
))
7045 inst
.error
= _("invalid register list");
7049 if ((mask
>> new_base
) != 0 && ! warned
)
7051 as_tsktsk (_("register list not in ascending order"));
7055 mask
|= 1 << new_base
;
7058 skip_whitespace (*str
);
7060 if (**str
== '-') /* We have the start of a range expression */
7067 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7070 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7074 if (high_range
<= new_base
)
7076 inst
.error
= _("register range not in ascending order");
7080 for (new_base
++; new_base
<= high_range
; new_base
++)
7082 if (mask
& (1 << new_base
))
7084 inst
.error
= _("invalid register list");
7088 mask
|= 1 << new_base
;
7093 while (skip_past_comma (str
) != FAIL
);
7097 inst
.error
= _("invalid register list");
7105 /* Sanity check -- should have raised a parse error above. */
7106 if (count
== 0 || count
> 16)
7109 /* Final test -- the registers must be consecutive. */
7112 if ((mask
& (1 << base_reg
++)) == 0)
7114 inst
.error
= _("non-contiguous register range");
7119 inst
.instruction
= tempinst
;
7124 vfp_sp_ldstm (str
, ldstm_type
)
7126 enum vfp_ldstm_type ldstm_type
;
7130 skip_whitespace (str
);
7132 if (reg_required_here (&str
, 16) == FAIL
)
7135 skip_whitespace (str
);
7139 inst
.instruction
|= WRITE_BACK
;
7142 else if (ldstm_type
!= VFP_LDSTMIA
)
7144 inst
.error
= _("this addressing mode requires base-register writeback");
7148 if (skip_past_comma (&str
) == FAIL
7149 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
7152 inst
.error
= BAD_ARGS
;
7156 inst
.instruction
|= range
;
7161 vfp_dp_ldstm (str
, ldstm_type
)
7163 enum vfp_ldstm_type ldstm_type
;
7167 skip_whitespace (str
);
7169 if (reg_required_here (&str
, 16) == FAIL
)
7172 skip_whitespace (str
);
7176 inst
.instruction
|= WRITE_BACK
;
7179 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7181 inst
.error
= _("this addressing mode requires base-register writeback");
7185 if (skip_past_comma (&str
) == FAIL
7186 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
7189 inst
.error
= BAD_ARGS
;
7193 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7196 inst
.instruction
|= range
;
7201 do_vfp_sp_ldstmia (str
)
7204 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7208 do_vfp_sp_ldstmdb (str
)
7211 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7215 do_vfp_dp_ldstmia (str
)
7218 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
7222 do_vfp_dp_ldstmdb (str
)
7225 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
7229 do_vfp_xp_ldstmia (str
)
7232 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
7236 do_vfp_xp_ldstmdb (str
)
7239 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
7243 do_vfp_sp_compare_z (str
)
7246 skip_whitespace (str
);
7248 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7251 inst
.error
= BAD_ARGS
;
7260 do_vfp_dp_compare_z (str
)
7263 skip_whitespace (str
);
7265 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7268 inst
.error
= BAD_ARGS
;
7277 do_vfp_dp_sp_cvt (str
)
7280 skip_whitespace (str
);
7282 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7285 if (skip_past_comma (&str
) == FAIL
7286 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7289 inst
.error
= BAD_ARGS
;
7298 do_vfp_sp_dp_cvt (str
)
7301 skip_whitespace (str
);
7303 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7306 if (skip_past_comma (&str
) == FAIL
7307 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7310 inst
.error
= BAD_ARGS
;
7318 /* Thumb specific routines. */
7320 /* Parse and validate that a register is of the right form, this saves
7321 repeated checking of this information in many similar cases.
7322 Unlike the 32-bit case we do not insert the register into the opcode
7323 here, since the position is often unknown until the full instruction
7327 thumb_reg (strp
, hi_lo
)
7333 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
7341 inst
.error
= _("lo register required");
7349 inst
.error
= _("hi register required");
7361 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
7365 thumb_add_sub (str
, subtract
)
7369 int Rd
, Rs
, Rn
= FAIL
;
7371 skip_whitespace (str
);
7373 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
7374 || skip_past_comma (&str
) == FAIL
)
7377 inst
.error
= BAD_ARGS
;
7381 if (is_immediate_prefix (*str
))
7385 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7390 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7393 if (skip_past_comma (&str
) == FAIL
)
7395 /* Two operand format, shuffle the registers
7396 and pretend there are 3. */
7400 else if (is_immediate_prefix (*str
))
7403 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7406 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7410 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7411 for the latter case, EXPR contains the immediate that was found. */
7414 /* All register format. */
7415 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
7419 inst
.error
= _("dest and source1 must be the same register");
7423 /* Can't do this for SUB. */
7426 inst
.error
= _("subtract valid only on lo regs");
7430 inst
.instruction
= (T_OPCODE_ADD_HI
7431 | (Rd
> 7 ? THUMB_H1
: 0)
7432 | (Rn
> 7 ? THUMB_H2
: 0));
7433 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
7437 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
7438 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
7443 /* Immediate expression, now things start to get nasty. */
7445 /* First deal with HI regs, only very restricted cases allowed:
7446 Adjusting SP, and using PC or SP to get an address. */
7447 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
7448 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
7450 inst
.error
= _("invalid Hi register with immediate");
7454 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7456 /* Value isn't known yet, all we can do is store all the fragments
7457 we know about in the instruction and let the reloc hacking
7459 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
7460 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
7464 int offset
= inst
.reloc
.exp
.X_add_number
;
7474 /* Quick check, in case offset is MIN_INT. */
7477 inst
.error
= _("immediate value out of range");
7481 /* Note - you cannot convert a subtract of 0 into an
7482 add of 0 because the carry flag is set differently. */
7483 else if (offset
> 0)
7488 if (offset
& ~0x1fc)
7490 inst
.error
= _("invalid immediate value for stack adjust");
7493 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
7494 inst
.instruction
|= offset
>> 2;
7496 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
7499 || (offset
& ~0x3fc))
7501 inst
.error
= _("invalid immediate for address calculation");
7504 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
7506 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
7512 inst
.error
= _("immediate value out of range");
7515 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
7516 inst
.instruction
|= (Rd
<< 8) | offset
;
7522 inst
.error
= _("immediate value out of range");
7525 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
7526 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
7535 thumb_shift (str
, shift
)
7539 int Rd
, Rs
, Rn
= FAIL
;
7541 skip_whitespace (str
);
7543 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7544 || skip_past_comma (&str
) == FAIL
)
7547 inst
.error
= BAD_ARGS
;
7551 if (is_immediate_prefix (*str
))
7553 /* Two operand immediate format, set Rs to Rd. */
7556 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7561 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7564 if (skip_past_comma (&str
) == FAIL
)
7566 /* Two operand format, shuffle the registers
7567 and pretend there are 3. */
7571 else if (is_immediate_prefix (*str
))
7574 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7577 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7581 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7582 for the latter case, EXPR contains the immediate that was found. */
7588 inst
.error
= _("source1 and dest must be same register");
7594 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
7595 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
7596 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
7599 inst
.instruction
|= Rd
| (Rn
<< 3);
7605 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
7606 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
7607 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
7610 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7612 /* Value isn't known yet, create a dummy reloc and let reloc
7613 hacking fix it up. */
7614 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
7618 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
7620 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
7622 inst
.error
= _("invalid immediate for shift");
7626 /* Shifts of zero are handled by converting to LSL. */
7627 if (shift_value
== 0)
7628 inst
.instruction
= T_OPCODE_LSL_I
;
7630 /* Shifts of 32 are encoded as a shift of zero. */
7631 if (shift_value
== 32)
7634 inst
.instruction
|= shift_value
<< 6;
7637 inst
.instruction
|= Rd
| (Rs
<< 3);
7644 thumb_mov_compare (str
, move
)
7650 skip_whitespace (str
);
7652 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
7653 || skip_past_comma (&str
) == FAIL
)
7656 inst
.error
= BAD_ARGS
;
7660 if (is_immediate_prefix (*str
))
7663 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7666 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7671 if (Rs
< 8 && Rd
< 8)
7673 if (move
== THUMB_MOVE
)
7674 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
7675 since a MOV instruction produces unpredictable results. */
7676 inst
.instruction
= T_OPCODE_ADD_I3
;
7678 inst
.instruction
= T_OPCODE_CMP_LR
;
7679 inst
.instruction
|= Rd
| (Rs
<< 3);
7683 if (move
== THUMB_MOVE
)
7684 inst
.instruction
= T_OPCODE_MOV_HR
;
7686 inst
.instruction
= T_OPCODE_CMP_HR
;
7689 inst
.instruction
|= THUMB_H1
;
7692 inst
.instruction
|= THUMB_H2
;
7694 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
7701 inst
.error
= _("only lo regs allowed with immediate");
7705 if (move
== THUMB_MOVE
)
7706 inst
.instruction
= T_OPCODE_MOV_I8
;
7708 inst
.instruction
= T_OPCODE_CMP_I8
;
7710 inst
.instruction
|= Rd
<< 8;
7712 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7713 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
7716 unsigned value
= inst
.reloc
.exp
.X_add_number
;
7720 inst
.error
= _("invalid immediate");
7724 inst
.instruction
|= value
;
7732 thumb_load_store (str
, load_store
, size
)
7737 int Rd
, Rb
, Ro
= FAIL
;
7739 skip_whitespace (str
);
7741 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7742 || skip_past_comma (&str
) == FAIL
)
7745 inst
.error
= BAD_ARGS
;
7752 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7755 if (skip_past_comma (&str
) != FAIL
)
7757 if (is_immediate_prefix (*str
))
7760 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7763 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7768 inst
.reloc
.exp
.X_op
= O_constant
;
7769 inst
.reloc
.exp
.X_add_number
= 0;
7774 inst
.error
= _("expected ']'");
7779 else if (*str
== '=')
7781 if (load_store
!= THUMB_LOAD
)
7783 inst
.error
= _("invalid pseudo operation");
7787 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7790 skip_whitespace (str
);
7792 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7797 if ( inst
.reloc
.exp
.X_op
!= O_constant
7798 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7800 inst
.error
= "Constant expression expected";
7804 if (inst
.reloc
.exp
.X_op
== O_constant
7805 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
7807 /* This can be done with a mov instruction. */
7809 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
7810 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7814 /* Insert into literal pool. */
7815 if (add_to_lit_pool () == FAIL
)
7818 inst
.error
= "literal pool insertion failed";
7822 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7823 inst
.reloc
.pc_rel
= 1;
7824 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
7825 /* Adjust ARM pipeline offset to Thumb. */
7826 inst
.reloc
.exp
.X_add_number
+= 4;
7832 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7835 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
7836 inst
.reloc
.pc_rel
= 1;
7837 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
7838 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7843 if (Rb
== REG_PC
|| Rb
== REG_SP
)
7845 if (size
!= THUMB_WORD
)
7847 inst
.error
= _("byte or halfword not valid for base register");
7850 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
7852 inst
.error
= _("r15 based store not allowed");
7855 else if (Ro
!= FAIL
)
7857 inst
.error
= _("invalid base register for register offset");
7862 inst
.instruction
= T_OPCODE_LDR_PC
;
7863 else if (load_store
== THUMB_LOAD
)
7864 inst
.instruction
= T_OPCODE_LDR_SP
;
7866 inst
.instruction
= T_OPCODE_STR_SP
;
7868 inst
.instruction
|= Rd
<< 8;
7869 if (inst
.reloc
.exp
.X_op
== O_constant
)
7871 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
7873 if (offset
& ~0x3fc)
7875 inst
.error
= _("invalid offset");
7879 inst
.instruction
|= offset
>> 2;
7882 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7886 inst
.error
= _("invalid base register in load/store");
7889 else if (Ro
== FAIL
)
7891 /* Immediate offset. */
7892 if (size
== THUMB_WORD
)
7893 inst
.instruction
= (load_store
== THUMB_LOAD
7894 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
7895 else if (size
== THUMB_HALFWORD
)
7896 inst
.instruction
= (load_store
== THUMB_LOAD
7897 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
7899 inst
.instruction
= (load_store
== THUMB_LOAD
7900 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
7902 inst
.instruction
|= Rd
| (Rb
<< 3);
7904 if (inst
.reloc
.exp
.X_op
== O_constant
)
7906 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
7908 if (offset
& ~(0x1f << size
))
7910 inst
.error
= _("invalid offset");
7913 inst
.instruction
|= (offset
>> size
) << 6;
7916 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7920 /* Register offset. */
7921 if (size
== THUMB_WORD
)
7922 inst
.instruction
= (load_store
== THUMB_LOAD
7923 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
7924 else if (size
== THUMB_HALFWORD
)
7925 inst
.instruction
= (load_store
== THUMB_LOAD
7926 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
7928 inst
.instruction
= (load_store
== THUMB_LOAD
7929 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
7931 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
7937 /* A register must be given at this point.
7939 Shift is the place to put it in inst.instruction.
7941 Restores input start point on err.
7942 Returns the reg#, or FAIL. */
7945 mav_reg_required_here (str
, shift
, regtype
)
7948 enum arm_reg_type regtype
;
7953 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
7956 inst
.instruction
|= reg
<< shift
;
7961 /* Restore the start point. */
7964 /* In the few cases where we might be able to accept something else
7965 this error can be overridden. */
7966 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7971 /* Cirrus Maverick Instructions. */
7973 /* Wrapper functions. */
7976 do_mav_binops_1a (str
)
7979 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
7983 do_mav_binops_1b (str
)
7986 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
7990 do_mav_binops_1c (str
)
7993 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
7997 do_mav_binops_1d (str
)
8000 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8004 do_mav_binops_1e (str
)
8007 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8011 do_mav_binops_1f (str
)
8014 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
8018 do_mav_binops_1g (str
)
8021 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
8025 do_mav_binops_1h (str
)
8028 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
8032 do_mav_binops_1i (str
)
8035 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
8039 do_mav_binops_1j (str
)
8042 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
8046 do_mav_binops_1k (str
)
8049 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
8053 do_mav_binops_1l (str
)
8056 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
8060 do_mav_binops_1m (str
)
8063 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8067 do_mav_binops_1n (str
)
8070 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8074 do_mav_binops_1o (str
)
8077 do_mav_binops (str
, MAV_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8081 do_mav_binops_2a (str
)
8084 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8088 do_mav_binops_2b (str
)
8091 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8095 do_mav_binops_2c (str
)
8098 do_mav_binops (str
, MAV_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8102 do_mav_binops_3a (str
)
8105 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8109 do_mav_binops_3b (str
)
8112 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8116 do_mav_binops_3c (str
)
8119 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8123 do_mav_binops_3d (str
)
8126 do_mav_binops (str
, MAV_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8130 do_mav_triple_4a (str
)
8133 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8137 do_mav_triple_4b (str
)
8140 do_mav_triple (str
, MAV_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8144 do_mav_triple_5a (str
)
8147 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8151 do_mav_triple_5b (str
)
8154 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8158 do_mav_triple_5c (str
)
8161 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8165 do_mav_triple_5d (str
)
8168 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8172 do_mav_triple_5e (str
)
8175 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8179 do_mav_triple_5f (str
)
8182 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8186 do_mav_triple_5g (str
)
8189 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8193 do_mav_triple_5h (str
)
8196 do_mav_triple (str
, MAV_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8200 do_mav_quad_6a (str
)
8203 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8208 do_mav_quad_6b (str
)
8211 do_mav_quad (str
, MAV_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8215 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
8217 do_mav_dspsc_1 (str
)
8220 skip_whitespace (str
);
8223 if (mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8224 || skip_past_comma (&str
) == FAIL
8225 || mav_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
8228 inst
.error
= BAD_ARGS
;
8236 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
8238 do_mav_dspsc_2 (str
)
8241 skip_whitespace (str
);
8244 if (mav_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
8245 || skip_past_comma (&str
) == FAIL
8246 || mav_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8249 inst
.error
= BAD_ARGS
;
8258 do_mav_shift_1 (str
)
8261 do_mav_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8265 do_mav_shift_2 (str
)
8268 do_mav_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8275 do_mav_ldst (str
, REG_TYPE_MVF
);
8282 do_mav_ldst (str
, REG_TYPE_MVD
);
8289 do_mav_ldst (str
, REG_TYPE_MVFX
);
8296 do_mav_ldst (str
, REG_TYPE_MVDX
);
8299 /* Isnsn like "foo X,Y". */
8302 do_mav_binops (str
, mode
, reg0
, reg1
)
8305 enum arm_reg_type reg0
;
8306 enum arm_reg_type reg1
;
8310 shift0
= mode
& 0xff;
8311 shift1
= (mode
>> 8) & 0xff;
8313 skip_whitespace (str
);
8315 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8316 || skip_past_comma (&str
) == FAIL
8317 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8320 inst
.error
= BAD_ARGS
;
8326 /* Isnsn like "foo X,Y,Z". */
8329 do_mav_triple (str
, mode
, reg0
, reg1
, reg2
)
8332 enum arm_reg_type reg0
;
8333 enum arm_reg_type reg1
;
8334 enum arm_reg_type reg2
;
8336 int shift0
, shift1
, shift2
;
8338 shift0
= mode
& 0xff;
8339 shift1
= (mode
>> 8) & 0xff;
8340 shift2
= (mode
>> 16) & 0xff;
8342 skip_whitespace (str
);
8344 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8345 || skip_past_comma (&str
) == FAIL
8346 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8347 || skip_past_comma (&str
) == FAIL
8348 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8351 inst
.error
= BAD_ARGS
;
8357 /* Isnsn like "foo W,X,Y,Z".
8358 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8361 do_mav_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
8364 enum arm_reg_type reg0
;
8365 enum arm_reg_type reg1
;
8366 enum arm_reg_type reg2
;
8367 enum arm_reg_type reg3
;
8369 int shift0
, shift1
, shift2
, shift3
;
8371 shift0
= mode
& 0xff;
8372 shift1
= (mode
>> 8) & 0xff;
8373 shift2
= (mode
>> 16) & 0xff;
8374 shift3
= (mode
>> 24) & 0xff;
8376 skip_whitespace (str
);
8378 if (mav_reg_required_here (&str
, shift0
, reg0
) == FAIL
8379 || skip_past_comma (&str
) == FAIL
8380 || mav_reg_required_here (&str
, shift1
, reg1
) == FAIL
8381 || skip_past_comma (&str
) == FAIL
8382 || mav_reg_required_here (&str
, shift2
, reg2
) == FAIL
8383 || skip_past_comma (&str
) == FAIL
8384 || mav_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8387 inst
.error
= BAD_ARGS
;
8393 /* Maverick shift immediate instructions.
8394 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8395 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8398 do_mav_shift (str
, reg0
, reg1
)
8400 enum arm_reg_type reg0
;
8401 enum arm_reg_type reg1
;
8406 skip_whitespace (str
);
8410 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8411 || skip_past_comma (&str
) == FAIL
8412 || mav_reg_required_here (&str
, 16, reg1
) == FAIL
8413 || skip_past_comma (&str
) == FAIL
)
8416 inst
.error
= BAD_ARGS
;
8420 /* Calculate the immediate operand.
8421 The operand is a 7bit signed number. */
8422 skip_whitespace (str
);
8427 if (!ISDIGIT (*str
) && *str
!= '-')
8429 inst
.error
= _("expecting immediate, 7bit operand");
8439 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
8440 imm
= imm
* 10 + *str
- '0';
8444 inst
.error
= _("immediate out of range");
8448 /* Make negative imm's into 7bit signed numbers. */
8455 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
8456 Bits 5-7 of the insn should have bits 4-6 of the immediate.
8457 Bit 4 should be 0. */
8458 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
8460 inst
.instruction
|= imm
;
8465 mav_parse_offset (str
, negative
)
8474 skip_whitespace (p
);
8487 inst
.error
= _("offset expected");
8491 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
8492 offset
= offset
* 10 + *p
- '0';
8496 inst
.error
= _("offset out of range");
8502 return *negative
? -offset
: offset
;
8505 /* Maverick load/store instructions.
8506 <insn><cond> CRd,[Rn,<offset>]{!}.
8507 <insn><cond> CRd,[Rn],<offset>. */
8510 do_mav_ldst (str
, reg0
)
8512 enum arm_reg_type reg0
;
8514 int offset
, negative
;
8516 skip_whitespace (str
);
8518 if (mav_reg_required_here (&str
, 12, reg0
) == FAIL
8519 || skip_past_comma (&str
) == FAIL
8521 || reg_required_here (&str
, 16) == FAIL
)
8524 if (skip_past_comma (&str
) == SUCCESS
)
8526 /* You are here: "<offset>]{!}". */
8527 inst
.instruction
|= PRE_INDEX
;
8529 offset
= mav_parse_offset (&str
, &negative
);
8536 inst
.error
= _("missing ]");
8542 inst
.instruction
|= WRITE_BACK
;
8548 /* You are here: "], <offset>". */
8551 inst
.error
= _("missing ]");
8555 if (skip_past_comma (&str
) == FAIL
8556 || (offset
= mav_parse_offset (&str
, &negative
), inst
.error
))
8559 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
8565 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
8567 inst
.instruction
|= offset
>> 2;
8573 inst
.error
= BAD_ARGS
;
8586 /* Handle the Format 4 instructions that do not have equivalents in other
8587 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
8596 skip_whitespace (str
);
8598 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8599 || skip_past_comma (&str
) == FAIL
8600 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8602 inst
.error
= BAD_ARGS
;
8606 if (skip_past_comma (&str
) != FAIL
)
8608 /* Three operand format not allowed for TST, CMN, NEG and MVN.
8609 (It isn't allowed for CMP either, but that isn't handled by this
8611 if (inst
.instruction
== T_OPCODE_TST
8612 || inst
.instruction
== T_OPCODE_CMN
8613 || inst
.instruction
== T_OPCODE_NEG
8614 || inst
.instruction
== T_OPCODE_MVN
)
8616 inst
.error
= BAD_ARGS
;
8620 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8625 inst
.error
= _("dest and source1 must be the same register");
8631 if (inst
.instruction
== T_OPCODE_MUL
8633 as_tsktsk (_("Rs and Rd must be different in MUL"));
8635 inst
.instruction
|= Rd
| (Rs
<< 3);
8643 thumb_add_sub (str
, 0);
8650 thumb_shift (str
, THUMB_ASR
);
8657 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8659 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
8660 inst
.reloc
.pc_rel
= 1;
8668 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8670 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
8671 inst
.reloc
.pc_rel
= 1;
8675 /* Find the real, Thumb encoded start of a Thumb function. */
8678 find_real_start (symbolP
)
8682 const char * name
= S_GET_NAME (symbolP
);
8683 symbolS
* new_target
;
8685 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
8686 #define STUB_NAME ".real_start_of"
8691 /* Names that start with '.' are local labels, not function entry points.
8692 The compiler may generate BL instructions to these labels because it
8693 needs to perform a branch to a far away location. */
8697 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
8698 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
8700 new_target
= symbol_find (real_start
);
8702 if (new_target
== NULL
)
8704 as_warn ("Failed to find real start of function: %s\n", name
);
8705 new_target
= symbolP
;
8717 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8720 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
8721 inst
.reloc
.pc_rel
= 1;
8724 /* If the destination of the branch is a defined symbol which does not have
8725 the THUMB_FUNC attribute, then we must be calling a function which has
8726 the (interfacearm) attribute. We look for the Thumb entry point to that
8727 function and change the branch to refer to that function instead. */
8728 if ( inst
.reloc
.exp
.X_op
== O_symbol
8729 && inst
.reloc
.exp
.X_add_symbol
!= NULL
8730 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
8731 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
8732 inst
.reloc
.exp
.X_add_symbol
=
8733 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
8742 skip_whitespace (str
);
8744 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8747 /* This sets THUMB_H2 from the top bit of reg. */
8748 inst
.instruction
|= reg
<< 3;
8750 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
8751 should cause the alignment to be checked once it is known. This is
8752 because BX PC only works if the instruction is word aligned. */
8761 thumb_mov_compare (str
, THUMB_COMPARE
);
8771 skip_whitespace (str
);
8773 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8777 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
8781 if (skip_past_comma (&str
) == FAIL
8782 || (range
= reg_list (&str
)) == FAIL
)
8785 inst
.error
= BAD_ARGS
;
8789 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8791 /* This really doesn't seem worth it. */
8792 inst
.reloc
.type
= BFD_RELOC_NONE
;
8793 inst
.error
= _("expression too complex");
8799 inst
.error
= _("only lo-regs valid in load/store multiple");
8803 inst
.instruction
|= (Rb
<< 8) | range
;
8811 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
8818 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
8825 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
8834 skip_whitespace (str
);
8836 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8837 || skip_past_comma (&str
) == FAIL
8839 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8840 || skip_past_comma (&str
) == FAIL
8841 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8845 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
8849 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8857 thumb_shift (str
, THUMB_LSL
);
8864 thumb_shift (str
, THUMB_LSR
);
8871 thumb_mov_compare (str
, THUMB_MOVE
);
8880 skip_whitespace (str
);
8882 if ((range
= reg_list (&str
)) == FAIL
)
8885 inst
.error
= BAD_ARGS
;
8889 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8891 /* This really doesn't seem worth it. */
8892 inst
.reloc
.type
= BFD_RELOC_NONE
;
8893 inst
.error
= _("expression too complex");
8899 if ((inst
.instruction
== T_OPCODE_PUSH
8900 && (range
& ~0xff) == 1 << REG_LR
)
8901 || (inst
.instruction
== T_OPCODE_POP
8902 && (range
& ~0xff) == 1 << REG_PC
))
8904 inst
.instruction
|= THUMB_PP_PC_LR
;
8909 inst
.error
= _("invalid register list to push/pop instruction");
8914 inst
.instruction
|= range
;
8922 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
8929 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
8936 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
8943 thumb_add_sub (str
, 1);
8950 skip_whitespace (str
);
8952 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8955 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8966 /* This is a pseudo-op of the form "adr rd, label" to be converted
8967 into a relative address of the form "add rd, pc, #label-.-4". */
8968 skip_whitespace (str
);
8970 /* Store Rd in temporary location inside instruction. */
8971 if ((reg
= reg_required_here (&str
, 4)) == FAIL
8972 || (reg
> 7) /* For Thumb reg must be r0..r7. */
8973 || skip_past_comma (&str
) == FAIL
8974 || my_get_expression (&inst
.reloc
.exp
, &str
))
8977 inst
.error
= BAD_ARGS
;
8981 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8982 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
8983 inst
.reloc
.pc_rel
= 1;
8984 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
8990 insert_reg (r
, htab
)
8991 const struct reg_entry
*r
;
8992 struct hash_control
*htab
;
8994 int len
= strlen (r
->name
) + 2;
8995 char * buf
= (char *) xmalloc (len
);
8996 char * buf2
= (char *) xmalloc (len
);
8999 #ifdef REGISTER_PREFIX
9000 buf
[i
++] = REGISTER_PREFIX
;
9003 strcpy (buf
+ i
, r
->name
);
9005 for (i
= 0; buf
[i
]; i
++)
9006 buf2
[i
] = TOUPPER (buf
[i
]);
9010 hash_insert (htab
, buf
, (PTR
) r
);
9011 hash_insert (htab
, buf2
, (PTR
) r
);
9016 struct reg_map
*map
;
9018 const struct reg_entry
*r
;
9020 if ((map
->htab
= hash_new ()) == NULL
)
9021 as_fatal (_("virtual memory exhausted"));
9023 for (r
= map
->names
; r
->name
!= NULL
; r
++)
9024 insert_reg (r
, map
->htab
);
9028 insert_reg_alias (str
, regnum
, htab
)
9031 struct hash_control
*htab
;
9033 struct reg_entry
*new =
9034 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
9035 char *name
= xmalloc (strlen (str
) + 1);
9039 new->number
= regnum
;
9041 hash_insert (htab
, name
, (PTR
) new);
9044 /* Look for the .req directive. This is of the form:
9046 newname .req existing_name
9048 If we find one, or if it looks sufficiently like one that we want to
9049 handle any error here, return non-zero. Otherwise return zero. */
9051 create_register_alias (newname
, p
)
9059 skip_whitespace (q
);
9064 if (*q
&& !strncmp (q
, ".req ", 5))
9069 #ifdef IGNORE_OPCODE_CASE
9070 newname
= original_case_string
;
9072 copy_of_str
= newname
;
9075 skip_whitespace (q
);
9077 for (r
= q
; *r
!= '\0'; r
++)
9083 enum arm_reg_type new_type
, old_type
;
9088 old_type
= arm_reg_parse_any (q
);
9091 new_type
= arm_reg_parse_any (newname
);
9093 if (new_type
== REG_TYPE_MAX
)
9095 if (old_type
!= REG_TYPE_MAX
)
9097 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9098 insert_reg_alias (newname
, old_regno
,
9099 all_reg_maps
[old_type
].htab
);
9102 as_warn (_("register '%s' does not exist\n"), q
);
9104 else if (old_type
== REG_TYPE_MAX
)
9106 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9111 /* Do not warn about redefinitions to the same alias. */
9112 if (new_type
!= old_type
9113 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9114 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9115 as_warn (_("ignoring redefinition of register alias '%s'"),
9121 as_warn (_("ignoring incomplete .req pseuso op"));
9131 set_constant_flonums ()
9135 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9136 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9140 /* Iterate over the base tables to create the instruction patterns. */
9142 build_arm_ops_hsh ()
9146 static struct obstack insn_obstack
;
9148 obstack_begin (&insn_obstack
, 4000);
9150 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
9152 const struct asm_opcode
*insn
= insns
+ i
;
9154 if (insn
->cond_offset
!= 0)
9156 /* Insn supports conditional execution. Build the varaints
9157 and insert them in the hash table. */
9158 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
9160 unsigned len
= strlen (insn
->template);
9161 struct asm_opcode
*new;
9164 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
9165 /* All condition codes are two characters. */
9166 template = obstack_alloc (&insn_obstack
, len
+ 3);
9168 strncpy (template, insn
->template, insn
->cond_offset
);
9169 strcpy (template + insn
->cond_offset
, conds
[j
].template);
9170 if (len
> insn
->cond_offset
)
9171 strcpy (template + insn
->cond_offset
+ 2,
9172 insn
->template + insn
->cond_offset
);
9173 new->template = template;
9174 new->cond_offset
= 0;
9175 new->variant
= insn
->variant
;
9176 new->parms
= insn
->parms
;
9177 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
9179 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
9182 /* Finally, insert the unconditional insn in the table directly;
9183 no need to build a copy. */
9184 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
9194 if ( (arm_ops_hsh
= hash_new ()) == NULL
9195 || (arm_tops_hsh
= hash_new ()) == NULL
9196 || (arm_cond_hsh
= hash_new ()) == NULL
9197 || (arm_shift_hsh
= hash_new ()) == NULL
9198 || (arm_psr_hsh
= hash_new ()) == NULL
)
9199 as_fatal (_("virtual memory exhausted"));
9201 build_arm_ops_hsh ();
9202 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
9203 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
9204 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
9205 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
9206 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
9207 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
9208 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
9209 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
9211 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
9212 build_reg_hsh (all_reg_maps
+ i
);
9214 set_constant_flonums ();
9216 /* Set the cpu variant based on the command-line options. We prefer
9217 -mcpu= over -march= if both are set (as for GCC); and we prefer
9218 -mfpu= over any other way of setting the floating point unit.
9219 Use of legacy options with new options are faulted. */
9220 if (legacy_cpu
!= -1)
9222 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
9223 as_bad (_("use of old and new-style options to set CPU type"));
9225 mcpu_cpu_opt
= legacy_cpu
;
9227 else if (mcpu_cpu_opt
== -1)
9228 mcpu_cpu_opt
= march_cpu_opt
;
9230 if (legacy_fpu
!= -1)
9233 as_bad (_("use of old and new-style options to set FPU type"));
9235 mfpu_opt
= legacy_fpu
;
9237 else if (mfpu_opt
== -1)
9239 if (mcpu_fpu_opt
!= -1)
9240 mfpu_opt
= mcpu_fpu_opt
;
9242 mfpu_opt
= march_fpu_opt
;
9247 if (mcpu_cpu_opt
== -1)
9248 mfpu_opt
= FPU_DEFAULT
;
9249 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
9250 mfpu_opt
= FPU_ARCH_VFP_V2
;
9252 mfpu_opt
= FPU_ARCH_FPA
;
9255 if (mcpu_cpu_opt
== -1)
9256 mcpu_cpu_opt
= CPU_DEFAULT
;
9258 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
9260 #if defined OBJ_COFF || defined OBJ_ELF
9262 unsigned int flags
= 0;
9264 /* Set the flags in the private structure. */
9265 if (uses_apcs_26
) flags
|= F_APCS26
;
9266 if (support_interwork
) flags
|= F_INTERWORK
;
9267 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
9268 if (pic_code
) flags
|= F_PIC
;
9269 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
9270 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
9271 flags
|= F_SOFT_FLOAT
;
9272 /* Using VFP conventions (even if soft-float). */
9273 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
9276 bfd_set_private_flags (stdoutput
, flags
);
9278 /* We have run out flags in the COFF header to encode the
9279 status of ATPCS support, so instead we create a dummy,
9280 empty, debug section called .arm.atpcs. */
9285 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
9289 bfd_set_section_flags
9290 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
9291 bfd_set_section_size (stdoutput
, sec
, 0);
9292 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
9298 /* Record the CPU type as well. */
9299 switch (cpu_variant
& ARM_CPU_MASK
)
9302 mach
= bfd_mach_arm_2
;
9305 case ARM_3
: /* Also ARM_250. */
9306 mach
= bfd_mach_arm_2a
;
9309 case ARM_6
: /* Also ARM_7. */
9310 mach
= bfd_mach_arm_3
;
9314 mach
= bfd_mach_arm_4
;
9318 /* Catch special cases. */
9319 if (cpu_variant
& ARM_CEXT_XSCALE
)
9320 mach
= bfd_mach_arm_XScale
;
9321 else if (cpu_variant
& ARM_EXT_V5E
)
9322 mach
= bfd_mach_arm_5TE
;
9323 else if (cpu_variant
& ARM_EXT_V5
)
9325 if (cpu_variant
& ARM_EXT_V4T
)
9326 mach
= bfd_mach_arm_5T
;
9328 mach
= bfd_mach_arm_5
;
9330 else if (cpu_variant
& ARM_EXT_V4
)
9332 if (cpu_variant
& ARM_EXT_V4T
)
9333 mach
= bfd_mach_arm_4T
;
9335 mach
= bfd_mach_arm_4
;
9337 else if (cpu_variant
& ARM_EXT_V3M
)
9338 mach
= bfd_mach_arm_3M
;
9340 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
9343 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
9344 for use in the a.out file, and stores them in the array pointed to by buf.
9345 This knows about the endian-ness of the target machine and does
9346 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
9347 2 (short) and 4 (long) Floating numbers are put out as a series of
9348 LITTLENUMS (shorts, here at least). */
9351 md_number_to_chars (buf
, val
, n
)
9356 if (target_big_endian
)
9357 number_to_chars_bigendian (buf
, val
, n
);
9359 number_to_chars_littleendian (buf
, val
, n
);
9363 md_chars_to_number (buf
, n
)
9368 unsigned char * where
= (unsigned char *) buf
;
9370 if (target_big_endian
)
9375 result
|= (*where
++ & 255);
9383 result
|= (where
[n
] & 255);
9390 /* Turn a string in input_line_pointer into a floating point constant
9391 of type TYPE, and store the appropriate bytes in *LITP. The number
9392 of LITTLENUMS emitted is stored in *SIZEP. An error message is
9393 returned, or NULL on OK.
9395 Note that fp constants aren't represent in the normal way on the ARM.
9396 In big endian mode, things are as expected. However, in little endian
9397 mode fp constants are big-endian word-wise, and little-endian byte-wise
9398 within the words. For example, (double) 1.1 in big endian mode is
9399 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
9400 the byte sequence 99 99 f1 3f 9a 99 99 99.
9402 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
9405 md_atof (type
, litP
, sizeP
)
9411 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
9443 return _("bad call to MD_ATOF()");
9446 t
= atof_ieee (input_line_pointer
, type
, words
);
9448 input_line_pointer
= t
;
9451 if (target_big_endian
)
9453 for (i
= 0; i
< prec
; i
++)
9455 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
9461 if (cpu_variant
& FPU_ARCH_VFP
)
9462 for (i
= prec
- 1; i
>= 0; i
--)
9464 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
9468 /* For a 4 byte float the order of elements in `words' is 1 0.
9469 For an 8 byte float the order is 1 0 3 2. */
9470 for (i
= 0; i
< prec
; i
+= 2)
9472 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
9473 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
9481 /* The knowledge of the PC's pipeline offset is built into the insns
9485 md_pcrel_from (fixP
)
9489 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
9490 && fixP
->fx_subsy
== NULL
)
9493 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
9495 /* PC relative addressing on the Thumb is slightly odd
9496 as the bottom two bits of the PC are forced to zero
9497 for the calculation. */
9498 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
9502 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
9503 so we un-adjust here to compensate for the accomodation. */
9504 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
9506 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
9510 /* Round up a section size to the appropriate boundary. */
9513 md_section_align (segment
, size
)
9514 segT segment ATTRIBUTE_UNUSED
;
9520 /* Round all sects to multiple of 4. */
9521 return (size
+ 3) & ~3;
9525 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
9526 Otherwise we have no need to default values of symbols. */
9529 md_undefined_symbol (name
)
9530 char * name ATTRIBUTE_UNUSED
;
9533 if (name
[0] == '_' && name
[1] == 'G'
9534 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
9538 if (symbol_find (name
))
9539 as_bad ("GOT already in the symbol table");
9541 GOT_symbol
= symbol_new (name
, undefined_section
,
9542 (valueT
) 0, & zero_address_frag
);
9552 /* arm_reg_parse () := if it looks like a register, return its token and
9553 advance the pointer. */
9556 arm_reg_parse (ccp
, htab
)
9557 register char ** ccp
;
9558 struct hash_control
*htab
;
9560 char * start
= * ccp
;
9563 struct reg_entry
* reg
;
9565 #ifdef REGISTER_PREFIX
9566 if (*start
!= REGISTER_PREFIX
)
9571 #ifdef OPTIONAL_REGISTER_PREFIX
9572 if (*p
== OPTIONAL_REGISTER_PREFIX
)
9576 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
9580 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
9584 reg
= (struct reg_entry
*) hash_find (htab
, start
);
9596 /* Search for the following register name in each of the possible reg name
9597 tables. Return the classification if found, or REG_TYPE_MAX if not
9599 static enum arm_reg_type
9600 arm_reg_parse_any (cp
)
9605 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
9606 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
9607 return (enum arm_reg_type
) i
;
9609 return REG_TYPE_MAX
;
9613 md_apply_fix3 (fixP
, valP
, seg
)
9618 offsetT value
= * valP
;
9620 unsigned int newimm
;
9623 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
9624 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
9626 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
9628 /* Note whether this will delete the relocation. */
9630 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
9631 doesn't work fully.) */
9632 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
9635 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
9639 /* If this symbol is in a different section then we need to leave it for
9640 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
9641 so we have to undo it's effects here. */
9644 if (fixP
->fx_addsy
!= NULL
9645 && S_IS_DEFINED (fixP
->fx_addsy
)
9646 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
9649 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
9650 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
9654 value
+= md_pcrel_from (fixP
);
9658 /* Remember value for emit_reloc. */
9659 fixP
->fx_addnumber
= value
;
9661 switch (fixP
->fx_r_type
)
9663 case BFD_RELOC_ARM_IMMEDIATE
:
9664 newimm
= validate_immediate (value
);
9665 temp
= md_chars_to_number (buf
, INSN_SIZE
);
9667 /* If the instruction will fail, see if we can fix things up by
9668 changing the opcode. */
9669 if (newimm
== (unsigned int) FAIL
9670 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
9672 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9673 _("invalid constant (%lx) after fixup"),
9674 (unsigned long) value
);
9678 newimm
|= (temp
& 0xfffff000);
9679 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
9683 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
9685 unsigned int highpart
= 0;
9686 unsigned int newinsn
= 0xe1a00000; /* nop. */
9688 newimm
= validate_immediate (value
);
9689 temp
= md_chars_to_number (buf
, INSN_SIZE
);
9691 /* If the instruction will fail, see if we can fix things up by
9692 changing the opcode. */
9693 if (newimm
== (unsigned int) FAIL
9694 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
9696 /* No ? OK - try using two ADD instructions to generate
9698 newimm
= validate_immediate_twopart (value
, & highpart
);
9700 /* Yes - then make sure that the second instruction is
9702 if (newimm
!= (unsigned int) FAIL
)
9704 /* Still No ? Try using a negated value. */
9705 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
9706 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
9707 /* Otherwise - give up. */
9710 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9711 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
9716 /* Replace the first operand in the 2nd instruction (which
9717 is the PC) with the destination register. We have
9718 already added in the PC in the first instruction and we
9719 do not want to do it again. */
9720 newinsn
&= ~ 0xf0000;
9721 newinsn
|= ((newinsn
& 0x0f000) << 4);
9724 newimm
|= (temp
& 0xfffff000);
9725 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
9727 highpart
|= (newinsn
& 0xfffff000);
9728 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
9732 case BFD_RELOC_ARM_OFFSET_IMM
:
9738 if (validate_offset_imm (value
, 0) == FAIL
)
9740 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9741 _("bad immediate value for offset (%ld)"),
9746 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9747 newval
&= 0xff7ff000;
9748 newval
|= value
| (sign
? INDEX_UP
: 0);
9749 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9752 case BFD_RELOC_ARM_OFFSET_IMM8
:
9753 case BFD_RELOC_ARM_HWLITERAL
:
9759 if (validate_offset_imm (value
, 1) == FAIL
)
9761 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
9762 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9763 _("invalid literal constant: pool needs to be closer"));
9765 as_bad (_("bad immediate value for half-word offset (%ld)"),
9770 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9771 newval
&= 0xff7ff0f0;
9772 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
9773 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9776 case BFD_RELOC_ARM_LITERAL
:
9782 if (validate_offset_imm (value
, 0) == FAIL
)
9784 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9785 _("invalid literal constant: pool needs to be closer"));
9789 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9790 newval
&= 0xff7ff000;
9791 newval
|= value
| (sign
? INDEX_UP
: 0);
9792 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9795 case BFD_RELOC_ARM_SHIFT_IMM
:
9796 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9797 if (((unsigned long) value
) > 32
9799 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
9801 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9802 _("shift expression is too large"));
9807 /* Shifts of zero must be done as lsl. */
9809 else if (value
== 32)
9811 newval
&= 0xfffff07f;
9812 newval
|= (value
& 0x1f) << 7;
9813 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9816 case BFD_RELOC_ARM_SWI
:
9817 if (arm_data
->thumb_mode
)
9819 if (((unsigned long) value
) > 0xff)
9820 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9821 _("invalid swi expression"));
9822 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
9824 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9828 if (((unsigned long) value
) > 0x00ffffff)
9829 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9830 _("invalid swi expression"));
9831 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
9833 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9837 case BFD_RELOC_ARM_MULTI
:
9838 if (((unsigned long) value
) > 0xffff)
9839 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9840 _("invalid expression in load/store multiple"));
9841 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
9842 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9845 case BFD_RELOC_ARM_PCREL_BRANCH
:
9846 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9848 /* Sign-extend a 24-bit number. */
9849 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
9853 value
= fixP
->fx_offset
;
9856 /* We are going to store value (shifted right by two) in the
9857 instruction, in a 24 bit, signed field. Thus we need to check
9858 that none of the top 8 bits of the shifted value (top 7 bits of
9859 the unshifted, unsigned value) are set, or that they are all set. */
9860 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
9861 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
9864 /* Normally we would be stuck at this point, since we cannot store
9865 the absolute address that is the destination of the branch in the
9866 24 bits of the branch instruction. If however, we happen to know
9867 that the destination of the branch is in the same section as the
9868 branch instruciton itself, then we can compute the relocation for
9869 ourselves and not have to bother the linker with it.
9871 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
9872 because I have not worked out how to do this for OBJ_COFF or
9875 && fixP
->fx_addsy
!= NULL
9876 && S_IS_DEFINED (fixP
->fx_addsy
)
9877 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
9879 /* Get pc relative value to go into the branch. */
9882 /* Permit a backward branch provided that enough bits
9883 are set. Allow a forwards branch, provided that
9884 enough bits are clear. */
9885 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
9886 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
9890 if (! fixP
->fx_done
)
9892 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9893 _("GAS can't handle same-section branch dest >= 0x04000000"));
9897 value
+= SEXT24 (newval
);
9899 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
9900 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
9901 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9902 _("out of range branch"));
9904 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
9905 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9908 case BFD_RELOC_ARM_PCREL_BLX
:
9911 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9915 value
= fixP
->fx_offset
;
9917 hbit
= (value
>> 1) & 1;
9918 value
= (value
>> 2) & 0x00ffffff;
9919 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
9920 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
9921 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9925 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
9926 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9928 addressT diff
= (newval
& 0xff) << 1;
9933 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
9934 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9935 _("branch out of range"));
9936 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
9938 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9941 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
9942 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9944 addressT diff
= (newval
& 0x7ff) << 1;
9949 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
9950 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9951 _("branch out of range"));
9952 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
9954 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9957 case BFD_RELOC_THUMB_PCREL_BLX
:
9958 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
9963 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9964 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
9965 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
9966 if (diff
& 0x400000)
9969 value
= fixP
->fx_offset
;
9973 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
9974 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9975 _("branch with link out of range"));
9977 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
9978 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
9979 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
9980 /* For a BLX instruction, make sure that the relocation is rounded up
9981 to a word boundary. This follows the semantics of the instruction
9982 which specifies that bit 1 of the target address will come from bit
9983 1 of the base address. */
9984 newval2
= (newval2
+ 1) & ~ 1;
9985 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9986 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
9991 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9992 md_number_to_chars (buf
, value
, 1);
9994 else if (!target_oabi
)
9996 value
= fixP
->fx_offset
;
9997 md_number_to_chars (buf
, value
, 1);
10003 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
10004 md_number_to_chars (buf
, value
, 2);
10006 else if (!target_oabi
)
10008 value
= fixP
->fx_offset
;
10009 md_number_to_chars (buf
, value
, 2);
10015 case BFD_RELOC_ARM_GOT32
:
10016 case BFD_RELOC_ARM_GOTOFF
:
10017 md_number_to_chars (buf
, 0, 4);
10021 case BFD_RELOC_RVA
:
10023 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
10024 md_number_to_chars (buf
, value
, 4);
10026 else if (!target_oabi
)
10028 value
= fixP
->fx_offset
;
10029 md_number_to_chars (buf
, value
, 4);
10035 case BFD_RELOC_ARM_PLT32
:
10036 /* It appears the instruction is fully prepared at this point. */
10040 case BFD_RELOC_ARM_CP_OFF_IMM
:
10042 if (value
< -1023 || value
> 1023 || (value
& 3))
10043 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10044 _("illegal value for co-processor offset"));
10047 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
10048 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
10049 md_number_to_chars (buf
, newval
, INSN_SIZE
);
10052 case BFD_RELOC_ARM_THUMB_OFFSET
:
10053 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10054 /* Exactly what ranges, and where the offset is inserted depends
10055 on the type of instruction, we can establish this from the
10057 switch (newval
>> 12)
10059 case 4: /* PC load. */
10060 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
10061 forced to zero for these loads, so we will need to round
10062 up the offset if the instruction address is not word
10063 aligned (since the final address produced must be, and
10064 we can only describe word-aligned immediate offsets). */
10066 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
10067 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10068 _("invalid offset, target not word aligned (0x%08X)"),
10069 (unsigned int) (fixP
->fx_frag
->fr_address
10070 + fixP
->fx_where
+ value
));
10072 if ((value
+ 2) & ~0x3fe)
10073 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10074 _("invalid offset, value too big (0x%08lX)"),
10077 /* Round up, since pc will be rounded down. */
10078 newval
|= (value
+ 2) >> 2;
10081 case 9: /* SP load/store. */
10082 if (value
& ~0x3fc)
10083 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10084 _("invalid offset, value too big (0x%08lX)"),
10086 newval
|= value
>> 2;
10089 case 6: /* Word load/store. */
10091 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10092 _("invalid offset, value too big (0x%08lX)"),
10094 newval
|= value
<< 4; /* 6 - 2. */
10097 case 7: /* Byte load/store. */
10099 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10100 _("invalid offset, value too big (0x%08lX)"),
10102 newval
|= value
<< 6;
10105 case 8: /* Halfword load/store. */
10107 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10108 _("invalid offset, value too big (0x%08lX)"),
10110 newval
|= value
<< 5; /* 6 - 1. */
10114 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10115 "Unable to process relocation for thumb opcode: %lx",
10116 (unsigned long) newval
);
10119 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10122 case BFD_RELOC_ARM_THUMB_ADD
:
10123 /* This is a complicated relocation, since we use it for all of
10124 the following immediate relocations:
10128 9bit ADD/SUB SP word-aligned
10129 10bit ADD PC/SP word-aligned
10131 The type of instruction being processed is encoded in the
10138 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10140 int rd
= (newval
>> 4) & 0xf;
10141 int rs
= newval
& 0xf;
10142 int subtract
= newval
& 0x8000;
10146 if (value
& ~0x1fc)
10147 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10148 _("invalid immediate for stack address calculation"));
10149 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
10150 newval
|= value
>> 2;
10152 else if (rs
== REG_PC
|| rs
== REG_SP
)
10156 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10157 _("invalid immediate for address calculation (value = 0x%08lX)"),
10158 (unsigned long) value
);
10159 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
10161 newval
|= value
>> 2;
10166 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10167 _("invalid 8bit immediate"));
10168 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
10169 newval
|= (rd
<< 8) | value
;
10174 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10175 _("invalid 3bit immediate"));
10176 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
10177 newval
|= rd
| (rs
<< 3) | (value
<< 6);
10180 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10183 case BFD_RELOC_ARM_THUMB_IMM
:
10184 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10185 switch (newval
>> 11)
10187 case 0x04: /* 8bit immediate MOV. */
10188 case 0x05: /* 8bit immediate CMP. */
10189 if (value
< 0 || value
> 255)
10190 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10191 _("invalid immediate: %ld is too large"),
10199 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10202 case BFD_RELOC_ARM_THUMB_SHIFT
:
10203 /* 5bit shift value (0..31). */
10204 if (value
< 0 || value
> 31)
10205 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10206 _("illegal Thumb shift value: %ld"), (long) value
);
10207 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
10208 newval
|= value
<< 6;
10209 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10212 case BFD_RELOC_VTABLE_INHERIT
:
10213 case BFD_RELOC_VTABLE_ENTRY
:
10217 case BFD_RELOC_NONE
:
10219 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10220 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
10224 /* Translate internal representation of relocation info to BFD target
10228 tc_gen_reloc (section
, fixp
)
10229 asection
* section ATTRIBUTE_UNUSED
;
10233 bfd_reloc_code_real_type code
;
10235 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
10237 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
10238 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
10239 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
10241 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
10243 if (fixp
->fx_pcrel
== 0)
10244 reloc
->addend
= fixp
->fx_offset
;
10246 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
10247 #else /* OBJ_ELF */
10248 reloc
->addend
= fixp
->fx_offset
;
10251 switch (fixp
->fx_r_type
)
10254 if (fixp
->fx_pcrel
)
10256 code
= BFD_RELOC_8_PCREL
;
10261 if (fixp
->fx_pcrel
)
10263 code
= BFD_RELOC_16_PCREL
;
10268 if (fixp
->fx_pcrel
)
10270 code
= BFD_RELOC_32_PCREL
;
10274 case BFD_RELOC_ARM_PCREL_BRANCH
:
10275 case BFD_RELOC_ARM_PCREL_BLX
:
10276 case BFD_RELOC_RVA
:
10277 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
10278 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
10279 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
10280 case BFD_RELOC_THUMB_PCREL_BLX
:
10281 case BFD_RELOC_VTABLE_ENTRY
:
10282 case BFD_RELOC_VTABLE_INHERIT
:
10283 code
= fixp
->fx_r_type
;
10286 case BFD_RELOC_ARM_LITERAL
:
10287 case BFD_RELOC_ARM_HWLITERAL
:
10288 /* If this is called then the a literal has
10289 been referenced across a section boundary. */
10290 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10291 _("literal referenced across section boundary"));
10295 case BFD_RELOC_ARM_GOT32
:
10296 case BFD_RELOC_ARM_GOTOFF
:
10297 case BFD_RELOC_ARM_PLT32
:
10298 code
= fixp
->fx_r_type
;
10302 case BFD_RELOC_ARM_IMMEDIATE
:
10303 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10304 _("internal relocation (type: IMMEDIATE) not fixed up"));
10307 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10308 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10309 _("ADRL used for a symbol not defined in the same file"));
10312 case BFD_RELOC_ARM_OFFSET_IMM
:
10313 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10314 _("internal_relocation (type: OFFSET_IMM) not fixed up"));
10321 switch (fixp
->fx_r_type
)
10323 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
10324 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
10325 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
10326 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
10327 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
10328 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
10329 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
10330 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
10331 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
10332 default: type
= _("<unknown>"); break;
10334 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10335 _("cannot represent %s relocation in this object file format"),
10342 if (code
== BFD_RELOC_32_PCREL
10344 && fixp
->fx_addsy
== GOT_symbol
)
10346 code
= BFD_RELOC_ARM_GOTPC
;
10347 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
10351 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
10353 if (reloc
->howto
== NULL
)
10355 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10356 _("cannot represent %s relocation in this object file format"),
10357 bfd_get_reloc_code_name (code
));
10361 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
10362 vtable entry to be used in the relocation's section offset. */
10363 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
10364 reloc
->address
= fixp
->fx_offset
;
10370 md_estimate_size_before_relax (fragP
, segtype
)
10371 fragS
* fragP ATTRIBUTE_UNUSED
;
10372 segT segtype ATTRIBUTE_UNUSED
;
10374 as_fatal (_("md_estimate_size_before_relax\n"));
10386 as_bad ("%s -- `%s'", inst
.error
, str
);
10390 to
= frag_more (inst
.size
);
10392 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
10394 assert (inst
.size
== (2 * THUMB_SIZE
));
10395 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
10396 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
10398 else if (inst
.size
> INSN_SIZE
)
10400 assert (inst
.size
== (2 * INSN_SIZE
));
10401 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
10402 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
10405 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
10407 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
10408 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
10409 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
10413 dwarf2_emit_insn (inst
.size
);
10425 /* Align the instruction.
10426 This may not be the right thing to do but ... */
10431 /* Align the previous label if needed. */
10432 if (last_label_seen
!= NULL
)
10434 symbol_set_frag (last_label_seen
, frag_now
);
10435 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
10436 S_SET_SEGMENT (last_label_seen
, now_seg
);
10439 memset (&inst
, '\0', sizeof (inst
));
10440 inst
.reloc
.type
= BFD_RELOC_NONE
;
10442 skip_whitespace (str
);
10444 /* Scan up to the end of the op-code, which must end in white space or
10446 for (start
= p
= str
; *p
!= '\0'; p
++)
10452 as_bad (_("no operator -- statement `%s'\n"), str
);
10458 const struct thumb_opcode
* opcode
;
10462 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
10467 /* Check that this instruction is supported for this CPU. */
10468 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
10470 as_bad (_("selected processor does not support `%s'"), str
);
10474 inst
.instruction
= opcode
->value
;
10475 inst
.size
= opcode
->size
;
10476 (*opcode
->parms
) (p
);
10483 const struct asm_opcode
* opcode
;
10487 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
10492 /* Check that this instruction is supported for this CPU. */
10493 if ((opcode
->variant
& cpu_variant
) == 0)
10495 as_bad (_("selected processor does not support `%s'"), str
);
10499 inst
.instruction
= opcode
->value
;
10500 inst
.size
= INSN_SIZE
;
10501 (*opcode
->parms
) (p
);
10507 /* It wasn't an instruction, but it might be a register alias of the form
10509 if (create_register_alias (str
, p
))
10512 as_bad (_("bad instruction `%s'"), start
);
10516 Invocation line includes a switch not recognized by the base assembler.
10517 See if it's a processor-specific option.
10519 This routine is somewhat complicated by the need for backwards
10520 compatibility (since older releases of gcc can't be changed).
10521 The new options try to make the interface as compatible as
10524 New options (supported) are:
10526 -mcpu=<cpu name> Assemble for selected processor
10527 -march=<architecture name> Assemble for selected architecture
10528 -mfpu=<fpu architecture> Assemble for selected FPU.
10529 -EB/-mbig-endian Big-endian
10530 -EL/-mlittle-endian Little-endian
10531 -k Generate PIC code
10532 -mthumb Start in Thumb mode
10533 -mthumb-interwork Code supports ARM/Thumb interworking
10535 For now we will also provide support for:
10537 -mapcs-32 32-bit Program counter
10538 -mapcs-26 26-bit Program counter
10539 -macps-float Floats passed in FP registers
10540 -mapcs-reentrant Reentrant code
10542 (sometime these will probably be replaced with -mapcs=<list of options>
10543 and -matpcs=<list of options>)
10545 The remaining options are only supported for back-wards compatibility.
10546 Cpu variants, the arm part is optional:
10547 -m[arm]1 Currently not supported.
10548 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
10549 -m[arm]3 Arm 3 processor
10550 -m[arm]6[xx], Arm 6 processors
10551 -m[arm]7[xx][t][[d]m] Arm 7 processors
10552 -m[arm]8[10] Arm 8 processors
10553 -m[arm]9[20][tdmi] Arm 9 processors
10554 -mstrongarm[110[0]] StrongARM processors
10555 -mxscale XScale processors
10556 -m[arm]v[2345[t[e]]] Arm architectures
10557 -mall All (except the ARM1)
10559 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
10560 -mfpe-old (No float load/store multiples)
10561 -mvfpxd VFP Single precision
10563 -mno-fpu Disable all floating point instructions
10565 The following CPU names are recognized:
10566 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
10567 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
10568 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
10569 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
10570 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
10571 arm10t arm10e, arm1020t, arm1020e, arm10200e,
10572 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
10576 const char * md_shortopts
= "m:k";
10578 #ifdef ARM_BI_ENDIAN
10579 #define OPTION_EB (OPTION_MD_BASE + 0)
10580 #define OPTION_EL (OPTION_MD_BASE + 1)
10582 #if TARGET_BYTES_BIG_ENDIAN
10583 #define OPTION_EB (OPTION_MD_BASE + 0)
10585 #define OPTION_EL (OPTION_MD_BASE + 1)
10589 struct option md_longopts
[] =
10592 {"EB", no_argument
, NULL
, OPTION_EB
},
10595 {"EL", no_argument
, NULL
, OPTION_EL
},
10597 {NULL
, no_argument
, NULL
, 0}
10600 size_t md_longopts_size
= sizeof (md_longopts
);
10602 struct arm_option_table
10604 char *option
; /* Option name to match. */
10605 char *help
; /* Help information. */
10606 int *var
; /* Variable to change. */
10607 int value
; /* What to change it to. */
10608 char *deprecated
; /* If non-null, print this message. */
10611 struct arm_option_table arm_opts
[] =
10613 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
10614 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
10615 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
10616 &support_interwork
, 1, NULL
},
10617 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
10618 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
10619 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
10620 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
10622 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
10623 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
10624 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
10625 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
10628 /* These are recognized by the assembler, but have no affect on code. */
10629 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
10630 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
10632 /* DON'T add any new processors to this list -- we want the whole list
10633 to go away... Add them to the processors table instead. */
10634 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
10635 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
10636 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
10637 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
10638 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
10639 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
10640 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
10641 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
10642 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
10643 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
10644 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
10645 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
10646 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
10647 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
10648 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
10649 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
10650 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
10651 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
10652 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
10653 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
10654 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
10655 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
10656 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
10657 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
10658 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
10659 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
10660 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
10661 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
10662 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
10663 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
10664 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
10665 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
10666 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
10667 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
10668 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
10669 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
10670 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
10671 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
10672 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
10673 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
10674 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
10675 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
10676 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
10677 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
10678 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
10679 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
10680 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10681 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10682 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10683 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10684 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
10685 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
10686 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
10687 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
10688 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
10689 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
10690 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
10691 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
10692 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
10693 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
10694 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
10695 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
10696 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
10697 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
10698 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
10699 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
10700 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
10701 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
10702 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
10703 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10704 N_("use -mcpu=strongarm110")},
10705 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10706 N_("use -mcpu=strongarm1100")},
10707 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10708 N_("use -mcpu=strongarm1110")},
10709 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
10710 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
10712 /* Architecture variants -- don't add any more to this list either. */
10713 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
10714 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
10715 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
10716 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
10717 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
10718 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
10719 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
10720 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
10721 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
10722 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
10723 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
10724 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
10725 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
10726 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
10727 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
10728 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
10729 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
10730 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
10732 /* Floating point variants -- don't add any more to this list either. */
10733 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
10734 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
10735 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
10736 {"mno-fpu", NULL
, &legacy_fpu
, 0,
10737 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
10739 {NULL
, NULL
, NULL
, 0, NULL
}
10742 struct arm_cpu_option_table
10746 /* For some CPUs we assume an FPU unless the user explicitly sets
10751 /* This list should, at a minimum, contain all the cpu names
10752 recognized by GCC. */
10753 static struct arm_cpu_option_table arm_cpus
[] =
10755 {"all", ARM_ANY
, FPU_ARCH_FPA
},
10756 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
10757 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
10758 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10759 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10760 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10761 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10762 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10763 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10764 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10765 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10766 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10767 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10768 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10769 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10770 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10771 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10772 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10773 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10774 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10775 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10776 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10777 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10778 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10779 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10780 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10781 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10782 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10783 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10784 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10785 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10786 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10787 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10788 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10789 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10790 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10791 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10792 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10793 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10794 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10795 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10796 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10797 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10798 /* For V5 or later processors we default to using VFP; but the user
10799 should really set the FPU type explicitly. */
10800 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10801 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10802 {"arm926ej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP_V2
},
10803 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10804 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10805 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10806 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10807 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
10808 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10809 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10810 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
10811 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10812 /* ??? XSCALE is really an architecture. */
10813 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
10814 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
10816 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
10820 struct arm_arch_option_table
10827 /* This list should, at a minimum, contain all the architecture names
10828 recognized by GCC. */
10829 static struct arm_arch_option_table arm_archs
[] =
10831 {"all", ARM_ANY
, FPU_ARCH_FPA
},
10832 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
10833 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
10834 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10835 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10836 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10837 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10838 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10839 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
10840 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10841 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
10842 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
10843 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
10844 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
10845 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
10846 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
10847 {"armv5tej", ARM_ARCH_V5TEJ
, FPU_ARCH_VFP
},
10848 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
10852 /* ISA extensions in the co-processor space. */
10853 struct arm_arch_extension_table
10859 static struct arm_arch_extension_table arm_extensions
[] =
10861 {"maverick", ARM_CEXT_MAVERICK
},
10862 {"xscale", ARM_CEXT_XSCALE
},
10866 struct arm_fpu_option_table
10872 /* This list should, at a minimum, contain all the fpu names
10873 recognized by GCC. */
10874 static struct arm_fpu_option_table arm_fpus
[] =
10876 {"softfpa", FPU_NONE
},
10877 {"fpe", FPU_ARCH_FPE
},
10878 {"fpe2", FPU_ARCH_FPE
},
10879 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
10880 {"fpa", FPU_ARCH_FPA
},
10881 {"fpa10", FPU_ARCH_FPA
},
10882 {"fpa11", FPU_ARCH_FPA
},
10883 {"arm7500fe", FPU_ARCH_FPA
},
10884 {"softvfp", FPU_ARCH_VFP
},
10885 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
10886 {"vfp", FPU_ARCH_VFP_V2
},
10887 {"vfp9", FPU_ARCH_VFP_V2
},
10888 {"vfp10", FPU_ARCH_VFP_V2
},
10889 {"vfp10-r0", FPU_ARCH_VFP_V1
},
10890 {"vfpxd", FPU_ARCH_VFP_V1xD
},
10891 {"arm1020t", FPU_ARCH_VFP_V1
},
10892 {"arm1020e", FPU_ARCH_VFP_V2
},
10896 struct arm_long_option_table
10898 char *option
; /* Substring to match. */
10899 char *help
; /* Help information. */
10900 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
10901 char *deprecated
; /* If non-null, print this message. */
10905 arm_parse_extension (str
, opt_p
)
10909 while (str
!= NULL
&& *str
!= 0)
10911 struct arm_arch_extension_table
*opt
;
10917 as_bad (_("invalid architectural extension"));
10922 ext
= strchr (str
, '+');
10925 optlen
= ext
- str
;
10927 optlen
= strlen (str
);
10931 as_bad (_("missing architectural extension"));
10935 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
10936 if (strncmp (opt
->name
, str
, optlen
) == 0)
10938 *opt_p
|= opt
->value
;
10942 if (opt
->name
== NULL
)
10944 as_bad (_("unknown architectural extnsion `%s'"), str
);
10955 arm_parse_cpu (str
)
10958 struct arm_cpu_option_table
*opt
;
10959 char *ext
= strchr (str
, '+');
10963 optlen
= ext
- str
;
10965 optlen
= strlen (str
);
10969 as_bad (_("missing cpu name `%s'"), str
);
10973 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
10974 if (strncmp (opt
->name
, str
, optlen
) == 0)
10976 mcpu_cpu_opt
= opt
->value
;
10977 mcpu_fpu_opt
= opt
->default_fpu
;
10980 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
10985 as_bad (_("unknown cpu `%s'"), str
);
10990 arm_parse_arch (str
)
10993 struct arm_arch_option_table
*opt
;
10994 char *ext
= strchr (str
, '+');
10998 optlen
= ext
- str
;
11000 optlen
= strlen (str
);
11004 as_bad (_("missing architecture name `%s'"), str
);
11009 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
11010 if (strcmp (opt
->name
, str
) == 0)
11012 march_cpu_opt
= opt
->value
;
11013 march_fpu_opt
= opt
->default_fpu
;
11016 return arm_parse_extension (ext
, &march_cpu_opt
);
11021 as_bad (_("unknown architecture `%s'\n"), str
);
11026 arm_parse_fpu (str
)
11029 struct arm_fpu_option_table
*opt
;
11031 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
11032 if (strcmp (opt
->name
, str
) == 0)
11034 mfpu_opt
= opt
->value
;
11038 as_bad (_("unknown floating point format `%s'\n"), str
);
11042 struct arm_long_option_table arm_long_opts
[] =
11044 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
11045 arm_parse_cpu
, NULL
},
11046 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
11047 arm_parse_arch
, NULL
},
11048 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
11049 arm_parse_fpu
, NULL
},
11050 {NULL
, NULL
, 0, NULL
}
11054 md_parse_option (c
, arg
)
11058 struct arm_option_table
*opt
;
11059 struct arm_long_option_table
*lopt
;
11065 target_big_endian
= 1;
11071 target_big_endian
= 0;
11076 /* Listing option. Just ignore these, we don't support additional
11081 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
11083 if (c
== opt
->option
[0]
11084 && ((arg
== NULL
&& opt
->option
[1] == 0)
11085 || strcmp (arg
, opt
->option
+ 1) == 0))
11087 #if WARN_DEPRECATED
11088 /* If the option is deprecated, tell the user. */
11089 if (opt
->deprecated
!= NULL
)
11090 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
11091 arg
? arg
: "", _(opt
->deprecated
));
11094 if (opt
->var
!= NULL
)
11095 *opt
->var
= opt
->value
;
11101 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
11103 /* These options are expected to have an argument. */
11104 if (c
== lopt
->option
[0]
11106 && strncmp (arg
, lopt
->option
+ 1,
11107 strlen (lopt
->option
+ 1)) == 0)
11109 #if WARN_DEPRECATED
11110 /* If the option is deprecated, tell the user. */
11111 if (lopt
->deprecated
!= NULL
)
11112 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
11113 _(lopt
->deprecated
));
11116 /* Call the sup-option parser. */
11117 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
11121 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
11132 struct arm_option_table
*opt
;
11133 struct arm_long_option_table
*lopt
;
11135 fprintf (fp
, _(" ARM-specific assembler options:\n"));
11137 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
11138 if (opt
->help
!= NULL
)
11139 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
11141 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
11142 if (lopt
->help
!= NULL
)
11143 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
11147 -EB assemble code for a big-endian cpu\n"));
11152 -EL assemble code for a little-endian cpu\n"));
11156 /* We need to be able to fix up arbitrary expressions in some statements.
11157 This is so that we can handle symbols that are an arbitrary distance from
11158 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
11159 which returns part of an address in a form which will be valid for
11160 a data instruction. We do this by pushing the expression into a symbol
11161 in the expr_section, and creating a fix for that. */
11164 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
11173 arm_fix_data
* arm_data
;
11181 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
11185 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
11190 /* Mark whether the fix is to a THUMB instruction, or an ARM
11192 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
11193 new_fix
->tc_fix_data
= (PTR
) arm_data
;
11194 arm_data
->thumb_mode
= thumb_mode
;
11199 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
11202 cons_fix_new_arm (frag
, where
, size
, exp
)
11208 bfd_reloc_code_real_type type
;
11212 FIXME: @@ Should look at CPU word size. */
11216 type
= BFD_RELOC_8
;
11219 type
= BFD_RELOC_16
;
11223 type
= BFD_RELOC_32
;
11226 type
= BFD_RELOC_64
;
11230 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
11233 /* A good place to do this, although this was probably not intended
11234 for this kind of use. We need to dump the literal pool before
11235 references are made to a null symbol pointer. */
11240 literal_pool
* pool
;
11242 for (pool
= list_of_pools
; pool
; pool
= pool
->next
)
11244 /* Put it at the end of the relevent section. */
11245 subseg_set (pool
->section
, pool
->sub_section
);
11251 arm_start_line_hook ()
11253 last_label_seen
= NULL
;
11257 arm_frob_label (sym
)
11260 last_label_seen
= sym
;
11262 ARM_SET_THUMB (sym
, thumb_mode
);
11264 #if defined OBJ_COFF || defined OBJ_ELF
11265 ARM_SET_INTERWORK (sym
, support_interwork
);
11268 /* Note - do not allow local symbols (.Lxxx) to be labeled
11269 as Thumb functions. This is because these labels, whilst
11270 they exist inside Thumb code, are not the entry points for
11271 possible ARM->Thumb calls. Also, these labels can be used
11272 as part of a computed goto or switch statement. eg gcc
11273 can generate code that looks like this:
11275 ldr r2, [pc, .Laaa]
11285 The first instruction loads the address of the jump table.
11286 The second instruction converts a table index into a byte offset.
11287 The third instruction gets the jump address out of the table.
11288 The fourth instruction performs the jump.
11290 If the address stored at .Laaa is that of a symbol which has the
11291 Thumb_Func bit set, then the linker will arrange for this address
11292 to have the bottom bit set, which in turn would mean that the
11293 address computation performed by the third instruction would end
11294 up with the bottom bit set. Since the ARM is capable of unaligned
11295 word loads, the instruction would then load the incorrect address
11296 out of the jump table, and chaos would ensue. */
11297 if (label_is_thumb_function_name
11298 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
11299 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
11301 /* When the address of a Thumb function is taken the bottom
11302 bit of that address should be set. This will allow
11303 interworking between Arm and Thumb functions to work
11306 THUMB_SET_FUNC (sym
, 1);
11308 label_is_thumb_function_name
= false;
11312 /* Adjust the symbol table. This marks Thumb symbols as distinct from
11316 arm_adjust_symtab ()
11321 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
11323 if (ARM_IS_THUMB (sym
))
11325 if (THUMB_IS_FUNC (sym
))
11327 /* Mark the symbol as a Thumb function. */
11328 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
11329 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
11330 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
11332 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
11333 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
11335 as_bad (_("%s: unexpected function type: %d"),
11336 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
11338 else switch (S_GET_STORAGE_CLASS (sym
))
11341 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
11344 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
11347 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
11355 if (ARM_IS_INTERWORK (sym
))
11356 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
11363 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
11365 if (ARM_IS_THUMB (sym
))
11367 elf_symbol_type
* elf_sym
;
11369 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
11370 bind
= ELF_ST_BIND (elf_sym
);
11372 /* If it's a .thumb_func, declare it as so,
11373 otherwise tag label as .code 16. */
11374 if (THUMB_IS_FUNC (sym
))
11375 elf_sym
->internal_elf_sym
.st_info
=
11376 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
11378 elf_sym
->internal_elf_sym
.st_info
=
11379 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
11386 arm_data_in_code ()
11388 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
11390 *input_line_pointer
= '/';
11391 input_line_pointer
+= 5;
11392 *input_line_pointer
= 0;
11400 arm_canonicalize_symbol_name (name
)
11405 if (thumb_mode
&& (len
= strlen (name
)) > 5
11406 && streq (name
+ len
- 5, "/data"))
11407 *(name
+ len
- 5) = 0;
11413 arm_validate_fix (fixP
)
11416 /* If the destination of the branch is a defined symbol which does not have
11417 the THUMB_FUNC attribute, then we must be calling a function which has
11418 the (interfacearm) attribute. We look for the Thumb entry point to that
11419 function and change the branch to refer to that function instead. */
11420 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
11421 && fixP
->fx_addsy
!= NULL
11422 && S_IS_DEFINED (fixP
->fx_addsy
)
11423 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
11425 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
11430 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
11431 local labels from being added to the output symbol table when they
11432 are used with the ADRL pseudo op. The ADRL relocation should always
11433 be resolved before the binbary is emitted, so it is safe to say that
11434 it is adjustable. */
11437 arm_fix_adjustable (fixP
)
11440 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
11446 /* Relocations against Thumb function names must be left unadjusted,
11447 so that the linker can use this information to correctly set the
11448 bottom bit of their addresses. The MIPS version of this function
11449 also prevents relocations that are mips-16 specific, but I do not
11450 know why it does this.
11453 There is one other problem that ought to be addressed here, but
11454 which currently is not: Taking the address of a label (rather
11455 than a function) and then later jumping to that address. Such
11456 addresses also ought to have their bottom bit set (assuming that
11457 they reside in Thumb code), but at the moment they will not. */
11460 arm_fix_adjustable (fixP
)
11463 if (fixP
->fx_addsy
== NULL
)
11466 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
11467 && fixP
->fx_subsy
== NULL
)
11470 /* We need the symbol name for the VTABLE entries. */
11471 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
11472 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11475 /* Don't allow symbols to be discarded on GOT related relocs. */
11476 if (fixP
->fx_r_type
== BFD_RELOC_ARM_PLT32
11477 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOT32
11478 || fixP
->fx_r_type
== BFD_RELOC_ARM_GOTOFF
)
11485 elf32_arm_target_format ()
11487 if (target_big_endian
)
11490 return "elf32-bigarm-oabi";
11492 return "elf32-bigarm";
11497 return "elf32-littlearm-oabi";
11499 return "elf32-littlearm";
11504 armelf_frob_symbol (symp
, puntp
)
11508 elf_frob_symbol (symp
, puntp
);
11512 arm_force_relocation (fixp
)
11515 if ( fixp
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
11516 || fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
11517 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11518 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11519 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
11520 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
11523 return S_FORCE_RELOC (fixp
->fx_addsy
);
11526 static bfd_reloc_code_real_type
11536 bfd_reloc_code_real_type reloc
;
11540 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
11541 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
11542 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
11543 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
11544 branch instructions generated by GCC for PLT relocs. */
11545 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
11546 { NULL
, 0, BFD_RELOC_UNUSED
}
11550 for (i
= 0, ip
= input_line_pointer
;
11551 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
11553 id
[i
] = TOLOWER (*ip
);
11555 for (i
= 0; reloc_map
[i
].str
; i
++)
11556 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
11559 input_line_pointer
+= reloc_map
[i
].len
;
11561 return reloc_map
[i
].reloc
;
11565 s_arm_elf_cons (nbytes
)
11570 #ifdef md_flush_pending_output
11571 md_flush_pending_output ();
11574 if (is_it_end_of_statement ())
11576 demand_empty_rest_of_line ();
11580 #ifdef md_cons_align
11581 md_cons_align (nbytes
);
11586 bfd_reloc_code_real_type reloc
;
11588 expression (& exp
);
11590 if (exp
.X_op
== O_symbol
11591 && * input_line_pointer
== '('
11592 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
11594 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
11595 int size
= bfd_get_reloc_size (howto
);
11598 as_bad ("%s relocations do not fit in %d bytes",
11599 howto
->name
, nbytes
);
11602 register char *p
= frag_more ((int) nbytes
);
11603 int offset
= nbytes
- size
;
11605 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
11610 emit_expr (&exp
, (unsigned int) nbytes
);
11612 while (*input_line_pointer
++ == ',');
11614 /* Put terminator back into stream. */
11615 input_line_pointer
--;
11616 demand_empty_rest_of_line ();
11619 #endif /* OBJ_ELF */
11621 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
11622 of an rs_align_code fragment. */
11625 arm_handle_align (fragP
)
11628 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
11629 static char const thumb_noop
[2] = { 0xc0, 0x46 };
11630 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
11631 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
11633 int bytes
, fix
, noop_size
;
11637 if (fragP
->fr_type
!= rs_align_code
)
11640 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
11641 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
11644 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
11645 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
11647 if (fragP
->tc_frag_data
)
11649 if (target_big_endian
)
11650 noop
= thumb_bigend_noop
;
11653 noop_size
= sizeof (thumb_noop
);
11657 if (target_big_endian
)
11658 noop
= arm_bigend_noop
;
11661 noop_size
= sizeof (arm_noop
);
11664 if (bytes
& (noop_size
- 1))
11666 fix
= bytes
& (noop_size
- 1);
11667 memset (p
, 0, fix
);
11672 while (bytes
>= noop_size
)
11674 memcpy (p
, noop
, noop_size
);
11676 bytes
-= noop_size
;
11680 fragP
->fr_fix
+= fix
;
11681 fragP
->fr_var
= noop_size
;
11684 /* Called from md_do_align. Used to create an alignment
11685 frag in a code section. */
11688 arm_frag_align_code (n
, max
)
11694 /* We assume that there will never be a requirment
11695 to support alignments greater than 32 bytes. */
11696 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
11697 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
11699 p
= frag_var (rs_align_code
,
11700 MAX_MEM_FOR_RS_ALIGN_CODE
,
11702 (relax_substateT
) max
,
11710 /* Perform target specific initialisation of a frag. */
11713 arm_init_frag (fragP
)
11716 /* Record whether this frag is in an ARM or a THUMB area. */
11717 fragP
->tc_frag_data
= thumb_mode
;