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. */
58 /* Co-processor space extensions. */
59 #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
60 #define ARM_CEXT_MAVERICK 0x00400000 /* Use Cirrus/DSP coprocessor. */
62 /* Architectures are the sum of the base and extensions. The ARM ARM (rev E)
63 defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
64 ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add
65 three more to cover cores prior to ARM6. Finally, there are cores which
66 implement further extensions in the co-processor space. */
67 #define ARM_ARCH_V1 ARM_EXT_V1
68 #define ARM_ARCH_V2 (ARM_ARCH_V1 | ARM_EXT_V2)
69 #define ARM_ARCH_V2S (ARM_ARCH_V2 | ARM_EXT_V2S)
70 #define ARM_ARCH_V3 (ARM_ARCH_V2S | ARM_EXT_V3)
71 #define ARM_ARCH_V3M (ARM_ARCH_V3 | ARM_EXT_V3M)
72 #define ARM_ARCH_V4xM (ARM_ARCH_V3 | ARM_EXT_V4)
73 #define ARM_ARCH_V4 (ARM_ARCH_V3M | ARM_EXT_V4)
74 #define ARM_ARCH_V4TxM (ARM_ARCH_V4xM | ARM_EXT_V4T)
75 #define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_EXT_V4T)
76 #define ARM_ARCH_V5xM (ARM_ARCH_V4xM | ARM_EXT_V5)
77 #define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
78 #define ARM_ARCH_V5TxM (ARM_ARCH_V5xM | ARM_EXT_V4T | ARM_EXT_V5T)
79 #define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_EXT_V4T | ARM_EXT_V5T)
80 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
81 #define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
83 /* Processors with specific extensions in the co-processor space. */
84 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
86 /* Some useful combinations: */
87 #define ARM_ANY 0x0000ffff /* Any basic core. */
88 #define ARM_ALL 0x00ffffff /* Any core + co-processor */
89 #define CPROC_ANY 0x00ff0000 /* Any co-processor */
90 #define FPU_ANY 0xff000000 /* Note this is ~ARM_ALL. */
93 #define FPU_FPA_EXT_V1 0x80000000 /* Base FPA instruction set. */
94 #define FPU_FPA_EXT_V2 0x40000000 /* LFM/SFM. */
95 #define FPU_VFP_EXT_NONE 0x20000000 /* Use VFP word-ordering. */
96 #define FPU_VFP_EXT_V1xD 0x10000000 /* Base VFP instruction set. */
97 #define FPU_VFP_EXT_V1 0x08000000 /* Double-precision insns. */
98 #define FPU_VFP_EXT_V2 0x04000000 /* ARM10E VFPr1. */
101 #define FPU_ARCH_FPE FPU_FPA_EXT_V1
102 #define FPU_ARCH_FPA (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
104 #define FPU_ARCH_VFP FPU_VFP_EXT_NONE
105 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
106 #define FPU_ARCH_VFP_V1 (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
107 #define FPU_ARCH_VFP_V2 (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
109 /* Types of processor to assemble for. */
110 #define ARM_1 ARM_ARCH_V1
111 #define ARM_2 ARM_ARCH_V2
112 #define ARM_3 ARM_ARCH_V2S
113 #define ARM_250 ARM_ARCH_V2S
114 #define ARM_6 ARM_ARCH_V3
115 #define ARM_7 ARM_ARCH_V3
116 #define ARM_8 ARM_ARCH_V4
117 #define ARM_9 ARM_ARCH_V4T
118 #define ARM_STRONG ARM_ARCH_V4
119 #define ARM_CPU_MASK 0x0000000f /* XXX? */
122 #if defined __XSCALE__
123 #define CPU_DEFAULT (ARM_ARCH_XSCALE)
125 #if defined __thumb__
126 #define CPU_DEFAULT (ARM_ARCH_V5T)
128 #define CPU_DEFAULT ARM_ANY
133 /* For backwards compatibility we default to the FPA. */
135 #define FPU_DEFAULT FPU_ARCH_FPA
138 #define streq(a, b) (strcmp (a, b) == 0)
139 #define skip_whitespace(str) while (*(str) == ' ') ++(str)
141 static unsigned long cpu_variant
;
142 static int target_oabi
= 0;
144 /* Flags stored in private area of BFD structure. */
145 static int uses_apcs_26
= false;
146 static int atpcs
= false;
147 static int support_interwork
= false;
148 static int uses_apcs_float
= false;
149 static int pic_code
= false;
151 /* Variables that we set while parsing command-line options. Once all
152 options have been read we re-process these values to set the real
154 static int legacy_cpu
= -1;
155 static int legacy_fpu
= -1;
157 static int mcpu_cpu_opt
= -1;
158 static int mcpu_fpu_opt
= -1;
159 static int march_cpu_opt
= -1;
160 static int march_fpu_opt
= -1;
161 static int mfpu_opt
= -1;
163 /* This array holds the chars that always start a comment. If the
164 pre-processor is disabled, these aren't very useful. */
165 const char comment_chars
[] = "@";
167 /* This array holds the chars that only start a comment at the beginning of
168 a line. If the line seems to have the form '# 123 filename'
169 .line and .file directives will appear in the pre-processed output. */
170 /* Note that input_file.c hand checks for '#' at the beginning of the
171 first line of the input file. This is because the compiler outputs
172 #NO_APP at the beginning of its output. */
173 /* Also note that comments like this one will always work. */
174 const char line_comment_chars
[] = "#";
176 const char line_separator_chars
[] = ";";
178 /* Chars that can be used to separate mant
179 from exp in floating point numbers. */
180 const char EXP_CHARS
[] = "eE";
182 /* Chars that mean this number is a floating point constant. */
186 const char FLT_CHARS
[] = "rRsSfFdDxXeEpP";
188 /* Prefix characters that indicate the start of an immediate
190 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
193 /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
194 symbolS
* GOT_symbol
;
197 /* Size of relocation record. */
198 const int md_reloc_size
= 8;
200 /* 0: assemble for ARM,
201 1: assemble for Thumb,
202 2: assemble for Thumb even though target CPU does not support thumb
204 static int thumb_mode
= 0;
206 typedef struct arm_fix
214 unsigned long instruction
;
218 bfd_reloc_code_real_type type
;
235 struct asm_shift_properties
237 enum asm_shift_index index
;
238 unsigned long bit_field
;
239 unsigned int allows_0
: 1;
240 unsigned int allows_32
: 1;
243 static const struct asm_shift_properties shift_properties
[] =
245 { SHIFT_LSL
, 0, 1, 0},
246 { SHIFT_LSR
, 0x20, 0, 1},
247 { SHIFT_ASR
, 0x40, 0, 1},
248 { SHIFT_ROR
, 0x60, 0, 0},
249 { SHIFT_RRX
, 0x60, 0, 0}
252 struct asm_shift_name
255 const struct asm_shift_properties
* properties
;
258 static const struct asm_shift_name shift_names
[] =
260 { "asl", shift_properties
+ SHIFT_LSL
},
261 { "lsl", shift_properties
+ SHIFT_LSL
},
262 { "lsr", shift_properties
+ SHIFT_LSR
},
263 { "asr", shift_properties
+ SHIFT_ASR
},
264 { "ror", shift_properties
+ SHIFT_ROR
},
265 { "rrx", shift_properties
+ SHIFT_RRX
},
266 { "ASL", shift_properties
+ SHIFT_LSL
},
267 { "LSL", shift_properties
+ SHIFT_LSL
},
268 { "LSR", shift_properties
+ SHIFT_LSR
},
269 { "ASR", shift_properties
+ SHIFT_ASR
},
270 { "ROR", shift_properties
+ SHIFT_ROR
},
271 { "RRX", shift_properties
+ SHIFT_RRX
}
274 #define NO_SHIFT_RESTRICT 1
275 #define SHIFT_RESTRICT 0
277 #define NUM_FLOAT_VALS 8
279 const char * fp_const
[] =
281 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
284 /* Number of littlenums required to hold an extended precision number. */
285 #define MAX_LITTLENUMS 6
287 LITTLENUM_TYPE fp_values
[NUM_FLOAT_VALS
][MAX_LITTLENUMS
];
292 /* Whether a Co-processor load/store operation accepts write-back forms. */
301 #define CP_T_X 0x00008000
302 #define CP_T_Y 0x00400000
303 #define CP_T_Pre 0x01000000
304 #define CP_T_UD 0x00800000
305 #define CP_T_WB 0x00200000
307 #define CONDS_BIT 0x00100000
308 #define LOAD_BIT 0x00100000
310 #define DOUBLE_LOAD_FLAG 0x00000001
314 const char * template;
318 #define COND_ALWAYS 0xe0000000
319 #define COND_MASK 0xf0000000
321 static const struct asm_cond conds
[] =
325 {"cs", 0x20000000}, {"hs", 0x20000000},
326 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
343 const char * template;
348 /* The bit that distnguishes CPSR and SPSR. */
349 #define SPSR_BIT (1 << 22)
351 /* How many bits to shift the PSR_xxx bits up by. */
354 #define PSR_c (1 << 0)
355 #define PSR_x (1 << 1)
356 #define PSR_s (1 << 2)
357 #define PSR_f (1 << 3)
359 static const struct asm_psr psrs
[] =
361 {"CPSR", true, PSR_c
| PSR_f
},
362 {"CPSR_all", true, PSR_c
| PSR_f
},
363 {"SPSR", false, PSR_c
| PSR_f
},
364 {"SPSR_all", false, PSR_c
| PSR_f
},
365 {"CPSR_flg", true, PSR_f
},
366 {"CPSR_f", true, PSR_f
},
367 {"SPSR_flg", false, PSR_f
},
368 {"SPSR_f", false, PSR_f
},
369 {"CPSR_c", true, PSR_c
},
370 {"CPSR_ctl", true, PSR_c
},
371 {"SPSR_c", false, PSR_c
},
372 {"SPSR_ctl", false, PSR_c
},
373 {"CPSR_x", true, PSR_x
},
374 {"CPSR_s", true, PSR_s
},
375 {"SPSR_x", false, PSR_x
},
376 {"SPSR_s", false, PSR_s
},
377 /* Combinations of flags. */
378 {"CPSR_fs", true, PSR_f
| PSR_s
},
379 {"CPSR_fx", true, PSR_f
| PSR_x
},
380 {"CPSR_fc", true, PSR_f
| PSR_c
},
381 {"CPSR_sf", true, PSR_s
| PSR_f
},
382 {"CPSR_sx", true, PSR_s
| PSR_x
},
383 {"CPSR_sc", true, PSR_s
| PSR_c
},
384 {"CPSR_xf", true, PSR_x
| PSR_f
},
385 {"CPSR_xs", true, PSR_x
| PSR_s
},
386 {"CPSR_xc", true, PSR_x
| PSR_c
},
387 {"CPSR_cf", true, PSR_c
| PSR_f
},
388 {"CPSR_cs", true, PSR_c
| PSR_s
},
389 {"CPSR_cx", true, PSR_c
| PSR_x
},
390 {"CPSR_fsx", true, PSR_f
| PSR_s
| PSR_x
},
391 {"CPSR_fsc", true, PSR_f
| PSR_s
| PSR_c
},
392 {"CPSR_fxs", true, PSR_f
| PSR_x
| PSR_s
},
393 {"CPSR_fxc", true, PSR_f
| PSR_x
| PSR_c
},
394 {"CPSR_fcs", true, PSR_f
| PSR_c
| PSR_s
},
395 {"CPSR_fcx", true, PSR_f
| PSR_c
| PSR_x
},
396 {"CPSR_sfx", true, PSR_s
| PSR_f
| PSR_x
},
397 {"CPSR_sfc", true, PSR_s
| PSR_f
| PSR_c
},
398 {"CPSR_sxf", true, PSR_s
| PSR_x
| PSR_f
},
399 {"CPSR_sxc", true, PSR_s
| PSR_x
| PSR_c
},
400 {"CPSR_scf", true, PSR_s
| PSR_c
| PSR_f
},
401 {"CPSR_scx", true, PSR_s
| PSR_c
| PSR_x
},
402 {"CPSR_xfs", true, PSR_x
| PSR_f
| PSR_s
},
403 {"CPSR_xfc", true, PSR_x
| PSR_f
| PSR_c
},
404 {"CPSR_xsf", true, PSR_x
| PSR_s
| PSR_f
},
405 {"CPSR_xsc", true, PSR_x
| PSR_s
| PSR_c
},
406 {"CPSR_xcf", true, PSR_x
| PSR_c
| PSR_f
},
407 {"CPSR_xcs", true, PSR_x
| PSR_c
| PSR_s
},
408 {"CPSR_cfs", true, PSR_c
| PSR_f
| PSR_s
},
409 {"CPSR_cfx", true, PSR_c
| PSR_f
| PSR_x
},
410 {"CPSR_csf", true, PSR_c
| PSR_s
| PSR_f
},
411 {"CPSR_csx", true, PSR_c
| PSR_s
| PSR_x
},
412 {"CPSR_cxf", true, PSR_c
| PSR_x
| PSR_f
},
413 {"CPSR_cxs", true, PSR_c
| PSR_x
| PSR_s
},
414 {"CPSR_fsxc", true, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
415 {"CPSR_fscx", true, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
416 {"CPSR_fxsc", true, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
417 {"CPSR_fxcs", true, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
418 {"CPSR_fcsx", true, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
419 {"CPSR_fcxs", true, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
420 {"CPSR_sfxc", true, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
421 {"CPSR_sfcx", true, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
422 {"CPSR_sxfc", true, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
423 {"CPSR_sxcf", true, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
424 {"CPSR_scfx", true, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
425 {"CPSR_scxf", true, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
426 {"CPSR_xfsc", true, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
427 {"CPSR_xfcs", true, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
428 {"CPSR_xsfc", true, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
429 {"CPSR_xscf", true, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
430 {"CPSR_xcfs", true, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
431 {"CPSR_xcsf", true, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
432 {"CPSR_cfsx", true, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
433 {"CPSR_cfxs", true, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
434 {"CPSR_csfx", true, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
435 {"CPSR_csxf", true, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
436 {"CPSR_cxfs", true, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
437 {"CPSR_cxsf", true, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
438 {"SPSR_fs", false, PSR_f
| PSR_s
},
439 {"SPSR_fx", false, PSR_f
| PSR_x
},
440 {"SPSR_fc", false, PSR_f
| PSR_c
},
441 {"SPSR_sf", false, PSR_s
| PSR_f
},
442 {"SPSR_sx", false, PSR_s
| PSR_x
},
443 {"SPSR_sc", false, PSR_s
| PSR_c
},
444 {"SPSR_xf", false, PSR_x
| PSR_f
},
445 {"SPSR_xs", false, PSR_x
| PSR_s
},
446 {"SPSR_xc", false, PSR_x
| PSR_c
},
447 {"SPSR_cf", false, PSR_c
| PSR_f
},
448 {"SPSR_cs", false, PSR_c
| PSR_s
},
449 {"SPSR_cx", false, PSR_c
| PSR_x
},
450 {"SPSR_fsx", false, PSR_f
| PSR_s
| PSR_x
},
451 {"SPSR_fsc", false, PSR_f
| PSR_s
| PSR_c
},
452 {"SPSR_fxs", false, PSR_f
| PSR_x
| PSR_s
},
453 {"SPSR_fxc", false, PSR_f
| PSR_x
| PSR_c
},
454 {"SPSR_fcs", false, PSR_f
| PSR_c
| PSR_s
},
455 {"SPSR_fcx", false, PSR_f
| PSR_c
| PSR_x
},
456 {"SPSR_sfx", false, PSR_s
| PSR_f
| PSR_x
},
457 {"SPSR_sfc", false, PSR_s
| PSR_f
| PSR_c
},
458 {"SPSR_sxf", false, PSR_s
| PSR_x
| PSR_f
},
459 {"SPSR_sxc", false, PSR_s
| PSR_x
| PSR_c
},
460 {"SPSR_scf", false, PSR_s
| PSR_c
| PSR_f
},
461 {"SPSR_scx", false, PSR_s
| PSR_c
| PSR_x
},
462 {"SPSR_xfs", false, PSR_x
| PSR_f
| PSR_s
},
463 {"SPSR_xfc", false, PSR_x
| PSR_f
| PSR_c
},
464 {"SPSR_xsf", false, PSR_x
| PSR_s
| PSR_f
},
465 {"SPSR_xsc", false, PSR_x
| PSR_s
| PSR_c
},
466 {"SPSR_xcf", false, PSR_x
| PSR_c
| PSR_f
},
467 {"SPSR_xcs", false, PSR_x
| PSR_c
| PSR_s
},
468 {"SPSR_cfs", false, PSR_c
| PSR_f
| PSR_s
},
469 {"SPSR_cfx", false, PSR_c
| PSR_f
| PSR_x
},
470 {"SPSR_csf", false, PSR_c
| PSR_s
| PSR_f
},
471 {"SPSR_csx", false, PSR_c
| PSR_s
| PSR_x
},
472 {"SPSR_cxf", false, PSR_c
| PSR_x
| PSR_f
},
473 {"SPSR_cxs", false, PSR_c
| PSR_x
| PSR_s
},
474 {"SPSR_fsxc", false, PSR_f
| PSR_s
| PSR_x
| PSR_c
},
475 {"SPSR_fscx", false, PSR_f
| PSR_s
| PSR_c
| PSR_x
},
476 {"SPSR_fxsc", false, PSR_f
| PSR_x
| PSR_s
| PSR_c
},
477 {"SPSR_fxcs", false, PSR_f
| PSR_x
| PSR_c
| PSR_s
},
478 {"SPSR_fcsx", false, PSR_f
| PSR_c
| PSR_s
| PSR_x
},
479 {"SPSR_fcxs", false, PSR_f
| PSR_c
| PSR_x
| PSR_s
},
480 {"SPSR_sfxc", false, PSR_s
| PSR_f
| PSR_x
| PSR_c
},
481 {"SPSR_sfcx", false, PSR_s
| PSR_f
| PSR_c
| PSR_x
},
482 {"SPSR_sxfc", false, PSR_s
| PSR_x
| PSR_f
| PSR_c
},
483 {"SPSR_sxcf", false, PSR_s
| PSR_x
| PSR_c
| PSR_f
},
484 {"SPSR_scfx", false, PSR_s
| PSR_c
| PSR_f
| PSR_x
},
485 {"SPSR_scxf", false, PSR_s
| PSR_c
| PSR_x
| PSR_f
},
486 {"SPSR_xfsc", false, PSR_x
| PSR_f
| PSR_s
| PSR_c
},
487 {"SPSR_xfcs", false, PSR_x
| PSR_f
| PSR_c
| PSR_s
},
488 {"SPSR_xsfc", false, PSR_x
| PSR_s
| PSR_f
| PSR_c
},
489 {"SPSR_xscf", false, PSR_x
| PSR_s
| PSR_c
| PSR_f
},
490 {"SPSR_xcfs", false, PSR_x
| PSR_c
| PSR_f
| PSR_s
},
491 {"SPSR_xcsf", false, PSR_x
| PSR_c
| PSR_s
| PSR_f
},
492 {"SPSR_cfsx", false, PSR_c
| PSR_f
| PSR_s
| PSR_x
},
493 {"SPSR_cfxs", false, PSR_c
| PSR_f
| PSR_x
| PSR_s
},
494 {"SPSR_csfx", false, PSR_c
| PSR_s
| PSR_f
| PSR_x
},
495 {"SPSR_csxf", false, PSR_c
| PSR_s
| PSR_x
| PSR_f
},
496 {"SPSR_cxfs", false, PSR_c
| PSR_x
| PSR_f
| PSR_s
},
497 {"SPSR_cxsf", false, PSR_c
| PSR_x
| PSR_s
| PSR_f
},
502 VFP_REG_Dd
, VFP_REG_Dm
, VFP_REG_Dn
507 VFP_REG_Sd
, VFP_REG_Sm
, VFP_REG_Sn
512 VFP_LDSTMIA
, VFP_LDSTMDB
, VFP_LDSTMIAX
, VFP_LDSTMDBX
515 /* VFP system registers. */
522 static const struct vfp_reg vfp_regs
[] =
524 {"fpsid", 0x00000000},
525 {"FPSID", 0x00000000},
526 {"fpscr", 0x00010000},
527 {"FPSCR", 0x00010000},
528 {"fpexc", 0x00080000},
529 {"FPEXC", 0x00080000}
532 /* Structure for a hash table entry for a register. */
539 /* Some well known registers that we refer to directly elsewhere. */
544 /* These are the standard names. Users can add aliases with .req. */
545 /* Integer Register Numbers. */
546 static const struct reg_entry rn_table
[] =
548 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
549 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
550 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
551 {"r12", 12}, {"r13", REG_SP
}, {"r14", REG_LR
}, {"r15", REG_PC
},
552 /* ATPCS Synonyms. */
553 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
554 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7},
555 {"v5", 8}, {"v6", 9}, {"v7", 10}, {"v8", 11},
556 /* Well-known aliases. */
558 {"sb", 9}, {"sl", 10}, {"fp", 11},
559 {"ip", 12}, {"sp", REG_SP
}, {"lr", REG_LR
}, {"pc", REG_PC
},
563 /* Co-processor Numbers. */
564 static const struct reg_entry cp_table
[] =
566 {"p0", 0}, {"p1", 1}, {"p2", 2}, {"p3", 3},
567 {"p4", 4}, {"p5", 5}, {"p6", 6}, {"p7", 7},
568 {"p8", 8}, {"p9", 9}, {"p10", 10}, {"p11", 11},
569 {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
573 /* Co-processor Register Numbers. */
574 static const struct reg_entry cn_table
[] =
576 {"c0", 0}, {"c1", 1}, {"c2", 2}, {"c3", 3},
577 {"c4", 4}, {"c5", 5}, {"c6", 6}, {"c7", 7},
578 {"c8", 8}, {"c9", 9}, {"c10", 10}, {"c11", 11},
579 {"c12", 12}, {"c13", 13}, {"c14", 14}, {"c15", 15},
580 /* Not really valid, but kept for back-wards compatibility. */
581 {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
582 {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
583 {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
584 {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
589 static const struct reg_entry fn_table
[] =
591 {"f0", 0}, {"f1", 1}, {"f2", 2}, {"f3", 3},
592 {"f4", 4}, {"f5", 5}, {"f6", 6}, {"f7", 7},
596 /* VFP SP Registers. */
597 static const struct reg_entry sn_table
[] =
599 {"s0", 0}, {"s1", 1}, {"s2", 2}, {"s3", 3},
600 {"s4", 4}, {"s5", 5}, {"s6", 6}, {"s7", 7},
601 {"s8", 8}, {"s9", 9}, {"s10", 10}, {"s11", 11},
602 {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
603 {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
604 {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
605 {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
606 {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
610 /* VFP DP Registers. */
611 static const struct reg_entry dn_table
[] =
613 {"d0", 0}, {"d1", 1}, {"d2", 2}, {"d3", 3},
614 {"d4", 4}, {"d5", 5}, {"d6", 6}, {"d7", 7},
615 {"d8", 8}, {"d9", 9}, {"d10", 10}, {"d11", 11},
616 {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
620 /* Cirrus DSP coprocessor registers. */
621 static const struct reg_entry mav_mvf_table
[] =
623 {"mvf0", 0}, {"mvf1", 1}, {"mvf2", 2}, {"mvf3", 3},
624 {"mvf4", 4}, {"mvf5", 5}, {"mvf6", 6}, {"mvf7", 7},
625 {"mvf8", 8}, {"mvf9", 9}, {"mvf10", 10}, {"mvf11", 11},
626 {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
630 static const struct reg_entry mav_mvd_table
[] =
632 {"mvd0", 0}, {"mvd1", 1}, {"mvd2", 2}, {"mvd3", 3},
633 {"mvd4", 4}, {"mvd5", 5}, {"mvd6", 6}, {"mvd7", 7},
634 {"mvd8", 8}, {"mvd9", 9}, {"mvd10", 10}, {"mvd11", 11},
635 {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
639 static const struct reg_entry mav_mvfx_table
[] =
641 {"mvfx0", 0}, {"mvfx1", 1}, {"mvfx2", 2}, {"mvfx3", 3},
642 {"mvfx4", 4}, {"mvfx5", 5}, {"mvfx6", 6}, {"mvfx7", 7},
643 {"mvfx8", 8}, {"mvfx9", 9}, {"mvfx10", 10}, {"mvfx11", 11},
644 {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
648 static const struct reg_entry mav_mvdx_table
[] =
650 {"mvdx0", 0}, {"mvdx1", 1}, {"mvdx2", 2}, {"mvdx3", 3},
651 {"mvdx4", 4}, {"mvdx5", 5}, {"mvdx6", 6}, {"mvdx7", 7},
652 {"mvdx8", 8}, {"mvdx9", 9}, {"mvdx10", 10}, {"mvdx11", 11},
653 {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
657 static const struct reg_entry mav_mvax_table
[] =
659 {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
663 static const struct reg_entry mav_dspsc_table
[] =
671 const struct reg_entry
*names
;
673 struct hash_control
*htab
;
674 const char *expected
;
677 struct reg_map all_reg_maps
[] =
679 {rn_table
, 15, NULL
, N_("ARM register expected")},
680 {cp_table
, 15, NULL
, N_("bad or missing co-processor number")},
681 {cn_table
, 15, NULL
, N_("co-processor register expected")},
682 {fn_table
, 7, NULL
, N_("FPA register expected")},
683 {sn_table
, 31, NULL
, N_("VFP single precision register expected")},
684 {dn_table
, 15, NULL
, N_("VFP double precision register expected")},
685 {mav_mvf_table
, 15, NULL
, N_("Maverick MVF register expected")},
686 {mav_mvd_table
, 15, NULL
, N_("Maverick MVD register expected")},
687 {mav_mvfx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
688 {mav_mvdx_table
, 15, NULL
, N_("Maverick MVFX register expected")},
689 {mav_mvax_table
, 3, NULL
, N_("Maverick MVAX register expected")},
690 {mav_dspsc_table
, 0, NULL
, N_("Maverick DSPSC register expected")},
693 /* Enumeration matching entries in table above. */
697 #define REG_TYPE_FIRST REG_TYPE_RN
713 /* Functions called by parser. */
714 /* ARM instructions. */
715 static void do_arit
PARAMS ((char *));
716 static void do_cmp
PARAMS ((char *));
717 static void do_mov
PARAMS ((char *));
718 static void do_ldst
PARAMS ((char *));
719 static void do_ldstt
PARAMS ((char *));
720 static void do_ldmstm
PARAMS ((char *));
721 static void do_branch
PARAMS ((char *));
722 static void do_swi
PARAMS ((char *));
724 /* Pseudo Op codes. */
725 static void do_adr
PARAMS ((char *));
726 static void do_adrl
PARAMS ((char *));
727 static void do_empty
PARAMS ((char *));
730 static void do_mul
PARAMS ((char *));
731 static void do_mla
PARAMS ((char *));
734 static void do_swap
PARAMS ((char *));
737 static void do_msr
PARAMS ((char *));
738 static void do_mrs
PARAMS ((char *));
741 static void do_mull
PARAMS ((char *));
744 static void do_ldstv4
PARAMS ((char *));
747 static void do_bx
PARAMS ((char *));
750 static void do_blx
PARAMS ((char *));
751 static void do_bkpt
PARAMS ((char *));
752 static void do_clz
PARAMS ((char *));
753 static void do_lstc2
PARAMS ((char *));
754 static void do_cdp2
PARAMS ((char *));
755 static void do_co_reg2
PARAMS ((char *));
758 static void do_smla
PARAMS ((char *));
759 static void do_smlal
PARAMS ((char *));
760 static void do_smul
PARAMS ((char *));
761 static void do_qadd
PARAMS ((char *));
764 static void do_pld
PARAMS ((char *));
765 static void do_ldrd
PARAMS ((char *));
766 static void do_co_reg2c
PARAMS ((char *));
768 /* Coprocessor Instructions. */
769 static void do_cdp
PARAMS ((char *));
770 static void do_lstc
PARAMS ((char *));
771 static void do_co_reg
PARAMS ((char *));
773 /* FPA instructions. */
774 static void do_fpa_ctrl
PARAMS ((char *));
775 static void do_fpa_ldst
PARAMS ((char *));
776 static void do_fpa_ldmstm
PARAMS ((char *));
777 static void do_fpa_dyadic
PARAMS ((char *));
778 static void do_fpa_monadic
PARAMS ((char *));
779 static void do_fpa_cmp
PARAMS ((char *));
780 static void do_fpa_from_reg
PARAMS ((char *));
781 static void do_fpa_to_reg
PARAMS ((char *));
783 /* VFP instructions. */
784 static void do_vfp_sp_monadic
PARAMS ((char *));
785 static void do_vfp_dp_monadic
PARAMS ((char *));
786 static void do_vfp_sp_dyadic
PARAMS ((char *));
787 static void do_vfp_dp_dyadic
PARAMS ((char *));
788 static void do_vfp_reg_from_sp
PARAMS ((char *));
789 static void do_vfp_sp_from_reg
PARAMS ((char *));
790 static void do_vfp_sp_reg2
PARAMS ((char *));
791 static void do_vfp_reg_from_dp
PARAMS ((char *));
792 static void do_vfp_reg2_from_dp
PARAMS ((char *));
793 static void do_vfp_dp_from_reg
PARAMS ((char *));
794 static void do_vfp_dp_from_reg2
PARAMS ((char *));
795 static void do_vfp_reg_from_ctrl
PARAMS ((char *));
796 static void do_vfp_ctrl_from_reg
PARAMS ((char *));
797 static void do_vfp_sp_ldst
PARAMS ((char *));
798 static void do_vfp_dp_ldst
PARAMS ((char *));
799 static void do_vfp_sp_ldstmia
PARAMS ((char *));
800 static void do_vfp_sp_ldstmdb
PARAMS ((char *));
801 static void do_vfp_dp_ldstmia
PARAMS ((char *));
802 static void do_vfp_dp_ldstmdb
PARAMS ((char *));
803 static void do_vfp_xp_ldstmia
PARAMS ((char *));
804 static void do_vfp_xp_ldstmdb
PARAMS ((char *));
805 static void do_vfp_sp_compare_z
PARAMS ((char *));
806 static void do_vfp_dp_compare_z
PARAMS ((char *));
807 static void do_vfp_dp_sp_cvt
PARAMS ((char *));
808 static void do_vfp_sp_dp_cvt
PARAMS ((char *));
811 static void do_mia
PARAMS ((char *));
812 static void do_mar
PARAMS ((char *));
813 static void do_mra
PARAMS ((char *));
816 static void do_c_binops
PARAMS ((char *, int, enum arm_reg_type
,
818 static void do_c_binops_1a
PARAMS ((char *));
819 static void do_c_binops_1b
PARAMS ((char *));
820 static void do_c_binops_1c
PARAMS ((char *));
821 static void do_c_binops_1d
PARAMS ((char *));
822 static void do_c_binops_1e
PARAMS ((char *));
823 static void do_c_binops_1f
PARAMS ((char *));
824 static void do_c_binops_1g
PARAMS ((char *));
825 static void do_c_binops_1h
PARAMS ((char *));
826 static void do_c_binops_1i
PARAMS ((char *));
827 static void do_c_binops_1j
PARAMS ((char *));
828 static void do_c_binops_1k
PARAMS ((char *));
829 static void do_c_binops_1l
PARAMS ((char *));
830 static void do_c_binops_1m
PARAMS ((char *));
831 static void do_c_binops_1n
PARAMS ((char *));
832 static void do_c_binops_1o
PARAMS ((char *));
833 static void do_c_binops_2a
PARAMS ((char *));
834 static void do_c_binops_2b
PARAMS ((char *));
835 static void do_c_binops_2c
PARAMS ((char *));
836 static void do_c_binops_3a
PARAMS ((char *));
837 static void do_c_binops_3b
PARAMS ((char *));
838 static void do_c_binops_3c
PARAMS ((char *));
839 static void do_c_binops_3d
PARAMS ((char *));
840 static void do_c_triple
PARAMS ((char *, int, enum arm_reg_type
,
843 static void do_c_triple_4a
PARAMS ((char *));
844 static void do_c_triple_4b
PARAMS ((char *));
845 static void do_c_triple_5a
PARAMS ((char *));
846 static void do_c_triple_5b
PARAMS ((char *));
847 static void do_c_triple_5c
PARAMS ((char *));
848 static void do_c_triple_5d
PARAMS ((char *));
849 static void do_c_triple_5e
PARAMS ((char *));
850 static void do_c_triple_5f
PARAMS ((char *));
851 static void do_c_triple_5g
PARAMS ((char *));
852 static void do_c_triple_5h
PARAMS ((char *));
853 static void do_c_quad
PARAMS ((char *, int, enum arm_reg_type
,
857 static void do_c_quad_6a
PARAMS ((char *));
858 static void do_c_quad_6b
PARAMS ((char *));
859 static void do_c_dspsc_1
PARAMS ((char *));
860 static void do_c_dspsc_2
PARAMS ((char *));
861 static void do_c_shift
PARAMS ((char *, enum arm_reg_type
,
863 static void do_c_shift_1
PARAMS ((char *));
864 static void do_c_shift_2
PARAMS ((char *));
865 static void do_c_ldst
PARAMS ((char *, enum arm_reg_type
));
866 static void do_c_ldst_1
PARAMS ((char *));
867 static void do_c_ldst_2
PARAMS ((char *));
868 static void do_c_ldst_3
PARAMS ((char *));
869 static void do_c_ldst_4
PARAMS ((char *));
871 static int cirrus_reg_required_here
PARAMS ((char **, int,
873 static int cirrus_parse_offset
PARAMS ((char **, int *));
875 static void fix_new_arm
PARAMS ((fragS
*, int, short, expressionS
*,
877 static int arm_reg_parse
PARAMS ((char **, struct hash_control
*));
878 static enum arm_reg_type arm_reg_parse_any
PARAMS ((char *));
879 static const struct asm_psr
* arm_psr_parse
PARAMS ((char **));
880 static void symbol_locate
PARAMS ((symbolS
*, const char *, segT
, valueT
,
882 static int add_to_lit_pool
PARAMS ((void));
883 static unsigned validate_immediate
PARAMS ((unsigned));
884 static unsigned validate_immediate_twopart
PARAMS ((unsigned int,
886 static int validate_offset_imm
PARAMS ((unsigned int, int));
887 static void opcode_select
PARAMS ((int));
888 static void end_of_line
PARAMS ((char *));
889 static int reg_required_here
PARAMS ((char **, int));
890 static int psr_required_here
PARAMS ((char **));
891 static int co_proc_number
PARAMS ((char **));
892 static int cp_opc_expr
PARAMS ((char **, int, int));
893 static int cp_reg_required_here
PARAMS ((char **, int));
894 static int fp_reg_required_here
PARAMS ((char **, int));
895 static int vfp_sp_reg_required_here
PARAMS ((char **, enum vfp_sp_reg_pos
));
896 static int vfp_dp_reg_required_here
PARAMS ((char **, enum vfp_dp_reg_pos
));
897 static void vfp_sp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
898 static void vfp_dp_ldstm
PARAMS ((char *, enum vfp_ldstm_type
));
899 static long vfp_sp_reg_list
PARAMS ((char **, enum vfp_sp_reg_pos
));
900 static long vfp_dp_reg_list
PARAMS ((char **));
901 static int vfp_psr_required_here
PARAMS ((char **str
));
902 static const struct vfp_reg
*vfp_psr_parse
PARAMS ((char **str
));
903 static int cp_address_offset
PARAMS ((char **));
904 static int cp_address_required_here
PARAMS ((char **, int));
905 static int my_get_float_expression
PARAMS ((char **));
906 static int skip_past_comma
PARAMS ((char **));
907 static int walk_no_bignums
PARAMS ((symbolS
*));
908 static int negate_data_op
PARAMS ((unsigned long *, unsigned long));
909 static int data_op2
PARAMS ((char **));
910 static int fp_op2
PARAMS ((char **));
911 static long reg_list
PARAMS ((char **));
912 static void thumb_load_store
PARAMS ((char *, int, int));
913 static int decode_shift
PARAMS ((char **, int));
914 static int ldst_extend
PARAMS ((char **));
915 static int ldst_extend_v4
PARAMS ((char **));
916 static void thumb_add_sub
PARAMS ((char *, int));
917 static void insert_reg
PARAMS ((const struct reg_entry
*,
918 struct hash_control
*));
919 static void thumb_shift
PARAMS ((char *, int));
920 static void thumb_mov_compare
PARAMS ((char *, int));
921 static void build_arm_ops_hsh
PARAMS ((void));
922 static void set_constant_flonums
PARAMS ((void));
923 static valueT md_chars_to_number
PARAMS ((char *, int));
924 static void build_reg_hsh
PARAMS ((struct reg_map
*));
925 static void insert_reg_alias
PARAMS ((char *, int, struct hash_control
*));
926 static int create_register_alias
PARAMS ((char *, char *));
927 static void output_inst
PARAMS ((const char *));
928 static int accum0_required_here
PARAMS ((char **));
929 static int ld_mode_required_here
PARAMS ((char **));
930 static void do_branch25
PARAMS ((char *));
931 static symbolS
* find_real_start
PARAMS ((symbolS
*));
933 static bfd_reloc_code_real_type arm_parse_reloc
PARAMS ((void));
936 /* ARM instructions take 4bytes in the object file, Thumb instructions
940 /* "INSN<cond> X,Y" where X:bit12, Y:bit16. */
941 #define CIRRUS_MODE1 0x100c
943 /* "INSN<cond> X,Y" where X:bit16, Y:bit12. */
944 #define CIRRUS_MODE2 0x0c10
946 /* "INSN<cond> X,Y" where X:0, Y:bit16. */
947 #define CIRRUS_MODE3 0x1000
949 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12. */
950 #define CIRRUS_MODE4 0x0c0010
952 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0. */
953 #define CIRRUS_MODE5 0x00100c
955 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0. */
956 #define CIRRUS_MODE6 0x00100c05
960 /* Basic string to match. */
961 const char * template;
963 /* Basic instruction code. */
966 /* Offset into the template where the condition code (if any) will be.
967 If zero, then the instruction is never conditional. */
968 unsigned cond_offset
;
970 /* Which architecture variant provides this instruction. */
971 unsigned long variant
;
973 /* Function to call to parse args. */
974 void (* parms
) PARAMS ((char *));
977 static const struct asm_opcode insns
[] =
979 /* Core ARM Instructions. */
980 {"and", 0xe0000000, 3, ARM_EXT_V1
, do_arit
},
981 {"ands", 0xe0100000, 3, ARM_EXT_V1
, do_arit
},
982 {"eor", 0xe0200000, 3, ARM_EXT_V1
, do_arit
},
983 {"eors", 0xe0300000, 3, ARM_EXT_V1
, do_arit
},
984 {"sub", 0xe0400000, 3, ARM_EXT_V1
, do_arit
},
985 {"subs", 0xe0500000, 3, ARM_EXT_V1
, do_arit
},
986 {"rsb", 0xe0600000, 3, ARM_EXT_V1
, do_arit
},
987 {"rsbs", 0xe0700000, 3, ARM_EXT_V1
, do_arit
},
988 {"add", 0xe0800000, 3, ARM_EXT_V1
, do_arit
},
989 {"adds", 0xe0900000, 3, ARM_EXT_V1
, do_arit
},
990 {"adc", 0xe0a00000, 3, ARM_EXT_V1
, do_arit
},
991 {"adcs", 0xe0b00000, 3, ARM_EXT_V1
, do_arit
},
992 {"sbc", 0xe0c00000, 3, ARM_EXT_V1
, do_arit
},
993 {"sbcs", 0xe0d00000, 3, ARM_EXT_V1
, do_arit
},
994 {"rsc", 0xe0e00000, 3, ARM_EXT_V1
, do_arit
},
995 {"rscs", 0xe0f00000, 3, ARM_EXT_V1
, do_arit
},
996 {"orr", 0xe1800000, 3, ARM_EXT_V1
, do_arit
},
997 {"orrs", 0xe1900000, 3, ARM_EXT_V1
, do_arit
},
998 {"bic", 0xe1c00000, 3, ARM_EXT_V1
, do_arit
},
999 {"bics", 0xe1d00000, 3, ARM_EXT_V1
, do_arit
},
1001 {"tst", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1002 {"tsts", 0xe1100000, 3, ARM_EXT_V1
, do_cmp
},
1003 {"tstp", 0xe110f000, 3, ARM_EXT_V1
, do_cmp
},
1004 {"teq", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1005 {"teqs", 0xe1300000, 3, ARM_EXT_V1
, do_cmp
},
1006 {"teqp", 0xe130f000, 3, ARM_EXT_V1
, do_cmp
},
1007 {"cmp", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1008 {"cmps", 0xe1500000, 3, ARM_EXT_V1
, do_cmp
},
1009 {"cmpp", 0xe150f000, 3, ARM_EXT_V1
, do_cmp
},
1010 {"cmn", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1011 {"cmns", 0xe1700000, 3, ARM_EXT_V1
, do_cmp
},
1012 {"cmnp", 0xe170f000, 3, ARM_EXT_V1
, do_cmp
},
1014 {"mov", 0xe1a00000, 3, ARM_EXT_V1
, do_mov
},
1015 {"movs", 0xe1b00000, 3, ARM_EXT_V1
, do_mov
},
1016 {"mvn", 0xe1e00000, 3, ARM_EXT_V1
, do_mov
},
1017 {"mvns", 0xe1f00000, 3, ARM_EXT_V1
, do_mov
},
1019 {"ldr", 0xe4100000, 3, ARM_EXT_V1
, do_ldst
},
1020 {"ldrb", 0xe4500000, 3, ARM_EXT_V1
, do_ldst
},
1021 {"ldrt", 0xe4300000, 3, ARM_EXT_V1
, do_ldstt
},
1022 {"ldrbt", 0xe4700000, 3, ARM_EXT_V1
, do_ldstt
},
1023 {"str", 0xe4000000, 3, ARM_EXT_V1
, do_ldst
},
1024 {"strb", 0xe4400000, 3, ARM_EXT_V1
, do_ldst
},
1025 {"strt", 0xe4200000, 3, ARM_EXT_V1
, do_ldstt
},
1026 {"strbt", 0xe4600000, 3, ARM_EXT_V1
, do_ldstt
},
1028 {"stmia", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1029 {"stmib", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1030 {"stmda", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1031 {"stmdb", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1032 {"stmfd", 0xe9000000, 3, ARM_EXT_V1
, do_ldmstm
},
1033 {"stmfa", 0xe9800000, 3, ARM_EXT_V1
, do_ldmstm
},
1034 {"stmea", 0xe8800000, 3, ARM_EXT_V1
, do_ldmstm
},
1035 {"stmed", 0xe8000000, 3, ARM_EXT_V1
, do_ldmstm
},
1037 {"ldmia", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1038 {"ldmib", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1039 {"ldmda", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1040 {"ldmdb", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1041 {"ldmfd", 0xe8900000, 3, ARM_EXT_V1
, do_ldmstm
},
1042 {"ldmfa", 0xe8100000, 3, ARM_EXT_V1
, do_ldmstm
},
1043 {"ldmea", 0xe9100000, 3, ARM_EXT_V1
, do_ldmstm
},
1044 {"ldmed", 0xe9900000, 3, ARM_EXT_V1
, do_ldmstm
},
1046 {"swi", 0xef000000, 3, ARM_EXT_V1
, do_swi
},
1048 /* XXX This is the wrong place to do this. Think multi-arch. */
1049 {"bl", 0xeb000000, 2, ARM_EXT_V1
, do_branch
},
1050 {"b", 0xea000000, 1, ARM_EXT_V1
, do_branch
},
1052 {"bl", 0xebfffffe, 2, ARM_EXT_V1
, do_branch
},
1053 {"b", 0xeafffffe, 1, ARM_EXT_V1
, do_branch
},
1057 {"adr", 0xe28f0000, 3, ARM_EXT_V1
, do_adr
},
1058 {"adrl", 0xe28f0000, 3, ARM_EXT_V1
, do_adrl
},
1059 {"nop", 0xe1a00000, 3, ARM_EXT_V1
, do_empty
},
1061 /* ARM 2 multiplies. */
1062 {"mul", 0xe0000090, 3, ARM_EXT_V2
, do_mul
},
1063 {"muls", 0xe0100090, 3, ARM_EXT_V2
, do_mul
},
1064 {"mla", 0xe0200090, 3, ARM_EXT_V2
, do_mla
},
1065 {"mlas", 0xe0300090, 3, ARM_EXT_V2
, do_mla
},
1067 /* Generic copressor instructions. */
1068 {"cdp", 0xee000000, 3, ARM_EXT_V2
, do_cdp
},
1069 {"ldc", 0xec100000, 3, ARM_EXT_V2
, do_lstc
},
1070 {"ldcl", 0xec500000, 3, ARM_EXT_V2
, do_lstc
},
1071 {"stc", 0xec000000, 3, ARM_EXT_V2
, do_lstc
},
1072 {"stcl", 0xec400000, 3, ARM_EXT_V2
, do_lstc
},
1073 {"mcr", 0xee000010, 3, ARM_EXT_V2
, do_co_reg
},
1074 {"mrc", 0xee100010, 3, ARM_EXT_V2
, do_co_reg
},
1076 /* ARM 3 - swp instructions. */
1077 {"swp", 0xe1000090, 3, ARM_EXT_V2S
, do_swap
},
1078 {"swpb", 0xe1400090, 3, ARM_EXT_V2S
, do_swap
},
1080 /* ARM 6 Status register instructions. */
1081 {"mrs", 0xe10f0000, 3, ARM_EXT_V3
, do_mrs
},
1082 {"msr", 0xe120f000, 3, ARM_EXT_V3
, do_msr
},
1083 /* ScottB: our code uses 0xe128f000 for msr.
1084 NickC: but this is wrong because the bits 16 through 19 are
1085 handled by the PSR_xxx defines above. */
1087 /* ARM 7M long multiplies. */
1088 {"smull", 0xe0c00090, 5, ARM_EXT_V3M
, do_mull
},
1089 {"smulls", 0xe0d00090, 5, ARM_EXT_V3M
, do_mull
},
1090 {"umull", 0xe0800090, 5, ARM_EXT_V3M
, do_mull
},
1091 {"umulls", 0xe0900090, 5, ARM_EXT_V3M
, do_mull
},
1092 {"smlal", 0xe0e00090, 5, ARM_EXT_V3M
, do_mull
},
1093 {"smlals", 0xe0f00090, 5, ARM_EXT_V3M
, do_mull
},
1094 {"umlal", 0xe0a00090, 5, ARM_EXT_V3M
, do_mull
},
1095 {"umlals", 0xe0b00090, 5, ARM_EXT_V3M
, do_mull
},
1097 /* ARM Architecture 4. */
1098 {"ldrh", 0xe01000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1099 {"ldrsh", 0xe01000f0, 3, ARM_EXT_V4
, do_ldstv4
},
1100 {"ldrsb", 0xe01000d0, 3, ARM_EXT_V4
, do_ldstv4
},
1101 {"strh", 0xe00000b0, 3, ARM_EXT_V4
, do_ldstv4
},
1103 /* ARM Architecture 4T. */
1104 /* Note: bx (and blx) are required on V5, even if the processor does
1105 not support Thumb. */
1106 {"bx", 0xe12fff10, 2, ARM_EXT_V4T
| ARM_EXT_V5
, do_bx
},
1108 /* ARM Architecture 5. */
1109 /* Note: blx has 2 variants, so the .value is set dynamically.
1110 Only one of the variants has conditional execution. */
1111 {"blx", 0xe0000000, 3, ARM_EXT_V5
, do_blx
},
1112 {"clz", 0xe16f0f10, 3, ARM_EXT_V5
, do_clz
},
1113 {"bkpt", 0xe1200070, 0, ARM_EXT_V5
, do_bkpt
},
1114 {"ldc2", 0xfc100000, 0, ARM_EXT_V5
, do_lstc2
},
1115 {"ldc2l", 0xfc500000, 0, ARM_EXT_V5
, do_lstc2
},
1116 {"stc2", 0xfc000000, 0, ARM_EXT_V5
, do_lstc2
},
1117 {"stc2l", 0xfc400000, 0, ARM_EXT_V5
, do_lstc2
},
1118 {"cdp2", 0xfe000000, 0, ARM_EXT_V5
, do_cdp2
},
1119 {"mcr2", 0xfe000010, 0, ARM_EXT_V5
, do_co_reg2
},
1120 {"mrc2", 0xfe100010, 0, ARM_EXT_V5
, do_co_reg2
},
1122 /* ARM Architecture 5ExP. */
1123 {"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP
, do_smla
},
1124 {"smlatb", 0xe10000a0, 6, ARM_EXT_V5ExP
, do_smla
},
1125 {"smlabt", 0xe10000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1126 {"smlatt", 0xe10000e0, 6, ARM_EXT_V5ExP
, do_smla
},
1128 {"smlawb", 0xe1200080, 6, ARM_EXT_V5ExP
, do_smla
},
1129 {"smlawt", 0xe12000c0, 6, ARM_EXT_V5ExP
, do_smla
},
1131 {"smlalbb", 0xe1400080, 7, ARM_EXT_V5ExP
, do_smlal
},
1132 {"smlaltb", 0xe14000a0, 7, ARM_EXT_V5ExP
, do_smlal
},
1133 {"smlalbt", 0xe14000c0, 7, ARM_EXT_V5ExP
, do_smlal
},
1134 {"smlaltt", 0xe14000e0, 7, ARM_EXT_V5ExP
, do_smlal
},
1136 {"smulbb", 0xe1600080, 6, ARM_EXT_V5ExP
, do_smul
},
1137 {"smultb", 0xe16000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1138 {"smulbt", 0xe16000c0, 6, ARM_EXT_V5ExP
, do_smul
},
1139 {"smultt", 0xe16000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1141 {"smulwb", 0xe12000a0, 6, ARM_EXT_V5ExP
, do_smul
},
1142 {"smulwt", 0xe12000e0, 6, ARM_EXT_V5ExP
, do_smul
},
1144 {"qadd", 0xe1000050, 4, ARM_EXT_V5ExP
, do_qadd
},
1145 {"qdadd", 0xe1400050, 5, ARM_EXT_V5ExP
, do_qadd
},
1146 {"qsub", 0xe1200050, 4, ARM_EXT_V5ExP
, do_qadd
},
1147 {"qdsub", 0xe1600050, 5, ARM_EXT_V5ExP
, do_qadd
},
1149 /* ARM Architecture 5E. */
1150 {"pld", 0xf450f000, 0, ARM_EXT_V5E
, do_pld
},
1151 {"ldrd", 0xe00000d0, 3, ARM_EXT_V5E
, do_ldrd
},
1152 {"strd", 0xe00000f0, 3, ARM_EXT_V5E
, do_ldrd
},
1154 {"mcrr", 0xec400000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1155 {"mrrc", 0xec500000, 4, ARM_EXT_V5E
, do_co_reg2c
},
1157 /* Core FPA instruction set (V1). */
1158 {"wfs", 0xee200110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1159 {"rfs", 0xee300110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1160 {"wfc", 0xee400110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1161 {"rfc", 0xee500110, 3, FPU_FPA_EXT_V1
, do_fpa_ctrl
},
1163 {"ldfs", 0xec100100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1164 {"ldfd", 0xec108100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1165 {"ldfe", 0xec500100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1166 {"ldfp", 0xec508100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1168 {"stfs", 0xec000100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1169 {"stfd", 0xec008100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1170 {"stfe", 0xec400100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1171 {"stfp", 0xec408100, 3, FPU_FPA_EXT_V1
, do_fpa_ldst
},
1173 {"mvfs", 0xee008100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1174 {"mvfsp", 0xee008120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1175 {"mvfsm", 0xee008140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1176 {"mvfsz", 0xee008160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1177 {"mvfd", 0xee008180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1178 {"mvfdp", 0xee0081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1179 {"mvfdm", 0xee0081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1180 {"mvfdz", 0xee0081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1181 {"mvfe", 0xee088100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1182 {"mvfep", 0xee088120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1183 {"mvfem", 0xee088140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1184 {"mvfez", 0xee088160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1186 {"mnfs", 0xee108100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1187 {"mnfsp", 0xee108120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1188 {"mnfsm", 0xee108140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1189 {"mnfsz", 0xee108160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1190 {"mnfd", 0xee108180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1191 {"mnfdp", 0xee1081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1192 {"mnfdm", 0xee1081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1193 {"mnfdz", 0xee1081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1194 {"mnfe", 0xee188100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1195 {"mnfep", 0xee188120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1196 {"mnfem", 0xee188140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1197 {"mnfez", 0xee188160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1199 {"abss", 0xee208100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1200 {"abssp", 0xee208120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1201 {"abssm", 0xee208140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1202 {"abssz", 0xee208160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1203 {"absd", 0xee208180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1204 {"absdp", 0xee2081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1205 {"absdm", 0xee2081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1206 {"absdz", 0xee2081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1207 {"abse", 0xee288100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1208 {"absep", 0xee288120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1209 {"absem", 0xee288140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1210 {"absez", 0xee288160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1212 {"rnds", 0xee308100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1213 {"rndsp", 0xee308120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1214 {"rndsm", 0xee308140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1215 {"rndsz", 0xee308160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1216 {"rndd", 0xee308180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1217 {"rnddp", 0xee3081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1218 {"rnddm", 0xee3081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1219 {"rnddz", 0xee3081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1220 {"rnde", 0xee388100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1221 {"rndep", 0xee388120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1222 {"rndem", 0xee388140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1223 {"rndez", 0xee388160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1225 {"sqts", 0xee408100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1226 {"sqtsp", 0xee408120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1227 {"sqtsm", 0xee408140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1228 {"sqtsz", 0xee408160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1229 {"sqtd", 0xee408180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1230 {"sqtdp", 0xee4081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1231 {"sqtdm", 0xee4081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1232 {"sqtdz", 0xee4081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1233 {"sqte", 0xee488100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1234 {"sqtep", 0xee488120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1235 {"sqtem", 0xee488140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1236 {"sqtez", 0xee488160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1238 {"logs", 0xee508100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1239 {"logsp", 0xee508120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1240 {"logsm", 0xee508140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1241 {"logsz", 0xee508160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1242 {"logd", 0xee508180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1243 {"logdp", 0xee5081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1244 {"logdm", 0xee5081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1245 {"logdz", 0xee5081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1246 {"loge", 0xee588100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1247 {"logep", 0xee588120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1248 {"logem", 0xee588140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1249 {"logez", 0xee588160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1251 {"lgns", 0xee608100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1252 {"lgnsp", 0xee608120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1253 {"lgnsm", 0xee608140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1254 {"lgnsz", 0xee608160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1255 {"lgnd", 0xee608180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1256 {"lgndp", 0xee6081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1257 {"lgndm", 0xee6081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1258 {"lgndz", 0xee6081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1259 {"lgne", 0xee688100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1260 {"lgnep", 0xee688120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1261 {"lgnem", 0xee688140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1262 {"lgnez", 0xee688160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1264 {"exps", 0xee708100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1265 {"expsp", 0xee708120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1266 {"expsm", 0xee708140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1267 {"expsz", 0xee708160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1268 {"expd", 0xee708180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1269 {"expdp", 0xee7081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1270 {"expdm", 0xee7081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1271 {"expdz", 0xee7081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1272 {"expe", 0xee788100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1273 {"expep", 0xee788120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1274 {"expem", 0xee788140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1275 {"expdz", 0xee788160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1277 {"sins", 0xee808100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1278 {"sinsp", 0xee808120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1279 {"sinsm", 0xee808140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1280 {"sinsz", 0xee808160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1281 {"sind", 0xee808180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1282 {"sindp", 0xee8081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1283 {"sindm", 0xee8081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1284 {"sindz", 0xee8081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1285 {"sine", 0xee888100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1286 {"sinep", 0xee888120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1287 {"sinem", 0xee888140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1288 {"sinez", 0xee888160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1290 {"coss", 0xee908100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1291 {"cossp", 0xee908120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1292 {"cossm", 0xee908140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1293 {"cossz", 0xee908160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1294 {"cosd", 0xee908180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1295 {"cosdp", 0xee9081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1296 {"cosdm", 0xee9081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1297 {"cosdz", 0xee9081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1298 {"cose", 0xee988100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1299 {"cosep", 0xee988120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1300 {"cosem", 0xee988140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1301 {"cosez", 0xee988160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1303 {"tans", 0xeea08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1304 {"tansp", 0xeea08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1305 {"tansm", 0xeea08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1306 {"tansz", 0xeea08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1307 {"tand", 0xeea08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1308 {"tandp", 0xeea081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1309 {"tandm", 0xeea081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1310 {"tandz", 0xeea081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1311 {"tane", 0xeea88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1312 {"tanep", 0xeea88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1313 {"tanem", 0xeea88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1314 {"tanez", 0xeea88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1316 {"asns", 0xeeb08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1317 {"asnsp", 0xeeb08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1318 {"asnsm", 0xeeb08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1319 {"asnsz", 0xeeb08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1320 {"asnd", 0xeeb08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1321 {"asndp", 0xeeb081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1322 {"asndm", 0xeeb081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1323 {"asndz", 0xeeb081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1324 {"asne", 0xeeb88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1325 {"asnep", 0xeeb88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1326 {"asnem", 0xeeb88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1327 {"asnez", 0xeeb88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1329 {"acss", 0xeec08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1330 {"acssp", 0xeec08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1331 {"acssm", 0xeec08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1332 {"acssz", 0xeec08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1333 {"acsd", 0xeec08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1334 {"acsdp", 0xeec081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1335 {"acsdm", 0xeec081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1336 {"acsdz", 0xeec081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1337 {"acse", 0xeec88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1338 {"acsep", 0xeec88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1339 {"acsem", 0xeec88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1340 {"acsez", 0xeec88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1342 {"atns", 0xeed08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1343 {"atnsp", 0xeed08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1344 {"atnsm", 0xeed08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1345 {"atnsz", 0xeed08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1346 {"atnd", 0xeed08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1347 {"atndp", 0xeed081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1348 {"atndm", 0xeed081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1349 {"atndz", 0xeed081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1350 {"atne", 0xeed88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1351 {"atnep", 0xeed88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1352 {"atnem", 0xeed88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1353 {"atnez", 0xeed88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1355 {"urds", 0xeee08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1356 {"urdsp", 0xeee08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1357 {"urdsm", 0xeee08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1358 {"urdsz", 0xeee08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1359 {"urdd", 0xeee08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1360 {"urddp", 0xeee081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1361 {"urddm", 0xeee081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1362 {"urddz", 0xeee081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1363 {"urde", 0xeee88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1364 {"urdep", 0xeee88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1365 {"urdem", 0xeee88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1366 {"urdez", 0xeee88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1368 {"nrms", 0xeef08100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1369 {"nrmsp", 0xeef08120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1370 {"nrmsm", 0xeef08140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1371 {"nrmsz", 0xeef08160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1372 {"nrmd", 0xeef08180, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1373 {"nrmdp", 0xeef081a0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1374 {"nrmdm", 0xeef081c0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1375 {"nrmdz", 0xeef081e0, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1376 {"nrme", 0xeef88100, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1377 {"nrmep", 0xeef88120, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1378 {"nrmem", 0xeef88140, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1379 {"nrmez", 0xeef88160, 3, FPU_FPA_EXT_V1
, do_fpa_monadic
},
1381 {"adfs", 0xee000100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1382 {"adfsp", 0xee000120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1383 {"adfsm", 0xee000140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1384 {"adfsz", 0xee000160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1385 {"adfd", 0xee000180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1386 {"adfdp", 0xee0001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1387 {"adfdm", 0xee0001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1388 {"adfdz", 0xee0001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1389 {"adfe", 0xee080100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1390 {"adfep", 0xee080120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1391 {"adfem", 0xee080140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1392 {"adfez", 0xee080160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1394 {"sufs", 0xee200100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1395 {"sufsp", 0xee200120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1396 {"sufsm", 0xee200140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1397 {"sufsz", 0xee200160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1398 {"sufd", 0xee200180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1399 {"sufdp", 0xee2001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1400 {"sufdm", 0xee2001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1401 {"sufdz", 0xee2001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1402 {"sufe", 0xee280100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1403 {"sufep", 0xee280120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1404 {"sufem", 0xee280140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1405 {"sufez", 0xee280160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1407 {"rsfs", 0xee300100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1408 {"rsfsp", 0xee300120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1409 {"rsfsm", 0xee300140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1410 {"rsfsz", 0xee300160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1411 {"rsfd", 0xee300180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1412 {"rsfdp", 0xee3001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1413 {"rsfdm", 0xee3001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1414 {"rsfdz", 0xee3001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1415 {"rsfe", 0xee380100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1416 {"rsfep", 0xee380120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1417 {"rsfem", 0xee380140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1418 {"rsfez", 0xee380160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1420 {"mufs", 0xee100100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1421 {"mufsp", 0xee100120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1422 {"mufsm", 0xee100140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1423 {"mufsz", 0xee100160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1424 {"mufd", 0xee100180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1425 {"mufdp", 0xee1001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1426 {"mufdm", 0xee1001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1427 {"mufdz", 0xee1001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1428 {"mufe", 0xee180100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1429 {"mufep", 0xee180120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1430 {"mufem", 0xee180140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1431 {"mufez", 0xee180160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1433 {"dvfs", 0xee400100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1434 {"dvfsp", 0xee400120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1435 {"dvfsm", 0xee400140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1436 {"dvfsz", 0xee400160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1437 {"dvfd", 0xee400180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1438 {"dvfdp", 0xee4001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1439 {"dvfdm", 0xee4001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1440 {"dvfdz", 0xee4001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1441 {"dvfe", 0xee480100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1442 {"dvfep", 0xee480120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1443 {"dvfem", 0xee480140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1444 {"dvfez", 0xee480160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1446 {"rdfs", 0xee500100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1447 {"rdfsp", 0xee500120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1448 {"rdfsm", 0xee500140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1449 {"rdfsz", 0xee500160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1450 {"rdfd", 0xee500180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1451 {"rdfdp", 0xee5001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1452 {"rdfdm", 0xee5001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1453 {"rdfdz", 0xee5001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1454 {"rdfe", 0xee580100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1455 {"rdfep", 0xee580120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1456 {"rdfem", 0xee580140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1457 {"rdfez", 0xee580160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1459 {"pows", 0xee600100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1460 {"powsp", 0xee600120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1461 {"powsm", 0xee600140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1462 {"powsz", 0xee600160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1463 {"powd", 0xee600180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1464 {"powdp", 0xee6001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1465 {"powdm", 0xee6001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1466 {"powdz", 0xee6001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1467 {"powe", 0xee680100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1468 {"powep", 0xee680120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1469 {"powem", 0xee680140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1470 {"powez", 0xee680160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1472 {"rpws", 0xee700100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1473 {"rpwsp", 0xee700120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1474 {"rpwsm", 0xee700140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1475 {"rpwsz", 0xee700160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1476 {"rpwd", 0xee700180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1477 {"rpwdp", 0xee7001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1478 {"rpwdm", 0xee7001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1479 {"rpwdz", 0xee7001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1480 {"rpwe", 0xee780100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1481 {"rpwep", 0xee780120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1482 {"rpwem", 0xee780140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1483 {"rpwez", 0xee780160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1485 {"rmfs", 0xee800100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1486 {"rmfsp", 0xee800120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1487 {"rmfsm", 0xee800140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1488 {"rmfsz", 0xee800160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1489 {"rmfd", 0xee800180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1490 {"rmfdp", 0xee8001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1491 {"rmfdm", 0xee8001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1492 {"rmfdz", 0xee8001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1493 {"rmfe", 0xee880100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1494 {"rmfep", 0xee880120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1495 {"rmfem", 0xee880140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1496 {"rmfez", 0xee880160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1498 {"fmls", 0xee900100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1499 {"fmlsp", 0xee900120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1500 {"fmlsm", 0xee900140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1501 {"fmlsz", 0xee900160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1502 {"fmld", 0xee900180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1503 {"fmldp", 0xee9001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1504 {"fmldm", 0xee9001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1505 {"fmldz", 0xee9001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1506 {"fmle", 0xee980100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1507 {"fmlep", 0xee980120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1508 {"fmlem", 0xee980140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1509 {"fmlez", 0xee980160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1511 {"fdvs", 0xeea00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1512 {"fdvsp", 0xeea00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1513 {"fdvsm", 0xeea00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1514 {"fdvsz", 0xeea00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1515 {"fdvd", 0xeea00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1516 {"fdvdp", 0xeea001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1517 {"fdvdm", 0xeea001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1518 {"fdvdz", 0xeea001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1519 {"fdve", 0xeea80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1520 {"fdvep", 0xeea80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1521 {"fdvem", 0xeea80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1522 {"fdvez", 0xeea80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1524 {"frds", 0xeeb00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1525 {"frdsp", 0xeeb00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1526 {"frdsm", 0xeeb00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1527 {"frdsz", 0xeeb00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1528 {"frdd", 0xeeb00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1529 {"frddp", 0xeeb001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1530 {"frddm", 0xeeb001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1531 {"frddz", 0xeeb001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1532 {"frde", 0xeeb80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1533 {"frdep", 0xeeb80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1534 {"frdem", 0xeeb80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1535 {"frdez", 0xeeb80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1537 {"pols", 0xeec00100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1538 {"polsp", 0xeec00120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1539 {"polsm", 0xeec00140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1540 {"polsz", 0xeec00160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1541 {"pold", 0xeec00180, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1542 {"poldp", 0xeec001a0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1543 {"poldm", 0xeec001c0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1544 {"poldz", 0xeec001e0, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1545 {"pole", 0xeec80100, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1546 {"polep", 0xeec80120, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1547 {"polem", 0xeec80140, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1548 {"polez", 0xeec80160, 3, FPU_FPA_EXT_V1
, do_fpa_dyadic
},
1550 {"cmf", 0xee90f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1551 {"cmfe", 0xeed0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1552 {"cnf", 0xeeb0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1553 {"cnfe", 0xeef0f110, 3, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1554 /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1555 not be an optional suffix, but part of the instruction. To be
1556 compatible, we accept either. */
1557 {"cmfe", 0xeed0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1558 {"cnfe", 0xeef0f110, 4, FPU_FPA_EXT_V1
, do_fpa_cmp
},
1560 {"flts", 0xee000110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1561 {"fltsp", 0xee000130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1562 {"fltsm", 0xee000150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1563 {"fltsz", 0xee000170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1564 {"fltd", 0xee000190, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1565 {"fltdp", 0xee0001b0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1566 {"fltdm", 0xee0001d0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1567 {"fltdz", 0xee0001f0, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1568 {"flte", 0xee080110, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1569 {"fltep", 0xee080130, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1570 {"fltem", 0xee080150, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1571 {"fltez", 0xee080170, 3, FPU_FPA_EXT_V1
, do_fpa_from_reg
},
1573 /* The implementation of the FIX instruction is broken on some
1574 assemblers, in that it accepts a precision specifier as well as a
1575 rounding specifier, despite the fact that this is meaningless.
1576 To be more compatible, we accept it as well, though of course it
1577 does not set any bits. */
1578 {"fix", 0xee100110, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1579 {"fixp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1580 {"fixm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1581 {"fixz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1582 {"fixsp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1583 {"fixsm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1584 {"fixsz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1585 {"fixdp", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1586 {"fixdm", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1587 {"fixdz", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1588 {"fixep", 0xee100130, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1589 {"fixem", 0xee100150, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1590 {"fixez", 0xee100170, 3, FPU_FPA_EXT_V1
, do_fpa_to_reg
},
1592 /* Instructions that were new with the real FPA, call them V2. */
1593 {"lfm", 0xec100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1594 {"lfmfd", 0xec900200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1595 {"lfmea", 0xed100200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1596 {"sfm", 0xec000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1597 {"sfmfd", 0xed000200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1598 {"sfmea", 0xec800200, 3, FPU_FPA_EXT_V2
, do_fpa_ldmstm
},
1600 /* VFP V1xD (single precision). */
1601 /* Moves and type conversions. */
1602 {"fcpys", 0xeeb00a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1603 {"fmrs", 0xee100a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_sp
},
1604 {"fmsr", 0xee000a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_from_reg
},
1605 {"fmstat", 0xeef1fa10, 6, FPU_VFP_EXT_V1xD
, do_empty
},
1606 {"fsitos", 0xeeb80ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1607 {"fuitos", 0xeeb80a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1608 {"ftosis", 0xeebd0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1609 {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1610 {"ftouis", 0xeebc0a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1611 {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1612 {"fmrx", 0xeef00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_reg_from_ctrl
},
1613 {"fmxr", 0xeee00a10, 4, FPU_VFP_EXT_V1xD
, do_vfp_ctrl_from_reg
},
1615 /* Memory operations. */
1616 {"flds", 0xed100a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1617 {"fsts", 0xed000a00, 4, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldst
},
1618 {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1619 {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1620 {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1621 {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1622 {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1623 {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1624 {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1625 {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1626 {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1627 {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmia
},
1628 {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1629 {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_ldstmdb
},
1630 {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1631 {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmia
},
1632 {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1633 {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD
, do_vfp_xp_ldstmdb
},
1635 /* Monadic operations. */
1636 {"fabss", 0xeeb00ac0, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1637 {"fnegs", 0xeeb10a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1638 {"fsqrts", 0xeeb10ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1640 /* Dyadic operations. */
1641 {"fadds", 0xee300a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1642 {"fsubs", 0xee300a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1643 {"fmuls", 0xee200a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1644 {"fdivs", 0xee800a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1645 {"fmacs", 0xee000a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1646 {"fmscs", 0xee100a00, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1647 {"fnmuls", 0xee200a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1648 {"fnmacs", 0xee000a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1649 {"fnmscs", 0xee100a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_dyadic
},
1652 {"fcmps", 0xeeb40a40, 5, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1653 {"fcmpzs", 0xeeb50a40, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1654 {"fcmpes", 0xeeb40ac0, 6, FPU_VFP_EXT_V1xD
, do_vfp_sp_monadic
},
1655 {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD
, do_vfp_sp_compare_z
},
1657 /* VFP V1 (Double precision). */
1658 /* Moves and type conversions. */
1659 {"fcpyd", 0xeeb00b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1660 {"fcvtds", 0xeeb70ac0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1661 {"fcvtsd", 0xeeb70bc0, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1662 {"fmdhr", 0xee200b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1663 {"fmdlr", 0xee000b10, 5, FPU_VFP_EXT_V1
, do_vfp_dp_from_reg
},
1664 {"fmrdh", 0xee300b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1665 {"fmrdl", 0xee100b10, 5, FPU_VFP_EXT_V1
, do_vfp_reg_from_dp
},
1666 {"fsitod", 0xeeb80bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1667 {"fuitod", 0xeeb80b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_sp_cvt
},
1668 {"ftosid", 0xeebd0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1669 {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1670 {"ftouid", 0xeebc0b40, 6, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1671 {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1
, do_vfp_sp_dp_cvt
},
1673 /* Memory operations. */
1674 {"fldd", 0xed100b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1675 {"fstd", 0xed000b00, 4, FPU_VFP_EXT_V1
, do_vfp_dp_ldst
},
1676 {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1677 {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1678 {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1679 {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1680 {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1681 {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmia
},
1682 {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1683 {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1
, do_vfp_dp_ldstmdb
},
1685 /* Monadic operations. */
1686 {"fabsd", 0xeeb00bc0, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1687 {"fnegd", 0xeeb10b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1688 {"fsqrtd", 0xeeb10bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1690 /* Dyadic operations. */
1691 {"faddd", 0xee300b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1692 {"fsubd", 0xee300b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1693 {"fmuld", 0xee200b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1694 {"fdivd", 0xee800b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1695 {"fmacd", 0xee000b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1696 {"fmscd", 0xee100b00, 5, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1697 {"fnmuld", 0xee200b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1698 {"fnmacd", 0xee000b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1699 {"fnmscd", 0xee100b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_dyadic
},
1702 {"fcmpd", 0xeeb40b40, 5, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1703 {"fcmpzd", 0xeeb50b40, 6, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1704 {"fcmped", 0xeeb40bc0, 6, FPU_VFP_EXT_V1
, do_vfp_dp_monadic
},
1705 {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1
, do_vfp_dp_compare_z
},
1708 {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1709 {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2
, do_vfp_sp_reg2
},
1710 {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2
, do_vfp_dp_from_reg2
},
1711 {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2
, do_vfp_reg2_from_dp
},
1713 /* Intel XScale extensions to ARM V5 ISA. (All use CP0). */
1714 {"mia", 0xee200010, 3, ARM_CEXT_XSCALE
, do_mia
},
1715 {"miaph", 0xee280010, 5, ARM_CEXT_XSCALE
, do_mia
},
1716 {"miabb", 0xee2c0010, 5, ARM_CEXT_XSCALE
, do_mia
},
1717 {"miabt", 0xee2d0010, 5, ARM_CEXT_XSCALE
, do_mia
},
1718 {"miatb", 0xee2e0010, 5, ARM_CEXT_XSCALE
, do_mia
},
1719 {"miatt", 0xee2f0010, 5, ARM_CEXT_XSCALE
, do_mia
},
1720 {"mar", 0xec400000, 3, ARM_CEXT_XSCALE
, do_mar
},
1721 {"mra", 0xec500000, 3, ARM_CEXT_XSCALE
, do_mra
},
1723 /* Cirrus DSP instructions. */
1724 {"cfldrs", 0xec100400, 6, ARM_CEXT_MAVERICK
, do_c_ldst_1
},
1725 {"cfldrd", 0xec500400, 6, ARM_CEXT_MAVERICK
, do_c_ldst_2
},
1726 {"cfldr32", 0xec100500, 7, ARM_CEXT_MAVERICK
, do_c_ldst_3
},
1727 {"cfldr64", 0xec500500, 7, ARM_CEXT_MAVERICK
, do_c_ldst_4
},
1728 {"cfstrs", 0xec000400, 6, ARM_CEXT_MAVERICK
, do_c_ldst_1
},
1729 {"cfstrd", 0xec400400, 6, ARM_CEXT_MAVERICK
, do_c_ldst_2
},
1730 {"cfstr32", 0xec000500, 7, ARM_CEXT_MAVERICK
, do_c_ldst_3
},
1731 {"cfstr64", 0xec400500, 7, ARM_CEXT_MAVERICK
, do_c_ldst_4
},
1732 {"cfmvsr", 0xee000450, 6, ARM_CEXT_MAVERICK
, do_c_binops_2a
},
1733 {"cfmvrs", 0xee100450, 6, ARM_CEXT_MAVERICK
, do_c_binops_1a
},
1734 {"cfmvdlr", 0xee000410, 7, ARM_CEXT_MAVERICK
, do_c_binops_2b
},
1735 {"cfmvrdl", 0xee100410, 7, ARM_CEXT_MAVERICK
, do_c_binops_1b
},
1736 {"cfmvdhr", 0xee000430, 7, ARM_CEXT_MAVERICK
, do_c_binops_2b
},
1737 {"cfmvrdh", 0xee100430, 7, ARM_CEXT_MAVERICK
, do_c_binops_1b
},
1738 {"cfmv64lr", 0xee000510, 8, ARM_CEXT_MAVERICK
, do_c_binops_2c
},
1739 {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK
, do_c_binops_1c
},
1740 {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK
, do_c_binops_2c
},
1741 {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK
, do_c_binops_1c
},
1742 {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK
, do_c_binops_3a
},
1743 {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK
, do_c_binops_3b
},
1744 {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK
, do_c_binops_3a
},
1745 {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK
, do_c_binops_3b
},
1746 {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK
, do_c_binops_3a
},
1747 {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK
, do_c_binops_3b
},
1748 {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK
, do_c_binops_3a
},
1749 {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK
, do_c_binops_3b
},
1750 {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK
, do_c_binops_3c
},
1751 {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK
, do_c_binops_3d
},
1752 {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK
, do_c_dspsc_1
},
1753 {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK
, do_c_dspsc_2
},
1754 {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK
, do_c_binops_1d
},
1755 {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK
, do_c_binops_1e
},
1756 {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK
, do_c_binops_1f
},
1757 {"cfcvtds", 0xee000440, 7, ARM_CEXT_MAVERICK
, do_c_binops_1g
},
1758 {"cfcvt32s", 0xee000480, 8, ARM_CEXT_MAVERICK
, do_c_binops_1h
},
1759 {"cfcvt32d", 0xee0004a0, 8, ARM_CEXT_MAVERICK
, do_c_binops_1i
},
1760 {"cfcvt64s", 0xee0004c0, 8, ARM_CEXT_MAVERICK
, do_c_binops_1j
},
1761 {"cfcvt64d", 0xee0004e0, 8, ARM_CEXT_MAVERICK
, do_c_binops_1k
},
1762 {"cfcvts32", 0xee100580, 8, ARM_CEXT_MAVERICK
, do_c_binops_1l
},
1763 {"cfcvtd32", 0xee1005a0, 8, ARM_CEXT_MAVERICK
, do_c_binops_1m
},
1764 {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK
, do_c_binops_1l
},
1765 {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK
, do_c_binops_1m
},
1766 {"cfrshl32", 0xee000550, 8, ARM_CEXT_MAVERICK
, do_c_triple_4a
},
1767 {"cfrshl64", 0xee000570, 8, ARM_CEXT_MAVERICK
, do_c_triple_4b
},
1768 {"cfsh32", 0xee000500, 6, ARM_CEXT_MAVERICK
, do_c_shift_1
},
1769 {"cfsh64", 0xee200500, 6, ARM_CEXT_MAVERICK
, do_c_shift_2
},
1770 {"cfcmps", 0xee100490, 6, ARM_CEXT_MAVERICK
, do_c_triple_5a
},
1771 {"cfcmpd", 0xee1004b0, 6, ARM_CEXT_MAVERICK
, do_c_triple_5b
},
1772 {"cfcmp32", 0xee100590, 7, ARM_CEXT_MAVERICK
, do_c_triple_5c
},
1773 {"cfcmp64", 0xee1005b0, 7, ARM_CEXT_MAVERICK
, do_c_triple_5d
},
1774 {"cfabss", 0xee300400, 6, ARM_CEXT_MAVERICK
, do_c_binops_1d
},
1775 {"cfabsd", 0xee300420, 6, ARM_CEXT_MAVERICK
, do_c_binops_1e
},
1776 {"cfnegs", 0xee300440, 6, ARM_CEXT_MAVERICK
, do_c_binops_1d
},
1777 {"cfnegd", 0xee300460, 6, ARM_CEXT_MAVERICK
, do_c_binops_1e
},
1778 {"cfadds", 0xee300480, 6, ARM_CEXT_MAVERICK
, do_c_triple_5e
},
1779 {"cfaddd", 0xee3004a0, 6, ARM_CEXT_MAVERICK
, do_c_triple_5f
},
1780 {"cfsubs", 0xee3004c0, 6, ARM_CEXT_MAVERICK
, do_c_triple_5e
},
1781 {"cfsubd", 0xee3004e0, 6, ARM_CEXT_MAVERICK
, do_c_triple_5f
},
1782 {"cfmuls", 0xee100400, 6, ARM_CEXT_MAVERICK
, do_c_triple_5e
},
1783 {"cfmuld", 0xee100420, 6, ARM_CEXT_MAVERICK
, do_c_triple_5f
},
1784 {"cfabs32", 0xee300500, 7, ARM_CEXT_MAVERICK
, do_c_binops_1n
},
1785 {"cfabs64", 0xee300520, 7, ARM_CEXT_MAVERICK
, do_c_binops_1o
},
1786 {"cfneg32", 0xee300540, 7, ARM_CEXT_MAVERICK
, do_c_binops_1n
},
1787 {"cfneg64", 0xee300560, 7, ARM_CEXT_MAVERICK
, do_c_binops_1o
},
1788 {"cfadd32", 0xee300580, 7, ARM_CEXT_MAVERICK
, do_c_triple_5g
},
1789 {"cfadd64", 0xee3005a0, 7, ARM_CEXT_MAVERICK
, do_c_triple_5h
},
1790 {"cfsub32", 0xee3005c0, 7, ARM_CEXT_MAVERICK
, do_c_triple_5g
},
1791 {"cfsub64", 0xee3005e0, 7, ARM_CEXT_MAVERICK
, do_c_triple_5h
},
1792 {"cfmul32", 0xee100500, 7, ARM_CEXT_MAVERICK
, do_c_triple_5g
},
1793 {"cfmul64", 0xee100520, 7, ARM_CEXT_MAVERICK
, do_c_triple_5h
},
1794 {"cfmac32", 0xee100540, 7, ARM_CEXT_MAVERICK
, do_c_triple_5g
},
1795 {"cfmsc32", 0xee100560, 7, ARM_CEXT_MAVERICK
, do_c_triple_5g
},
1796 {"cfmadd32", 0xee000600, 8, ARM_CEXT_MAVERICK
, do_c_quad_6a
},
1797 {"cfmsub32", 0xee100600, 8, ARM_CEXT_MAVERICK
, do_c_quad_6a
},
1798 {"cfmadda32", 0xee200600, 9, ARM_CEXT_MAVERICK
, do_c_quad_6b
},
1799 {"cfmsuba32", 0xee300600, 9, ARM_CEXT_MAVERICK
, do_c_quad_6b
},
1802 /* Defines for various bits that we will want to toggle. */
1803 #define INST_IMMEDIATE 0x02000000
1804 #define OFFSET_REG 0x02000000
1805 #define HWOFFSET_IMM 0x00400000
1806 #define SHIFT_BY_REG 0x00000010
1807 #define PRE_INDEX 0x01000000
1808 #define INDEX_UP 0x00800000
1809 #define WRITE_BACK 0x00200000
1810 #define LDM_TYPE_2_OR_3 0x00400000
1812 #define LITERAL_MASK 0xf000f000
1813 #define OPCODE_MASK 0xfe1fffff
1814 #define V4_STR_BIT 0x00000020
1816 #define DATA_OP_SHIFT 21
1818 /* Codes to distinguish the arithmetic instructions. */
1819 #define OPCODE_AND 0
1820 #define OPCODE_EOR 1
1821 #define OPCODE_SUB 2
1822 #define OPCODE_RSB 3
1823 #define OPCODE_ADD 4
1824 #define OPCODE_ADC 5
1825 #define OPCODE_SBC 6
1826 #define OPCODE_RSC 7
1827 #define OPCODE_TST 8
1828 #define OPCODE_TEQ 9
1829 #define OPCODE_CMP 10
1830 #define OPCODE_CMN 11
1831 #define OPCODE_ORR 12
1832 #define OPCODE_MOV 13
1833 #define OPCODE_BIC 14
1834 #define OPCODE_MVN 15
1836 /* Thumb v1 (ARMv4T). */
1837 static void do_t_nop
PARAMS ((char *));
1838 static void do_t_arit
PARAMS ((char *));
1839 static void do_t_add
PARAMS ((char *));
1840 static void do_t_asr
PARAMS ((char *));
1841 static void do_t_branch9
PARAMS ((char *));
1842 static void do_t_branch12
PARAMS ((char *));
1843 static void do_t_branch23
PARAMS ((char *));
1844 static void do_t_bx
PARAMS ((char *));
1845 static void do_t_compare
PARAMS ((char *));
1846 static void do_t_ldmstm
PARAMS ((char *));
1847 static void do_t_ldr
PARAMS ((char *));
1848 static void do_t_ldrb
PARAMS ((char *));
1849 static void do_t_ldrh
PARAMS ((char *));
1850 static void do_t_lds
PARAMS ((char *));
1851 static void do_t_lsl
PARAMS ((char *));
1852 static void do_t_lsr
PARAMS ((char *));
1853 static void do_t_mov
PARAMS ((char *));
1854 static void do_t_push_pop
PARAMS ((char *));
1855 static void do_t_str
PARAMS ((char *));
1856 static void do_t_strb
PARAMS ((char *));
1857 static void do_t_strh
PARAMS ((char *));
1858 static void do_t_sub
PARAMS ((char *));
1859 static void do_t_swi
PARAMS ((char *));
1860 static void do_t_adr
PARAMS ((char *));
1862 /* Thumb v2 (ARMv5T). */
1863 static void do_t_blx
PARAMS ((char *));
1864 static void do_t_bkpt
PARAMS ((char *));
1866 #define T_OPCODE_MUL 0x4340
1867 #define T_OPCODE_TST 0x4200
1868 #define T_OPCODE_CMN 0x42c0
1869 #define T_OPCODE_NEG 0x4240
1870 #define T_OPCODE_MVN 0x43c0
1872 #define T_OPCODE_ADD_R3 0x1800
1873 #define T_OPCODE_SUB_R3 0x1a00
1874 #define T_OPCODE_ADD_HI 0x4400
1875 #define T_OPCODE_ADD_ST 0xb000
1876 #define T_OPCODE_SUB_ST 0xb080
1877 #define T_OPCODE_ADD_SP 0xa800
1878 #define T_OPCODE_ADD_PC 0xa000
1879 #define T_OPCODE_ADD_I8 0x3000
1880 #define T_OPCODE_SUB_I8 0x3800
1881 #define T_OPCODE_ADD_I3 0x1c00
1882 #define T_OPCODE_SUB_I3 0x1e00
1884 #define T_OPCODE_ASR_R 0x4100
1885 #define T_OPCODE_LSL_R 0x4080
1886 #define T_OPCODE_LSR_R 0x40c0
1887 #define T_OPCODE_ASR_I 0x1000
1888 #define T_OPCODE_LSL_I 0x0000
1889 #define T_OPCODE_LSR_I 0x0800
1891 #define T_OPCODE_MOV_I8 0x2000
1892 #define T_OPCODE_CMP_I8 0x2800
1893 #define T_OPCODE_CMP_LR 0x4280
1894 #define T_OPCODE_MOV_HR 0x4600
1895 #define T_OPCODE_CMP_HR 0x4500
1897 #define T_OPCODE_LDR_PC 0x4800
1898 #define T_OPCODE_LDR_SP 0x9800
1899 #define T_OPCODE_STR_SP 0x9000
1900 #define T_OPCODE_LDR_IW 0x6800
1901 #define T_OPCODE_STR_IW 0x6000
1902 #define T_OPCODE_LDR_IH 0x8800
1903 #define T_OPCODE_STR_IH 0x8000
1904 #define T_OPCODE_LDR_IB 0x7800
1905 #define T_OPCODE_STR_IB 0x7000
1906 #define T_OPCODE_LDR_RW 0x5800
1907 #define T_OPCODE_STR_RW 0x5000
1908 #define T_OPCODE_LDR_RH 0x5a00
1909 #define T_OPCODE_STR_RH 0x5200
1910 #define T_OPCODE_LDR_RB 0x5c00
1911 #define T_OPCODE_STR_RB 0x5400
1913 #define T_OPCODE_PUSH 0xb400
1914 #define T_OPCODE_POP 0xbc00
1916 #define T_OPCODE_BRANCH 0xe7fe
1918 static int thumb_reg
PARAMS ((char ** str
, int hi_lo
));
1920 #define THUMB_SIZE 2 /* Size of thumb instruction. */
1921 #define THUMB_REG_LO 0x1
1922 #define THUMB_REG_HI 0x2
1923 #define THUMB_REG_ANY 0x3
1925 #define THUMB_H1 0x0080
1926 #define THUMB_H2 0x0040
1932 #define THUMB_MOVE 0
1933 #define THUMB_COMPARE 1
1935 #define THUMB_LOAD 0
1936 #define THUMB_STORE 1
1938 #define THUMB_PP_PC_LR 0x0100
1940 /* These three are used for immediate shifts, do not alter. */
1941 #define THUMB_WORD 2
1942 #define THUMB_HALFWORD 1
1943 #define THUMB_BYTE 0
1947 /* Basic string to match. */
1948 const char * template;
1950 /* Basic instruction code. */
1951 unsigned long value
;
1955 /* Which CPU variants this exists for. */
1956 unsigned long variant
;
1958 /* Function to call to parse args. */
1959 void (* parms
) PARAMS ((char *));
1962 static const struct thumb_opcode tinsns
[] =
1964 /* Thumb v1 (ARMv4T). */
1965 {"adc", 0x4140, 2, ARM_EXT_V4T
, do_t_arit
},
1966 {"add", 0x0000, 2, ARM_EXT_V4T
, do_t_add
},
1967 {"and", 0x4000, 2, ARM_EXT_V4T
, do_t_arit
},
1968 {"asr", 0x0000, 2, ARM_EXT_V4T
, do_t_asr
},
1969 {"b", T_OPCODE_BRANCH
, 2, ARM_EXT_V4T
, do_t_branch12
},
1970 {"beq", 0xd0fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1971 {"bne", 0xd1fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1972 {"bcs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1973 {"bhs", 0xd2fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1974 {"bcc", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1975 {"bul", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1976 {"blo", 0xd3fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1977 {"bmi", 0xd4fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1978 {"bpl", 0xd5fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1979 {"bvs", 0xd6fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1980 {"bvc", 0xd7fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1981 {"bhi", 0xd8fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1982 {"bls", 0xd9fe, 2, ARM_EXT_V4T
, do_t_branch9
},
1983 {"bge", 0xdafe, 2, ARM_EXT_V4T
, do_t_branch9
},
1984 {"blt", 0xdbfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1985 {"bgt", 0xdcfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1986 {"ble", 0xddfe, 2, ARM_EXT_V4T
, do_t_branch9
},
1987 {"bal", 0xdefe, 2, ARM_EXT_V4T
, do_t_branch9
},
1988 {"bic", 0x4380, 2, ARM_EXT_V4T
, do_t_arit
},
1989 {"bl", 0xf7fffffe, 4, ARM_EXT_V4T
, do_t_branch23
},
1990 {"bx", 0x4700, 2, ARM_EXT_V4T
, do_t_bx
},
1991 {"cmn", T_OPCODE_CMN
, 2, ARM_EXT_V4T
, do_t_arit
},
1992 {"cmp", 0x0000, 2, ARM_EXT_V4T
, do_t_compare
},
1993 {"eor", 0x4040, 2, ARM_EXT_V4T
, do_t_arit
},
1994 {"ldmia", 0xc800, 2, ARM_EXT_V4T
, do_t_ldmstm
},
1995 {"ldr", 0x0000, 2, ARM_EXT_V4T
, do_t_ldr
},
1996 {"ldrb", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrb
},
1997 {"ldrh", 0x0000, 2, ARM_EXT_V4T
, do_t_ldrh
},
1998 {"ldrsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
1999 {"ldrsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2000 {"ldsb", 0x5600, 2, ARM_EXT_V4T
, do_t_lds
},
2001 {"ldsh", 0x5e00, 2, ARM_EXT_V4T
, do_t_lds
},
2002 {"lsl", 0x0000, 2, ARM_EXT_V4T
, do_t_lsl
},
2003 {"lsr", 0x0000, 2, ARM_EXT_V4T
, do_t_lsr
},
2004 {"mov", 0x0000, 2, ARM_EXT_V4T
, do_t_mov
},
2005 {"mul", T_OPCODE_MUL
, 2, ARM_EXT_V4T
, do_t_arit
},
2006 {"mvn", T_OPCODE_MVN
, 2, ARM_EXT_V4T
, do_t_arit
},
2007 {"neg", T_OPCODE_NEG
, 2, ARM_EXT_V4T
, do_t_arit
},
2008 {"orr", 0x4300, 2, ARM_EXT_V4T
, do_t_arit
},
2009 {"pop", 0xbc00, 2, ARM_EXT_V4T
, do_t_push_pop
},
2010 {"push", 0xb400, 2, ARM_EXT_V4T
, do_t_push_pop
},
2011 {"ror", 0x41c0, 2, ARM_EXT_V4T
, do_t_arit
},
2012 {"sbc", 0x4180, 2, ARM_EXT_V4T
, do_t_arit
},
2013 {"stmia", 0xc000, 2, ARM_EXT_V4T
, do_t_ldmstm
},
2014 {"str", 0x0000, 2, ARM_EXT_V4T
, do_t_str
},
2015 {"strb", 0x0000, 2, ARM_EXT_V4T
, do_t_strb
},
2016 {"strh", 0x0000, 2, ARM_EXT_V4T
, do_t_strh
},
2017 {"swi", 0xdf00, 2, ARM_EXT_V4T
, do_t_swi
},
2018 {"sub", 0x0000, 2, ARM_EXT_V4T
, do_t_sub
},
2019 {"tst", T_OPCODE_TST
, 2, ARM_EXT_V4T
, do_t_arit
},
2021 {"adr", 0x0000, 2, ARM_EXT_V4T
, do_t_adr
},
2022 {"nop", 0x46C0, 2, ARM_EXT_V4T
, do_t_nop
}, /* mov r8,r8 */
2023 /* Thumb v2 (ARMv5T). */
2024 {"blx", 0, 0, ARM_EXT_V5T
, do_t_blx
},
2025 {"bkpt", 0xbe00, 2, ARM_EXT_V5T
, do_t_bkpt
},
2028 #define BAD_ARGS _("bad arguments to instruction")
2029 #define BAD_PC _("r15 not allowed here")
2030 #define BAD_COND _("instruction is not conditional")
2031 #define ERR_NO_ACCUM _("acc0 expected")
2033 static struct hash_control
* arm_ops_hsh
= NULL
;
2034 static struct hash_control
* arm_tops_hsh
= NULL
;
2035 static struct hash_control
* arm_cond_hsh
= NULL
;
2036 static struct hash_control
* arm_shift_hsh
= NULL
;
2037 static struct hash_control
* arm_psr_hsh
= NULL
;
2039 /* This table describes all the machine specific pseudo-ops the assembler
2040 has to support. The fields are:
2041 pseudo-op name without dot
2042 function to call to execute this pseudo-op
2043 Integer arg to pass to the function. */
2045 static void s_req
PARAMS ((int));
2046 static void s_align
PARAMS ((int));
2047 static void s_bss
PARAMS ((int));
2048 static void s_even
PARAMS ((int));
2049 static void s_ltorg
PARAMS ((int));
2050 static void s_arm
PARAMS ((int));
2051 static void s_thumb
PARAMS ((int));
2052 static void s_code
PARAMS ((int));
2053 static void s_force_thumb
PARAMS ((int));
2054 static void s_thumb_func
PARAMS ((int));
2055 static void s_thumb_set
PARAMS ((int));
2056 static void arm_s_text
PARAMS ((int));
2057 static void arm_s_data
PARAMS ((int));
2059 static void arm_s_section
PARAMS ((int));
2060 static void s_arm_elf_cons
PARAMS ((int));
2063 static int my_get_expression
PARAMS ((expressionS
*, char **));
2065 const pseudo_typeS md_pseudo_table
[] =
2067 /* Never called becasue '.req' does not start line. */
2068 { "req", s_req
, 0 },
2069 { "bss", s_bss
, 0 },
2070 { "align", s_align
, 0 },
2071 { "arm", s_arm
, 0 },
2072 { "thumb", s_thumb
, 0 },
2073 { "code", s_code
, 0 },
2074 { "force_thumb", s_force_thumb
, 0 },
2075 { "thumb_func", s_thumb_func
, 0 },
2076 { "thumb_set", s_thumb_set
, 0 },
2077 { "even", s_even
, 0 },
2078 { "ltorg", s_ltorg
, 0 },
2079 { "pool", s_ltorg
, 0 },
2080 /* Allow for the effect of section changes. */
2081 { "text", arm_s_text
, 0 },
2082 { "data", arm_s_data
, 0 },
2084 { "section", arm_s_section
, 0 },
2085 { "section.s", arm_s_section
, 0 },
2086 { "sect", arm_s_section
, 0 },
2087 { "sect.s", arm_s_section
, 0 },
2088 { "word", s_arm_elf_cons
, 4 },
2089 { "long", s_arm_elf_cons
, 4 },
2090 { "file", dwarf2_directive_file
, 0 },
2091 { "loc", dwarf2_directive_loc
, 0 },
2095 { "extend", float_cons
, 'x' },
2096 { "ldouble", float_cons
, 'x' },
2097 { "packed", float_cons
, 'p' },
2101 /* Other internal functions. */
2102 static int arm_parse_extension
PARAMS ((char *, int *));
2103 static int arm_parse_cpu
PARAMS ((char *));
2104 static int arm_parse_arch
PARAMS ((char *));
2105 static int arm_parse_fpu
PARAMS ((char *));
2107 /* Stuff needed to resolve the label ambiguity
2117 symbolS
* last_label_seen
;
2118 static int label_is_thumb_function_name
= false;
2120 /* Literal stuff. */
2122 #define MAX_LITERAL_POOL_SIZE 1024
2124 typedef struct literalS
2126 struct expressionS exp
;
2127 struct arm_it
* inst
;
2130 literalT literals
[MAX_LITERAL_POOL_SIZE
];
2132 /* Next free entry in the pool. */
2133 int next_literal_pool_place
= 0;
2135 /* Next literal pool number. */
2136 int lit_pool_num
= 1;
2138 symbolS
* current_poolP
= NULL
;
2145 if (current_poolP
== NULL
)
2146 current_poolP
= symbol_create (FAKE_LABEL_NAME
, undefined_section
,
2147 (valueT
) 0, &zero_address_frag
);
2149 /* Check if this literal value is already in the pool: */
2150 while (lit_count
< next_literal_pool_place
)
2152 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
2153 && inst
.reloc
.exp
.X_op
== O_constant
2154 && (literals
[lit_count
].exp
.X_add_number
2155 == inst
.reloc
.exp
.X_add_number
)
2156 && literals
[lit_count
].exp
.X_unsigned
== inst
.reloc
.exp
.X_unsigned
)
2159 if (literals
[lit_count
].exp
.X_op
== inst
.reloc
.exp
.X_op
2160 && inst
.reloc
.exp
.X_op
== O_symbol
2161 && (literals
[lit_count
].exp
.X_add_number
2162 == inst
.reloc
.exp
.X_add_number
)
2163 && (literals
[lit_count
].exp
.X_add_symbol
2164 == inst
.reloc
.exp
.X_add_symbol
)
2165 && (literals
[lit_count
].exp
.X_op_symbol
2166 == inst
.reloc
.exp
.X_op_symbol
))
2172 if (lit_count
== next_literal_pool_place
) /* New entry. */
2174 if (next_literal_pool_place
>= MAX_LITERAL_POOL_SIZE
)
2176 inst
.error
= _("literal pool overflow");
2180 literals
[next_literal_pool_place
].exp
= inst
.reloc
.exp
;
2181 lit_count
= next_literal_pool_place
++;
2184 inst
.reloc
.exp
.X_op
= O_symbol
;
2185 inst
.reloc
.exp
.X_add_number
= (lit_count
) * 4 - 8;
2186 inst
.reloc
.exp
.X_add_symbol
= current_poolP
;
2191 /* Can't use symbol_new here, so have to create a symbol and then at
2192 a later date assign it a value. Thats what these functions do. */
2195 symbol_locate (symbolP
, name
, segment
, valu
, frag
)
2197 const char * name
; /* It is copied, the caller can modify. */
2198 segT segment
; /* Segment identifier (SEG_<something>). */
2199 valueT valu
; /* Symbol value. */
2200 fragS
* frag
; /* Associated fragment. */
2202 unsigned int name_length
;
2203 char * preserved_copy_of_name
;
2205 name_length
= strlen (name
) + 1; /* +1 for \0. */
2206 obstack_grow (¬es
, name
, name_length
);
2207 preserved_copy_of_name
= obstack_finish (¬es
);
2208 #ifdef STRIP_UNDERSCORE
2209 if (preserved_copy_of_name
[0] == '_')
2210 preserved_copy_of_name
++;
2213 #ifdef tc_canonicalize_symbol_name
2214 preserved_copy_of_name
=
2215 tc_canonicalize_symbol_name (preserved_copy_of_name
);
2218 S_SET_NAME (symbolP
, preserved_copy_of_name
);
2220 S_SET_SEGMENT (symbolP
, segment
);
2221 S_SET_VALUE (symbolP
, valu
);
2222 symbol_clear_list_pointers(symbolP
);
2224 symbol_set_frag (symbolP
, frag
);
2226 /* Link to end of symbol chain. */
2228 extern int symbol_table_frozen
;
2229 if (symbol_table_frozen
)
2233 symbol_append (symbolP
, symbol_lastP
, & symbol_rootP
, & symbol_lastP
);
2235 obj_symbol_new_hook (symbolP
);
2237 #ifdef tc_symbol_new_hook
2238 tc_symbol_new_hook (symbolP
);
2242 verify_symbol_chain (symbol_rootP
, symbol_lastP
);
2243 #endif /* DEBUG_SYMS */
2246 /* Check that an immediate is valid.
2247 If so, convert it to the right format. */
2250 validate_immediate (val
)
2256 #define rotate_left(v, n) (v << n | v >> (32 - n))
2258 for (i
= 0; i
< 32; i
+= 2)
2259 if ((a
= rotate_left (val
, i
)) <= 0xff)
2260 return a
| (i
<< 7); /* 12-bit pack: [shift-cnt,const]. */
2265 /* Check to see if an immediate can be computed as two seperate immediate
2266 values, added together. We already know that this value cannot be
2267 computed by just one ARM instruction. */
2270 validate_immediate_twopart (val
, highpart
)
2272 unsigned int * highpart
;
2277 for (i
= 0; i
< 32; i
+= 2)
2278 if (((a
= rotate_left (val
, i
)) & 0xff) != 0)
2284 * highpart
= (a
>> 8) | ((i
+ 24) << 7);
2286 else if (a
& 0xff0000)
2290 * highpart
= (a
>> 16) | ((i
+ 16) << 7);
2294 assert (a
& 0xff000000);
2295 * highpart
= (a
>> 24) | ((i
+ 8) << 7);
2298 return (a
& 0xff) | (i
<< 7);
2305 validate_offset_imm (val
, hwse
)
2309 if ((hwse
&& val
> 255) || val
> 4095)
2316 int a ATTRIBUTE_UNUSED
;
2318 as_bad (_("invalid syntax for .req directive"));
2323 int ignore ATTRIBUTE_UNUSED
;
2325 /* We don't support putting frags in the BSS segment, we fake it by
2326 marking in_bss, then looking at s_skip for clues. */
2327 subseg_set (bss_section
, 0);
2328 demand_empty_rest_of_line ();
2333 int ignore ATTRIBUTE_UNUSED
;
2335 /* Never make frag if expect extra pass. */
2337 frag_align (1, 0, 0);
2339 record_alignment (now_seg
, 1);
2341 demand_empty_rest_of_line ();
2346 int ignored ATTRIBUTE_UNUSED
;
2351 if (current_poolP
== NULL
)
2354 /* Align pool as you have word accesses.
2355 Only make a frag if we have to. */
2357 frag_align (2, 0, 0);
2359 record_alignment (now_seg
, 2);
2361 sprintf (sym_name
, "$$lit_\002%x", lit_pool_num
++);
2363 symbol_locate (current_poolP
, sym_name
, now_seg
,
2364 (valueT
) frag_now_fix (), frag_now
);
2365 symbol_table_insert (current_poolP
);
2367 ARM_SET_THUMB (current_poolP
, thumb_mode
);
2369 #if defined OBJ_COFF || defined OBJ_ELF
2370 ARM_SET_INTERWORK (current_poolP
, support_interwork
);
2373 while (lit_count
< next_literal_pool_place
)
2374 /* First output the expression in the instruction to the pool. */
2375 emit_expr (&(literals
[lit_count
++].exp
), 4); /* .word */
2377 next_literal_pool_place
= 0;
2378 current_poolP
= NULL
;
2381 /* Same as s_align_ptwo but align 0 => align 2. */
2385 int unused ATTRIBUTE_UNUSED
;
2388 register long temp_fill
;
2389 long max_alignment
= 15;
2391 temp
= get_absolute_expression ();
2392 if (temp
> max_alignment
)
2393 as_bad (_("alignment too large: %d assumed"), temp
= max_alignment
);
2396 as_bad (_("alignment negative. 0 assumed."));
2400 if (*input_line_pointer
== ',')
2402 input_line_pointer
++;
2403 temp_fill
= get_absolute_expression ();
2411 /* Only make a frag if we HAVE to. */
2412 if (temp
&& !need_pass_2
)
2413 frag_align (temp
, (int) temp_fill
, 0);
2414 demand_empty_rest_of_line ();
2416 record_alignment (now_seg
, temp
);
2420 s_force_thumb (ignore
)
2421 int ignore ATTRIBUTE_UNUSED
;
2423 /* If we are not already in thumb mode go into it, EVEN if
2424 the target processor does not support thumb instructions.
2425 This is used by gcc/config/arm/lib1funcs.asm for example
2426 to compile interworking support functions even if the
2427 target processor should not support interworking. */
2432 record_alignment (now_seg
, 1);
2435 demand_empty_rest_of_line ();
2439 s_thumb_func (ignore
)
2440 int ignore ATTRIBUTE_UNUSED
;
2445 /* The following label is the name/address of the start of a Thumb function.
2446 We need to know this for the interworking support. */
2447 label_is_thumb_function_name
= true;
2449 demand_empty_rest_of_line ();
2452 /* Perform a .set directive, but also mark the alias as
2453 being a thumb function. */
2459 /* XXX the following is a duplicate of the code for s_set() in read.c
2460 We cannot just call that code as we need to get at the symbol that
2462 register char * name
;
2463 register char delim
;
2464 register char * end_name
;
2465 register symbolS
* symbolP
;
2467 /* Especial apologies for the random logic:
2468 This just grew, and could be parsed much more simply!
2470 name
= input_line_pointer
;
2471 delim
= get_symbol_end ();
2472 end_name
= input_line_pointer
;
2477 if (*input_line_pointer
!= ',')
2480 as_bad (_("expected comma after name \"%s\""), name
);
2482 ignore_rest_of_line ();
2486 input_line_pointer
++;
2489 if (name
[0] == '.' && name
[1] == '\0')
2491 /* XXX - this should not happen to .thumb_set. */
2495 if ((symbolP
= symbol_find (name
)) == NULL
2496 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2499 /* When doing symbol listings, play games with dummy fragments living
2500 outside the normal fragment chain to record the file and line info
2502 if (listing
& LISTING_SYMBOLS
)
2504 extern struct list_info_struct
* listing_tail
;
2505 fragS
* dummy_frag
= (fragS
*) xmalloc (sizeof (fragS
));
2507 memset (dummy_frag
, 0, sizeof (fragS
));
2508 dummy_frag
->fr_type
= rs_fill
;
2509 dummy_frag
->line
= listing_tail
;
2510 symbolP
= symbol_new (name
, undefined_section
, 0, dummy_frag
);
2511 dummy_frag
->fr_symbol
= symbolP
;
2515 symbolP
= symbol_new (name
, undefined_section
, 0, &zero_address_frag
);
2518 /* "set" symbols are local unless otherwise specified. */
2519 SF_SET_LOCAL (symbolP
);
2520 #endif /* OBJ_COFF */
2521 } /* Make a new symbol. */
2523 symbol_table_insert (symbolP
);
2528 && S_IS_DEFINED (symbolP
)
2529 && S_GET_SEGMENT (symbolP
) != reg_section
)
2530 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP
));
2532 pseudo_set (symbolP
);
2534 demand_empty_rest_of_line ();
2536 /* XXX Now we come to the Thumb specific bit of code. */
2538 THUMB_SET_FUNC (symbolP
, 1);
2539 ARM_SET_THUMB (symbolP
, 1);
2540 #if defined OBJ_ELF || defined OBJ_COFF
2541 ARM_SET_INTERWORK (symbolP
, support_interwork
);
2545 /* If we change section we must dump the literal pool first. */
2551 if (now_seg
!= text_section
)
2555 obj_elf_text (ignore
);
2565 if (flag_readonly_data_in_text
)
2567 if (now_seg
!= text_section
)
2570 else if (now_seg
!= data_section
)
2574 obj_elf_data (ignore
);
2582 arm_s_section (ignore
)
2587 obj_elf_section (ignore
);
2592 opcode_select (width
)
2600 if (! (cpu_variant
& ARM_EXT_V4T
))
2601 as_bad (_("selected processor does not support THUMB opcodes"));
2604 /* No need to force the alignment, since we will have been
2605 coming from ARM mode, which is word-aligned. */
2606 record_alignment (now_seg
, 1);
2613 if ((cpu_variant
& ARM_ALL
) == ARM_EXT_V4T
)
2614 as_bad (_("selected processor does not support ARM opcodes"));
2619 frag_align (2, 0, 0);
2621 record_alignment (now_seg
, 1);
2626 as_bad (_("invalid instruction size selected (%d)"), width
);
2632 int ignore ATTRIBUTE_UNUSED
;
2635 demand_empty_rest_of_line ();
2640 int ignore ATTRIBUTE_UNUSED
;
2643 demand_empty_rest_of_line ();
2648 int unused ATTRIBUTE_UNUSED
;
2652 temp
= get_absolute_expression ();
2657 opcode_select (temp
);
2661 as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp
);
2669 skip_whitespace (str
);
2671 if (*str
!= '\0' && !inst
.error
)
2672 inst
.error
= _("garbage following instruction");
2676 skip_past_comma (str
)
2679 char * p
= * str
, c
;
2682 while ((c
= *p
) == ' ' || c
== ',')
2685 if (c
== ',' && comma
++)
2693 return comma
? SUCCESS
: FAIL
;
2696 /* A standard register must be given at this point.
2697 SHIFT is the place to put it in inst.instruction.
2698 Restores input start point on error.
2699 Returns the reg#, or FAIL. */
2702 reg_required_here (str
, shift
)
2706 static char buff
[128]; /* XXX */
2708 char * start
= * str
;
2710 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_RN
].htab
)) != FAIL
)
2713 inst
.instruction
|= reg
<< shift
;
2717 /* Restore the start point, we may have got a reg of the wrong class. */
2720 /* In the few cases where we might be able to accept something else
2721 this error can be overridden. */
2722 sprintf (buff
, _("register expected, not '%.100s'"), start
);
2728 static const struct asm_psr
*
2730 register char ** ccp
;
2732 char * start
= * ccp
;
2735 const struct asm_psr
* psr
;
2739 /* Skip to the end of the next word in the input stream. */
2744 while (ISALPHA (c
) || c
== '_');
2746 /* Terminate the word. */
2749 /* CPSR's and SPSR's can now be lowercase. This is just a convenience
2750 feature for ease of use and backwards compatibility. */
2751 if (!strncmp (start
, "cpsr", 4))
2752 strncpy (start
, "CPSR", 4);
2753 else if (!strncmp (start
, "spsr", 4))
2754 strncpy (start
, "SPSR", 4);
2756 /* Now locate the word in the psr hash table. */
2757 psr
= (const struct asm_psr
*) hash_find (arm_psr_hsh
, start
);
2759 /* Restore the input stream. */
2762 /* If we found a valid match, advance the
2763 stream pointer past the end of the word. */
2769 /* Parse the input looking for a PSR flag. */
2772 psr_required_here (str
)
2775 char * start
= * str
;
2776 const struct asm_psr
* psr
;
2778 psr
= arm_psr_parse (str
);
2782 /* If this is the SPSR that is being modified, set the R bit. */
2784 inst
.instruction
|= SPSR_BIT
;
2786 /* Set the psr flags in the MSR instruction. */
2787 inst
.instruction
|= psr
->field
<< PSR_SHIFT
;
2792 /* In the few cases where we might be able to accept
2793 something else this error can be overridden. */
2794 inst
.error
= _("flag for {c}psr instruction expected");
2796 /* Restore the start point. */
2802 co_proc_number (str
)
2805 int processor
, pchar
;
2808 skip_whitespace (*str
);
2811 /* The data sheet seems to imply that just a number on its own is valid
2812 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
2814 if ((processor
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CP
].htab
))
2820 if (pchar
>= '0' && pchar
<= '9')
2822 processor
= pchar
- '0';
2823 if (**str
>= '0' && **str
<= '9')
2825 processor
= processor
* 10 + *(*str
)++ - '0';
2828 inst
.error
= _("illegal co-processor number");
2835 inst
.error
= _("bad or missing co-processor number");
2840 inst
.instruction
|= processor
<< 8;
2845 cp_opc_expr (str
, where
, length
)
2852 skip_whitespace (* str
);
2854 memset (&expr
, '\0', sizeof (expr
));
2856 if (my_get_expression (&expr
, str
))
2858 if (expr
.X_op
!= O_constant
)
2860 inst
.error
= _("bad or missing expression");
2864 if ((expr
.X_add_number
& ((1 << length
) - 1)) != expr
.X_add_number
)
2866 inst
.error
= _("immediate co-processor expression too large");
2870 inst
.instruction
|= expr
.X_add_number
<< where
;
2875 cp_reg_required_here (str
, where
)
2880 char * start
= *str
;
2882 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_CN
].htab
)) != FAIL
)
2884 inst
.instruction
|= reg
<< where
;
2888 /* In the few cases where we might be able to accept something else
2889 this error can be overridden. */
2890 inst
.error
= _("co-processor register expected");
2892 /* Restore the start point. */
2898 fp_reg_required_here (str
, where
)
2903 char * start
= * str
;
2905 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_FN
].htab
)) != FAIL
)
2907 inst
.instruction
|= reg
<< where
;
2911 /* In the few cases where we might be able to accept something else
2912 this error can be overridden. */
2913 inst
.error
= _("floating point register expected");
2915 /* Restore the start point. */
2921 cp_address_offset (str
)
2926 skip_whitespace (* str
);
2928 if (! is_immediate_prefix (**str
))
2930 inst
.error
= _("immediate expression expected");
2936 if (my_get_expression (& inst
.reloc
.exp
, str
))
2939 if (inst
.reloc
.exp
.X_op
== O_constant
)
2941 offset
= inst
.reloc
.exp
.X_add_number
;
2945 inst
.error
= _("co-processor address must be word aligned");
2949 if (offset
> 1023 || offset
< -1023)
2951 inst
.error
= _("offset too large");
2956 inst
.instruction
|= INDEX_UP
;
2960 inst
.instruction
|= offset
>> 2;
2963 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
2969 cp_address_required_here (str
, wb_ok
)
2982 skip_whitespace (p
);
2984 if ((reg
= reg_required_here (& p
, 16)) == FAIL
)
2987 skip_whitespace (p
);
2993 if (wb_ok
&& skip_past_comma (& p
) == SUCCESS
)
2996 write_back
= WRITE_BACK
;
3000 inst
.error
= _("pc may not be used in post-increment");
3004 if (cp_address_offset (& p
) == FAIL
)
3008 pre_inc
= PRE_INDEX
| INDEX_UP
;
3012 /* '['Rn, #expr']'[!] */
3014 if (skip_past_comma (& p
) == FAIL
)
3016 inst
.error
= _("pre-indexed expression expected");
3020 pre_inc
= PRE_INDEX
;
3022 if (cp_address_offset (& p
) == FAIL
)
3025 skip_whitespace (p
);
3029 inst
.error
= _("missing ]");
3033 skip_whitespace (p
);
3035 if (wb_ok
&& *p
== '!')
3039 inst
.error
= _("pc may not be used with write-back");
3044 write_back
= WRITE_BACK
;
3050 if (my_get_expression (&inst
.reloc
.exp
, &p
))
3053 inst
.reloc
.type
= BFD_RELOC_ARM_CP_OFF_IMM
;
3054 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3055 inst
.reloc
.pc_rel
= 1;
3056 inst
.instruction
|= (REG_PC
<< 16);
3057 pre_inc
= PRE_INDEX
;
3060 inst
.instruction
|= write_back
| pre_inc
;
3069 /* Do nothing really. */
3080 /* Only one syntax. */
3081 skip_whitespace (str
);
3083 if (reg_required_here (&str
, 12) == FAIL
)
3085 inst
.error
= BAD_ARGS
;
3089 if (skip_past_comma (&str
) == FAIL
)
3091 inst
.error
= _("comma expected after register name");
3095 skip_whitespace (str
);
3097 if ( strcmp (str
, "CPSR") == 0
3098 || strcmp (str
, "SPSR") == 0
3099 /* Lower case versions for backwards compatability. */
3100 || strcmp (str
, "cpsr") == 0
3101 || strcmp (str
, "spsr") == 0)
3104 /* This is for backwards compatability with older toolchains. */
3105 else if ( strcmp (str
, "cpsr_all") == 0
3106 || strcmp (str
, "spsr_all") == 0)
3110 inst
.error
= _("CPSR or SPSR expected");
3114 if (* str
== 's' || * str
== 'S')
3115 inst
.instruction
|= SPSR_BIT
;
3121 /* Two possible forms:
3122 "{C|S}PSR_<field>, Rm",
3123 "{C|S}PSR_f, #expression". */
3129 skip_whitespace (str
);
3131 if (psr_required_here (& str
) == FAIL
)
3134 if (skip_past_comma (& str
) == FAIL
)
3136 inst
.error
= _("comma missing after psr flags");
3140 skip_whitespace (str
);
3142 if (reg_required_here (& str
, 0) != FAIL
)
3149 if (! is_immediate_prefix (* str
))
3152 _("only a register or immediate value can follow a psr flag");
3159 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3162 _("only a register or immediate value can follow a psr flag");
3166 #if 0 /* The first edition of the ARM architecture manual stated that
3167 writing anything other than the flags with an immediate operation
3168 had UNPREDICTABLE effects. This constraint was removed in the
3169 second edition of the specification. */
3170 if ((cpu_variant
& ARM_EXT_V5
) != ARM_EXT_V5
3171 && inst
.instruction
& ((PSR_c
| PSR_x
| PSR_s
) << PSR_SHIFT
))
3173 inst
.error
= _("immediate value cannot be used to set this field");
3178 inst
.instruction
|= INST_IMMEDIATE
;
3180 if (inst
.reloc
.exp
.X_add_symbol
)
3182 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
3183 inst
.reloc
.pc_rel
= 0;
3187 unsigned value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
3189 if (value
== (unsigned) FAIL
)
3191 inst
.error
= _("invalid constant");
3195 inst
.instruction
|= value
;
3202 /* Long Multiply Parser
3203 UMULL RdLo, RdHi, Rm, Rs
3204 SMULL RdLo, RdHi, Rm, Rs
3205 UMLAL RdLo, RdHi, Rm, Rs
3206 SMLAL RdLo, RdHi, Rm, Rs. */
3212 int rdlo
, rdhi
, rm
, rs
;
3214 /* Only one format "rdlo, rdhi, rm, rs". */
3215 skip_whitespace (str
);
3217 if ((rdlo
= reg_required_here (&str
, 12)) == FAIL
)
3219 inst
.error
= BAD_ARGS
;
3223 if (skip_past_comma (&str
) == FAIL
3224 || (rdhi
= reg_required_here (&str
, 16)) == FAIL
)
3226 inst
.error
= BAD_ARGS
;
3230 if (skip_past_comma (&str
) == FAIL
3231 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3233 inst
.error
= BAD_ARGS
;
3237 /* rdhi, rdlo and rm must all be different. */
3238 if (rdlo
== rdhi
|| rdlo
== rm
|| rdhi
== rm
)
3239 as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3241 if (skip_past_comma (&str
) == FAIL
3242 || (rs
= reg_required_here (&str
, 8)) == FAIL
)
3244 inst
.error
= BAD_ARGS
;
3248 if (rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
|| rdhi
== REG_PC
)
3250 inst
.error
= BAD_PC
;
3264 /* Only one format "rd, rm, rs". */
3265 skip_whitespace (str
);
3267 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3269 inst
.error
= BAD_ARGS
;
3275 inst
.error
= BAD_PC
;
3279 if (skip_past_comma (&str
) == FAIL
3280 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3282 inst
.error
= BAD_ARGS
;
3288 inst
.error
= BAD_PC
;
3293 as_tsktsk (_("rd and rm should be different in mul"));
3295 if (skip_past_comma (&str
) == FAIL
3296 || (rm
= reg_required_here (&str
, 8)) == FAIL
)
3298 inst
.error
= BAD_ARGS
;
3304 inst
.error
= BAD_PC
;
3318 /* Only one format "rd, rm, rs, rn". */
3319 skip_whitespace (str
);
3321 if ((rd
= reg_required_here (&str
, 16)) == FAIL
)
3323 inst
.error
= BAD_ARGS
;
3329 inst
.error
= BAD_PC
;
3333 if (skip_past_comma (&str
) == FAIL
3334 || (rm
= reg_required_here (&str
, 0)) == FAIL
)
3336 inst
.error
= BAD_ARGS
;
3342 inst
.error
= BAD_PC
;
3347 as_tsktsk (_("rd and rm should be different in mla"));
3349 if (skip_past_comma (&str
) == FAIL
3350 || (rd
= reg_required_here (&str
, 8)) == FAIL
3351 || skip_past_comma (&str
) == FAIL
3352 || (rm
= reg_required_here (&str
, 12)) == FAIL
)
3354 inst
.error
= BAD_ARGS
;
3358 if (rd
== REG_PC
|| rm
== REG_PC
)
3360 inst
.error
= BAD_PC
;
3368 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3369 Advances *str to the next non-alphanumeric.
3370 Returns 0, or else FAIL (in which case sets inst.error).
3372 (In a future XScale, there may be accumulators other than zero.
3373 At that time this routine and its callers can be upgraded to suit.) */
3376 accum0_required_here (str
)
3379 static char buff
[128]; /* Note the address is taken. Hence, static. */
3382 int result
= 0; /* The accum number. */
3384 skip_whitespace (p
);
3386 *str
= p
; /* Advance caller's string pointer too. */
3391 *--p
= 0; /* Aap nul into input buffer at non-alnum. */
3393 if (! ( streq (*str
, "acc0") || streq (*str
, "ACC0")))
3395 sprintf (buff
, _("acc0 expected, not '%.100s'"), *str
);
3400 *p
= c
; /* Unzap. */
3401 *str
= p
; /* Caller's string pointer to after match. */
3405 /* Expects **str -> after a comma. May be leading blanks.
3406 Advances *str, recognizing a load mode, and setting inst.instruction.
3407 Returns rn, or else FAIL (in which case may set inst.error
3408 and not advance str)
3410 Note: doesn't know Rd, so no err checks that require such knowledge. */
3413 ld_mode_required_here (string
)
3416 char * str
= * string
;
3420 skip_whitespace (str
);
3426 skip_whitespace (str
);
3428 if ((rn
= reg_required_here (& str
, 16)) == FAIL
)
3431 skip_whitespace (str
);
3437 if (skip_past_comma (& str
) == SUCCESS
)
3439 /* [Rn],... (post inc) */
3440 if (ldst_extend_v4 (&str
) == FAIL
)
3445 skip_whitespace (str
);
3450 inst
.instruction
|= WRITE_BACK
;
3453 inst
.instruction
|= INDEX_UP
| HWOFFSET_IMM
;
3459 if (skip_past_comma (& str
) == FAIL
)
3461 inst
.error
= _("pre-indexed expression expected");
3467 if (ldst_extend_v4 (&str
) == FAIL
)
3470 skip_whitespace (str
);
3472 if (* str
++ != ']')
3474 inst
.error
= _("missing ]");
3478 skip_whitespace (str
);
3483 inst
.instruction
|= WRITE_BACK
;
3487 else if (* str
== '=') /* ldr's "r,=label" syntax */
3488 /* We should never reach here, because <text> = <expression> is
3489 caught gas/read.c read_a_source_file() as a .set operation. */
3491 else /* PC +- 8 bit immediate offset. */
3493 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3496 inst
.instruction
|= HWOFFSET_IMM
; /* The I bit. */
3497 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
3498 inst
.reloc
.exp
.X_add_number
-= 8; /* PC rel adjust. */
3499 inst
.reloc
.pc_rel
= 1;
3500 inst
.instruction
|= (REG_PC
<< 16);
3506 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
3512 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3513 SMLAxy{cond} Rd,Rm,Rs,Rn
3514 SMLAWy{cond} Rd,Rm,Rs,Rn
3515 Error if any register is R15. */
3523 skip_whitespace (str
);
3525 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3526 || skip_past_comma (& str
) == FAIL
3527 || (rm
= reg_required_here (& str
, 0)) == FAIL
3528 || skip_past_comma (& str
) == FAIL
3529 || (rs
= reg_required_here (& str
, 8)) == FAIL
3530 || skip_past_comma (& str
) == FAIL
3531 || (rn
= reg_required_here (& str
, 12)) == FAIL
)
3532 inst
.error
= BAD_ARGS
;
3534 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
|| rn
== REG_PC
)
3535 inst
.error
= BAD_PC
;
3541 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
3542 SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
3543 Error if any register is R15.
3544 Warning if Rdlo == Rdhi. */
3550 int rdlo
, rdhi
, rm
, rs
;
3552 skip_whitespace (str
);
3554 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
3555 || skip_past_comma (& str
) == FAIL
3556 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
3557 || skip_past_comma (& str
) == FAIL
3558 || (rm
= reg_required_here (& str
, 0)) == FAIL
3559 || skip_past_comma (& str
) == FAIL
3560 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3562 inst
.error
= BAD_ARGS
;
3566 if (rdlo
== REG_PC
|| rdhi
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3568 inst
.error
= BAD_PC
;
3573 as_tsktsk (_("rdhi and rdlo must be different"));
3578 /* ARM V5E (El Segundo) signed-multiply (argument parse)
3579 SMULxy{cond} Rd,Rm,Rs
3580 Error if any register is R15. */
3588 skip_whitespace (str
);
3590 if ((rd
= reg_required_here (& str
, 16)) == FAIL
3591 || skip_past_comma (& str
) == FAIL
3592 || (rm
= reg_required_here (& str
, 0)) == FAIL
3593 || skip_past_comma (& str
) == FAIL
3594 || (rs
= reg_required_here (& str
, 8)) == FAIL
)
3595 inst
.error
= BAD_ARGS
;
3597 else if (rd
== REG_PC
|| rm
== REG_PC
|| rs
== REG_PC
)
3598 inst
.error
= BAD_PC
;
3604 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
3605 Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
3606 Error if any register is R15. */
3614 skip_whitespace (str
);
3616 if ((rd
= reg_required_here (& str
, 12)) == FAIL
3617 || skip_past_comma (& str
) == FAIL
3618 || (rm
= reg_required_here (& str
, 0)) == FAIL
3619 || skip_past_comma (& str
) == FAIL
3620 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3621 inst
.error
= BAD_ARGS
;
3623 else if (rd
== REG_PC
|| rm
== REG_PC
|| rn
== REG_PC
)
3624 inst
.error
= BAD_PC
;
3630 /* ARM V5E (el Segundo)
3631 MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3632 MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
3634 These are equivalent to the XScale instructions MAR and MRA,
3635 respectively, when coproc == 0, opcode == 0, and CRm == 0.
3637 Result unpredicatable if Rd or Rn is R15. */
3645 skip_whitespace (str
);
3647 if (co_proc_number (& str
) == FAIL
)
3650 inst
.error
= BAD_ARGS
;
3654 if (skip_past_comma (& str
) == FAIL
3655 || cp_opc_expr (& str
, 4, 4) == FAIL
)
3658 inst
.error
= BAD_ARGS
;
3662 if (skip_past_comma (& str
) == FAIL
3663 || (rd
= reg_required_here (& str
, 12)) == FAIL
)
3666 inst
.error
= BAD_ARGS
;
3670 if (skip_past_comma (& str
) == FAIL
3671 || (rn
= reg_required_here (& str
, 16)) == FAIL
)
3674 inst
.error
= BAD_ARGS
;
3678 /* Unpredictable result if rd or rn is R15. */
3679 if (rd
== REG_PC
|| rn
== REG_PC
)
3681 (_("Warning: instruction unpredictable when using r15"));
3683 if (skip_past_comma (& str
) == FAIL
3684 || cp_reg_required_here (& str
, 0) == FAIL
)
3687 inst
.error
= BAD_ARGS
;
3694 /* ARM V5 count-leading-zeroes instruction (argument parse)
3695 CLZ{<cond>} <Rd>, <Rm>
3696 Condition defaults to COND_ALWAYS.
3697 Error if Rd or Rm are R15. */
3705 skip_whitespace (str
);
3707 if (((rd
= reg_required_here (& str
, 12)) == FAIL
)
3708 || (skip_past_comma (& str
) == FAIL
)
3709 || ((rm
= reg_required_here (& str
, 0)) == FAIL
))
3710 inst
.error
= BAD_ARGS
;
3712 else if (rd
== REG_PC
|| rm
== REG_PC
)
3713 inst
.error
= BAD_PC
;
3719 /* ARM V5 (argument parse)
3720 LDC2{L} <coproc>, <CRd>, <addressing mode>
3721 STC2{L} <coproc>, <CRd>, <addressing mode>
3722 Instruction is not conditional, and has 0xf in the codition field.
3723 Otherwise, it's the same as LDC/STC. */
3729 skip_whitespace (str
);
3731 if (co_proc_number (& str
) == FAIL
)
3734 inst
.error
= BAD_ARGS
;
3736 else if (skip_past_comma (& str
) == FAIL
3737 || cp_reg_required_here (& str
, 12) == FAIL
)
3740 inst
.error
= BAD_ARGS
;
3742 else if (skip_past_comma (& str
) == FAIL
3743 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
3746 inst
.error
= BAD_ARGS
;
3752 /* ARM V5 (argument parse)
3753 CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
3754 Instruction is not conditional, and has 0xf in the condition field.
3755 Otherwise, it's the same as CDP. */
3761 skip_whitespace (str
);
3763 if (co_proc_number (& str
) == FAIL
)
3766 inst
.error
= BAD_ARGS
;
3770 if (skip_past_comma (& str
) == FAIL
3771 || cp_opc_expr (& str
, 20,4) == FAIL
)
3774 inst
.error
= BAD_ARGS
;
3778 if (skip_past_comma (& str
) == FAIL
3779 || cp_reg_required_here (& str
, 12) == FAIL
)
3782 inst
.error
= BAD_ARGS
;
3786 if (skip_past_comma (& str
) == FAIL
3787 || cp_reg_required_here (& str
, 16) == FAIL
)
3790 inst
.error
= BAD_ARGS
;
3794 if (skip_past_comma (& str
) == FAIL
3795 || cp_reg_required_here (& str
, 0) == FAIL
)
3798 inst
.error
= BAD_ARGS
;
3802 if (skip_past_comma (& str
) == SUCCESS
)
3804 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3807 inst
.error
= BAD_ARGS
;
3815 /* ARM V5 (argument parse)
3816 MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3817 MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
3818 Instruction is not conditional, and has 0xf in the condition field.
3819 Otherwise, it's the same as MCR/MRC. */
3825 skip_whitespace (str
);
3827 if (co_proc_number (& str
) == FAIL
)
3830 inst
.error
= BAD_ARGS
;
3834 if (skip_past_comma (& str
) == FAIL
3835 || cp_opc_expr (& str
, 21, 3) == FAIL
)
3838 inst
.error
= BAD_ARGS
;
3842 if (skip_past_comma (& str
) == FAIL
3843 || reg_required_here (& str
, 12) == FAIL
)
3846 inst
.error
= BAD_ARGS
;
3850 if (skip_past_comma (& str
) == FAIL
3851 || cp_reg_required_here (& str
, 16) == FAIL
)
3854 inst
.error
= BAD_ARGS
;
3858 if (skip_past_comma (& str
) == FAIL
3859 || cp_reg_required_here (& str
, 0) == FAIL
)
3862 inst
.error
= BAD_ARGS
;
3866 if (skip_past_comma (& str
) == SUCCESS
)
3868 if (cp_opc_expr (& str
, 5, 3) == FAIL
)
3871 inst
.error
= BAD_ARGS
;
3879 /* THUMB V5 breakpoint instruction (argument parse)
3887 unsigned long number
;
3889 skip_whitespace (str
);
3891 /* Allow optional leading '#'. */
3892 if (is_immediate_prefix (*str
))
3895 memset (& expr
, '\0', sizeof (expr
));
3896 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
3898 inst
.error
= _("bad or missing expression");
3902 number
= expr
.X_add_number
;
3904 /* Check it fits an 8 bit unsigned. */
3905 if (number
!= (number
& 0xff))
3907 inst
.error
= _("immediate value out of range");
3911 inst
.instruction
|= number
;
3916 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
3917 Expects inst.instruction is set for BLX(1).
3918 Note: this is cloned from do_branch, and the reloc changed to be a
3919 new one that can cope with setting one extra bit (the H bit). */
3925 if (my_get_expression (& inst
.reloc
.exp
, & str
))
3932 /* ScottB: February 5, 1998 */
3933 /* Check to see of PLT32 reloc required for the instruction. */
3935 /* arm_parse_reloc() works on input_line_pointer.
3936 We actually want to parse the operands to the branch instruction
3937 passed in 'str'. Save the input pointer and restore it later. */
3938 save_in
= input_line_pointer
;
3939 input_line_pointer
= str
;
3941 if (inst
.reloc
.exp
.X_op
== O_symbol
3943 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
3945 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
3946 inst
.reloc
.pc_rel
= 0;
3947 /* Modify str to point to after parsed operands, otherwise
3948 end_of_line() will complain about the (PLT) left in str. */
3949 str
= input_line_pointer
;
3953 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3954 inst
.reloc
.pc_rel
= 1;
3957 input_line_pointer
= save_in
;
3960 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BLX
;
3961 inst
.reloc
.pc_rel
= 1;
3962 #endif /* OBJ_ELF */
3967 /* ARM V5 branch-link-exchange instruction (argument parse)
3968 BLX <target_addr> ie BLX(1)
3969 BLX{<condition>} <Rm> ie BLX(2)
3970 Unfortunately, there are two different opcodes for this mnemonic.
3971 So, the insns[].value is not used, and the code here zaps values
3972 into inst.instruction.
3973 Also, the <target_addr> can be 25 bits, hence has its own reloc. */
3982 skip_whitespace (mystr
);
3983 rm
= reg_required_here (& mystr
, 0);
3985 /* The above may set inst.error. Ignore his opinion. */
3990 /* Arg is a register.
3991 Use the condition code our caller put in inst.instruction.
3992 Pass ourselves off as a BX with a funny opcode. */
3993 inst
.instruction
|= 0x012fff30;
3998 /* This must be is BLX <target address>, no condition allowed. */
3999 if (inst
.instruction
!= COND_ALWAYS
)
4001 inst
.error
= BAD_COND
;
4005 inst
.instruction
= 0xfafffffe;
4007 /* Process like a B/BL, but with a different reloc.
4008 Note that B/BL expecte fffffe, not 0, offset in the opcode table. */
4013 /* ARM V5 Thumb BLX (argument parse)
4014 BLX <target_addr> which is BLX(1)
4015 BLX <Rm> which is BLX(2)
4016 Unfortunately, there are two different opcodes for this mnemonic.
4017 So, the tinsns[].value is not used, and the code here zaps values
4018 into inst.instruction. */
4027 skip_whitespace (mystr
);
4028 inst
.instruction
= 0x4780;
4030 /* Note that this call is to the ARM register recognizer. BLX(2)
4031 uses the ARM register space, not the Thumb one, so a call to
4032 thumb_reg() would be wrong. */
4033 rm
= reg_required_here (& mystr
, 3);
4038 /* It's BLX(2). The .instruction was zapped with rm & is final. */
4043 /* No ARM register. This must be BLX(1). Change the .instruction. */
4044 inst
.instruction
= 0xf7ffeffe;
4047 if (my_get_expression (& inst
.reloc
.exp
, & mystr
))
4050 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BLX
;
4051 inst
.reloc
.pc_rel
= 1;
4054 end_of_line (mystr
);
4057 /* ARM V5 breakpoint instruction (argument parse)
4058 BKPT <16 bit unsigned immediate>
4059 Instruction is not conditional.
4060 The bit pattern given in insns[] has the COND_ALWAYS condition,
4061 and it is an error if the caller tried to override that. */
4068 unsigned long number
;
4070 skip_whitespace (str
);
4072 /* Allow optional leading '#'. */
4073 if (is_immediate_prefix (* str
))
4076 memset (& expr
, '\0', sizeof (expr
));
4078 if (my_get_expression (& expr
, & str
) || (expr
.X_op
!= O_constant
))
4080 inst
.error
= _("bad or missing expression");
4084 number
= expr
.X_add_number
;
4086 /* Check it fits a 16 bit unsigned. */
4087 if (number
!= (number
& 0xffff))
4089 inst
.error
= _("immediate value out of range");
4093 /* Top 12 of 16 bits to bits 19:8. */
4094 inst
.instruction
|= (number
& 0xfff0) << 4;
4096 /* Bottom 4 of 16 bits to bits 3:0. */
4097 inst
.instruction
|= number
& 0xf;
4102 /* Xscale multiply-accumulate (argument parse)
4105 MIAxycc acc0,Rm,Rs. */
4114 if (accum0_required_here (& str
) == FAIL
)
4115 inst
.error
= ERR_NO_ACCUM
;
4117 else if (skip_past_comma (& str
) == FAIL
4118 || (rm
= reg_required_here (& str
, 0)) == FAIL
)
4119 inst
.error
= BAD_ARGS
;
4121 else if (skip_past_comma (& str
) == FAIL
4122 || (rs
= reg_required_here (& str
, 12)) == FAIL
)
4123 inst
.error
= BAD_ARGS
;
4125 /* inst.instruction has now been zapped with both rm and rs. */
4126 else if (rm
== REG_PC
|| rs
== REG_PC
)
4127 inst
.error
= BAD_PC
; /* Undefined result if rm or rs is R15. */
4133 /* Xscale move-accumulator-register (argument parse)
4135 MARcc acc0,RdLo,RdHi. */
4143 if (accum0_required_here (& str
) == FAIL
)
4144 inst
.error
= ERR_NO_ACCUM
;
4146 else if (skip_past_comma (& str
) == FAIL
4147 || (rdlo
= reg_required_here (& str
, 12)) == FAIL
)
4148 inst
.error
= BAD_ARGS
;
4150 else if (skip_past_comma (& str
) == FAIL
4151 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
4152 inst
.error
= BAD_ARGS
;
4154 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4155 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
4156 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
4162 /* Xscale move-register-accumulator (argument parse)
4164 MRAcc RdLo,RdHi,acc0. */
4173 skip_whitespace (str
);
4175 if ((rdlo
= reg_required_here (& str
, 12)) == FAIL
)
4176 inst
.error
= BAD_ARGS
;
4178 else if (skip_past_comma (& str
) == FAIL
4179 || (rdhi
= reg_required_here (& str
, 16)) == FAIL
)
4180 inst
.error
= BAD_ARGS
;
4182 else if (skip_past_comma (& str
) == FAIL
4183 || accum0_required_here (& str
) == FAIL
)
4184 inst
.error
= ERR_NO_ACCUM
;
4186 /* inst.instruction has now been zapped with both rdlo and rdhi. */
4187 else if (rdlo
== rdhi
)
4188 inst
.error
= BAD_ARGS
; /* Undefined result if 2 writes to same reg. */
4190 else if (rdlo
== REG_PC
|| rdhi
== REG_PC
)
4191 inst
.error
= BAD_PC
; /* Undefined result if rdlo or rdhi is R15. */
4196 /* ARMv5TE: Preload-Cache
4200 Syntactically, like LDR with B=1, W=0, L=1. */
4208 skip_whitespace (str
);
4212 inst
.error
= _("'[' expected after PLD mnemonic");
4217 skip_whitespace (str
);
4219 if ((rd
= reg_required_here (& str
, 16)) == FAIL
)
4222 skip_whitespace (str
);
4228 skip_whitespace (str
);
4230 /* Post-indexed addressing is not allowed with PLD. */
4231 if (skip_past_comma (&str
) == SUCCESS
)
4234 = _("post-indexed expression used in preload instruction");
4237 else if (*str
== '!') /* [Rn]! */
4239 inst
.error
= _("writeback used in preload instruction");
4243 inst
.instruction
|= INDEX_UP
| PRE_INDEX
;
4245 else /* [Rn, ...] */
4247 if (skip_past_comma (& str
) == FAIL
)
4249 inst
.error
= _("pre-indexed expression expected");
4253 if (ldst_extend (&str
) == FAIL
)
4256 skip_whitespace (str
);
4260 inst
.error
= _("missing ]");
4265 skip_whitespace (str
);
4267 if (* str
== '!') /* [Rn]! */
4269 inst
.error
= _("writeback used in preload instruction");
4273 inst
.instruction
|= PRE_INDEX
;
4279 /* ARMv5TE load-consecutive (argument parse)
4292 skip_whitespace (str
);
4294 if ((rd
= reg_required_here (& str
, 12)) == FAIL
)
4296 inst
.error
= BAD_ARGS
;
4300 if (skip_past_comma (& str
) == FAIL
4301 || (rn
= ld_mode_required_here (& str
)) == FAIL
)
4304 inst
.error
= BAD_ARGS
;
4308 /* inst.instruction has now been zapped with Rd and the addressing mode. */
4309 if (rd
& 1) /* Unpredictable result if Rd is odd. */
4311 inst
.error
= _("destination register must be even");
4317 inst
.error
= _("r14 not allowed here");
4321 if (((rd
== rn
) || (rd
+ 1 == rn
))
4322 && ((inst
.instruction
& WRITE_BACK
)
4323 || (!(inst
.instruction
& PRE_INDEX
))))
4324 as_warn (_("pre/post-indexing used when modified address register is destination"));
4326 /* For an index-register load, the index register must not overlap the
4327 destination (even if not write-back). */
4328 if ((inst
.instruction
& V4_STR_BIT
) == 0
4329 && (inst
.instruction
& HWOFFSET_IMM
) == 0)
4331 int rm
= inst
.instruction
& 0x0000000f;
4333 if (rm
== rd
|| (rm
== rd
+ 1))
4334 as_warn (_("ldrd destination registers must not overlap index register"));
4340 /* Returns the index into fp_values of a floating point number,
4341 or -1 if not in the table. */
4344 my_get_float_expression (str
)
4347 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
4353 memset (words
, 0, MAX_LITTLENUMS
* sizeof (LITTLENUM_TYPE
));
4355 /* Look for a raw floating point number. */
4356 if ((save_in
= atof_ieee (*str
, 'x', words
)) != NULL
4357 && is_end_of_line
[(unsigned char) *save_in
])
4359 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4361 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4363 if (words
[j
] != fp_values
[i
][j
])
4367 if (j
== MAX_LITTLENUMS
)
4375 /* Try and parse a more complex expression, this will probably fail
4376 unless the code uses a floating point prefix (eg "0f"). */
4377 save_in
= input_line_pointer
;
4378 input_line_pointer
= *str
;
4379 if (expression (&exp
) == absolute_section
4380 && exp
.X_op
== O_big
4381 && exp
.X_add_number
< 0)
4383 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
4385 if (gen_to_words (words
, 5, (long) 15) == 0)
4387 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
4389 for (j
= 0; j
< MAX_LITTLENUMS
; j
++)
4391 if (words
[j
] != fp_values
[i
][j
])
4395 if (j
== MAX_LITTLENUMS
)
4397 *str
= input_line_pointer
;
4398 input_line_pointer
= save_in
;
4405 *str
= input_line_pointer
;
4406 input_line_pointer
= save_in
;
4410 /* Return true if anything in the expression is a bignum. */
4413 walk_no_bignums (sp
)
4416 if (symbol_get_value_expression (sp
)->X_op
== O_big
)
4419 if (symbol_get_value_expression (sp
)->X_add_symbol
)
4421 return (walk_no_bignums (symbol_get_value_expression (sp
)->X_add_symbol
)
4422 || (symbol_get_value_expression (sp
)->X_op_symbol
4423 && walk_no_bignums (symbol_get_value_expression (sp
)->X_op_symbol
)));
4429 static int in_my_get_expression
= 0;
4432 my_get_expression (ep
, str
)
4439 save_in
= input_line_pointer
;
4440 input_line_pointer
= *str
;
4441 in_my_get_expression
= 1;
4442 seg
= expression (ep
);
4443 in_my_get_expression
= 0;
4445 if (ep
->X_op
== O_illegal
)
4447 /* We found a bad expression in md_operand(). */
4448 *str
= input_line_pointer
;
4449 input_line_pointer
= save_in
;
4454 if (seg
!= absolute_section
4455 && seg
!= text_section
4456 && seg
!= data_section
4457 && seg
!= bss_section
4458 && seg
!= undefined_section
)
4460 inst
.error
= _("bad_segment");
4461 *str
= input_line_pointer
;
4462 input_line_pointer
= save_in
;
4467 /* Get rid of any bignums now, so that we don't generate an error for which
4468 we can't establish a line number later on. Big numbers are never valid
4469 in instructions, which is where this routine is always called. */
4470 if (ep
->X_op
== O_big
4471 || (ep
->X_add_symbol
4472 && (walk_no_bignums (ep
->X_add_symbol
)
4474 && walk_no_bignums (ep
->X_op_symbol
)))))
4476 inst
.error
= _("invalid constant");
4477 *str
= input_line_pointer
;
4478 input_line_pointer
= save_in
;
4482 *str
= input_line_pointer
;
4483 input_line_pointer
= save_in
;
4487 /* We handle all bad expressions here, so that we can report the faulty
4488 instruction in the error message. */
4493 if (in_my_get_expression
)
4495 expr
->X_op
= O_illegal
;
4496 if (inst
.error
== NULL
)
4497 inst
.error
= _("bad expression");
4501 /* UNRESTRICT should be one if <shift> <register> is permitted for this
4505 decode_shift (str
, unrestrict
)
4509 const struct asm_shift_name
* shift
;
4513 skip_whitespace (* str
);
4515 for (p
= * str
; ISALPHA (* p
); p
++)
4520 inst
.error
= _("shift expression expected");
4526 shift
= (const struct asm_shift_name
*) hash_find (arm_shift_hsh
, * str
);
4531 inst
.error
= _("shift expression expected");
4535 assert (shift
->properties
->index
== shift_properties
[shift
->properties
->index
].index
);
4537 if (shift
->properties
->index
== SHIFT_RRX
)
4540 inst
.instruction
|= shift
->properties
->bit_field
;
4544 skip_whitespace (p
);
4546 if (unrestrict
&& reg_required_here (& p
, 8) != FAIL
)
4548 inst
.instruction
|= shift
->properties
->bit_field
| SHIFT_BY_REG
;
4552 else if (! is_immediate_prefix (* p
))
4554 inst
.error
= (unrestrict
4555 ? _("shift requires register or #expression")
4556 : _("shift requires #expression"));
4564 if (my_get_expression (& inst
.reloc
.exp
, & p
))
4567 /* Validate some simple #expressions. */
4568 if (inst
.reloc
.exp
.X_op
== O_constant
)
4570 unsigned num
= inst
.reloc
.exp
.X_add_number
;
4572 /* Reject operations greater than 32. */
4574 /* Reject a shift of 0 unless the mode allows it. */
4575 || (num
== 0 && shift
->properties
->allows_0
== 0)
4576 /* Reject a shift of 32 unless the mode allows it. */
4577 || (num
== 32 && shift
->properties
->allows_32
== 0)
4580 /* As a special case we allow a shift of zero for
4581 modes that do not support it to be recoded as an
4582 logical shift left of zero (ie nothing). We warn
4583 about this though. */
4586 as_warn (_("shift of 0 ignored."));
4587 shift
= & shift_names
[0];
4588 assert (shift
->properties
->index
== SHIFT_LSL
);
4592 inst
.error
= _("invalid immediate shift");
4597 /* Shifts of 32 are encoded as 0, for those shifts that
4602 inst
.instruction
|= (num
<< 7) | shift
->properties
->bit_field
;
4606 inst
.reloc
.type
= BFD_RELOC_ARM_SHIFT_IMM
;
4607 inst
.reloc
.pc_rel
= 0;
4608 inst
.instruction
|= shift
->properties
->bit_field
;
4615 /* Do those data_ops which can take a negative immediate constant
4616 by altering the instuction. A bit of a hack really.
4620 by inverting the second operand, and
4623 by negating the second operand. */
4626 negate_data_op (instruction
, value
)
4627 unsigned long * instruction
;
4628 unsigned long value
;
4631 unsigned long negated
, inverted
;
4633 negated
= validate_immediate (-value
);
4634 inverted
= validate_immediate (~value
);
4636 op
= (*instruction
>> DATA_OP_SHIFT
) & 0xf;
4639 /* First negates. */
4640 case OPCODE_SUB
: /* ADD <-> SUB */
4641 new_inst
= OPCODE_ADD
;
4646 new_inst
= OPCODE_SUB
;
4650 case OPCODE_CMP
: /* CMP <-> CMN */
4651 new_inst
= OPCODE_CMN
;
4656 new_inst
= OPCODE_CMP
;
4660 /* Now Inverted ops. */
4661 case OPCODE_MOV
: /* MOV <-> MVN */
4662 new_inst
= OPCODE_MVN
;
4667 new_inst
= OPCODE_MOV
;
4671 case OPCODE_AND
: /* AND <-> BIC */
4672 new_inst
= OPCODE_BIC
;
4677 new_inst
= OPCODE_AND
;
4681 case OPCODE_ADC
: /* ADC <-> SBC */
4682 new_inst
= OPCODE_SBC
;
4687 new_inst
= OPCODE_ADC
;
4691 /* We cannot do anything. */
4696 if (value
== (unsigned) FAIL
)
4699 *instruction
&= OPCODE_MASK
;
4700 *instruction
|= new_inst
<< DATA_OP_SHIFT
;
4711 skip_whitespace (* str
);
4713 if (reg_required_here (str
, 0) != FAIL
)
4715 if (skip_past_comma (str
) == SUCCESS
)
4716 /* Shift operation on register. */
4717 return decode_shift (str
, NO_SHIFT_RESTRICT
);
4723 /* Immediate expression. */
4724 if (is_immediate_prefix (**str
))
4729 if (my_get_expression (&inst
.reloc
.exp
, str
))
4732 if (inst
.reloc
.exp
.X_add_symbol
)
4734 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4735 inst
.reloc
.pc_rel
= 0;
4739 if (skip_past_comma (str
) == SUCCESS
)
4741 /* #x, y -- ie explicit rotation by Y. */
4742 if (my_get_expression (&expr
, str
))
4745 if (expr
.X_op
!= O_constant
)
4747 inst
.error
= _("constant expression expected");
4751 /* Rotate must be a multiple of 2. */
4752 if (((unsigned) expr
.X_add_number
) > 30
4753 || (expr
.X_add_number
& 1) != 0
4754 || ((unsigned) inst
.reloc
.exp
.X_add_number
) > 255)
4756 inst
.error
= _("invalid constant");
4759 inst
.instruction
|= INST_IMMEDIATE
;
4760 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
4761 inst
.instruction
|= expr
.X_add_number
<< 7;
4765 /* Implicit rotation, select a suitable one. */
4766 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
4770 /* Can't be done. Perhaps the code reads something like
4771 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK. */
4772 if ((value
= negate_data_op (&inst
.instruction
,
4773 inst
.reloc
.exp
.X_add_number
))
4776 inst
.error
= _("invalid constant");
4781 inst
.instruction
|= value
;
4784 inst
.instruction
|= INST_IMMEDIATE
;
4789 inst
.error
= _("register or shift expression expected");
4798 skip_whitespace (* str
);
4800 if (fp_reg_required_here (str
, 0) != FAIL
)
4804 /* Immediate expression. */
4805 if (*((*str
)++) == '#')
4811 skip_whitespace (* str
);
4813 /* First try and match exact strings, this is to guarantee
4814 that some formats will work even for cross assembly. */
4816 for (i
= 0; fp_const
[i
]; i
++)
4818 if (strncmp (*str
, fp_const
[i
], strlen (fp_const
[i
])) == 0)
4822 *str
+= strlen (fp_const
[i
]);
4823 if (is_end_of_line
[(unsigned char) **str
])
4825 inst
.instruction
|= i
+ 8;
4832 /* Just because we didn't get a match doesn't mean that the
4833 constant isn't valid, just that it is in a format that we
4834 don't automatically recognize. Try parsing it with
4835 the standard expression routines. */
4836 if ((i
= my_get_float_expression (str
)) >= 0)
4838 inst
.instruction
|= i
+ 8;
4842 inst
.error
= _("invalid floating point immediate expression");
4846 _("floating point register or immediate expression expected");
4855 skip_whitespace (str
);
4857 if (reg_required_here (&str
, 12) == FAIL
4858 || skip_past_comma (&str
) == FAIL
4859 || reg_required_here (&str
, 16) == FAIL
4860 || skip_past_comma (&str
) == FAIL
4861 || data_op2 (&str
) == FAIL
)
4864 inst
.error
= BAD_ARGS
;
4876 /* This is a pseudo-op of the form "adr rd, label" to be converted
4877 into a relative address of the form "add rd, pc, #label-.-8". */
4878 skip_whitespace (str
);
4880 if (reg_required_here (&str
, 12) == FAIL
4881 || skip_past_comma (&str
) == FAIL
4882 || my_get_expression (&inst
.reloc
.exp
, &str
))
4885 inst
.error
= BAD_ARGS
;
4889 /* Frag hacking will turn this into a sub instruction if the offset turns
4890 out to be negative. */
4891 inst
.reloc
.type
= BFD_RELOC_ARM_IMMEDIATE
;
4892 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust. */
4893 inst
.reloc
.pc_rel
= 1;
4902 /* This is a pseudo-op of the form "adrl rd, label" to be converted
4903 into a relative address of the form:
4904 add rd, pc, #low(label-.-8)"
4905 add rd, rd, #high(label-.-8)" */
4907 skip_whitespace (str
);
4909 if (reg_required_here (&str
, 12) == FAIL
4910 || skip_past_comma (&str
) == FAIL
4911 || my_get_expression (&inst
.reloc
.exp
, &str
))
4914 inst
.error
= BAD_ARGS
;
4920 /* Frag hacking will turn this into a sub instruction if the offset turns
4921 out to be negative. */
4922 inst
.reloc
.type
= BFD_RELOC_ARM_ADRL_IMMEDIATE
;
4923 inst
.reloc
.exp
.X_add_number
-= 8; /* PC relative adjust */
4924 inst
.reloc
.pc_rel
= 1;
4925 inst
.size
= INSN_SIZE
* 2;
4934 skip_whitespace (str
);
4936 if (reg_required_here (&str
, 16) == FAIL
)
4939 inst
.error
= BAD_ARGS
;
4943 if (skip_past_comma (&str
) == FAIL
4944 || data_op2 (&str
) == FAIL
)
4947 inst
.error
= BAD_ARGS
;
4959 skip_whitespace (str
);
4961 if (reg_required_here (&str
, 12) == FAIL
)
4964 inst
.error
= BAD_ARGS
;
4968 if (skip_past_comma (&str
) == FAIL
4969 || data_op2 (&str
) == FAIL
)
4972 inst
.error
= BAD_ARGS
;
4991 if (my_get_expression (& inst
.reloc
.exp
, str
))
4994 if (inst
.reloc
.exp
.X_op
== O_constant
)
4996 int value
= inst
.reloc
.exp
.X_add_number
;
4998 if (value
< -4095 || value
> 4095)
5000 inst
.error
= _("address offset too large");
5010 inst
.instruction
|= add
| value
;
5014 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5015 inst
.reloc
.pc_rel
= 0;
5028 if (reg_required_here (str
, 0) == FAIL
)
5031 inst
.instruction
|= add
| OFFSET_REG
;
5032 if (skip_past_comma (str
) == SUCCESS
)
5033 return decode_shift (str
, SHIFT_RESTRICT
);
5047 skip_whitespace (str
);
5049 if ((conflict_reg
= reg_required_here (&str
, 12)) == FAIL
)
5052 inst
.error
= BAD_ARGS
;
5056 if (skip_past_comma (&str
) == FAIL
)
5058 inst
.error
= _("address expected");
5068 skip_whitespace (str
);
5070 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5073 /* Conflicts can occur on stores as well as loads. */
5074 conflict_reg
= (conflict_reg
== reg
);
5076 skip_whitespace (str
);
5082 if (skip_past_comma (&str
) == SUCCESS
)
5084 /* [Rn],... (post inc) */
5085 if (ldst_extend (&str
) == FAIL
)
5088 as_warn (_("%s register same as write-back base"),
5089 ((inst
.instruction
& LOAD_BIT
)
5090 ? _("destination") : _("source")));
5095 skip_whitespace (str
);
5100 as_warn (_("%s register same as write-back base"),
5101 ((inst
.instruction
& LOAD_BIT
)
5102 ? _("destination") : _("source")));
5104 inst
.instruction
|= WRITE_BACK
;
5107 inst
.instruction
|= INDEX_UP
;
5114 if (skip_past_comma (&str
) == FAIL
)
5116 inst
.error
= _("pre-indexed expression expected");
5121 if (ldst_extend (&str
) == FAIL
)
5124 skip_whitespace (str
);
5128 inst
.error
= _("missing ]");
5132 skip_whitespace (str
);
5137 as_warn (_("%s register same as write-back base"),
5138 ((inst
.instruction
& LOAD_BIT
)
5139 ? _("destination") : _("source")));
5141 inst
.instruction
|= WRITE_BACK
;
5145 else if (*str
== '=')
5147 if ((inst
.instruction
& LOAD_BIT
) == 0)
5149 inst
.error
= _("invalid pseudo operation");
5153 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5156 skip_whitespace (str
);
5158 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5161 if (inst
.reloc
.exp
.X_op
!= O_constant
5162 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5164 inst
.error
= _("constant expression expected");
5168 if (inst
.reloc
.exp
.X_op
== O_constant
)
5170 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5174 /* This can be done with a mov instruction. */
5175 inst
.instruction
&= LITERAL_MASK
;
5176 inst
.instruction
|= (INST_IMMEDIATE
5177 | (OPCODE_MOV
<< DATA_OP_SHIFT
));
5178 inst
.instruction
|= value
& 0xfff;
5183 value
= validate_immediate (~inst
.reloc
.exp
.X_add_number
);
5187 /* This can be done with a mvn instruction. */
5188 inst
.instruction
&= LITERAL_MASK
;
5189 inst
.instruction
|= (INST_IMMEDIATE
5190 | (OPCODE_MVN
<< DATA_OP_SHIFT
));
5191 inst
.instruction
|= value
& 0xfff;
5197 /* Insert into literal pool. */
5198 if (add_to_lit_pool () == FAIL
)
5201 inst
.error
= _("literal pool insertion failed");
5205 /* Change the instruction exp to point to the pool. */
5206 inst
.reloc
.type
= BFD_RELOC_ARM_LITERAL
;
5207 inst
.reloc
.pc_rel
= 1;
5208 inst
.instruction
|= (REG_PC
<< 16);
5213 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5216 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM
;
5218 /* PC rel adjust. */
5219 inst
.reloc
.exp
.X_add_number
-= 8;
5221 inst
.reloc
.pc_rel
= 1;
5222 inst
.instruction
|= (REG_PC
<< 16);
5226 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5237 skip_whitespace (str
);
5239 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5242 inst
.error
= BAD_ARGS
;
5246 if (skip_past_comma (& str
) == FAIL
)
5248 inst
.error
= _("address expected");
5258 skip_whitespace (str
);
5260 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5263 /* ldrt/strt always use post-indexed addressing, so if the base is
5264 the same as Rd, we warn. */
5265 if (conflict_reg
== reg
)
5266 as_warn (_("%s register same as write-back base"),
5267 ((inst
.instruction
& LOAD_BIT
)
5268 ? _("destination") : _("source")));
5270 skip_whitespace (str
);
5276 if (skip_past_comma (&str
) == SUCCESS
)
5278 /* [Rn],... (post inc) */
5279 if (ldst_extend (&str
) == FAIL
)
5285 skip_whitespace (str
);
5287 /* Skip a write-back '!'. */
5291 inst
.instruction
|= INDEX_UP
;
5296 inst
.error
= _("post-indexed expression expected");
5302 inst
.error
= _("post-indexed expression expected");
5311 ldst_extend_v4 (str
)
5321 if (my_get_expression (& inst
.reloc
.exp
, str
))
5324 if (inst
.reloc
.exp
.X_op
== O_constant
)
5326 int value
= inst
.reloc
.exp
.X_add_number
;
5328 if (value
< -255 || value
> 255)
5330 inst
.error
= _("address offset too large");
5340 /* Halfword and signextension instructions have the
5341 immediate value split across bits 11..8 and bits 3..0. */
5342 inst
.instruction
|= (add
| HWOFFSET_IMM
5343 | ((value
>> 4) << 8) | (value
& 0xF));
5347 inst
.instruction
|= HWOFFSET_IMM
;
5348 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5349 inst
.reloc
.pc_rel
= 0;
5362 if (reg_required_here (str
, 0) == FAIL
)
5365 inst
.instruction
|= add
;
5370 /* Halfword and signed-byte load/store operations. */
5379 skip_whitespace (str
);
5381 if ((conflict_reg
= reg_required_here (& str
, 12)) == FAIL
)
5384 inst
.error
= BAD_ARGS
;
5388 if (skip_past_comma (& str
) == FAIL
)
5390 inst
.error
= _("address expected");
5400 skip_whitespace (str
);
5402 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5405 /* Conflicts can occur on stores as well as loads. */
5406 conflict_reg
= (conflict_reg
== reg
);
5408 skip_whitespace (str
);
5414 if (skip_past_comma (&str
) == SUCCESS
)
5416 /* [Rn],... (post inc) */
5417 if (ldst_extend_v4 (&str
) == FAIL
)
5420 as_warn (_("%s register same as write-back base"),
5421 ((inst
.instruction
& LOAD_BIT
)
5422 ? _("destination") : _("source")));
5427 inst
.instruction
|= HWOFFSET_IMM
;
5429 skip_whitespace (str
);
5434 as_warn (_("%s register same as write-back base"),
5435 ((inst
.instruction
& LOAD_BIT
)
5436 ? _("destination") : _("source")));
5438 inst
.instruction
|= WRITE_BACK
;
5441 inst
.instruction
|= INDEX_UP
;
5448 if (skip_past_comma (&str
) == FAIL
)
5450 inst
.error
= _("pre-indexed expression expected");
5455 if (ldst_extend_v4 (&str
) == FAIL
)
5458 skip_whitespace (str
);
5462 inst
.error
= _("missing ]");
5466 skip_whitespace (str
);
5471 as_warn (_("%s register same as write-back base"),
5472 ((inst
.instruction
& LOAD_BIT
)
5473 ? _("destination") : _("source")));
5475 inst
.instruction
|= WRITE_BACK
;
5479 else if (*str
== '=')
5481 if ((inst
.instruction
& LOAD_BIT
) == 0)
5483 inst
.error
= _("invalid pseudo operation");
5487 /* XXX Does this work correctly for half-word/byte ops? */
5488 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
5491 skip_whitespace (str
);
5493 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5496 if (inst
.reloc
.exp
.X_op
!= O_constant
5497 && inst
.reloc
.exp
.X_op
!= O_symbol
)
5499 inst
.error
= _("constant expression expected");
5503 if (inst
.reloc
.exp
.X_op
== O_constant
)
5505 value
= validate_immediate (inst
.reloc
.exp
.X_add_number
);
5509 /* This can be done with a mov instruction. */
5510 inst
.instruction
&= LITERAL_MASK
;
5511 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MOV
<< DATA_OP_SHIFT
);
5512 inst
.instruction
|= value
& 0xfff;
5517 value
= validate_immediate (~ inst
.reloc
.exp
.X_add_number
);
5521 /* This can be done with a mvn instruction. */
5522 inst
.instruction
&= LITERAL_MASK
;
5523 inst
.instruction
|= INST_IMMEDIATE
| (OPCODE_MVN
<< DATA_OP_SHIFT
);
5524 inst
.instruction
|= value
& 0xfff;
5530 /* Insert into literal pool. */
5531 if (add_to_lit_pool () == FAIL
)
5534 inst
.error
= _("literal pool insertion failed");
5538 /* Change the instruction exp to point to the pool. */
5539 inst
.instruction
|= HWOFFSET_IMM
;
5540 inst
.reloc
.type
= BFD_RELOC_ARM_HWLITERAL
;
5541 inst
.reloc
.pc_rel
= 1;
5542 inst
.instruction
|= (REG_PC
<< 16);
5547 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5550 inst
.instruction
|= HWOFFSET_IMM
;
5551 inst
.reloc
.type
= BFD_RELOC_ARM_OFFSET_IMM8
;
5553 /* PC rel adjust. */
5554 inst
.reloc
.exp
.X_add_number
-= 8;
5556 inst
.reloc
.pc_rel
= 1;
5557 inst
.instruction
|= (REG_PC
<< 16);
5561 inst
.instruction
|= (pre_inc
? PRE_INDEX
: 0);
5570 char * str
= * strp
;
5574 /* We come back here if we get ranges concatenated by '+' or '|'. */
5589 skip_whitespace (str
);
5591 if ((reg
= reg_required_here (& str
, -1)) == FAIL
)
5600 inst
.error
= _("bad range in register list");
5604 for (i
= cur_reg
+ 1; i
< reg
; i
++)
5606 if (range
& (1 << i
))
5608 (_("Warning: duplicated register (r%d) in register list"),
5616 if (range
& (1 << reg
))
5617 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
5619 else if (reg
<= cur_reg
)
5620 as_tsktsk (_("Warning: register range not in ascending order"));
5625 while (skip_past_comma (&str
) != FAIL
5626 || (in_range
= 1, *str
++ == '-'));
5628 skip_whitespace (str
);
5632 inst
.error
= _("missing `}'");
5640 if (my_get_expression (&expr
, &str
))
5643 if (expr
.X_op
== O_constant
)
5645 if (expr
.X_add_number
5646 != (expr
.X_add_number
& 0x0000ffff))
5648 inst
.error
= _("invalid register mask");
5652 if ((range
& expr
.X_add_number
) != 0)
5654 int regno
= range
& expr
.X_add_number
;
5657 regno
= (1 << regno
) - 1;
5659 (_("Warning: duplicated register (r%d) in register list"),
5663 range
|= expr
.X_add_number
;
5667 if (inst
.reloc
.type
!= 0)
5669 inst
.error
= _("expression too complex");
5673 memcpy (&inst
.reloc
.exp
, &expr
, sizeof (expressionS
));
5674 inst
.reloc
.type
= BFD_RELOC_ARM_MULTI
;
5675 inst
.reloc
.pc_rel
= 0;
5679 skip_whitespace (str
);
5681 if (*str
== '|' || *str
== '+')
5687 while (another_range
);
5700 skip_whitespace (str
);
5702 if ((base_reg
= reg_required_here (&str
, 16)) == FAIL
)
5705 if (base_reg
== REG_PC
)
5707 inst
.error
= _("r15 not allowed as base register");
5711 skip_whitespace (str
);
5715 inst
.instruction
|= WRITE_BACK
;
5719 if (skip_past_comma (&str
) == FAIL
5720 || (range
= reg_list (&str
)) == FAIL
)
5723 inst
.error
= BAD_ARGS
;
5730 inst
.instruction
|= LDM_TYPE_2_OR_3
;
5733 inst
.instruction
|= range
;
5742 skip_whitespace (str
);
5744 /* Allow optional leading '#'. */
5745 if (is_immediate_prefix (*str
))
5748 if (my_get_expression (& inst
.reloc
.exp
, & str
))
5751 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
5752 inst
.reloc
.pc_rel
= 0;
5764 skip_whitespace (str
);
5766 if ((reg
= reg_required_here (&str
, 12)) == FAIL
)
5771 inst
.error
= _("r15 not allowed in swap");
5775 if (skip_past_comma (&str
) == FAIL
5776 || (reg
= reg_required_here (&str
, 0)) == FAIL
)
5779 inst
.error
= BAD_ARGS
;
5785 inst
.error
= _("r15 not allowed in swap");
5789 if (skip_past_comma (&str
) == FAIL
5792 inst
.error
= BAD_ARGS
;
5796 skip_whitespace (str
);
5798 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
5803 inst
.error
= BAD_PC
;
5807 skip_whitespace (str
);
5811 inst
.error
= _("missing ]");
5823 if (my_get_expression (&inst
.reloc
.exp
, &str
))
5830 /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
5831 required for the instruction. */
5833 /* arm_parse_reloc () works on input_line_pointer.
5834 We actually want to parse the operands to the branch instruction
5835 passed in 'str'. Save the input pointer and restore it later. */
5836 save_in
= input_line_pointer
;
5837 input_line_pointer
= str
;
5838 if (inst
.reloc
.exp
.X_op
== O_symbol
5840 && arm_parse_reloc () == BFD_RELOC_ARM_PLT32
)
5842 inst
.reloc
.type
= BFD_RELOC_ARM_PLT32
;
5843 inst
.reloc
.pc_rel
= 0;
5844 /* Modify str to point to after parsed operands, otherwise
5845 end_of_line() will complain about the (PLT) left in str. */
5846 str
= input_line_pointer
;
5850 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5851 inst
.reloc
.pc_rel
= 1;
5853 input_line_pointer
= save_in
;
5856 inst
.reloc
.type
= BFD_RELOC_ARM_PCREL_BRANCH
;
5857 inst
.reloc
.pc_rel
= 1;
5858 #endif /* OBJ_ELF */
5870 skip_whitespace (str
);
5872 if ((reg
= reg_required_here (&str
, 0)) == FAIL
)
5874 inst
.error
= BAD_ARGS
;
5878 /* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
5880 as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
5889 /* Co-processor data operation.
5890 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
5891 skip_whitespace (str
);
5893 if (co_proc_number (&str
) == FAIL
)
5896 inst
.error
= BAD_ARGS
;
5900 if (skip_past_comma (&str
) == FAIL
5901 || cp_opc_expr (&str
, 20,4) == FAIL
)
5904 inst
.error
= BAD_ARGS
;
5908 if (skip_past_comma (&str
) == FAIL
5909 || cp_reg_required_here (&str
, 12) == FAIL
)
5912 inst
.error
= BAD_ARGS
;
5916 if (skip_past_comma (&str
) == FAIL
5917 || cp_reg_required_here (&str
, 16) == FAIL
)
5920 inst
.error
= BAD_ARGS
;
5924 if (skip_past_comma (&str
) == FAIL
5925 || cp_reg_required_here (&str
, 0) == FAIL
)
5928 inst
.error
= BAD_ARGS
;
5932 if (skip_past_comma (&str
) == SUCCESS
)
5934 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
5937 inst
.error
= BAD_ARGS
;
5950 /* Co-processor register load/store.
5951 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
5953 skip_whitespace (str
);
5955 if (co_proc_number (&str
) == FAIL
)
5958 inst
.error
= BAD_ARGS
;
5962 if (skip_past_comma (&str
) == FAIL
5963 || cp_reg_required_here (&str
, 12) == FAIL
)
5966 inst
.error
= BAD_ARGS
;
5970 if (skip_past_comma (&str
) == FAIL
5971 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
5974 inst
.error
= BAD_ARGS
;
5986 /* Co-processor register transfer.
5987 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
5989 skip_whitespace (str
);
5991 if (co_proc_number (&str
) == FAIL
)
5994 inst
.error
= BAD_ARGS
;
5998 if (skip_past_comma (&str
) == FAIL
5999 || cp_opc_expr (&str
, 21, 3) == FAIL
)
6002 inst
.error
= BAD_ARGS
;
6006 if (skip_past_comma (&str
) == FAIL
6007 || reg_required_here (&str
, 12) == FAIL
)
6010 inst
.error
= BAD_ARGS
;
6014 if (skip_past_comma (&str
) == FAIL
6015 || cp_reg_required_here (&str
, 16) == FAIL
)
6018 inst
.error
= BAD_ARGS
;
6022 if (skip_past_comma (&str
) == FAIL
6023 || cp_reg_required_here (&str
, 0) == FAIL
)
6026 inst
.error
= BAD_ARGS
;
6030 if (skip_past_comma (&str
) == SUCCESS
)
6032 if (cp_opc_expr (&str
, 5, 3) == FAIL
)
6035 inst
.error
= BAD_ARGS
;
6048 /* FP control registers.
6049 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
6051 skip_whitespace (str
);
6053 if (reg_required_here (&str
, 12) == FAIL
)
6056 inst
.error
= BAD_ARGS
;
6068 skip_whitespace (str
);
6070 if (fp_reg_required_here (&str
, 12) == FAIL
)
6073 inst
.error
= BAD_ARGS
;
6077 if (skip_past_comma (&str
) == FAIL
6078 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6081 inst
.error
= BAD_ARGS
;
6094 skip_whitespace (str
);
6096 if (fp_reg_required_here (&str
, 12) == FAIL
)
6099 inst
.error
= BAD_ARGS
;
6103 /* Get Number of registers to transfer. */
6104 if (skip_past_comma (&str
) == FAIL
6105 || my_get_expression (&inst
.reloc
.exp
, &str
))
6108 inst
.error
= _("constant expression expected");
6112 if (inst
.reloc
.exp
.X_op
!= O_constant
)
6114 inst
.error
= _("constant value required for number of registers");
6118 num_regs
= inst
.reloc
.exp
.X_add_number
;
6120 if (num_regs
< 1 || num_regs
> 4)
6122 inst
.error
= _("number of registers must be in the range [1:4]");
6129 inst
.instruction
|= CP_T_X
;
6132 inst
.instruction
|= CP_T_Y
;
6135 inst
.instruction
|= CP_T_Y
| CP_T_X
;
6143 if (inst
.instruction
& (CP_T_Pre
| CP_T_UD
)) /* ea/fd format. */
6149 /* The instruction specified "ea" or "fd", so we can only accept
6150 [Rn]{!}. The instruction does not really support stacking or
6151 unstacking, so we have to emulate these by setting appropriate
6152 bits and offsets. */
6153 if (skip_past_comma (&str
) == FAIL
6157 inst
.error
= BAD_ARGS
;
6162 skip_whitespace (str
);
6164 if ((reg
= reg_required_here (&str
, 16)) == FAIL
)
6167 skip_whitespace (str
);
6171 inst
.error
= BAD_ARGS
;
6183 _("r15 not allowed as base register with write-back");
6190 if (inst
.instruction
& CP_T_Pre
)
6192 /* Pre-decrement. */
6193 offset
= 3 * num_regs
;
6195 inst
.instruction
|= CP_T_WB
;
6199 /* Post-increment. */
6202 inst
.instruction
|= CP_T_WB
;
6203 offset
= 3 * num_regs
;
6207 /* No write-back, so convert this into a standard pre-increment
6208 instruction -- aesthetically more pleasing. */
6209 inst
.instruction
|= CP_T_Pre
| CP_T_UD
;
6214 inst
.instruction
|= offset
;
6216 else if (skip_past_comma (&str
) == FAIL
6217 || cp_address_required_here (&str
, CP_WB_OK
) == FAIL
)
6220 inst
.error
= BAD_ARGS
;
6231 skip_whitespace (str
);
6233 if (fp_reg_required_here (&str
, 12) == FAIL
)
6236 inst
.error
= BAD_ARGS
;
6240 if (skip_past_comma (&str
) == FAIL
6241 || fp_reg_required_here (&str
, 16) == FAIL
)
6244 inst
.error
= BAD_ARGS
;
6248 if (skip_past_comma (&str
) == FAIL
6249 || fp_op2 (&str
) == FAIL
)
6252 inst
.error
= BAD_ARGS
;
6261 do_fpa_monadic (str
)
6264 skip_whitespace (str
);
6266 if (fp_reg_required_here (&str
, 12) == FAIL
)
6269 inst
.error
= BAD_ARGS
;
6273 if (skip_past_comma (&str
) == FAIL
6274 || fp_op2 (&str
) == FAIL
)
6277 inst
.error
= BAD_ARGS
;
6289 skip_whitespace (str
);
6291 if (fp_reg_required_here (&str
, 16) == FAIL
)
6294 inst
.error
= BAD_ARGS
;
6298 if (skip_past_comma (&str
) == FAIL
6299 || fp_op2 (&str
) == FAIL
)
6302 inst
.error
= BAD_ARGS
;
6311 do_fpa_from_reg (str
)
6314 skip_whitespace (str
);
6316 if (fp_reg_required_here (&str
, 16) == FAIL
)
6319 inst
.error
= BAD_ARGS
;
6323 if (skip_past_comma (&str
) == FAIL
6324 || reg_required_here (&str
, 12) == FAIL
)
6327 inst
.error
= BAD_ARGS
;
6339 skip_whitespace (str
);
6341 if (reg_required_here (&str
, 12) == FAIL
)
6344 if (skip_past_comma (&str
) == FAIL
6345 || fp_reg_required_here (&str
, 0) == FAIL
)
6348 inst
.error
= BAD_ARGS
;
6357 vfp_sp_reg_required_here (str
, pos
)
6359 enum vfp_sp_reg_pos pos
;
6364 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
)) != FAIL
)
6369 inst
.instruction
|= ((reg
>> 1) << 12) | ((reg
& 1) << 22);
6373 inst
.instruction
|= ((reg
>> 1) << 16) | ((reg
& 1) << 7);
6377 inst
.instruction
|= ((reg
>> 1) << 0) | ((reg
& 1) << 5);
6386 /* In the few cases where we might be able to accept something else
6387 this error can be overridden. */
6388 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
6390 /* Restore the start point. */
6396 vfp_dp_reg_required_here (str
, pos
)
6398 enum vfp_sp_reg_pos pos
;
6403 if ((reg
= arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
)) != FAIL
)
6408 inst
.instruction
|= reg
<< 12;
6412 inst
.instruction
|= reg
<< 16;
6416 inst
.instruction
|= reg
<< 0;
6425 /* In the few cases where we might be able to accept something else
6426 this error can be overridden. */
6427 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
6429 /* Restore the start point. */
6435 do_vfp_sp_monadic (str
)
6438 skip_whitespace (str
);
6440 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6443 if (skip_past_comma (&str
) == FAIL
6444 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
6447 inst
.error
= BAD_ARGS
;
6456 do_vfp_dp_monadic (str
)
6459 skip_whitespace (str
);
6461 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6464 if (skip_past_comma (&str
) == FAIL
6465 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6468 inst
.error
= BAD_ARGS
;
6477 do_vfp_sp_dyadic (str
)
6480 skip_whitespace (str
);
6482 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6485 if (skip_past_comma (&str
) == FAIL
6486 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
6487 || skip_past_comma (&str
) == FAIL
6488 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
6491 inst
.error
= BAD_ARGS
;
6500 do_vfp_dp_dyadic (str
)
6503 skip_whitespace (str
);
6505 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6508 if (skip_past_comma (&str
) == FAIL
6509 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
6510 || skip_past_comma (&str
) == FAIL
6511 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6514 inst
.error
= BAD_ARGS
;
6523 do_vfp_reg_from_sp (str
)
6526 skip_whitespace (str
);
6528 if (reg_required_here (&str
, 12) == FAIL
)
6531 if (skip_past_comma (&str
) == FAIL
6532 || vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
6535 inst
.error
= BAD_ARGS
;
6544 do_vfp_sp_reg2 (str
)
6547 skip_whitespace (str
);
6549 if (reg_required_here (&str
, 12) == FAIL
)
6552 if (skip_past_comma (&str
) == FAIL
6553 || reg_required_here (&str
, 16) == FAIL
6554 || skip_past_comma (&str
) == FAIL
)
6557 inst
.error
= BAD_ARGS
;
6561 /* We require exactly two consecutive SP registers. */
6562 if (vfp_sp_reg_list (&str
, VFP_REG_Sm
) != 2)
6565 inst
.error
= _("only two consecutive VFP SP registers allowed here");
6573 do_vfp_sp_from_reg (str
)
6576 skip_whitespace (str
);
6578 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sn
) == FAIL
)
6581 if (skip_past_comma (&str
) == FAIL
6582 || reg_required_here (&str
, 12) == FAIL
)
6585 inst
.error
= BAD_ARGS
;
6594 do_vfp_reg_from_dp (str
)
6597 skip_whitespace (str
);
6599 if (reg_required_here (&str
, 12) == FAIL
)
6602 if (skip_past_comma (&str
) == FAIL
6603 || vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
6606 inst
.error
= BAD_ARGS
;
6615 do_vfp_reg2_from_dp (str
)
6618 skip_whitespace (str
);
6620 if (reg_required_here (&str
, 12) == FAIL
)
6623 if (skip_past_comma (&str
) == FAIL
6624 || reg_required_here (&str
, 16) == FAIL
6625 || skip_past_comma (&str
) == FAIL
6626 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6629 inst
.error
= BAD_ARGS
;
6638 do_vfp_dp_from_reg (str
)
6641 skip_whitespace (str
);
6643 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dn
) == FAIL
)
6646 if (skip_past_comma (&str
) == FAIL
6647 || reg_required_here (&str
, 12) == FAIL
)
6650 inst
.error
= BAD_ARGS
;
6659 do_vfp_dp_from_reg2 (str
)
6662 skip_whitespace (str
);
6664 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
6667 if (skip_past_comma (&str
) == FAIL
6668 || reg_required_here (&str
, 12) == FAIL
6669 || skip_past_comma (&str
) == FAIL
6670 || reg_required_here (&str
, 16))
6673 inst
.error
= BAD_ARGS
;
6681 static const struct vfp_reg
*
6688 const struct vfp_reg
*vreg
;
6692 /* Find the end of the current token. */
6697 while (ISALPHA (c
));
6702 for (vreg
= vfp_regs
+ 0;
6703 vreg
< vfp_regs
+ sizeof (vfp_regs
) / sizeof (struct vfp_reg
);
6706 if (strcmp (start
, vreg
->name
) == 0)
6719 vfp_psr_required_here (str
)
6723 const struct vfp_reg
*vreg
;
6725 vreg
= vfp_psr_parse (str
);
6729 inst
.instruction
|= vreg
->regno
;
6733 inst
.error
= _("VFP system register expected");
6740 do_vfp_reg_from_ctrl (str
)
6743 skip_whitespace (str
);
6745 if (reg_required_here (&str
, 12) == FAIL
)
6748 if (skip_past_comma (&str
) == FAIL
6749 || vfp_psr_required_here (&str
) == FAIL
)
6752 inst
.error
= BAD_ARGS
;
6761 do_vfp_ctrl_from_reg (str
)
6764 skip_whitespace (str
);
6766 if (vfp_psr_required_here (&str
) == FAIL
)
6769 if (skip_past_comma (&str
) == FAIL
6770 || reg_required_here (&str
, 12) == FAIL
)
6773 inst
.error
= BAD_ARGS
;
6782 do_vfp_sp_ldst (str
)
6785 skip_whitespace (str
);
6787 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
6790 inst
.error
= BAD_ARGS
;
6794 if (skip_past_comma (&str
) == FAIL
6795 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
6798 inst
.error
= BAD_ARGS
;
6807 do_vfp_dp_ldst (str
)
6810 skip_whitespace (str
);
6812 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
6815 inst
.error
= BAD_ARGS
;
6819 if (skip_past_comma (&str
) == FAIL
6820 || cp_address_required_here (&str
, CP_NO_WB
) == FAIL
)
6823 inst
.error
= BAD_ARGS
;
6831 /* Parse and encode a VFP SP register list, storing the initial
6832 register in position POS and returning the range as the result. If
6833 the string is invalid return FAIL (an invalid range). */
6835 vfp_sp_reg_list (str
, pos
)
6837 enum vfp_sp_reg_pos pos
;
6845 unsigned long mask
= 0;
6852 skip_whitespace (*str
);
6854 tempinst
= inst
.instruction
;
6858 inst
.instruction
= 0;
6860 if ((new_base
= vfp_sp_reg_required_here (str
, pos
)) == FAIL
)
6863 if (count
== 0 || base_reg
> new_base
)
6865 base_reg
= new_base
;
6866 base_bits
= inst
.instruction
;
6869 if (mask
& (1 << new_base
))
6871 inst
.error
= _("invalid register list");
6875 if ((mask
>> new_base
) != 0 && ! warned
)
6877 as_tsktsk (_("register list not in ascending order"));
6881 mask
|= 1 << new_base
;
6884 skip_whitespace (*str
);
6886 if (**str
== '-') /* We have the start of a range expression */
6893 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_SN
].htab
))
6896 inst
.error
= _(all_reg_maps
[REG_TYPE_SN
].expected
);
6900 if (high_range
<= new_base
)
6902 inst
.error
= _("register range not in ascending order");
6906 for (new_base
++; new_base
<= high_range
; new_base
++)
6908 if (mask
& (1 << new_base
))
6910 inst
.error
= _("invalid register list");
6914 mask
|= 1 << new_base
;
6919 while (skip_past_comma (str
) != FAIL
);
6923 inst
.error
= _("invalid register list");
6931 /* Sanity check -- should have raised a parse error above. */
6932 if (count
== 0 || count
> 32)
6935 /* Final test -- the registers must be consecutive. */
6938 if ((mask
& (1 << base_reg
++)) == 0)
6940 inst
.error
= _("non-contiguous register range");
6945 inst
.instruction
= tempinst
| base_bits
;
6950 vfp_dp_reg_list (str
)
6958 unsigned long mask
= 0;
6965 skip_whitespace (*str
);
6967 tempinst
= inst
.instruction
;
6971 inst
.instruction
= 0;
6973 if ((new_base
= vfp_dp_reg_required_here (str
, VFP_REG_Dd
)) == FAIL
)
6976 if (count
== 0 || base_reg
> new_base
)
6978 base_reg
= new_base
;
6979 range
= inst
.instruction
;
6982 if (mask
& (1 << new_base
))
6984 inst
.error
= _("invalid register list");
6988 if ((mask
>> new_base
) != 0 && ! warned
)
6990 as_tsktsk (_("register list not in ascending order"));
6994 mask
|= 1 << new_base
;
6997 skip_whitespace (*str
);
6999 if (**str
== '-') /* We have the start of a range expression */
7006 = arm_reg_parse (str
, all_reg_maps
[REG_TYPE_DN
].htab
))
7009 inst
.error
= _(all_reg_maps
[REG_TYPE_DN
].expected
);
7013 if (high_range
<= new_base
)
7015 inst
.error
= _("register range not in ascending order");
7019 for (new_base
++; new_base
<= high_range
; new_base
++)
7021 if (mask
& (1 << new_base
))
7023 inst
.error
= _("invalid register list");
7027 mask
|= 1 << new_base
;
7032 while (skip_past_comma (str
) != FAIL
);
7036 inst
.error
= _("invalid register list");
7044 /* Sanity check -- should have raised a parse error above. */
7045 if (count
== 0 || count
> 16)
7048 /* Final test -- the registers must be consecutive. */
7051 if ((mask
& (1 << base_reg
++)) == 0)
7053 inst
.error
= _("non-contiguous register range");
7058 inst
.instruction
= tempinst
;
7063 vfp_sp_ldstm(str
, ldstm_type
)
7065 enum vfp_ldstm_type ldstm_type
;
7069 skip_whitespace (str
);
7071 if (reg_required_here (&str
, 16) == FAIL
)
7074 skip_whitespace (str
);
7078 inst
.instruction
|= WRITE_BACK
;
7081 else if (ldstm_type
!= VFP_LDSTMIA
)
7083 inst
.error
= _("this addressing mode requires base-register writeback");
7087 if (skip_past_comma (&str
) == FAIL
7088 || (range
= vfp_sp_reg_list (&str
, VFP_REG_Sd
)) == FAIL
)
7091 inst
.error
= BAD_ARGS
;
7095 inst
.instruction
|= range
;
7100 vfp_dp_ldstm(str
, ldstm_type
)
7102 enum vfp_ldstm_type ldstm_type
;
7106 skip_whitespace (str
);
7108 if (reg_required_here (&str
, 16) == FAIL
)
7111 skip_whitespace (str
);
7115 inst
.instruction
|= WRITE_BACK
;
7118 else if (ldstm_type
!= VFP_LDSTMIA
&& ldstm_type
!= VFP_LDSTMIAX
)
7120 inst
.error
= _("this addressing mode requires base-register writeback");
7124 if (skip_past_comma (&str
) == FAIL
7125 || (range
= vfp_dp_reg_list (&str
)) == FAIL
)
7128 inst
.error
= BAD_ARGS
;
7132 if (ldstm_type
== VFP_LDSTMIAX
|| ldstm_type
== VFP_LDSTMDBX
)
7135 inst
.instruction
|= range
;
7140 do_vfp_sp_ldstmia (str
)
7143 vfp_sp_ldstm (str
, VFP_LDSTMIA
);
7147 do_vfp_sp_ldstmdb (str
)
7150 vfp_sp_ldstm (str
, VFP_LDSTMDB
);
7154 do_vfp_dp_ldstmia (str
)
7157 vfp_dp_ldstm (str
, VFP_LDSTMIA
);
7161 do_vfp_dp_ldstmdb (str
)
7164 vfp_dp_ldstm (str
, VFP_LDSTMDB
);
7168 do_vfp_xp_ldstmia (str
)
7171 vfp_dp_ldstm (str
, VFP_LDSTMIAX
);
7175 do_vfp_xp_ldstmdb (str
)
7178 vfp_dp_ldstm (str
, VFP_LDSTMDBX
);
7182 do_vfp_sp_compare_z (str
)
7185 skip_whitespace (str
);
7187 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7190 inst
.error
= BAD_ARGS
;
7199 do_vfp_dp_compare_z (str
)
7202 skip_whitespace (str
);
7204 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7207 inst
.error
= BAD_ARGS
;
7216 do_vfp_dp_sp_cvt (str
)
7219 skip_whitespace (str
);
7221 if (vfp_dp_reg_required_here (&str
, VFP_REG_Dd
) == FAIL
)
7224 if (skip_past_comma (&str
) == FAIL
7225 || vfp_sp_reg_required_here (&str
, VFP_REG_Sm
) == FAIL
)
7228 inst
.error
= BAD_ARGS
;
7237 do_vfp_sp_dp_cvt (str
)
7240 skip_whitespace (str
);
7242 if (vfp_sp_reg_required_here (&str
, VFP_REG_Sd
) == FAIL
)
7245 if (skip_past_comma (&str
) == FAIL
7246 || vfp_dp_reg_required_here (&str
, VFP_REG_Dm
) == FAIL
)
7249 inst
.error
= BAD_ARGS
;
7257 /* Thumb specific routines. */
7259 /* Parse and validate that a register is of the right form, this saves
7260 repeated checking of this information in many similar cases.
7261 Unlike the 32-bit case we do not insert the register into the opcode
7262 here, since the position is often unknown until the full instruction
7266 thumb_reg (strp
, hi_lo
)
7272 if ((reg
= reg_required_here (strp
, -1)) == FAIL
)
7280 inst
.error
= _("lo register required");
7288 inst
.error
= _("hi register required");
7300 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
7304 thumb_add_sub (str
, subtract
)
7308 int Rd
, Rs
, Rn
= FAIL
;
7310 skip_whitespace (str
);
7312 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
7313 || skip_past_comma (&str
) == FAIL
)
7316 inst
.error
= BAD_ARGS
;
7320 if (is_immediate_prefix (*str
))
7324 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7329 if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7332 if (skip_past_comma (&str
) == FAIL
)
7334 /* Two operand format, shuffle the registers
7335 and pretend there are 3. */
7339 else if (is_immediate_prefix (*str
))
7342 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7345 else if ((Rn
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7349 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7350 for the latter case, EXPR contains the immediate that was found. */
7353 /* All register format. */
7354 if (Rd
> 7 || Rs
> 7 || Rn
> 7)
7358 inst
.error
= _("dest and source1 must be the same register");
7362 /* Can't do this for SUB. */
7365 inst
.error
= _("subtract valid only on lo regs");
7369 inst
.instruction
= (T_OPCODE_ADD_HI
7370 | (Rd
> 7 ? THUMB_H1
: 0)
7371 | (Rn
> 7 ? THUMB_H2
: 0));
7372 inst
.instruction
|= (Rd
& 7) | ((Rn
& 7) << 3);
7376 inst
.instruction
= subtract
? T_OPCODE_SUB_R3
: T_OPCODE_ADD_R3
;
7377 inst
.instruction
|= Rd
| (Rs
<< 3) | (Rn
<< 6);
7382 /* Immediate expression, now things start to get nasty. */
7384 /* First deal with HI regs, only very restricted cases allowed:
7385 Adjusting SP, and using PC or SP to get an address. */
7386 if ((Rd
> 7 && (Rd
!= REG_SP
|| Rs
!= REG_SP
))
7387 || (Rs
> 7 && Rs
!= REG_SP
&& Rs
!= REG_PC
))
7389 inst
.error
= _("invalid Hi register with immediate");
7393 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7395 /* Value isn't known yet, all we can do is store all the fragments
7396 we know about in the instruction and let the reloc hacking
7398 inst
.instruction
= (subtract
? 0x8000 : 0) | (Rd
<< 4) | Rs
;
7399 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
7403 int offset
= inst
.reloc
.exp
.X_add_number
;
7413 /* Quick check, in case offset is MIN_INT. */
7416 inst
.error
= _("immediate value out of range");
7425 if (offset
& ~0x1fc)
7427 inst
.error
= _("invalid immediate value for stack adjust");
7430 inst
.instruction
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
7431 inst
.instruction
|= offset
>> 2;
7433 else if (Rs
== REG_PC
|| Rs
== REG_SP
)
7436 || (offset
& ~0x3fc))
7438 inst
.error
= _("invalid immediate for address calculation");
7441 inst
.instruction
= (Rs
== REG_PC
? T_OPCODE_ADD_PC
7443 inst
.instruction
|= (Rd
<< 8) | (offset
>> 2);
7449 inst
.error
= _("immediate value out of range");
7452 inst
.instruction
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
7453 inst
.instruction
|= (Rd
<< 8) | offset
;
7459 inst
.error
= _("immediate value out of range");
7462 inst
.instruction
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
7463 inst
.instruction
|= Rd
| (Rs
<< 3) | (offset
<< 6);
7472 thumb_shift (str
, shift
)
7476 int Rd
, Rs
, Rn
= FAIL
;
7478 skip_whitespace (str
);
7480 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7481 || skip_past_comma (&str
) == FAIL
)
7484 inst
.error
= BAD_ARGS
;
7488 if (is_immediate_prefix (*str
))
7490 /* Two operand immediate format, set Rs to Rd. */
7493 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7498 if ((Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7501 if (skip_past_comma (&str
) == FAIL
)
7503 /* Two operand format, shuffle the registers
7504 and pretend there are 3. */
7508 else if (is_immediate_prefix (*str
))
7511 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7514 else if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7518 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
7519 for the latter case, EXPR contains the immediate that was found. */
7525 inst
.error
= _("source1 and dest must be same register");
7531 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_R
; break;
7532 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_R
; break;
7533 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_R
; break;
7536 inst
.instruction
|= Rd
| (Rn
<< 3);
7542 case THUMB_ASR
: inst
.instruction
= T_OPCODE_ASR_I
; break;
7543 case THUMB_LSL
: inst
.instruction
= T_OPCODE_LSL_I
; break;
7544 case THUMB_LSR
: inst
.instruction
= T_OPCODE_LSR_I
; break;
7547 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7549 /* Value isn't known yet, create a dummy reloc and let reloc
7550 hacking fix it up. */
7551 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_SHIFT
;
7555 unsigned shift_value
= inst
.reloc
.exp
.X_add_number
;
7557 if (shift_value
> 32 || (shift_value
== 32 && shift
== THUMB_LSL
))
7559 inst
.error
= _("invalid immediate for shift");
7563 /* Shifts of zero are handled by converting to LSL. */
7564 if (shift_value
== 0)
7565 inst
.instruction
= T_OPCODE_LSL_I
;
7567 /* Shifts of 32 are encoded as a shift of zero. */
7568 if (shift_value
== 32)
7571 inst
.instruction
|= shift_value
<< 6;
7574 inst
.instruction
|= Rd
| (Rs
<< 3);
7581 thumb_mov_compare (str
, move
)
7587 skip_whitespace (str
);
7589 if ((Rd
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
7590 || skip_past_comma (&str
) == FAIL
)
7593 inst
.error
= BAD_ARGS
;
7597 if (is_immediate_prefix (*str
))
7600 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7603 else if ((Rs
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7608 if (Rs
< 8 && Rd
< 8)
7610 if (move
== THUMB_MOVE
)
7611 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
7612 since a MOV instruction produces unpredictable results. */
7613 inst
.instruction
= T_OPCODE_ADD_I3
;
7615 inst
.instruction
= T_OPCODE_CMP_LR
;
7616 inst
.instruction
|= Rd
| (Rs
<< 3);
7620 if (move
== THUMB_MOVE
)
7621 inst
.instruction
= T_OPCODE_MOV_HR
;
7623 inst
.instruction
= T_OPCODE_CMP_HR
;
7626 inst
.instruction
|= THUMB_H1
;
7629 inst
.instruction
|= THUMB_H2
;
7631 inst
.instruction
|= (Rd
& 7) | ((Rs
& 7) << 3);
7638 inst
.error
= _("only lo regs allowed with immediate");
7642 if (move
== THUMB_MOVE
)
7643 inst
.instruction
= T_OPCODE_MOV_I8
;
7645 inst
.instruction
= T_OPCODE_CMP_I8
;
7647 inst
.instruction
|= Rd
<< 8;
7649 if (inst
.reloc
.exp
.X_op
!= O_constant
)
7650 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_IMM
;
7653 unsigned value
= inst
.reloc
.exp
.X_add_number
;
7657 inst
.error
= _("invalid immediate");
7661 inst
.instruction
|= value
;
7669 thumb_load_store (str
, load_store
, size
)
7674 int Rd
, Rb
, Ro
= FAIL
;
7676 skip_whitespace (str
);
7678 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
7679 || skip_past_comma (&str
) == FAIL
)
7682 inst
.error
= BAD_ARGS
;
7689 if ((Rb
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
7692 if (skip_past_comma (&str
) != FAIL
)
7694 if (is_immediate_prefix (*str
))
7697 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7700 else if ((Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
7705 inst
.reloc
.exp
.X_op
= O_constant
;
7706 inst
.reloc
.exp
.X_add_number
= 0;
7711 inst
.error
= _("expected ']'");
7716 else if (*str
== '=')
7718 if (load_store
!= THUMB_LOAD
)
7720 inst
.error
= _("invalid pseudo operation");
7724 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op. */
7727 skip_whitespace (str
);
7729 if (my_get_expression (& inst
.reloc
.exp
, & str
))
7734 if ( inst
.reloc
.exp
.X_op
!= O_constant
7735 && inst
.reloc
.exp
.X_op
!= O_symbol
)
7737 inst
.error
= "Constant expression expected";
7741 if (inst
.reloc
.exp
.X_op
== O_constant
7742 && ((inst
.reloc
.exp
.X_add_number
& ~0xFF) == 0))
7744 /* This can be done with a mov instruction. */
7746 inst
.instruction
= T_OPCODE_MOV_I8
| (Rd
<< 8);
7747 inst
.instruction
|= inst
.reloc
.exp
.X_add_number
;
7751 /* Insert into literal pool. */
7752 if (add_to_lit_pool () == FAIL
)
7755 inst
.error
= "literal pool insertion failed";
7759 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7760 inst
.reloc
.pc_rel
= 1;
7761 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
7762 /* Adjust ARM pipeline offset to Thumb. */
7763 inst
.reloc
.exp
.X_add_number
+= 4;
7769 if (my_get_expression (&inst
.reloc
.exp
, &str
))
7772 inst
.instruction
= T_OPCODE_LDR_PC
| (Rd
<< 8);
7773 inst
.reloc
.pc_rel
= 1;
7774 inst
.reloc
.exp
.X_add_number
-= 4; /* Pipeline offset. */
7775 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7780 if (Rb
== REG_PC
|| Rb
== REG_SP
)
7782 if (size
!= THUMB_WORD
)
7784 inst
.error
= _("byte or halfword not valid for base register");
7787 else if (Rb
== REG_PC
&& load_store
!= THUMB_LOAD
)
7789 inst
.error
= _("r15 based store not allowed");
7792 else if (Ro
!= FAIL
)
7794 inst
.error
= _("invalid base register for register offset");
7799 inst
.instruction
= T_OPCODE_LDR_PC
;
7800 else if (load_store
== THUMB_LOAD
)
7801 inst
.instruction
= T_OPCODE_LDR_SP
;
7803 inst
.instruction
= T_OPCODE_STR_SP
;
7805 inst
.instruction
|= Rd
<< 8;
7806 if (inst
.reloc
.exp
.X_op
== O_constant
)
7808 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
7810 if (offset
& ~0x3fc)
7812 inst
.error
= _("invalid offset");
7816 inst
.instruction
|= offset
>> 2;
7819 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7823 inst
.error
= _("invalid base register in load/store");
7826 else if (Ro
== FAIL
)
7828 /* Immediate offset. */
7829 if (size
== THUMB_WORD
)
7830 inst
.instruction
= (load_store
== THUMB_LOAD
7831 ? T_OPCODE_LDR_IW
: T_OPCODE_STR_IW
);
7832 else if (size
== THUMB_HALFWORD
)
7833 inst
.instruction
= (load_store
== THUMB_LOAD
7834 ? T_OPCODE_LDR_IH
: T_OPCODE_STR_IH
);
7836 inst
.instruction
= (load_store
== THUMB_LOAD
7837 ? T_OPCODE_LDR_IB
: T_OPCODE_STR_IB
);
7839 inst
.instruction
|= Rd
| (Rb
<< 3);
7841 if (inst
.reloc
.exp
.X_op
== O_constant
)
7843 unsigned offset
= inst
.reloc
.exp
.X_add_number
;
7845 if (offset
& ~(0x1f << size
))
7847 inst
.error
= _("invalid offset");
7850 inst
.instruction
|= (offset
>> size
) << 6;
7853 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_OFFSET
;
7857 /* Register offset. */
7858 if (size
== THUMB_WORD
)
7859 inst
.instruction
= (load_store
== THUMB_LOAD
7860 ? T_OPCODE_LDR_RW
: T_OPCODE_STR_RW
);
7861 else if (size
== THUMB_HALFWORD
)
7862 inst
.instruction
= (load_store
== THUMB_LOAD
7863 ? T_OPCODE_LDR_RH
: T_OPCODE_STR_RH
);
7865 inst
.instruction
= (load_store
== THUMB_LOAD
7866 ? T_OPCODE_LDR_RB
: T_OPCODE_STR_RB
);
7868 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
7874 /* A register must be given at this point.
7876 Shift is the place to put it in inst.instruction.
7878 Restores input start point on err.
7879 Returns the reg#, or FAIL. */
7882 cirrus_reg_required_here (str
, shift
, regtype
)
7885 enum arm_reg_type regtype
;
7890 if ((reg
= arm_reg_parse (str
, all_reg_maps
[regtype
].htab
)) != FAIL
)
7893 inst
.instruction
|= reg
<< shift
;
7898 /* Restore the start point. */
7901 /* In the few cases where we might be able to accept something else
7902 this error can be overridden. */
7903 inst
.error
= _(all_reg_maps
[regtype
].expected
);
7908 /* Cirrus Instructions. */
7910 /* Wrapper functions. */
7913 do_c_binops_1a (str
)
7916 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_RN
, REG_TYPE_MVF
);
7920 do_c_binops_1b (str
)
7923 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_RN
, REG_TYPE_MVD
);
7927 do_c_binops_1c (str
)
7930 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_RN
, REG_TYPE_MVDX
);
7934 do_c_binops_1d (str
)
7937 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVF
);
7941 do_c_binops_1e (str
)
7944 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVD
);
7948 do_c_binops_1f (str
)
7951 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVF
);
7955 do_c_binops_1g (str
)
7958 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVD
);
7962 do_c_binops_1h (str
)
7965 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVFX
);
7969 do_c_binops_1i (str
)
7972 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVFX
);
7976 do_c_binops_1j (str
)
7979 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVF
, REG_TYPE_MVDX
);
7983 do_c_binops_1k (str
)
7986 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVD
, REG_TYPE_MVDX
);
7990 do_c_binops_1l (str
)
7993 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVF
);
7997 do_c_binops_1m (str
)
8000 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVD
);
8004 do_c_binops_1n (str
)
8007 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8011 do_c_binops_1o (str
)
8014 do_c_binops (str
, CIRRUS_MODE1
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8018 do_c_binops_2a (str
)
8021 do_c_binops (str
, CIRRUS_MODE2
, REG_TYPE_MVF
, REG_TYPE_RN
);
8025 do_c_binops_2b (str
)
8028 do_c_binops (str
, CIRRUS_MODE2
, REG_TYPE_MVD
, REG_TYPE_RN
);
8032 do_c_binops_2c (str
)
8035 do_c_binops (str
, CIRRUS_MODE2
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8039 do_c_binops_3a (str
)
8042 do_c_binops (str
, CIRRUS_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVFX
);
8046 do_c_binops_3b (str
)
8049 do_c_binops (str
, CIRRUS_MODE3
, REG_TYPE_MVFX
, REG_TYPE_MVAX
);
8053 do_c_binops_3c (str
)
8056 do_c_binops (str
, CIRRUS_MODE3
, REG_TYPE_MVAX
, REG_TYPE_MVDX
);
8060 do_c_binops_3d (str
)
8063 do_c_binops (str
, CIRRUS_MODE3
, REG_TYPE_MVDX
, REG_TYPE_MVAX
);
8067 do_c_triple_4a (str
)
8070 do_c_triple (str
, CIRRUS_MODE4
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_RN
);
8074 do_c_triple_4b (str
)
8077 do_c_triple (str
, CIRRUS_MODE4
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_RN
);
8081 do_c_triple_5a (str
)
8084 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_RN
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8088 do_c_triple_5b (str
)
8091 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_RN
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8095 do_c_triple_5c (str
)
8098 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_RN
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8102 do_c_triple_5d (str
)
8105 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_RN
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8109 do_c_triple_5e (str
)
8112 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_MVF
, REG_TYPE_MVF
, REG_TYPE_MVF
);
8116 do_c_triple_5f (str
)
8119 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_MVD
, REG_TYPE_MVD
, REG_TYPE_MVD
);
8123 do_c_triple_5g (str
)
8126 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_MVFX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8130 do_c_triple_5h (str
)
8133 do_c_triple (str
, CIRRUS_MODE5
, REG_TYPE_MVDX
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8140 do_c_quad (str
, CIRRUS_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVFX
, REG_TYPE_MVFX
,
8148 do_c_quad (str
, CIRRUS_MODE6
, REG_TYPE_MVAX
, REG_TYPE_MVAX
, REG_TYPE_MVFX
,
8152 /* cfmvsc32<cond> DSPSC,MVFX[15:0]. */
8157 skip_whitespace (str
);
8160 if (cirrus_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
8161 || skip_past_comma (&str
) == FAIL
8162 || cirrus_reg_required_here (&str
, 16, REG_TYPE_MVFX
) == FAIL
)
8165 inst
.error
= BAD_ARGS
;
8173 /* cfmv32sc<cond> MVFX[15:0],DSPSC. */
8178 skip_whitespace (str
);
8181 if (cirrus_reg_required_here (&str
, 0, REG_TYPE_MVFX
) == FAIL
8182 || skip_past_comma (&str
) == FAIL
8183 || cirrus_reg_required_here (&str
, -1, REG_TYPE_DSPSC
) == FAIL
)
8186 inst
.error
= BAD_ARGS
;
8198 do_c_shift (str
, REG_TYPE_MVFX
, REG_TYPE_MVFX
);
8205 do_c_shift (str
, REG_TYPE_MVDX
, REG_TYPE_MVDX
);
8212 do_c_ldst (str
, REG_TYPE_MVF
);
8219 do_c_ldst (str
, REG_TYPE_MVD
);
8226 do_c_ldst (str
, REG_TYPE_MVFX
);
8233 do_c_ldst (str
, REG_TYPE_MVDX
);
8236 /* Isnsn like "foo X,Y". */
8239 do_c_binops (str
, mode
, reg0
, reg1
)
8242 enum arm_reg_type reg0
;
8243 enum arm_reg_type reg1
;
8247 shift0
= mode
& 0xff;
8248 shift1
= (mode
>> 8) & 0xff;
8250 skip_whitespace (str
);
8252 if (cirrus_reg_required_here (&str
, shift0
, reg0
) == FAIL
8253 || skip_past_comma (&str
) == FAIL
8254 || cirrus_reg_required_here (&str
, shift1
, reg1
) == FAIL
)
8257 inst
.error
= BAD_ARGS
;
8263 /* Isnsn like "foo X,Y,Z". */
8266 do_c_triple (str
, mode
, reg0
, reg1
, reg2
)
8269 enum arm_reg_type reg0
;
8270 enum arm_reg_type reg1
;
8271 enum arm_reg_type reg2
;
8273 int shift0
, shift1
, shift2
;
8275 shift0
= mode
& 0xff;
8276 shift1
= (mode
>> 8) & 0xff;
8277 shift2
= (mode
>> 16) & 0xff;
8279 skip_whitespace (str
);
8281 if (cirrus_reg_required_here (&str
, shift0
, reg0
) == FAIL
8282 || skip_past_comma (&str
) == FAIL
8283 || cirrus_reg_required_here (&str
, shift1
, reg1
) == FAIL
8284 || skip_past_comma (&str
) == FAIL
8285 || cirrus_reg_required_here (&str
, shift2
, reg2
) == FAIL
)
8288 inst
.error
= BAD_ARGS
;
8294 /* Isnsn like "foo W,X,Y,Z".
8295 where W=MVAX[0:3] and X,Y,Z=MVFX[0:15]. */
8298 do_c_quad (str
, mode
, reg0
, reg1
, reg2
, reg3
)
8301 enum arm_reg_type reg0
;
8302 enum arm_reg_type reg1
;
8303 enum arm_reg_type reg2
;
8304 enum arm_reg_type reg3
;
8306 int shift0
, shift1
, shift2
, shift3
;
8308 shift0
= mode
& 0xff;
8309 shift1
= (mode
>> 8) & 0xff;
8310 shift2
= (mode
>> 16) & 0xff;
8311 shift3
= (mode
>> 24) & 0xff;
8313 skip_whitespace (str
);
8315 if (cirrus_reg_required_here (&str
, shift0
, reg0
) == FAIL
8316 || skip_past_comma (&str
) == FAIL
8317 || cirrus_reg_required_here (&str
, shift1
, reg1
) == FAIL
8318 || skip_past_comma (&str
) == FAIL
8319 || cirrus_reg_required_here (&str
, shift2
, reg2
) == FAIL
8320 || skip_past_comma (&str
) == FAIL
8321 || cirrus_reg_required_here (&str
, shift3
, reg3
) == FAIL
)
8324 inst
.error
= BAD_ARGS
;
8330 /* Cirrus shift immediate instructions.
8331 cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
8332 cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0]. */
8335 do_c_shift (str
, reg0
, reg1
)
8337 enum arm_reg_type reg0
;
8338 enum arm_reg_type reg1
;
8343 skip_whitespace (str
);
8347 if (cirrus_reg_required_here (&str
, 12, reg0
) == FAIL
8348 || skip_past_comma (&str
) == FAIL
8349 || cirrus_reg_required_here (&str
, 16, reg1
) == FAIL
8350 || skip_past_comma (&str
) == FAIL
)
8353 inst
.error
= BAD_ARGS
;
8357 /* Calculate the immediate operand.
8358 The operand is a 7bit signed number. */
8359 skip_whitespace (str
);
8364 if (!ISDIGIT (*str
) && *str
!= '-')
8366 inst
.error
= _("expecting immediate, 7bit operand");
8376 for (imm
= 0; *str
&& ISDIGIT (*str
); ++str
)
8377 imm
= imm
* 10 + *str
- '0';
8381 inst
.error
= _("immediate out of range");
8385 /* Make negative imm's into 7bit signed numbers. */
8392 /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
8393 Bits 5-7 of the insn should have bits 4-6 of the immediate.
8394 Bit 4 should be 0. */
8395 imm
= (imm
& 0xf) | ((imm
& 0x70) << 1);
8397 inst
.instruction
|= imm
;
8402 cirrus_parse_offset (str
, negative
)
8411 skip_whitespace (p
);
8424 inst
.error
= _("offset expected");
8428 for (offset
= 0; *p
&& ISDIGIT (*p
); ++p
)
8429 offset
= offset
* 10 + *p
- '0';
8433 inst
.error
= _("offset out of range");
8439 return *negative
? -offset
: offset
;
8442 /* Cirrus load/store instructions.
8443 <insn><cond> CRd,[Rn,<offset>]{!}.
8444 <insn><cond> CRd,[Rn],<offset>. */
8447 do_c_ldst (str
, reg0
)
8449 enum arm_reg_type reg0
;
8451 int offset
, negative
;
8453 skip_whitespace (str
);
8455 if (cirrus_reg_required_here (&str
, 12, reg0
) == FAIL
8456 || skip_past_comma (&str
) == FAIL
8458 || reg_required_here (&str
, 16) == FAIL
)
8461 if (skip_past_comma (&str
) == SUCCESS
)
8463 /* You are here: "<offset>]{!}". */
8464 inst
.instruction
|= PRE_INDEX
;
8466 offset
= cirrus_parse_offset (&str
, &negative
);
8473 inst
.error
= _("missing ]");
8479 inst
.instruction
|= WRITE_BACK
;
8485 /* You are here: "], <offset>". */
8488 inst
.error
= _("missing ]");
8492 if (skip_past_comma (&str
) == FAIL
8493 || (offset
= cirrus_parse_offset (&str
, &negative
), inst
.error
))
8496 inst
.instruction
|= CP_T_WB
; /* Post indexed, set bit W. */
8502 inst
.instruction
|= CP_T_UD
; /* Postive, so set bit U. */
8504 inst
.instruction
|= offset
>> 2;
8510 inst
.error
= BAD_ARGS
;
8523 /* Handle the Format 4 instructions that do not have equivalents in other
8524 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
8533 skip_whitespace (str
);
8535 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8536 || skip_past_comma (&str
) == FAIL
8537 || (Rs
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8539 inst
.error
= BAD_ARGS
;
8543 if (skip_past_comma (&str
) != FAIL
)
8545 /* Three operand format not allowed for TST, CMN, NEG and MVN.
8546 (It isn't allowed for CMP either, but that isn't handled by this
8548 if (inst
.instruction
== T_OPCODE_TST
8549 || inst
.instruction
== T_OPCODE_CMN
8550 || inst
.instruction
== T_OPCODE_NEG
8551 || inst
.instruction
== T_OPCODE_MVN
)
8553 inst
.error
= BAD_ARGS
;
8557 if ((Rn
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8562 inst
.error
= _("dest and source1 must be the same register");
8568 if (inst
.instruction
== T_OPCODE_MUL
8570 as_tsktsk (_("Rs and Rd must be different in MUL"));
8572 inst
.instruction
|= Rd
| (Rs
<< 3);
8580 thumb_add_sub (str
, 0);
8587 thumb_shift (str
, THUMB_ASR
);
8594 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8596 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH9
;
8597 inst
.reloc
.pc_rel
= 1;
8605 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8607 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH12
;
8608 inst
.reloc
.pc_rel
= 1;
8612 /* Find the real, Thumb encoded start of a Thumb function. */
8615 find_real_start (symbolP
)
8619 const char * name
= S_GET_NAME (symbolP
);
8620 symbolS
* new_target
;
8622 /* This definiton must agree with the one in gcc/config/arm/thumb.c. */
8623 #define STUB_NAME ".real_start_of"
8628 /* Names that start with '.' are local labels, not function entry points.
8629 The compiler may generate BL instructions to these labels because it
8630 needs to perform a branch to a far away location. */
8634 real_start
= malloc (strlen (name
) + strlen (STUB_NAME
) + 1);
8635 sprintf (real_start
, "%s%s", STUB_NAME
, name
);
8637 new_target
= symbol_find (real_start
);
8639 if (new_target
== NULL
)
8641 as_warn ("Failed to find real start of function: %s\n", name
);
8642 new_target
= symbolP
;
8654 if (my_get_expression (& inst
.reloc
.exp
, & str
))
8657 inst
.reloc
.type
= BFD_RELOC_THUMB_PCREL_BRANCH23
;
8658 inst
.reloc
.pc_rel
= 1;
8661 /* If the destination of the branch is a defined symbol which does not have
8662 the THUMB_FUNC attribute, then we must be calling a function which has
8663 the (interfacearm) attribute. We look for the Thumb entry point to that
8664 function and change the branch to refer to that function instead. */
8665 if ( inst
.reloc
.exp
.X_op
== O_symbol
8666 && inst
.reloc
.exp
.X_add_symbol
!= NULL
8667 && S_IS_DEFINED (inst
.reloc
.exp
.X_add_symbol
)
8668 && ! THUMB_IS_FUNC (inst
.reloc
.exp
.X_add_symbol
))
8669 inst
.reloc
.exp
.X_add_symbol
=
8670 find_real_start (inst
.reloc
.exp
.X_add_symbol
);
8679 skip_whitespace (str
);
8681 if ((reg
= thumb_reg (&str
, THUMB_REG_ANY
)) == FAIL
)
8684 /* This sets THUMB_H2 from the top bit of reg. */
8685 inst
.instruction
|= reg
<< 3;
8687 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
8688 should cause the alignment to be checked once it is known. This is
8689 because BX PC only works if the instruction is word aligned. */
8698 thumb_mov_compare (str
, THUMB_COMPARE
);
8708 skip_whitespace (str
);
8710 if ((Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
)
8714 as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
8718 if (skip_past_comma (&str
) == FAIL
8719 || (range
= reg_list (&str
)) == FAIL
)
8722 inst
.error
= BAD_ARGS
;
8726 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8728 /* This really doesn't seem worth it. */
8729 inst
.reloc
.type
= BFD_RELOC_NONE
;
8730 inst
.error
= _("expression too complex");
8736 inst
.error
= _("only lo-regs valid in load/store multiple");
8740 inst
.instruction
|= (Rb
<< 8) | range
;
8748 thumb_load_store (str
, THUMB_LOAD
, THUMB_WORD
);
8755 thumb_load_store (str
, THUMB_LOAD
, THUMB_BYTE
);
8762 thumb_load_store (str
, THUMB_LOAD
, THUMB_HALFWORD
);
8771 skip_whitespace (str
);
8773 if ((Rd
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8774 || skip_past_comma (&str
) == FAIL
8776 || (Rb
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8777 || skip_past_comma (&str
) == FAIL
8778 || (Ro
= thumb_reg (&str
, THUMB_REG_LO
)) == FAIL
8782 inst
.error
= _("syntax: ldrs[b] Rd, [Rb, Ro]");
8786 inst
.instruction
|= Rd
| (Rb
<< 3) | (Ro
<< 6);
8794 thumb_shift (str
, THUMB_LSL
);
8801 thumb_shift (str
, THUMB_LSR
);
8808 thumb_mov_compare (str
, THUMB_MOVE
);
8817 skip_whitespace (str
);
8819 if ((range
= reg_list (&str
)) == FAIL
)
8822 inst
.error
= BAD_ARGS
;
8826 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
8828 /* This really doesn't seem worth it. */
8829 inst
.reloc
.type
= BFD_RELOC_NONE
;
8830 inst
.error
= _("expression too complex");
8836 if ((inst
.instruction
== T_OPCODE_PUSH
8837 && (range
& ~0xff) == 1 << REG_LR
)
8838 || (inst
.instruction
== T_OPCODE_POP
8839 && (range
& ~0xff) == 1 << REG_PC
))
8841 inst
.instruction
|= THUMB_PP_PC_LR
;
8846 inst
.error
= _("invalid register list to push/pop instruction");
8851 inst
.instruction
|= range
;
8859 thumb_load_store (str
, THUMB_STORE
, THUMB_WORD
);
8866 thumb_load_store (str
, THUMB_STORE
, THUMB_BYTE
);
8873 thumb_load_store (str
, THUMB_STORE
, THUMB_HALFWORD
);
8880 thumb_add_sub (str
, 1);
8887 skip_whitespace (str
);
8889 if (my_get_expression (&inst
.reloc
.exp
, &str
))
8892 inst
.reloc
.type
= BFD_RELOC_ARM_SWI
;
8903 /* This is a pseudo-op of the form "adr rd, label" to be converted
8904 into a relative address of the form "add rd, pc, #label-.-4". */
8905 skip_whitespace (str
);
8907 /* Store Rd in temporary location inside instruction. */
8908 if ((reg
= reg_required_here (&str
, 4)) == FAIL
8909 || (reg
> 7) /* For Thumb reg must be r0..r7. */
8910 || skip_past_comma (&str
) == FAIL
8911 || my_get_expression (&inst
.reloc
.exp
, &str
))
8914 inst
.error
= BAD_ARGS
;
8918 inst
.reloc
.type
= BFD_RELOC_ARM_THUMB_ADD
;
8919 inst
.reloc
.exp
.X_add_number
-= 4; /* PC relative adjust. */
8920 inst
.reloc
.pc_rel
= 1;
8921 inst
.instruction
|= REG_PC
; /* Rd is already placed into the instruction. */
8927 insert_reg (r
, htab
)
8928 const struct reg_entry
*r
;
8929 struct hash_control
*htab
;
8931 int len
= strlen (r
->name
) + 2;
8932 char * buf
= (char *) xmalloc (len
);
8933 char * buf2
= (char *) xmalloc (len
);
8936 #ifdef REGISTER_PREFIX
8937 buf
[i
++] = REGISTER_PREFIX
;
8940 strcpy (buf
+ i
, r
->name
);
8942 for (i
= 0; buf
[i
]; i
++)
8943 buf2
[i
] = TOUPPER (buf
[i
]);
8947 hash_insert (htab
, buf
, (PTR
) r
);
8948 hash_insert (htab
, buf2
, (PTR
) r
);
8953 struct reg_map
*map
;
8955 const struct reg_entry
*r
;
8957 if ((map
->htab
= hash_new ()) == NULL
)
8958 as_fatal (_("virtual memory exhausted"));
8960 for (r
= map
->names
; r
->name
!= NULL
; r
++)
8961 insert_reg (r
, map
->htab
);
8965 insert_reg_alias (str
, regnum
, htab
)
8968 struct hash_control
*htab
;
8970 struct reg_entry
*new =
8971 (struct reg_entry
*) xmalloc (sizeof (struct reg_entry
));
8972 char *name
= xmalloc (strlen (str
) + 1);
8976 new->number
= regnum
;
8978 hash_insert (htab
, name
, (PTR
) new);
8981 /* Look for the .req directive. This is of the form:
8983 newname .req existing_name
8985 If we find one, or if it looks sufficiently like one that we want to
8986 handle any error here, return non-zero. Otherwise return zero. */
8988 create_register_alias (newname
, p
)
8996 skip_whitespace (q
);
9001 if (*q
&& !strncmp (q
, ".req ", 5))
9006 #ifdef IGNORE_OPCODE_CASE
9007 newname
= original_case_string
;
9009 copy_of_str
= newname
;
9012 skip_whitespace (q
);
9014 for (r
= q
; *r
!= '\0'; r
++)
9020 enum arm_reg_type new_type
, old_type
;
9025 old_type
= arm_reg_parse_any (q
);
9028 new_type
= arm_reg_parse_any (newname
);
9030 if (new_type
== REG_TYPE_MAX
)
9032 if (old_type
!= REG_TYPE_MAX
)
9034 old_regno
= arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
);
9035 insert_reg_alias (newname
, old_regno
,
9036 all_reg_maps
[old_type
].htab
);
9039 as_warn (_("register '%s' does not exist\n"), q
);
9041 else if (old_type
== REG_TYPE_MAX
)
9043 as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
9048 /* Do not warn about redefinitions to the same alias. */
9049 if (new_type
!= old_type
9050 || (arm_reg_parse (&q
, all_reg_maps
[old_type
].htab
)
9051 != arm_reg_parse (&q
, all_reg_maps
[new_type
].htab
)))
9052 as_warn (_("ignoring redefinition of register alias '%s'"),
9058 as_warn (_("ignoring incomplete .req pseuso op"));
9068 set_constant_flonums ()
9072 for (i
= 0; i
< NUM_FLOAT_VALS
; i
++)
9073 if (atof_ieee ((char *) fp_const
[i
], 'x', fp_values
[i
]) == NULL
)
9077 /* Iterate over the base tables to create the instruction patterns. */
9079 build_arm_ops_hsh ()
9083 static struct obstack insn_obstack
;
9085 obstack_begin (&insn_obstack
, 4000);
9087 for (i
= 0; i
< sizeof (insns
) / sizeof (struct asm_opcode
); i
++)
9089 const struct asm_opcode
*insn
= insns
+ i
;
9091 if (insn
->cond_offset
!= 0)
9093 /* Insn supports conditional execution. Build the varaints
9094 and insert them in the hash table. */
9095 for (j
= 0; j
< sizeof (conds
) / sizeof (struct asm_cond
); j
++)
9097 unsigned len
= strlen (insn
->template);
9098 struct asm_opcode
*new;
9101 new = obstack_alloc (&insn_obstack
, sizeof (struct asm_opcode
));
9102 /* All condition codes are two characters. */
9103 template = obstack_alloc (&insn_obstack
, len
+ 3);
9105 strncpy (template, insn
->template, insn
->cond_offset
);
9106 strcpy (template + insn
->cond_offset
, conds
[j
].template);
9107 if (len
> insn
->cond_offset
)
9108 strcpy (template + insn
->cond_offset
+ 2,
9109 insn
->template + insn
->cond_offset
);
9110 new->template = template;
9111 new->cond_offset
= 0;
9112 new->variant
= insn
->variant
;
9113 new->parms
= insn
->parms
;
9114 new->value
= (insn
->value
& ~COND_MASK
) | conds
[j
].value
;
9116 hash_insert (arm_ops_hsh
, new->template, (PTR
) new);
9119 /* Finally, insert the unconditional insn in the table directly;
9120 no need to build a copy. */
9121 hash_insert (arm_ops_hsh
, insn
->template, (PTR
) insn
);
9131 if ( (arm_ops_hsh
= hash_new ()) == NULL
9132 || (arm_tops_hsh
= hash_new ()) == NULL
9133 || (arm_cond_hsh
= hash_new ()) == NULL
9134 || (arm_shift_hsh
= hash_new ()) == NULL
9135 || (arm_psr_hsh
= hash_new ()) == NULL
)
9136 as_fatal (_("virtual memory exhausted"));
9138 build_arm_ops_hsh ();
9139 for (i
= 0; i
< sizeof (tinsns
) / sizeof (struct thumb_opcode
); i
++)
9140 hash_insert (arm_tops_hsh
, tinsns
[i
].template, (PTR
) (tinsns
+ i
));
9141 for (i
= 0; i
< sizeof (conds
) / sizeof (struct asm_cond
); i
++)
9142 hash_insert (arm_cond_hsh
, conds
[i
].template, (PTR
) (conds
+ i
));
9143 for (i
= 0; i
< sizeof (shift_names
) / sizeof (struct asm_shift_name
); i
++)
9144 hash_insert (arm_shift_hsh
, shift_names
[i
].name
, (PTR
) (shift_names
+ i
));
9145 for (i
= 0; i
< sizeof (psrs
) / sizeof (struct asm_psr
); i
++)
9146 hash_insert (arm_psr_hsh
, psrs
[i
].template, (PTR
) (psrs
+ i
));
9148 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
9149 build_reg_hsh (all_reg_maps
+ i
);
9151 set_constant_flonums ();
9153 /* Set the cpu variant based on the command-line options. We prefer
9154 -mcpu= over -march= if both are set (as for GCC); and we prefer
9155 -mfpu= over any other way of setting the floating point unit.
9156 Use of legacy options with new options are faulted. */
9157 if (legacy_cpu
!= -1)
9159 if (mcpu_cpu_opt
!= -1 || march_cpu_opt
!= -1)
9160 as_bad (_("use of old and new-style options to set CPU type"));
9162 mcpu_cpu_opt
= legacy_cpu
;
9164 else if (mcpu_cpu_opt
== -1)
9165 mcpu_cpu_opt
= march_cpu_opt
;
9167 if (legacy_fpu
!= -1)
9170 as_bad (_("use of old and new-style options to set FPU type"));
9172 mfpu_opt
= legacy_fpu
;
9174 else if (mfpu_opt
== -1)
9176 if (mcpu_fpu_opt
!= -1)
9177 mfpu_opt
= mcpu_fpu_opt
;
9179 mfpu_opt
= march_fpu_opt
;
9184 if (mcpu_cpu_opt
== -1)
9185 mfpu_opt
= FPU_DEFAULT
;
9186 else if (mcpu_cpu_opt
& ARM_EXT_V5
)
9187 mfpu_opt
= FPU_ARCH_VFP_V2
;
9189 mfpu_opt
= FPU_ARCH_FPA
;
9192 if (mcpu_cpu_opt
== -1)
9193 mcpu_cpu_opt
= CPU_DEFAULT
;
9195 cpu_variant
= mcpu_cpu_opt
| mfpu_opt
;
9197 #if defined OBJ_COFF || defined OBJ_ELF
9199 unsigned int flags
= 0;
9201 /* Set the flags in the private structure. */
9202 if (uses_apcs_26
) flags
|= F_APCS26
;
9203 if (support_interwork
) flags
|= F_INTERWORK
;
9204 if (uses_apcs_float
) flags
|= F_APCS_FLOAT
;
9205 if (pic_code
) flags
|= F_PIC
;
9206 if ((cpu_variant
& FPU_ANY
) == FPU_NONE
9207 || (cpu_variant
& FPU_ANY
) == FPU_ARCH_VFP
) /* VFP layout only. */
9208 flags
|= F_SOFT_FLOAT
;
9209 /* Using VFP conventions (even if soft-float). */
9210 if (cpu_variant
& FPU_VFP_EXT_NONE
) flags
|= F_VFP_FLOAT
;
9213 bfd_set_private_flags (stdoutput
, flags
);
9215 /* We have run out flags in the COFF header to encode the
9216 status of ATPCS support, so instead we create a dummy,
9217 empty, debug section called .arm.atpcs. */
9222 sec
= bfd_make_section (stdoutput
, ".arm.atpcs");
9226 bfd_set_section_flags
9227 (stdoutput
, sec
, SEC_READONLY
| SEC_DEBUGGING
/* | SEC_HAS_CONTENTS */);
9228 bfd_set_section_size (stdoutput
, sec
, 0);
9229 bfd_set_section_contents (stdoutput
, sec
, NULL
, 0, 0);
9235 /* Record the CPU type as well. */
9236 switch (cpu_variant
& ARM_CPU_MASK
)
9239 mach
= bfd_mach_arm_2
;
9242 case ARM_3
: /* Also ARM_250. */
9243 mach
= bfd_mach_arm_2a
;
9246 case ARM_6
: /* Also ARM_7. */
9247 mach
= bfd_mach_arm_3
;
9251 mach
= bfd_mach_arm_4
;
9255 /* Catch special cases. */
9256 if (cpu_variant
& ARM_CEXT_XSCALE
)
9257 mach
= bfd_mach_arm_XScale
;
9258 else if (cpu_variant
& ARM_EXT_V5E
)
9259 mach
= bfd_mach_arm_5TE
;
9260 else if (cpu_variant
& ARM_EXT_V5
)
9262 if (cpu_variant
& ARM_EXT_V4T
)
9263 mach
= bfd_mach_arm_5T
;
9265 mach
= bfd_mach_arm_5
;
9267 else if (cpu_variant
& ARM_EXT_V4
)
9269 if (cpu_variant
& ARM_EXT_V4T
)
9270 mach
= bfd_mach_arm_4T
;
9272 mach
= bfd_mach_arm_4
;
9274 else if (cpu_variant
& ARM_EXT_V3M
)
9275 mach
= bfd_mach_arm_3M
;
9277 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, mach
);
9280 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
9281 for use in the a.out file, and stores them in the array pointed to by buf.
9282 This knows about the endian-ness of the target machine and does
9283 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
9284 2 (short) and 4 (long) Floating numbers are put out as a series of
9285 LITTLENUMS (shorts, here at least). */
9288 md_number_to_chars (buf
, val
, n
)
9293 if (target_big_endian
)
9294 number_to_chars_bigendian (buf
, val
, n
);
9296 number_to_chars_littleendian (buf
, val
, n
);
9300 md_chars_to_number (buf
, n
)
9305 unsigned char * where
= (unsigned char *) buf
;
9307 if (target_big_endian
)
9312 result
|= (*where
++ & 255);
9320 result
|= (where
[n
] & 255);
9327 /* Turn a string in input_line_pointer into a floating point constant
9328 of type TYPE, and store the appropriate bytes in *LITP. The number
9329 of LITTLENUMS emitted is stored in *SIZEP. An error message is
9330 returned, or NULL on OK.
9332 Note that fp constants aren't represent in the normal way on the ARM.
9333 In big endian mode, things are as expected. However, in little endian
9334 mode fp constants are big-endian word-wise, and little-endian byte-wise
9335 within the words. For example, (double) 1.1 in big endian mode is
9336 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
9337 the byte sequence 99 99 f1 3f 9a 99 99 99.
9339 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
9342 md_atof (type
, litP
, sizeP
)
9348 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
9380 return _("bad call to MD_ATOF()");
9383 t
= atof_ieee (input_line_pointer
, type
, words
);
9385 input_line_pointer
= t
;
9388 if (target_big_endian
)
9390 for (i
= 0; i
< prec
; i
++)
9392 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
9398 if (cpu_variant
& FPU_ARCH_VFP
)
9399 for (i
= prec
- 1; i
>= 0; i
--)
9401 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
9405 /* For a 4 byte float the order of elements in `words' is 1 0.
9406 For an 8 byte float the order is 1 0 3 2. */
9407 for (i
= 0; i
< prec
; i
+= 2)
9409 md_number_to_chars (litP
, (valueT
) words
[i
+ 1], 2);
9410 md_number_to_chars (litP
+ 2, (valueT
) words
[i
], 2);
9418 /* The knowledge of the PC's pipeline offset is built into the insns
9422 md_pcrel_from (fixP
)
9426 && S_GET_SEGMENT (fixP
->fx_addsy
) == undefined_section
9427 && fixP
->fx_subsy
== NULL
)
9430 if (fixP
->fx_pcrel
&& (fixP
->fx_r_type
== BFD_RELOC_ARM_THUMB_ADD
))
9432 /* PC relative addressing on the Thumb is slightly odd
9433 as the bottom two bits of the PC are forced to zero
9434 for the calculation. */
9435 return (fixP
->fx_where
+ fixP
->fx_frag
->fr_address
) & ~3;
9439 /* The pattern was adjusted to accomodate CE's off-by-one fixups,
9440 so we un-adjust here to compensate for the accomodation. */
9441 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
+ 8;
9443 return fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
9447 /* Round up a section size to the appropriate boundary. */
9450 md_section_align (segment
, size
)
9451 segT segment ATTRIBUTE_UNUSED
;
9457 /* Round all sects to multiple of 4. */
9458 return (size
+ 3) & ~3;
9462 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
9463 Otherwise we have no need to default values of symbols. */
9466 md_undefined_symbol (name
)
9467 char * name ATTRIBUTE_UNUSED
;
9470 if (name
[0] == '_' && name
[1] == 'G'
9471 && streq (name
, GLOBAL_OFFSET_TABLE_NAME
))
9475 if (symbol_find (name
))
9476 as_bad ("GOT already in the symbol table");
9478 GOT_symbol
= symbol_new (name
, undefined_section
,
9479 (valueT
) 0, & zero_address_frag
);
9489 /* arm_reg_parse () := if it looks like a register, return its token and
9490 advance the pointer. */
9493 arm_reg_parse (ccp
, htab
)
9494 register char ** ccp
;
9495 struct hash_control
*htab
;
9497 char * start
= * ccp
;
9500 struct reg_entry
* reg
;
9502 #ifdef REGISTER_PREFIX
9503 if (*start
!= REGISTER_PREFIX
)
9508 #ifdef OPTIONAL_REGISTER_PREFIX
9509 if (*p
== OPTIONAL_REGISTER_PREFIX
)
9513 if (!ISALPHA (*p
) || !is_name_beginner (*p
))
9517 while (ISALPHA (c
) || ISDIGIT (c
) || c
== '_')
9521 reg
= (struct reg_entry
*) hash_find (htab
, start
);
9533 /* Search for the following register name in each of the possible reg name
9534 tables. Return the classification if found, or REG_TYPE_MAX if not
9536 static enum arm_reg_type
9537 arm_reg_parse_any (cp
)
9542 for (i
= (int) REG_TYPE_FIRST
; i
< (int) REG_TYPE_MAX
; i
++)
9543 if (arm_reg_parse (&cp
, all_reg_maps
[i
].htab
) != FAIL
)
9544 return (enum arm_reg_type
) i
;
9546 return REG_TYPE_MAX
;
9550 md_apply_fix3 (fixP
, valP
, seg
)
9555 offsetT value
= * valP
;
9557 unsigned int newimm
;
9560 char * buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
9561 arm_fix_data
* arm_data
= (arm_fix_data
*) fixP
->tc_fix_data
;
9563 assert (fixP
->fx_r_type
< BFD_RELOC_UNUSED
);
9565 /* Note whether this will delete the relocation. */
9567 /* Patch from REarnshaw to JDavis (disabled for the moment, since it
9568 doesn't work fully.) */
9569 if ((fixP
->fx_addsy
== 0 || symbol_constant_p (fixP
->fx_addsy
))
9572 if (fixP
->fx_addsy
== 0 && !fixP
->fx_pcrel
)
9576 /* If this symbol is in a different section then we need to leave it for
9577 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
9578 so we have to undo it's effects here. */
9581 if (fixP
->fx_addsy
!= NULL
9582 && S_IS_DEFINED (fixP
->fx_addsy
)
9583 && S_GET_SEGMENT (fixP
->fx_addsy
) != seg
)
9586 && (fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
9587 || fixP
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
9591 value
+= md_pcrel_from (fixP
);
9595 /* Remember value for emit_reloc. */
9596 fixP
->fx_addnumber
= value
;
9598 switch (fixP
->fx_r_type
)
9600 case BFD_RELOC_ARM_IMMEDIATE
:
9601 newimm
= validate_immediate (value
);
9602 temp
= md_chars_to_number (buf
, INSN_SIZE
);
9604 /* If the instruction will fail, see if we can fix things up by
9605 changing the opcode. */
9606 if (newimm
== (unsigned int) FAIL
9607 && (newimm
= negate_data_op (&temp
, value
)) == (unsigned int) FAIL
)
9609 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9610 _("invalid constant (%lx) after fixup"),
9611 (unsigned long) value
);
9615 newimm
|= (temp
& 0xfffff000);
9616 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
9619 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
9621 unsigned int highpart
= 0;
9622 unsigned int newinsn
= 0xe1a00000; /* nop. */
9623 newimm
= validate_immediate (value
);
9624 temp
= md_chars_to_number (buf
, INSN_SIZE
);
9626 /* If the instruction will fail, see if we can fix things up by
9627 changing the opcode. */
9628 if (newimm
== (unsigned int) FAIL
9629 && (newimm
= negate_data_op (& temp
, value
)) == (unsigned int) FAIL
)
9631 /* No ? OK - try using two ADD instructions to generate
9633 newimm
= validate_immediate_twopart (value
, & highpart
);
9635 /* Yes - then make sure that the second instruction is
9637 if (newimm
!= (unsigned int) FAIL
)
9639 /* Still No ? Try using a negated value. */
9640 else if ((newimm
= validate_immediate_twopart (- value
, & highpart
)) != (unsigned int) FAIL
)
9641 temp
= newinsn
= (temp
& OPCODE_MASK
) | OPCODE_SUB
<< DATA_OP_SHIFT
;
9642 /* Otherwise - give up. */
9645 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9646 _("unable to compute ADRL instructions for PC offset of 0x%lx"),
9651 /* Replace the first operand in the 2nd instruction (which
9652 is the PC) with the destination register. We have
9653 already added in the PC in the first instruction and we
9654 do not want to do it again. */
9655 newinsn
&= ~ 0xf0000;
9656 newinsn
|= ((newinsn
& 0x0f000) << 4);
9659 newimm
|= (temp
& 0xfffff000);
9660 md_number_to_chars (buf
, (valueT
) newimm
, INSN_SIZE
);
9662 highpart
|= (newinsn
& 0xfffff000);
9663 md_number_to_chars (buf
+ INSN_SIZE
, (valueT
) highpart
, INSN_SIZE
);
9667 case BFD_RELOC_ARM_OFFSET_IMM
:
9673 if (validate_offset_imm (value
, 0) == FAIL
)
9675 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9676 _("bad immediate value for offset (%ld)"),
9681 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9682 newval
&= 0xff7ff000;
9683 newval
|= value
| (sign
? INDEX_UP
: 0);
9684 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9687 case BFD_RELOC_ARM_OFFSET_IMM8
:
9688 case BFD_RELOC_ARM_HWLITERAL
:
9694 if (validate_offset_imm (value
, 1) == FAIL
)
9696 if (fixP
->fx_r_type
== BFD_RELOC_ARM_HWLITERAL
)
9697 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9698 _("invalid literal constant: pool needs to be closer"));
9700 as_bad (_("bad immediate value for half-word offset (%ld)"),
9705 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9706 newval
&= 0xff7ff0f0;
9707 newval
|= ((value
>> 4) << 8) | (value
& 0xf) | (sign
? INDEX_UP
: 0);
9708 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9711 case BFD_RELOC_ARM_LITERAL
:
9717 if (validate_offset_imm (value
, 0) == FAIL
)
9719 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9720 _("invalid literal constant: pool needs to be closer"));
9724 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9725 newval
&= 0xff7ff000;
9726 newval
|= value
| (sign
? INDEX_UP
: 0);
9727 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9730 case BFD_RELOC_ARM_SHIFT_IMM
:
9731 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9732 if (((unsigned long) value
) > 32
9734 && (((newval
& 0x60) == 0) || (newval
& 0x60) == 0x60)))
9736 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9737 _("shift expression is too large"));
9742 /* Shifts of zero must be done as lsl. */
9744 else if (value
== 32)
9746 newval
&= 0xfffff07f;
9747 newval
|= (value
& 0x1f) << 7;
9748 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9751 case BFD_RELOC_ARM_SWI
:
9752 if (arm_data
->thumb_mode
)
9754 if (((unsigned long) value
) > 0xff)
9755 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9756 _("invalid swi expression"));
9757 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xff00;
9759 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9763 if (((unsigned long) value
) > 0x00ffffff)
9764 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9765 _("invalid swi expression"));
9766 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff000000;
9768 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9772 case BFD_RELOC_ARM_MULTI
:
9773 if (((unsigned long) value
) > 0xffff)
9774 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9775 _("invalid expression in load/store multiple"));
9776 newval
= value
| md_chars_to_number (buf
, INSN_SIZE
);
9777 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9780 case BFD_RELOC_ARM_PCREL_BRANCH
:
9781 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9783 /* Sign-extend a 24-bit number. */
9784 #define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
9788 value
= fixP
->fx_offset
;
9791 /* We are going to store value (shifted right by two) in the
9792 instruction, in a 24 bit, signed field. Thus we need to check
9793 that none of the top 8 bits of the shifted value (top 7 bits of
9794 the unshifted, unsigned value) are set, or that they are all set. */
9795 if ((value
& ~ ((offsetT
) 0x1ffffff)) != 0
9796 && ((value
& ~ ((offsetT
) 0x1ffffff)) != ~ ((offsetT
) 0x1ffffff)))
9799 /* Normally we would be stuck at this point, since we cannot store
9800 the absolute address that is the destination of the branch in the
9801 24 bits of the branch instruction. If however, we happen to know
9802 that the destination of the branch is in the same section as the
9803 branch instruciton itself, then we can compute the relocation for
9804 ourselves and not have to bother the linker with it.
9806 FIXME: The tests for OBJ_ELF and ! target_oabi are only here
9807 because I have not worked out how to do this for OBJ_COFF or
9810 && fixP
->fx_addsy
!= NULL
9811 && S_IS_DEFINED (fixP
->fx_addsy
)
9812 && S_GET_SEGMENT (fixP
->fx_addsy
) == seg
)
9814 /* Get pc relative value to go into the branch. */
9817 /* Permit a backward branch provided that enough bits
9818 are set. Allow a forwards branch, provided that
9819 enough bits are clear. */
9820 if ( (value
& ~ ((offsetT
) 0x1ffffff)) == ~ ((offsetT
) 0x1ffffff)
9821 || (value
& ~ ((offsetT
) 0x1ffffff)) == 0)
9825 if (! fixP
->fx_done
)
9827 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9828 _("GAS can't handle same-section branch dest >= 0x04000000"));
9832 value
+= SEXT24 (newval
);
9834 if ( (value
& ~ ((offsetT
) 0xffffff)) != 0
9835 && ((value
& ~ ((offsetT
) 0xffffff)) != ~ ((offsetT
) 0xffffff)))
9836 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9837 _("out of range branch"));
9839 newval
= (value
& 0x00ffffff) | (newval
& 0xff000000);
9840 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9843 case BFD_RELOC_ARM_PCREL_BLX
:
9846 newval
= md_chars_to_number (buf
, INSN_SIZE
);
9850 value
= fixP
->fx_offset
;
9852 hbit
= (value
>> 1) & 1;
9853 value
= (value
>> 2) & 0x00ffffff;
9854 value
= (value
+ (newval
& 0x00ffffff)) & 0x00ffffff;
9855 newval
= value
| (newval
& 0xfe000000) | (hbit
<< 24);
9856 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9860 case BFD_RELOC_THUMB_PCREL_BRANCH9
: /* Conditional branch. */
9861 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9863 addressT diff
= (newval
& 0xff) << 1;
9868 if ((value
& ~0xff) && ((value
& ~0xff) != ~0xff))
9869 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9870 _("branch out of range"));
9871 newval
= (newval
& 0xff00) | ((value
& 0x1ff) >> 1);
9873 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9876 case BFD_RELOC_THUMB_PCREL_BRANCH12
: /* Unconditional branch. */
9877 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9879 addressT diff
= (newval
& 0x7ff) << 1;
9884 if ((value
& ~0x7ff) && ((value
& ~0x7ff) != ~0x7ff))
9885 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9886 _("branch out of range"));
9887 newval
= (newval
& 0xf800) | ((value
& 0xfff) >> 1);
9889 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9892 case BFD_RELOC_THUMB_PCREL_BLX
:
9893 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
9898 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9899 newval2
= md_chars_to_number (buf
+ THUMB_SIZE
, THUMB_SIZE
);
9900 diff
= ((newval
& 0x7ff) << 12) | ((newval2
& 0x7ff) << 1);
9901 if (diff
& 0x400000)
9904 value
= fixP
->fx_offset
;
9907 if ((value
& ~0x3fffff) && ((value
& ~0x3fffff) != ~0x3fffff))
9908 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9909 _("branch with link out of range"));
9911 newval
= (newval
& 0xf800) | ((value
& 0x7fffff) >> 12);
9912 newval2
= (newval2
& 0xf800) | ((value
& 0xfff) >> 1);
9913 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
)
9914 /* Remove bit zero of the adjusted offset. Bit zero can only be
9915 set if the upper insn is at a half-word boundary, since the
9916 destination address, an ARM instruction, must always be on a
9917 word boundary. The semantics of the BLX (1) instruction, however,
9918 are that bit zero in the offset must always be zero, and the
9919 corresponding bit one in the target address will be set from bit
9920 one of the source address. */
9922 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
9923 md_number_to_chars (buf
+ THUMB_SIZE
, newval2
, THUMB_SIZE
);
9928 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9929 md_number_to_chars (buf
, value
, 1);
9931 else if (!target_oabi
)
9933 value
= fixP
->fx_offset
;
9934 md_number_to_chars (buf
, value
, 1);
9940 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9941 md_number_to_chars (buf
, value
, 2);
9943 else if (!target_oabi
)
9945 value
= fixP
->fx_offset
;
9946 md_number_to_chars (buf
, value
, 2);
9952 case BFD_RELOC_ARM_GOT32
:
9953 case BFD_RELOC_ARM_GOTOFF
:
9954 md_number_to_chars (buf
, 0, 4);
9960 if (fixP
->fx_done
|| fixP
->fx_pcrel
)
9961 md_number_to_chars (buf
, value
, 4);
9963 else if (!target_oabi
)
9965 value
= fixP
->fx_offset
;
9966 md_number_to_chars (buf
, value
, 4);
9972 case BFD_RELOC_ARM_PLT32
:
9973 /* It appears the instruction is fully prepared at this point. */
9977 case BFD_RELOC_ARM_GOTPC
:
9978 md_number_to_chars (buf
, value
, 4);
9981 case BFD_RELOC_ARM_CP_OFF_IMM
:
9983 if (value
< -1023 || value
> 1023 || (value
& 3))
9984 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
9985 _("illegal value for co-processor offset"));
9988 newval
= md_chars_to_number (buf
, INSN_SIZE
) & 0xff7fff00;
9989 newval
|= (value
>> 2) | (sign
? INDEX_UP
: 0);
9990 md_number_to_chars (buf
, newval
, INSN_SIZE
);
9993 case BFD_RELOC_ARM_THUMB_OFFSET
:
9994 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
9995 /* Exactly what ranges, and where the offset is inserted depends
9996 on the type of instruction, we can establish this from the
9998 switch (newval
>> 12)
10000 case 4: /* PC load. */
10001 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
10002 forced to zero for these loads, so we will need to round
10003 up the offset if the instruction address is not word
10004 aligned (since the final address produced must be, and
10005 we can only describe word-aligned immediate offsets). */
10007 if ((fixP
->fx_frag
->fr_address
+ fixP
->fx_where
+ value
) & 3)
10008 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10009 _("invalid offset, target not word aligned (0x%08X)"),
10010 (unsigned int) (fixP
->fx_frag
->fr_address
10011 + fixP
->fx_where
+ value
));
10013 if ((value
+ 2) & ~0x3fe)
10014 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10015 _("invalid offset, value too big (0x%08lX)"), value
);
10017 /* Round up, since pc will be rounded down. */
10018 newval
|= (value
+ 2) >> 2;
10021 case 9: /* SP load/store. */
10022 if (value
& ~0x3fc)
10023 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10024 _("invalid offset, value too big (0x%08lX)"), value
);
10025 newval
|= value
>> 2;
10028 case 6: /* Word load/store. */
10030 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10031 _("invalid offset, value too big (0x%08lX)"), value
);
10032 newval
|= value
<< 4; /* 6 - 2. */
10035 case 7: /* Byte load/store. */
10037 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10038 _("invalid offset, value too big (0x%08lX)"), value
);
10039 newval
|= value
<< 6;
10042 case 8: /* Halfword load/store. */
10044 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10045 _("invalid offset, value too big (0x%08lX)"), value
);
10046 newval
|= value
<< 5; /* 6 - 1. */
10050 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10051 "Unable to process relocation for thumb opcode: %lx",
10052 (unsigned long) newval
);
10055 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10058 case BFD_RELOC_ARM_THUMB_ADD
:
10059 /* This is a complicated relocation, since we use it for all of
10060 the following immediate relocations:
10064 9bit ADD/SUB SP word-aligned
10065 10bit ADD PC/SP word-aligned
10067 The type of instruction being processed is encoded in the
10074 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10076 int rd
= (newval
>> 4) & 0xf;
10077 int rs
= newval
& 0xf;
10078 int subtract
= newval
& 0x8000;
10082 if (value
& ~0x1fc)
10083 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10084 _("invalid immediate for stack address calculation"));
10085 newval
= subtract
? T_OPCODE_SUB_ST
: T_OPCODE_ADD_ST
;
10086 newval
|= value
>> 2;
10088 else if (rs
== REG_PC
|| rs
== REG_SP
)
10092 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10093 _("invalid immediate for address calculation (value = 0x%08lX)"),
10094 (unsigned long) value
);
10095 newval
= (rs
== REG_PC
? T_OPCODE_ADD_PC
: T_OPCODE_ADD_SP
);
10097 newval
|= value
>> 2;
10102 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10103 _("invalid 8bit immediate"));
10104 newval
= subtract
? T_OPCODE_SUB_I8
: T_OPCODE_ADD_I8
;
10105 newval
|= (rd
<< 8) | value
;
10110 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10111 _("invalid 3bit immediate"));
10112 newval
= subtract
? T_OPCODE_SUB_I3
: T_OPCODE_ADD_I3
;
10113 newval
|= rd
| (rs
<< 3) | (value
<< 6);
10116 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10119 case BFD_RELOC_ARM_THUMB_IMM
:
10120 newval
= md_chars_to_number (buf
, THUMB_SIZE
);
10121 switch (newval
>> 11)
10123 case 0x04: /* 8bit immediate MOV. */
10124 case 0x05: /* 8bit immediate CMP. */
10125 if (value
< 0 || value
> 255)
10126 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10127 _("invalid immediate: %ld is too large"),
10135 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10138 case BFD_RELOC_ARM_THUMB_SHIFT
:
10139 /* 5bit shift value (0..31). */
10140 if (value
< 0 || value
> 31)
10141 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10142 _("illegal Thumb shift value: %ld"), (long) value
);
10143 newval
= md_chars_to_number (buf
, THUMB_SIZE
) & 0xf03f;
10144 newval
|= value
<< 6;
10145 md_number_to_chars (buf
, newval
, THUMB_SIZE
);
10148 case BFD_RELOC_VTABLE_INHERIT
:
10149 case BFD_RELOC_VTABLE_ENTRY
:
10153 case BFD_RELOC_NONE
:
10155 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
10156 _("bad relocation fixup type (%d)"), fixP
->fx_r_type
);
10160 /* Translate internal representation of relocation info to BFD target
10164 tc_gen_reloc (section
, fixp
)
10165 asection
* section ATTRIBUTE_UNUSED
;
10169 bfd_reloc_code_real_type code
;
10171 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
10173 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
10174 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
10175 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
10177 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
10179 if (fixp
->fx_pcrel
== 0)
10180 reloc
->addend
= fixp
->fx_offset
;
10182 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
10183 #else /* OBJ_ELF */
10184 reloc
->addend
= fixp
->fx_offset
;
10187 switch (fixp
->fx_r_type
)
10190 if (fixp
->fx_pcrel
)
10192 code
= BFD_RELOC_8_PCREL
;
10197 if (fixp
->fx_pcrel
)
10199 code
= BFD_RELOC_16_PCREL
;
10204 if (fixp
->fx_pcrel
)
10206 code
= BFD_RELOC_32_PCREL
;
10210 case BFD_RELOC_ARM_PCREL_BRANCH
:
10211 case BFD_RELOC_ARM_PCREL_BLX
:
10212 case BFD_RELOC_RVA
:
10213 case BFD_RELOC_THUMB_PCREL_BRANCH9
:
10214 case BFD_RELOC_THUMB_PCREL_BRANCH12
:
10215 case BFD_RELOC_THUMB_PCREL_BRANCH23
:
10216 case BFD_RELOC_THUMB_PCREL_BLX
:
10217 case BFD_RELOC_VTABLE_ENTRY
:
10218 case BFD_RELOC_VTABLE_INHERIT
:
10219 code
= fixp
->fx_r_type
;
10222 case BFD_RELOC_ARM_LITERAL
:
10223 case BFD_RELOC_ARM_HWLITERAL
:
10224 /* If this is called then the a literal has been referenced across
10225 a section boundary - possibly due to an implicit dump. */
10226 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10227 _("literal referenced across section boundary (Implicit dump?)"));
10231 case BFD_RELOC_ARM_GOT32
:
10232 case BFD_RELOC_ARM_GOTOFF
:
10233 case BFD_RELOC_ARM_PLT32
:
10234 code
= fixp
->fx_r_type
;
10238 case BFD_RELOC_ARM_IMMEDIATE
:
10239 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10240 _("internal relocation (type %d) not fixed up (IMMEDIATE)"),
10244 case BFD_RELOC_ARM_ADRL_IMMEDIATE
:
10245 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10246 _("ADRL used for a symbol not defined in the same file"));
10249 case BFD_RELOC_ARM_OFFSET_IMM
:
10250 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10251 _("internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
10259 switch (fixp
->fx_r_type
)
10261 case BFD_RELOC_ARM_IMMEDIATE
: type
= "IMMEDIATE"; break;
10262 case BFD_RELOC_ARM_OFFSET_IMM
: type
= "OFFSET_IMM"; break;
10263 case BFD_RELOC_ARM_OFFSET_IMM8
: type
= "OFFSET_IMM8"; break;
10264 case BFD_RELOC_ARM_SHIFT_IMM
: type
= "SHIFT_IMM"; break;
10265 case BFD_RELOC_ARM_SWI
: type
= "SWI"; break;
10266 case BFD_RELOC_ARM_MULTI
: type
= "MULTI"; break;
10267 case BFD_RELOC_ARM_CP_OFF_IMM
: type
= "CP_OFF_IMM"; break;
10268 case BFD_RELOC_ARM_THUMB_ADD
: type
= "THUMB_ADD"; break;
10269 case BFD_RELOC_ARM_THUMB_SHIFT
: type
= "THUMB_SHIFT"; break;
10270 case BFD_RELOC_ARM_THUMB_IMM
: type
= "THUMB_IMM"; break;
10271 case BFD_RELOC_ARM_THUMB_OFFSET
: type
= "THUMB_OFFSET"; break;
10272 default: type
= _("<unknown>"); break;
10274 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10275 _("cannot represent %s relocation in this object file format"),
10282 if (code
== BFD_RELOC_32_PCREL
10284 && fixp
->fx_addsy
== GOT_symbol
)
10286 code
= BFD_RELOC_ARM_GOTPC
;
10287 reloc
->addend
= fixp
->fx_offset
= reloc
->address
;
10291 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
10293 if (reloc
->howto
== NULL
)
10295 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
10296 _("cannot represent %s relocation in this object file format"),
10297 bfd_get_reloc_code_name (code
));
10301 /* HACK: Since arm ELF uses Rel instead of Rela, encode the
10302 vtable entry to be used in the relocation's section offset. */
10303 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
10304 reloc
->address
= fixp
->fx_offset
;
10310 md_estimate_size_before_relax (fragP
, segtype
)
10311 fragS
* fragP ATTRIBUTE_UNUSED
;
10312 segT segtype ATTRIBUTE_UNUSED
;
10314 as_fatal (_("md_estimate_size_before_relax\n"));
10326 as_bad ("%s -- `%s'", inst
.error
, str
);
10330 to
= frag_more (inst
.size
);
10332 if (thumb_mode
&& (inst
.size
> THUMB_SIZE
))
10334 assert (inst
.size
== (2 * THUMB_SIZE
));
10335 md_number_to_chars (to
, inst
.instruction
>> 16, THUMB_SIZE
);
10336 md_number_to_chars (to
+ THUMB_SIZE
, inst
.instruction
, THUMB_SIZE
);
10338 else if (inst
.size
> INSN_SIZE
)
10340 assert (inst
.size
== (2 * INSN_SIZE
));
10341 md_number_to_chars (to
, inst
.instruction
, INSN_SIZE
);
10342 md_number_to_chars (to
+ INSN_SIZE
, inst
.instruction
, INSN_SIZE
);
10345 md_number_to_chars (to
, inst
.instruction
, inst
.size
);
10347 if (inst
.reloc
.type
!= BFD_RELOC_NONE
)
10348 fix_new_arm (frag_now
, to
- frag_now
->fr_literal
,
10349 inst
.size
, & inst
.reloc
.exp
, inst
.reloc
.pc_rel
,
10353 dwarf2_emit_insn (inst
.size
);
10365 /* Align the instruction.
10366 This may not be the right thing to do but ... */
10370 listing_prev_line (); /* Defined in listing.h. */
10372 /* Align the previous label if needed. */
10373 if (last_label_seen
!= NULL
)
10375 symbol_set_frag (last_label_seen
, frag_now
);
10376 S_SET_VALUE (last_label_seen
, (valueT
) frag_now_fix ());
10377 S_SET_SEGMENT (last_label_seen
, now_seg
);
10380 memset (&inst
, '\0', sizeof (inst
));
10381 inst
.reloc
.type
= BFD_RELOC_NONE
;
10383 skip_whitespace (str
);
10385 /* Scan up to the end of the op-code, which must end in white space or
10387 for (start
= p
= str
; *p
!= '\0'; p
++)
10393 as_bad (_("no operator -- statement `%s'\n"), str
);
10399 const struct thumb_opcode
* opcode
;
10403 opcode
= (const struct thumb_opcode
*) hash_find (arm_tops_hsh
, str
);
10408 /* Check that this instruction is supported for this CPU. */
10409 if (thumb_mode
== 1 && (opcode
->variant
& cpu_variant
) == 0)
10411 as_bad (_("selected processor does not support `%s'"), str
);
10415 inst
.instruction
= opcode
->value
;
10416 inst
.size
= opcode
->size
;
10417 (*opcode
->parms
) (p
);
10424 const struct asm_opcode
* opcode
;
10428 opcode
= (const struct asm_opcode
*) hash_find (arm_ops_hsh
, str
);
10433 /* Check that this instruction is supported for this CPU. */
10434 if ((opcode
->variant
& cpu_variant
) == 0)
10436 as_bad (_("selected processor does not support `%s'"), str
);
10440 inst
.instruction
= opcode
->value
;
10441 inst
.size
= INSN_SIZE
;
10442 (*opcode
->parms
) (p
);
10448 /* It wasn't an instruction, but it might be a register alias of the form
10450 if (create_register_alias (str
, p
))
10453 as_bad (_("bad instruction `%s'"), start
);
10457 Invocation line includes a switch not recognized by the base assembler.
10458 See if it's a processor-specific option.
10460 This routine is somewhat complicated by the need for backwards
10461 compatibility (since older releases of gcc can't be changed).
10462 The new options try to make the interface as compatible as
10465 New options (supported) are:
10467 -mcpu=<cpu name> Assemble for selected processor
10468 -march=<architecture name> Assemble for selected architecture
10469 -mfpu=<fpu architecture> Assemble for selected FPU.
10470 -EB/-mbig-endian Big-endian
10471 -EL/-mlittle-endian Little-endian
10472 -k Generate PIC code
10473 -mthumb Start in Thumb mode
10474 -mthumb-interwork Code supports ARM/Thumb interworking
10476 For now we will also provide support for
10478 -mapcs-32 32-bit Program counter
10479 -mapcs-26 26-bit Program counter
10480 -macps-float Floats passed in FP registers
10481 -mapcs-reentrant Reentrant code
10483 (sometime these will probably be replaced with -mapcs=<list of options>
10484 and -matpcs=<list of options>)
10486 The remaining options are only supported for back-wards compatibility.
10487 Cpu variants, the arm part is optional:
10488 -m[arm]1 Currently not supported.
10489 -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
10490 -m[arm]3 Arm 3 processor
10491 -m[arm]6[xx], Arm 6 processors
10492 -m[arm]7[xx][t][[d]m] Arm 7 processors
10493 -m[arm]8[10] Arm 8 processors
10494 -m[arm]9[20][tdmi] Arm 9 processors
10495 -marm9e Allow Cirrus/DSP instructions
10496 -mstrongarm[110[0]] StrongARM processors
10497 -mxscale XScale processors
10498 -m[arm]v[2345[t[e]]] Arm architectures
10499 -mall All (except the ARM1)
10501 -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
10502 -mfpe-old (No float load/store multiples)
10503 -mvfpxd VFP Single precision
10505 -mno-fpu Disable all floating point instructions
10507 The following CPU names are recognized:
10508 arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
10509 arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
10510 arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
10511 arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
10512 arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
10513 arm10t arm10e, arm1020t, arm1020e, arm10200e,
10514 strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
10518 CONST
char * md_shortopts
= "m:k";
10520 #ifdef ARM_BI_ENDIAN
10521 #define OPTION_EB (OPTION_MD_BASE + 0)
10522 #define OPTION_EL (OPTION_MD_BASE + 1)
10524 #if TARGET_BYTES_BIG_ENDIAN
10525 #define OPTION_EB (OPTION_MD_BASE + 0)
10527 #define OPTION_EL (OPTION_MD_BASE + 1)
10531 struct option md_longopts
[] =
10534 {"EB", no_argument
, NULL
, OPTION_EB
},
10537 {"EL", no_argument
, NULL
, OPTION_EL
},
10539 {NULL
, no_argument
, NULL
, 0}
10542 size_t md_longopts_size
= sizeof (md_longopts
);
10544 struct arm_option_table
10546 char *option
; /* Option name to match. */
10547 char *help
; /* Help information. */
10548 int *var
; /* Variable to change. */
10549 int value
; /* What to change it to. */
10550 char *deprecated
; /* If non-null, print this message. */
10553 struct arm_option_table arm_opts
[] =
10555 {"k", N_("generate PIC code"), &pic_code
, 1, NULL
},
10556 {"mthumb", N_("assemble Thumb code"), &thumb_mode
, 1, NULL
},
10557 {"mthumb-interwork", N_("support ARM/Thumb interworking"),
10558 &support_interwork
, 1, NULL
},
10559 {"moabi", N_("use old ABI (ELF only)"), &target_oabi
, 1, NULL
},
10560 {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26
, 0, NULL
},
10561 {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26
, 1, NULL
},
10562 {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float
,
10564 {"mapcs-reentrant", N_("re-entrant code"), &pic_code
, 1, NULL
},
10565 {"matpcs", N_("code is ATPCS conformant"), &atpcs
, 1, NULL
},
10566 {"mbig-endian", N_("assemble for big-endian"), &target_big_endian
, 1, NULL
},
10567 {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian
, 1,
10570 /* These are recognized by the assembler, but have no affect on code. */
10571 {"mapcs-frame", N_("use frame pointer"), NULL
, 0, NULL
},
10572 {"mapcs-stack-check", N_("use stack size checking"), NULL
, 0, NULL
},
10574 /* DON'T add any new processors to this list -- we want the whole list
10575 to go away... Add them to the processors table instead. */
10576 {"marm1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
10577 {"m1", NULL
, &legacy_cpu
, ARM_ARCH_V1
, N_("use -mcpu=arm1")},
10578 {"marm2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
10579 {"m2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -mcpu=arm2")},
10580 {"marm250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
10581 {"m250", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm250")},
10582 {"marm3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
10583 {"m3", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -mcpu=arm3")},
10584 {"marm6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
10585 {"m6", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm6")},
10586 {"marm600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
10587 {"m600", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm600")},
10588 {"marm610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
10589 {"m610", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm610")},
10590 {"marm620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
10591 {"m620", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm620")},
10592 {"marm7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
10593 {"m7", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7")},
10594 {"marm70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
10595 {"m70", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm70")},
10596 {"marm700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
10597 {"m700", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700")},
10598 {"marm700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
10599 {"m700i", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm700i")},
10600 {"marm710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
10601 {"m710", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710")},
10602 {"marm710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
10603 {"m710c", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm710c")},
10604 {"marm720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
10605 {"m720", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm720")},
10606 {"marm7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
10607 {"m7d", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7d")},
10608 {"marm7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
10609 {"m7di", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7di")},
10610 {"marm7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
10611 {"m7m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7m")},
10612 {"marm7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
10613 {"m7dm", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dm")},
10614 {"marm7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
10615 {"m7dmi", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -mcpu=arm7dmi")},
10616 {"marm7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
10617 {"m7100", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7100")},
10618 {"marm7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
10619 {"m7500", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500")},
10620 {"marm7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
10621 {"m7500fe", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -mcpu=arm7500fe")},
10622 {"marm7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10623 {"m7t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10624 {"marm7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10625 {"m7tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm7tdmi")},
10626 {"marm710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
10627 {"m710t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm710t")},
10628 {"marm720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
10629 {"m720t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm720t")},
10630 {"marm740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
10631 {"m740t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm740t")},
10632 {"marm8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
10633 {"m8", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm8")},
10634 {"marm810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
10635 {"m810", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=arm810")},
10636 {"marm9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
10637 {"m9", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9")},
10638 {"marm9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
10639 {"m9tdmi", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm9tdmi")},
10640 {"marm920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
10641 {"m920", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm920")},
10642 {"marm940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
10643 {"m940", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -mcpu=arm940")},
10644 {"mstrongarm", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -mcpu=strongarm")},
10645 {"mstrongarm110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10646 N_("use -mcpu=strongarm110")},
10647 {"mstrongarm1100", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10648 N_("use -mcpu=strongarm1100")},
10649 {"mstrongarm1110", NULL
, &legacy_cpu
, ARM_ARCH_V4
,
10650 N_("use -mcpu=strongarm1110")},
10651 {"mxscale", NULL
, &legacy_cpu
, ARM_ARCH_XSCALE
, N_("use -mcpu=xscale")},
10652 {"mall", NULL
, &legacy_cpu
, ARM_ANY
, N_("use -mcpu=all")},
10654 /* Architecture variants -- don't add any more to this list either. */
10655 {"mv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
10656 {"marmv2", NULL
, &legacy_cpu
, ARM_ARCH_V2
, N_("use -march=armv2")},
10657 {"mv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
10658 {"marmv2a", NULL
, &legacy_cpu
, ARM_ARCH_V2S
, N_("use -march=armv2a")},
10659 {"mv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
10660 {"marmv3", NULL
, &legacy_cpu
, ARM_ARCH_V3
, N_("use -march=armv3")},
10661 {"mv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
10662 {"marmv3m", NULL
, &legacy_cpu
, ARM_ARCH_V3M
, N_("use -march=armv3m")},
10663 {"mv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
10664 {"marmv4", NULL
, &legacy_cpu
, ARM_ARCH_V4
, N_("use -march=armv4")},
10665 {"mv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
10666 {"marmv4t", NULL
, &legacy_cpu
, ARM_ARCH_V4T
, N_("use -march=armv4t")},
10667 {"mv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
10668 {"marmv5", NULL
, &legacy_cpu
, ARM_ARCH_V5
, N_("use -march=armv5")},
10669 {"mv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
10670 {"marmv5t", NULL
, &legacy_cpu
, ARM_ARCH_V5T
, N_("use -march=armv5t")},
10671 {"mv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
10672 {"marmv5e", NULL
, &legacy_cpu
, ARM_ARCH_V5TE
, N_("use -march=armv5te")},
10674 /* Floating point variants -- don't add any more to this list either. */
10675 {"mfpe-old", NULL
, &legacy_fpu
, FPU_ARCH_FPE
, N_("use -mfpu=fpe")},
10676 {"mfpa10", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa10")},
10677 {"mfpa11", NULL
, &legacy_fpu
, FPU_ARCH_FPA
, N_("use -mfpu=fpa11")},
10678 {"mno-fpu", NULL
, &legacy_fpu
, 0,
10679 N_("use either -mfpu=softfpa or -mfpu=softvfp")},
10681 {NULL
, NULL
, NULL
, 0, NULL
}
10684 struct arm_cpu_option_table
10688 /* For some CPUs we assume an FPU unless the user explicitly sets
10693 /* This list should, at a minimum, contain all the cpu names
10694 recognized by GCC. */
10695 static struct arm_cpu_option_table arm_cpus
[] =
10697 {"all", ARM_ANY
, FPU_ARCH_FPA
},
10698 {"arm1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
10699 {"arm2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
10700 {"arm250", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10701 {"arm3", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10702 {"arm6", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10703 {"arm60", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10704 {"arm600", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10705 {"arm610", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10706 {"arm620", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10707 {"arm7", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10708 {"arm7m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10709 {"arm7d", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10710 {"arm7dm", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10711 {"arm7di", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10712 {"arm7dmi", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10713 {"arm70", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10714 {"arm700", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10715 {"arm700i", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10716 {"arm710", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10717 {"arm710t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10718 {"arm720", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10719 {"arm720t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10720 {"arm740t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10721 {"arm710c", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10722 {"arm7100", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10723 {"arm7500", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10724 {"arm7500fe", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10725 {"arm7t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10726 {"arm7tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10727 {"arm8", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10728 {"arm810", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10729 {"strongarm", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10730 {"strongarm1", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10731 {"strongarm110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10732 {"strongarm1100", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10733 {"strongarm1110", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10734 {"arm9", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10735 {"arm920", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10736 {"arm920t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10737 {"arm922t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10738 {"arm940t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10739 {"arm9tdmi", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10740 /* For V5 or later processors we default to using VFP; but the user
10741 should really set the FPU type explicitly. */
10742 {"arm9e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10743 {"arm9e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10744 {"arm946e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10745 {"arm946e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10746 {"arm966e-r0", ARM_ARCH_V5TExP
, FPU_ARCH_VFP_V2
},
10747 {"arm966e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10748 {"arm10t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
10749 {"arm10e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10750 {"arm1020", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10751 {"arm1020t", ARM_ARCH_V5T
, FPU_ARCH_VFP_V1
},
10752 {"arm1020e", ARM_ARCH_V5TE
, FPU_ARCH_VFP_V2
},
10753 /* ??? XSCALE is really an architecture. */
10754 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
10755 {"i80200", ARM_ARCH_XSCALE
, FPU_ARCH_VFP_V2
},
10757 {"ep9312", ARM_ARCH_V4T
| ARM_CEXT_MAVERICK
, FPU_NONE
},
10761 struct arm_arch_option_table
10768 /* This list should, at a minimum, contain all the architecture names
10769 recognized by GCC. */
10770 static struct arm_arch_option_table arm_archs
[] =
10772 {"all", ARM_ANY
, FPU_ARCH_FPA
},
10773 {"armv1", ARM_ARCH_V1
, FPU_ARCH_FPA
},
10774 {"armv2", ARM_ARCH_V2
, FPU_ARCH_FPA
},
10775 {"armv2a", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10776 {"armv2s", ARM_ARCH_V2S
, FPU_ARCH_FPA
},
10777 {"armv3", ARM_ARCH_V3
, FPU_ARCH_FPA
},
10778 {"armv3m", ARM_ARCH_V3M
, FPU_ARCH_FPA
},
10779 {"armv4", ARM_ARCH_V4
, FPU_ARCH_FPA
},
10780 {"armv4xm", ARM_ARCH_V4xM
, FPU_ARCH_FPA
},
10781 {"armv4t", ARM_ARCH_V4T
, FPU_ARCH_FPA
},
10782 {"armv4txm", ARM_ARCH_V4TxM
, FPU_ARCH_FPA
},
10783 {"armv5", ARM_ARCH_V5
, FPU_ARCH_VFP
},
10784 {"armv5t", ARM_ARCH_V5T
, FPU_ARCH_VFP
},
10785 {"armv5txm", ARM_ARCH_V5TxM
, FPU_ARCH_VFP
},
10786 {"armv5te", ARM_ARCH_V5TE
, FPU_ARCH_VFP
},
10787 {"armv5texp", ARM_ARCH_V5TExP
, FPU_ARCH_VFP
},
10788 {"xscale", ARM_ARCH_XSCALE
, FPU_ARCH_VFP
},
10792 /* ISA extensions in the co-processor space. */
10793 struct arm_arch_extension_table
10799 static struct arm_arch_extension_table arm_extensions
[] =
10801 {"maverick", ARM_CEXT_MAVERICK
},
10802 {"xscale", ARM_CEXT_XSCALE
},
10806 struct arm_fpu_option_table
10812 /* This list should, at a minimum, contain all the fpu names
10813 recognized by GCC. */
10814 static struct arm_fpu_option_table arm_fpus
[] =
10816 {"softfpa", FPU_NONE
},
10817 {"fpe", FPU_ARCH_FPE
},
10818 {"fpe2", FPU_ARCH_FPE
},
10819 {"fpe3", FPU_ARCH_FPA
}, /* Third release supports LFM/SFM. */
10820 {"fpa", FPU_ARCH_FPA
},
10821 {"fpa10", FPU_ARCH_FPA
},
10822 {"fpa11", FPU_ARCH_FPA
},
10823 {"arm7500fe", FPU_ARCH_FPA
},
10824 {"softvfp", FPU_ARCH_VFP
},
10825 {"softvfp+vfp", FPU_ARCH_VFP_V2
},
10826 {"vfp", FPU_ARCH_VFP_V2
},
10827 {"vfp9", FPU_ARCH_VFP_V2
},
10828 {"vfp10", FPU_ARCH_VFP_V2
},
10829 {"vfp10-r0", FPU_ARCH_VFP_V1
},
10830 {"vfpxd", FPU_ARCH_VFP_V1xD
},
10831 {"arm1020t", FPU_ARCH_VFP_V1
},
10832 {"arm1020e", FPU_ARCH_VFP_V2
},
10836 struct arm_long_option_table
10838 char *option
; /* Substring to match. */
10839 char *help
; /* Help information. */
10840 int (*func
) PARAMS ((char *subopt
)); /* Function to decode sub-option. */
10841 char *deprecated
; /* If non-null, print this message. */
10845 arm_parse_extension (str
, opt_p
)
10849 while (str
!= NULL
&& *str
!= 0)
10851 struct arm_arch_extension_table
*opt
;
10857 as_bad (_("invalid architectural extension"));
10862 ext
= strchr (str
, '+');
10865 optlen
= ext
- str
;
10867 optlen
= strlen (str
);
10871 as_bad (_("missing architectural extension"));
10875 for (opt
= arm_extensions
; opt
->name
!= NULL
; opt
++)
10876 if (strncmp (opt
->name
, str
, optlen
) == 0)
10878 *opt_p
|= opt
->value
;
10882 if (opt
->name
== NULL
)
10884 as_bad (_("unknown architectural extnsion `%s'"), str
);
10895 arm_parse_cpu (str
)
10898 struct arm_cpu_option_table
*opt
;
10899 char *ext
= strchr (str
, '+');
10903 optlen
= ext
- str
;
10905 optlen
= strlen (str
);
10909 as_bad (_("missing cpu name `%s'"), str
);
10913 for (opt
= arm_cpus
; opt
->name
!= NULL
; opt
++)
10914 if (strncmp (opt
->name
, str
, optlen
) == 0)
10916 mcpu_cpu_opt
= opt
->value
;
10917 mcpu_fpu_opt
= opt
->default_fpu
;
10920 return arm_parse_extension (ext
, &mcpu_cpu_opt
);
10925 as_bad (_("unknown cpu `%s'"), str
);
10930 arm_parse_arch (str
)
10933 struct arm_arch_option_table
*opt
;
10934 char *ext
= strchr (str
, '+');
10938 optlen
= ext
- str
;
10940 optlen
= strlen (str
);
10944 as_bad (_("missing architecture name `%s'"), str
);
10949 for (opt
= arm_archs
; opt
->name
!= NULL
; opt
++)
10950 if (strcmp (opt
->name
, str
) == 0)
10952 march_cpu_opt
= opt
->value
;
10953 march_fpu_opt
= opt
->default_fpu
;
10956 return arm_parse_extension (ext
, &march_cpu_opt
);
10961 as_bad (_("unknown architecture `%s'\n"), str
);
10966 arm_parse_fpu (str
)
10969 struct arm_fpu_option_table
*opt
;
10971 for (opt
= arm_fpus
; opt
->name
!= NULL
; opt
++)
10972 if (strcmp (opt
->name
, str
) == 0)
10974 mfpu_opt
= opt
->value
;
10978 as_bad (_("unknown floating point format `%s'\n"), str
);
10982 struct arm_long_option_table arm_long_opts
[] =
10984 {"mcpu=", N_("<cpu name>\t assemble for CPU <cpu name>"),
10985 arm_parse_cpu
, NULL
},
10986 {"march=", N_("<arch name>\t assemble for architecture <arch name>"),
10987 arm_parse_arch
, NULL
},
10988 {"mfpu=", N_("<fpu name>\t assemble for FPU architecture <fpu name>"),
10989 arm_parse_fpu
, NULL
},
10990 {NULL
, NULL
, 0, NULL
}
10994 md_parse_option (c
, arg
)
10998 struct arm_option_table
*opt
;
10999 struct arm_long_option_table
*lopt
;
11005 target_big_endian
= 1;
11011 target_big_endian
= 0;
11016 /* Listing option. Just ignore these, we don't support additional
11021 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
11023 if (c
== opt
->option
[0]
11024 && ((arg
== NULL
&& opt
->option
[1] == 0)
11025 || strcmp (arg
, opt
->option
+ 1) == 0))
11027 #if WARN_DEPRECATED
11028 /* If the option is deprecated, tell the user. */
11029 if (opt
->deprecated
!= NULL
)
11030 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
,
11031 arg
? arg
: "", _(opt
->deprecated
));
11034 if (opt
->var
!= NULL
)
11035 *opt
->var
= opt
->value
;
11041 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
11043 /* These options are expected to have an argument. */
11044 if (c
== lopt
->option
[0]
11046 && strncmp (arg
, lopt
->option
+ 1,
11047 strlen (lopt
->option
+ 1)) == 0)
11049 #if WARN_DEPRECATED
11050 /* If the option is deprecated, tell the user. */
11051 if (lopt
->deprecated
!= NULL
)
11052 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c
, arg
,
11053 _(lopt
->deprecated
));
11056 /* Call the sup-option parser. */
11057 return (*lopt
->func
)(arg
+ strlen (lopt
->option
) - 1);
11061 as_bad (_("unrecognized option `-%c%s'"), c
, arg
? arg
: "");
11072 struct arm_option_table
*opt
;
11073 struct arm_long_option_table
*lopt
;
11075 fprintf (fp
, _(" ARM-specific assembler options:\n"));
11077 for (opt
= arm_opts
; opt
->option
!= NULL
; opt
++)
11078 if (opt
->help
!= NULL
)
11079 fprintf (fp
, " -%-23s%s\n", opt
->option
, _(opt
->help
));
11081 for (lopt
= arm_long_opts
; lopt
->option
!= NULL
; lopt
++)
11082 if (lopt
->help
!= NULL
)
11083 fprintf (fp
, " -%s%s\n", lopt
->option
, _(lopt
->help
));
11087 -EB assemble code for a big-endian cpu\n"));
11092 -EL assemble code for a little-endian cpu\n"));
11096 /* We need to be able to fix up arbitrary expressions in some statements.
11097 This is so that we can handle symbols that are an arbitrary distance from
11098 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
11099 which returns part of an address in a form which will be valid for
11100 a data instruction. We do this by pushing the expression into a symbol
11101 in the expr_section, and creating a fix for that. */
11104 fix_new_arm (frag
, where
, size
, exp
, pc_rel
, reloc
)
11113 arm_fix_data
* arm_data
;
11121 new_fix
= fix_new_exp (frag
, where
, size
, exp
, pc_rel
, reloc
);
11125 new_fix
= fix_new (frag
, where
, size
, make_expr_symbol (exp
), 0,
11130 /* Mark whether the fix is to a THUMB instruction, or an ARM
11132 arm_data
= (arm_fix_data
*) obstack_alloc (& notes
, sizeof (arm_fix_data
));
11133 new_fix
->tc_fix_data
= (PTR
) arm_data
;
11134 arm_data
->thumb_mode
= thumb_mode
;
11139 /* This fix_new is called by cons via TC_CONS_FIX_NEW. */
11142 cons_fix_new_arm (frag
, where
, size
, exp
)
11148 bfd_reloc_code_real_type type
;
11152 FIXME: @@ Should look at CPU word size. */
11156 type
= BFD_RELOC_8
;
11159 type
= BFD_RELOC_16
;
11163 type
= BFD_RELOC_32
;
11166 type
= BFD_RELOC_64
;
11170 fix_new_exp (frag
, where
, (int) size
, exp
, pcrel
, type
);
11173 /* A good place to do this, although this was probably not intended
11174 for this kind of use. We need to dump the literal pool before
11175 references are made to a null symbol pointer. */
11180 if (current_poolP
== NULL
)
11183 /* Put it at the end of text section. */
11184 subseg_set (text_section
, 0);
11186 listing_prev_line ();
11190 arm_start_line_hook ()
11192 last_label_seen
= NULL
;
11196 arm_frob_label (sym
)
11199 last_label_seen
= sym
;
11201 ARM_SET_THUMB (sym
, thumb_mode
);
11203 #if defined OBJ_COFF || defined OBJ_ELF
11204 ARM_SET_INTERWORK (sym
, support_interwork
);
11207 /* Note - do not allow local symbols (.Lxxx) to be labeled
11208 as Thumb functions. This is because these labels, whilst
11209 they exist inside Thumb code, are not the entry points for
11210 possible ARM->Thumb calls. Also, these labels can be used
11211 as part of a computed goto or switch statement. eg gcc
11212 can generate code that looks like this:
11214 ldr r2, [pc, .Laaa]
11224 The first instruction loads the address of the jump table.
11225 The second instruction converts a table index into a byte offset.
11226 The third instruction gets the jump address out of the table.
11227 The fourth instruction performs the jump.
11229 If the address stored at .Laaa is that of a symbol which has the
11230 Thumb_Func bit set, then the linker will arrange for this address
11231 to have the bottom bit set, which in turn would mean that the
11232 address computation performed by the third instruction would end
11233 up with the bottom bit set. Since the ARM is capable of unaligned
11234 word loads, the instruction would then load the incorrect address
11235 out of the jump table, and chaos would ensue. */
11236 if (label_is_thumb_function_name
11237 && (S_GET_NAME (sym
)[0] != '.' || S_GET_NAME (sym
)[1] != 'L')
11238 && (bfd_get_section_flags (stdoutput
, now_seg
) & SEC_CODE
) != 0)
11240 /* When the address of a Thumb function is taken the bottom
11241 bit of that address should be set. This will allow
11242 interworking between Arm and Thumb functions to work
11245 THUMB_SET_FUNC (sym
, 1);
11247 label_is_thumb_function_name
= false;
11251 /* Adjust the symbol table. This marks Thumb symbols as distinct from
11255 arm_adjust_symtab ()
11260 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
11262 if (ARM_IS_THUMB (sym
))
11264 if (THUMB_IS_FUNC (sym
))
11266 /* Mark the symbol as a Thumb function. */
11267 if ( S_GET_STORAGE_CLASS (sym
) == C_STAT
11268 || S_GET_STORAGE_CLASS (sym
) == C_LABEL
) /* This can happen! */
11269 S_SET_STORAGE_CLASS (sym
, C_THUMBSTATFUNC
);
11271 else if (S_GET_STORAGE_CLASS (sym
) == C_EXT
)
11272 S_SET_STORAGE_CLASS (sym
, C_THUMBEXTFUNC
);
11274 as_bad (_("%s: unexpected function type: %d"),
11275 S_GET_NAME (sym
), S_GET_STORAGE_CLASS (sym
));
11277 else switch (S_GET_STORAGE_CLASS (sym
))
11280 S_SET_STORAGE_CLASS (sym
, C_THUMBEXT
);
11283 S_SET_STORAGE_CLASS (sym
, C_THUMBSTAT
);
11286 S_SET_STORAGE_CLASS (sym
, C_THUMBLABEL
);
11294 if (ARM_IS_INTERWORK (sym
))
11295 coffsymbol (symbol_get_bfdsym (sym
))->native
->u
.syment
.n_flags
= 0xFF;
11302 for (sym
= symbol_rootP
; sym
!= NULL
; sym
= symbol_next (sym
))
11304 if (ARM_IS_THUMB (sym
))
11306 elf_symbol_type
* elf_sym
;
11308 elf_sym
= elf_symbol (symbol_get_bfdsym (sym
));
11309 bind
= ELF_ST_BIND (elf_sym
);
11311 /* If it's a .thumb_func, declare it as so,
11312 otherwise tag label as .code 16. */
11313 if (THUMB_IS_FUNC (sym
))
11314 elf_sym
->internal_elf_sym
.st_info
=
11315 ELF_ST_INFO (bind
, STT_ARM_TFUNC
);
11317 elf_sym
->internal_elf_sym
.st_info
=
11318 ELF_ST_INFO (bind
, STT_ARM_16BIT
);
11325 arm_data_in_code ()
11327 if (thumb_mode
&& ! strncmp (input_line_pointer
+ 1, "data:", 5))
11329 *input_line_pointer
= '/';
11330 input_line_pointer
+= 5;
11331 *input_line_pointer
= 0;
11339 arm_canonicalize_symbol_name (name
)
11344 if (thumb_mode
&& (len
= strlen (name
)) > 5
11345 && streq (name
+ len
- 5, "/data"))
11346 *(name
+ len
- 5) = 0;
11352 arm_validate_fix (fixP
)
11355 /* If the destination of the branch is a defined symbol which does not have
11356 the THUMB_FUNC attribute, then we must be calling a function which has
11357 the (interfacearm) attribute. We look for the Thumb entry point to that
11358 function and change the branch to refer to that function instead. */
11359 if (fixP
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
11360 && fixP
->fx_addsy
!= NULL
11361 && S_IS_DEFINED (fixP
->fx_addsy
)
11362 && ! THUMB_IS_FUNC (fixP
->fx_addsy
))
11364 fixP
->fx_addsy
= find_real_start (fixP
->fx_addsy
);
11372 /* This is a little hack to help the gas/arm/adrl.s test. It prevents
11373 local labels from being added to the output symbol table when they
11374 are used with the ADRL pseudo op. The ADRL relocation should always
11375 be resolved before the binbary is emitted, so it is safe to say that
11376 it is adjustable. */
11379 arm_fix_adjustable (fixP
)
11382 if (fixP
->fx_r_type
== BFD_RELOC_ARM_ADRL_IMMEDIATE
)
11388 /* Relocations against Thumb function names must be left unadjusted,
11389 so that the linker can use this information to correctly set the
11390 bottom bit of their addresses. The MIPS version of this function
11391 also prevents relocations that are mips-16 specific, but I do not
11392 know why it does this.
11395 There is one other problem that ought to be addressed here, but
11396 which currently is not: Taking the address of a label (rather
11397 than a function) and then later jumping to that address. Such
11398 addresses also ought to have their bottom bit set (assuming that
11399 they reside in Thumb code), but at the moment they will not. */
11402 arm_fix_adjustable (fixP
)
11405 if (fixP
->fx_addsy
== NULL
)
11408 /* Prevent all adjustments to global symbols. */
11409 if (S_IS_EXTERN (fixP
->fx_addsy
))
11412 if (S_IS_WEAK (fixP
->fx_addsy
))
11415 if (THUMB_IS_FUNC (fixP
->fx_addsy
)
11416 && fixP
->fx_subsy
== NULL
)
11419 /* We need the symbol name for the VTABLE entries. */
11420 if ( fixP
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
11421 || fixP
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
11428 elf32_arm_target_format ()
11430 if (target_big_endian
)
11433 return "elf32-bigarm-oabi";
11435 return "elf32-bigarm";
11440 return "elf32-littlearm-oabi";
11442 return "elf32-littlearm";
11447 armelf_frob_symbol (symp
, puntp
)
11451 elf_frob_symbol (symp
, puntp
);
11455 arm_force_relocation (fixp
)
11458 if ( fixp
->fx_r_type
== BFD_RELOC_VTABLE_INHERIT
11459 || fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
11460 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BRANCH
11461 || fixp
->fx_r_type
== BFD_RELOC_ARM_PCREL_BLX
11462 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BLX
11463 || fixp
->fx_r_type
== BFD_RELOC_THUMB_PCREL_BRANCH23
)
11469 static bfd_reloc_code_real_type
11479 bfd_reloc_code_real_type reloc
;
11483 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
11484 MAP ("(got)", BFD_RELOC_ARM_GOT32
),
11485 MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF
),
11486 /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
11487 branch instructions generated by GCC for PLT relocs. */
11488 MAP ("(plt)", BFD_RELOC_ARM_PLT32
),
11489 { NULL
, 0, BFD_RELOC_UNUSED
}
11493 for (i
= 0, ip
= input_line_pointer
;
11494 i
< sizeof (id
) && (ISALNUM (*ip
) || ISPUNCT (*ip
));
11496 id
[i
] = TOLOWER (*ip
);
11498 for (i
= 0; reloc_map
[i
].str
; i
++)
11499 if (strncmp (id
, reloc_map
[i
].str
, reloc_map
[i
].len
) == 0)
11502 input_line_pointer
+= reloc_map
[i
].len
;
11504 return reloc_map
[i
].reloc
;
11508 s_arm_elf_cons (nbytes
)
11513 #ifdef md_flush_pending_output
11514 md_flush_pending_output ();
11517 if (is_it_end_of_statement ())
11519 demand_empty_rest_of_line ();
11523 #ifdef md_cons_align
11524 md_cons_align (nbytes
);
11529 bfd_reloc_code_real_type reloc
;
11531 expression (& exp
);
11533 if (exp
.X_op
== O_symbol
11534 && * input_line_pointer
== '('
11535 && (reloc
= arm_parse_reloc ()) != BFD_RELOC_UNUSED
)
11537 reloc_howto_type
*howto
= bfd_reloc_type_lookup (stdoutput
, reloc
);
11538 int size
= bfd_get_reloc_size (howto
);
11541 as_bad ("%s relocations do not fit in %d bytes",
11542 howto
->name
, nbytes
);
11545 register char *p
= frag_more ((int) nbytes
);
11546 int offset
= nbytes
- size
;
11548 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
+ offset
, size
,
11553 emit_expr (&exp
, (unsigned int) nbytes
);
11555 while (*input_line_pointer
++ == ',');
11557 /* Put terminator back into stream. */
11558 input_line_pointer
--;
11559 demand_empty_rest_of_line ();
11562 #endif /* OBJ_ELF */
11564 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
11565 of an rs_align_code fragment. */
11568 arm_handle_align (fragP
)
11571 static char const arm_noop
[4] = { 0x00, 0x00, 0xa0, 0xe1 };
11572 static char const thumb_noop
[2] = { 0xc0, 0x46 };
11573 static char const arm_bigend_noop
[4] = { 0xe1, 0xa0, 0x00, 0x00 };
11574 static char const thumb_bigend_noop
[2] = { 0x46, 0xc0 };
11576 int bytes
, fix
, noop_size
;
11580 if (fragP
->fr_type
!= rs_align_code
)
11583 bytes
= fragP
->fr_next
->fr_address
- fragP
->fr_address
- fragP
->fr_fix
;
11584 p
= fragP
->fr_literal
+ fragP
->fr_fix
;
11587 if (bytes
> MAX_MEM_FOR_RS_ALIGN_CODE
)
11588 bytes
&= MAX_MEM_FOR_RS_ALIGN_CODE
;
11590 if (fragP
->tc_frag_data
)
11592 if (target_big_endian
)
11593 noop
= thumb_bigend_noop
;
11596 noop_size
= sizeof (thumb_noop
);
11600 if (target_big_endian
)
11601 noop
= arm_bigend_noop
;
11604 noop_size
= sizeof (arm_noop
);
11607 if (bytes
& (noop_size
- 1))
11609 fix
= bytes
& (noop_size
- 1);
11610 memset (p
, 0, fix
);
11615 while (bytes
>= noop_size
)
11617 memcpy (p
, noop
, noop_size
);
11619 bytes
-= noop_size
;
11623 fragP
->fr_fix
+= fix
;
11624 fragP
->fr_var
= noop_size
;
11627 /* Called from md_do_align. Used to create an alignment
11628 frag in a code section. */
11631 arm_frag_align_code (n
, max
)
11637 /* We assume that there will never be a requirment
11638 to support alignments greater than 32 bytes. */
11639 if (max
> MAX_MEM_FOR_RS_ALIGN_CODE
)
11640 as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
11642 p
= frag_var (rs_align_code
,
11643 MAX_MEM_FOR_RS_ALIGN_CODE
,
11645 (relax_substateT
) max
,
11653 /* Perform target specific initialisation of a frag. */
11656 arm_init_frag (fragP
)
11659 /* Record whether this frag is in an ARM or a THUMB area. */
11660 fragP
->tc_frag_data
= thumb_mode
;